tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

pkcs11testmodule.cpp (28509B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* This Source Code Form is subject to the terms of the Mozilla Public
      3 * License, v. 2.0. If a copy of the MPL was not distributed with this
      4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      5 
      6 // This is a testing PKCS #11 module that simulates a token being inserted and
      7 // removed from a slot every 50ms. This is achieved mainly in
      8 // Test_C_WaitForSlotEvent. If the application that loaded this module calls
      9 // C_WaitForSlotEvent, this module waits for 50ms and returns, having changed
     10 // its internal state to report that the token has either been inserted or
     11 // removed, as appropriate.
     12 // This module also provides an alternate token that is always present for tests
     13 // that don't want the cyclic behavior described above.
     14 
     15 #include <assert.h>
     16 #include <string.h>
     17 
     18 #ifdef _WIN32
     19 #  include <windows.h>  // for Sleep
     20 #else
     21 #  include <unistd.h>  // for usleep
     22 #endif
     23 
     24 #include "pkcs11t.h"
     25 
     26 #undef CK_DECLARE_FUNCTION
     27 
     28 #ifdef _WIN32
     29 #define CK_DECLARE_FUNCTION(rtype, func) extern rtype __declspec(dllexport) func
     30 #else
     31 #define CK_DECLARE_FUNCTION(rtype, func) extern rtype func
     32 #endif
     33 
     34 #include "pkcs11.h"
     35 
     36 #if __cplusplus < 201103L
     37 #  include <prtypes.h>
     38 #  define static_assert(condition, message) PR_STATIC_ASSERT(condition)
     39 #endif
     40 
     41 CK_RV Test_C_Initialize(CK_VOID_PTR) { return CKR_OK; }
     42 
     43 CK_RV Test_C_Finalize(CK_VOID_PTR) { return CKR_OK; }
     44 
     45 static const CK_VERSION CryptokiVersion = {2, 2};
     46 static const CK_VERSION TestLibraryVersion = {0, 0};
     47 static const char TestLibraryDescription[] = "Test PKCS11 Library";
     48 static const char TestManufacturerID[] = "Test PKCS11 Manufacturer ID";
     49 
     50 /* The dest buffer is one in the CK_INFO or CK_TOKEN_INFO structs.
     51 * Those buffers are padded with spaces. DestSize corresponds to the declared
     52 * size for those buffers (e.g. 32 for `char foo[32]`).
     53 * The src buffer is a string literal. SrcSize includes the string
     54 * termination character (e.g. 4 for `const char foo[] = "foo"` */
     55 template <size_t DestSize, size_t SrcSize>
     56 void CopyString(unsigned char (&dest)[DestSize], const char (&src)[SrcSize]) {
     57  static_assert(DestSize >= SrcSize - 1, "DestSize >= SrcSize - 1");
     58  memcpy(dest, src, SrcSize - 1);
     59  memset(dest + SrcSize - 1, ' ', DestSize - SrcSize + 1);
     60 }
     61 
     62 CK_RV Test_C_GetInfo(CK_INFO_PTR pInfo) {
     63  if (!pInfo) {
     64    return CKR_ARGUMENTS_BAD;
     65  }
     66 
     67  pInfo->cryptokiVersion = CryptokiVersion;
     68  CopyString(pInfo->manufacturerID, TestManufacturerID);
     69  pInfo->flags = 0;  // must be 0
     70  CopyString(pInfo->libraryDescription, TestLibraryDescription);
     71  pInfo->libraryVersion = TestLibraryVersion;
     72  return CKR_OK;
     73 }
     74 
     75 CK_RV Test_C_GetFunctionList(CK_FUNCTION_LIST_PTR_PTR) { return CKR_OK; }
     76 
     77 static int tokenPresent = 0;
     78 
     79 // The token in slot 4 has 4 objects:
     80 // 1. CKO_PROFILE with CKP_PUBLIC_CERTIFICATES_TOKEN
     81 // 2. CKO_PROFILE with CKP_BASELINE_PROVIDER
     82 // 3. CKO_CERTIFICATE with CKA_ID "\x00..\x0f"
     83 // 4. CKO_CERTIFICATE with CKA_ID "\x10..\x1f"
     84 static bool readingProfile = false;
     85 static const CK_PROFILE_ID profiles[] = {CKP_PUBLIC_CERTIFICATES_TOKEN,
     86                                         CKP_BASELINE_PROVIDER};
     87 static int profileIndex = 0;
     88 
     89 static bool readingCert = false;
     90 static const unsigned char certId1[] = {
     91  0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
     92  0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
     93 };
     94 static const char *certLabel1 = "cert1";
     95 static const unsigned char certId2[] = {
     96  0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
     97  0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f
     98 };
     99 static const char *certLabel2 = "cert2";
    100 
    101 static const unsigned char certValue[] = {
    102  0x30, 0x82, 0x01, 0x54, 0x30, 0x81, 0xfc, 0xa0, 0x03, 0x02, 0x01, 0x02,
    103  0x02, 0x02, 0x0e, 0x42, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce,
    104  0x3d, 0x04, 0x03, 0x02, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03,
    105  0x55, 0x04, 0x03, 0x13, 0x0a, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65,
    106  0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, 0x32, 0x30, 0x31, 0x32, 0x31,
    107  0x39, 0x30, 0x39, 0x30, 0x32, 0x34, 0x39, 0x5a, 0x17, 0x0d, 0x32, 0x31,
    108  0x30, 0x33, 0x31, 0x39, 0x30, 0x39, 0x30, 0x32, 0x34, 0x39, 0x5a, 0x30,
    109  0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a,
    110  0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x43, 0x41, 0x30, 0x59,
    111  0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06,
    112  0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00,
    113  0x04, 0x24, 0xd1, 0x96, 0xcc, 0x72, 0x36, 0xbb, 0xd6, 0x04, 0x36, 0x14,
    114  0x59, 0x9a, 0x27, 0x24, 0x6b, 0x03, 0x7c, 0x02, 0x69, 0x68, 0x50, 0x70,
    115  0x52, 0xe5, 0x5f, 0xe1, 0xf1, 0xd4, 0x0a, 0x00, 0x18, 0x76, 0x14, 0xa3,
    116  0xed, 0x7d, 0xc5, 0x0a, 0xfe, 0xe4, 0x6f, 0x09, 0xf8, 0xcd, 0xe8, 0x5a,
    117  0x39, 0x81, 0xf4, 0xcc, 0x25, 0xbe, 0x26, 0x76, 0xe1, 0x23, 0x52, 0x09,
    118  0x6f, 0xbd, 0xf1, 0x75, 0xbe, 0xa3, 0x3c, 0x30, 0x3a, 0x30, 0x14, 0x06,
    119  0x09, 0x60, 0x86, 0x48, 0x01, 0x86, 0xf8, 0x42, 0x01, 0x01, 0x01, 0x01,
    120  0xff, 0x04, 0x04, 0x03, 0x02, 0x02, 0x04, 0x30, 0x12, 0x06, 0x03, 0x55,
    121  0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff,
    122  0x02, 0x01, 0x00, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01,
    123  0xff, 0x04, 0x04, 0x03, 0x02, 0x07, 0x80, 0x30, 0x0a, 0x06, 0x08, 0x2a,
    124  0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x47, 0x00, 0x30, 0x44,
    125  0x02, 0x20, 0x76, 0x56, 0x09, 0xe9, 0x79, 0xc2, 0x62, 0x28, 0xfc, 0x48,
    126  0xf8, 0xac, 0x73, 0xbb, 0xe1, 0xe5, 0x79, 0x93, 0x78, 0x05, 0x4b, 0x45,
    127  0x08, 0xcf, 0x10, 0x9f, 0x0d, 0xb9, 0x50, 0x7d, 0x70, 0x24, 0x02, 0x20,
    128  0x27, 0x52, 0xe7, 0x9e, 0x42, 0xe3, 0xb2, 0x4d, 0xbb, 0x7d, 0xa3, 0x81,
    129  0x5f, 0x7f, 0x0f, 0x3a, 0x55, 0x34, 0xfa, 0x86, 0x35, 0xcb, 0x68, 0x4f,
    130  0xad, 0x67, 0x67, 0x05, 0x36, 0xcb, 0x11, 0x4d
    131 };
    132 static const unsigned char certSerial[] = {
    133  0x02, 0x02, 0x0e, 0x42
    134 };
    135 static const unsigned char certIssuer[] = {
    136  0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
    137  0x0a, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x43, 0x41
    138 };
    139 
    140 static const struct cert {
    141  const unsigned char *id;
    142  size_t idLen;
    143  const char *label;
    144 } certs[] = {
    145  { certId1, sizeof(certId1), certLabel1 },
    146  { certId2, sizeof(certId2), certLabel2 }
    147 };
    148 static int certIndex = 0;
    149 static CK_OBJECT_HANDLE certHandle = CK_INVALID_HANDLE;
    150 static bool certIdGiven = false;
    151 
    152 CK_RV Test_C_GetSlotList(CK_BBOOL limitToTokensPresent,
    153                         CK_SLOT_ID_PTR pSlotList, CK_ULONG_PTR pulCount) {
    154  if (!pulCount) {
    155    return CKR_ARGUMENTS_BAD;
    156  }
    157 
    158  CK_SLOT_ID slots[4];
    159  CK_ULONG slotCount = 0;
    160 
    161  // We always return slot 2 and 4.
    162  slots[slotCount++] = 2;
    163  slots[slotCount++] = 4;
    164 
    165  // Slot 1 is a removable slot where a token is present if
    166  // tokenPresent = CK_TRUE.
    167  if (tokenPresent || !limitToTokensPresent) {
    168    slots[slotCount++] = 1;
    169  }
    170 
    171  // Slot 3 is a removable slot which never has a token.
    172  if (!limitToTokensPresent) {
    173    slots[slotCount++] = 3;
    174  }
    175 
    176  if (pSlotList) {
    177    if (*pulCount < slotCount) {
    178      return CKR_BUFFER_TOO_SMALL;
    179    }
    180    memcpy(pSlotList, slots, sizeof(CK_SLOT_ID) * slotCount);
    181  }
    182 
    183  *pulCount = slotCount;
    184  return CKR_OK;
    185 }
    186 
    187 static const char TestSlotDescription[] = "Test PKCS11 Slot";
    188 static const char TestSlot2Description[] = "Test PKCS11 Slot 二";
    189 static const char TestSlot3Description[] = "Empty PKCS11 Slot";
    190 static const char TestSlot4Description[] = "Test PKCS11 Public Certs Slot";
    191 
    192 CK_RV Test_C_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo) {
    193  if (!pInfo) {
    194    return CKR_ARGUMENTS_BAD;
    195  }
    196 
    197  switch (slotID) {
    198    case 1:
    199      CopyString(pInfo->slotDescription, TestSlotDescription);
    200      pInfo->flags =
    201          (tokenPresent ? CKF_TOKEN_PRESENT : 0) | CKF_REMOVABLE_DEVICE;
    202      break;
    203    case 2:
    204      CopyString(pInfo->slotDescription, TestSlot2Description);
    205      pInfo->flags = CKF_TOKEN_PRESENT | CKF_REMOVABLE_DEVICE;
    206      break;
    207    case 3:
    208      CopyString(pInfo->slotDescription, TestSlot3Description);
    209      pInfo->flags = CKF_REMOVABLE_DEVICE;
    210      break;
    211    case 4:
    212      CopyString(pInfo->slotDescription, TestSlot4Description);
    213      pInfo->flags = CKF_TOKEN_PRESENT | CKF_REMOVABLE_DEVICE;
    214      break;
    215    default:
    216      return CKR_ARGUMENTS_BAD;
    217  }
    218 
    219  CopyString(pInfo->manufacturerID, TestManufacturerID);
    220  pInfo->hardwareVersion = TestLibraryVersion;
    221  pInfo->firmwareVersion = TestLibraryVersion;
    222  return CKR_OK;
    223 }
    224 
    225 // Deliberately include énye to ensure we're handling encoding correctly.
    226 // The PKCS #11 base specification v2.20 specifies that strings be encoded
    227 // as UTF-8.
    228 static const char TestTokenLabel[] = "Test PKCS11 Tokeñ Label";
    229 static const char TestToken2Label[] = "Test PKCS11 Tokeñ 2 Label";
    230 static const char TestToken4Label[] = "Test PKCS11 Public Certs Token";
    231 static const char TestTokenModel[] = "Test Model";
    232 
    233 CK_RV Test_C_GetTokenInfo(CK_SLOT_ID slotID, CK_TOKEN_INFO_PTR pInfo) {
    234  if (!pInfo) {
    235    return CKR_ARGUMENTS_BAD;
    236  }
    237 
    238  switch (slotID) {
    239    case 1:
    240      CopyString(pInfo->label, TestTokenLabel);
    241      break;
    242    case 2:
    243      CopyString(pInfo->label, TestToken2Label);
    244      break;
    245    case 4:
    246      CopyString(pInfo->label, TestToken4Label);
    247      break;
    248    default:
    249      return CKR_ARGUMENTS_BAD;
    250  }
    251 
    252  CopyString(pInfo->manufacturerID, TestManufacturerID);
    253  CopyString(pInfo->model, TestTokenModel);
    254  memset(pInfo->serialNumber, 0, sizeof(pInfo->serialNumber));
    255  pInfo->flags = CKF_TOKEN_INITIALIZED;
    256  pInfo->ulMaxSessionCount = 1;
    257  pInfo->ulSessionCount = 0;
    258  pInfo->ulMaxRwSessionCount = 1;
    259  pInfo->ulRwSessionCount = 0;
    260  pInfo->ulMaxPinLen = 4;
    261  pInfo->ulMinPinLen = 4;
    262  pInfo->ulTotalPublicMemory = 1024;
    263  pInfo->ulFreePublicMemory = 1024;
    264  pInfo->ulTotalPrivateMemory = 1024;
    265  pInfo->ulFreePrivateMemory = 1024;
    266  pInfo->hardwareVersion = TestLibraryVersion;
    267  pInfo->firmwareVersion = TestLibraryVersion;
    268  memset(pInfo->utcTime, 0, sizeof(pInfo->utcTime));
    269  return CKR_OK;
    270 }
    271 
    272 CK_RV Test_C_GetMechanismList(CK_SLOT_ID, CK_MECHANISM_TYPE_PTR,
    273                              CK_ULONG_PTR pulCount) {
    274  if (!pulCount) {
    275    return CKR_ARGUMENTS_BAD;
    276  }
    277 
    278  *pulCount = 0;
    279  return CKR_OK;
    280 }
    281 
    282 CK_RV Test_C_GetMechanismInfo(CK_SLOT_ID, CK_MECHANISM_TYPE,
    283                              CK_MECHANISM_INFO_PTR) {
    284  return CKR_OK;
    285 }
    286 
    287 CK_RV Test_C_InitToken(CK_SLOT_ID, CK_UTF8CHAR_PTR, CK_ULONG, CK_UTF8CHAR_PTR) {
    288  return CKR_OK;
    289 }
    290 
    291 CK_RV Test_C_InitPIN(CK_SESSION_HANDLE, CK_UTF8CHAR_PTR, CK_ULONG) {
    292  return CKR_FUNCTION_NOT_SUPPORTED;
    293 }
    294 
    295 CK_RV Test_C_SetPIN(CK_SESSION_HANDLE, CK_UTF8CHAR_PTR, CK_ULONG,
    296                    CK_UTF8CHAR_PTR, CK_ULONG) {
    297  return CKR_FUNCTION_NOT_SUPPORTED;
    298 }
    299 
    300 CK_RV Test_C_OpenSession(CK_SLOT_ID slotID, CK_FLAGS, CK_VOID_PTR, CK_NOTIFY,
    301                         CK_SESSION_HANDLE_PTR phSession) {
    302  switch (slotID) {
    303    case 1:
    304      *phSession = 1;
    305      break;
    306    case 2:
    307      *phSession = 2;
    308      break;
    309    case 4:
    310      *phSession = 4;
    311      break;
    312    default:
    313      return CKR_ARGUMENTS_BAD;
    314  }
    315 
    316  return CKR_OK;
    317 }
    318 
    319 CK_RV Test_C_CloseSession(CK_SESSION_HANDLE) { return CKR_OK; }
    320 
    321 CK_RV Test_C_CloseAllSessions(CK_SLOT_ID) { return CKR_OK; }
    322 
    323 CK_RV Test_C_GetSessionInfo(CK_SESSION_HANDLE hSession,
    324                            CK_SESSION_INFO_PTR pInfo) {
    325  if (!pInfo) {
    326    return CKR_ARGUMENTS_BAD;
    327  }
    328 
    329  switch (hSession) {
    330    case 1:
    331      pInfo->slotID = 1;
    332      break;
    333    case 2:
    334      pInfo->slotID = 2;
    335      break;
    336    case 4:
    337      pInfo->slotID = 4;
    338      break;
    339    default:
    340      return CKR_ARGUMENTS_BAD;
    341  }
    342 
    343  pInfo->state = CKS_RO_PUBLIC_SESSION;
    344  pInfo->flags = CKF_SERIAL_SESSION;
    345  return CKR_OK;
    346 }
    347 
    348 CK_RV Test_C_GetOperationState(CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG_PTR) {
    349  return CKR_FUNCTION_NOT_SUPPORTED;
    350 }
    351 
    352 CK_RV Test_C_SetOperationState(CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG,
    353                               CK_OBJECT_HANDLE, CK_OBJECT_HANDLE) {
    354  return CKR_FUNCTION_NOT_SUPPORTED;
    355 }
    356 
    357 CK_RV Test_C_Login(CK_SESSION_HANDLE, CK_USER_TYPE, CK_UTF8CHAR_PTR, CK_ULONG) {
    358  return CKR_FUNCTION_NOT_SUPPORTED;
    359 }
    360 
    361 CK_RV Test_C_Logout(CK_SESSION_HANDLE) { return CKR_FUNCTION_NOT_SUPPORTED; }
    362 
    363 CK_RV Test_C_CreateObject(CK_SESSION_HANDLE, CK_ATTRIBUTE_PTR, CK_ULONG,
    364                          CK_OBJECT_HANDLE_PTR) {
    365  return CKR_FUNCTION_NOT_SUPPORTED;
    366 }
    367 
    368 CK_RV Test_C_CopyObject(CK_SESSION_HANDLE, CK_OBJECT_HANDLE, CK_ATTRIBUTE_PTR,
    369                        CK_ULONG, CK_OBJECT_HANDLE_PTR) {
    370  return CKR_FUNCTION_NOT_SUPPORTED;
    371 }
    372 
    373 CK_RV Test_C_DestroyObject(CK_SESSION_HANDLE, CK_OBJECT_HANDLE) {
    374  return CKR_FUNCTION_NOT_SUPPORTED;
    375 }
    376 
    377 CK_RV Test_C_GetObjectSize(CK_SESSION_HANDLE, CK_OBJECT_HANDLE, CK_ULONG_PTR) {
    378  return CKR_FUNCTION_NOT_SUPPORTED;
    379 }
    380 
    381 CK_RV Test_C_GetAttributeValue(CK_SESSION_HANDLE hSession,
    382                               CK_OBJECT_HANDLE hObject,
    383                               CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount) {
    384  if (hSession == 4) {
    385    switch (hObject) {
    386    case 1:
    387    case 2:
    388      for (CK_ULONG count = 0; count < ulCount; count++) {
    389        if (pTemplate[count].type == CKA_PROFILE_ID) {
    390          if (pTemplate[count].pValue) {
    391            assert(pTemplate[count].ulValueLen == sizeof(CK_ULONG));
    392            CK_ULONG value = profiles[hObject - 1];
    393            memcpy(pTemplate[count].pValue, &value, sizeof(value));
    394          } else {
    395            pTemplate[count].ulValueLen = sizeof(CK_ULONG);
    396          }
    397        } else {
    398          pTemplate[count].ulValueLen = (CK_ULONG)-1;
    399        }
    400      }
    401      return CKR_OK;
    402    case 3:
    403    case 4:
    404      for (CK_ULONG count = 0; count < ulCount; count++) {
    405        switch (pTemplate[count].type) {
    406        case CKA_TOKEN:
    407          if (pTemplate[count].pValue) {
    408            assert(pTemplate[count].ulValueLen == sizeof(CK_BBOOL));
    409            CK_BBOOL value = true;
    410            memcpy(pTemplate[count].pValue, &value, sizeof(value));
    411          } else {
    412            pTemplate[count].ulValueLen = sizeof(CK_BBOOL);
    413          }
    414          break;
    415 
    416        case CKA_LABEL: {
    417          const char *label = certs[hObject - 3].label;
    418          size_t labelLen = strlen(label);
    419          if (pTemplate[count].pValue) {
    420            if (pTemplate[count].ulValueLen >= labelLen) {
    421              memcpy(pTemplate[count].pValue, label, labelLen);
    422            } else {
    423              pTemplate[count].ulValueLen = CK_UNAVAILABLE_INFORMATION;
    424            }
    425          } else {
    426            pTemplate[count].ulValueLen = labelLen;
    427          }
    428          break;
    429        }
    430 
    431 #define BYTEARRAY_CASE(label, array) \
    432        case label: \
    433          if (pTemplate[count].pValue) { \
    434            if (pTemplate[count].ulValueLen >= sizeof(array)) { \
    435              memcpy(pTemplate[count].pValue, array, sizeof(array)); \
    436            } else { \
    437              pTemplate[count].ulValueLen = CK_UNAVAILABLE_INFORMATION; \
    438            } \
    439          } else { \
    440            pTemplate[count].ulValueLen = sizeof(array); \
    441          } \
    442          break;
    443 
    444        BYTEARRAY_CASE(CKA_VALUE, certValue)
    445        BYTEARRAY_CASE(CKA_SERIAL_NUMBER, certSerial)
    446        BYTEARRAY_CASE(CKA_ISSUER, certIssuer)
    447 
    448        default:
    449          pTemplate[count].ulValueLen = CK_UNAVAILABLE_INFORMATION;
    450          break;
    451        }
    452      }
    453      return CKR_OK;
    454    default:
    455      break;
    456    }
    457  }
    458  return CKR_FUNCTION_NOT_SUPPORTED;
    459 }
    460 
    461 CK_RV Test_C_SetAttributeValue(CK_SESSION_HANDLE, CK_OBJECT_HANDLE,
    462                               CK_ATTRIBUTE_PTR, CK_ULONG) {
    463  return CKR_FUNCTION_NOT_SUPPORTED;
    464 }
    465 
    466 CK_RV Test_C_FindObjectsInit(CK_SESSION_HANDLE hSession,
    467                             CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount) {
    468  // Slot 4
    469  if (hSession == 4) {
    470    CK_OBJECT_CLASS objectClass = CKO_DATA;
    471    CK_BYTE *id = NULL;
    472    CK_ULONG idLen = 0;
    473    for (CK_ULONG count = 0; count < ulCount; count++) {
    474      CK_ATTRIBUTE attribute = pTemplate[count];
    475      switch (attribute.type) {
    476      case CKA_CLASS:
    477        assert(attribute.ulValueLen == sizeof(CK_OBJECT_CLASS));
    478 
    479        memcpy(&objectClass, attribute.pValue, attribute.ulValueLen);
    480        break;
    481      case CKA_ID:
    482        id = (CK_BYTE *)attribute.pValue;
    483        idLen = attribute.ulValueLen;
    484        break;
    485      default:
    486        break;
    487      }
    488    }
    489 
    490    switch (objectClass) {
    491    case CKO_PROFILE:
    492      readingProfile = true;
    493      profileIndex = 0;
    494      break;
    495    case CKO_CERTIFICATE:
    496      readingCert = true;
    497      certIndex = 0;
    498      if (id) {
    499        certIdGiven = true;
    500        for (size_t count = 0; count < sizeof(certs) / sizeof(certs[0]); count++) {
    501          if (certs[count].idLen == idLen &&
    502              memcmp(certs[count].id, id, idLen) == 0) {
    503            certHandle = count + 3;
    504            break;
    505          }
    506        }
    507      }
    508      break;
    509    default:
    510      break;
    511    }
    512  }
    513  return CKR_OK;
    514 }
    515 
    516 CK_RV Test_C_FindObjects(CK_SESSION_HANDLE hSession,
    517                         CK_OBJECT_HANDLE_PTR phObject,
    518                         CK_ULONG ulMaxObjectCount,
    519                         CK_ULONG_PTR pulObjectCount) {
    520  if (readingProfile) {
    521    assert(hSession == 4);
    522    CK_ULONG count = ulMaxObjectCount;
    523    size_t remaining = sizeof(profiles) / sizeof(profiles[0]) - profileIndex;
    524    if (count > remaining) {
    525      count = remaining;
    526    }
    527    for (CK_ULONG i = 0; i < count; i++) {
    528      phObject[i] = i + 1;
    529    }
    530    profileIndex += count;
    531    *pulObjectCount = count;
    532  } else if (readingCert) {
    533    assert(hSession == 4);
    534    if (!certIdGiven) {
    535      CK_ULONG count = ulMaxObjectCount;
    536      size_t remaining = sizeof(certs) / sizeof(certs[0]) - certIndex;
    537      if (count > remaining) {
    538        count = remaining;
    539      }
    540      for (CK_ULONG i = 0; i < count; i++) {
    541        phObject[i] = i + 3;
    542      }
    543      *pulObjectCount = count;
    544      certIndex += count;
    545    } else if (certHandle != CK_INVALID_HANDLE) {
    546      if (certIndex == 0 && ulMaxObjectCount > 0) {
    547        phObject[0] = certHandle;
    548        *pulObjectCount = 1;
    549        certIndex = 1;
    550      } else {
    551        *pulObjectCount = 0;
    552      }
    553    } else {
    554      *pulObjectCount = 0;
    555    }
    556  } else {
    557    *pulObjectCount = 0;
    558  }
    559  return CKR_OK;
    560 }
    561 
    562 CK_RV Test_C_FindObjectsFinal(CK_SESSION_HANDLE hSession) {
    563  readingProfile = false;
    564  readingCert = false;
    565  certHandle = CK_INVALID_HANDLE;
    566  certIdGiven = false;
    567  return CKR_OK;
    568 }
    569 
    570 CK_RV Test_C_EncryptInit(CK_SESSION_HANDLE, CK_MECHANISM_PTR,
    571                         CK_OBJECT_HANDLE) {
    572  return CKR_FUNCTION_NOT_SUPPORTED;
    573 }
    574 
    575 CK_RV Test_C_Encrypt(CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG, CK_BYTE_PTR,
    576                     CK_ULONG_PTR) {
    577  return CKR_FUNCTION_NOT_SUPPORTED;
    578 }
    579 
    580 CK_RV Test_C_EncryptUpdate(CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG,
    581                           CK_BYTE_PTR, CK_ULONG_PTR) {
    582  return CKR_FUNCTION_NOT_SUPPORTED;
    583 }
    584 
    585 CK_RV Test_C_EncryptFinal(CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG_PTR) {
    586  return CKR_FUNCTION_NOT_SUPPORTED;
    587 }
    588 
    589 CK_RV Test_C_DecryptInit(CK_SESSION_HANDLE, CK_MECHANISM_PTR,
    590                         CK_OBJECT_HANDLE) {
    591  return CKR_FUNCTION_NOT_SUPPORTED;
    592 }
    593 
    594 CK_RV Test_C_Decrypt(CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG, CK_BYTE_PTR,
    595                     CK_ULONG_PTR) {
    596  return CKR_FUNCTION_NOT_SUPPORTED;
    597 }
    598 
    599 CK_RV Test_C_DecryptUpdate(CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG,
    600                           CK_BYTE_PTR, CK_ULONG_PTR) {
    601  return CKR_FUNCTION_NOT_SUPPORTED;
    602 }
    603 
    604 CK_RV Test_C_DecryptFinal(CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG_PTR) {
    605  return CKR_FUNCTION_NOT_SUPPORTED;
    606 }
    607 
    608 CK_RV Test_C_DigestInit(CK_SESSION_HANDLE, CK_MECHANISM_PTR) {
    609  return CKR_FUNCTION_NOT_SUPPORTED;
    610 }
    611 
    612 CK_RV Test_C_Digest(CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG, CK_BYTE_PTR,
    613                    CK_ULONG_PTR) {
    614  return CKR_FUNCTION_NOT_SUPPORTED;
    615 }
    616 
    617 CK_RV Test_C_DigestUpdate(CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG) {
    618  return CKR_FUNCTION_NOT_SUPPORTED;
    619 }
    620 
    621 CK_RV Test_C_DigestKey(CK_SESSION_HANDLE, CK_OBJECT_HANDLE) {
    622  return CKR_FUNCTION_NOT_SUPPORTED;
    623 }
    624 
    625 CK_RV Test_C_DigestFinal(CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG_PTR) {
    626  return CKR_FUNCTION_NOT_SUPPORTED;
    627 }
    628 
    629 CK_RV Test_C_SignInit(CK_SESSION_HANDLE, CK_MECHANISM_PTR, CK_OBJECT_HANDLE) {
    630  return CKR_FUNCTION_NOT_SUPPORTED;
    631 }
    632 
    633 CK_RV Test_C_Sign(CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG, CK_BYTE_PTR,
    634                  CK_ULONG_PTR) {
    635  return CKR_FUNCTION_NOT_SUPPORTED;
    636 }
    637 
    638 CK_RV Test_C_SignUpdate(CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG) {
    639  return CKR_FUNCTION_NOT_SUPPORTED;
    640 }
    641 
    642 CK_RV Test_C_SignFinal(CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG_PTR) {
    643  return CKR_FUNCTION_NOT_SUPPORTED;
    644 }
    645 
    646 CK_RV Test_C_SignRecoverInit(CK_SESSION_HANDLE, CK_MECHANISM_PTR,
    647                             CK_OBJECT_HANDLE) {
    648  return CKR_FUNCTION_NOT_SUPPORTED;
    649 }
    650 
    651 CK_RV Test_C_SignRecover(CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG, CK_BYTE_PTR,
    652                         CK_ULONG_PTR) {
    653  return CKR_FUNCTION_NOT_SUPPORTED;
    654 }
    655 
    656 CK_RV Test_C_VerifyInit(CK_SESSION_HANDLE, CK_MECHANISM_PTR, CK_OBJECT_HANDLE) {
    657  return CKR_FUNCTION_NOT_SUPPORTED;
    658 }
    659 
    660 CK_RV Test_C_Verify(CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG, CK_BYTE_PTR,
    661                    CK_ULONG) {
    662  return CKR_FUNCTION_NOT_SUPPORTED;
    663 }
    664 
    665 CK_RV Test_C_VerifyUpdate(CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG) {
    666  return CKR_FUNCTION_NOT_SUPPORTED;
    667 }
    668 
    669 CK_RV Test_C_VerifyFinal(CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG) {
    670  return CKR_FUNCTION_NOT_SUPPORTED;
    671 }
    672 
    673 CK_RV Test_C_VerifyRecoverInit(CK_SESSION_HANDLE, CK_MECHANISM_PTR,
    674                               CK_OBJECT_HANDLE) {
    675  return CKR_FUNCTION_NOT_SUPPORTED;
    676 }
    677 
    678 CK_RV Test_C_VerifyRecover(CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG,
    679                           CK_BYTE_PTR, CK_ULONG_PTR) {
    680  return CKR_FUNCTION_NOT_SUPPORTED;
    681 }
    682 
    683 CK_RV Test_C_DigestEncryptUpdate(CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG,
    684                                 CK_BYTE_PTR, CK_ULONG_PTR) {
    685  return CKR_FUNCTION_NOT_SUPPORTED;
    686 }
    687 
    688 CK_RV Test_C_DecryptDigestUpdate(CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG,
    689                                 CK_BYTE_PTR, CK_ULONG_PTR) {
    690  return CKR_FUNCTION_NOT_SUPPORTED;
    691 }
    692 
    693 CK_RV Test_C_SignEncryptUpdate(CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG,
    694                               CK_BYTE_PTR, CK_ULONG_PTR) {
    695  return CKR_FUNCTION_NOT_SUPPORTED;
    696 }
    697 
    698 CK_RV Test_C_DecryptVerifyUpdate(CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG,
    699                                 CK_BYTE_PTR, CK_ULONG_PTR) {
    700  return CKR_FUNCTION_NOT_SUPPORTED;
    701 }
    702 
    703 CK_RV Test_C_GenerateKey(CK_SESSION_HANDLE, CK_MECHANISM_PTR, CK_ATTRIBUTE_PTR,
    704                         CK_ULONG, CK_OBJECT_HANDLE_PTR) {
    705  return CKR_FUNCTION_NOT_SUPPORTED;
    706 }
    707 
    708 CK_RV Test_C_GenerateKeyPair(CK_SESSION_HANDLE, CK_MECHANISM_PTR,
    709                             CK_ATTRIBUTE_PTR, CK_ULONG, CK_ATTRIBUTE_PTR,
    710                             CK_ULONG, CK_OBJECT_HANDLE_PTR,
    711                             CK_OBJECT_HANDLE_PTR) {
    712  return CKR_FUNCTION_NOT_SUPPORTED;
    713 }
    714 
    715 CK_RV Test_C_WrapKey(CK_SESSION_HANDLE, CK_MECHANISM_PTR, CK_OBJECT_HANDLE,
    716                     CK_OBJECT_HANDLE, CK_BYTE_PTR, CK_ULONG_PTR) {
    717  return CKR_FUNCTION_NOT_SUPPORTED;
    718 }
    719 
    720 CK_RV Test_C_UnwrapKey(CK_SESSION_HANDLE, CK_MECHANISM_PTR, CK_OBJECT_HANDLE,
    721                       CK_BYTE_PTR, CK_ULONG, CK_ATTRIBUTE_PTR, CK_ULONG,
    722                       CK_OBJECT_HANDLE_PTR) {
    723  return CKR_FUNCTION_NOT_SUPPORTED;
    724 }
    725 
    726 CK_RV Test_C_DeriveKey(CK_SESSION_HANDLE, CK_MECHANISM_PTR, CK_OBJECT_HANDLE,
    727                       CK_ATTRIBUTE_PTR, CK_ULONG, CK_OBJECT_HANDLE_PTR) {
    728  return CKR_FUNCTION_NOT_SUPPORTED;
    729 }
    730 
    731 CK_RV Test_C_SeedRandom(CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG) {
    732  return CKR_FUNCTION_NOT_SUPPORTED;
    733 }
    734 
    735 CK_RV Test_C_GenerateRandom(CK_SESSION_HANDLE, CK_BYTE_PTR, CK_ULONG) {
    736  return CKR_FUNCTION_NOT_SUPPORTED;
    737 }
    738 
    739 CK_RV Test_C_GetFunctionStatus(CK_SESSION_HANDLE) {
    740  return CKR_FUNCTION_NOT_SUPPORTED;
    741 }
    742 
    743 CK_RV Test_C_CancelFunction(CK_SESSION_HANDLE) {
    744  return CKR_FUNCTION_NOT_SUPPORTED;
    745 }
    746 
    747 CK_RV Test_C_WaitForSlotEvent(CK_FLAGS, CK_SLOT_ID_PTR pSlot, CK_VOID_PTR) {
    748 #ifdef _WIN32
    749  Sleep(50);  // Sleep takes the duration argument as milliseconds
    750 #else
    751  usleep(50000);  // usleep takes the duration argument as microseconds
    752 #endif
    753  *pSlot = 1;
    754  tokenPresent = !tokenPresent;
    755  return CKR_OK;
    756 }
    757 
    758 static CK_FUNCTION_LIST FunctionList = {{2, 2},
    759                                        Test_C_Initialize,
    760                                        Test_C_Finalize,
    761                                        Test_C_GetInfo,
    762                                        Test_C_GetFunctionList,
    763                                        Test_C_GetSlotList,
    764                                        Test_C_GetSlotInfo,
    765                                        Test_C_GetTokenInfo,
    766                                        Test_C_GetMechanismList,
    767                                        Test_C_GetMechanismInfo,
    768                                        Test_C_InitToken,
    769                                        Test_C_InitPIN,
    770                                        Test_C_SetPIN,
    771                                        Test_C_OpenSession,
    772                                        Test_C_CloseSession,
    773                                        Test_C_CloseAllSessions,
    774                                        Test_C_GetSessionInfo,
    775                                        Test_C_GetOperationState,
    776                                        Test_C_SetOperationState,
    777                                        Test_C_Login,
    778                                        Test_C_Logout,
    779                                        Test_C_CreateObject,
    780                                        Test_C_CopyObject,
    781                                        Test_C_DestroyObject,
    782                                        Test_C_GetObjectSize,
    783                                        Test_C_GetAttributeValue,
    784                                        Test_C_SetAttributeValue,
    785                                        Test_C_FindObjectsInit,
    786                                        Test_C_FindObjects,
    787                                        Test_C_FindObjectsFinal,
    788                                        Test_C_EncryptInit,
    789                                        Test_C_Encrypt,
    790                                        Test_C_EncryptUpdate,
    791                                        Test_C_EncryptFinal,
    792                                        Test_C_DecryptInit,
    793                                        Test_C_Decrypt,
    794                                        Test_C_DecryptUpdate,
    795                                        Test_C_DecryptFinal,
    796                                        Test_C_DigestInit,
    797                                        Test_C_Digest,
    798                                        Test_C_DigestUpdate,
    799                                        Test_C_DigestKey,
    800                                        Test_C_DigestFinal,
    801                                        Test_C_SignInit,
    802                                        Test_C_Sign,
    803                                        Test_C_SignUpdate,
    804                                        Test_C_SignFinal,
    805                                        Test_C_SignRecoverInit,
    806                                        Test_C_SignRecover,
    807                                        Test_C_VerifyInit,
    808                                        Test_C_Verify,
    809                                        Test_C_VerifyUpdate,
    810                                        Test_C_VerifyFinal,
    811                                        Test_C_VerifyRecoverInit,
    812                                        Test_C_VerifyRecover,
    813                                        Test_C_DigestEncryptUpdate,
    814                                        Test_C_DecryptDigestUpdate,
    815                                        Test_C_SignEncryptUpdate,
    816                                        Test_C_DecryptVerifyUpdate,
    817                                        Test_C_GenerateKey,
    818                                        Test_C_GenerateKeyPair,
    819                                        Test_C_WrapKey,
    820                                        Test_C_UnwrapKey,
    821                                        Test_C_DeriveKey,
    822                                        Test_C_SeedRandom,
    823                                        Test_C_GenerateRandom,
    824                                        Test_C_GetFunctionStatus,
    825                                        Test_C_CancelFunction,
    826                                        Test_C_WaitForSlotEvent};
    827 
    828 #ifdef _WIN32
    829 __declspec(dllexport)
    830 #endif
    831 
    832 CK_RV C_GetFunctionList(CK_FUNCTION_LIST_PTR_PTR ppFunctionList) {
    833  *ppFunctionList = &FunctionList;
    834  return CKR_OK;
    835 }