Hello S-1-1-0,

Today I’m continuing my certutil tips and tricks post series. In this post, I will get an introduction into cryptographic service provider architecture and how certutil can list and query them.

A short introduction to Cryptographic Providers

Windows Cryptography relies on a cryptographic service provider (CSP) architecture when performing cryptographic operations. CSP is a program module that represents an abstraction between client application and functions that utilize private keys. Applications are not required to interact with private key material directly, implement cryptographic functions. They only interact with known CSPs that implement private key storage database and cryptographic functions and operations. Here is a simple diagram that shows the relationship between client application and CSP:

image

When certificate is installed into Windows Certificate Store, public certificate is installed in registry and private key is registered and installed in selected CSP. When necessary, application queries the CSP and asks CSP to do the job, say generate key, hash, encrypt or sign data and get results. Application has zero knowledge of what is happening behind.

Microsoft Windows can support multiple CSPs and allows developers to write their own CSPs. One common cases of custom providers are hardware key storages like smart cards and hardware security modules (HSM). Custom CSP implements cryptographic algorithms, operations and interaction with key storage on hardware devices. If application needs to access the certificate on a smart card, application just communicates with smart card CSP via unified interface and all the rest is done by CSP.

After releasing Windows Vista and Windows Server 2008, there is a brand new CSP subsystem called Cryptography Next Generation (CNG). CNG is was written from scratch and is not compatible with legacy CSP subsystem. CNG brings a lot of improvements to CryptoAPI, but the idea is still the same. Also, CNG ships a new class of CSPs  called Key Storage Provider  or KSP. In general, KSP and CSP are similar in terms of their purpose. CSP refers to legacy CryptoAPI 1.0 and KSP refers to CNG or CAPI2.

Microsoft ships a number of different providers with different capabilities. Custom providers may be installed. So, let’s start with basic operations.

Enumerate the list of providers

we can use certutil -csplist to enumerate all registered providers (both, CSP and KSP):

PS C:\> certutil -csplist
Provider Name: Athena ASECard Crypto CSP
Provider Type: 1 - PROV_RSA_FULL

Provider Name: Microsoft Base Cryptographic Provider v1.0
Provider Type: 1 - PROV_RSA_FULL

Provider Name: Microsoft Base DSS and Diffie-Hellman Cryptographic Provider
Provider Type: 13 - PROV_DSS_DH

Provider Name: Microsoft Base DSS Cryptographic Provider
Provider Type: 3 - PROV_DSS

Provider Name: Microsoft Base Smart Card Crypto Provider
Provider Type: 1 - PROV_RSA_FULL

Provider Name: Microsoft DH SChannel Cryptographic Provider
Provider Type: 18 - PROV_DH_SCHANNEL

Provider Name: Microsoft Enhanced Cryptographic Provider v1.0
Provider Type: 1 - PROV_RSA_FULL

Provider Name: Microsoft Enhanced DSS and Diffie-Hellman Cryptographic Provider
Provider Type: 13 - PROV_DSS_DH

Provider Name: Microsoft Enhanced RSA and AES Cryptographic Provider
Provider Type: 24 - PROV_RSA_AES

Provider Name: Microsoft RSA SChannel Cryptographic Provider
Provider Type: 12 - PROV_RSA_SCHANNEL

Provider Name: Microsoft Strong Cryptographic Provider
Provider Type: 1 - PROV_RSA_FULL

Provider Name: Microsoft Software Key Storage Provider

Provider Name: Athena Key Storage Provider

Provider Name: Microsoft Passport Key Storage Provider

Provider Name: Microsoft Platform Crypto Provider
Microsoft Platform Crypto Provider: The device that is required by this cryptographic provider is not ready for use.

Provider Name: Microsoft Smart Card Key Storage Provider
CertUtil: -csplist command FAILED: 0x80090030 (-2146893776 NTE_DEVICE_NOT_READY)
CertUtil: The device that is required by this cryptographic provider is not ready for use.
PS C:\>

There are two ways to quickly say which provider is legacy CSP and which is CNG:

  1. legacy CSP always specify Provider Type field.
  2. CNG providers usually use Key Storage Provider in their names.

My current system has two custom providers, legacy CSP called “Athena ASECard Crypto CSP” and modern KSP called “Athena Key Storage Provider” which are used to access my Athena smart card. Providers may expose some capabilities in their names. For example, “Microsoft Enhanced RSA and AES Cryptographic Provider” name suggests, that this particular CSP implements AES algorithm operations (in fact, this CSP is the only built-in legacy CSP that implements AES). “Microsoft Platform Crypto Provider” provider suggests that it is intended to interact with Trusted Platform Module (TPM).

Dump CSP or KSP capabilities

We can use certutil -csptest command to dump specific provider capabilities:

C:\> certutil -csp "Athena Key Storage Provider" -csptest

Provider Name: Athena Key Storage Provider
  Name: Athena Key Storage Provider
  HWND Handle:Binary:
0000    00 00 00 00 00 00 00 00                            ........
  Impl Type: 11 (0xb)
    NCRYPT_IMPL_HARDWARE_FLAG -- 1
    NCRYPT_IMPL_SOFTWARE_FLAG -- 2
    NCRYPT_IMPL_REMOVABLE_FLAG -- 8

  Version: 65536 (0x10000)
  Pass

  Provider Aliases:
    Athena ASECard Crypto CSP

  Provider Module:
      UM(1): aseKSP.dll
      0(1): 10001, 1
        0: KEY_STORAGE

  Asymmetric Encryption Algorithms:
   RSA
    BCRYPT_ASYMMETRIC_ENCRYPTION_INTERFACE -- 3
    NCRYPT_ASYMMETRIC_ENCRYPTION_OPERATION -- 4
    NCRYPT_SIGNATURE_OPERATION -- 10 (16)

  Secret Agreement Algorithms:
   ECDH_P256
    BCRYPT_SECRET_AGREEMENT_INTERFACE -- 4
    NCRYPT_SECRET_AGREEMENT_OPERATION -- 8
    NCRYPT_SIGNATURE_OPERATION -- 10 (16)

   ECDH_P384
    BCRYPT_SECRET_AGREEMENT_INTERFACE -- 4
    NCRYPT_SECRET_AGREEMENT_OPERATION -- 8
    NCRYPT_SIGNATURE_OPERATION -- 10 (16)

   ECDH_P521
    BCRYPT_SECRET_AGREEMENT_INTERFACE -- 4
    NCRYPT_SECRET_AGREEMENT_OPERATION -- 8
    NCRYPT_SIGNATURE_OPERATION -- 10 (16)

  Signature Algorithms:
   RSA
    BCRYPT_ASYMMETRIC_ENCRYPTION_INTERFACE -- 3
    NCRYPT_ASYMMETRIC_ENCRYPTION_OPERATION -- 4
    NCRYPT_SIGNATURE_OPERATION -- 10 (16)

   ECDSA_P256
    BCRYPT_SIGNATURE_INTERFACE -- 5
    NCRYPT_SIGNATURE_OPERATION -- 10 (16)

   ECDSA_P384
    BCRYPT_SIGNATURE_INTERFACE -- 5
    NCRYPT_SIGNATURE_OPERATION -- 10 (16)

   ECDSA_P521
    BCRYPT_SIGNATURE_INTERFACE -- 5
    NCRYPT_SIGNATURE_OPERATION -- 10 (16)

  Asymmetric Algorithms:
   RSA
    BCRYPT_ASYMMETRIC_ENCRYPTION_INTERFACE -- 3
    NCRYPT_ASYMMETRIC_ENCRYPTION_OPERATION -- 4
    NCRYPT_SIGNATURE_OPERATION -- 10 (16)

    NCryptCreatePersistedKey(Athena Key Storage Provider, RSA)
  Algorithm Group: RSA
  Algorithm Name: RSA
  Length: 2048 (0x800)
  Lengths:
    dwMinLength = 1024 (0x400)
    dwMaxLength = 4096 (0x1000)
    dwIncrement = 512 (0x200)
    dwDefaultLength = 2048 (0x800)
  Block Length: 256 (0x100)
  UI Policy:
    dwVersion = 1 (0x1)
    dwFlags = 0 (0x0)
    pszCreationTitle = (null)
    pszFriendlyName = (null)
    pszDescription = (null)
  Export Policy: 0 (0x0)

  HWND Handle:Binary:
0000    00 00 00 00 00 00 00 00                            ........
  Key Usage: 0 (0x0)

  Pass

   ECDH_P256
    BCRYPT_SECRET_AGREEMENT_INTERFACE -- 4
    NCRYPT_SECRET_AGREEMENT_OPERATION -- 8
    NCRYPT_SIGNATURE_OPERATION -- 10 (16)

    NCryptCreatePersistedKey(Athena Key Storage Provider, ECDH_P256)
  Algorithm Group: ECDH
  Algorithm Name: ECDH_P256
  Length: 256 (0x100)
  Lengths:
    dwMinLength = 256 (0x100)
    dwMaxLength = 256 (0x100)
    dwIncrement = 0 (0x0)
    dwDefaultLength = 256 (0x100)
  UI Policy:
    dwVersion = 1 (0x1)
    dwFlags = 0 (0x0)
    pszCreationTitle = (null)
    pszFriendlyName = (null)
    pszDescription = (null)
  Export Policy: 0 (0x0)

  HWND Handle:Binary:
0000    00 00 00 00 00 00 00 00                            ........
  Key Usage: 0 (0x0)

  Pass

   ECDH_P384
    BCRYPT_SECRET_AGREEMENT_INTERFACE -- 4
    NCRYPT_SECRET_AGREEMENT_OPERATION -- 8
    NCRYPT_SIGNATURE_OPERATION -- 10 (16)

    NCryptCreatePersistedKey(Athena Key Storage Provider, ECDH_P384)
  Algorithm Group: ECDH
  Algorithm Name: ECDH_P384
  Length: 384 (0x180)
  Lengths:
    dwMinLength = 384 (0x180)
    dwMaxLength = 384 (0x180)
    dwIncrement = 0 (0x0)
    dwDefaultLength = 384 (0x180)
  UI Policy:
    dwVersion = 1 (0x1)
    dwFlags = 0 (0x0)
    pszCreationTitle = (null)
    pszFriendlyName = (null)
    pszDescription = (null)
  Export Policy: 0 (0x0)

  HWND Handle:Binary:
0000    00 00 00 00 00 00 00 00                            ........
  Key Usage: 0 (0x0)

  Pass

   ECDH_P521
    BCRYPT_SECRET_AGREEMENT_INTERFACE -- 4
    NCRYPT_SECRET_AGREEMENT_OPERATION -- 8
    NCRYPT_SIGNATURE_OPERATION -- 10 (16)

    NCryptCreatePersistedKey(Athena Key Storage Provider, ECDH_P521)
  Algorithm Group: ECDH
  Algorithm Name: ECDH_P521
  Length: 521 (0x209)
  Lengths:
    dwMinLength = 521 (0x209)
    dwMaxLength = 521 (0x209)
    dwIncrement = 0 (0x0)
    dwDefaultLength = 521 (0x209)
  UI Policy:
    dwVersion = 1 (0x1)
    dwFlags = 0 (0x0)
    pszCreationTitle = (null)
    pszFriendlyName = (null)
    pszDescription = (null)
  Export Policy: 0 (0x0)

  HWND Handle:Binary:
0000    00 00 00 00 00 00 00 00                            ........
  Key Usage: 0 (0x0)

  Pass

   ECDSA_P256
    BCRYPT_SIGNATURE_INTERFACE -- 5
    NCRYPT_SIGNATURE_OPERATION -- 10 (16)

    NCryptCreatePersistedKey(Athena Key Storage Provider, ECDSA_P256)
  Algorithm Group: ECDSA
  Algorithm Name: ECDSA_P256
  Length: 256 (0x100)
  Lengths:
    dwMinLength = 256 (0x100)
    dwMaxLength = 256 (0x100)
    dwIncrement = 0 (0x0)
    dwDefaultLength = 256 (0x100)
  UI Policy:
    dwVersion = 1 (0x1)
    dwFlags = 0 (0x0)
    pszCreationTitle = (null)
    pszFriendlyName = (null)
    pszDescription = (null)
  Export Policy: 0 (0x0)

  HWND Handle:Binary:
0000    00 00 00 00 00 00 00 00                            ........
  Key Usage: 0 (0x0)

  Pass

   ECDSA_P384
    BCRYPT_SIGNATURE_INTERFACE -- 5
    NCRYPT_SIGNATURE_OPERATION -- 10 (16)

    NCryptCreatePersistedKey(Athena Key Storage Provider, ECDSA_P384)
  Algorithm Group: ECDSA
  Algorithm Name: ECDSA_P384
  Length: 384 (0x180)
  Lengths:
    dwMinLength = 384 (0x180)
    dwMaxLength = 384 (0x180)
    dwIncrement = 0 (0x0)
    dwDefaultLength = 384 (0x180)
  UI Policy:
    dwVersion = 1 (0x1)
    dwFlags = 0 (0x0)
    pszCreationTitle = (null)
    pszFriendlyName = (null)
    pszDescription = (null)
  Export Policy: 0 (0x0)

  HWND Handle:Binary:
0000    00 00 00 00 00 00 00 00                            ........
  Key Usage: 0 (0x0)

  Pass

   ECDSA_P521
    BCRYPT_SIGNATURE_INTERFACE -- 5
    NCRYPT_SIGNATURE_OPERATION -- 10 (16)

    NCryptCreatePersistedKey(Athena Key Storage Provider, ECDSA_P521)
  Algorithm Group: ECDSA
  Algorithm Name: ECDSA_P521
  Length: 521 (0x209)
  Lengths:
    dwMinLength = 521 (0x209)
    dwMaxLength = 521 (0x209)
    dwIncrement = 0 (0x0)
    dwDefaultLength = 521 (0x209)
  UI Policy:
    dwVersion = 1 (0x1)
    dwFlags = 0 (0x0)
    pszCreationTitle = (null)
    pszFriendlyName = (null)
    pszDescription = (null)
  Export Policy: 0 (0x0)

  HWND Handle:Binary:
0000    00 00 00 00 00 00 00 00                            ........
  Key Usage: 0 (0x0)

  Pass

  All Algorithms:
   RSA
    BCRYPT_ASYMMETRIC_ENCRYPTION_INTERFACE -- 3
    NCRYPT_ASYMMETRIC_ENCRYPTION_OPERATION -- 4
    NCRYPT_SIGNATURE_OPERATION -- 10 (16)

   ECDH_P256
    BCRYPT_SECRET_AGREEMENT_INTERFACE -- 4
    NCRYPT_SECRET_AGREEMENT_OPERATION -- 8
    NCRYPT_SIGNATURE_OPERATION -- 10 (16)

   ECDH_P384
    BCRYPT_SECRET_AGREEMENT_INTERFACE -- 4
    NCRYPT_SECRET_AGREEMENT_OPERATION -- 8
    NCRYPT_SIGNATURE_OPERATION -- 10 (16)

   ECDH_P521
    BCRYPT_SECRET_AGREEMENT_INTERFACE -- 4
    NCRYPT_SECRET_AGREEMENT_OPERATION -- 8
    NCRYPT_SIGNATURE_OPERATION -- 10 (16)

   ECDSA_P256
    BCRYPT_SIGNATURE_INTERFACE -- 5
    NCRYPT_SIGNATURE_OPERATION -- 10 (16)

   ECDSA_P384
    BCRYPT_SIGNATURE_INTERFACE -- 5
    NCRYPT_SIGNATURE_OPERATION -- 10 (16)

   ECDSA_P521
    BCRYPT_SIGNATURE_INTERFACE -- 5
    NCRYPT_SIGNATURE_OPERATION -- 10 (16)


BCryptEnumAlgorithms:
  Hash Algorithms:
    SHA256
    SHA384
    SHA512
    SHA1
    MD5
    MD4
    MD2
    AES-GMAC
    AES-CMAC

  Asymmetric Encryption Algorithms:
    RSA

  Secret Agreement Algorithms:
    DH
    ECDH_P256
    ECDH_P384
    ECDH_P521
    ECDH

  Signature Algorithms:
    RSA_SIGN
    ECDSA_P256
    ECDSA_P384
    ECDSA_P521
    ECDSA
    DSA

  Cipher Algorithms:
    AES
      dwMinLength=128 dwMaxLength=256 dwIncrement=64
    3DES
      dwMinLength=192 dwMaxLength=192 dwIncrement=0
    3DES_112
      dwMinLength=128 dwMaxLength=128 dwIncrement=0
    XTS-AES
      dwMinLength=256 dwMaxLength=512 dwIncrement=128
    DESX
      dwMinLength=192 dwMaxLength=192 dwIncrement=0
    DES
      dwMinLength=64 dwMaxLength=64 dwIncrement=0
    RC2
      dwMinLength=16 dwMaxLength=128 dwIncrement=8
    RC4
      dwMinLength=8 dwMaxLength=512 dwIncrement=8

  RNG Algorithms:
    RNG
    FIPS186DSARNG
    DUALECRNG

  Asymmetric Algorithms:
    RSA
    DH
    ECDH_P256
    ECDH_P384
    ECDH_P521
    ECDH
    RSA_SIGN
    ECDSA_P256
    ECDSA_P384
    ECDSA_P521
    ECDSA
    DSA

  All Algorithms:
    AES
      dwMinLength=128 dwMaxLength=256 dwIncrement=64
    3DES
      dwMinLength=192 dwMaxLength=192 dwIncrement=0
    3DES_112
      dwMinLength=128 dwMaxLength=128 dwIncrement=0
    XTS-AES
      dwMinLength=256 dwMaxLength=512 dwIncrement=128
    DESX
      dwMinLength=192 dwMaxLength=192 dwIncrement=0
    DES
      dwMinLength=64 dwMaxLength=64 dwIncrement=0
    RC2
      dwMinLength=16 dwMaxLength=128 dwIncrement=8
    RC4
      dwMinLength=8 dwMaxLength=512 dwIncrement=8
    SHA256
    SHA384
    SHA512
    SHA1
    MD5
    MD4
    MD2
    AES-GMAC
    AES-CMAC
    RSA
    DH
    ECDH_P256
    ECDH_P384
    ECDH_P521
    ECDH
    RSA_SIGN
    ECDSA_P256
    ECDSA_P384
    ECDSA_P521
    ECDSA
    DSA
    RNG
    FIPS186DSARNG
    DUALECRNG
    SP800_108_CTR_HMAC
    SP800_56A_CONCAT
    PBKDF2
    CAPI_KDF
    TLS1_1_KDF
    TLS1_2_KDF
    HKDF

CertUtil: -csptest command completed successfully.
C:\>

The output is quite verbose, but it exposes all supported symmetric and asymmetric algorithms, hash algorithms, key sizes, etc.. For example, this block shows RSA asymmetric key generation options:

Algorithm Name: RSA
  Length: 2048 (0x800)
  Lengths:
    dwMinLength = 1024 (0x400)
    dwMaxLength = 4096 (0x1000)
    dwIncrement = 512 (0x200)
    dwDefaultLength = 2048 (0x800)

Athena KSP supports RSA keys starting with 1024 bits and up to 4096 bits with 512 bit step and default key size is 2048.

Enumerate keys in CSP and KSP

Certutil can query provider database to list all keys stored within particular provider by running certutil -key command and specifying desired provider name:

C:\> certutil -csp "Microsoft Software Key Storage Provider" -key
Microsoft Software Key Storage Provider:
  tq-07e1b2b4-eb66-4055-aeba-0fae6310f200
  3b77025f895e02021ad09cc75d8b941d_c0f790f6-ac7a-4d83-add9-d6e26941ca7e
  ECDH_P384
  ECDH


  tq-f81ae2fb-b235-4a44-bc3a-8698b3103549
  610832fd5c5833e12471e0d4d28c0bc4_c0f790f6-ac7a-4d83-add9-d6e26941ca7e
  ECDH_P384
  ECDH


  tq-04de85ef-2f1a-4396-9d70-a03fd8a48242
  ca359a08fea20a03fdfd19f37c6027bf_c0f790f6-ac7a-4d83-add9-d6e26941ca7e
  ECDH_P384
  ECDH


CertUtil: -key command completed successfully.
C:\>

The output shows three key containers (or keys) with the following information:

  1. key container name (example: tq-07e1b2b4-eb66-4055-aeba-0fae6310f200)
  2. unique container name (example: 3b77025f895e02021ad09cc75d8b941d_c0f790f6-ac7a-4d83-add9-d6e26941ca7e)
  3. key algorithm (example: ECDH_P384)
  4. key algorithm group (example: ECDH)

What is the difference between first two? Key container name is the name of key container which may contain one or more keys. Unique container name is key name within provider. Unique container name is used as a private key file name when software provider is used.

we can add -v switch in order to get more detailed output:

C:\> certutil -v -csp "Microsoft Software Key Storage Provider" -key
Microsoft Software Key Storage Provider:
  tq-07e1b2b4-eb66-4055-aeba-0fae6310f200
  3b77025f895e02021ad09cc75d8b941d_c0f790f6-ac7a-4d83-add9-d6e26941ca7e
  AD(AT_NONE): b7680f1e88de194625f0d64b4b6bde9bea062a4d
  AD(AT_KEYEXCHANGE): 1c68213f8ab0f04cef612ef48fe260ea669154f4
  AD(AT_SIGNATURE): 40ffbfed123ac8deb0d6040b2e0c38cd8bbbea74

  ECDH_P384
  ECDH
Key Id Hash(rfc-sha1): 7092789a284e2f6490e5beab217a7c063936dcdc
Key Id Hash(sha1): a0e57d359dc667c2ec5705bcc9c22696267f16ef
Key Id Hash(bcrypt-sha1): ae761ac98deb8121d9d87a727b43eb3a8c42d061
Key Id Hash(bcrypt-sha256): c23b22c807e7c3629768ea017451f7fa82a0821ab29988bb192d1fff6a40e1d0
Container Public Key:
  0000  04 81 48 02 a6 c4 7e 6b  ae 9d 93 13 0c b1 84 bb
  0010  d5 ba f4 97 37 4d 85 bb  c3 ab ae 16 e7 19 58 10
  0020  70 9c e1 41 71 a6 aa 83  f7 22 57 16 57 17 05 52
  0030  25 93 ba be 2a 84 cc 3d  a3 8e 7d 19 8f b5 2f f2
  0040  70 7d 7a f9 88 77 0d 38  e2 b8 cd 72 c6 7e 98 df
  0050  8d b5 eb a6 14 d6 68 52  73 29 7c 47 bf b3 3d 0b
  0060  17
Cached Key Identifier: tq-07e1b2b4-eb66-4055-aeba-0fae6310f200: Found exact match
    NCRYPT_ALLOW_DECRYPT_FLAG -- 1
    NCRYPT_ALLOW_SIGNING_FLAG -- 2
    NCRYPT_ALLOW_KEY_AGREEMENT_FLAG -- 4
    NCRYPT_ALLOW_KEY_IMPORT_FLAG -- 8
    NCRYPT_ALLOW_ALL_USAGES -- ffffff (16777215)
  UI Policy = 0
      (NCRYPT_UI_PROTECT_KEY_FLAG -- 1)
      (NCRYPT_UI_FORCE_HIGH_PROTECTION_FLAG -- 2)
    Version: 0
  Export Policy = 0
      (NCRYPT_ALLOW_EXPORT_FLAG -- 1)
      (NCRYPT_ALLOW_PLAINTEXT_EXPORT_FLAG -- 2)
      (NCRYPT_ALLOW_ARCHIVING_FLAG -- 4)
      (NCRYPT_ALLOW_PLAINTEXT_ARCHIVING_FLAG -- 8)
  Name: tq-07e1b2b4-eb66-4055-aeba-0fae6310f200
  Algorithm Group: ECDH
  Algorithm Name: ECDH_P384
  Length: 384 (0x180)
  Lengths:
    dwMinLength = 384 (0x180)
    dwMaxLength = 384 (0x180)
    dwIncrement = 0 (0x0)
    dwDefaultLength = 384 (0x180)
  UI Policy:
    dwVersion = 1 (0x1)
    dwFlags = 0 (0x0)
    pszCreationTitle = (null)
    pszFriendlyName = (null)
    pszDescription = (null)
  Export Policy: 0 (0x0)
      (NCRYPT_ALLOW_EXPORT_FLAG -- 1)
      (NCRYPT_ALLOW_PLAINTEXT_EXPORT_FLAG -- 2)
      (NCRYPT_ALLOW_ARCHIVING_FLAG -- 4)
      (NCRYPT_ALLOW_PLAINTEXT_ARCHIVING_FLAG -- 8)

  Key Usage: 16777215 (0xffffff)
    NCRYPT_ALLOW_DECRYPT_FLAG -- 1
    NCRYPT_ALLOW_SIGNING_FLAG -- 2
    NCRYPT_ALLOW_KEY_AGREEMENT_FLAG -- 4
    NCRYPT_ALLOW_KEY_IMPORT_FLAG -- 8
    NCRYPT_ALLOW_ALL_USAGES -- ffffff (16777215)

  Security Descr: D:PAI(A;;0x80120089;;;NS)(A;;0xd01f01ff;;;BA)(A;;0xd01f01ff;;;SY)
  Modified: 01.11.2016 15:51
  Virtual Iso: 0 (0x0)
  Per Boot Key: 0 (0x0)

Private key is NOT exportable

  D:PAI(A;;0x80120089;;;NS)(A;;0xd01f01ff;;;BA)(A;;0xd01f01ff;;;SY)

    Allow Write NT AUTHORITY\NETWORK SERVICE
    Allow Write BUILTIN\Administrators
    Allow Write NT AUTHORITY\SYSTEM



  tq-f81ae2fb-b235-4a44-bc3a-8698b3103549
  610832fd5c5833e12471e0d4d28c0bc4_c0f790f6-ac7a-4d83-add9-d6e26941ca7e
  AD(AT_NONE): 75a883f9ace7bd02f9271e8efe3fd6b4548fe8e9
  AD(AT_KEYEXCHANGE): 54ad855bc53968041a8433031362cfc88bc8cbe7
  AD(AT_SIGNATURE): 89ad1b600b527adeccd2f2a27e1b565d054fdc90

  ECDH_P384
  ECDH
Key Id Hash(rfc-sha1): a1cf4cf92f7f38366b781074675b6cafaccf9c10
Key Id Hash(sha1): 9ceec12e97cb8e2f56cff51aba7865406c7a2f4e
Key Id Hash(bcrypt-sha1): ee79615101f64059e8b98d4ff6633b18b268bd08
Key Id Hash(bcrypt-sha256): fbea73a80c6941a87cbbf12bdd756c162e02efb1bbff0d2e64c6fe11e0c91f3d
Container Public Key:
  0000  04 bc a9 d1 d4 07 58 50  e5 f5 0a 20 9f a7 ed d1
  0010  12 cb e3 39 b0 3e 98 c9  aa c3 c6 ce 76 7f 6b 4f
  0020  e1 01 aa 4b 9d c1 84 3d  8a ea 4e b6 e0 f3 c1 be
  0030  bf c8 4c 90 1a 48 99 40  3b b2 0a cc a7 cf f7 a0
  0040  c3 dc 90 93 74 ad a1 c5  3a 6b 8d 03 f6 69 b3 dd
  0050  c5 49 de 23 b7 e8 3c 15  3d aa 8d 0a 77 0c 6f 55
  0060  42
Cached Key Identifier: tq-f81ae2fb-b235-4a44-bc3a-8698b3103549: Found exact match
    NCRYPT_ALLOW_DECRYPT_FLAG -- 1
    NCRYPT_ALLOW_SIGNING_FLAG -- 2
    NCRYPT_ALLOW_KEY_AGREEMENT_FLAG -- 4
    NCRYPT_ALLOW_KEY_IMPORT_FLAG -- 8
    NCRYPT_ALLOW_ALL_USAGES -- ffffff (16777215)
  UI Policy = 0
      (NCRYPT_UI_PROTECT_KEY_FLAG -- 1)
      (NCRYPT_UI_FORCE_HIGH_PROTECTION_FLAG -- 2)
    Version: 0
  Export Policy = 0
      (NCRYPT_ALLOW_EXPORT_FLAG -- 1)
      (NCRYPT_ALLOW_PLAINTEXT_EXPORT_FLAG -- 2)
      (NCRYPT_ALLOW_ARCHIVING_FLAG -- 4)
      (NCRYPT_ALLOW_PLAINTEXT_ARCHIVING_FLAG -- 8)
  Name: tq-f81ae2fb-b235-4a44-bc3a-8698b3103549
  Algorithm Group: ECDH
  Algorithm Name: ECDH_P384
  Length: 384 (0x180)
  Lengths:
    dwMinLength = 384 (0x180)
    dwMaxLength = 384 (0x180)
    dwIncrement = 0 (0x0)
    dwDefaultLength = 384 (0x180)
  UI Policy:
    dwVersion = 1 (0x1)
    dwFlags = 0 (0x0)
    pszCreationTitle = (null)
    pszFriendlyName = (null)
    pszDescription = (null)
  Export Policy: 0 (0x0)
      (NCRYPT_ALLOW_EXPORT_FLAG -- 1)
      (NCRYPT_ALLOW_PLAINTEXT_EXPORT_FLAG -- 2)
      (NCRYPT_ALLOW_ARCHIVING_FLAG -- 4)
      (NCRYPT_ALLOW_PLAINTEXT_ARCHIVING_FLAG -- 8)

  Key Usage: 16777215 (0xffffff)
    NCRYPT_ALLOW_DECRYPT_FLAG -- 1
    NCRYPT_ALLOW_SIGNING_FLAG -- 2
    NCRYPT_ALLOW_KEY_AGREEMENT_FLAG -- 4
    NCRYPT_ALLOW_KEY_IMPORT_FLAG -- 8
    NCRYPT_ALLOW_ALL_USAGES -- ffffff (16777215)

  Security Descr: D:PAI(A;;0x80120089;;;NS)(A;;0xd01f01ff;;;BA)(A;;0xd01f01ff;;;SY)
  Modified: 11.05.2018 20:09
  Virtual Iso: 0 (0x0)
  Per Boot Key: 0 (0x0)

Private key is NOT exportable

  D:PAI(A;;0x80120089;;;NS)(A;;0xd01f01ff;;;BA)(A;;0xd01f01ff;;;SY)

    Allow Write NT AUTHORITY\NETWORK SERVICE
    Allow Write BUILTIN\Administrators
    Allow Write NT AUTHORITY\SYSTEM



  tq-04de85ef-2f1a-4396-9d70-a03fd8a48242
  ca359a08fea20a03fdfd19f37c6027bf_c0f790f6-ac7a-4d83-add9-d6e26941ca7e
  AD(AT_NONE): a9c052679273c3dba5f84327479d9c4d8a3403a5
  AD(AT_KEYEXCHANGE): 928750413b6faf33c149ac49724d92d8f393c048
  AD(AT_SIGNATURE): c3fbab9e2d67c92ff33dfba1e1e6e7bd5d69f010

  ECDH_P384
  ECDH
Key Id Hash(rfc-sha1): ba7e4b3a0c2d5ab2a953d4af54291e454a3313c3
Key Id Hash(sha1): 7ecec7e7a25fd55c68f6695e36f1670f76a72f61
Key Id Hash(bcrypt-sha1): cdebfc063e315a269e90fc0f5bdb9445102170ac
Key Id Hash(bcrypt-sha256): 89a52fb54b114af118f5294d61c068510de83671a251057524af5341eb602a2d
Container Public Key:
  0000  04 70 82 b2 25 a8 3d 88  3b 28 0b ad 14 1e c4 99
  0010  cb 05 92 a5 88 2f 9b 47  2b a1 82 12 b2 de 15 83
  0020  f8 8d 50 b4 34 0e 4b 2d  4b 82 b8 d9 ac 9f 0e 2d
  0030  3f 20 a5 e4 6e b2 90 66  b2 4b 62 ab 03 6b c0 d2
  0040  5b 75 9c 3e e2 74 20 91  03 2c 39 a3 35 59 83 b2
  0050  72 18 79 d0 f5 b2 0e 93  3e 14 e9 bf dd 7e 57 8a
  0060  36
Cached Key Identifier: tq-04de85ef-2f1a-4396-9d70-a03fd8a48242: Found exact match
    NCRYPT_ALLOW_DECRYPT_FLAG -- 1
    NCRYPT_ALLOW_SIGNING_FLAG -- 2
    NCRYPT_ALLOW_KEY_AGREEMENT_FLAG -- 4
    NCRYPT_ALLOW_KEY_IMPORT_FLAG -- 8
    NCRYPT_ALLOW_ALL_USAGES -- ffffff (16777215)
  UI Policy = 0
      (NCRYPT_UI_PROTECT_KEY_FLAG -- 1)
      (NCRYPT_UI_FORCE_HIGH_PROTECTION_FLAG -- 2)
    Version: 0
  Export Policy = 0
      (NCRYPT_ALLOW_EXPORT_FLAG -- 1)
      (NCRYPT_ALLOW_PLAINTEXT_EXPORT_FLAG -- 2)
      (NCRYPT_ALLOW_ARCHIVING_FLAG -- 4)
      (NCRYPT_ALLOW_PLAINTEXT_ARCHIVING_FLAG -- 8)
  Name: tq-04de85ef-2f1a-4396-9d70-a03fd8a48242
  Algorithm Group: ECDH
  Algorithm Name: ECDH_P384
  Length: 384 (0x180)
  Lengths:
    dwMinLength = 384 (0x180)
    dwMaxLength = 384 (0x180)
    dwIncrement = 0 (0x0)
    dwDefaultLength = 384 (0x180)
  UI Policy:
    dwVersion = 1 (0x1)
    dwFlags = 0 (0x0)
    pszCreationTitle = (null)
    pszFriendlyName = (null)
    pszDescription = (null)
  Export Policy: 0 (0x0)
      (NCRYPT_ALLOW_EXPORT_FLAG -- 1)
      (NCRYPT_ALLOW_PLAINTEXT_EXPORT_FLAG -- 2)
      (NCRYPT_ALLOW_ARCHIVING_FLAG -- 4)
      (NCRYPT_ALLOW_PLAINTEXT_ARCHIVING_FLAG -- 8)

  Key Usage: 16777215 (0xffffff)
    NCRYPT_ALLOW_DECRYPT_FLAG -- 1
    NCRYPT_ALLOW_SIGNING_FLAG -- 2
    NCRYPT_ALLOW_KEY_AGREEMENT_FLAG -- 4
    NCRYPT_ALLOW_KEY_IMPORT_FLAG -- 8
    NCRYPT_ALLOW_ALL_USAGES -- ffffff (16777215)

  Security Descr: D:PAI(A;;0x80120089;;;NS)(A;;0xd01f01ff;;;BA)(A;;0xd01f01ff;;;SY)
  Modified: 01.11.2018 18:18
  Virtual Iso: 0 (0x0)
  Per Boot Key: 0 (0x0)

Private key is NOT exportable

  D:PAI(A;;0x80120089;;;NS)(A;;0xd01f01ff;;;BA)(A;;0xd01f01ff;;;SY)

    Allow Write NT AUTHORITY\NETWORK SERVICE
    Allow Write BUILTIN\Administrators
    Allow Write NT AUTHORITY\SYSTEM



CertUtil: -key command completed successfully.

C:\>

Once again, with the -v switch we get very verbose output. This dump shows more details about each key. For example, it shows public key associated with the specified private key, file system permissions on the key and intended usages.

Relationships between certificate and key container

In previous section, we enumerated private keys within KSP, but what the certificate this key belongs to? We can query local certificate store and find matching certificate:

C:\> certutil -store my
my "Personal"
<...>
================ Certificate 3 ================
Serial Number: 1800000018899823eb0d33bb5e000000000018
Issuer: CN=*******
 NotBefore: 05.11.2017 13:25
 NotAfter: 05.11.2018 13:25
Subject: CN=*******
Non-root Certificate
Cert Hash(sha1): 697d819ccc5f3f00c2f12b89138c2c98f94837f7
  Key Container = tq-f81ae2fb-b235-4a44-bc3a-8698b3103549
  Unique container name: 610832fd5c5833e12471e0d4d28c0bc4_c0f790f6-ac7a-4d83-add9-d6e26941ca7e
  Provider = Microsoft Software Key Storage Provider
Private key is NOT exportable
Encryption test passed
CertUtil: -store command completed successfully.


C:\>

And indeed, we saw selected (in bold) key container and unique container name in the certutil -key command's output:

  tq-f81ae2fb-b235-4a44-bc3a-8698b3103549
  610832fd5c5833e12471e0d4d28c0bc4_c0f790f6-ac7a-4d83-add9-d6e26941ca7e
  ECDH_P384
  ECDH

this way we can bind the public certificate (which is stored in registry) to a corresponding private key.

Delete private keys in CSP and KSP

Private key deletion may be very tricky. For example, many users and IT administrators think that by deleting the certificate from certificate store, the key is deleted as well. It is incorrect and this case was explained in one of my blog posts: The case of accidentally deleted user certificates. This means that when you need to delete the certificate and corresponding private key, you have to delete the key first. Then you can delete the certificate from certificate store.

We can use certutil to delete the private key material from device (file system or hardware device) with certutil -delkey command:

PS C:\> certutil -csp "Microsoft Software Key Storage Provider" -delkey tq-f81ae2fb-b235-4a44-bc3a-8698b3103549
  tq-f81ae2fb-b235-4a44-bc3a-8698b3103549
CertUtil: -delkey command completed successfully.
PS C:\>

I deleted the key container from previous example (the certificate is already expired, so it is not harmful in this case). The command doesn’t produce any useful output. However, if we query the certificate again, we will see the difference:

PS C:\> certutil -store my 1800000018899823eb0d33bb5e000000000018
my "Personal"
================ Certificate 3 ================
Serial Number: 1800000018899823eb0d33bb5e000000000018
Issuer: CN=********
 NotBefore: 05.11.2017 13:25
 NotAfter: 05.11.2018 13:25
Subject: CN=*********
Non-root Certificate
Cert Hash(sha1): 697d819ccc5f3f00c2f12b89138c2c98f94837f7
  Key Container = tq-f81ae2fb-b235-4a44-bc3a-8698b3103549
  Provider = Microsoft Software Key Storage Provider
Missing stored keyset
CertUtil: -store command completed successfully.
PS C:\>

Instead of “Encryption test passed” line we see another line: Missing stored keyset. We deleted the private key and certutil (and other tools as well) is unable to find the key and use it for any operation. Even though, the key icon is still present on certificate in certificate store, it is misleading, because the key is gone.

Last Line

Today we explored the power of certutil in managing cryptographic providers and private keys. I’m a big fan of PowerShell, but PowerShell is nearly nowhere when the talk comes to cryptography. I’m still putting a lot of efforts to make PowerShell a little closer to certutil in these questions, but the road is very long. That’s all for today. Stay tuned for other PowerShell certutil stuff!


Share this article:

Comments:

Roman Krylov

Thank you very much, for that material.

Vaclav

Thanks for the helpfull article.

Is there any possibility to import a public certificate (e.g. trusted third party, without having a private key) and store it's public key to a provider's container (e.g. based on a HSM)? So that the public key is not stored only within the certificate (at registery), but also at the provider's container (on HSM)?

You have written, that certificates are always stored at registery no matter what the provider is. And of course, public keys are stored within certificates. But public keys are also stored in CSP/KSP providers - as you shown with certutil and -key and -v flags.

So is the linkage from certificates to a public-key-only-container possible or is that something what windows doesn't support at all?

The goal would be a higher confidence when checking the PKI chain when e.g. connecting to the third party or verifying a signature (provided that windows look at the certificate's public key and checks it with the one stored on provider's container while doing PKI chain check)

Thank you

Vadims Podāns

For public certificate import onto hardware devices (HSM, smart cards), you have to use software provided by HSM. I don't know ways to do this programmatically.

Vaclav

Thank you!

Kumar

Fantastic explanation.!

sebus

User personal store. User certificate. Yet I cannot delete private key of expired certificate:

Administrator permissions are needed to use the selected options.  Use an administrator command prompt to complete these tasks.
CertUtil: The requested operation requires elevation.

But ofcourse with evelvate cmd I get an error:

CertUtil: -delkey command FAILED: 0x80090016 (-2146893802 NTE_BAD_KEYSET)
CertUtil: Keyset does not exist

 

sebus

The key is listed correctly by

certutil -user -csp "Microsoft Software Key Storage Provider" -key

Elena

This is such a pain. It started in Windows 7 for me couple of weeks ago:

 

certutil Failed extract of third-party root list from auto update cab at: <http://www.download.windowsupdate.com/msdownload/update/v3/static/trustedr/en/authrootstl.cab> with error: A certificate chain processed, but terminated in a root certificate which is not trusted by the trust provider. .

First I followed this tutorial, then tried to clean out the reg keys restart CryptSvc.

https://www.sysadmins.lv/blog-en/the-case-of-third-party-root-list-update-error.aspx

Still the error kept coming back. Then I downloaded that cab file extracted the STL from it and imported it following this guide:

https://knowledge.digicert.com/solution/SO13755.html

and finally worked. Keep deleting the stupid certificates will do NOTHING since it tries to redownload it and fail over and over again.

I couldn't even care less about using any certificate thingies it was just messing up my windows and needed to be fixed.

I know that Windows7 is out of date now but people will be using it for a good +20 years, I don't recall issues like this with Windows XP.

Azharuddin

quick query how the certificate relates to the CSP function exposed? For example if my certificate has SHA256 hashing algorithm but the private key is stored in "Microsoft RSA SChannel Cryptographic Provider" which does not support SHA256 for hashing. How it will work?

Jakub Bereżański

FWIW, you can conveniently delete a certificate together with its private key in one go with PowerShell, using the "Cert:" drive, which exposes user and machine certificate stores as a pseudo-filesystem (stores are "directories" and certificates are "files" named after their thumbprints):

    cd Cert:\CurrentUser\My

    del .\<thumbprint> -DeleteKey

(Due to the way the Certificate namespace provider is implemented in PowerShell, the -DeleteKey parameter only works when the current location is inside the Cert: drive.)

Jakub Bereżański

@sebus The access rights (ACL) on the private key file may not grant Administrators the right to delete (happened for me today with a cert injected into an Azure virtual machine). You need to inspect and possibly change the permissions on the appropriate file.

For machine-level keys, the CNG Microsoft Software Key Storage Provider stores private keys as files in C:\ProgramData\Microsoft\Crypto\Keys. The CryptoAPI software CSPs do the same but in C:\ProgramData\Microsoft\Crypto\RSA\MachineKeys. In both cases file names match the "Unique container name" certificate property. For user-level keys, replace C:\ProgramData with %USERPROFILE%\AppData\Roaming.

Reference: https://docs.microsoft.com/en-us/windows/win32/seccng/key-storage-and-retrieval#key-directories-and-files

Bernd

What I noticed is that the powershell cert: drive has CSP details but not for KSP keys. Do you think that will improve, it somewhat feeld KSP support is still laggard in many tools.

     (ls Cert:\LocalMAchine\my).PrivateKEy.CspKeyContainerInfo

Vadims Podāns

> drive has CSP details but not for KSP keys

it is known issue, PrivateKey property does not support KSP and this will never be fixed. Instead, you should use extension methods for X509Certificate2 class.

Daniel

Hi, could you explain the difference between the KSP and the CertStore?

There are a lot of certificates stored in KSP, that I cannot see in the CertStore. But when I import a key-pair into the CertStore it seems that I can also see it in the KSP.

Is there a GUI that I can use to browse the KSP?

Vadims Podāns

KSP and CSP are different key storage models. The fact that you can see keys in KSP that aren't visible in CSP means that these keys are stored in KSP. However, KSP has a bridge API NCryptTranslateHandle which allows to convert CSP handle into KSP handle. That is, KSP can access keys in both, KSP and CSP, while CSP can access keys only in CSP.

A

Hi, 

i cannot delete key

PS C:\Users\Administrator> certutil.exe -v -csp "Microsoft Software Key Storage Provider" -delkey PFXEncryptionKeyImported
CertUtil: -delkey command FAILED: 0x80070005 (WIN32: 5 ERROR_ACCESS_DENIED)
CertUtil: Access is denied.

Vadims Podāns

> CertUtil: Access is denied.

make sure if your PS console is running in elevated mode.

Jozef

Hello,

is there a way to select or specify particular CSP (e.g.  Microsoft Enhanced RSA and AES Cryptographic Provider) when creating pfx file?

or  is it somehow associated how CSR is generated (e.g. openssl, mmc console  or browser api? 

 

 


Post your comment:

Please, solve this little equation and enter result below. Captcha