How to get a certificate store from a smart card (USB Token) using CNG?

4

I'm using Crypto API's CryptAcquireContext function (https://docs.microsoft.com/en-us/windows/desktop/api/Wincrypt/nf-wincrypt-cryptacquirecontexta) to get access to my Certificate Store contained on my USB Token, and this is working like a charm!

However, the CryptAcquireContext function is deprecated and the Crypto API documentation recommends the use of CNG to achieve the same results. All my problem now is how to use CNG to get a certificate context from my USB Token, and to achieve this I'm using the following code:

var
  Provider: NCRYPT_PROV_HANDLE;
  Reader: PByte;
  ReaderSize: DWORD;
  MemorySize: DWORD;
begin
  // Get a handle to the smartcard reader specific provider
  Status := NCryptOpenStorageProvider(@Provider
                                     ,'SafeSign Standard RSA and AES Cryptographic Service Provider'
                                     ,0); // returns ERROR_SUCCESS
  // Convert the name of the reader to a PByte
  UnicodeStringToBinary('Giesecke & Devrient GmbH StarSign CUT 0',Reader,ReaderSize);

  // Inform the name of the reader to the CNG
  Status := NCryptSetProperty(Provider
                             ,NCRYPT_READER_PROPERTY
                             ,Reader
                             ,ReaderSize
                             ,0); // returns ERROR_SUCCESS

  MemorySize := SizeOf(HCERTSTORE);

  // Try to get the size needed to a variable of type HCERTSTORE.
  // This is the first step before get the certificate store
  Status := NCryptGetProperty(Provider
                             ,NCRYPT_USER_CERTSTORE_PROPERTY
                             ,nil
                             ,0
                             ,@MemorySize
                             ,0); //Returns 0x80090029 (NTE_NOT_SUPPORTED)
end;

As you can see the NCryptGetProperty function fails with error code 0x80090029 which means NTE_NOT_SUPPORTED. What I'm doing wrong? I've found an example (C++) doing the same as me, so, I guess everything is OK with my implementation, but...

My goal is to list all certificates on my smart card (actually an USB Token). I can do this using Crypto API, but the CryptAcquireContext function is deprecated, so, I need to use another one. Using CAPI I get the Certificate Store and I can list It using the default certificate dialog, so, I need, using CNG, get the Certificate Store to do the same thing, but the way I'm doing now seems wrong.

Well, some observations:

  1. I'm not checking the returns here (Status variable) to simplify this code sample
  2. The UnicodeStringToBinary function is strictly correct. The returned buffer (PByte) has twice the size of the original string and the bytes are all "nn 00 nn 00 nn 00", so, the Reader variable contains an Unicode String, just like the NCRYPT_READER_PROPERTY property requires. I can post the code on request.
  3. My NCryptOpenStorageProvider signature is more close of the Windows API version, so, its first argument is a pointer to NCRYPT_PROV_HANDLE
delphi
certificate
cng
asked on Stack Overflow Jun 27, 2018 by Carlos B. Feitoza Filho • edited Sep 4, 2018 by Jason Aller

0 Answers

Nobody has answered this question yet.


User contributions licensed under CC BY-SA 3.0