Discuss this help topic in SecureBlackbox Forum

Use PKCS#11 (hardware) storages

PKCS#11 is an interface for communicating with hardware security modules (HSMs), often also referred to as smart cards, crypto-tokens or simply tokens. SecureBlackbox works with certificates and keys stored on hardware tokens via its TElPKCS11CertStorage component. TElPKCS11CertStorage, just as any other certificate storage, provides unified interface to certificate media.

To access certificates stored on a security device via the PKCS#11 interface you need to know the location of its PKCS#11 driver. This driver, typically a dynamically linked library (DLL), is normally installed with the token software package either to Windows System32 directory, or to the driver vendor's subdirectory in Program Files. Note that the platform for which the driver was compiled must match the platform for which your application is compiled. That is, if you compile your application for x64 target, you will need an x64 PKCS#11 driver. The majority of vendors deploy two copies of the driver, for x64 and x86 environments.

Among sample driver names are asepkcs.dll, pteidpkcs11.dll and aitpkc211.dll, but generally the name is unique to the vendor and its device type.

The following step-by-step instruction explains how to access device-based certificates. Note (.NET only), Before compiling and running your code, put the SecureBlackbox_PKCS11Proxy.dll assembly next to your application's binary. The proxy DLL dispatches calls from the managed .NET code to the unmanaged driver DLL and back, and ensures that the data are sent in the correct form.

  1. Create a TElPKCS11CertStorage object (SBPKCS11CertStorage namespace): TElPKCS11CertStorage storage = new TElPKCS11CertStorage();
  2. Unless your application is really simple and/or you only plan to use one storage per the lifetime of your process, create a dedicated cryptoprovider for your storage (SBCryptoProvPKCS11 namespace): TElPKCS11CryptoProvider prov = new TElPKCS11CryptoProvider();
    storage.CryptoProvider = prov;
  3. Assign the full path to the PKCS#11 driver DLL to the DLLName property of the storage object: storage.DLLName = @"C:\Windows\System32\asepkcs.dll"; Don't forget that the target of your application must match the target of the driver!
  4. Call Open(): storage.Open(); This loads the driver and promotes the list of slots.
  5. If the storage was opened successfully, you can iterate over the list of slots exposed by the driver, and find the ones with the token 'inserted'. These are typically virtual slots, having nothing to do with your USB ports or card slots on the reader. Therefore, be prepared to have only one slot used for the physical token among many virtual ones.
    
    for (int i = 0; i < storage.Module.SlotCount; i++)
    {
      slotInfo = storage.Module.get_Slot(i);
      if (slotInfo.TokenPresent)
      {
        cbSlots.Items.Add(slotInfo.SlotDescription);
      }
    }
    
  6. Once you've found the required slot, you can open a session to it: TElPKCS11SessionInfo sessInfo = storage.OpenSession(slotIndex, true); The second parameter set to true means that we are opening a read-only session. It is recommended to always open read-only sessions, unless you need to modify the contents of the token (by adding or removing certificates or keys). In most cases you don't need a PIN on this stage, though some tokens, very rarely, may show a customised PIN window.
  7. Once the session is opened, the public area of the token (mainly comprised by certificates and public keys) will be accessible. You can access the certificates via the Certificates[] property of the storage object. You can also access low-level PKCS#11 objects via the Objects[] property: TElX509Certificate firstCert = storage.get_Certificates(0);
  8. You typically need to log in to the token to be able to use its the private area (private keys) and perform signing or decryption. This is done with the Login() method of the session object: sessInfo.Login(SBPKCS11Base.Unit.utUser, "1234"); The first parameter means that we are logging in as a normal user (there is another alternative, a security officer). The second parameter passes the PIN.
  9. Now that you are logged in, you can use certificates for signing. This sample code assumes you are using CMS classes: TElX509Certificate firstCert = storage.get_Certificates(0);
    cmsSig.Sign(firstCert, storage);
  10. Once you've finished with the storage, close the session. Then close the storage. After that, dispose both the storage and the crypto provider objects:
    
    sessInfo.Logout();
    storage.CloseSession(0);
    
    storage.Close();
    
    prov.Dispose();
    storage.Dispose();
    
    

How To articles related to PKCS#11

Discuss this help topic in SecureBlackbox Forum