Skip to content

Example to use OpenSC with Microsoft CNG and CryptoAPI

Veronika Hanulíková edited this page May 3, 2024 · 2 revisions

OpenSC and Microsoft CNG

It is possible to use the Smartcard via OpenSC with the Microsoft CNG library. CNG can be used together with CryptoAPI.

Example: Read the x509 Certificate from connected Smartcard

With the CNG its easy to use the smartcard like a normal pkcs12 container or something similar.

#include <Windows.h>
#include <wincrypt.h>

#include <functional>
#include <memory>
#include <vector>

template <typename T>
using raii_ptr = std::unique_ptr<T, std::function<void(T *)>>;

// Read the x509 from connected smartcard
int main() {
  NCRYPT_PROV_HANDLE provider = NULL;
  raii_ptr<NCRYPT_PROV_HANDLE> hProvider(&provider,
                                         [](NCRYPT_PROV_HANDLE *handle) {
                                           if (handle)
                                             NCryptFreeObject(*handle);
                                         });
  NCryptOpenStorageProvider(hProvider.get(), MS_SMART_CARD_KEY_STORAGE_PROVIDER,
                            0);

  NCryptKeyName *pKeyName = nullptr;
  PVOID pState = nullptr;

  auto status = NCryptEnumKeys(*hProvider, 0, &pKeyName, &pState, 0);
  if (status == NTE_NO_MORE_ITEMS)
    return 0;

  if (status != ERROR_SUCCESS && status != ERROR_SUCCESS) {
    printf("Error: NCryptEnumKeys : 0x%x\n", status);
    return 0;
  }
  printf("Ok: NCryptEnumKeys : 0x%x\n", status);

  NCRYPT_KEY_HANDLE key = NULL;
  raii_ptr<NCRYPT_KEY_HANDLE> hKey(&key, [](NCRYPT_KEY_HANDLE *handle) {
    if (handle)
      NCryptFreeObject(*handle);
  });
  status = NCryptOpenKey(*hProvider, hKey.get(), pKeyName->pszName,
                         pKeyName->dwLegacyKeySpec, 0);

  wprintf(L"Ok: NCryptOpenKey : 0x%x, Key Name: %s\n", status,
          pKeyName->pszName);
  wprintf(L"Using key : %s\n", pKeyName->pszName);

  DWORD size = 0;
  NCryptGetProperty(*hKey, NCRYPT_CERTIFICATE_PROPERTY, nullptr, 0, &size, 0);
  std::vector<BYTE> cert;
  cert.resize(size);
  NCryptGetProperty(*hKey, NCRYPT_CERTIFICATE_PROPERTY, &cert[0], size, &size,
                    0);

  DWORD nDestinationSize;
  if (CryptBinaryToString(reinterpret_cast<const BYTE *>(&cert[0]), cert.size(),
                          CRYPT_STRING_BASE64, nullptr, &nDestinationSize)) {
    LPTSTR pszDestination = static_cast<LPTSTR>(HeapAlloc(
        GetProcessHeap(), HEAP_NO_SERIALIZE, nDestinationSize * sizeof(TCHAR)));
    if (pszDestination) {
      if (CryptBinaryToString(reinterpret_cast<const BYTE *>(&cert[0]),
                              cert.size(), CRYPT_STRING_BASE64, pszDestination,
                              &nDestinationSize)) {

        printf(pszDestination);
      }
      HeapFree(GetProcessHeap(), HEAP_NO_SERIALIZE, pszDestination);
    }
  }
  return 0;
}

Important functions

Clone this wiki locally
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy