fix(sign): explain 0x8009001D when a store key's provider fails to load (#2207)

Windows reports NTE_PROVIDER_DLL_FAIL when the key storage provider
holding a certificate's private key can't load its DLL: smart card or
token middleware that is missing or broken, or a provider that exists
only as 32-bit code a 64-bit process can't load. The certificate list
showed it only as "Windows error 0x8009001D"; it now says what that
means, as it already did for a missing card or provider.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RUNQSPVXx3dDBabRZHAnjz
This commit is contained in:
mtlcl410
2026-10-17 15:29:59 +08:00
co-authored by Claude Opus 5.5
parent 924c4da4ac
commit 07524f5e8c
+11
View File
@@ -200,6 +200,7 @@ const NTE_NOT_FOUND: u32 = 0x8009_0011;
const NTE_BAD_PROVIDER: u32 = 0x8009_0013;
const NTE_BAD_PROV_TYPE: u32 = 0x8009_0014;
const NTE_BAD_KEYSET: u32 = 0x8009_0016;
const NTE_PROVIDER_DLL_FAIL: u32 = 0x8009_001D;
const NTE_PROV_DLL_NOT_FOUND: u32 = 0x8009_001E;
const NTE_SILENT_CONTEXT: u32 = 0x8009_0022;
const NTE_NOT_SUPPORTED: u32 = 0x8009_0029;
@@ -218,6 +219,11 @@ fn describe(e: &CngError) -> String {
NTE_BAD_PROVIDER | NTE_BAD_PROV_TYPE | NTE_PROV_DLL_NOT_FOUND => {
"its key provider isn't available to CNG (a legacy CryptoAPI-only provider, or its driver isn't installed)"
}
// #2207: a smart card or token's middleware that is missing or broken, or a provider
// that exists only as 32-bit code, which a 64-bit process can't load.
NTE_PROVIDER_DLL_FAIL => {
"its key provider's software failed to load (a smart card or token driver that is missing or broken, or a 32-bit-only provider)"
}
NTE_NOT_SUPPORTED => "its key provider doesn't support the operation",
NTE_DEVICE_NOT_READY | NTE_DEVICE_NOT_FOUND => "the smart card or token isn't available",
NTE_USER_CANCELLED => "the request was cancelled",
@@ -240,6 +246,11 @@ mod tests {
"the key is missing from its key store (deleted, or imported under another Windows account) (Windows error 0x80090016)"
);
assert_eq!(describe(&CngError::WindowsError(0x8010_000C)), "the smart card isn't available (Windows error 0x8010000C)");
assert_eq!(
describe(&CngError::WindowsError(0x8009_001D)),
"its key provider's software failed to load (a smart card or token driver that is missing or broken, or a 32-bit-only provider) (Windows error 0x8009001D)",
"#2207"
);
assert_eq!(describe(&CngError::WindowsError(0x57)), "Windows error 0x00000057");
assert_eq!(describe(&CngError::InvalidHashLength), "Invalid hash length");
}