1

I am developing a CNG Key Store Provider (KSP) that will store keys and certificates remotely in a backend server in order to be used not only on Windows, but also on other OS without the need to export/import several times, every OS will have its own driver.

Currently I am investigating how to let Windows know that my KSP has personal certificates that must be available to other apps using the CryptoAPI, like browsers.

I have read that, when using smartcards, this procedure is done by the "Certificate Propagation Service", that notices when a smartcard is inserted, and then copies the certificates to the "MY" certificate store of current user.

How to do the propagation of certificates available in the KSP? If I call CertAddEncodedCertificateToStore asking to put the certificate in the "MY" store, will it do the trick persisting the certificate for future sessions? If so, I imagine that when some app call CryptAcquireCertificatePrivateKey with that certificate as parameter, the CryptoAPI will ask the KSP for a reference to the private key, right?

1

After digging a lot and making a lot of tests, I've finally found a way to "propagate" the certificate. This is what need to be done so that CryptoAPI knows that your KSP has user certificates:

  1. Create a certificate context using CertCreateCertificateContext passing the DER encoding of desired certificate;
  2. Create a CRYPT_KEY_PROV_INFO provInfo and set the fields:

    • Set pwszContainerName to a string of your choice, just to identify the key internally;
    • Set the field pwszProvName to the name of your provider. This is how CryptoAPI knows that the private key corresponding to this certificate is kept by your KSP;
    • Set dwKeySpec to AT_SIGNATURE;
    • The other fields can be NULL.
  3. Associate the provInfo to the context by calling CertSetCertificateContextProperty using CERT_KEY_PROV_INFO_PROP_ID as the property ID;

  4. Open the "MY" store by calling CertOpenSystemStore(NULL, L"MY")
  5. Add the context to the store by calling CertAddCertificateContextToStore(hCertStore, pCertContext, CERT_STORE_ADD_REPLACE_EXISTING, NULL)

After this, the certificate will be available for use in any application compatible with the CryptoAPI, like some browsers. As an example, in Internet Explorer you can access the certificate list in: "Tools" menu > "Internet Options" submenu > "Content" tab > "Certificates" button > "Personal" tab.

Whenever the user wants to use that certificate to authenticate in a website (or other use), the CryptoAPI will call your KSP, passing a hash value to be signed be the private key.

  • 1
    Thanks for the useful answer. Using this I was able to get my certificate displayed in the browser when a client certificate is required. However, when I select the certificate and klick "OK" my KSP is not called. Do you have any idea what this could be? Perhaps the registration of the KSP? Answers can be left in this SO-question – Frank Apr 25 '18 at 7:30
  • Frank, I was not able to post a comment to your other question due to lack of enough points.You said that certutil was able to make a digital signature using your KSP, this indicates that your KSP is properly configured and active, otherwise NCryptSignHashFn would not have been called. The authentication in the browser may be failing due to other factors. Is the web server properly configured to accept the certificate chain that was used to issue your certificate? – Fabiano Pereira Apr 26 '18 at 15:09
  • Thanks for the comment. This helps me a lot as I know now that the propagation works as expected and the problem lies somewhere else. I have found some strange entries in the windows event log and think this is the path I will follow for the next stage of research of the problem. – Frank Apr 27 '18 at 9:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.