Sample code for 30+ languages & platforms
Pascal (Lazarus/Delphi)

PKCS11 Get Token Info

See more PKCS11 Examples

Example showing how to discover the readers (slots) and smart cards and tokens available through a vendor's PKCS11 Cryptoki module, and get token information for each.

Chilkat Pascal (Lazarus/Delphi) Downloads

Pascal (Lazarus/Delphi)
program ChilkatDemo;

// Demonstrates using the Chilkat Pascal wrapper via the C bridge DLL.
// Builds as a console application under Lazarus (FPC) or Delphi.

{$IFDEF FPC}
  {$MODE DELPHI}
{$ENDIF}
{$APPTYPE CONSOLE}

uses
  {$IFDEF UNIX}
  cthreads,
  {$ENDIF}
  SysUtils,
  CkDllLoader,
  Chilkat.JsonArray,
  Chilkat.Pkcs11,
  Chilkat.JsonObject;

// ---------------------------------------------------------------------------

procedure RunDemo;
var
  success: Boolean;
  pkcs11: TPkcs11;
  onlyTokensPresent: Boolean;
  json: TJsonObject;
  id: Integer;
  slotDescription: string;
  tokenPresent: Boolean;
  removableDevice: Boolean;
  hardwareSlot: Boolean;
  hardwareVersionMajor: Integer;
  hardwareVersionMinor: Integer;
  firmwareVersionMajor: Integer;
  firmwareVersionMinor: Integer;
  tokenLabel: string;
  tokenManufacturerID: string;
  tokenModel: string;
  tokenSerialNumber: string;
  tokenMaxSessionCount: Integer;
  tokenSessionCount: Integer;
  tokenMaxRwSessionCount: Integer;
  tokenRwSessionCount: Integer;
  tokenMaxPinLen: Integer;
  tokenMinPinLen: Integer;
  tokenTotalPublicMemory: Integer;
  tokenFreePublicMemory: Integer;
  tokenTotalPrivateMemory: Integer;
  tokenFreePrivateMemory: Integer;
  tokenHardwareVersionMajor: Integer;
  tokenHardwareVersionMinor: Integer;
  tokenFirmwareVersionMajor: Integer;
  tokenFirmwareVersionMinor: Integer;
  tokenUtcTime: string;
  tokenRsaMinKeySize: Integer;
  tokenRsaMaxKeySize: Integer;
  j: Integer;
  count_j: Integer;
  strVal: string;
  tokenFlag: string;
  cryptokiVersionMajor: Integer;
  cryptokiVersionMinor: Integer;
  manufacturerID: string;
  libraryDescription: string;
  libraryVersionMajor: Integer;
  libraryVersionMinor: Integer;
  i: Integer;
  count_i: Integer;
  aFlags: TJsonArray;

begin
  success := False;

  //  This example requires the Chilkat API to have been previously unlocked.
  //  See Global Unlock Sample for sample code.

  //  Note: Chilkat's PKCS11 implementation runs on Windows, Linux, Mac OS X, and other supported operating systems.

  pkcs11 := TPkcs11.Create;

  //  Specify the vendor's Cryptoki module DLL / shared lib.
  //  The following PKCS11 driver DLL is for the WatchData ProxKey USB token. 
  //  You would use your smartcard/token vendor's PKCS11 driver DLL.
  pkcs11.SharedLibPath := 'SignatureP11.dll';

  success := pkcs11.Initialize();
  if (success = False) then
    begin
      WriteLn(pkcs11.LastErrorText);
      Exit;
    end;

  //  Call Discover to discover what's available.
  //  Indicate that we only want to return slots (readers) where tokens (or smart cards) are present.
  onlyTokensPresent := True;
  json := TJsonObject.Create;
  success := pkcs11.Discover(onlyTokensPresent,json);
  if (success = False) then
    begin
      WriteLn(pkcs11.LastErrorText);
      Exit;
    end;

  json.EmitCompact := False;
  WriteLn(json.Emit());

  //  Sample JSON output.
  //  Code for parsing this JSON is shown below..

  //  {
  //    "cryptokiVersion": {
  //      "major": 2,
  //      "minor": 10
  //    },
  //    "manufacturerID": "WatchData",
  //    "libraryDescription": "PKCS#11 cryptoki module",
  //    "libraryVersion": {
  //      "major": 3,
  //      "minor": 10
  //    },
  //    "slot": [
  //      {
  //        "id": 16385,
  //        "slotDescription": "Watchdata IC CARD Reader/Writer",
  //        "manufacturerID": "Watchdata",
  //        "tokenPresent": true,
  //        "removableDevice": true,
  //        "hardwareSlot": true,
  //        "hardwareVersion": {
  //          "major": 1,
  //          "minor": 0
  //        },
  //        "firmwareVersion": {
  //          "major": 1,
  //          "minor": 0
  //        },
  //        "token": {
  //          "label": "WD PROXKey",
  //          "manufacturerID": "Watchdata Corp.",
  //          "model": "TimeCos/PK",
  //          "serialNumber": "WD05376504",
  //          "flags": [
  //            "CKF_RNG",
  //            "CKF_LOGIN_REQUIRED",
  //            "CKF_USER_PIN_INITIALIZED",
  //            "CKF_DUAL_CRYPTO_OPERATIONS",
  //            "CKF_TOKEN_INITIALIZED"
  //          ],
  //          "maxSessionCount": 0,
  //          "sessionCount": 0,
  //          "maxRwSessionCount": 0,
  //          "rwSessionCount": 0,
  //          "maxPinLen": 32,
  //          "minPinLen": 6,
  //          "totalPublicMemory": 61440,
  //          "freePublicMemory": 70144,
  //          "totalPrivateMemory": 61440,
  //          "freePrivateMemory": 70144,
  //          "hardwareVersion": {
  //            "major": 2,
  //            "minor": 1
  //          },
  //          "firmwareVersion": {
  //            "major": 0,
  //            "minor": 0
  //          },
  //          "utcTime": "2024011509254600",
  //          "mechanism": [
  //            "CKM_RSA_PKCS_KEY_PAIR_GEN",
  //            "CKM_EC_KEY_PAIR_GEN",
  //            "CKM_DES_KEY_GEN",
  //            "80000001",
  //            "8000000B",
  //            "CKM_AES_KEY_GEN",
  //            "CKM_DES2_KEY_GEN",
  //            "CKM_DES3_KEY_GEN",
  //            "CKM_RSA_PKCS",
  //            "CKM_RSA_X_509",
  //            "CKM_ECDSA",
  //            "CKM_ECDSA_SHA1",
  //            "CKM_MD2_RSA_PKCS",
  //            "CKM_MD5_RSA_PKCS",
  //            "CKM_SHA1_RSA_PKCS",
  //            "CKM_SHA256_RSA_PKCS",
  //            "CKM_DES_ECB",
  //            "CKM_DES_CBC",
  //            "CKM_DES_CBC_PAD",
  //            "80000002",
  //            "CKM_CPK_ECDSA",
  //            "CKM_CPK_ECDSA_SHA1",
  //            "8000000C",
  //            "8000000D",
  //            "8000000E",
  //            "CKM_AES_ECB",
  //            "CKM_AES_CBC",
  //            "CKM_AES_CBC_PAD",
  //            "CKM_DES3_ECB",
  //            "CKM_DES3_CBC",
  //            "CKM_DES3_CBC_PAD",
  //            "CKM_SHA_1",
  //            "CKM_SHA_1_HMAC",
  //            "CKM_SHA_1_HMAC_GENERAL",
  //            "CKM_SHA256",
  //            "CKM_SHA256_HMAC",
  //            "CKM_SHA256_HMAC_GENERAL",
  //            "CKM_MD2",
  //            "CKM_MD2_HMAC",
  //            "CKM_MD2_HMAC_GENERAL",
  //            "CKM_MD5",
  //            "CKM_MD5_HMAC",
  //            "CKM_MD5_HMAC_GENERAL",
  //            "CKM_SSL3_PRE_MASTER_KEY_GEN",
  //            "CKM_SSL3_MASTER_KEY_DERIVE",
  //            "CKM_SSL3_KEY_AND_MAC_DERIVE",
  //            "CKM_SSL3_MD5_MAC",
  //            "CKM_SSL3_SHA1_MAC"
  //          ],
  //          "rsa": {
  //            "minKeySize": 1024,
  //            "maxKeySize": 4096
  //          }
  //        }
  //      }
  //    ]
  //  }

  //  Use this online tool to generate parsing code from sample JSON: 
  //  Generate Parsing Code from JSON

  //  Use this online tool to generate parsing code from sample JSON: 
  //  Generate Parsing Code from JSON

  cryptokiVersionMajor := json.IntOf('cryptokiVersion.major');
  cryptokiVersionMinor := json.IntOf('cryptokiVersion.minor');
  manufacturerID := json.StringOf('manufacturerID');
  libraryDescription := json.StringOf('libraryDescription');
  libraryVersionMajor := json.IntOf('libraryVersion.major');
  libraryVersionMinor := json.IntOf('libraryVersion.minor');
  i := 0;
  count_i := json.SizeOfArray('slot');
  while i < count_i do
    begin
      json.I := i;
      id := json.IntOf('slot[i].id');
      slotDescription := json.StringOf('slot[i].slotDescription');
      manufacturerID := json.StringOf('slot[i].manufacturerID');
      tokenPresent := json.BoolOf('slot[i].tokenPresent');
      removableDevice := json.BoolOf('slot[i].removableDevice');
      hardwareSlot := json.BoolOf('slot[i].hardwareSlot');
      hardwareVersionMajor := json.IntOf('slot[i].hardwareVersion.major');
      hardwareVersionMinor := json.IntOf('slot[i].hardwareVersion.minor');
      firmwareVersionMajor := json.IntOf('slot[i].firmwareVersion.major');
      firmwareVersionMinor := json.IntOf('slot[i].firmwareVersion.minor');
      tokenLabel := json.StringOf('slot[i].token.label');
      tokenManufacturerID := json.StringOf('slot[i].token.manufacturerID');
      tokenModel := json.StringOf('slot[i].token.model');
      tokenSerialNumber := json.StringOf('slot[i].token.serialNumber');
      tokenMaxSessionCount := json.IntOf('slot[i].token.maxSessionCount');
      tokenSessionCount := json.IntOf('slot[i].token.sessionCount');
      tokenMaxRwSessionCount := json.IntOf('slot[i].token.maxRwSessionCount');
      tokenRwSessionCount := json.IntOf('slot[i].token.rwSessionCount');
      tokenMaxPinLen := json.IntOf('slot[i].token.maxPinLen');
      tokenMinPinLen := json.IntOf('slot[i].token.minPinLen');
      tokenTotalPublicMemory := json.IntOf('slot[i].token.totalPublicMemory');
      tokenFreePublicMemory := json.IntOf('slot[i].token.freePublicMemory');
      tokenTotalPrivateMemory := json.IntOf('slot[i].token.totalPrivateMemory');
      tokenFreePrivateMemory := json.IntOf('slot[i].token.freePrivateMemory');
      tokenHardwareVersionMajor := json.IntOf('slot[i].token.hardwareVersion.major');
      tokenHardwareVersionMinor := json.IntOf('slot[i].token.hardwareVersion.minor');
      tokenFirmwareVersionMajor := json.IntOf('slot[i].token.firmwareVersion.major');
      tokenFirmwareVersionMinor := json.IntOf('slot[i].token.firmwareVersion.minor');
      tokenUtcTime := json.StringOf('slot[i].token.utcTime');
      tokenRsaMinKeySize := json.IntOf('slot[i].token.rsa.minKeySize');
      tokenRsaMaxKeySize := json.IntOf('slot[i].token.rsa.maxKeySize');

      //  The following token flag strings are possible:

      //  CKF_RNG: has random # generator

      //  CKF_WRITE_PROTECTED: token is write-protected

      //  CKF_LOGIN_REQUIRED:user must login

      //  CKF_USER_PIN_INITIALIZED:normal user's PIN is set

      //  CKF_RESTORE_KEY_NOT_NEEDED: Every time the state of cryptographic operations of a session is
      //     successfully saved, all keys needed to continue those operations are stored in the state

      //  CKF_CLOCK_ON_TOKEN: The token has some sort of clock.  The time on the clock is returned in the slot[i].token.utcTime

      //  CKF_PROTECTED_AUTHENTICATION_PATH: There is some way for the user to login without sending a PIN through the Cryptoki library itself

      //  CKF_DUAL_CRYPTO_OPERATIONS: A single session with the token can perform dual simultaneous cryptographic operations
      //     (digest and encrypt; decrypt and digest; sign and encrypt; and decrypt and sign)

      //  CKF_TOKEN_INITIALIZED: The token has been initialized.

      //  CKF_SECONDARY_AUTHENTICATION: The token supports secondary authentication for private key objects.

      //  CKF_USER_PIN_COUNT_LOW: An incorrect user login PIN has been entered at least once since the last successful authentication.

      //  CKF_USER_PIN_FINAL_TRY: Supplying an incorrect user PIN will it to become locked.

      //  CKF_USER_PIN_LOCKED: The user PIN has been locked. User login to the token is not possible.

      //  CKF_USER_PIN_TO_BE_CHANGED: The user PIN value is the default value set by token initialization or manufacturing,
      //     or the PIN has been expired by the card.

      //  CKF_SO_PIN_COUNT_LOW: An incorrect SO login PIN has been entered at least once since the last successful authentication.

      //  CKF_SO_PIN_FINAL_TRY: Supplying an incorrect SO PIN will it to become locked.

      //  CKF_SO_PIN_LOCKED: The SO PIN has been locked. SO login to the token is not possible.

      //  CKF_SO_PIN_TO_BE_CHANGED: The SO PIN value is the default value set by token initialization or manufacturing,
      //     or the PIN has been expired by the card.

      //  To see if particular flags are present:
      aFlags := json.ArrayOf('slot[i].token.flags');
      if (aFlags.FindString('CKF_USER_PIN_LOCKED',True) >= 0) then
        begin
          WriteLn('The token is locked.');
        end;
      if (aFlags.FindString('CKF_RNG',True) >= 0) then
        begin
          WriteLn('The token has a random number generator.');
        end;
      //  ...
      aFlags.Free;

      //  To iterate over all flags..
      j := 0;
      count_j := json.SizeOfArray('slot[i].token.flags');
      while j < count_j do
        begin
          json.J := j;
          tokenFlag := json.StringOf('slot[i].token.flags[j]');
          j := j + 1;
        end;

      j := 0;
      count_j := json.SizeOfArray('slot[i].token.mechanism');
      while j < count_j do
        begin
          json.J := j;
          strVal := json.StringOf('slot[i].token.mechanism[j]');
          j := j + 1;
        end;

      i := i + 1;
    end;



  pkcs11.Free;
  json.Free;

end;

// ---------------------------------------------------------------------------

begin

  try
    RunDemo;
  except
    on E: Exception do
      WriteLn('Unhandled exception: ', E.ClassName, ': ', E.Message);
  end;

  WriteLn;
  {$IFDEF MSWINDOWS}
  WriteLn('Press Enter to exit...');
  ReadLn;
  {$ENDIF}
end.