tor-browser

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

pk11mode.c (189154B)


      1 /*
      2 * pk11mode.c - Test FIPS or NONFIPS Modes for the NSS PKCS11 api.
      3 *              The goal of this program is to test every function
      4 *              entry point of the PKCS11 api at least once.
      5 *              To test in FIPS mode: pk11mode
      6 *              To test in NONFIPS mode: pk11mode -n
      7 *              usage: pk11mode -h
      8 *
      9 * This Source Code Form is subject to the terms of the Mozilla Public
     10 * License, v. 2.0. If a copy of the MPL was not distributed with this
     11 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     12 
     13 #include <assert.h>
     14 #include <stdio.h>
     15 #include <stdlib.h>
     16 #include <string.h>
     17 #include <stdarg.h>
     18 
     19 #if defined(XP_UNIX) && defined(DO_FORK_CHECK)
     20 #include <unistd.h>
     21 #include <sys/wait.h>
     22 #else
     23 #ifndef NO_FORK_CHECK
     24 #define NO_FORK_CHECK
     25 #endif
     26 #endif
     27 
     28 #ifdef _WIN32
     29 #include <windows.h>
     30 #define LIB_NAME "softokn3.dll"
     31 #endif
     32 #include "prlink.h"
     33 #include "prprf.h"
     34 #include "plgetopt.h"
     35 #include "prenv.h"
     36 
     37 #include "pk11table.h"
     38 
     39 #define NUM_ELEM(array) (sizeof(array) / sizeof(array[0]))
     40 
     41 #ifndef NULL_PTR
     42 #define NULL_PTR 0
     43 #endif
     44 
     45 /* Returns constant error string for "CRV".
     46 * Returns "unknown error" if errNum is unknown.
     47 */
     48 const char *
     49 PKM_CK_RVtoStr(CK_RV errNum)
     50 {
     51    const char *err;
     52 
     53    err = getName(errNum, ConstResult);
     54 
     55    if (err)
     56        return err;
     57 
     58    return "unknown error";
     59 }
     60 
     61 #include "pkcs11p.h"
     62 
     63 typedef struct CK_C_INITIALIZE_ARGS_NSS {
     64    CK_CREATEMUTEX CreateMutex;
     65    CK_DESTROYMUTEX DestroyMutex;
     66    CK_LOCKMUTEX LockMutex;
     67    CK_UNLOCKMUTEX UnlockMutex;
     68    CK_FLAGS flags;
     69    /* The official PKCS #11 spec does not have a 'LibraryParameters' field, but
     70     * a reserved field. NSS needs a way to pass instance-specific information
     71     * to the library (like where to find its config files, etc). This
     72     * information is usually provided by the installer and passed uninterpreted
     73     * by NSS to the library, though NSS does know the specifics of the softoken
     74     * version of this parameter. Most compliant PKCS#11 modules expect this
     75     * parameter to be NULL, and will return CKR_ARGUMENTS_BAD from
     76     * C_Initialize if Library parameters is supplied. */
     77    CK_CHAR_PTR *LibraryParameters;
     78    /* This field is only present if the LibraryParameters is not NULL. It must
     79     * be NULL in all cases */
     80    CK_VOID_PTR pReserved;
     81 } CK_C_INITIALIZE_ARGS_NSS;
     82 
     83 #include "pkcs11u.h"
     84 
     85 #define MAX_SIG_SZ 128
     86 #define MAX_CIPHER_SZ 128
     87 #define MAX_DATA_SZ 64
     88 #define MAX_DIGEST_SZ 64
     89 #define HMAC_MAX_LENGTH 64
     90 #define FIPSMODE 0
     91 #define NONFIPSMODE 1
     92 #define HYBRIDMODE 2
     93 #define NOMODE 3
     94 int MODE = FIPSMODE;
     95 
     96 CK_BBOOL ck_true = CK_TRUE;
     97 CK_BBOOL ck_false = CK_FALSE;
     98 static const CK_BYTE PLAINTEXT[] = { "Firefox  Rules!" };
     99 static const CK_BYTE PLAINTEXT_PAD[] = { "Firefox and thunderbird rule the world!" };
    100 CK_ULONG NUMTESTS = 0;
    101 
    102 static const char *slotFlagName[] = {
    103    "CKF_TOKEN_PRESENT",
    104    "CKF_REMOVABLE_DEVICE",
    105    "CKF_HW_SLOT",
    106    "unknown token flag 0x00000008",
    107    "unknown token flag 0x00000010",
    108    "unknown token flag 0x00000020",
    109    "unknown token flag 0x00000040",
    110    "unknown token flag 0x00000080",
    111    "unknown token flag 0x00000100",
    112    "unknown token flag 0x00000200",
    113    "unknown token flag 0x00000400",
    114    "unknown token flag 0x00000800",
    115    "unknown token flag 0x00001000",
    116    "unknown token flag 0x00002000",
    117    "unknown token flag 0x00004000",
    118    "unknown token flag 0x00008000"
    119    "unknown token flag 0x00010000",
    120    "unknown token flag 0x00020000",
    121    "unknown token flag 0x00040000",
    122    "unknown token flag 0x00080000",
    123    "unknown token flag 0x00100000",
    124    "unknown token flag 0x00200000",
    125    "unknown token flag 0x00400000",
    126    "unknown token flag 0x00800000"
    127    "unknown token flag 0x01000000",
    128    "unknown token flag 0x02000000",
    129    "unknown token flag 0x04000000",
    130    "unknown token flag 0x08000000",
    131    "unknown token flag 0x10000000",
    132    "unknown token flag 0x20000000",
    133    "unknown token flag 0x40000000",
    134    "unknown token flag 0x80000000"
    135 };
    136 
    137 static const char *tokenFlagName[] = {
    138    "CKF_PKM_RNG",
    139    "CKF_WRITE_PROTECTED",
    140    "CKF_LOGIN_REQUIRED",
    141    "CKF_USER_PIN_INITIALIZED",
    142    "unknown token flag 0x00000010",
    143    "CKF_RESTORE_KEY_NOT_NEEDED",
    144    "CKF_CLOCK_ON_TOKEN",
    145    "unknown token flag 0x00000080",
    146    "CKF_PROTECTED_AUTHENTICATION_PATH",
    147    "CKF_DUAL_CRYPTO_OPERATIONS",
    148    "CKF_TOKEN_INITIALIZED",
    149    "CKF_SECONDARY_AUTHENTICATION",
    150    "unknown token flag 0x00001000",
    151    "unknown token flag 0x00002000",
    152    "unknown token flag 0x00004000",
    153    "unknown token flag 0x00008000",
    154    "CKF_USER_PIN_COUNT_LOW",
    155    "CKF_USER_PIN_FINAL_TRY",
    156    "CKF_USER_PIN_LOCKED",
    157    "CKF_USER_PIN_TO_BE_CHANGED",
    158    "CKF_SO_PIN_COUNT_LOW",
    159    "CKF_SO_PIN_FINAL_TRY",
    160    "CKF_SO_PIN_LOCKED",
    161    "CKF_SO_PIN_TO_BE_CHANGED",
    162    "unknown token flag 0x01000000",
    163    "unknown token flag 0x02000000",
    164    "unknown token flag 0x04000000",
    165    "unknown token flag 0x08000000",
    166    "unknown token flag 0x10000000",
    167    "unknown token flag 0x20000000",
    168    "unknown token flag 0x40000000",
    169    "unknown token flag 0x80000000"
    170 };
    171 
    172 static const unsigned char TLSClientRandom[] = {
    173    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    174    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    175    0x0d, 0x90, 0xbb, 0x5e, 0xc6, 0xe1, 0x3f, 0x71,
    176    0x0a, 0xa2, 0x70, 0x5a, 0x4f, 0xbc, 0x3f, 0x0d
    177 };
    178 static const unsigned char TLSServerRandom[] = {
    179    0x00, 0x00, 0x1d, 0x4a, 0x7a, 0x0a, 0xa5, 0x01,
    180    0x8e, 0x79, 0x72, 0xde, 0x9e, 0x2f, 0x8a, 0x0d,
    181    0xed, 0xb2, 0x5d, 0xf1, 0x14, 0xc2, 0xc6, 0x66,
    182    0x95, 0x86, 0xb0, 0x0d, 0x87, 0x2a, 0x2a, 0xc9
    183 };
    184 
    185 typedef enum {
    186    CORRECT,
    187    BOGUS_CLIENT_RANDOM,
    188    BOGUS_CLIENT_RANDOM_LEN,
    189    BOGUS_SERVER_RANDOM,
    190    BOGUS_SERVER_RANDOM_LEN
    191 } enum_random_t;
    192 
    193 void
    194 dumpToHash64(const unsigned char *buf, unsigned int bufLen)
    195 {
    196    unsigned int i;
    197    for (i = 0; i < bufLen; i += 8) {
    198        if (i % 32 == 0)
    199            printf("\n");
    200        printf(" 0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,",
    201               buf[i], buf[i + 1], buf[i + 2], buf[i + 3],
    202               buf[i + 4], buf[i + 5], buf[i + 6], buf[i + 7]);
    203    }
    204    printf("\n");
    205 }
    206 
    207 #ifdef _WIN32
    208 HMODULE hModule;
    209 #else
    210 PRLibrary *lib;
    211 #endif
    212 
    213 /*
    214 * All api that belongs to pk11mode.c layer start with the prefix PKM_
    215 */
    216 void PKM_LogIt(const char *fmt, ...);
    217 void PKM_Error(const char *fmt, ...);
    218 CK_SLOT_ID *PKM_GetSlotList(CK_FUNCTION_LIST_PTR pFunctionList,
    219                            CK_ULONG slotID);
    220 CK_RV PKM_ShowInfo(CK_FUNCTION_LIST_PTR pFunctionList, CK_ULONG slotID);
    221 CK_RV PKM_InitPWforDB(CK_FUNCTION_LIST_PTR pFunctionList,
    222                      CK_SLOT_ID *pSlotList, CK_ULONG slotID,
    223                      CK_UTF8CHAR_PTR pwd, CK_ULONG pwdLen);
    224 CK_RV PKM_Mechanism(CK_FUNCTION_LIST_PTR pFunctionList,
    225                    CK_SLOT_ID *pSlotList, CK_ULONG slotID);
    226 CK_RV PKM_RNG(CK_FUNCTION_LIST_PTR pFunctionList, CK_SLOT_ID *pSlotList,
    227              CK_ULONG slotID);
    228 CK_RV PKM_SessionLogin(CK_FUNCTION_LIST_PTR pFunctionList,
    229                       CK_SLOT_ID *pSlotList, CK_ULONG slotID,
    230                       CK_UTF8CHAR_PTR pwd, CK_ULONG pwdLen);
    231 CK_RV PKM_SecretKey(CK_FUNCTION_LIST_PTR pFunctionList, CK_SLOT_ID *pSlotList,
    232                    CK_ULONG slotID, CK_UTF8CHAR_PTR pwd, CK_ULONG pwdLen);
    233 CK_RV PKM_PublicKey(CK_FUNCTION_LIST_PTR pFunctionList, CK_SLOT_ID *pSlotList,
    234                    CK_ULONG slotID, CK_UTF8CHAR_PTR pwd, CK_ULONG pwdLen);
    235 CK_RV PKM_HybridMode(CK_UTF8CHAR_PTR pwd, CK_ULONG pwdLen,
    236                     CK_C_INITIALIZE_ARGS_NSS *initArgs);
    237 CK_RV PKM_FindAllObjects(CK_FUNCTION_LIST_PTR pFunctionList,
    238                         CK_SLOT_ID *pSlotList, CK_ULONG slotID,
    239                         CK_UTF8CHAR_PTR pwd, CK_ULONG pwdLen);
    240 CK_RV PKM_MultiObjectManagement(CK_FUNCTION_LIST_PTR pFunctionList,
    241                                CK_SLOT_ID *pSlotList, CK_ULONG slotID,
    242                                CK_UTF8CHAR_PTR pwd, CK_ULONG pwdLen);
    243 CK_RV PKM_OperationalState(CK_FUNCTION_LIST_PTR pFunctionList,
    244                           CK_SLOT_ID *pSlotList, CK_ULONG slotID,
    245                           CK_UTF8CHAR_PTR pwd, CK_ULONG pwdLen);
    246 CK_RV PKM_LegacyFunctions(CK_FUNCTION_LIST_PTR pFunctionList,
    247                          CK_SLOT_ID *pSlotList, CK_ULONG slotID,
    248                          CK_UTF8CHAR_PTR pwd, CK_ULONG pwdLen);
    249 CK_RV PKM_AttributeCheck(CK_FUNCTION_LIST_PTR pFunctionList,
    250                         CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE obj,
    251                         CK_ATTRIBUTE_PTR expected_attrs,
    252                         CK_ULONG expected_attrs_count);
    253 CK_RV PKM_MechCheck(CK_FUNCTION_LIST_PTR pFunctionList,
    254                    CK_SESSION_HANDLE hSession, CK_MECHANISM_TYPE mechType,
    255                    CK_FLAGS flags, CK_BBOOL check_sizes,
    256                    CK_ULONG minkeysize, CK_ULONG maxkeysize);
    257 CK_RV PKM_TLSKeyAndMacDerive(CK_FUNCTION_LIST_PTR pFunctionList,
    258                             CK_SLOT_ID *pSlotList, CK_ULONG slotID,
    259                             CK_UTF8CHAR_PTR pwd, CK_ULONG pwdLen,
    260                             CK_MECHANISM_TYPE mechType, enum_random_t rnd);
    261 CK_RV PKM_TLSMasterKeyDerive(CK_FUNCTION_LIST_PTR pFunctionList,
    262                             CK_SLOT_ID *pSlotList, CK_ULONG slotID,
    263                             CK_UTF8CHAR_PTR pwd, CK_ULONG pwdLen,
    264                             CK_MECHANISM_TYPE mechType,
    265                             enum_random_t rnd);
    266 CK_RV PKM_KeyTests(CK_FUNCTION_LIST_PTR pFunctionList,
    267                   CK_SLOT_ID *pSlotList, CK_ULONG slotID,
    268                   CK_UTF8CHAR_PTR pwd, CK_ULONG pwdLen);
    269 CK_RV PKM_DualFuncSign(CK_FUNCTION_LIST_PTR pFunctionList,
    270                       CK_SESSION_HANDLE hRwSession,
    271                       CK_OBJECT_HANDLE publicKey, CK_OBJECT_HANDLE privateKey,
    272                       CK_MECHANISM *sigMech, CK_OBJECT_HANDLE secretKey,
    273                       CK_MECHANISM *cryptMech,
    274                       const CK_BYTE *pData, CK_ULONG pDataLen);
    275 CK_RV PKM_DualFuncDigest(CK_FUNCTION_LIST_PTR pFunctionList,
    276                         CK_SESSION_HANDLE hSession,
    277                         CK_OBJECT_HANDLE hSecKey, CK_MECHANISM *cryptMech,
    278                         CK_OBJECT_HANDLE hSecKeyDigest,
    279                         CK_MECHANISM *digestMech,
    280                         const CK_BYTE *pData, CK_ULONG pDataLen);
    281 CK_RV PKM_PubKeySign(CK_FUNCTION_LIST_PTR pFunctionList,
    282                     CK_SESSION_HANDLE hRwSession,
    283                     CK_OBJECT_HANDLE hPubKey, CK_OBJECT_HANDLE hPrivKey,
    284                     CK_MECHANISM *signMech, const CK_BYTE *pData,
    285                     CK_ULONG dataLen);
    286 CK_RV PKM_SecKeyCrypt(CK_FUNCTION_LIST_PTR pFunctionList,
    287                      CK_SESSION_HANDLE hSession,
    288                      CK_OBJECT_HANDLE hSymKey, CK_MECHANISM *cryptMech,
    289                      const CK_BYTE *pData, CK_ULONG dataLen);
    290 CK_RV PKM_Hmac(CK_FUNCTION_LIST_PTR pFunctionList, CK_SESSION_HANDLE hSession,
    291               CK_OBJECT_HANDLE sKey, CK_MECHANISM *hmacMech,
    292               const CK_BYTE *pData, CK_ULONG pDataLen);
    293 CK_RV PKM_Digest(CK_FUNCTION_LIST_PTR pFunctionList,
    294                 CK_SESSION_HANDLE hRwSession,
    295                 CK_MECHANISM *digestMech, CK_OBJECT_HANDLE hSecretKey,
    296                 const CK_BYTE *pData, CK_ULONG pDataLen);
    297 CK_RV PKM_wrapUnwrap(CK_FUNCTION_LIST_PTR pFunctionList,
    298                     CK_SESSION_HANDLE hSession,
    299                     CK_OBJECT_HANDLE hPublicKey,
    300                     CK_OBJECT_HANDLE hPrivateKey,
    301                     CK_MECHANISM *wrapMechanism,
    302                     CK_OBJECT_HANDLE hSecretKey,
    303                     CK_ATTRIBUTE *sKeyTemplate,
    304                     CK_ULONG skeyTempSize);
    305 CK_RV PKM_RecoverFunctions(CK_FUNCTION_LIST_PTR pFunctionList,
    306                           CK_SESSION_HANDLE hSession,
    307                           CK_OBJECT_HANDLE hPubKey, CK_OBJECT_HANDLE hPrivKey,
    308                           CK_MECHANISM *signMech, const CK_BYTE *pData,
    309                           CK_ULONG pDataLen);
    310 CK_RV PKM_ForkCheck(int expected, CK_FUNCTION_LIST_PTR fList,
    311                    PRBool forkAssert, CK_C_INITIALIZE_ARGS_NSS *initArgs);
    312 
    313 void PKM_Help();
    314 void PKM_CheckPath(char *string);
    315 char *PKM_FilePasswd(char *pwFile);
    316 static PRBool verbose = PR_FALSE;
    317 
    318 int
    319 main(int argc, char **argv)
    320 {
    321    CK_C_GetFunctionList pC_GetFunctionList;
    322    CK_FUNCTION_LIST_PTR pFunctionList;
    323    CK_RV crv = CKR_OK;
    324    CK_C_INITIALIZE_ARGS_NSS initArgs;
    325    CK_C_INITIALIZE_ARGS_NSS initArgsRerun; /* rerun selftests */
    326    CK_SLOT_ID *pSlotList = NULL;
    327    CK_TOKEN_INFO tokenInfo;
    328    CK_ULONG slotID = 0; /* slotID == 0 for FIPSMODE */
    329 
    330    CK_UTF8CHAR *pwd = NULL;
    331    CK_ULONG pwdLen = 0;
    332    char *moduleSpec = NULL;
    333    char *moduleSpecRerun = NULL;
    334    char *configDir = NULL;
    335    char *dbPrefix = NULL;
    336    char *disableUnload = NULL;
    337    PRBool doForkTests = PR_TRUE;
    338 
    339    PLOptStatus os;
    340    PLOptState *opt = PL_CreateOptState(argc, argv, "nvhf:Fd:p:");
    341    while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) {
    342        if (PL_OPT_BAD == os)
    343            continue;
    344        switch (opt->option) {
    345            case 'F': /* disable fork tests */
    346                doForkTests = PR_FALSE;
    347                break;
    348            case 'n': /* non fips mode */
    349                MODE = NONFIPSMODE;
    350                slotID = 1;
    351                break;
    352            case 'f': /* password file */
    353                pwd = (CK_UTF8CHAR *)PKM_FilePasswd((char *)opt->value);
    354                if (!pwd)
    355                    PKM_Help();
    356                break;
    357            case 'd': /* opt_CertDir */
    358                if (!opt->value)
    359                    PKM_Help();
    360                configDir = strdup(opt->value);
    361                PKM_CheckPath(configDir);
    362                break;
    363            case 'p': /* opt_DBPrefix */
    364                if (!opt->value)
    365                    PKM_Help();
    366                dbPrefix = strdup(opt->value);
    367                break;
    368            case 'v':
    369                verbose = PR_TRUE;
    370                break;
    371            case 'h': /* help message */
    372            default:
    373                PKM_Help();
    374                break;
    375        }
    376    }
    377    PL_DestroyOptState(opt);
    378 
    379    if (!pwd) {
    380        pwd = (CK_UTF8CHAR *)strdup("1Mozilla");
    381    }
    382    pwdLen = strlen((const char *)pwd);
    383    if (!configDir) {
    384        configDir = strdup(".");
    385    }
    386    if (!dbPrefix) {
    387        dbPrefix = strdup("");
    388    }
    389 
    390    if (doForkTests) {
    391        /* first, try to fork without softoken loaded to make sure
    392         * everything is OK */
    393        crv = PKM_ForkCheck(123, NULL, PR_FALSE, NULL);
    394        if (crv != CKR_OK)
    395            goto cleanup;
    396    }
    397 
    398 #ifdef _WIN32
    399    hModule = LoadLibrary(LIB_NAME);
    400    if (hModule == NULL) {
    401        PKM_Error("cannot load %s\n", LIB_NAME);
    402        goto cleanup;
    403    }
    404    if (MODE == FIPSMODE) {
    405        /* FIPS mode == FC_GetFunctionList */
    406        pC_GetFunctionList = (CK_C_GetFunctionList)
    407            GetProcAddress(hModule, "FC_GetFunctionList");
    408    } else {
    409        /* NON FIPS mode  == C_GetFunctionList */
    410        pC_GetFunctionList = (CK_C_GetFunctionList)
    411            GetProcAddress(hModule, "C_GetFunctionList");
    412    }
    413    if (pC_GetFunctionList == NULL) {
    414        PKM_Error("cannot load %s\n", LIB_NAME);
    415        goto cleanup;
    416    }
    417 #else
    418    {
    419        char *libname = NULL;
    420        /* Get the platform-dependent library name of the NSS cryptographic module */
    421        libname = PR_GetLibraryName(NULL, "softokn3");
    422        assert(libname != NULL);
    423        lib = PR_LoadLibrary(libname);
    424        assert(lib != NULL);
    425        PR_FreeLibraryName(libname);
    426    }
    427    if (MODE == FIPSMODE) {
    428        pC_GetFunctionList = (CK_C_GetFunctionList)PR_FindFunctionSymbol(lib,
    429                                                                         "FC_GetFunctionList");
    430        assert(pC_GetFunctionList != NULL);
    431        slotID = 0;
    432    } else {
    433        pC_GetFunctionList = (CK_C_GetFunctionList)PR_FindFunctionSymbol(lib,
    434                                                                         "C_GetFunctionList");
    435        assert(pC_GetFunctionList != NULL);
    436        slotID = 1;
    437    }
    438 #endif
    439 
    440    if (MODE == FIPSMODE) {
    441        printf("Loaded FC_GetFunctionList for FIPS MODE; slotID %d \n",
    442               (int)slotID);
    443    } else {
    444        printf("loaded C_GetFunctionList for NON FIPS MODE; slotID %d \n",
    445               (int)slotID);
    446    }
    447 
    448    crv = (*pC_GetFunctionList)(&pFunctionList);
    449    assert(crv == CKR_OK);
    450 
    451    if (doForkTests) {
    452        /* now, try to fork with softoken loaded, but not initialized */
    453        crv = PKM_ForkCheck(CKR_CRYPTOKI_NOT_INITIALIZED, pFunctionList,
    454                            PR_TRUE, NULL);
    455        if (crv != CKR_OK)
    456            goto cleanup;
    457    }
    458 
    459    initArgs.CreateMutex = NULL;
    460    initArgs.DestroyMutex = NULL;
    461    initArgs.LockMutex = NULL;
    462    initArgs.UnlockMutex = NULL;
    463    initArgs.flags = CKF_OS_LOCKING_OK;
    464    moduleSpec = PR_smprintf("configdir='%s' certPrefix='%s' "
    465                             "keyPrefix='%s' secmod='secmod.db' flags= ",
    466                             configDir, dbPrefix, dbPrefix);
    467    moduleSpecRerun = PR_smprintf("configdir='%s' certPrefix='%s' "
    468                                  "keyPrefix='%s' secmod='secmod.db' flags=forcePOST ",
    469                                  configDir, dbPrefix, dbPrefix);
    470    initArgs.LibraryParameters = (CK_CHAR_PTR *)moduleSpec;
    471    initArgs.pReserved = NULL;
    472    initArgsRerun = initArgs;
    473    initArgsRerun.LibraryParameters = (CK_CHAR_PTR *)moduleSpecRerun;
    474 
    475    /*DebugBreak();*/
    476    /* FIPSMODE invokes FC_Initialize as pFunctionList->C_Initialize */
    477    /* NSS cryptographic module library initialization for the FIPS  */
    478    /* Approved mode when FC_Initialize is envoked will perfom       */
    479    /* software integrity test, and power-up self-tests before       */
    480    /* FC_Initialize returns                                         */
    481    crv = pFunctionList->C_Initialize(&initArgs);
    482    if (crv == CKR_OK) {
    483        PKM_LogIt("C_Initialize succeeded\n");
    484    } else {
    485        PKM_Error("C_Initialize failed with 0x%08X, %-26s\n", crv,
    486                  PKM_CK_RVtoStr(crv));
    487        goto cleanup;
    488    }
    489 
    490    if (doForkTests) {
    491        /* Disable core on fork for this test, since we are testing the
    492         * pathological case, and if enabled, the child process would dump
    493         * core in C_GetTokenInfo .
    494         * We can still differentiate the correct from incorrect behavior
    495         * by the PKCS#11 return code.
    496         */
    497        /* try to fork with softoken both loaded and initialized */
    498        crv = PKM_ForkCheck(CKR_DEVICE_ERROR, pFunctionList, PR_FALSE, NULL);
    499        if (crv != CKR_OK)
    500            goto cleanup;
    501    }
    502 
    503    if (doForkTests) {
    504        /* In this next test, we fork and try to re-initialize softoken in
    505         * the child. This should now work because softoken has the ability
    506         * to hard reset.
    507         */
    508        /* try to fork with softoken both loaded and initialized */
    509        crv = PKM_ForkCheck(CKR_OK, pFunctionList, PR_TRUE, &initArgs);
    510        if (crv != CKR_OK)
    511            goto cleanup;
    512    }
    513 
    514    crv = PKM_ShowInfo(pFunctionList, slotID);
    515    if (crv == CKR_OK) {
    516        PKM_LogIt("PKM_ShowInfo succeeded\n");
    517    } else {
    518        PKM_Error("PKM_ShowInfo failed with 0x%08X, %-26s\n", crv,
    519                  PKM_CK_RVtoStr(crv));
    520        goto cleanup;
    521    }
    522    pSlotList = PKM_GetSlotList(pFunctionList, slotID);
    523    if (pSlotList == NULL) {
    524        PKM_Error("PKM_GetSlotList failed with \n");
    525        goto cleanup;
    526    }
    527    crv = pFunctionList->C_GetTokenInfo(pSlotList[slotID], &tokenInfo);
    528    if (crv == CKR_OK) {
    529        PKM_LogIt("C_GetTokenInfo succeeded\n\n");
    530    } else {
    531        PKM_Error("C_GetTokenInfo failed with 0x%08X, %-26s\n", crv,
    532                  PKM_CK_RVtoStr(crv));
    533        goto cleanup;
    534    }
    535 
    536    if (!(tokenInfo.flags & CKF_USER_PIN_INITIALIZED)) {
    537        PKM_LogIt("Initing PW for DB\n");
    538        crv = PKM_InitPWforDB(pFunctionList, pSlotList, slotID,
    539                              pwd, pwdLen);
    540        if (crv == CKR_OK) {
    541            PKM_LogIt("PKM_InitPWforDB succeeded\n\n");
    542        } else {
    543            PKM_Error("PKM_InitPWforDB failed with 0x%08X, %-26s\n", crv,
    544                      PKM_CK_RVtoStr(crv));
    545            goto cleanup;
    546        }
    547    } else {
    548        PKM_LogIt("using existing DB\n");
    549    }
    550 
    551    /* general mechanism by token */
    552    crv = PKM_Mechanism(pFunctionList, pSlotList, slotID);
    553    if (crv == CKR_OK) {
    554        PKM_LogIt("PKM_Mechanism succeeded\n\n");
    555    } else {
    556        PKM_Error("PKM_Mechanism failed with 0x%08X, %-26s\n", crv,
    557                  PKM_CK_RVtoStr(crv));
    558        goto cleanup;
    559    }
    560    /* RNG example without Login */
    561    crv = PKM_RNG(pFunctionList, pSlotList, slotID);
    562    if (crv == CKR_OK) {
    563        PKM_LogIt("PKM_RNG succeeded\n\n");
    564    } else {
    565        PKM_Error("PKM_RNG failed with 0x%08X, %-26s\n", crv,
    566                  PKM_CK_RVtoStr(crv));
    567        goto cleanup;
    568    }
    569 
    570    crv = PKM_SessionLogin(pFunctionList, pSlotList, slotID,
    571                           pwd, pwdLen);
    572    if (crv == CKR_OK) {
    573        PKM_LogIt("PKM_SessionLogin succeeded\n\n");
    574    } else {
    575        PKM_Error("PKM_SessionLogin failed with 0x%08X, %-26s\n", crv,
    576                  PKM_CK_RVtoStr(crv));
    577        goto cleanup;
    578    }
    579 
    580    /*
    581     * PKM_KeyTest creates RSA,ECDSA public keys
    582     * and AES, DES3 secret keys.
    583     * then does digest, hmac, encrypt/decrypt, signing operations.
    584     */
    585    crv = PKM_KeyTests(pFunctionList, pSlotList, slotID,
    586                       pwd, pwdLen);
    587    if (crv == CKR_OK) {
    588        PKM_LogIt("PKM_KeyTests succeeded\n\n");
    589    } else {
    590        PKM_Error("PKM_KeyTest failed with 0x%08X, %-26s\n", crv,
    591                  PKM_CK_RVtoStr(crv));
    592        goto cleanup;
    593    }
    594 
    595    crv = PKM_SecretKey(pFunctionList, pSlotList, slotID, pwd,
    596                        pwdLen);
    597    if (crv == CKR_OK) {
    598        PKM_LogIt("PKM_SecretKey succeeded\n\n");
    599    } else {
    600        PKM_Error("PKM_SecretKey failed with 0x%08X, %-26s\n", crv,
    601                  PKM_CK_RVtoStr(crv));
    602        goto cleanup;
    603    }
    604 
    605    crv = PKM_PublicKey(pFunctionList, pSlotList, slotID,
    606                        pwd, pwdLen);
    607    if (crv == CKR_OK) {
    608        PKM_LogIt("PKM_PublicKey succeeded\n\n");
    609    } else {
    610        PKM_Error("PKM_PublicKey failed with 0x%08X, %-26s\n", crv,
    611                  PKM_CK_RVtoStr(crv));
    612        goto cleanup;
    613    }
    614    crv = PKM_OperationalState(pFunctionList, pSlotList, slotID,
    615                               pwd, pwdLen);
    616    if (crv == CKR_OK) {
    617        PKM_LogIt("PKM_OperationalState succeeded\n\n");
    618    } else {
    619        PKM_Error("PKM_OperationalState failed with 0x%08X, %-26s\n", crv,
    620                  PKM_CK_RVtoStr(crv));
    621        goto cleanup;
    622    }
    623    crv = PKM_MultiObjectManagement(pFunctionList, pSlotList, slotID,
    624                                    pwd, pwdLen);
    625    if (crv == CKR_OK) {
    626        PKM_LogIt("PKM_MultiObjectManagement succeeded\n\n");
    627    } else {
    628        PKM_Error("PKM_MultiObjectManagement failed with 0x%08X, %-26s\n", crv,
    629                  PKM_CK_RVtoStr(crv));
    630        goto cleanup;
    631    }
    632    crv = PKM_LegacyFunctions(pFunctionList, pSlotList, slotID,
    633                              pwd, pwdLen);
    634    if (crv == CKR_OK) {
    635        PKM_LogIt("PKM_LegacyFunctions succeeded\n\n");
    636    } else {
    637        PKM_Error("PKM_LegacyFunctions failed with 0x%08X, %-26s\n", crv,
    638                  PKM_CK_RVtoStr(crv));
    639        goto cleanup;
    640    }
    641    crv = PKM_TLSKeyAndMacDerive(pFunctionList, pSlotList, slotID,
    642                                 pwd, pwdLen,
    643                                 CKM_TLS_KEY_AND_MAC_DERIVE, CORRECT);
    644 
    645    if (crv == CKR_OK) {
    646        PKM_LogIt("PKM_TLSKeyAndMacDerive succeeded\n\n");
    647    } else {
    648        PKM_Error("PKM_TLSKeyAndMacDerive failed with 0x%08X, %-26s\n", crv,
    649                  PKM_CK_RVtoStr(crv));
    650        goto cleanup;
    651    }
    652    crv = PKM_TLSMasterKeyDerive(pFunctionList, pSlotList, slotID,
    653                                 pwd, pwdLen,
    654                                 CKM_TLS_MASTER_KEY_DERIVE,
    655                                 CORRECT);
    656    if (crv == CKR_OK) {
    657        PKM_LogIt("PKM_TLSMasterKeyDerive succeeded\n\n");
    658    } else {
    659        PKM_Error("PKM_TLSMasterKeyDerive failed with 0x%08X, %-26s\n", crv,
    660                  PKM_CK_RVtoStr(crv));
    661        goto cleanup;
    662    }
    663    crv = PKM_TLSMasterKeyDerive(pFunctionList, pSlotList, slotID,
    664                                 pwd, pwdLen,
    665                                 CKM_TLS_MASTER_KEY_DERIVE_DH,
    666                                 CORRECT);
    667    if (crv == CKR_OK) {
    668        PKM_LogIt("PKM_TLSMasterKeyDerive succeeded\n\n");
    669    } else {
    670        PKM_Error("PKM_TLSMasterKeyDerive failed with 0x%08X, %-26s\n", crv,
    671                  PKM_CK_RVtoStr(crv));
    672        goto cleanup;
    673    }
    674    crv = PKM_FindAllObjects(pFunctionList, pSlotList, slotID,
    675                             pwd, pwdLen);
    676    if (crv == CKR_OK) {
    677        PKM_LogIt("PKM_FindAllObjects succeeded\n\n");
    678    } else {
    679        PKM_Error("PKM_FindAllObjects failed with 0x%08X, %-26s\n", crv,
    680                  PKM_CK_RVtoStr(crv));
    681        goto cleanup;
    682    }
    683    crv = pFunctionList->C_Finalize(NULL);
    684    if (crv == CKR_OK) {
    685        PKM_LogIt("C_Finalize succeeded\n");
    686    } else {
    687        PKM_Error("C_Finalize failed with 0x%08X, %-26s\n", crv,
    688                  PKM_CK_RVtoStr(crv));
    689        goto cleanup;
    690    }
    691 
    692    if (doForkTests) {
    693        /* try to fork with softoken still loaded, but de-initialized */
    694        crv = PKM_ForkCheck(CKR_CRYPTOKI_NOT_INITIALIZED, pFunctionList,
    695                            PR_TRUE, NULL);
    696        if (crv != CKR_OK)
    697            goto cleanup;
    698    }
    699 
    700    free(pSlotList);
    701 
    702    /* demonstrate how an application can be in Hybrid mode */
    703    /* PKM_HybridMode shows how to switch between NONFIPS */
    704    /* mode to FIPS mode */
    705 
    706    PKM_LogIt("Testing Hybrid mode \n");
    707    crv = PKM_HybridMode(pwd, pwdLen, &initArgs);
    708    if (crv == CKR_OK) {
    709        PKM_LogIt("PKM_HybridMode succeeded\n");
    710    } else {
    711        PKM_Error("PKM_HybridMode failed with 0x%08X, %-26s\n", crv,
    712                  PKM_CK_RVtoStr(crv));
    713        goto cleanup;
    714    }
    715 
    716    if (doForkTests) {
    717        /* testing one more C_Initialize / C_Finalize to exercise getpid()
    718         * fork check code */
    719        crv = pFunctionList->C_Initialize(&initArgsRerun);
    720        if (crv == CKR_OK) {
    721            PKM_LogIt("C_Initialize succeeded\n");
    722        } else {
    723            PKM_Error("C_Initialize failed with 0x%08X, %-26s\n", crv,
    724                      PKM_CK_RVtoStr(crv));
    725            goto cleanup;
    726        }
    727        crv = pFunctionList->C_Finalize(NULL);
    728        if (crv == CKR_OK) {
    729            PKM_LogIt("C_Finalize succeeded\n");
    730        } else {
    731            PKM_Error("C_Finalize failed with 0x%08X, %-26s\n", crv,
    732                      PKM_CK_RVtoStr(crv));
    733            goto cleanup;
    734        }
    735        /* try to C_Initialize / C_Finalize in child. This should succeed */
    736        crv = PKM_ForkCheck(CKR_OK, pFunctionList, PR_TRUE, &initArgs);
    737    }
    738 
    739    PKM_LogIt("unloading NSS PKCS # 11 softoken and exiting\n");
    740 
    741 cleanup:
    742 
    743    if (pwd) {
    744        free(pwd);
    745    }
    746    if (configDir) {
    747        free(configDir);
    748    }
    749    if (dbPrefix) {
    750        free(dbPrefix);
    751    }
    752    if (moduleSpec) {
    753        PR_smprintf_free(moduleSpec);
    754    }
    755    if (moduleSpecRerun) {
    756        PR_smprintf_free(moduleSpecRerun);
    757    }
    758 
    759 #ifdef _WIN32
    760    FreeLibrary(hModule);
    761 #else
    762    disableUnload = PR_GetEnvSecure("NSS_DISABLE_UNLOAD");
    763    if (!disableUnload) {
    764        PR_UnloadLibrary(lib);
    765    }
    766 #endif
    767    if (CKR_OK == crv && doForkTests && !disableUnload) {
    768        /* try to fork with softoken both de-initialized and unloaded */
    769        crv = PKM_ForkCheck(123, NULL, PR_TRUE, NULL);
    770    }
    771 
    772    printf("**** Total number of TESTS ran in %s is %d. ****\n",
    773           ((MODE == FIPSMODE) ? "FIPS MODE" : "NON FIPS MODE"), (int)NUMTESTS);
    774    if (CKR_OK == crv) {
    775        printf("**** ALL TESTS PASSED ****\n");
    776    }
    777 
    778    return crv;
    779 }
    780 
    781 /*
    782 *  PKM_KeyTests
    783 *
    784 *
    785 */
    786 
    787 CK_RV
    788 PKM_KeyTests(CK_FUNCTION_LIST_PTR pFunctionList,
    789             CK_SLOT_ID *pSlotList, CK_ULONG slotID,
    790             CK_UTF8CHAR_PTR pwd, CK_ULONG pwdLen)
    791 {
    792    CK_SESSION_HANDLE hRwSession;
    793 
    794    CK_RV crv = CKR_OK;
    795 
    796    /*** ECDSA Key ***/
    797    CK_BYTE ECDSA_P256_PARAMS[] = { 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07 };
    798    CK_MECHANISM ecdsaKeyPairGenMech;
    799    CK_ATTRIBUTE ecdsaPubKeyTemplate[3];
    800    CK_ATTRIBUTE ecdsaPrivKeyTemplate[5];
    801    CK_OBJECT_HANDLE hECDSApubKey = CK_INVALID_HANDLE;
    802    CK_OBJECT_HANDLE hECDSAprivKey = CK_INVALID_HANDLE;
    803 
    804    /**** RSA Key ***/
    805    CK_KEY_TYPE rsatype = CKK_RSA;
    806    CK_MECHANISM rsaKeyPairGenMech;
    807    CK_BYTE subject[] = { "RSA Private Key" };
    808    CK_ULONG modulusBits = 1024;
    809    CK_BYTE publicExponent[] = { 0x01, 0x00, 0x01 };
    810    CK_BYTE id[] = { "RSA123" };
    811    CK_ATTRIBUTE rsaPubKeyTemplate[9];
    812    CK_ATTRIBUTE rsaPrivKeyTemplate[11];
    813    CK_OBJECT_HANDLE hRSApubKey = CK_INVALID_HANDLE;
    814    CK_OBJECT_HANDLE hRSAprivKey = CK_INVALID_HANDLE;
    815 
    816    /*** AES Key ***/
    817    CK_MECHANISM sAESKeyMech = {
    818        CKM_AES_KEY_GEN, NULL, 0
    819    };
    820    CK_OBJECT_CLASS class = CKO_SECRET_KEY;
    821    CK_KEY_TYPE keyAESType = CKK_AES;
    822    CK_UTF8CHAR AESlabel[] = "An AES secret key object";
    823    CK_ULONG AESvalueLen = 32;
    824    CK_ATTRIBUTE sAESKeyTemplate[9];
    825    CK_OBJECT_HANDLE hAESSecKey;
    826 
    827    /*** DES3 Key ***/
    828    CK_KEY_TYPE keyDES3Type = CKK_DES3;
    829    CK_UTF8CHAR DES3label[] = "An Triple DES secret key object";
    830    CK_ULONG DES3valueLen = 56;
    831    CK_MECHANISM sDES3KeyGenMechanism = {
    832        CKM_DES3_KEY_GEN, NULL, 0
    833    };
    834    CK_ATTRIBUTE sDES3KeyTemplate[9];
    835    CK_OBJECT_HANDLE hDES3SecKey;
    836 
    837    CK_MECHANISM ecdsaWithSha256Mech = {
    838        CKM_ECDSA_SHA256, NULL, 0
    839    };
    840 
    841    CK_BYTE IV[16];
    842    CK_MECHANISM mech_DES3_CBC;
    843    CK_MECHANISM mech_DES3_CBC_PAD;
    844    CK_MECHANISM mech_AES_CBC_PAD;
    845    CK_MECHANISM mech_AES_CBC;
    846    struct mech_str {
    847        CK_ULONG mechanism;
    848        const char *mechanismStr;
    849    };
    850 
    851    typedef struct mech_str mech_str;
    852 
    853    mech_str digestMechs[] = {
    854        { CKM_SHA_1, "CKM_SHA_1 " },
    855        { CKM_SHA224, "CKM_SHA224" },
    856        { CKM_SHA256, "CKM_SHA256" },
    857        { CKM_SHA384, "CKM_SHA384" },
    858        { CKM_SHA512, "CKM_SHA512" }
    859    };
    860    mech_str hmacMechs[] = {
    861        { CKM_SHA_1_HMAC, "CKM_SHA_1_HMAC" },
    862        { CKM_SHA224_HMAC, "CKM_SHA224_HMAC" },
    863        { CKM_SHA256_HMAC, "CKM_SHA256_HMAC" },
    864        { CKM_SHA384_HMAC, "CKM_SHA384_HMAC" },
    865        { CKM_SHA512_HMAC, "CKM_SHA512_HMAC" }
    866    };
    867    mech_str sigRSAMechs[] = {
    868        { CKM_SHA1_RSA_PKCS, "CKM_SHA1_RSA_PKCS" },
    869        { CKM_SHA224_RSA_PKCS, "CKM_SHA224_RSA_PKCS" },
    870        { CKM_SHA256_RSA_PKCS, "CKM_SHA256_RSA_PKCS" },
    871        { CKM_SHA384_RSA_PKCS, "CKM_SHA384_RSA_PKCS" },
    872        { CKM_SHA512_RSA_PKCS, "CKM_SHA512_RSA_PKCS" }
    873    };
    874 
    875    CK_ULONG digestMechsSZ = NUM_ELEM(digestMechs);
    876    CK_ULONG sigRSAMechsSZ = NUM_ELEM(sigRSAMechs);
    877    CK_ULONG hmacMechsSZ = NUM_ELEM(hmacMechs);
    878    CK_MECHANISM mech;
    879 
    880    unsigned int i;
    881 
    882    NUMTESTS++; /* increment NUMTESTS */
    883 
    884    /* DSA key init */
    885    ecdsaPubKeyTemplate[0].type = CKA_EC_PARAMS;
    886    ecdsaPubKeyTemplate[0].pValue = ECDSA_P256_PARAMS;
    887    ecdsaPubKeyTemplate[0].ulValueLen = sizeof(ECDSA_P256_PARAMS);
    888    ecdsaPubKeyTemplate[1].type = CKA_TOKEN;
    889    ecdsaPubKeyTemplate[1].pValue = &ck_true;
    890    ecdsaPubKeyTemplate[1].ulValueLen = sizeof(ck_true);
    891    ecdsaPubKeyTemplate[2].type = CKA_VERIFY;
    892    ecdsaPubKeyTemplate[2].pValue = &ck_true;
    893    ecdsaPubKeyTemplate[2].ulValueLen = sizeof(ck_true);
    894    ecdsaKeyPairGenMech.mechanism = CKM_ECDSA_KEY_PAIR_GEN;
    895    ecdsaKeyPairGenMech.pParameter = NULL_PTR;
    896    ecdsaKeyPairGenMech.ulParameterLen = 0;
    897    ecdsaPrivKeyTemplate[0].type = CKA_TOKEN;
    898    ecdsaPrivKeyTemplate[0].pValue = &ck_true;
    899    ecdsaPrivKeyTemplate[0].ulValueLen = sizeof(ck_true);
    900    ecdsaPrivKeyTemplate[1].type = CKA_PRIVATE;
    901    ecdsaPrivKeyTemplate[1].pValue = &ck_true;
    902    ecdsaPrivKeyTemplate[1].ulValueLen = sizeof(ck_true);
    903    ecdsaPrivKeyTemplate[2].type = CKA_SENSITIVE;
    904    ecdsaPrivKeyTemplate[2].pValue = &ck_true;
    905    ecdsaPrivKeyTemplate[2].ulValueLen = sizeof(ck_true);
    906    ecdsaPrivKeyTemplate[3].type = CKA_SIGN,
    907    ecdsaPrivKeyTemplate[3].pValue = &ck_true;
    908    ecdsaPrivKeyTemplate[3].ulValueLen = sizeof(ck_true);
    909    ecdsaPrivKeyTemplate[4].type = CKA_EXTRACTABLE;
    910    ecdsaPrivKeyTemplate[4].pValue = &ck_true;
    911    ecdsaPrivKeyTemplate[4].ulValueLen = sizeof(ck_true);
    912 
    913    /* RSA key init */
    914    rsaKeyPairGenMech.mechanism = CKM_RSA_PKCS_KEY_PAIR_GEN;
    915    rsaKeyPairGenMech.pParameter = NULL_PTR;
    916    rsaKeyPairGenMech.ulParameterLen = 0;
    917 
    918    rsaPubKeyTemplate[0].type = CKA_KEY_TYPE;
    919    rsaPubKeyTemplate[0].pValue = &rsatype;
    920    rsaPubKeyTemplate[0].ulValueLen = sizeof(rsatype);
    921    rsaPubKeyTemplate[1].type = CKA_PRIVATE;
    922    rsaPubKeyTemplate[1].pValue = &ck_true;
    923    rsaPubKeyTemplate[1].ulValueLen = sizeof(ck_true);
    924    rsaPubKeyTemplate[2].type = CKA_ENCRYPT;
    925    rsaPubKeyTemplate[2].pValue = &ck_true;
    926    rsaPubKeyTemplate[2].ulValueLen = sizeof(ck_true);
    927    rsaPubKeyTemplate[3].type = CKA_DECRYPT;
    928    rsaPubKeyTemplate[3].pValue = &ck_true;
    929    rsaPubKeyTemplate[3].ulValueLen = sizeof(ck_true);
    930    rsaPubKeyTemplate[4].type = CKA_VERIFY;
    931    rsaPubKeyTemplate[4].pValue = &ck_true;
    932    rsaPubKeyTemplate[4].ulValueLen = sizeof(ck_true);
    933    rsaPubKeyTemplate[5].type = CKA_SIGN;
    934    rsaPubKeyTemplate[5].pValue = &ck_true;
    935    rsaPubKeyTemplate[5].ulValueLen = sizeof(ck_true);
    936    rsaPubKeyTemplate[6].type = CKA_WRAP;
    937    rsaPubKeyTemplate[6].pValue = &ck_true;
    938    rsaPubKeyTemplate[6].ulValueLen = sizeof(ck_true);
    939    rsaPubKeyTemplate[7].type = CKA_MODULUS_BITS;
    940    rsaPubKeyTemplate[7].pValue = &modulusBits;
    941    rsaPubKeyTemplate[7].ulValueLen = sizeof(modulusBits);
    942    rsaPubKeyTemplate[8].type = CKA_PUBLIC_EXPONENT;
    943    rsaPubKeyTemplate[8].pValue = publicExponent;
    944    rsaPubKeyTemplate[8].ulValueLen = sizeof(publicExponent);
    945 
    946    rsaPrivKeyTemplate[0].type = CKA_KEY_TYPE;
    947    rsaPrivKeyTemplate[0].pValue = &rsatype;
    948    rsaPrivKeyTemplate[0].ulValueLen = sizeof(rsatype);
    949    rsaPrivKeyTemplate[1].type = CKA_TOKEN;
    950    rsaPrivKeyTemplate[1].pValue = &ck_true;
    951    rsaPrivKeyTemplate[1].ulValueLen = sizeof(ck_true);
    952    rsaPrivKeyTemplate[2].type = CKA_PRIVATE;
    953    rsaPrivKeyTemplate[2].pValue = &ck_true;
    954    rsaPrivKeyTemplate[2].ulValueLen = sizeof(ck_true);
    955    rsaPrivKeyTemplate[3].type = CKA_SUBJECT;
    956    rsaPrivKeyTemplate[3].pValue = subject;
    957    rsaPrivKeyTemplate[3].ulValueLen = sizeof(subject);
    958    rsaPrivKeyTemplate[4].type = CKA_ID;
    959    rsaPrivKeyTemplate[4].pValue = id;
    960    rsaPrivKeyTemplate[4].ulValueLen = sizeof(id);
    961    rsaPrivKeyTemplate[5].type = CKA_SENSITIVE;
    962    rsaPrivKeyTemplate[5].pValue = &ck_true;
    963    rsaPrivKeyTemplate[5].ulValueLen = sizeof(ck_true);
    964    rsaPrivKeyTemplate[6].type = CKA_ENCRYPT;
    965    rsaPrivKeyTemplate[6].pValue = &ck_true;
    966    rsaPrivKeyTemplate[6].ulValueLen = sizeof(ck_true);
    967    rsaPrivKeyTemplate[7].type = CKA_DECRYPT;
    968    rsaPrivKeyTemplate[7].pValue = &ck_true;
    969    rsaPrivKeyTemplate[7].ulValueLen = sizeof(ck_true);
    970    rsaPrivKeyTemplate[8].type = CKA_VERIFY;
    971    rsaPrivKeyTemplate[8].pValue = &ck_true;
    972    rsaPrivKeyTemplate[8].ulValueLen = sizeof(ck_true);
    973    rsaPrivKeyTemplate[9].type = CKA_SIGN;
    974    rsaPrivKeyTemplate[9].pValue = &ck_true;
    975    rsaPrivKeyTemplate[9].ulValueLen = sizeof(ck_true);
    976    rsaPrivKeyTemplate[10].type = CKA_UNWRAP;
    977    rsaPrivKeyTemplate[10].pValue = &ck_true;
    978    rsaPrivKeyTemplate[10].ulValueLen = sizeof(ck_true);
    979 
    980    /* AES key template */
    981    sAESKeyTemplate[0].type = CKA_CLASS;
    982    sAESKeyTemplate[0].pValue = &class;
    983    sAESKeyTemplate[0].ulValueLen = sizeof(class);
    984    sAESKeyTemplate[1].type = CKA_KEY_TYPE;
    985    sAESKeyTemplate[1].pValue = &keyAESType;
    986    sAESKeyTemplate[1].ulValueLen = sizeof(keyAESType);
    987    sAESKeyTemplate[2].type = CKA_LABEL;
    988    sAESKeyTemplate[2].pValue = AESlabel;
    989    sAESKeyTemplate[2].ulValueLen = sizeof(AESlabel) - 1;
    990    sAESKeyTemplate[3].type = CKA_ENCRYPT;
    991    sAESKeyTemplate[3].pValue = &ck_true;
    992    sAESKeyTemplate[3].ulValueLen = sizeof(ck_true);
    993    sAESKeyTemplate[4].type = CKA_DECRYPT;
    994    sAESKeyTemplate[4].pValue = &ck_true;
    995    sAESKeyTemplate[4].ulValueLen = sizeof(ck_true);
    996    sAESKeyTemplate[5].type = CKA_SIGN;
    997    sAESKeyTemplate[5].pValue = &ck_true;
    998    sAESKeyTemplate[5].ulValueLen = sizeof(ck_true);
    999    sAESKeyTemplate[6].type = CKA_VERIFY;
   1000    sAESKeyTemplate[6].pValue = &ck_true;
   1001    sAESKeyTemplate[6].ulValueLen = sizeof(ck_true);
   1002    sAESKeyTemplate[7].type = CKA_UNWRAP;
   1003    sAESKeyTemplate[7].pValue = &ck_true;
   1004    sAESKeyTemplate[7].ulValueLen = sizeof(ck_true);
   1005    sAESKeyTemplate[8].type = CKA_VALUE_LEN;
   1006    sAESKeyTemplate[8].pValue = &AESvalueLen;
   1007    sAESKeyTemplate[8].ulValueLen = sizeof(AESvalueLen);
   1008 
   1009    /* DES3 key template */
   1010    sDES3KeyTemplate[0].type = CKA_CLASS;
   1011    sDES3KeyTemplate[0].pValue = &class;
   1012    sDES3KeyTemplate[0].ulValueLen = sizeof(class);
   1013    sDES3KeyTemplate[1].type = CKA_KEY_TYPE;
   1014    sDES3KeyTemplate[1].pValue = &keyDES3Type;
   1015    sDES3KeyTemplate[1].ulValueLen = sizeof(keyDES3Type);
   1016    sDES3KeyTemplate[2].type = CKA_LABEL;
   1017    sDES3KeyTemplate[2].pValue = DES3label;
   1018    sDES3KeyTemplate[2].ulValueLen = sizeof(DES3label) - 1;
   1019    sDES3KeyTemplate[3].type = CKA_ENCRYPT;
   1020    sDES3KeyTemplate[3].pValue = &ck_true;
   1021    sDES3KeyTemplate[3].ulValueLen = sizeof(ck_true);
   1022    sDES3KeyTemplate[4].type = CKA_DECRYPT;
   1023    sDES3KeyTemplate[4].pValue = &ck_true;
   1024    sDES3KeyTemplate[4].ulValueLen = sizeof(ck_true);
   1025    sDES3KeyTemplate[5].type = CKA_UNWRAP;
   1026    sDES3KeyTemplate[5].pValue = &ck_true;
   1027    sDES3KeyTemplate[5].ulValueLen = sizeof(ck_true);
   1028    sDES3KeyTemplate[6].type = CKA_SIGN,
   1029    sDES3KeyTemplate[6].pValue = &ck_true;
   1030    sDES3KeyTemplate[6].ulValueLen = sizeof(ck_true);
   1031    sDES3KeyTemplate[7].type = CKA_VERIFY;
   1032    sDES3KeyTemplate[7].pValue = &ck_true;
   1033    sDES3KeyTemplate[7].ulValueLen = sizeof(ck_true);
   1034    sDES3KeyTemplate[8].type = CKA_VALUE_LEN;
   1035    sDES3KeyTemplate[8].pValue = &DES3valueLen;
   1036    sDES3KeyTemplate[8].ulValueLen = sizeof(DES3valueLen);
   1037 
   1038    /* mech init */
   1039    memset(IV, 0x01, sizeof(IV));
   1040    mech_DES3_CBC.mechanism = CKM_DES3_CBC;
   1041    mech_DES3_CBC.pParameter = IV;
   1042    mech_DES3_CBC.ulParameterLen = sizeof(IV);
   1043    mech_DES3_CBC_PAD.mechanism = CKM_DES3_CBC_PAD;
   1044    mech_DES3_CBC_PAD.pParameter = IV;
   1045    mech_DES3_CBC_PAD.ulParameterLen = sizeof(IV);
   1046    mech_AES_CBC.mechanism = CKM_AES_CBC;
   1047    mech_AES_CBC.pParameter = IV;
   1048    mech_AES_CBC.ulParameterLen = sizeof(IV);
   1049    mech_AES_CBC_PAD.mechanism = CKM_AES_CBC_PAD;
   1050    mech_AES_CBC_PAD.pParameter = IV;
   1051    mech_AES_CBC_PAD.ulParameterLen = sizeof(IV);
   1052 
   1053    crv = pFunctionList->C_OpenSession(pSlotList[slotID],
   1054                                       CKF_RW_SESSION | CKF_SERIAL_SESSION,
   1055                                       NULL, NULL, &hRwSession);
   1056    if (crv == CKR_OK) {
   1057        PKM_LogIt("Opening a read/write session succeeded\n");
   1058    } else {
   1059        PKM_Error("Opening a read/write session failed "
   1060                  "with 0x%08X, %-26s\n",
   1061                  crv, PKM_CK_RVtoStr(crv));
   1062        return crv;
   1063    }
   1064 
   1065    if (MODE == FIPSMODE) {
   1066        crv = pFunctionList->C_GenerateKey(hRwSession, &sAESKeyMech,
   1067                                           sAESKeyTemplate,
   1068                                           NUM_ELEM(sAESKeyTemplate),
   1069                                           &hAESSecKey);
   1070        if (crv == CKR_OK) {
   1071            PKM_Error("C_GenerateKey succeeded when not logged in.\n");
   1072            return CKR_GENERAL_ERROR;
   1073        } else {
   1074            PKM_LogIt("C_GenerateKey returned as EXPECTED with 0x%08X, %-26s\n"
   1075                      "since not logged in\n",
   1076                      crv, PKM_CK_RVtoStr(crv));
   1077        }
   1078        crv = pFunctionList->C_GenerateKeyPair(hRwSession, &rsaKeyPairGenMech,
   1079                                               rsaPubKeyTemplate,
   1080                                               NUM_ELEM(rsaPubKeyTemplate),
   1081                                               rsaPrivKeyTemplate,
   1082                                               NUM_ELEM(rsaPrivKeyTemplate),
   1083                                               &hRSApubKey, &hRSAprivKey);
   1084        if (crv == CKR_OK) {
   1085            PKM_Error("C_GenerateKeyPair succeeded when not logged in.\n");
   1086            return CKR_GENERAL_ERROR;
   1087        } else {
   1088            PKM_LogIt("C_GenerateKeyPair returned as EXPECTED with 0x%08X, "
   1089                      "%-26s\n since not logged in\n",
   1090                      crv,
   1091                      PKM_CK_RVtoStr(crv));
   1092        }
   1093    }
   1094 
   1095    crv = pFunctionList->C_Login(hRwSession, CKU_USER, pwd, pwdLen);
   1096    if (crv == CKR_OK) {
   1097        PKM_LogIt("C_Login with correct password succeeded\n");
   1098    } else {
   1099        PKM_Error("C_Login with correct password failed "
   1100                  "with 0x%08X, %-26s\n",
   1101                  crv, PKM_CK_RVtoStr(crv));
   1102        return crv;
   1103    }
   1104 
   1105    PKM_LogIt("Generate an AES key ... \n");
   1106    /* generate an AES Secret Key */
   1107    crv = pFunctionList->C_GenerateKey(hRwSession, &sAESKeyMech,
   1108                                       sAESKeyTemplate,
   1109                                       NUM_ELEM(sAESKeyTemplate),
   1110                                       &hAESSecKey);
   1111    if (crv == CKR_OK) {
   1112        PKM_LogIt("C_GenerateKey AES succeeded\n");
   1113    } else {
   1114        PKM_Error("C_GenerateKey AES failed with 0x%08X, %-26s\n",
   1115                  crv, PKM_CK_RVtoStr(crv));
   1116        return crv;
   1117    }
   1118 
   1119    PKM_LogIt("Generate an 3DES key ...\n");
   1120    /* generate an 3DES Secret Key */
   1121    crv = pFunctionList->C_GenerateKey(hRwSession, &sDES3KeyGenMechanism,
   1122                                       sDES3KeyTemplate,
   1123                                       NUM_ELEM(sDES3KeyTemplate),
   1124                                       &hDES3SecKey);
   1125    if (crv == CKR_OK) {
   1126        PKM_LogIt("C_GenerateKey DES3 succeeded\n");
   1127    } else {
   1128        PKM_Error("C_GenerateKey failed with 0x%08X, %-26s\n", crv,
   1129                  PKM_CK_RVtoStr(crv));
   1130        return crv;
   1131    }
   1132 
   1133    PKM_LogIt("Generate a ECDSA key pair ... \n");
   1134    /* Generate a persistent ECDSA key pair */
   1135    crv = pFunctionList->C_GenerateKeyPair(hRwSession, &ecdsaKeyPairGenMech,
   1136                                           ecdsaPubKeyTemplate,
   1137                                           NUM_ELEM(ecdsaPubKeyTemplate),
   1138                                           ecdsaPrivKeyTemplate,
   1139                                           NUM_ELEM(ecdsaPrivKeyTemplate),
   1140                                           &hECDSApubKey, &hECDSAprivKey);
   1141    if (crv == CKR_OK) {
   1142        PKM_LogIt("ECDSA key pair generation succeeded\n");
   1143    } else {
   1144        PKM_Error("ECDSA key pair generation failed "
   1145                  "with 0x%08X, %-26s\n",
   1146                  crv, PKM_CK_RVtoStr(crv));
   1147        return crv;
   1148    }
   1149 
   1150    PKM_LogIt("Generate a RSA key pair ... \n");
   1151    /*** GEN RSA Key ***/
   1152    crv = pFunctionList->C_GenerateKeyPair(hRwSession, &rsaKeyPairGenMech,
   1153                                           rsaPubKeyTemplate,
   1154                                           NUM_ELEM(rsaPubKeyTemplate),
   1155                                           rsaPrivKeyTemplate,
   1156                                           NUM_ELEM(rsaPrivKeyTemplate),
   1157                                           &hRSApubKey, &hRSAprivKey);
   1158    if (crv == CKR_OK) {
   1159        PKM_LogIt("C_GenerateKeyPair created an RSA key pair. \n");
   1160    } else {
   1161        PKM_Error("C_GenerateKeyPair failed to create an RSA key pair.\n"
   1162                  "with 0x%08X, %-26s\n",
   1163                  crv, PKM_CK_RVtoStr(crv));
   1164        return crv;
   1165    }
   1166 
   1167    PKM_LogIt("**** Generation of keys completed ***** \n");
   1168 
   1169    mech.mechanism = CKM_RSA_PKCS;
   1170    mech.pParameter = NULL;
   1171    mech.ulParameterLen = 0;
   1172 
   1173    crv = PKM_wrapUnwrap(pFunctionList,
   1174                         hRwSession,
   1175                         hRSApubKey, hRSAprivKey,
   1176                         &mech,
   1177                         hAESSecKey,
   1178                         sAESKeyTemplate,
   1179                         NUM_ELEM(sAESKeyTemplate));
   1180 
   1181    if (crv == CKR_OK) {
   1182        PKM_LogIt("PKM_wrapUnwrap using RSA keypair to wrap AES key "
   1183                  "succeeded\n\n");
   1184    } else {
   1185        PKM_Error("PKM_wrapUnwrap using RSA keypair to wrap AES key failed "
   1186                  "with 0x%08X, %-26s\n",
   1187                  crv,
   1188                  PKM_CK_RVtoStr(crv));
   1189        return crv;
   1190    }
   1191 
   1192    crv = PKM_wrapUnwrap(pFunctionList,
   1193                         hRwSession,
   1194                         hRSApubKey, hRSAprivKey,
   1195                         &mech,
   1196                         hDES3SecKey,
   1197                         sDES3KeyTemplate,
   1198                         NUM_ELEM(sDES3KeyTemplate));
   1199 
   1200    if (crv == CKR_OK) {
   1201        PKM_LogIt("PKM_wrapUnwrap using RSA keypair to wrap DES3 key "
   1202                  "succeeded\n\n");
   1203    } else {
   1204        PKM_Error("PKM_wrapUnwrap using RSA keypair to wrap DES3 key "
   1205                  "failed with 0x%08X, %-26s\n",
   1206                  crv,
   1207                  PKM_CK_RVtoStr(crv));
   1208        return crv;
   1209    }
   1210 
   1211    crv = PKM_SecKeyCrypt(pFunctionList, hRwSession,
   1212                          hAESSecKey, &mech_AES_CBC_PAD,
   1213                          PLAINTEXT_PAD, sizeof(PLAINTEXT_PAD));
   1214    if (crv == CKR_OK) {
   1215        PKM_LogIt("PKM_SecKeyCrypt succeeded \n\n");
   1216    } else {
   1217        PKM_Error("PKM_SecKeyCrypt failed "
   1218                  "with 0x%08X, %-26s\n",
   1219                  crv, PKM_CK_RVtoStr(crv));
   1220        return crv;
   1221    }
   1222 
   1223    crv = PKM_SecKeyCrypt(pFunctionList, hRwSession,
   1224                          hAESSecKey, &mech_AES_CBC,
   1225                          PLAINTEXT, sizeof(PLAINTEXT));
   1226    if (crv == CKR_OK) {
   1227        PKM_LogIt("PKM_SecKeyCrypt AES succeeded \n\n");
   1228    } else {
   1229        PKM_Error("PKM_SecKeyCrypt failed "
   1230                  "with 0x%08X, %-26s\n",
   1231                  crv, PKM_CK_RVtoStr(crv));
   1232        return crv;
   1233    }
   1234 
   1235    crv = PKM_SecKeyCrypt(pFunctionList, hRwSession,
   1236                          hDES3SecKey, &mech_DES3_CBC,
   1237                          PLAINTEXT, sizeof(PLAINTEXT));
   1238    if (crv == CKR_OK) {
   1239        PKM_LogIt("PKM_SecKeyCrypt DES3 succeeded \n");
   1240    } else {
   1241        PKM_Error("PKM_SecKeyCrypt DES3 failed "
   1242                  "with 0x%08X, %-26s\n",
   1243                  crv, PKM_CK_RVtoStr(crv));
   1244        return crv;
   1245    }
   1246 
   1247    crv = PKM_SecKeyCrypt(pFunctionList, hRwSession,
   1248                          hDES3SecKey, &mech_DES3_CBC_PAD,
   1249                          PLAINTEXT_PAD, sizeof(PLAINTEXT_PAD));
   1250    if (crv == CKR_OK) {
   1251        PKM_LogIt("PKM_SecKeyCrypt DES3 succeeded \n\n");
   1252    } else {
   1253        PKM_Error("PKM_SecKeyCrypt DES3 failed "
   1254                  "with 0x%08X, %-26s\n",
   1255                  crv, PKM_CK_RVtoStr(crv));
   1256        return crv;
   1257    }
   1258 
   1259    mech.mechanism = CKM_RSA_PKCS;
   1260    crv = PKM_RecoverFunctions(pFunctionList, hRwSession,
   1261                               hRSApubKey, hRSAprivKey,
   1262                               &mech,
   1263                               PLAINTEXT, sizeof(PLAINTEXT));
   1264    if (crv == CKR_OK) {
   1265        PKM_LogIt("PKM_RecoverFunctions for CKM_RSA_PKCS succeeded\n\n");
   1266    } else {
   1267        PKM_Error("PKM_RecoverFunctions failed with 0x%08X, %-26s\n", crv,
   1268                  PKM_CK_RVtoStr(crv));
   1269        return crv;
   1270    }
   1271 
   1272    mech.pParameter = NULL;
   1273    mech.ulParameterLen = 0;
   1274 
   1275    for (i = 0; i < sigRSAMechsSZ; i++) {
   1276 
   1277        mech.mechanism = sigRSAMechs[i].mechanism;
   1278 
   1279        crv = PKM_PubKeySign(pFunctionList, hRwSession,
   1280                             hRSApubKey, hRSAprivKey,
   1281                             &mech,
   1282                             PLAINTEXT, sizeof(PLAINTEXT));
   1283        if (crv == CKR_OK) {
   1284            PKM_LogIt("PKM_PubKeySign succeeded for %-10s\n\n",
   1285                      sigRSAMechs[i].mechanismStr);
   1286        } else {
   1287            PKM_Error("PKM_PubKeySign failed for %-10s  "
   1288                      "with 0x%08X, %-26s\n",
   1289                      sigRSAMechs[i].mechanismStr, crv,
   1290                      PKM_CK_RVtoStr(crv));
   1291            return crv;
   1292        }
   1293        crv = PKM_DualFuncSign(pFunctionList, hRwSession,
   1294                               hRSApubKey, hRSAprivKey,
   1295                               &mech,
   1296                               hAESSecKey, &mech_AES_CBC,
   1297                               PLAINTEXT, sizeof(PLAINTEXT));
   1298        if (crv == CKR_OK) {
   1299            PKM_LogIt("PKM_DualFuncSign with AES secret key succeeded "
   1300                      "for %-10s\n\n",
   1301                      sigRSAMechs[i].mechanismStr);
   1302        } else {
   1303            PKM_Error("PKM_DualFuncSign with AES secret key failed "
   1304                      "for %-10s  "
   1305                      "with 0x%08X, %-26s\n",
   1306                      sigRSAMechs[i].mechanismStr, crv,
   1307                      PKM_CK_RVtoStr(crv));
   1308            return crv;
   1309        }
   1310        crv = PKM_DualFuncSign(pFunctionList, hRwSession,
   1311                               hRSApubKey, hRSAprivKey,
   1312                               &mech,
   1313                               hDES3SecKey, &mech_DES3_CBC,
   1314                               PLAINTEXT, sizeof(PLAINTEXT));
   1315        if (crv == CKR_OK) {
   1316            PKM_LogIt("PKM_DualFuncSign with DES3 secret key succeeded "
   1317                      "for %-10s\n\n",
   1318                      sigRSAMechs[i].mechanismStr);
   1319        } else {
   1320            PKM_Error("PKM_DualFuncSign with DES3 secret key failed "
   1321                      "for %-10s  "
   1322                      "with 0x%08X, %-26s\n",
   1323                      sigRSAMechs[i].mechanismStr, crv,
   1324                      PKM_CK_RVtoStr(crv));
   1325            return crv;
   1326        }
   1327        crv = PKM_DualFuncSign(pFunctionList, hRwSession,
   1328                               hRSApubKey, hRSAprivKey,
   1329                               &mech,
   1330                               hAESSecKey, &mech_AES_CBC_PAD,
   1331                               PLAINTEXT_PAD, sizeof(PLAINTEXT_PAD));
   1332        if (crv == CKR_OK) {
   1333            PKM_LogIt("PKM_DualFuncSign with AES secret key CBC_PAD "
   1334                      "succeeded for %-10s\n\n",
   1335                      sigRSAMechs[i].mechanismStr);
   1336        } else {
   1337            PKM_Error("PKM_DualFuncSign with AES secret key CBC_PAD "
   1338                      "failed for %-10s  "
   1339                      "with 0x%08X, %-26s\n",
   1340                      sigRSAMechs[i].mechanismStr, crv,
   1341                      PKM_CK_RVtoStr(crv));
   1342            return crv;
   1343        }
   1344        crv = PKM_DualFuncSign(pFunctionList, hRwSession,
   1345                               hRSApubKey, hRSAprivKey,
   1346                               &mech,
   1347                               hDES3SecKey, &mech_DES3_CBC_PAD,
   1348                               PLAINTEXT_PAD, sizeof(PLAINTEXT_PAD));
   1349        if (crv == CKR_OK) {
   1350            PKM_LogIt("PKM_DualFuncSign with DES3 secret key CBC_PAD "
   1351                      "succeeded for %-10s\n\n",
   1352                      sigRSAMechs[i].mechanismStr);
   1353        } else {
   1354            PKM_Error("PKM_DualFuncSign with DES3 secret key CBC_PAD "
   1355                      "failed for %-10s  "
   1356                      "with 0x%08X, %-26s\n",
   1357                      sigRSAMechs[i].mechanismStr, crv,
   1358                      PKM_CK_RVtoStr(crv));
   1359            return crv;
   1360        }
   1361 
   1362    } /* end of RSA for loop */
   1363 
   1364    crv = PKM_PubKeySign(pFunctionList, hRwSession,
   1365                         hECDSApubKey, hECDSAprivKey,
   1366                         &ecdsaWithSha256Mech, PLAINTEXT, sizeof(PLAINTEXT));
   1367    if (crv == CKR_OK) {
   1368        PKM_LogIt("PKM_PubKeySign for ECDSAwithSHA256 succeeded \n\n");
   1369    } else {
   1370        PKM_Error("PKM_PubKeySign failed "
   1371                  "with 0x%08X, %-26s\n",
   1372                  crv, PKM_CK_RVtoStr(crv));
   1373        return crv;
   1374    }
   1375    crv = PKM_DualFuncSign(pFunctionList, hRwSession,
   1376                           hECDSApubKey, hECDSAprivKey,
   1377                           &ecdsaWithSha256Mech,
   1378                           hAESSecKey, &mech_AES_CBC,
   1379                           PLAINTEXT, sizeof(PLAINTEXT));
   1380    if (crv == CKR_OK) {
   1381        PKM_LogIt("PKM_DualFuncSign with AES secret key succeeded "
   1382                  "for DSAWithSHA1\n\n");
   1383    } else {
   1384        PKM_Error("PKM_DualFuncSign with AES secret key failed "
   1385                  "for DSAWithSHA1 with 0x%08X, %-26s\n",
   1386                  crv, PKM_CK_RVtoStr(crv));
   1387        return crv;
   1388    }
   1389    crv = PKM_DualFuncSign(pFunctionList, hRwSession,
   1390                           hECDSApubKey, hECDSAprivKey,
   1391                           &ecdsaWithSha256Mech,
   1392                           hDES3SecKey, &mech_DES3_CBC,
   1393                           PLAINTEXT, sizeof(PLAINTEXT));
   1394    if (crv == CKR_OK) {
   1395        PKM_LogIt("PKM_DualFuncSign with DES3 secret key succeeded "
   1396                  "for ECDSAWithSHA256\n\n");
   1397    } else {
   1398        PKM_Error("PKM_DualFuncSign with DES3 secret key failed "
   1399                  "for ECDSAWithSHA256 with 0x%08X, %-26s\n",
   1400                  crv, PKM_CK_RVtoStr(crv));
   1401        return crv;
   1402    }
   1403    crv = PKM_DualFuncSign(pFunctionList, hRwSession,
   1404                           hECDSApubKey, hECDSAprivKey,
   1405                           &ecdsaWithSha256Mech,
   1406                           hAESSecKey, &mech_AES_CBC_PAD,
   1407                           PLAINTEXT_PAD, sizeof(PLAINTEXT_PAD));
   1408    if (crv == CKR_OK) {
   1409        PKM_LogIt("PKM_DualFuncSign with AES secret key CBC_PAD succeeded "
   1410                  "for ECDSAWithSHA256\n\n");
   1411    } else {
   1412        PKM_Error("PKM_DualFuncSign with AES secret key CBC_PAD failed "
   1413                  "for ECDSAWithSHA256 with 0x%08X, %-26s\n",
   1414                  crv, PKM_CK_RVtoStr(crv));
   1415        return crv;
   1416    }
   1417    crv = PKM_DualFuncSign(pFunctionList, hRwSession,
   1418                           hECDSApubKey, hECDSAprivKey,
   1419                           &ecdsaWithSha256Mech,
   1420                           hDES3SecKey, &mech_DES3_CBC_PAD,
   1421                           PLAINTEXT_PAD, sizeof(PLAINTEXT_PAD));
   1422    if (crv == CKR_OK) {
   1423        PKM_LogIt("PKM_DualFuncSign with DES3 secret key CBC_PAD succeeded "
   1424                  "for ECDSAWithSHA256\n\n");
   1425    } else {
   1426        PKM_Error("PKM_DualFuncSign with DES3 secret key CBC_PAD failed "
   1427                  "for ECDSAWithSHA256 with 0x%08X, %-26s\n",
   1428                  crv, PKM_CK_RVtoStr(crv));
   1429        return crv;
   1430    }
   1431 
   1432    for (i = 0; i < digestMechsSZ; i++) {
   1433        mech.mechanism = digestMechs[i].mechanism;
   1434        crv = PKM_Digest(pFunctionList, hRwSession,
   1435                         &mech, hAESSecKey,
   1436                         PLAINTEXT, sizeof(PLAINTEXT));
   1437        if (crv == CKR_OK) {
   1438            PKM_LogIt("PKM_Digest with AES secret key succeeded for %-10s\n\n",
   1439                      digestMechs[i].mechanismStr);
   1440        } else {
   1441            PKM_Error("PKM_Digest with AES secret key failed for "
   1442                      "%-10s with 0x%08X,  %-26s\n",
   1443                      digestMechs[i].mechanismStr, crv,
   1444                      PKM_CK_RVtoStr(crv));
   1445            return crv;
   1446        }
   1447        crv = PKM_DualFuncDigest(pFunctionList, hRwSession,
   1448                                 hAESSecKey, &mech_AES_CBC,
   1449                                 0, &mech,
   1450                                 PLAINTEXT, sizeof(PLAINTEXT));
   1451        if (crv == CKR_OK) {
   1452            PKM_LogIt("PKM_DualFuncDigest with AES secret key succeeded\n\n");
   1453        } else {
   1454            PKM_Error("PKM_DualFuncDigest with AES secret key "
   1455                      "failed with 0x%08X, %-26s\n",
   1456                      crv,
   1457                      PKM_CK_RVtoStr(crv));
   1458        }
   1459 
   1460        crv = PKM_Digest(pFunctionList, hRwSession,
   1461                         &mech, hDES3SecKey,
   1462                         PLAINTEXT, sizeof(PLAINTEXT));
   1463        if (crv == CKR_OK) {
   1464            PKM_LogIt("PKM_Digest with DES3 secret key succeeded for %-10s\n\n",
   1465                      digestMechs[i].mechanismStr);
   1466        } else {
   1467            PKM_Error("PKM_Digest with DES3 secret key failed for "
   1468                      "%-10s with 0x%08X,  %-26s\n",
   1469                      digestMechs[i].mechanismStr, crv,
   1470                      PKM_CK_RVtoStr(crv));
   1471            return crv;
   1472        }
   1473        crv = PKM_DualFuncDigest(pFunctionList, hRwSession,
   1474                                 hDES3SecKey, &mech_DES3_CBC,
   1475                                 0, &mech,
   1476                                 PLAINTEXT, sizeof(PLAINTEXT));
   1477        if (crv == CKR_OK) {
   1478            PKM_LogIt("PKM_DualFuncDigest DES3 secret key succeeded\n\n");
   1479        } else {
   1480            PKM_Error("PKM_DualFuncDigest DES3 secret key "
   1481                      "failed with 0x%08X, %-26s\n",
   1482                      crv,
   1483                      PKM_CK_RVtoStr(crv));
   1484        }
   1485 
   1486        crv = PKM_Digest(pFunctionList, hRwSession,
   1487                         &mech, 0,
   1488                         PLAINTEXT, sizeof(PLAINTEXT));
   1489        if (crv == CKR_OK) {
   1490            PKM_LogIt("PKM_Digest with no secret key succeeded for %-10s\n\n",
   1491                      digestMechs[i].mechanismStr);
   1492        } else {
   1493            PKM_Error("PKM_Digest with no secret key failed for %-10s  "
   1494                      "with 0x%08X, %-26s\n",
   1495                      digestMechs[i].mechanismStr, crv,
   1496                      PKM_CK_RVtoStr(crv));
   1497            return crv;
   1498        }
   1499    } /* end of digest loop */
   1500 
   1501    for (i = 0; i < hmacMechsSZ; i++) {
   1502        mech.mechanism = hmacMechs[i].mechanism;
   1503        crv = PKM_Hmac(pFunctionList, hRwSession,
   1504                       hAESSecKey, &mech,
   1505                       PLAINTEXT, sizeof(PLAINTEXT));
   1506        if (crv == CKR_OK) {
   1507            PKM_LogIt("PKM_Hmac with AES secret key succeeded for %-10s\n\n",
   1508                      hmacMechs[i].mechanismStr);
   1509        } else {
   1510            PKM_Error("PKM_Hmac with AES secret key failed for %-10s "
   1511                      "with 0x%08X, %-26s\n",
   1512                      hmacMechs[i].mechanismStr, crv, PKM_CK_RVtoStr(crv));
   1513            return crv;
   1514        }
   1515        if ((MODE == FIPSMODE) && (mech.mechanism == CKM_SHA512_HMAC))
   1516            break;
   1517        crv = PKM_Hmac(pFunctionList, hRwSession,
   1518                       hDES3SecKey, &mech,
   1519                       PLAINTEXT, sizeof(PLAINTEXT));
   1520        if (crv == CKR_OK) {
   1521            PKM_LogIt("PKM_Hmac with DES3 secret key succeeded for %-10s\n\n",
   1522                      hmacMechs[i].mechanismStr);
   1523        } else {
   1524            PKM_Error("PKM_Hmac with DES3 secret key failed for %-10s "
   1525                      "with 0x%08X,  %-26s\n",
   1526                      hmacMechs[i].mechanismStr, crv, PKM_CK_RVtoStr(crv));
   1527            return crv;
   1528        }
   1529 
   1530    } /* end of hmac loop */
   1531 
   1532    crv = pFunctionList->C_Logout(hRwSession);
   1533    if (crv == CKR_OK) {
   1534        PKM_LogIt("C_Logout succeeded\n");
   1535    } else {
   1536        PKM_Error("C_Logout failed with 0x%08X, %-26s\n", crv,
   1537                  PKM_CK_RVtoStr(crv));
   1538        return crv;
   1539    }
   1540 
   1541    crv = pFunctionList->C_CloseSession(hRwSession);
   1542    if (crv != CKR_OK) {
   1543        PKM_Error("C_CloseSession failed with 0x%08X, %-26s\n", crv,
   1544                  PKM_CK_RVtoStr(crv));
   1545        return crv;
   1546    }
   1547 
   1548    return crv;
   1549 }
   1550 
   1551 void
   1552 PKM_LogIt(const char *fmt, ...)
   1553 {
   1554    va_list args;
   1555 
   1556    if (verbose) {
   1557        va_start(args, fmt);
   1558        if (MODE == FIPSMODE) {
   1559            printf("FIPS MODE: ");
   1560        } else if (MODE == NONFIPSMODE) {
   1561            printf("NON FIPS MODE: ");
   1562        } else if (MODE == HYBRIDMODE) {
   1563            printf("Hybrid MODE: ");
   1564        }
   1565        vprintf(fmt, args);
   1566        va_end(args);
   1567    }
   1568 }
   1569 
   1570 void
   1571 PKM_Error(const char *fmt, ...)
   1572 {
   1573    va_list args;
   1574    va_start(args, fmt);
   1575 
   1576    if (MODE == FIPSMODE) {
   1577        fprintf(stderr, "\nFIPS MODE PKM_Error: ");
   1578    } else if (MODE == NONFIPSMODE) {
   1579        fprintf(stderr, "NON FIPS MODE PKM_Error: ");
   1580    } else if (MODE == HYBRIDMODE) {
   1581        fprintf(stderr, "Hybrid MODE PKM_Error: ");
   1582    } else
   1583        fprintf(stderr, "NOMODE PKM_Error: ");
   1584    vfprintf(stderr, fmt, args);
   1585    va_end(args);
   1586 }
   1587 CK_SLOT_ID *
   1588 PKM_GetSlotList(CK_FUNCTION_LIST_PTR pFunctionList,
   1589                CK_ULONG slotID)
   1590 {
   1591    CK_RV crv = CKR_OK;
   1592    CK_SLOT_ID *pSlotList = NULL;
   1593    CK_ULONG slotCount;
   1594 
   1595    NUMTESTS++; /* increment NUMTESTS */
   1596 
   1597    /* Get slot list */
   1598    crv = pFunctionList->C_GetSlotList(CK_FALSE /* all slots */,
   1599                                       NULL, &slotCount);
   1600    if (crv != CKR_OK) {
   1601        PKM_Error("C_GetSlotList failed with 0x%08X, %-26s\n", crv,
   1602                  PKM_CK_RVtoStr(crv));
   1603        return NULL;
   1604    }
   1605    PKM_LogIt("C_GetSlotList reported there are %lu slots\n", slotCount);
   1606    pSlotList = (CK_SLOT_ID *)malloc(slotCount * sizeof(CK_SLOT_ID));
   1607    if (!pSlotList) {
   1608        PKM_Error("failed to allocate slot list\n");
   1609        return NULL;
   1610    }
   1611    crv = pFunctionList->C_GetSlotList(CK_FALSE /* all slots */,
   1612                                       pSlotList, &slotCount);
   1613    if (crv != CKR_OK) {
   1614        PKM_Error("C_GetSlotList failed with 0x%08X, %-26s\n", crv,
   1615                  PKM_CK_RVtoStr(crv));
   1616        if (pSlotList)
   1617            free(pSlotList);
   1618        return NULL;
   1619    }
   1620    return pSlotList;
   1621 }
   1622 
   1623 CK_RV
   1624 PKM_InitPWforDB(CK_FUNCTION_LIST_PTR pFunctionList,
   1625                CK_SLOT_ID *pSlotList, CK_ULONG slotID,
   1626                CK_UTF8CHAR_PTR pwd, CK_ULONG pwdLen)
   1627 {
   1628    CK_RV crv = CKR_OK;
   1629    CK_SESSION_HANDLE hSession;
   1630    static const CK_UTF8CHAR testPin[] = { "0Mozilla" };
   1631    static const CK_UTF8CHAR weakPin[] = { "mozilla" };
   1632 
   1633    crv = pFunctionList->C_OpenSession(pSlotList[slotID],
   1634                                       CKF_RW_SESSION | CKF_SERIAL_SESSION,
   1635                                       NULL, NULL, &hSession);
   1636    if (crv != CKR_OK) {
   1637        PKM_Error("C_OpenSession failed with 0x%08X, %-26s\n", crv,
   1638                  PKM_CK_RVtoStr(crv));
   1639        return crv;
   1640    }
   1641    PKM_LogIt("CKU_USER 0x%08X \n", CKU_USER);
   1642 
   1643    crv = pFunctionList->C_Login(hSession, CKU_SO, NULL, 0);
   1644    if (crv != CKR_OK) {
   1645        PKM_Error("C_Login failed with 0x%08X, %-26s\n", crv,
   1646                  PKM_CK_RVtoStr(crv));
   1647        return crv;
   1648    }
   1649    if (MODE == FIPSMODE) {
   1650        crv = pFunctionList->C_InitPIN(hSession, (CK_UTF8CHAR *)weakPin,
   1651                                       strlen((char *)weakPin));
   1652        if (crv == CKR_OK) {
   1653            PKM_Error("C_InitPIN with a weak password succeeded\n");
   1654            return crv;
   1655        } else {
   1656            PKM_LogIt("C_InitPIN with a weak password failed with "
   1657                      "0x%08X, %-26s\n",
   1658                      crv, PKM_CK_RVtoStr(crv));
   1659        }
   1660    }
   1661    crv = pFunctionList->C_InitPIN(hSession, (CK_UTF8CHAR *)testPin,
   1662                                   strlen((char *)testPin));
   1663    if (crv == CKR_OK) {
   1664        PKM_LogIt("C_InitPIN succeeded\n");
   1665    } else {
   1666        PKM_Error("C_InitPIN failed with 0x%08X, %-26s\n", crv,
   1667                  PKM_CK_RVtoStr(crv));
   1668        return crv;
   1669    }
   1670    crv = pFunctionList->C_Logout(hSession);
   1671    if (crv != CKR_OK) {
   1672        PKM_Error("C_Logout failed with 0x%08X, %-26s\n", crv,
   1673                  PKM_CK_RVtoStr(crv));
   1674        return crv;
   1675    }
   1676    crv = pFunctionList->C_CloseSession(hSession);
   1677    if (crv != CKR_OK) {
   1678        PKM_Error("C_CloseSession failed with 0x%08X, %-26s\n", crv,
   1679                  PKM_CK_RVtoStr(crv));
   1680        return crv;
   1681    }
   1682 
   1683    crv = pFunctionList->C_OpenSession(pSlotList[slotID],
   1684                                       CKF_RW_SESSION | CKF_SERIAL_SESSION,
   1685                                       NULL, NULL, &hSession);
   1686    if (crv != CKR_OK) {
   1687        PKM_Error("C_OpenSession failed with 0x%08X, %-26s\n", crv,
   1688                  PKM_CK_RVtoStr(crv));
   1689        return crv;
   1690    }
   1691 
   1692    PKM_LogIt("CKU_USER 0x%08X \n", CKU_USER);
   1693 
   1694    crv = pFunctionList->C_Login(hSession, CKU_USER, (CK_UTF8CHAR *)testPin,
   1695                                 strlen((const char *)testPin));
   1696    if (crv != CKR_OK) {
   1697        PKM_Error("C_Login failed with 0x%08X, %-26s\n", crv,
   1698                  PKM_CK_RVtoStr(crv));
   1699        return crv;
   1700    }
   1701    if (MODE == FIPSMODE) {
   1702        crv = pFunctionList->C_SetPIN(
   1703            hSession, (CK_UTF8CHAR *)testPin,
   1704            strlen((const char *)testPin),
   1705            (CK_UTF8CHAR *)weakPin,
   1706            strlen((const char *)weakPin));
   1707        if (crv == CKR_OK) {
   1708            PKM_Error("C_SetPIN with a weak password succeeded\n");
   1709            return crv;
   1710        } else {
   1711            PKM_LogIt("C_SetPIN with a weak password returned with "
   1712                      "0x%08X, %-26s\n",
   1713                      crv, PKM_CK_RVtoStr(crv));
   1714        }
   1715    }
   1716    crv = pFunctionList->C_SetPIN(
   1717        hSession, (CK_UTF8CHAR *)testPin,
   1718        strlen((const char *)testPin),
   1719        pwd, pwdLen);
   1720    if (crv != CKR_OK) {
   1721        PKM_Error("C_CSetPin failed with 0x%08X, %-26s\n", crv,
   1722                  PKM_CK_RVtoStr(crv));
   1723        return crv;
   1724    }
   1725    crv = pFunctionList->C_Logout(hSession);
   1726    if (crv != CKR_OK) {
   1727        PKM_Error("C_Logout failed with 0x%08X, %-26s\n", crv,
   1728                  PKM_CK_RVtoStr(crv));
   1729        return crv;
   1730    }
   1731    crv = pFunctionList->C_CloseSession(hSession);
   1732    if (crv != CKR_OK) {
   1733        PKM_Error("C_CloseSession failed with 0x%08X, %-26s\n", crv,
   1734                  PKM_CK_RVtoStr(crv));
   1735        return crv;
   1736    }
   1737    return crv;
   1738 }
   1739 
   1740 CK_RV
   1741 PKM_ShowInfo(CK_FUNCTION_LIST_PTR pFunctionList, CK_ULONG slotID)
   1742 {
   1743    CK_RV crv = CKR_OK;
   1744    CK_INFO info;
   1745    CK_SLOT_ID *pSlotList = NULL;
   1746    unsigned i;
   1747 
   1748    CK_SLOT_INFO slotInfo;
   1749    CK_TOKEN_INFO tokenInfo;
   1750    CK_FLAGS bitflag;
   1751 
   1752    NUMTESTS++; /* increment NUMTESTS */
   1753 
   1754    crv = pFunctionList->C_GetInfo(&info);
   1755    if (crv == CKR_OK) {
   1756        PKM_LogIt("C_GetInfo succeeded\n");
   1757    } else {
   1758        PKM_Error("C_GetInfo failed with 0x%08X, %-26s\n", crv,
   1759                  PKM_CK_RVtoStr(crv));
   1760        return crv;
   1761    }
   1762    PKM_LogIt("General information about the PKCS #11 library:\n");
   1763    PKM_LogIt("    PKCS #11 version: %d.%d\n",
   1764              (int)info.cryptokiVersion.major,
   1765              (int)info.cryptokiVersion.minor);
   1766    PKM_LogIt("    manufacturer ID: %.32s\n", info.manufacturerID);
   1767    PKM_LogIt("    flags: 0x%08lX\n", info.flags);
   1768    PKM_LogIt("    library description: %.32s\n", info.libraryDescription);
   1769    PKM_LogIt("    library version: %d.%d\n",
   1770              (int)info.libraryVersion.major, (int)info.libraryVersion.minor);
   1771    PKM_LogIt("\n");
   1772 
   1773    /* Get slot list */
   1774    pSlotList = PKM_GetSlotList(pFunctionList, slotID);
   1775    if (pSlotList == NULL) {
   1776        PKM_Error("PKM_GetSlotList failed with \n");
   1777        return crv;
   1778    }
   1779    crv = pFunctionList->C_GetSlotInfo(pSlotList[slotID], &slotInfo);
   1780    if (crv == CKR_OK) {
   1781        PKM_LogIt("C_GetSlotInfo succeeded\n");
   1782    } else {
   1783        PKM_Error("C_GetSlotInfo failed with 0x%08X, %-26s\n", crv,
   1784                  PKM_CK_RVtoStr(crv));
   1785        return crv;
   1786    }
   1787    PKM_LogIt("Information about slot %lu:\n", pSlotList[slotID]);
   1788    PKM_LogIt("    slot description: %.64s\n", slotInfo.slotDescription);
   1789    PKM_LogIt("    slot manufacturer ID: %.32s\n", slotInfo.manufacturerID);
   1790    PKM_LogIt("    flags: 0x%08lX\n", slotInfo.flags);
   1791    bitflag = 1;
   1792    for (i = 0; i < sizeof(slotFlagName) / sizeof(slotFlagName[0]); i++) {
   1793        if (slotInfo.flags & bitflag) {
   1794            PKM_LogIt("           %s\n", slotFlagName[i]);
   1795        }
   1796        bitflag <<= 1;
   1797    }
   1798    PKM_LogIt("    slot's hardware version number: %d.%d\n",
   1799              (int)slotInfo.hardwareVersion.major,
   1800              (int)slotInfo.hardwareVersion.minor);
   1801    PKM_LogIt("    slot's firmware version number: %d.%d\n",
   1802              (int)slotInfo.firmwareVersion.major,
   1803              (int)slotInfo.firmwareVersion.minor);
   1804    PKM_LogIt("\n");
   1805 
   1806    crv = pFunctionList->C_GetTokenInfo(pSlotList[slotID], &tokenInfo);
   1807    if (crv == CKR_OK) {
   1808        PKM_LogIt("C_GetTokenInfo succeeded\n");
   1809    } else {
   1810        PKM_Error("C_GetTokenInfo failed with 0x%08X, %-26s\n", crv,
   1811                  PKM_CK_RVtoStr(crv));
   1812        return crv;
   1813    }
   1814    PKM_LogIt("Information about the token in slot %lu:\n",
   1815              pSlotList[slotID]);
   1816    PKM_LogIt("    label: %.32s\n", tokenInfo.label);
   1817    PKM_LogIt("    device manufacturer ID: %.32s\n",
   1818              tokenInfo.manufacturerID);
   1819    PKM_LogIt("    device model: %.16s\n", tokenInfo.model);
   1820    PKM_LogIt("    device serial number: %.16s\n", tokenInfo.serialNumber);
   1821    PKM_LogIt("    flags: 0x%08lX\n", tokenInfo.flags);
   1822    bitflag = 1;
   1823    for (i = 0; i < sizeof(tokenFlagName) / sizeof(tokenFlagName[0]); i++) {
   1824        if (tokenInfo.flags & bitflag) {
   1825            PKM_LogIt("           %s\n", tokenFlagName[i]);
   1826        }
   1827        bitflag <<= 1;
   1828    }
   1829    PKM_LogIt("    maximum session count: %lu\n",
   1830              tokenInfo.ulMaxSessionCount);
   1831    PKM_LogIt("    session count: %lu\n", tokenInfo.ulSessionCount);
   1832    PKM_LogIt("    maximum read/write session count: %lu\n",
   1833              tokenInfo.ulMaxRwSessionCount);
   1834    PKM_LogIt("    read/write session count: %lu\n",
   1835              tokenInfo.ulRwSessionCount);
   1836    PKM_LogIt("    maximum PIN length: %lu\n", tokenInfo.ulMaxPinLen);
   1837    PKM_LogIt("    minimum PIN length: %lu\n", tokenInfo.ulMinPinLen);
   1838    PKM_LogIt("    total public memory: %lu\n",
   1839              tokenInfo.ulTotalPublicMemory);
   1840    PKM_LogIt("    free public memory: %lu\n",
   1841              tokenInfo.ulFreePublicMemory);
   1842    PKM_LogIt("    total private memory: %lu\n",
   1843              tokenInfo.ulTotalPrivateMemory);
   1844    PKM_LogIt("    free private memory: %lu\n",
   1845              tokenInfo.ulFreePrivateMemory);
   1846    PKM_LogIt("    hardware version number: %d.%d\n",
   1847              (int)tokenInfo.hardwareVersion.major,
   1848              (int)tokenInfo.hardwareVersion.minor);
   1849    PKM_LogIt("    firmware version number: %d.%d\n",
   1850              (int)tokenInfo.firmwareVersion.major,
   1851              (int)tokenInfo.firmwareVersion.minor);
   1852    if (tokenInfo.flags & CKF_CLOCK_ON_TOKEN) {
   1853        PKM_LogIt("    current time: %.16s\n", tokenInfo.utcTime);
   1854    }
   1855    PKM_LogIt("PKM_ShowInfo done \n\n");
   1856    free(pSlotList);
   1857    return crv;
   1858 }
   1859 
   1860 /* PKM_HybridMode                                                         */
   1861 /* The NSS cryptographic module has two modes of operation: FIPS Approved */
   1862 /* mode and NONFIPS Approved mode. The two modes of operation are         */
   1863 /* independent of each other -- they have their own copies of data        */
   1864 /* structures and they are even allowed to be active at the same time.    */
   1865 /* The module is FIPS 140-2 compliant only when the NONFIPS mode          */
   1866 /* is inactive.                                                           */
   1867 /* PKM_HybridMode demostrates how an application can switch between the   */
   1868 /* two modes: FIPS Approved mode and NONFIPS mode.                        */
   1869 CK_RV
   1870 PKM_HybridMode(CK_UTF8CHAR_PTR pwd, CK_ULONG pwdLen,
   1871               CK_C_INITIALIZE_ARGS_NSS *initArgs)
   1872 {
   1873 
   1874    CK_C_GetFunctionList pC_GetFunctionList; /* NONFIPSMode */
   1875    CK_FUNCTION_LIST_PTR pC_FunctionList;
   1876    CK_SLOT_ID *pC_SlotList = NULL;
   1877    CK_ULONG slotID_C = 1;
   1878    CK_C_GetFunctionList pFC_GetFunctionList; /* FIPSMode */
   1879    CK_FUNCTION_LIST_PTR pFC_FunctionList;
   1880    CK_SLOT_ID *pFC_SlotList = NULL;
   1881    CK_ULONG slotID_FC = 0;
   1882    CK_RV crv = CKR_OK;
   1883    CK_SESSION_HANDLE hSession;
   1884    int origMode = MODE; /* remember the orginal MODE value */
   1885 
   1886    NUMTESTS++; /* increment NUMTESTS */
   1887    MODE = NONFIPSMODE;
   1888 #ifdef _WIN32
   1889    /* NON FIPS mode  == C_GetFunctionList */
   1890    pC_GetFunctionList = (CK_C_GetFunctionList)
   1891        GetProcAddress(hModule, "C_GetFunctionList");
   1892    if (pC_GetFunctionList == NULL) {
   1893        PKM_Error("cannot load %s\n", LIB_NAME);
   1894        return crv;
   1895    }
   1896 #else
   1897    pC_GetFunctionList = (CK_C_GetFunctionList)PR_FindFunctionSymbol(lib,
   1898                                                                     "C_GetFunctionList");
   1899    assert(pC_GetFunctionList != NULL);
   1900 #endif
   1901    PKM_LogIt("loading C_GetFunctionList for Non FIPS Mode; slotID %d \n",
   1902              slotID_C);
   1903    crv = (*pC_GetFunctionList)(&pC_FunctionList);
   1904    assert(crv == CKR_OK);
   1905 
   1906    /* invoke C_Initialize as pC_FunctionList->C_Initialize */
   1907    crv = pC_FunctionList->C_Initialize(initArgs);
   1908    if (crv == CKR_OK) {
   1909        PKM_LogIt("C_Initialize succeeded\n");
   1910    } else {
   1911        PKM_Error("C_Initialize failed with 0x%08X, %-26s\n", crv,
   1912                  PKM_CK_RVtoStr(crv));
   1913        return crv;
   1914    }
   1915 
   1916    pC_SlotList = PKM_GetSlotList(pC_FunctionList, slotID_C);
   1917    if (pC_SlotList == NULL) {
   1918        PKM_Error("PKM_GetSlotList failed with \n");
   1919        return crv;
   1920    }
   1921    crv = pC_FunctionList->C_OpenSession(pC_SlotList[slotID_C],
   1922                                         CKF_SERIAL_SESSION,
   1923                                         NULL, NULL, &hSession);
   1924    if (crv == CKR_OK) {
   1925        PKM_LogIt("NONFIPS C_OpenSession succeeded\n");
   1926    } else {
   1927        PKM_Error("C_OpenSession failed for NONFIPS token "
   1928                  "with 0x%08X, %-26s\n",
   1929                  crv, PKM_CK_RVtoStr(crv));
   1930        return crv;
   1931    }
   1932 
   1933    crv = pC_FunctionList->C_Login(hSession, CKU_USER, pwd, pwdLen);
   1934    if (crv == CKR_OK) {
   1935        PKM_LogIt("able to login in NONFIPS token\n");
   1936    } else {
   1937        PKM_Error("Unable to login in to NONFIPS token "
   1938                  "with 0x%08X, %-26s\n",
   1939                  crv, PKM_CK_RVtoStr(crv));
   1940        return crv;
   1941    }
   1942 
   1943    crv = pC_FunctionList->C_Logout(hSession);
   1944    if (crv == CKR_OK) {
   1945        PKM_LogIt("C_Logout succeeded\n");
   1946    } else {
   1947        PKM_Error("C_Logout failed with 0x%08X, %-26s\n", crv,
   1948                  PKM_CK_RVtoStr(crv));
   1949        return crv;
   1950    }
   1951 
   1952    PKM_ShowInfo(pC_FunctionList, slotID_C);
   1953    MODE = HYBRIDMODE;
   1954 
   1955    /* Now load the FIPS token */
   1956    /* FIPS mode == FC_GetFunctionList */
   1957    pFC_GetFunctionList = NULL;
   1958 #ifdef _WIN32
   1959    pFC_GetFunctionList = (CK_C_GetFunctionList)
   1960        GetProcAddress(hModule, "FC_GetFunctionList");
   1961 #else
   1962    pFC_GetFunctionList = (CK_C_GetFunctionList)PR_FindFunctionSymbol(lib,
   1963                                                                      "FC_GetFunctionList");
   1964    assert(pFC_GetFunctionList != NULL);
   1965 #endif
   1966 
   1967    PKM_LogIt("loading FC_GetFunctionList for FIPS Mode; slotID %d \n",
   1968              slotID_FC);
   1969    PKM_LogIt("pFC_FunctionList->C_Foo == pFC_FunctionList->FC_Foo\n");
   1970    if (pFC_GetFunctionList == NULL) {
   1971        PKM_Error("unable to load pFC_GetFunctionList\n");
   1972        return crv;
   1973    }
   1974 
   1975    crv = (*pFC_GetFunctionList)(&pFC_FunctionList);
   1976    assert(crv == CKR_OK);
   1977 
   1978    /* invoke FC_Initialize as pFunctionList->C_Initialize */
   1979    crv = pFC_FunctionList->C_Initialize(initArgs);
   1980    if (crv == CKR_OK) {
   1981        PKM_LogIt("FC_Initialize succeeded\n");
   1982    } else {
   1983        PKM_Error("FC_Initialize failed with 0x%08X, %-26s\n", crv,
   1984                  PKM_CK_RVtoStr(crv));
   1985        return crv;
   1986    }
   1987    PKM_ShowInfo(pFC_FunctionList, slotID_FC);
   1988 
   1989    pFC_SlotList = PKM_GetSlotList(pFC_FunctionList, slotID_FC);
   1990    if (pFC_SlotList == NULL) {
   1991        PKM_Error("PKM_GetSlotList failed with \n");
   1992        return crv;
   1993    }
   1994 
   1995    crv = pC_FunctionList->C_Login(hSession, CKU_USER, pwd, pwdLen);
   1996    if (crv != CKR_OK) {
   1997        PKM_LogIt("NONFIPS token cannot log in when FIPS token is loaded\n");
   1998    } else {
   1999        PKM_Error("Able to login in to NONFIPS token\n");
   2000        return crv;
   2001    }
   2002    crv = pC_FunctionList->C_CloseSession(hSession);
   2003    if (crv == CKR_OK) {
   2004        PKM_LogIt("NONFIPS pC_CloseSession succeeded\n");
   2005    } else {
   2006        PKM_Error("pC_CloseSession failed for NONFIPS token "
   2007                  "with 0x%08X, %-26s\n",
   2008                  crv, PKM_CK_RVtoStr(crv));
   2009        return crv;
   2010    }
   2011 
   2012    PKM_LogIt("The module is FIPS 140-2 compliant\n"
   2013              "only when the NONFIPS Approved mode is inactive by \n"
   2014              "calling C_Finalize on the NONFIPS token.\n");
   2015 
   2016    /* to go in FIPSMODE you must Finalize the NONFIPS mode pointer */
   2017    crv = pC_FunctionList->C_Finalize(NULL);
   2018    if (crv == CKR_OK) {
   2019        PKM_LogIt("C_Finalize of NONFIPS Token succeeded\n");
   2020        MODE = FIPSMODE;
   2021    } else {
   2022        PKM_Error("C_Finalize of NONFIPS Token failed with "
   2023                  "0x%08X, %-26s\n",
   2024                  crv,
   2025                  PKM_CK_RVtoStr(crv));
   2026        return crv;
   2027    }
   2028 
   2029    PKM_LogIt("*** In FIPS mode!  ***\n");
   2030 
   2031    /* could do some operations in FIPS MODE */
   2032 
   2033    crv = pFC_FunctionList->C_Finalize(NULL);
   2034    if (crv == CKR_OK) {
   2035        PKM_LogIt("Exiting FIPSMODE by caling FC_Finalize.\n");
   2036        MODE = NOMODE;
   2037    } else {
   2038        PKM_Error("FC_Finalize failed with 0x%08X, %-26s\n", crv,
   2039                  PKM_CK_RVtoStr(crv));
   2040        return crv;
   2041    }
   2042 
   2043    if (pC_SlotList)
   2044        free(pC_SlotList);
   2045    if (pFC_SlotList)
   2046        free(pFC_SlotList);
   2047 
   2048    MODE = origMode; /* set the mode back to the orginal Mode value */
   2049    PKM_LogIt("PKM_HybridMode test Completed\n\n");
   2050    return crv;
   2051 }
   2052 
   2053 CK_RV
   2054 PKM_Mechanism(CK_FUNCTION_LIST_PTR pFunctionList,
   2055              CK_SLOT_ID *pSlotList, CK_ULONG slotID)
   2056 {
   2057 
   2058    CK_RV crv = CKR_OK;
   2059    CK_MECHANISM_TYPE *pMechanismList;
   2060    CK_ULONG mechanismCount;
   2061    CK_ULONG i;
   2062    const char *mechName = NULL;
   2063 
   2064    NUMTESTS++; /* increment NUMTESTS */
   2065 
   2066    /* Get the mechanism list */
   2067    crv = pFunctionList->C_GetMechanismList(pSlotList[slotID],
   2068                                            NULL, &mechanismCount);
   2069    if (crv != CKR_OK) {
   2070        PKM_Error("C_GetMechanismList failed with 0x%08X, %-26s\n", crv,
   2071                  PKM_CK_RVtoStr(crv));
   2072        return crv;
   2073    }
   2074    PKM_LogIt("C_GetMechanismList reported there are %lu mechanisms\n",
   2075              mechanismCount);
   2076    pMechanismList = (CK_MECHANISM_TYPE *)
   2077        malloc(mechanismCount * sizeof(CK_MECHANISM_TYPE));
   2078    if (!pMechanismList) {
   2079        PKM_Error("failed to allocate mechanism list\n");
   2080        return crv;
   2081    }
   2082    crv = pFunctionList->C_GetMechanismList(pSlotList[slotID],
   2083                                            pMechanismList, &mechanismCount);
   2084    if (crv != CKR_OK) {
   2085        PKM_Error("C_GetMechanismList failed with 0x%08X, %-26s\n", crv,
   2086                  PKM_CK_RVtoStr(crv));
   2087        return crv;
   2088    }
   2089    PKM_LogIt("C_GetMechanismList returned the mechanism types:\n");
   2090    if (verbose) {
   2091        for (i = 0; i < mechanismCount; i++) {
   2092            mechName = getName(pMechanismList[(i)], ConstMechanism);
   2093 
   2094            /* output two mechanism name on each line */
   2095            /* currently the longest known mechansim name length is 37 */
   2096            if (mechName) {
   2097                printf("%-40s", mechName);
   2098            } else {
   2099                printf("Unknown mechanism: 0x%08lX ", pMechanismList[i]);
   2100            }
   2101            if ((i % 2) == 1)
   2102                printf("\n");
   2103        }
   2104        printf("\n\n");
   2105    }
   2106 
   2107    for (i = 0; i < mechanismCount; i++) {
   2108        CK_MECHANISM_INFO minfo;
   2109 
   2110        memset(&minfo, 0, sizeof(CK_MECHANISM_INFO));
   2111        crv = pFunctionList->C_GetMechanismInfo(pSlotList[slotID],
   2112                                                pMechanismList[i], &minfo);
   2113        if (CKR_OK != crv) {
   2114            PKM_Error("C_GetMechanismInfo(%lu, %lu) returned 0x%08X, %-26s\n",
   2115                      pSlotList[slotID], pMechanismList[i], crv,
   2116                      PKM_CK_RVtoStr(crv));
   2117            return crv;
   2118        }
   2119 
   2120        mechName = getName(pMechanismList[i], ConstMechanism);
   2121        if (!mechName)
   2122            mechName = "Unknown mechanism";
   2123        PKM_LogIt("    [%lu]: CK_MECHANISM_TYPE = %s 0x%08lX\n", (i + 1),
   2124                  mechName,
   2125                  pMechanismList[i]);
   2126        PKM_LogIt("    ulMinKeySize = %lu\n", minfo.ulMinKeySize);
   2127        PKM_LogIt("    ulMaxKeySize = %lu\n", minfo.ulMaxKeySize);
   2128        PKM_LogIt("    flags = 0x%08x\n", minfo.flags);
   2129        PKM_LogIt("        -> HW = %s\n", minfo.flags & CKF_HW ? "TRUE" : "FALSE");
   2130        PKM_LogIt("        -> ENCRYPT = %s\n", minfo.flags & CKF_ENCRYPT ? "TRUE" : "FALSE");
   2131        PKM_LogIt("        -> DECRYPT = %s\n", minfo.flags & CKF_DECRYPT ? "TRUE" : "FALSE");
   2132        PKM_LogIt("        -> DIGEST = %s\n", minfo.flags & CKF_DIGEST ? "TRUE" : "FALSE");
   2133        PKM_LogIt("        -> SIGN = %s\n", minfo.flags & CKF_SIGN ? "TRUE" : "FALSE");
   2134        PKM_LogIt("        -> SIGN_RECOVER = %s\n", minfo.flags & CKF_SIGN_RECOVER ? "TRUE" : "FALSE");
   2135        PKM_LogIt("        -> VERIFY = %s\n", minfo.flags & CKF_VERIFY ? "TRUE" : "FALSE");
   2136        PKM_LogIt("        -> VERIFY_RECOVER = %s\n",
   2137                  minfo.flags & CKF_VERIFY_RECOVER ? "TRUE" : "FALSE");
   2138        PKM_LogIt("        -> GENERATE = %s\n", minfo.flags & CKF_GENERATE ? "TRUE" : "FALSE");
   2139        PKM_LogIt("        -> GENERATE_KEY_PAIR = %s\n",
   2140                  minfo.flags & CKF_GENERATE_KEY_PAIR ? "TRUE" : "FALSE");
   2141        PKM_LogIt("        -> WRAP = %s\n", minfo.flags & CKF_WRAP ? "TRUE" : "FALSE");
   2142        PKM_LogIt("        -> UNWRAP = %s\n", minfo.flags & CKF_UNWRAP ? "TRUE" : "FALSE");
   2143        PKM_LogIt("        -> DERIVE = %s\n", minfo.flags & CKF_DERIVE ? "TRUE" : "FALSE");
   2144        PKM_LogIt("        -> EXTENSION = %s\n", minfo.flags & CKF_EXTENSION ? "TRUE" : "FALSE");
   2145 
   2146        PKM_LogIt("\n");
   2147    }
   2148 
   2149    return crv;
   2150 }
   2151 
   2152 CK_RV
   2153 PKM_RNG(CK_FUNCTION_LIST_PTR pFunctionList, CK_SLOT_ID *pSlotList,
   2154        CK_ULONG slotID)
   2155 {
   2156    CK_SESSION_HANDLE hSession;
   2157    CK_RV crv = CKR_OK;
   2158    CK_BYTE randomData[16];
   2159    CK_BYTE seed[] = { 0x01, 0x03, 0x35, 0x55, 0xFF };
   2160 
   2161    NUMTESTS++; /* increment NUMTESTS */
   2162 
   2163    crv = pFunctionList->C_OpenSession(pSlotList[slotID], CKF_SERIAL_SESSION,
   2164                                       NULL, NULL, &hSession);
   2165    if (crv != CKR_OK) {
   2166        PKM_Error("C_OpenSession failed with 0x%08X, %-26s\n", crv,
   2167                  PKM_CK_RVtoStr(crv));
   2168        return crv;
   2169    }
   2170 
   2171    crv = pFunctionList->C_GenerateRandom(hSession,
   2172                                          randomData, sizeof randomData);
   2173    if (crv == CKR_OK) {
   2174        PKM_LogIt("C_GenerateRandom without login succeeded\n");
   2175    } else {
   2176        PKM_Error("C_GenerateRandom without login failed "
   2177                  "with 0x%08X, %-26s\n",
   2178                  crv, PKM_CK_RVtoStr(crv));
   2179        return crv;
   2180    }
   2181    crv = pFunctionList->C_SeedRandom(hSession, seed, sizeof(seed));
   2182    if (crv == CKR_OK) {
   2183        PKM_LogIt("C_SeedRandom without login succeeded\n");
   2184    } else {
   2185        PKM_Error("C_SeedRandom without login failed "
   2186                  "with 0x%08X, %-26s\n",
   2187                  crv, PKM_CK_RVtoStr(crv));
   2188        return crv;
   2189    }
   2190    crv = pFunctionList->C_GenerateRandom(hSession,
   2191                                          randomData, sizeof randomData);
   2192    if (crv == CKR_OK) {
   2193        PKM_LogIt("C_GenerateRandom without login succeeded\n");
   2194    } else {
   2195        PKM_Error("C_GenerateRandom without login failed "
   2196                  "with 0x%08X, %-26s\n",
   2197                  crv, PKM_CK_RVtoStr(crv));
   2198        return crv;
   2199    }
   2200    crv = pFunctionList->C_CloseSession(hSession);
   2201    if (crv != CKR_OK) {
   2202        PKM_Error("C_CloseSession failed with 0x%08X, %-26s\n", crv,
   2203                  PKM_CK_RVtoStr(crv));
   2204        return crv;
   2205    }
   2206 
   2207    return crv;
   2208 }
   2209 
   2210 CK_RV
   2211 PKM_SessionLogin(CK_FUNCTION_LIST_PTR pFunctionList,
   2212                 CK_SLOT_ID *pSlotList, CK_ULONG slotID,
   2213                 CK_UTF8CHAR_PTR pwd, CK_ULONG pwdLen)
   2214 {
   2215    CK_SESSION_HANDLE hSession;
   2216    CK_RV crv = CKR_OK;
   2217 
   2218    NUMTESTS++; /* increment NUMTESTS */
   2219 
   2220    crv = pFunctionList->C_OpenSession(pSlotList[slotID], CKF_SERIAL_SESSION,
   2221                                       NULL, NULL, &hSession);
   2222    if (crv != CKR_OK) {
   2223        PKM_Error("C_OpenSession failed with 0x%08X, %-26s\n", crv,
   2224                  PKM_CK_RVtoStr(crv));
   2225        return crv;
   2226    }
   2227 
   2228    crv = pFunctionList->C_Login(hSession, CKU_USER, (unsigned char *)"netscape", 8);
   2229    if (crv == CKR_OK) {
   2230        PKM_Error("C_Login with wrong password succeeded\n");
   2231        return CKR_FUNCTION_FAILED;
   2232    } else {
   2233        PKM_LogIt("As expected C_Login with wrong password returned 0x%08X, "
   2234                  "%-26s.\n ",
   2235                  crv, PKM_CK_RVtoStr(crv));
   2236    }
   2237    crv = pFunctionList->C_Login(hSession, CKU_USER, (unsigned char *)"red hat", 7);
   2238    if (crv == CKR_OK) {
   2239        PKM_Error("C_Login with wrong password succeeded\n");
   2240        return CKR_FUNCTION_FAILED;
   2241    } else {
   2242        PKM_LogIt("As expected C_Login with wrong password returned 0x%08X, "
   2243                  "%-26s.\n ",
   2244                  crv, PKM_CK_RVtoStr(crv));
   2245    }
   2246    crv = pFunctionList->C_Login(hSession, CKU_USER,
   2247                                 (unsigned char *)"sun", 3);
   2248    if (crv == CKR_OK) {
   2249        PKM_Error("C_Login with wrong password succeeded\n");
   2250        return CKR_FUNCTION_FAILED;
   2251    } else {
   2252        PKM_LogIt("As expected C_Login with wrong password returned 0x%08X, "
   2253                  "%-26s.\n ",
   2254                  crv, PKM_CK_RVtoStr(crv));
   2255    }
   2256    crv = pFunctionList->C_Login(hSession, CKU_USER, pwd, pwdLen);
   2257    if (crv == CKR_OK) {
   2258        PKM_LogIt("C_Login with correct password succeeded\n");
   2259    } else {
   2260        PKM_Error("C_Login with correct password failed "
   2261                  "with 0x%08X, %-26s\n",
   2262                  crv, PKM_CK_RVtoStr(crv));
   2263        return crv;
   2264    }
   2265 
   2266    crv = pFunctionList->C_Logout(hSession);
   2267    if (crv == CKR_OK) {
   2268        PKM_LogIt("C_Logout succeeded\n");
   2269    } else {
   2270        PKM_Error("C_Logout failed with 0x%08X, %-26s\n", crv,
   2271                  PKM_CK_RVtoStr(crv));
   2272        return crv;
   2273    }
   2274 
   2275    crv = pFunctionList->C_CloseSession(hSession);
   2276    if (crv != CKR_OK) {
   2277        PKM_Error("C_CloseSession failed with 0x%08X, %-26s\n", crv,
   2278                  PKM_CK_RVtoStr(crv));
   2279        return crv;
   2280    }
   2281 
   2282    return crv;
   2283 }
   2284 
   2285 /*
   2286 * PKM_LegacyFunctions
   2287 *
   2288 * Legacyfunctions exist only for backwards compatibility.
   2289 * C_GetFunctionStatus and C_CancelFunction functions were
   2290 * meant for managing parallel execution of cryptographic functions.
   2291 *
   2292 * C_GetFunctionStatus is a legacy function which should simply return
   2293 * the value CKR_FUNCTION_NOT_PARALLEL.
   2294 *
   2295 * C_CancelFunction is a legacy function which should simply return the
   2296 * value CKR_FUNCTION_NOT_PARALLEL.
   2297 *
   2298 */
   2299 CK_RV
   2300 PKM_LegacyFunctions(CK_FUNCTION_LIST_PTR pFunctionList,
   2301                    CK_SLOT_ID *pSlotList, CK_ULONG slotID,
   2302                    CK_UTF8CHAR_PTR pwd, CK_ULONG pwdLen)
   2303 {
   2304    CK_SESSION_HANDLE hSession;
   2305    CK_RV crv = CKR_OK;
   2306    NUMTESTS++; /* increment NUMTESTS */
   2307 
   2308    crv = pFunctionList->C_OpenSession(pSlotList[slotID], CKF_SERIAL_SESSION,
   2309                                       NULL, NULL, &hSession);
   2310    if (crv != CKR_OK) {
   2311        PKM_Error("C_OpenSession failed with 0x%08X, %-26s\n", crv,
   2312                  PKM_CK_RVtoStr(crv));
   2313        return crv;
   2314    }
   2315 
   2316    crv = pFunctionList->C_Login(hSession, CKU_USER, pwd, pwdLen);
   2317    if (crv == CKR_OK) {
   2318        PKM_LogIt("C_Login with correct password succeeded\n");
   2319    } else {
   2320        PKM_Error("C_Login with correct password failed "
   2321                  "with 0x%08X, %-26s\n",
   2322                  crv, PKM_CK_RVtoStr(crv));
   2323        return crv;
   2324    }
   2325 
   2326    crv = pFunctionList->C_GetFunctionStatus(hSession);
   2327    if (crv == CKR_FUNCTION_NOT_PARALLEL) {
   2328        PKM_LogIt("C_GetFunctionStatus correctly"
   2329                  "returned CKR_FUNCTION_NOT_PARALLEL \n");
   2330    } else {
   2331        PKM_Error("C_GetFunctionStatus failed "
   2332                  "with 0x%08X, %-26s\n",
   2333                  crv, PKM_CK_RVtoStr(crv));
   2334        return crv;
   2335    }
   2336 
   2337    crv = pFunctionList->C_CancelFunction(hSession);
   2338    if (crv == CKR_FUNCTION_NOT_PARALLEL) {
   2339        PKM_LogIt("C_CancelFunction correctly "
   2340                  "returned CKR_FUNCTION_NOT_PARALLEL \n");
   2341    } else {
   2342        PKM_Error("C_CancelFunction failed "
   2343                  "with 0x%08X, %-26s\n",
   2344                  crv, PKM_CK_RVtoStr(crv));
   2345        return crv;
   2346    }
   2347 
   2348    crv = pFunctionList->C_Logout(hSession);
   2349    if (crv == CKR_OK) {
   2350        PKM_LogIt("C_Logout succeeded\n");
   2351    } else {
   2352        PKM_Error("C_Logout failed with 0x%08X, %-26s\n", crv,
   2353                  PKM_CK_RVtoStr(crv));
   2354        return crv;
   2355    }
   2356 
   2357    crv = pFunctionList->C_CloseSession(hSession);
   2358    if (crv != CKR_OK) {
   2359        PKM_Error("C_CloseSession failed with 0x%08X, %-26s\n", crv,
   2360                  PKM_CK_RVtoStr(crv));
   2361        return crv;
   2362    }
   2363 
   2364    return crv;
   2365 }
   2366 
   2367 /*
   2368 *  PKM_DualFuncDigest - demostrates the Dual-function
   2369 *  cryptograpic functions:
   2370 *
   2371 *   C_DigestEncryptUpdate - multi-part Digest and Encrypt
   2372 *   C_DecryptDigestUpdate - multi-part Decrypt and Digest
   2373 *
   2374 *
   2375 */
   2376 
   2377 CK_RV
   2378 PKM_DualFuncDigest(CK_FUNCTION_LIST_PTR pFunctionList,
   2379                   CK_SESSION_HANDLE hSession,
   2380                   CK_OBJECT_HANDLE hSecKey, CK_MECHANISM *cryptMech,
   2381                   CK_OBJECT_HANDLE hSecKeyDigest,
   2382                   CK_MECHANISM *digestMech,
   2383                   const CK_BYTE *pData, CK_ULONG pDataLen)
   2384 {
   2385    CK_RV crv = CKR_OK;
   2386    CK_BYTE eDigest[MAX_DIGEST_SZ];
   2387    CK_BYTE dDigest[MAX_DIGEST_SZ];
   2388    CK_ULONG ulDigestLen;
   2389    CK_BYTE ciphertext[MAX_CIPHER_SZ];
   2390    CK_ULONG ciphertextLen, lastLen;
   2391    CK_BYTE plaintext[MAX_DATA_SZ];
   2392    CK_ULONG plaintextLen;
   2393    unsigned int i;
   2394 
   2395    memset(eDigest, 0, sizeof(eDigest));
   2396    memset(dDigest, 0, sizeof(dDigest));
   2397    memset(ciphertext, 0, sizeof(ciphertext));
   2398    memset(plaintext, 0, sizeof(plaintext));
   2399 
   2400    NUMTESTS++; /* increment NUMTESTS */
   2401 
   2402    /*
   2403     * First init the Digest and Ecrypt operations
   2404     */
   2405    crv = pFunctionList->C_EncryptInit(hSession, cryptMech, hSecKey);
   2406    if (crv != CKR_OK) {
   2407        PKM_Error("C_EncryptInit failed with 0x%08X, %-26s\n", crv,
   2408                  PKM_CK_RVtoStr(crv));
   2409        return crv;
   2410    }
   2411    crv = pFunctionList->C_DigestInit(hSession, digestMech);
   2412    if (crv != CKR_OK) {
   2413        PKM_Error("C_DigestInit failed with 0x%08X, %-26s\n", crv,
   2414                  PKM_CK_RVtoStr(crv));
   2415        return crv;
   2416    }
   2417 
   2418    ciphertextLen = sizeof(ciphertext);
   2419    crv = pFunctionList->C_DigestEncryptUpdate(hSession, (CK_BYTE *)pData,
   2420                                               pDataLen,
   2421                                               ciphertext, &ciphertextLen);
   2422    if (crv != CKR_OK) {
   2423        PKM_Error("C_DigestEncryptUpdate failed with 0x%08X, %-26s\n", crv,
   2424                  PKM_CK_RVtoStr(crv));
   2425        return crv;
   2426    }
   2427 
   2428    ulDigestLen = sizeof(eDigest);
   2429    crv = pFunctionList->C_DigestFinal(hSession, eDigest, &ulDigestLen);
   2430    if (crv != CKR_OK) {
   2431        PKM_Error("C_DigestFinal failed with 0x%08X, %-26s\n", crv,
   2432                  PKM_CK_RVtoStr(crv));
   2433        return crv;
   2434    }
   2435 
   2436    /* get the last piece of ciphertext (length should be 0 */
   2437    lastLen = sizeof(ciphertext) - ciphertextLen;
   2438    crv = pFunctionList->C_EncryptFinal(hSession,
   2439                                        (CK_BYTE *)&ciphertext[ciphertextLen],
   2440                                        &lastLen);
   2441    if (crv != CKR_OK) {
   2442        PKM_Error("C_EncryptFinal failed with 0x%08X, %-26s\n", crv,
   2443                  PKM_CK_RVtoStr(crv));
   2444        return crv;
   2445    }
   2446    ciphertextLen = ciphertextLen + lastLen;
   2447    if (verbose) {
   2448        printf("ciphertext = ");
   2449        for (i = 0; i < ciphertextLen; i++) {
   2450            printf("%02x", (unsigned)ciphertext[i]);
   2451        }
   2452        printf("\n");
   2453        printf("eDigest = ");
   2454        for (i = 0; i < ulDigestLen; i++) {
   2455            printf("%02x", (unsigned)eDigest[i]);
   2456        }
   2457        printf("\n");
   2458    }
   2459 
   2460    /* Decrypt the text */
   2461    crv = pFunctionList->C_DecryptInit(hSession, cryptMech, hSecKey);
   2462    if (crv != CKR_OK) {
   2463        PKM_Error("C_DecryptInit failed with 0x%08X, %-26s\n", crv,
   2464                  PKM_CK_RVtoStr(crv));
   2465        return crv;
   2466    }
   2467    crv = pFunctionList->C_DigestInit(hSession, digestMech);
   2468    if (crv != CKR_OK) {
   2469        PKM_Error("C_DecryptInit failed with 0x%08X, %-26s\n", crv,
   2470                  PKM_CK_RVtoStr(crv));
   2471        return crv;
   2472    }
   2473 
   2474    plaintextLen = sizeof(plaintext);
   2475    crv = pFunctionList->C_DecryptDigestUpdate(hSession, ciphertext,
   2476                                               ciphertextLen,
   2477                                               plaintext,
   2478                                               &plaintextLen);
   2479    if (crv != CKR_OK) {
   2480        PKM_Error("C_DecryptDigestUpdate failed with 0x%08X, %-26s\n", crv,
   2481                  PKM_CK_RVtoStr(crv));
   2482        return crv;
   2483    }
   2484    lastLen = sizeof(plaintext) - plaintextLen;
   2485 
   2486    crv = pFunctionList->C_DecryptFinal(hSession,
   2487                                        (CK_BYTE *)&plaintext[plaintextLen],
   2488                                        &lastLen);
   2489    if (crv != CKR_OK) {
   2490        PKM_Error("C_DecryptFinal failed with 0x%08X, %-26s\n", crv,
   2491                  PKM_CK_RVtoStr(crv));
   2492        return crv;
   2493    }
   2494    plaintextLen = plaintextLen + lastLen;
   2495 
   2496    ulDigestLen = sizeof(dDigest);
   2497    crv = pFunctionList->C_DigestFinal(hSession, dDigest, &ulDigestLen);
   2498    if (crv != CKR_OK) {
   2499        PKM_Error("C_DigestFinal failed with 0x%08X, %-26s\n", crv,
   2500                  PKM_CK_RVtoStr(crv));
   2501        return crv;
   2502    }
   2503 
   2504    if (plaintextLen != pDataLen) {
   2505        PKM_Error("plaintextLen is %lu\n", plaintextLen);
   2506        return crv;
   2507    }
   2508 
   2509    if (verbose) {
   2510        printf("plaintext = ");
   2511        for (i = 0; i < plaintextLen; i++) {
   2512            printf("%02x", (unsigned)plaintext[i]);
   2513        }
   2514        printf("\n");
   2515        printf("dDigest = ");
   2516        for (i = 0; i < ulDigestLen; i++) {
   2517            printf("%02x", (unsigned)dDigest[i]);
   2518        }
   2519        printf("\n");
   2520    }
   2521 
   2522    if (memcmp(eDigest, dDigest, ulDigestLen) == 0) {
   2523        PKM_LogIt("Encrypted Digest equals Decrypted Digest\n");
   2524    } else {
   2525        PKM_Error("Digests don't match\n");
   2526    }
   2527 
   2528    if ((plaintextLen == pDataLen) &&
   2529        (memcmp(plaintext, pData, pDataLen)) == 0) {
   2530        PKM_LogIt("DualFuncDigest decrypt test case passed\n");
   2531    } else {
   2532        PKM_Error("DualFuncDigest derypt test case failed\n");
   2533    }
   2534 
   2535    return crv;
   2536 }
   2537 
   2538 /*
   2539 * PKM_SecKeyCrypt - Symmetric key encrypt/decyprt
   2540 *
   2541 */
   2542 
   2543 CK_RV
   2544 PKM_SecKeyCrypt(CK_FUNCTION_LIST_PTR pFunctionList,
   2545                CK_SESSION_HANDLE hSession,
   2546                CK_OBJECT_HANDLE hSymKey, CK_MECHANISM *cryptMech,
   2547                const CK_BYTE *pData, CK_ULONG dataLen)
   2548 {
   2549    CK_RV crv = CKR_OK;
   2550 
   2551    CK_BYTE cipher1[MAX_CIPHER_SZ];
   2552    CK_BYTE cipher2[MAX_CIPHER_SZ];
   2553    CK_BYTE data1[MAX_DATA_SZ];
   2554    CK_BYTE data2[MAX_DATA_SZ];
   2555    CK_ULONG cipher1Len = 0, cipher2Len = 0, lastLen = 0;
   2556    CK_ULONG data1Len = 0, data2Len = 0;
   2557 
   2558    NUMTESTS++; /* increment NUMTESTS */
   2559 
   2560    memset(cipher1, 0, sizeof(cipher1));
   2561    memset(cipher2, 0, sizeof(cipher2));
   2562    memset(data1, 0, sizeof(data1));
   2563    memset(data2, 0, sizeof(data2));
   2564 
   2565    /* C_Encrypt */
   2566    crv = pFunctionList->C_EncryptInit(hSession, cryptMech, hSymKey);
   2567    if (crv != CKR_OK) {
   2568        PKM_Error("C_EncryptInit failed with 0x%08X, %-26s\n", crv,
   2569                  PKM_CK_RVtoStr(crv));
   2570        return crv;
   2571    }
   2572    cipher1Len = sizeof(cipher1);
   2573    crv = pFunctionList->C_Encrypt(hSession, (CK_BYTE *)pData, dataLen,
   2574                                   cipher1, &cipher1Len);
   2575    if (crv != CKR_OK) {
   2576        PKM_Error("C_Encrypt failed with 0x%08X, %-26s\n", crv,
   2577                  PKM_CK_RVtoStr(crv));
   2578        return crv;
   2579    }
   2580 
   2581    /* C_EncryptUpdate */
   2582    crv = pFunctionList->C_EncryptInit(hSession, cryptMech, hSymKey);
   2583    if (crv != CKR_OK) {
   2584        PKM_Error("C_EncryptInit failed with 0x%08X, %-26s\n", crv,
   2585                  PKM_CK_RVtoStr(crv));
   2586        return crv;
   2587    }
   2588    cipher2Len = sizeof(cipher2);
   2589    crv = pFunctionList->C_EncryptUpdate(hSession, (CK_BYTE *)pData,
   2590                                         dataLen,
   2591                                         cipher2, &cipher2Len);
   2592    if (crv != CKR_OK) {
   2593        PKM_Error("C_EncryptUpdate failed with 0x%08X, %-26s\n", crv,
   2594                  PKM_CK_RVtoStr(crv));
   2595        return crv;
   2596    }
   2597    lastLen = sizeof(cipher2) - cipher2Len;
   2598 
   2599    crv = pFunctionList->C_EncryptFinal(hSession,
   2600                                        (CK_BYTE *)&cipher2[cipher2Len],
   2601                                        &lastLen);
   2602    cipher2Len = cipher2Len + lastLen;
   2603 
   2604    if ((cipher1Len == cipher2Len) &&
   2605        (memcmp(cipher1, cipher2, sizeof(cipher1Len)) == 0)) {
   2606        PKM_LogIt("encrypt test case passed\n");
   2607    } else {
   2608        PKM_Error("encrypt test case failed\n");
   2609        return CKR_GENERAL_ERROR;
   2610    }
   2611 
   2612    /* C_Decrypt */
   2613    crv = pFunctionList->C_DecryptInit(hSession, cryptMech, hSymKey);
   2614    if (crv != CKR_OK) {
   2615        PKM_Error("C_DecryptInit failed with 0x%08X, %-26s\n", crv,
   2616                  PKM_CK_RVtoStr(crv));
   2617        return crv;
   2618    }
   2619    data1Len = sizeof(data1);
   2620    crv = pFunctionList->C_Decrypt(hSession, cipher1, cipher1Len,
   2621                                   data1, &data1Len);
   2622    if (crv != CKR_OK) {
   2623        PKM_Error("C_DecryptInit failed with 0x%08X, %-26s\n", crv,
   2624                  PKM_CK_RVtoStr(crv));
   2625        return crv;
   2626    }
   2627    /* now use C_DecryptUpdate the text */
   2628    crv = pFunctionList->C_DecryptInit(hSession, cryptMech, hSymKey);
   2629    if (crv != CKR_OK) {
   2630        PKM_Error("C_DecryptInit failed with 0x%08X, %-26s\n", crv,
   2631                  PKM_CK_RVtoStr(crv));
   2632        return crv;
   2633    }
   2634    data2Len = sizeof(data2);
   2635    crv = pFunctionList->C_DecryptUpdate(hSession, cipher2,
   2636                                         cipher2Len,
   2637                                         data2, &data2Len);
   2638    if (crv != CKR_OK) {
   2639        PKM_Error("C_DecryptUpdate failed with 0x%08X, %-26s\n", crv,
   2640                  PKM_CK_RVtoStr(crv));
   2641        return crv;
   2642    }
   2643    lastLen = sizeof(data2) - data2Len;
   2644    crv = pFunctionList->C_DecryptFinal(hSession,
   2645                                        (CK_BYTE *)&data2[data2Len],
   2646                                        &lastLen);
   2647    if (crv != CKR_OK) {
   2648        PKM_Error("C_DecryptFinal failed with 0x%08X, %-26s\n", crv,
   2649                  PKM_CK_RVtoStr(crv));
   2650        return crv;
   2651    }
   2652    data2Len = data2Len + lastLen;
   2653 
   2654    /* Comparison of Decrypt data */
   2655 
   2656    if ((data1Len == data2Len) && (dataLen == data1Len) &&
   2657        (memcmp(data1, pData, dataLen) == 0) &&
   2658        (memcmp(data2, pData, dataLen) == 0)) {
   2659        PKM_LogIt("decrypt test case passed\n");
   2660    } else {
   2661        PKM_Error("derypt test case failed\n");
   2662    }
   2663 
   2664    return crv;
   2665 }
   2666 
   2667 CK_RV
   2668 PKM_SecretKey(CK_FUNCTION_LIST_PTR pFunctionList,
   2669              CK_SLOT_ID *pSlotList, CK_ULONG slotID,
   2670              CK_UTF8CHAR_PTR pwd, CK_ULONG pwdLen)
   2671 {
   2672    CK_SESSION_HANDLE hSession;
   2673    CK_RV crv = CKR_OK;
   2674    CK_MECHANISM sAESKeyMech = {
   2675        CKM_AES_KEY_GEN, NULL, 0
   2676    };
   2677    CK_OBJECT_CLASS class = CKO_SECRET_KEY;
   2678    CK_KEY_TYPE keyAESType = CKK_AES;
   2679    CK_UTF8CHAR AESlabel[] = "An AES secret key object";
   2680    CK_ULONG AESvalueLen = 16;
   2681    CK_ATTRIBUTE sAESKeyTemplate[9];
   2682    CK_OBJECT_HANDLE hKey = CK_INVALID_HANDLE;
   2683 
   2684    CK_BYTE KEY[16];
   2685    CK_BYTE IV[16];
   2686    static const CK_BYTE CIPHERTEXT[] = {
   2687        0x7e, 0x6a, 0x3f, 0x3b, 0x39, 0x3c, 0xf2, 0x4b,
   2688        0xce, 0xcc, 0x23, 0x6d, 0x80, 0xfd, 0xe0, 0xff
   2689    };
   2690    CK_BYTE ciphertext[64];
   2691    CK_BYTE ciphertext2[64];
   2692    CK_ULONG ciphertextLen, ciphertext2Len, lastLen;
   2693    CK_BYTE plaintext[32];
   2694    CK_BYTE plaintext2[32];
   2695    CK_ULONG plaintextLen, plaintext2Len;
   2696    CK_BYTE wrappedKey[16];
   2697    CK_ULONG wrappedKeyLen;
   2698    CK_MECHANISM aesEcbMech = {
   2699        CKM_AES_ECB, NULL, 0
   2700    };
   2701    CK_OBJECT_HANDLE hTestKey;
   2702    CK_MECHANISM mech_AES_CBC;
   2703 
   2704    NUMTESTS++; /* increment NUMTESTS */
   2705 
   2706    memset(ciphertext, 0, sizeof(ciphertext));
   2707    memset(ciphertext2, 0, sizeof(ciphertext2));
   2708    memset(IV, 0x00, sizeof(IV));
   2709    memset(KEY, 0x00, sizeof(KEY));
   2710 
   2711    mech_AES_CBC.mechanism = CKM_AES_CBC;
   2712    mech_AES_CBC.pParameter = IV;
   2713    mech_AES_CBC.ulParameterLen = sizeof(IV);
   2714 
   2715    /* AES key template */
   2716    sAESKeyTemplate[0].type = CKA_CLASS;
   2717    sAESKeyTemplate[0].pValue = &class;
   2718    sAESKeyTemplate[0].ulValueLen = sizeof(class);
   2719    sAESKeyTemplate[1].type = CKA_KEY_TYPE;
   2720    sAESKeyTemplate[1].pValue = &keyAESType;
   2721    sAESKeyTemplate[1].ulValueLen = sizeof(keyAESType);
   2722    sAESKeyTemplate[2].type = CKA_LABEL;
   2723    sAESKeyTemplate[2].pValue = AESlabel;
   2724    sAESKeyTemplate[2].ulValueLen = sizeof(AESlabel) - 1;
   2725    sAESKeyTemplate[3].type = CKA_ENCRYPT;
   2726    sAESKeyTemplate[3].pValue = &ck_true;
   2727    sAESKeyTemplate[3].ulValueLen = sizeof(ck_true);
   2728    sAESKeyTemplate[4].type = CKA_DECRYPT;
   2729    sAESKeyTemplate[4].pValue = &ck_true;
   2730    sAESKeyTemplate[4].ulValueLen = sizeof(ck_true);
   2731    sAESKeyTemplate[5].type = CKA_SIGN;
   2732    sAESKeyTemplate[5].pValue = &ck_true;
   2733    sAESKeyTemplate[5].ulValueLen = sizeof(ck_true);
   2734    sAESKeyTemplate[6].type = CKA_VERIFY;
   2735    sAESKeyTemplate[6].pValue = &ck_true;
   2736    sAESKeyTemplate[6].ulValueLen = sizeof(ck_true);
   2737    sAESKeyTemplate[7].type = CKA_UNWRAP;
   2738    sAESKeyTemplate[7].pValue = &ck_true;
   2739    sAESKeyTemplate[7].ulValueLen = sizeof(ck_true);
   2740    sAESKeyTemplate[8].type = CKA_VALUE_LEN;
   2741    sAESKeyTemplate[8].pValue = &AESvalueLen;
   2742    sAESKeyTemplate[8].ulValueLen = sizeof(AESvalueLen);
   2743 
   2744    crv = pFunctionList->C_OpenSession(pSlotList[slotID], CKF_SERIAL_SESSION,
   2745                                       NULL, NULL, &hSession);
   2746    if (crv != CKR_OK) {
   2747        PKM_Error("C_OpenSession failed with 0x%08X, %-26s\n", crv,
   2748                  PKM_CK_RVtoStr(crv));
   2749        return crv;
   2750    }
   2751 
   2752    crv = pFunctionList->C_Login(hSession, CKU_USER, pwd, pwdLen);
   2753    if (crv == CKR_OK) {
   2754        PKM_LogIt("C_Login with correct password succeeded\n");
   2755    } else {
   2756        PKM_Error("C_Login with correct password failed "
   2757                  "with 0x%08X, %-26s\n",
   2758                  crv, PKM_CK_RVtoStr(crv));
   2759        return crv;
   2760    }
   2761 
   2762    PKM_LogIt("Generate an AES key ... \n");
   2763    /* generate an AES Secret Key */
   2764    crv = pFunctionList->C_GenerateKey(hSession, &sAESKeyMech,
   2765                                       sAESKeyTemplate,
   2766                                       NUM_ELEM(sAESKeyTemplate),
   2767                                       &hKey);
   2768    if (crv == CKR_OK) {
   2769        PKM_LogIt("C_GenerateKey AES succeeded\n");
   2770    } else {
   2771        PKM_Error("C_GenerateKey AES failed with 0x%08X, %-26s\n",
   2772                  crv, PKM_CK_RVtoStr(crv));
   2773        return crv;
   2774    }
   2775 
   2776    crv = pFunctionList->C_EncryptInit(hSession, &aesEcbMech, hKey);
   2777    if (crv != CKR_OK) {
   2778        PKM_Error("C_EncryptInit failed with 0x%08X, %-26s\n", crv,
   2779                  PKM_CK_RVtoStr(crv));
   2780        return crv;
   2781    }
   2782    wrappedKeyLen = sizeof(wrappedKey);
   2783    crv = pFunctionList->C_Encrypt(hSession, KEY, sizeof(KEY),
   2784                                   wrappedKey, &wrappedKeyLen);
   2785    if (crv != CKR_OK) {
   2786        PKM_Error("C_Encrypt failed with 0x%08X, %-26s\n", crv,
   2787                  PKM_CK_RVtoStr(crv));
   2788        return crv;
   2789    }
   2790    if (wrappedKeyLen != sizeof(wrappedKey)) {
   2791        PKM_Error("wrappedKeyLen is %lu\n", wrappedKeyLen);
   2792        return crv;
   2793    }
   2794    /* Import an encrypted key */
   2795    crv = pFunctionList->C_UnwrapKey(hSession, &aesEcbMech, hKey,
   2796                                     wrappedKey, wrappedKeyLen,
   2797                                     sAESKeyTemplate,
   2798                                     NUM_ELEM(sAESKeyTemplate),
   2799                                     &hTestKey);
   2800    if (crv != CKR_OK) {
   2801        PKM_Error("C_UnwraPKey failed with 0x%08X, %-26s\n", crv,
   2802                  PKM_CK_RVtoStr(crv));
   2803        return crv;
   2804    }
   2805    /* AES Encrypt the text */
   2806    crv = pFunctionList->C_EncryptInit(hSession, &mech_AES_CBC, hTestKey);
   2807    if (crv != CKR_OK) {
   2808        PKM_Error("C_EncryptInit failed with 0x%08X, %-26s\n", crv,
   2809                  PKM_CK_RVtoStr(crv));
   2810        return crv;
   2811    }
   2812    ciphertextLen = sizeof(ciphertext);
   2813    crv = pFunctionList->C_Encrypt(hSession, (CK_BYTE *)PLAINTEXT,
   2814                                   sizeof(PLAINTEXT),
   2815                                   ciphertext, &ciphertextLen);
   2816    if (crv != CKR_OK) {
   2817        PKM_Error("C_Encrypt failed with 0x%08X, %-26s\n", crv,
   2818                  PKM_CK_RVtoStr(crv));
   2819        return crv;
   2820    }
   2821 
   2822    if ((ciphertextLen == sizeof(CIPHERTEXT)) &&
   2823        (memcmp(ciphertext, CIPHERTEXT, ciphertextLen) == 0)) {
   2824        PKM_LogIt("AES CBCVarKey128 encrypt test case 1 passed\n");
   2825    } else {
   2826        PKM_Error("AES CBCVarKey128 encrypt test case 1 failed\n");
   2827        return crv;
   2828    }
   2829 
   2830    /* now use EncryptUpdate the text */
   2831    crv = pFunctionList->C_EncryptInit(hSession, &mech_AES_CBC, hTestKey);
   2832    if (crv != CKR_OK) {
   2833        PKM_Error("C_EncryptInit failed with 0x%08X, %-26s\n", crv,
   2834                  PKM_CK_RVtoStr(crv));
   2835        return crv;
   2836    }
   2837    ciphertext2Len = sizeof(ciphertext2);
   2838    crv = pFunctionList->C_EncryptUpdate(hSession, (CK_BYTE *)PLAINTEXT,
   2839                                         sizeof(PLAINTEXT),
   2840                                         ciphertext2, &ciphertext2Len);
   2841    if (crv != CKR_OK) {
   2842        PKM_Error("C_EncryptUpdate failed with 0x%08X, %-26s\n", crv,
   2843                  PKM_CK_RVtoStr(crv));
   2844        return crv;
   2845    }
   2846    lastLen = sizeof(ciphertext2) - ciphertext2Len;
   2847 
   2848    crv = pFunctionList->C_EncryptFinal(hSession,
   2849                                        (CK_BYTE *)&ciphertext2[ciphertext2Len],
   2850                                        &lastLen);
   2851    ciphertext2Len = ciphertext2Len + lastLen;
   2852 
   2853    if ((ciphertextLen == ciphertext2Len) &&
   2854        (memcmp(ciphertext, ciphertext2, sizeof(CIPHERTEXT)) == 0) &&
   2855        (memcmp(ciphertext2, CIPHERTEXT, sizeof(CIPHERTEXT)) == 0)) {
   2856        PKM_LogIt("AES CBCVarKey128 encrypt test case 2 passed\n");
   2857    } else {
   2858        PKM_Error("AES CBCVarKey128 encrypt test case 2 failed\n");
   2859        return CKR_GENERAL_ERROR;
   2860    }
   2861 
   2862    /* AES CBC Decrypt the text */
   2863    crv = pFunctionList->C_DecryptInit(hSession, &mech_AES_CBC, hTestKey);
   2864    if (crv != CKR_OK) {
   2865        PKM_Error("C_DecryptInit failed with 0x%08X, %-26s\n", crv,
   2866                  PKM_CK_RVtoStr(crv));
   2867        return crv;
   2868    }
   2869    plaintextLen = sizeof(plaintext);
   2870    crv = pFunctionList->C_Decrypt(hSession, ciphertext, ciphertextLen,
   2871                                   plaintext, &plaintextLen);
   2872    if (crv != CKR_OK) {
   2873        PKM_Error("C_DecryptInit failed with 0x%08X, %-26s\n", crv,
   2874                  PKM_CK_RVtoStr(crv));
   2875        return crv;
   2876    }
   2877    if ((plaintextLen == sizeof(PLAINTEXT)) &&
   2878        (memcmp(plaintext, PLAINTEXT, plaintextLen) == 0)) {
   2879        PKM_LogIt("AES CBCVarKey128 decrypt test case 1 passed\n");
   2880    } else {
   2881        PKM_Error("AES CBCVarKey128 derypt test case 1 failed\n");
   2882    }
   2883    /* now use DecryptUpdate the text */
   2884    crv = pFunctionList->C_DecryptInit(hSession, &mech_AES_CBC, hTestKey);
   2885    if (crv != CKR_OK) {
   2886        PKM_Error("C_DecryptInit failed with 0x%08X, %-26s\n", crv,
   2887                  PKM_CK_RVtoStr(crv));
   2888        return crv;
   2889    }
   2890    plaintext2Len = sizeof(plaintext2);
   2891    crv = pFunctionList->C_DecryptUpdate(hSession, ciphertext2,
   2892                                         ciphertext2Len,
   2893                                         plaintext2, &plaintext2Len);
   2894    if (crv != CKR_OK) {
   2895        PKM_Error("C_DecryptUpdate failed with 0x%08X, %-26s\n", crv,
   2896                  PKM_CK_RVtoStr(crv));
   2897        return crv;
   2898    }
   2899    lastLen = sizeof(plaintext2) - plaintext2Len;
   2900    crv = pFunctionList->C_DecryptFinal(hSession,
   2901                                        (CK_BYTE *)&plaintext2[plaintext2Len],
   2902                                        &lastLen);
   2903    plaintext2Len = plaintext2Len + lastLen;
   2904 
   2905    if ((plaintextLen == plaintext2Len) &&
   2906        (memcmp(plaintext, plaintext2, plaintext2Len) == 0) &&
   2907        (memcmp(plaintext2, PLAINTEXT, sizeof(PLAINTEXT)) == 0)) {
   2908        PKM_LogIt("AES CBCVarKey128 decrypt test case 2 passed\n");
   2909    } else {
   2910        PKM_Error("AES CBCVarKey128 decrypt test case 2 failed\n");
   2911        return CKR_GENERAL_ERROR;
   2912    }
   2913 
   2914    crv = pFunctionList->C_Logout(hSession);
   2915    if (crv == CKR_OK) {
   2916        PKM_LogIt("C_Logout succeeded\n");
   2917    } else {
   2918        PKM_Error("C_Logout failed with 0x%08X, %-26s\n", crv,
   2919                  PKM_CK_RVtoStr(crv));
   2920        return crv;
   2921    }
   2922    crv = pFunctionList->C_CloseSession(hSession);
   2923    if (crv != CKR_OK) {
   2924        PKM_Error("C_CloseSession failed with 0x%08X, %-26s\n", crv,
   2925                  PKM_CK_RVtoStr(crv));
   2926        return crv;
   2927    }
   2928 
   2929    return crv;
   2930 }
   2931 
   2932 CK_RV
   2933 PKM_PubKeySign(CK_FUNCTION_LIST_PTR pFunctionList,
   2934               CK_SESSION_HANDLE hRwSession,
   2935               CK_OBJECT_HANDLE hPubKey, CK_OBJECT_HANDLE hPrivKey,
   2936               CK_MECHANISM *signMech, const CK_BYTE *pData,
   2937               CK_ULONG pDataLen)
   2938 {
   2939    CK_RV crv = CKR_OK;
   2940    CK_BYTE sig[MAX_SIG_SZ];
   2941    CK_ULONG sigLen = 0;
   2942 
   2943    NUMTESTS++; /* increment NUMTESTS */
   2944    memset(sig, 0, sizeof(sig));
   2945 
   2946    /* C_Sign  */
   2947    crv = pFunctionList->C_SignInit(hRwSession, signMech, hPrivKey);
   2948    if (crv != CKR_OK) {
   2949        PKM_Error("C_SignInit failed with 0x%08X, %-26s\n", crv,
   2950                  PKM_CK_RVtoStr(crv));
   2951        return crv;
   2952    }
   2953    sigLen = sizeof(sig);
   2954    crv = pFunctionList->C_Sign(hRwSession, (CK_BYTE *)pData, pDataLen,
   2955                                sig, &sigLen);
   2956    if (crv != CKR_OK) {
   2957        PKM_Error("C_Sign failed with 0x%08X, %-26s\n", crv,
   2958                  PKM_CK_RVtoStr(crv));
   2959        return crv;
   2960    }
   2961 
   2962    /* C_Verify the signature */
   2963    crv = pFunctionList->C_VerifyInit(hRwSession, signMech, hPubKey);
   2964    if (crv != CKR_OK) {
   2965        PKM_Error("C_VerifyInit failed with 0x%08X, %-26s\n", crv,
   2966                  PKM_CK_RVtoStr(crv));
   2967        return crv;
   2968    }
   2969    crv = pFunctionList->C_Verify(hRwSession, (CK_BYTE *)pData, pDataLen,
   2970                                  sig, sigLen);
   2971    if (crv == CKR_OK) {
   2972        PKM_LogIt("C_Verify succeeded\n");
   2973    } else {
   2974        PKM_Error("C_Verify failed with 0x%08X, %-26s\n", crv,
   2975                  PKM_CK_RVtoStr(crv));
   2976        return crv;
   2977    }
   2978 
   2979    /* Check that the mechanism is Multi-part */
   2980    if (signMech->mechanism == CKM_ECDSA ||
   2981        signMech->mechanism == CKM_RSA_PKCS) {
   2982        return crv;
   2983    }
   2984 
   2985    memset(sig, 0, sizeof(sig));
   2986    /* SignUpdate  */
   2987    crv = pFunctionList->C_SignInit(hRwSession, signMech, hPrivKey);
   2988    if (crv != CKR_OK) {
   2989        PKM_Error("C_SignInit failed with 0x%08lX %-26s\n", crv,
   2990                  PKM_CK_RVtoStr(crv));
   2991        return crv;
   2992    }
   2993    crv = pFunctionList->C_SignUpdate(hRwSession, (CK_BYTE *)pData, pDataLen);
   2994    if (crv != CKR_OK) {
   2995        PKM_Error("C_Sign failed with 0x%08lX %-26s\n", crv,
   2996                  PKM_CK_RVtoStr(crv));
   2997        return crv;
   2998    }
   2999 
   3000    sigLen = sizeof(sig);
   3001    crv = pFunctionList->C_SignFinal(hRwSession, sig, &sigLen);
   3002    if (crv != CKR_OK) {
   3003        PKM_Error("C_Sign failed with 0x%08X, %-26s\n", crv,
   3004                  PKM_CK_RVtoStr(crv));
   3005        return crv;
   3006    }
   3007 
   3008    /* C_VerifyUpdate the signature  */
   3009    crv = pFunctionList->C_VerifyInit(hRwSession, signMech,
   3010                                      hPubKey);
   3011    if (crv != CKR_OK) {
   3012        PKM_Error("C_VerifyInit failed with 0x%08X, %-26s\n", crv,
   3013                  PKM_CK_RVtoStr(crv));
   3014        return crv;
   3015    }
   3016    crv = pFunctionList->C_VerifyUpdate(hRwSession, (CK_BYTE *)pData,
   3017                                        pDataLen);
   3018    if (crv != CKR_OK) {
   3019        PKM_Error("C_VerifyUpdate failed with 0x%08X, %-26s\n", crv,
   3020                  PKM_CK_RVtoStr(crv));
   3021        return crv;
   3022    }
   3023    crv = pFunctionList->C_VerifyFinal(hRwSession, sig, sigLen);
   3024    if (crv == CKR_OK) {
   3025        PKM_LogIt("C_VerifyFinal succeeded\n");
   3026    } else {
   3027        PKM_Error("C_VerifyFinal failed with 0x%08X, %-26s\n", crv,
   3028                  PKM_CK_RVtoStr(crv));
   3029        return crv;
   3030    }
   3031    return crv;
   3032 }
   3033 
   3034 #define SHA256_LENGTH 32
   3035 CK_RV
   3036 PKM_PublicKey(CK_FUNCTION_LIST_PTR pFunctionList,
   3037              CK_SLOT_ID *pSlotList,
   3038              CK_ULONG slotID, CK_UTF8CHAR_PTR pwd,
   3039              CK_ULONG pwdLen)
   3040 {
   3041    CK_SESSION_HANDLE hSession;
   3042    CK_RV crv = CKR_OK;
   3043 
   3044    /*** ECDSA Key ***/
   3045    CK_MECHANISM ecdsaKeyPairGenMech;
   3046    CK_ATTRIBUTE ecdsaPubKeyTemplate[3];
   3047    CK_ATTRIBUTE ecdsaPrivKeyTemplate[5];
   3048    CK_OBJECT_HANDLE hECDSApubKey = CK_INVALID_HANDLE;
   3049    CK_OBJECT_HANDLE hECDSAprivKey = CK_INVALID_HANDLE;
   3050    CK_BYTE ECDSA_P256_PARAMS[] = { 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07 };
   3051 
   3052    /* From SHA1ShortMsg.req, Len = 136 */
   3053    CK_BYTE MSG[] = {
   3054        0xba, 0x33, 0x95, 0xfb,
   3055        0x5a, 0xfa, 0x8e, 0x6a,
   3056        0x43, 0xdf, 0x41, 0x6b,
   3057        0x32, 0x7b, 0x74, 0xfa,
   3058        0x44
   3059    };
   3060    CK_BYTE MD[] = {
   3061        0x88, 0x78, 0xe1, 0x1e,
   3062        0x63, 0x74, 0xa9, 0xd9,
   3063        0x90, 0xd0, 0xeb, 0x2c,
   3064        0xeb, 0x62, 0x2b, 0x04,
   3065        0x53, 0x9f, 0xa0, 0xfc
   3066    };
   3067 
   3068    CK_BYTE sha256Digest[SHA256_LENGTH];
   3069    CK_ULONG sha256DigestLen;
   3070    CK_BYTE ecdsaSig[SHA256_LENGTH * 2 + 1];
   3071    CK_ULONG ecdsaSigLen;
   3072    CK_MECHANISM sha256Mech = {
   3073        CKM_SHA256, NULL, 0
   3074    };
   3075    CK_MECHANISM ecdsaMech = {
   3076        CKM_ECDSA, NULL, 0
   3077    };
   3078    CK_MECHANISM ecdsaWithSha256Mech = {
   3079        CKM_ECDSA_SHA256, NULL, 0
   3080    };
   3081 
   3082    NUMTESTS++; /* increment NUMTESTS */
   3083 
   3084    /* ECDSA key init */
   3085    ecdsaPubKeyTemplate[0].type = CKA_EC_PARAMS;
   3086    ecdsaPubKeyTemplate[0].pValue = ECDSA_P256_PARAMS;
   3087    ecdsaPubKeyTemplate[0].ulValueLen = sizeof(ECDSA_P256_PARAMS);
   3088    ecdsaPubKeyTemplate[1].type = CKA_TOKEN;
   3089    ecdsaPubKeyTemplate[1].pValue = &ck_true;
   3090    ecdsaPubKeyTemplate[1].ulValueLen = sizeof(ck_true);
   3091    ecdsaPubKeyTemplate[2].type = CKA_VERIFY;
   3092    ecdsaPubKeyTemplate[2].pValue = &ck_true;
   3093    ecdsaPubKeyTemplate[2].ulValueLen = sizeof(ck_true);
   3094    ecdsaKeyPairGenMech.mechanism = CKM_ECDSA_KEY_PAIR_GEN;
   3095    ecdsaKeyPairGenMech.pParameter = NULL_PTR;
   3096    ecdsaKeyPairGenMech.ulParameterLen = 0;
   3097    ecdsaPrivKeyTemplate[0].type = CKA_TOKEN;
   3098    ecdsaPrivKeyTemplate[0].pValue = &ck_true;
   3099    ecdsaPrivKeyTemplate[0].ulValueLen = sizeof(ck_true);
   3100    ecdsaPrivKeyTemplate[1].type = CKA_PRIVATE;
   3101    ecdsaPrivKeyTemplate[1].pValue = &ck_true;
   3102    ecdsaPrivKeyTemplate[1].ulValueLen = sizeof(ck_true);
   3103    ecdsaPrivKeyTemplate[2].type = CKA_SENSITIVE;
   3104    ecdsaPrivKeyTemplate[2].pValue = &ck_true;
   3105    ecdsaPrivKeyTemplate[2].ulValueLen = sizeof(ck_true);
   3106    ecdsaPrivKeyTemplate[3].type = CKA_SIGN,
   3107    ecdsaPrivKeyTemplate[3].pValue = &ck_true;
   3108    ecdsaPrivKeyTemplate[3].ulValueLen = sizeof(ck_true);
   3109    ecdsaPrivKeyTemplate[4].type = CKA_EXTRACTABLE;
   3110    ecdsaPrivKeyTemplate[4].pValue = &ck_true;
   3111    ecdsaPrivKeyTemplate[4].ulValueLen = sizeof(ck_true);
   3112 
   3113    crv = pFunctionList->C_OpenSession(pSlotList[slotID],
   3114                                       CKF_RW_SESSION | CKF_SERIAL_SESSION,
   3115                                       NULL, NULL, &hSession);
   3116    if (crv != CKR_OK) {
   3117        PKM_Error("C_OpenSession failed with 0x%08X, %-26s\n", crv,
   3118                  PKM_CK_RVtoStr(crv));
   3119        return crv;
   3120    }
   3121 
   3122    crv = pFunctionList->C_Login(hSession, CKU_USER, pwd, pwdLen);
   3123    if (crv == CKR_OK) {
   3124        PKM_LogIt("C_Login with correct password succeeded\n");
   3125    } else {
   3126        PKM_Error("C_Login with correct password failed "
   3127                  "with 0x%08X, %-26s\n",
   3128                  crv, PKM_CK_RVtoStr(crv));
   3129        return crv;
   3130    }
   3131 
   3132    PKM_LogIt("Generate a ECDSA key pair ... \n");
   3133    /* Generate a persistent ECDSA key pair */
   3134    crv = pFunctionList->C_GenerateKeyPair(hSession, &ecdsaKeyPairGenMech,
   3135                                           ecdsaPubKeyTemplate,
   3136                                           NUM_ELEM(ecdsaPubKeyTemplate),
   3137                                           ecdsaPrivKeyTemplate,
   3138                                           NUM_ELEM(ecdsaPrivKeyTemplate),
   3139                                           &hECDSApubKey, &hECDSAprivKey);
   3140    if (crv == CKR_OK) {
   3141        PKM_LogIt("ECDSA key pair generation succeeded\n");
   3142    } else {
   3143        PKM_Error("ECDSA key pair generation failed "
   3144                  "with 0x%08X, %-26s\n",
   3145                  crv, PKM_CK_RVtoStr(crv));
   3146        return crv;
   3147    }
   3148 
   3149    /* Compute SHA-1 digest */
   3150    crv = pFunctionList->C_DigestInit(hSession, &sha256Mech);
   3151    if (crv != CKR_OK) {
   3152        PKM_Error("C_DigestInit failed with 0x%08X, %-26s\n", crv,
   3153                  PKM_CK_RVtoStr(crv));
   3154        return crv;
   3155    }
   3156    sha256DigestLen = sizeof(sha256Digest);
   3157    crv = pFunctionList->C_Digest(hSession, MSG, sizeof(MSG),
   3158                                  sha256Digest, &sha256DigestLen);
   3159    if (crv != CKR_OK) {
   3160        PKM_Error("C_Digest failed with 0x%08X, %-26s\n", crv,
   3161                  PKM_CK_RVtoStr(crv));
   3162        return crv;
   3163    }
   3164    if (sha256DigestLen != sizeof(sha256Digest)) {
   3165        PKM_Error("sha1DigestLen is %lu\n", sha256DigestLen);
   3166        return crv;
   3167    }
   3168 
   3169    if (memcmp(sha256Digest, MD, sizeof(MD)) == 0) {
   3170        PKM_LogIt("SHA-256 SHA256ShortMsg test case Len = 136 passed\n");
   3171    } else {
   3172        PKM_Error("SHA-256 SHA256ShortMsg test case Len = 136 failed\n");
   3173    }
   3174 
   3175    crv = PKM_PubKeySign(pFunctionList, hSession,
   3176                         hECDSApubKey, hECDSAprivKey,
   3177                         &ecdsaMech, sha256Digest, sizeof(sha256Digest));
   3178    if (crv == CKR_OK) {
   3179        PKM_LogIt("PKM_PubKeySign CKM_ECDSA succeeded \n");
   3180    } else {
   3181        PKM_Error("PKM_PubKeySign failed "
   3182                  "with 0x%08X, %-26s\n",
   3183                  crv, PKM_CK_RVtoStr(crv));
   3184        return crv;
   3185    }
   3186    crv = PKM_PubKeySign(pFunctionList, hSession,
   3187                         hECDSApubKey, hECDSAprivKey,
   3188                         &ecdsaWithSha256Mech, PLAINTEXT, sizeof(PLAINTEXT));
   3189    if (crv == CKR_OK) {
   3190        PKM_LogIt("PKM_PubKeySign CKM_DSA_SHA256 succeeded \n");
   3191    } else {
   3192        PKM_Error("PKM_PubKeySign failed "
   3193                  "with 0x%08X, %-26s\n",
   3194                  crv, PKM_CK_RVtoStr(crv));
   3195        return crv;
   3196    }
   3197 
   3198    /* Sign with ECDSA */
   3199    crv = pFunctionList->C_SignInit(hSession, &ecdsaMech, hECDSAprivKey);
   3200    if (crv != CKR_OK) {
   3201        PKM_Error("C_SignInit failed with 0x%08X, %-26s\n", crv,
   3202                  PKM_CK_RVtoStr(crv));
   3203        return crv;
   3204    }
   3205    ecdsaSigLen = sizeof(ecdsaSig);
   3206    crv = pFunctionList->C_Sign(hSession, sha256Digest, sha256DigestLen,
   3207                                ecdsaSig, &ecdsaSigLen);
   3208    if (crv != CKR_OK) {
   3209        PKM_Error("C_Sign failed with 0x%08X, %-26s\n", crv,
   3210                  PKM_CK_RVtoStr(crv));
   3211        return crv;
   3212    }
   3213 
   3214    /* Verify the DSA signature */
   3215    crv = pFunctionList->C_VerifyInit(hSession, &ecdsaMech, hECDSApubKey);
   3216    if (crv != CKR_OK) {
   3217        PKM_Error("C_VerifyInit failed with 0x%08X, %-26s\n", crv,
   3218                  PKM_CK_RVtoStr(crv));
   3219        return crv;
   3220    }
   3221    crv = pFunctionList->C_Verify(hSession, sha256Digest, sha256DigestLen,
   3222                                  ecdsaSig, ecdsaSigLen);
   3223    if (crv == CKR_OK) {
   3224        PKM_LogIt("C_Verify succeeded\n");
   3225    } else {
   3226        PKM_Error("C_Verify failed with 0x%08X, %-26s\n", crv,
   3227                  PKM_CK_RVtoStr(crv));
   3228        return crv;
   3229    }
   3230 
   3231    /* Verify the signature in a different way */
   3232    crv = pFunctionList->C_VerifyInit(hSession, &ecdsaWithSha256Mech,
   3233                                      hECDSApubKey);
   3234    if (crv != CKR_OK) {
   3235        PKM_Error("C_VerifyInit failed with 0x%08X, %-26s\n", crv,
   3236                  PKM_CK_RVtoStr(crv));
   3237        return crv;
   3238    }
   3239    crv = pFunctionList->C_VerifyUpdate(hSession, MSG, 1);
   3240    if (crv != CKR_OK) {
   3241        PKM_Error("C_VerifyUpdate failed with 0x%08X, %-26s\n", crv,
   3242                  PKM_CK_RVtoStr(crv));
   3243        return crv;
   3244    }
   3245    crv = pFunctionList->C_VerifyUpdate(hSession, MSG + 1, sizeof(MSG) - 1);
   3246    if (crv != CKR_OK) {
   3247        PKM_Error("C_VerifyUpdate failed with 0x%08X, %-26s\n", crv,
   3248                  PKM_CK_RVtoStr(crv));
   3249        return crv;
   3250    }
   3251    crv = pFunctionList->C_VerifyFinal(hSession, ecdsaSig, ecdsaSigLen);
   3252    if (crv == CKR_OK) {
   3253        PKM_LogIt("C_VerifyFinal succeeded\n");
   3254    } else {
   3255        PKM_Error("C_VerifyFinal failed with 0x%08X, %-26s\n", crv,
   3256                  PKM_CK_RVtoStr(crv));
   3257        return crv;
   3258    }
   3259 
   3260    /* Verify the signature in a different way */
   3261    crv = pFunctionList->C_VerifyInit(hSession, &ecdsaWithSha256Mech,
   3262                                      hECDSApubKey);
   3263    if (crv != CKR_OK) {
   3264        PKM_Error("C_VerifyInit failed with 0x%08X, %-26s\n",
   3265                  crv, PKM_CK_RVtoStr(crv));
   3266        return crv;
   3267    }
   3268    crv = pFunctionList->C_VerifyUpdate(hSession, MSG, 1);
   3269    if (crv != CKR_OK) {
   3270        PKM_Error("C_VerifyUpdate failed with 0x%08X, %-26s\n",
   3271                  crv, PKM_CK_RVtoStr(crv));
   3272        return crv;
   3273    }
   3274    crv = pFunctionList->C_VerifyUpdate(hSession, MSG + 1, sizeof(MSG) - 1);
   3275    if (crv != CKR_OK) {
   3276        PKM_Error("C_VerifyUpdate failed with 0x%08X, %-26s\n",
   3277                  crv, PKM_CK_RVtoStr(crv));
   3278        return crv;
   3279    }
   3280    crv = pFunctionList->C_VerifyFinal(hSession, ecdsaSig, ecdsaSigLen);
   3281    if (crv == CKR_OK) {
   3282        PKM_LogIt("C_VerifyFinal of multi update succeeded.\n");
   3283    } else {
   3284        PKM_Error("C_VerifyFinal of multi update failed with 0x%08X, %-26s\n",
   3285                  crv, PKM_CK_RVtoStr(crv));
   3286        return crv;
   3287    }
   3288    /* Now modify the data */
   3289    MSG[0] += 1;
   3290    /* Compute SHA-1 digest */
   3291    crv = pFunctionList->C_DigestInit(hSession, &sha256Mech);
   3292    if (crv != CKR_OK) {
   3293        PKM_Error("C_DigestInit failed with 0x%08X, %-26s\n", crv,
   3294                  PKM_CK_RVtoStr(crv));
   3295        return crv;
   3296    }
   3297    sha256DigestLen = sizeof(sha256Digest);
   3298    crv = pFunctionList->C_Digest(hSession, MSG, sizeof(MSG),
   3299                                  sha256Digest, &sha256DigestLen);
   3300    if (crv != CKR_OK) {
   3301        PKM_Error("C_Digest failed with 0x%08X, %-26s\n", crv,
   3302                  PKM_CK_RVtoStr(crv));
   3303        return crv;
   3304    }
   3305    crv = pFunctionList->C_VerifyInit(hSession, &ecdsaMech, hECDSApubKey);
   3306    if (crv != CKR_OK) {
   3307        PKM_Error("C_VerifyInit failed with 0x%08X, %-26s\n", crv,
   3308                  PKM_CK_RVtoStr(crv));
   3309        return crv;
   3310    }
   3311    crv = pFunctionList->C_Verify(hSession, sha256Digest, sha256DigestLen,
   3312                                  ecdsaSig, ecdsaSigLen);
   3313    if (crv != CKR_SIGNATURE_INVALID) {
   3314        PKM_Error("C_Verify of modified data succeeded\n");
   3315        return crv;
   3316    } else {
   3317        PKM_LogIt("C_Verify of modified data returned as EXPECTED "
   3318                  " with 0x%08X, %-26s\n",
   3319                  crv, PKM_CK_RVtoStr(crv));
   3320    }
   3321 
   3322    crv = pFunctionList->C_Logout(hSession);
   3323    if (crv == CKR_OK) {
   3324        PKM_LogIt("C_Logout succeeded\n");
   3325    } else {
   3326        PKM_Error("C_Logout failed with 0x%08X, %-26s\n", crv,
   3327                  PKM_CK_RVtoStr(crv));
   3328        return crv;
   3329    }
   3330 
   3331    crv = pFunctionList->C_CloseSession(hSession);
   3332    if (crv != CKR_OK) {
   3333        PKM_Error("C_CloseSession failed with 0x%08X, %-26s\n", crv,
   3334                  PKM_CK_RVtoStr(crv));
   3335        return crv;
   3336    }
   3337 
   3338    return crv;
   3339 }
   3340 
   3341 CK_RV
   3342 PKM_Hmac(CK_FUNCTION_LIST_PTR pFunctionList, CK_SESSION_HANDLE hSession,
   3343         CK_OBJECT_HANDLE sKey, CK_MECHANISM *hmacMech,
   3344         const CK_BYTE *pData, CK_ULONG pDataLen)
   3345 {
   3346 
   3347    CK_RV crv = CKR_OK;
   3348 
   3349    CK_BYTE hmac1[HMAC_MAX_LENGTH];
   3350    CK_ULONG hmac1Len = 0;
   3351    CK_BYTE hmac2[HMAC_MAX_LENGTH];
   3352    CK_ULONG hmac2Len = 0;
   3353 
   3354    memset(hmac1, 0, sizeof(hmac1));
   3355    memset(hmac2, 0, sizeof(hmac2));
   3356 
   3357    NUMTESTS++; /* increment NUMTESTS */
   3358 
   3359    crv = pFunctionList->C_SignInit(hSession, hmacMech, sKey);
   3360    if (crv == CKR_OK) {
   3361        PKM_LogIt("C_SignInit succeeded\n");
   3362    } else {
   3363        PKM_Error("C_SignInit failed with 0x%08X, %-26s\n", crv,
   3364                  PKM_CK_RVtoStr(crv));
   3365        return crv;
   3366    }
   3367 
   3368    hmac1Len = sizeof(hmac1);
   3369    crv = pFunctionList->C_Sign(hSession, (CK_BYTE *)pData,
   3370                                pDataLen,
   3371                                (CK_BYTE *)hmac1, &hmac1Len);
   3372    if (crv == CKR_OK) {
   3373        PKM_LogIt("C_Sign succeeded\n");
   3374    } else {
   3375        PKM_Error("C_Sign failed with 0x%08X, %-26s\n", crv,
   3376                  PKM_CK_RVtoStr(crv));
   3377        return crv;
   3378    }
   3379 
   3380    crv = pFunctionList->C_SignInit(hSession, hmacMech, sKey);
   3381    if (crv == CKR_OK) {
   3382        PKM_LogIt("C_SignInit succeeded\n");
   3383    } else {
   3384        PKM_Error("C_SignInit failed with 0x%08X, %-26s\n", crv,
   3385                  PKM_CK_RVtoStr(crv));
   3386        return crv;
   3387    }
   3388 
   3389    crv = pFunctionList->C_SignUpdate(hSession, (CK_BYTE *)pData,
   3390                                      pDataLen);
   3391    if (crv == CKR_OK) {
   3392        PKM_LogIt("C_SignUpdate succeeded\n");
   3393    } else {
   3394        PKM_Error("C_SignUpdate failed with 0x%08X, %-26s\n", crv,
   3395                  PKM_CK_RVtoStr(crv));
   3396        return crv;
   3397    }
   3398 
   3399    hmac2Len = sizeof(hmac2);
   3400    crv = pFunctionList->C_SignFinal(hSession, (CK_BYTE *)hmac2, &hmac2Len);
   3401    if (crv == CKR_OK) {
   3402        PKM_LogIt("C_SignFinal succeeded\n");
   3403    } else {
   3404        PKM_Error("C_SignFinal failed with 0x%08X, %-26s\n", crv,
   3405                  PKM_CK_RVtoStr(crv));
   3406        return crv;
   3407    }
   3408 
   3409    if ((hmac1Len == hmac2Len) && (memcmp(hmac1, hmac2, hmac1Len) == 0)) {
   3410        PKM_LogIt("hmacs are equal!\n");
   3411    } else {
   3412        PKM_Error("hmacs are not equal!\n");
   3413    }
   3414    crv = pFunctionList->C_VerifyInit(hSession, hmacMech, sKey);
   3415    if (crv != CKR_OK) {
   3416        PKM_Error("C_VerifyInit failed with 0x%08X, %-26s\n", crv,
   3417                  PKM_CK_RVtoStr(crv));
   3418        return crv;
   3419    }
   3420    crv = pFunctionList->C_Verify(hSession, (CK_BYTE *)pData,
   3421                                  pDataLen,
   3422                                  (CK_BYTE *)hmac2, hmac2Len);
   3423    if (crv == CKR_OK) {
   3424        PKM_LogIt("C_Verify of hmac succeeded\n");
   3425    } else {
   3426        PKM_Error("C_Verify failed with 0x%08X, %-26s\n", crv,
   3427                  PKM_CK_RVtoStr(crv));
   3428        return crv;
   3429    }
   3430    crv = pFunctionList->C_VerifyInit(hSession, hmacMech, sKey);
   3431    if (crv != CKR_OK) {
   3432        PKM_Error("C_VerifyInit failed with 0x%08X, %-26s\n", crv,
   3433                  PKM_CK_RVtoStr(crv));
   3434        return crv;
   3435    }
   3436    crv = pFunctionList->C_VerifyUpdate(hSession, (CK_BYTE *)pData,
   3437                                        pDataLen);
   3438    if (crv == CKR_OK) {
   3439        PKM_LogIt("C_VerifyUpdate of hmac succeeded\n");
   3440    } else {
   3441        PKM_Error("C_VerifyUpdate failed with 0x%08X, %-26s\n", crv,
   3442                  PKM_CK_RVtoStr(crv));
   3443        return crv;
   3444    }
   3445    crv = pFunctionList->C_VerifyFinal(hSession, (CK_BYTE *)hmac1,
   3446                                       hmac1Len);
   3447    if (crv == CKR_OK) {
   3448        PKM_LogIt("C_VerifyFinal of hmac succeeded\n");
   3449    } else {
   3450        PKM_Error("C_VerifyFinal failed with 0x%08X, %-26s\n", crv,
   3451                  PKM_CK_RVtoStr(crv));
   3452        return crv;
   3453    }
   3454    return crv;
   3455 }
   3456 
   3457 CK_RV
   3458 PKM_FindAllObjects(CK_FUNCTION_LIST_PTR pFunctionList,
   3459                   CK_SLOT_ID *pSlotList, CK_ULONG slotID,
   3460                   CK_UTF8CHAR_PTR pwd, CK_ULONG pwdLen)
   3461 {
   3462    CK_RV crv = CKR_OK;
   3463 
   3464    CK_SESSION_HANDLE h = (CK_SESSION_HANDLE)0;
   3465    CK_SESSION_INFO sinfo;
   3466    CK_ATTRIBUTE_PTR pTemplate;
   3467    CK_ULONG tnObjects = 0;
   3468    int curMode;
   3469    unsigned int i;
   3470    unsigned int number_of_all_known_attribute_types = totalKnownType(ConstAttribute);
   3471 
   3472    NUMTESTS++; /* increment NUMTESTS */
   3473 
   3474    crv = pFunctionList->C_OpenSession(pSlotList[slotID], CKF_SERIAL_SESSION,
   3475                                       NULL, NULL, &h);
   3476    if (CKR_OK != crv) {
   3477        PKM_Error("C_OpenSession(%lu, CKF_SERIAL_SESSION, , )"
   3478                  "returned 0x%08X, %-26s\n",
   3479                  pSlotList[slotID], crv,
   3480                  PKM_CK_RVtoStr(crv));
   3481        return crv;
   3482    }
   3483 
   3484    PKM_LogIt("    Opened a session: handle = 0x%08x\n", h);
   3485 
   3486    (void)memset(&sinfo, 0, sizeof(CK_SESSION_INFO));
   3487    crv = pFunctionList->C_GetSessionInfo(h, &sinfo);
   3488    if (CKR_OK != crv) {
   3489        PKM_LogIt("C_GetSessionInfo(%lu, ) returned 0x%08X, %-26s\n", h, crv,
   3490                  PKM_CK_RVtoStr(crv));
   3491        return crv;
   3492    }
   3493 
   3494    PKM_LogIt("    SESSION INFO:\n");
   3495    PKM_LogIt("        slotID = %lu\n", sinfo.slotID);
   3496    PKM_LogIt("        state = %lu\n", sinfo.state);
   3497    PKM_LogIt("        flags = 0x%08x\n", sinfo.flags);
   3498 #ifdef CKF_EXCLUSIVE_SESSION
   3499    PKM_LogIt("            -> EXCLUSIVE SESSION = %s\n", sinfo.flags & CKF_EXCLUSIVE_SESSION ? "TRUE" : "FALSE");
   3500 #endif /* CKF_EXCLUSIVE_SESSION */
   3501    PKM_LogIt("            -> RW SESSION = %s\n", sinfo.flags & CKF_RW_SESSION ? "TRUE" : "FALSE");
   3502    PKM_LogIt("            -> SERIAL SESSION = %s\n", sinfo.flags & CKF_SERIAL_SESSION ? "TRUE" : "FALSE");
   3503 #ifdef CKF_INSERTION_CALLBACK
   3504    PKM_LogIt("            -> INSERTION CALLBACK = %s\n", sinfo.flags & CKF_INSERTION_CALLBACK ? "TRUE" : "FALSE");
   3505 #endif /* CKF_INSERTION_CALLBACK */
   3506    PKM_LogIt("        ulDeviceError = %lu\n", sinfo.ulDeviceError);
   3507    PKM_LogIt("\n");
   3508 
   3509    crv = pFunctionList->C_FindObjectsInit(h, NULL, 0);
   3510    if (CKR_OK != crv) {
   3511        PKM_LogIt("C_FindObjectsInit(%lu, NULL, 0) returned "
   3512                  "0x%08X, %-26s\n",
   3513                  h, crv, PKM_CK_RVtoStr(crv));
   3514        return crv;
   3515    }
   3516 
   3517    pTemplate = (CK_ATTRIBUTE_PTR)calloc(number_of_all_known_attribute_types,
   3518                                         sizeof(CK_ATTRIBUTE));
   3519    if ((CK_ATTRIBUTE_PTR)NULL == pTemplate) {
   3520        PKM_Error("[pTemplate memory allocation of %lu bytes failed]\n",
   3521                  number_of_all_known_attribute_types *
   3522                      sizeof(CK_ATTRIBUTE));
   3523        return crv;
   3524    }
   3525 
   3526    PKM_LogIt("    All objects:\n");
   3527    /* Printing table set to NOMODE */
   3528    curMode = MODE;
   3529    MODE = NOMODE;
   3530 
   3531    while (1) {
   3532        CK_OBJECT_HANDLE o = (CK_OBJECT_HANDLE)0;
   3533        CK_ULONG nObjects = 0;
   3534        CK_ULONG k;
   3535        CK_ULONG nAttributes = 0;
   3536        CK_ATTRIBUTE_PTR pT2;
   3537        CK_ULONG l;
   3538        const char *attName = NULL;
   3539 
   3540        crv = pFunctionList->C_FindObjects(h, &o, 1, &nObjects);
   3541        if (CKR_OK != crv) {
   3542            PKM_Error("C_FindObjects(%lu, , 1, ) returned 0x%08X, %-26s\n",
   3543                      h, crv, PKM_CK_RVtoStr(crv));
   3544            return crv;
   3545        }
   3546 
   3547        if (0 == nObjects) {
   3548            PKM_LogIt("\n");
   3549            break;
   3550        }
   3551 
   3552        tnObjects++;
   3553 
   3554        PKM_LogIt("        OBJECT HANDLE %lu:\n", o);
   3555 
   3556        k = 0;
   3557        for (i = 0; i < constCount; i++) {
   3558            if (consts[i].type == ConstAttribute) {
   3559                pTemplate[k].type = consts[i].value;
   3560                pTemplate[k].pValue = (CK_VOID_PTR)NULL;
   3561                pTemplate[k].ulValueLen = 0;
   3562                k++;
   3563            }
   3564            assert(k <= number_of_all_known_attribute_types);
   3565        }
   3566 
   3567        crv = pFunctionList->C_GetAttributeValue(h, o, pTemplate,
   3568                                                 number_of_all_known_attribute_types);
   3569        switch (crv) {
   3570            case CKR_OK:
   3571            case CKR_ATTRIBUTE_SENSITIVE:
   3572            case CKR_ATTRIBUTE_TYPE_INVALID:
   3573            case CKR_BUFFER_TOO_SMALL:
   3574                break;
   3575            default:
   3576                PKM_Error("C_GetAtributeValue(%lu, %lu, {all attribute types},"
   3577                          "%lu) returned 0x%08X, %-26s\n",
   3578                          h, o, number_of_all_known_attribute_types, crv,
   3579                          PKM_CK_RVtoStr(crv));
   3580                return crv;
   3581        }
   3582 
   3583        for (k = 0; k < (CK_ULONG)number_of_all_known_attribute_types; k++) {
   3584            if (-1 != (CK_LONG)pTemplate[k].ulValueLen) {
   3585                nAttributes++;
   3586            }
   3587        }
   3588 
   3589        PKM_LogIt("            %lu attributes:\n", nAttributes);
   3590        for (k = 0; k < (CK_ULONG)number_of_all_known_attribute_types;
   3591             k++) {
   3592            if (-1 != (CK_LONG)pTemplate[k].ulValueLen) {
   3593                attName = getNameFromAttribute(pTemplate[k].type);
   3594                if (!attName) {
   3595                    PKM_Error("Unable to find attribute name update pk11table.c\n");
   3596                }
   3597                PKM_LogIt("                %s 0x%08x (len = %lu)\n",
   3598                          attName,
   3599                          pTemplate[k].type,
   3600                          pTemplate[k].ulValueLen);
   3601            }
   3602        }
   3603        PKM_LogIt("\n");
   3604 
   3605        pT2 = (CK_ATTRIBUTE_PTR)calloc(nAttributes, sizeof(CK_ATTRIBUTE));
   3606        if ((CK_ATTRIBUTE_PTR)NULL == pT2) {
   3607            PKM_Error("[pT2 memory allocation of %lu bytes failed]\n",
   3608                      nAttributes * sizeof(CK_ATTRIBUTE));
   3609            return crv;
   3610        }
   3611 
   3612        /* allocate memory for the attribute values */
   3613        for (l = 0, k = 0; k < (CK_ULONG)number_of_all_known_attribute_types;
   3614             k++) {
   3615            if (-1 != (CK_LONG)pTemplate[k].ulValueLen) {
   3616                pT2[l].type = pTemplate[k].type;
   3617                pT2[l].ulValueLen = pTemplate[k].ulValueLen;
   3618                if (pT2[l].ulValueLen > 0) {
   3619                    pT2[l].pValue = (CK_VOID_PTR)malloc(pT2[l].ulValueLen);
   3620                    if ((CK_VOID_PTR)NULL == pT2[l].pValue) {
   3621                        PKM_Error("pValue memory allocation of %lu bytes failed]\n",
   3622                                  pT2[l].ulValueLen);
   3623                        return crv;
   3624                    }
   3625                } else
   3626                    pT2[l].pValue = (CK_VOID_PTR)NULL;
   3627                l++;
   3628            }
   3629        }
   3630 
   3631        assert(l == nAttributes);
   3632 
   3633        crv = pFunctionList->C_GetAttributeValue(h, o, pT2, nAttributes);
   3634        switch (crv) {
   3635            case CKR_OK:
   3636            case CKR_ATTRIBUTE_SENSITIVE:
   3637            case CKR_ATTRIBUTE_TYPE_INVALID:
   3638            case CKR_BUFFER_TOO_SMALL:
   3639                break;
   3640            default:
   3641                PKM_Error("C_GetAtributeValue(%lu, %lu, {existent attribute"
   3642                          " types}, %lu) returned 0x%08X, %-26s\n",
   3643                          h, o, nAttributes, crv, PKM_CK_RVtoStr(crv));
   3644                return crv;
   3645        }
   3646 
   3647        for (l = 0; l < nAttributes; l++) {
   3648            attName = getNameFromAttribute(pT2[l].type);
   3649            if (!attName)
   3650                attName = "unknown attribute";
   3651            PKM_LogIt("            type = %s len = %ld",
   3652                      attName, (CK_LONG)pT2[l].ulValueLen);
   3653 
   3654            if (-1 == (CK_LONG)pT2[l].ulValueLen) {
   3655                ;
   3656            } else {
   3657                CK_ULONG m;
   3658 
   3659                if (pT2[l].ulValueLen <= 8) {
   3660                    PKM_LogIt(", value = ");
   3661                } else {
   3662                    PKM_LogIt(", value = \n                ");
   3663                }
   3664 
   3665                for (m = 0; (m < pT2[l].ulValueLen) && (m < 20); m++) {
   3666                    PKM_LogIt("%02x", (CK_ULONG)(0xff &
   3667                                                 ((CK_CHAR_PTR)pT2[l].pValue)[m]));
   3668                }
   3669 
   3670                PKM_LogIt(" ");
   3671 
   3672                for (m = 0; (m < pT2[l].ulValueLen) && (m < 20); m++) {
   3673                    CK_CHAR c = ((CK_CHAR_PTR)pT2[l].pValue)[m];
   3674                    if ((c < 0x20) || (c >= 0x7f)) {
   3675                        c = '.';
   3676                    }
   3677                    PKM_LogIt("%c", c);
   3678                }
   3679            }
   3680 
   3681            PKM_LogIt("\n");
   3682        }
   3683 
   3684        PKM_LogIt("\n");
   3685 
   3686        for (l = 0; l < nAttributes; l++) {
   3687            if (pT2[l].pValue) {
   3688                free(pT2[l].pValue);
   3689            }
   3690        }
   3691        free(pT2);
   3692    } /* while(1) */
   3693 
   3694    MODE = curMode; /* reset the logging MODE */
   3695 
   3696    crv = pFunctionList->C_FindObjectsFinal(h);
   3697    if (CKR_OK != crv) {
   3698        PKM_Error("C_FindObjectsFinal(%lu) returned 0x%08X, %-26s\n", h, crv,
   3699                  PKM_CK_RVtoStr(crv));
   3700        return crv;
   3701    }
   3702 
   3703    PKM_LogIt("    (%lu objects total)\n", tnObjects);
   3704 
   3705    crv = pFunctionList->C_CloseSession(h);
   3706    if (CKR_OK != crv) {
   3707        PKM_Error("C_CloseSession(%lu) returned 0x%08X, %-26s\n", h, crv,
   3708                  PKM_CK_RVtoStr(crv));
   3709        return crv;
   3710    }
   3711 
   3712    return crv;
   3713 }
   3714 /* session to create, find, and delete a couple session objects */
   3715 CK_RV
   3716 PKM_MultiObjectManagement(CK_FUNCTION_LIST_PTR pFunctionList,
   3717                          CK_SLOT_ID *pSlotList, CK_ULONG slotID,
   3718                          CK_UTF8CHAR_PTR pwd, CK_ULONG pwdLen)
   3719 {
   3720 
   3721    CK_RV crv = CKR_OK;
   3722 
   3723    CK_SESSION_HANDLE h = (CK_SESSION_HANDLE)0;
   3724    CK_SESSION_HANDLE h2 = (CK_SESSION_HANDLE)0;
   3725    CK_ATTRIBUTE one[7], two[7], three[7], delta[1], mask[1];
   3726    CK_OBJECT_CLASS cko_data = CKO_DATA;
   3727    char *key = "TEST PROGRAM";
   3728    CK_ULONG key_len = 0;
   3729    CK_OBJECT_HANDLE hOneIn = (CK_OBJECT_HANDLE)0;
   3730    CK_OBJECT_HANDLE hTwoIn = (CK_OBJECT_HANDLE)0;
   3731    CK_OBJECT_HANDLE hThreeIn = (CK_OBJECT_HANDLE)0;
   3732    CK_OBJECT_HANDLE hDeltaIn = (CK_OBJECT_HANDLE)0;
   3733    CK_OBJECT_HANDLE found[10];
   3734    CK_ULONG nFound;
   3735    CK_ULONG hDeltaLen, hThreeLen = 0;
   3736 
   3737    CK_TOKEN_INFO tinfo;
   3738 
   3739    NUMTESTS++; /* increment NUMTESTS */
   3740    key_len = sizeof(key);
   3741    crv = pFunctionList->C_OpenSession(pSlotList[slotID],
   3742                                       CKF_SERIAL_SESSION, NULL, NULL, &h);
   3743    if (CKR_OK != crv) {
   3744        PKM_Error("C_OpenSession(%lu, CKF_SERIAL_SESSION, , )"
   3745                  "returned 0x%08X, %-26s\n",
   3746                  pSlotList[slotID], crv,
   3747                  PKM_CK_RVtoStr(crv));
   3748        return crv;
   3749    }
   3750    crv = pFunctionList->C_Login(h, CKU_USER, pwd, pwdLen);
   3751    if (crv == CKR_OK) {
   3752        PKM_LogIt("C_Login with correct password succeeded\n");
   3753    } else {
   3754        PKM_Error("C_Login with correct password failed "
   3755                  "with 0x%08X, %-26s\n",
   3756                  crv, PKM_CK_RVtoStr(crv));
   3757        return crv;
   3758    }
   3759 
   3760    (void)memset(&tinfo, 0, sizeof(CK_TOKEN_INFO));
   3761    crv = pFunctionList->C_GetTokenInfo(pSlotList[slotID], &tinfo);
   3762    if (CKR_OK != crv) {
   3763        PKM_Error("C_GetTokenInfo(%lu, ) returned 0x%08X, %-26s\n",
   3764                  pSlotList[slotID], crv, PKM_CK_RVtoStr(crv));
   3765        return crv;
   3766    }
   3767 
   3768    PKM_LogIt("    Opened a session: handle = 0x%08x\n", h);
   3769 
   3770    one[0].type = CKA_CLASS;
   3771    one[0].pValue = &cko_data;
   3772    one[0].ulValueLen = sizeof(CK_OBJECT_CLASS);
   3773    one[1].type = CKA_TOKEN;
   3774    one[1].pValue = &ck_false;
   3775    one[1].ulValueLen = sizeof(CK_BBOOL);
   3776    one[2].type = CKA_PRIVATE;
   3777    one[2].pValue = &ck_false;
   3778    one[2].ulValueLen = sizeof(CK_BBOOL);
   3779    one[3].type = CKA_MODIFIABLE;
   3780    one[3].pValue = &ck_true;
   3781    one[3].ulValueLen = sizeof(CK_BBOOL);
   3782    one[4].type = CKA_LABEL;
   3783    one[4].pValue = "Test data object one";
   3784    one[4].ulValueLen = strlen(one[4].pValue);
   3785    one[5].type = CKA_APPLICATION;
   3786    one[5].pValue = key;
   3787    one[5].ulValueLen = key_len;
   3788    one[6].type = CKA_VALUE;
   3789    one[6].pValue = "Object one";
   3790    one[6].ulValueLen = strlen(one[6].pValue);
   3791 
   3792    two[0].type = CKA_CLASS;
   3793    two[0].pValue = &cko_data;
   3794    two[0].ulValueLen = sizeof(CK_OBJECT_CLASS);
   3795    two[1].type = CKA_TOKEN;
   3796    two[1].pValue = &ck_false;
   3797    two[1].ulValueLen = sizeof(CK_BBOOL);
   3798    two[2].type = CKA_PRIVATE;
   3799    two[2].pValue = &ck_false;
   3800    two[2].ulValueLen = sizeof(CK_BBOOL);
   3801    two[3].type = CKA_MODIFIABLE;
   3802    two[3].pValue = &ck_true;
   3803    two[3].ulValueLen = sizeof(CK_BBOOL);
   3804    two[4].type = CKA_LABEL;
   3805    two[4].pValue = "Test data object two";
   3806    two[4].ulValueLen = strlen(two[4].pValue);
   3807    two[5].type = CKA_APPLICATION;
   3808    two[5].pValue = key;
   3809    two[5].ulValueLen = key_len;
   3810    two[6].type = CKA_VALUE;
   3811    two[6].pValue = "Object two";
   3812    two[6].ulValueLen = strlen(two[6].pValue);
   3813 
   3814    three[0].type = CKA_CLASS;
   3815    three[0].pValue = &cko_data;
   3816    three[0].ulValueLen = sizeof(CK_OBJECT_CLASS);
   3817    three[1].type = CKA_TOKEN;
   3818    three[1].pValue = &ck_false;
   3819    three[1].ulValueLen = sizeof(CK_BBOOL);
   3820    three[2].type = CKA_PRIVATE;
   3821    three[2].pValue = &ck_false;
   3822    three[2].ulValueLen = sizeof(CK_BBOOL);
   3823    three[3].type = CKA_MODIFIABLE;
   3824    three[3].pValue = &ck_true;
   3825    three[3].ulValueLen = sizeof(CK_BBOOL);
   3826    three[4].type = CKA_LABEL;
   3827    three[4].pValue = "Test data object three";
   3828    three[4].ulValueLen = strlen(three[4].pValue);
   3829    three[5].type = CKA_APPLICATION;
   3830    three[5].pValue = key;
   3831    three[5].ulValueLen = key_len;
   3832    three[6].type = CKA_VALUE;
   3833    three[6].pValue = "Object three";
   3834    three[6].ulValueLen = strlen(three[6].pValue);
   3835 
   3836    crv = pFunctionList->C_CreateObject(h, one, 7, &hOneIn);
   3837    if (CKR_OK != crv) {
   3838        PKM_Error("C_CreateObject(%lu, one, 7, ) returned 0x%08X, %-26s\n",
   3839                  h, crv, PKM_CK_RVtoStr(crv));
   3840        return crv;
   3841    }
   3842 
   3843    PKM_LogIt("    Created object one: handle = %lu\n", hOneIn);
   3844 
   3845    crv = pFunctionList->C_CreateObject(h, two, 7, &hTwoIn);
   3846    if (CKR_OK != crv) {
   3847        PKM_Error("C_CreateObject(%lu, two, 7, ) returned 0x%08X, %-26s\n",
   3848                  h, crv, PKM_CK_RVtoStr(crv));
   3849        return crv;
   3850    }
   3851 
   3852    PKM_LogIt("    Created object two: handle = %lu\n", hTwoIn);
   3853 
   3854    crv = pFunctionList->C_CreateObject(h, three, 7, &hThreeIn);
   3855    if (CKR_OK != crv) {
   3856        PKM_Error("C_CreateObject(%lu, three, 7, ) returned 0x%08x\n",
   3857                  h, crv, PKM_CK_RVtoStr(crv));
   3858        return crv;
   3859    }
   3860    crv = pFunctionList->C_GetObjectSize(h, hThreeIn, &hThreeLen);
   3861    if (crv == CKR_OK) {
   3862        PKM_LogIt("C_GetObjectSize succeeded\n");
   3863    } else {
   3864        PKM_Error("C_GetObjectSize failed "
   3865                  "with 0x%08X, %-26s\n",
   3866                  crv, PKM_CK_RVtoStr(crv));
   3867        return crv;
   3868    }
   3869 
   3870    PKM_LogIt("    Created object three: handle = %lu\n", hThreeIn);
   3871 
   3872    delta[0].type = CKA_VALUE;
   3873    delta[0].pValue = "Copied object";
   3874    delta[0].ulValueLen = strlen(delta[0].pValue);
   3875 
   3876    crv = pFunctionList->C_CopyObject(h, hThreeIn, delta, 1, &hDeltaIn);
   3877    if (CKR_OK != crv) {
   3878        PKM_Error("C_CopyObject(%lu, %lu, delta, 1, ) returned "
   3879                  "0x%08X, %-26s\n",
   3880                  h, hThreeIn, crv, PKM_CK_RVtoStr(crv));
   3881        return crv;
   3882    }
   3883    crv = pFunctionList->C_GetObjectSize(h, hDeltaIn, &hDeltaLen);
   3884    if (crv == CKR_OK) {
   3885        PKM_LogIt("C_GetObjectSize succeeded\n");
   3886    } else {
   3887        PKM_Error("C_GetObjectSize failed "
   3888                  "with 0x%08X, %-26s\n",
   3889                  crv, PKM_CK_RVtoStr(crv));
   3890        return crv;
   3891    }
   3892 
   3893    if (hThreeLen == hDeltaLen) {
   3894        PKM_LogIt("Copied object size same as orginal\n");
   3895    } else {
   3896        PKM_Error("Copied object different from original\n");
   3897        return CKR_DEVICE_ERROR;
   3898    }
   3899 
   3900    PKM_LogIt("    Copied object three: new handle = %lu\n", hDeltaIn);
   3901 
   3902    mask[0].type = CKA_APPLICATION;
   3903    mask[0].pValue = key;
   3904    mask[0].ulValueLen = key_len;
   3905 
   3906    crv = pFunctionList->C_FindObjectsInit(h, mask, 1);
   3907    if (CKR_OK != crv) {
   3908        PKM_Error("C_FindObjectsInit(%lu, mask, 1) returned 0x%08X, %-26s\n",
   3909                  h, crv, PKM_CK_RVtoStr(crv));
   3910        return crv;
   3911    }
   3912 
   3913    (void)memset(&found, 0, sizeof(found));
   3914    nFound = 0;
   3915    crv = pFunctionList->C_FindObjects(h, found, 10, &nFound);
   3916    if (CKR_OK != crv) {
   3917        PKM_Error("C_FindObjects(%lu,, 10, ) returned 0x%08X, %-26s\n",
   3918                  h, crv, PKM_CK_RVtoStr(crv));
   3919        return crv;
   3920    }
   3921 
   3922    if (4 != nFound) {
   3923        PKM_Error("Found %lu objects, not 4.\n", nFound);
   3924        return crv;
   3925    }
   3926 
   3927    PKM_LogIt("    Found 4 objects: %lu, %lu, %lu, %lu\n",
   3928              found[0], found[1], found[2], found[3]);
   3929 
   3930    crv = pFunctionList->C_FindObjectsFinal(h);
   3931    if (CKR_OK != crv) {
   3932        PKM_Error("C_FindObjectsFinal(%lu) returned 0x%08X, %-26s\n",
   3933                  h, crv, PKM_CK_RVtoStr(crv));
   3934        return crv;
   3935    }
   3936 
   3937    crv = pFunctionList->C_DestroyObject(h, hThreeIn);
   3938    if (CKR_OK != crv) {
   3939        PKM_Error("C_DestroyObject(%lu, %lu) returned 0x%08X, %-26s\n", h,
   3940                  hThreeIn, crv, PKM_CK_RVtoStr(crv));
   3941        return crv;
   3942    }
   3943 
   3944    PKM_LogIt("    Destroyed object three (handle = %lu)\n", hThreeIn);
   3945 
   3946    delta[0].type = CKA_APPLICATION;
   3947    delta[0].pValue = "Changed application";
   3948    delta[0].ulValueLen = strlen(delta[0].pValue);
   3949 
   3950    crv = pFunctionList->C_SetAttributeValue(h, hTwoIn, delta, 1);
   3951    if (CKR_OK != crv) {
   3952        PKM_Error("C_SetAttributeValue(%lu, %lu, delta, 1) returned "
   3953                  "0x%08X, %-26s\n",
   3954                  h, hTwoIn, crv, PKM_CK_RVtoStr(crv));
   3955        return crv;
   3956    }
   3957 
   3958    PKM_LogIt("    Changed object two (handle = %lu).\n", hTwoIn);
   3959 
   3960    /* Can another session find these session objects? */
   3961 
   3962    crv = pFunctionList->C_OpenSession(pSlotList[slotID], CKF_SERIAL_SESSION,
   3963                                       NULL, NULL, &h2);
   3964    if (CKR_OK != crv) {
   3965        PKM_Error("C_OpenSession(%lu, CKF_SERIAL_SESSION, , )"
   3966                  " returned 0x%08X, %-26s\n",
   3967                  pSlotList[slotID], crv,
   3968                  PKM_CK_RVtoStr(crv));
   3969        return crv;
   3970    }
   3971    PKM_LogIt("    Opened a second session: handle = 0x%08x\n", h2);
   3972 
   3973    /* mask is still the same */
   3974 
   3975    crv = pFunctionList->C_FindObjectsInit(h2, mask, 1);
   3976    if (CKR_OK != crv) {
   3977        PKM_Error("C_FindObjectsInit(%lu, mask, 1) returned 0x%08X, %-26s\n",
   3978                  h2, crv, PKM_CK_RVtoStr(crv));
   3979        return crv;
   3980    }
   3981 
   3982    (void)memset(&found, 0, sizeof(found));
   3983    nFound = 0;
   3984    crv = pFunctionList->C_FindObjects(h2, found, 10, &nFound);
   3985    if (CKR_OK != crv) {
   3986        PKM_Error("C_FindObjects(%lu,, 10, ) returned 0x%08X, %-26s\n",
   3987                  h2, crv, PKM_CK_RVtoStr(crv));
   3988        return crv;
   3989    }
   3990 
   3991    if (2 != nFound) {
   3992        PKM_Error("Found %lu objects, not 2.\n", nFound);
   3993        return crv;
   3994    }
   3995 
   3996    PKM_LogIt("    Found 2 objects: %lu, %lu\n",
   3997              found[0], found[1]);
   3998 
   3999    crv = pFunctionList->C_FindObjectsFinal(h2);
   4000    if (CKR_OK != crv) {
   4001        PKM_Error("C_FindObjectsFinal(%lu) returned 0x%08X, %-26s\n", h2, crv,
   4002                  PKM_CK_RVtoStr(crv));
   4003        return crv;
   4004    }
   4005    crv = pFunctionList->C_Logout(h);
   4006    if (crv == CKR_OK) {
   4007        PKM_LogIt("C_Logout succeeded\n");
   4008    } else {
   4009        PKM_Error("C_Logout failed with 0x%08X, %-26s\n", crv,
   4010                  PKM_CK_RVtoStr(crv));
   4011        return crv;
   4012    }
   4013    crv = pFunctionList->C_CloseAllSessions(pSlotList[slotID]);
   4014    if (CKR_OK != crv) {
   4015        PKM_Error("C_CloseAllSessions(%lu) returned 0x%08X, %-26s\n",
   4016                  pSlotList[slotID], crv, PKM_CK_RVtoStr(crv));
   4017        return crv;
   4018    }
   4019 
   4020    PKM_LogIt("\n");
   4021    return crv;
   4022 }
   4023 
   4024 CK_RV
   4025 PKM_OperationalState(CK_FUNCTION_LIST_PTR pFunctionList,
   4026                     CK_SLOT_ID *pSlotList, CK_ULONG slotID,
   4027                     CK_UTF8CHAR_PTR pwd, CK_ULONG pwdLen)
   4028 {
   4029    CK_SESSION_HANDLE hSession;
   4030    CK_RV crv = CKR_OK;
   4031    CK_MECHANISM sAESKeyMech = {
   4032        CKM_AES_KEY_GEN, NULL, 0
   4033    };
   4034    CK_OBJECT_CLASS class = CKO_SECRET_KEY;
   4035    CK_KEY_TYPE keyAESType = CKK_AES;
   4036    CK_UTF8CHAR AESlabel[] = "An AES secret key object";
   4037    CK_ULONG AESvalueLen = 16;
   4038    CK_ATTRIBUTE sAESKeyTemplate[9];
   4039    CK_OBJECT_HANDLE sKey = CK_INVALID_HANDLE;
   4040    CK_BYTE_PTR pstate = NULL;
   4041    CK_ULONG statelen, digestlen, plainlen, plainlen_1, plainlen_2, slen;
   4042 
   4043    static const CK_UTF8CHAR *plaintext = (CK_UTF8CHAR *)"Firefox rules.";
   4044    static const CK_UTF8CHAR *plaintext_1 = (CK_UTF8CHAR *)"Thunderbird rules.";
   4045    static const CK_UTF8CHAR *plaintext_2 = (CK_UTF8CHAR *)"Firefox and Thunderbird.";
   4046 
   4047    char digest[MAX_DIGEST_SZ], digest_1[MAX_DIGEST_SZ];
   4048    char sign[MAX_SIG_SZ];
   4049    CK_MECHANISM signmech;
   4050    CK_MECHANISM digestmech;
   4051 
   4052    NUMTESTS++; /* increment NUMTESTS */
   4053 
   4054    /* AES key template */
   4055    sAESKeyTemplate[0].type = CKA_CLASS;
   4056    sAESKeyTemplate[0].pValue = &class;
   4057    sAESKeyTemplate[0].ulValueLen = sizeof(class);
   4058    sAESKeyTemplate[1].type = CKA_KEY_TYPE;
   4059    sAESKeyTemplate[1].pValue = &keyAESType;
   4060    sAESKeyTemplate[1].ulValueLen = sizeof(keyAESType);
   4061    sAESKeyTemplate[2].type = CKA_LABEL;
   4062    sAESKeyTemplate[2].pValue = AESlabel;
   4063    sAESKeyTemplate[2].ulValueLen = sizeof(AESlabel) - 1;
   4064    sAESKeyTemplate[3].type = CKA_ENCRYPT;
   4065    sAESKeyTemplate[3].pValue = &ck_true;
   4066    sAESKeyTemplate[3].ulValueLen = sizeof(ck_true);
   4067    sAESKeyTemplate[4].type = CKA_DECRYPT;
   4068    sAESKeyTemplate[4].pValue = &ck_true;
   4069    sAESKeyTemplate[4].ulValueLen = sizeof(ck_true);
   4070    sAESKeyTemplate[5].type = CKA_SIGN;
   4071    sAESKeyTemplate[5].pValue = &ck_true;
   4072    sAESKeyTemplate[5].ulValueLen = sizeof(ck_true);
   4073    sAESKeyTemplate[6].type = CKA_VERIFY;
   4074    sAESKeyTemplate[6].pValue = &ck_true;
   4075    sAESKeyTemplate[6].ulValueLen = sizeof(ck_true);
   4076    sAESKeyTemplate[7].type = CKA_UNWRAP;
   4077    sAESKeyTemplate[7].pValue = &ck_true;
   4078    sAESKeyTemplate[7].ulValueLen = sizeof(ck_true);
   4079    sAESKeyTemplate[8].type = CKA_VALUE_LEN;
   4080    sAESKeyTemplate[8].pValue = &AESvalueLen;
   4081    sAESKeyTemplate[8].ulValueLen = sizeof(AESvalueLen);
   4082 
   4083    signmech.mechanism = CKM_SHA_1_HMAC;
   4084    signmech.pParameter = NULL;
   4085    signmech.ulParameterLen = 0;
   4086    digestmech.mechanism = CKM_SHA256;
   4087    digestmech.pParameter = NULL;
   4088    digestmech.ulParameterLen = 0;
   4089 
   4090    plainlen = strlen((char *)plaintext);
   4091    plainlen_1 = strlen((char *)plaintext_1);
   4092    plainlen_2 = strlen((char *)plaintext_2);
   4093    digestlen = MAX_DIGEST_SZ;
   4094 
   4095    crv = pFunctionList->C_OpenSession(pSlotList[slotID], CKF_SERIAL_SESSION,
   4096                                       NULL, NULL, &hSession);
   4097    if (crv != CKR_OK) {
   4098        PKM_Error("C_OpenSession failed with 0x%08X, %-26s\n", crv,
   4099                  PKM_CK_RVtoStr(crv));
   4100        return crv;
   4101    }
   4102 
   4103    crv = pFunctionList->C_Login(hSession, CKU_USER, pwd, pwdLen);
   4104    if (crv == CKR_OK) {
   4105        PKM_LogIt("C_Login with correct password succeeded\n");
   4106    } else {
   4107        PKM_Error("C_Login with correct password failed "
   4108                  "with 0x%08X, %-26s\n",
   4109                  crv, PKM_CK_RVtoStr(crv));
   4110        return crv;
   4111    }
   4112 
   4113    PKM_LogIt("Generate an AES key ...\n");
   4114    /* generate an AES Secret Key */
   4115    crv = pFunctionList->C_GenerateKey(hSession, &sAESKeyMech,
   4116                                       sAESKeyTemplate,
   4117                                       NUM_ELEM(sAESKeyTemplate),
   4118                                       &sKey);
   4119    if (crv == CKR_OK) {
   4120        PKM_LogIt("C_GenerateKey AES succeeded\n");
   4121    } else {
   4122        PKM_Error("C_GenerateKey AES failed with 0x%08X, %-26s\n",
   4123                  crv, PKM_CK_RVtoStr(crv));
   4124        return crv;
   4125    }
   4126 
   4127    crv = pFunctionList->C_SignInit(hSession, &signmech, sKey);
   4128    if (crv != CKR_OK) {
   4129        PKM_Error("C_SignInit failed returned 0x%08X, %-26s\n", crv,
   4130                  PKM_CK_RVtoStr(crv));
   4131        return crv;
   4132    }
   4133 
   4134    slen = sizeof(sign);
   4135    crv = pFunctionList->C_Sign(hSession, (CK_BYTE_PTR)plaintext, plainlen,
   4136                                (CK_BYTE_PTR)sign, &slen);
   4137    if (crv != CKR_OK) {
   4138        PKM_Error("C_Sign failed returned 0x%08X, %-26s\n", crv,
   4139                  PKM_CK_RVtoStr(crv));
   4140        return crv;
   4141    }
   4142 
   4143    crv = pFunctionList->C_DestroyObject(hSession, sKey);
   4144    if (crv != CKR_OK) {
   4145        PKM_Error("C_DestroyObject failed returned 0x%08X, %-26s\n", crv,
   4146                  PKM_CK_RVtoStr(crv));
   4147        return crv;
   4148    }
   4149 
   4150    digestlen = MAX_DIGEST_SZ;
   4151    crv = pFunctionList->C_DigestInit(hSession, &digestmech);
   4152    if (crv != CKR_OK) {
   4153        PKM_Error("C_DigestInit failed returned 0x%08X, %-26s\n", crv,
   4154                  PKM_CK_RVtoStr(crv));
   4155        return crv;
   4156    }
   4157    crv = pFunctionList->C_DigestUpdate(hSession, (CK_BYTE_PTR)plaintext,
   4158                                        plainlen);
   4159    if (crv != CKR_OK) {
   4160        PKM_Error("C_DigestUpdate failed returned 0x%08X, %-26s\n", crv,
   4161                  PKM_CK_RVtoStr(crv));
   4162        return crv;
   4163    }
   4164 
   4165    crv = pFunctionList->C_GetOperationState(hSession, NULL, &statelen);
   4166    if (crv != CKR_OK) {
   4167        PKM_Error("C_GetOperationState failed returned 0x%08X, %-26s\n", crv,
   4168                  PKM_CK_RVtoStr(crv));
   4169        return crv;
   4170    }
   4171 
   4172    pstate = (CK_BYTE_PTR)malloc(statelen * sizeof(CK_BYTE_PTR));
   4173    crv = pFunctionList->C_GetOperationState(hSession, pstate, &statelen);
   4174    if (crv != CKR_OK) {
   4175        PKM_Error("C_GetOperationState failed returned 0x%08X, %-26s\n", crv,
   4176                  PKM_CK_RVtoStr(crv));
   4177        return crv;
   4178    }
   4179 
   4180    crv = pFunctionList->C_DigestUpdate(hSession, (CK_BYTE_PTR)plaintext_1,
   4181                                        plainlen_1);
   4182    if (crv != CKR_OK) {
   4183        PKM_Error("C_DigestUpdate failed returned 0x%08X, %-26s\n", crv,
   4184                  PKM_CK_RVtoStr(crv));
   4185        return crv;
   4186    }
   4187    crv = pFunctionList->C_DigestUpdate(hSession, (CK_BYTE_PTR)plaintext_2,
   4188                                        plainlen_2);
   4189    if (crv != CKR_OK) {
   4190        PKM_Error("C_DigestUpdate failed returned 0x%08X, %-26s\n", crv,
   4191                  PKM_CK_RVtoStr(crv));
   4192        return crv;
   4193    }
   4194 
   4195    /*
   4196     *      This will override/negate the above 2 digest_update
   4197     *      operations
   4198     */
   4199    crv = pFunctionList->C_SetOperationState(hSession, pstate, statelen,
   4200                                             0, 0);
   4201    if (crv != CKR_OK) {
   4202        PKM_Error("C_SetOperationState failed returned 0x%08X, %-26s\n", crv,
   4203                  PKM_CK_RVtoStr(crv));
   4204        return crv;
   4205    }
   4206    crv = pFunctionList->C_DigestFinal(hSession, (CK_BYTE_PTR)digest,
   4207                                       &digestlen);
   4208    if (crv != CKR_OK) {
   4209        PKM_Error("C_DigestFinal failed returned 0x%08X, %-26s\n", crv,
   4210                  PKM_CK_RVtoStr(crv));
   4211        return crv;
   4212    }
   4213    digestlen = MAX_DIGEST_SZ;
   4214    crv = pFunctionList->C_DigestInit(hSession, &digestmech);
   4215    if (crv != CKR_OK) {
   4216        PKM_Error("C_DigestInit failed returned 0x%08X, %-26s\n", crv,
   4217                  PKM_CK_RVtoStr(crv));
   4218        return crv;
   4219    }
   4220    crv = pFunctionList->C_Digest(hSession, (CK_BYTE_PTR)plaintext, plainlen,
   4221                                  (CK_BYTE_PTR)digest_1, &digestlen);
   4222    if (crv != CKR_OK) {
   4223        PKM_Error("C_Digest failed returned 0x%08X, %-26s\n", crv,
   4224                  PKM_CK_RVtoStr(crv));
   4225        return crv;
   4226    }
   4227    if (memcmp(digest, digest_1, digestlen) == 0) {
   4228        PKM_LogIt("Digest and digest_1 are equal!\n");
   4229    } else {
   4230        PKM_Error("Digest and digest_1 are not equal!\n");
   4231    }
   4232    crv = pFunctionList->C_Logout(hSession);
   4233    if (crv == CKR_OK) {
   4234        PKM_LogIt("C_Logout succeeded\n");
   4235    } else {
   4236        PKM_Error("C_Logout failed with 0x%08X, %-26s\n", crv,
   4237                  PKM_CK_RVtoStr(crv));
   4238        return crv;
   4239    }
   4240    crv = pFunctionList->C_CloseSession(hSession);
   4241    if (CKR_OK != crv) {
   4242        PKM_Error("C_CloseSession(%lu) returned 0x%08X, %-26s\n",
   4243                  hSession, crv, PKM_CK_RVtoStr(crv));
   4244        return crv;
   4245    }
   4246 
   4247    return crv;
   4248 }
   4249 
   4250 /*
   4251 * Recover Functions
   4252 */
   4253 CK_RV
   4254 PKM_RecoverFunctions(CK_FUNCTION_LIST_PTR pFunctionList,
   4255                     CK_SESSION_HANDLE hSession,
   4256                     CK_OBJECT_HANDLE hPubKey, CK_OBJECT_HANDLE hPrivKey,
   4257                     CK_MECHANISM *signMech, const CK_BYTE *pData,
   4258                     CK_ULONG pDataLen)
   4259 {
   4260    CK_RV crv = CKR_OK;
   4261    CK_BYTE sig[MAX_SIG_SZ];
   4262    CK_ULONG sigLen = MAX_SIG_SZ;
   4263    CK_BYTE recover[MAX_SIG_SZ];
   4264    CK_ULONG recoverLen = MAX_SIG_SZ;
   4265 
   4266    NUMTESTS++; /* increment NUMTESTS */
   4267 
   4268    /* initializes a signature operation,
   4269     *  where the data can be recovered from the signature
   4270     */
   4271    crv = pFunctionList->C_SignRecoverInit(hSession, signMech,
   4272                                           hPrivKey);
   4273    if (crv == CKR_OK) {
   4274        PKM_LogIt("C_SignRecoverInit succeeded. \n");
   4275    } else {
   4276        PKM_Error("C_SignRecoverInit failed.\n"
   4277                  "with 0x%08X, %-26s\n",
   4278                  crv, PKM_CK_RVtoStr(crv));
   4279        return crv;
   4280    }
   4281 
   4282    /* signs single-part data,
   4283     * where the data can be recovered from the signature
   4284     */
   4285    crv = pFunctionList->C_SignRecover(hSession, (CK_BYTE *)pData,
   4286                                       pDataLen,
   4287                                       (CK_BYTE *)sig, &sigLen);
   4288    if (crv == CKR_OK) {
   4289        PKM_LogIt("C_SignRecover succeeded. \n");
   4290    } else {
   4291        PKM_Error("C_SignRecoverInit failed to create an RSA key pair.\n"
   4292                  "with 0x%08X, %-26s\n",
   4293                  crv, PKM_CK_RVtoStr(crv));
   4294        return crv;
   4295    }
   4296 
   4297    /*
   4298     * initializes a verification operation
   4299     *where the data is recovered from the signature
   4300     */
   4301    crv = pFunctionList->C_VerifyRecoverInit(hSession, signMech,
   4302                                             hPubKey);
   4303    if (crv == CKR_OK) {
   4304        PKM_LogIt("C_VerifyRecoverInit succeeded. \n");
   4305    } else {
   4306        PKM_Error("C_VerifyRecoverInit failed.\n"
   4307                  "with 0x%08X, %-26s\n",
   4308                  crv, PKM_CK_RVtoStr(crv));
   4309        return crv;
   4310    }
   4311 
   4312    /*
   4313     * verifies a signature on single-part data,
   4314     * where the data is recovered from the signature
   4315     */
   4316    crv = pFunctionList->C_VerifyRecover(hSession, (CK_BYTE *)sig,
   4317                                         sigLen,
   4318                                         (CK_BYTE *)recover, &recoverLen);
   4319    if (crv == CKR_OK) {
   4320        PKM_LogIt("C_VerifyRecover succeeded. \n");
   4321    } else {
   4322        PKM_Error("C_VerifyRecover failed.\n"
   4323                  "with 0x%08X, %-26s\n",
   4324                  crv, PKM_CK_RVtoStr(crv));
   4325        return crv;
   4326    }
   4327 
   4328    if ((recoverLen == pDataLen) &&
   4329        (memcmp(recover, pData, pDataLen) == 0)) {
   4330        PKM_LogIt("VerifyRecover test case passed\n");
   4331    } else {
   4332        PKM_Error("VerifyRecover test case failed\n");
   4333    }
   4334 
   4335    return crv;
   4336 }
   4337 /*
   4338 * wrapUnwrap
   4339 * wrap the secretkey with the public key.
   4340 * unwrap the secretkey with the private key.
   4341 */
   4342 CK_RV
   4343 PKM_wrapUnwrap(CK_FUNCTION_LIST_PTR pFunctionList,
   4344               CK_SESSION_HANDLE hSession,
   4345               CK_OBJECT_HANDLE hPublicKey,
   4346               CK_OBJECT_HANDLE hPrivateKey,
   4347               CK_MECHANISM *wrapMechanism,
   4348               CK_OBJECT_HANDLE hSecretKey,
   4349               CK_ATTRIBUTE *sKeyTemplate,
   4350               CK_ULONG skeyTempSize)
   4351 {
   4352    CK_RV crv = CKR_OK;
   4353    CK_OBJECT_HANDLE hSecretKeyUnwrapped = CK_INVALID_HANDLE;
   4354    CK_BYTE wrappedKey[128];
   4355    CK_ULONG ulWrappedKeyLen = 0;
   4356 
   4357    NUMTESTS++; /* increment NUMTESTS */
   4358 
   4359    ulWrappedKeyLen = sizeof(wrappedKey);
   4360    crv = pFunctionList->C_WrapKey(
   4361        hSession, wrapMechanism,
   4362        hPublicKey, hSecretKey,
   4363        wrappedKey, &ulWrappedKeyLen);
   4364    if (crv == CKR_OK) {
   4365        PKM_LogIt("C_WrapKey succeeded\n");
   4366    } else {
   4367        PKM_Error("C_WrapKey failed with 0x%08X, %-26s\n", crv,
   4368                  PKM_CK_RVtoStr(crv));
   4369        return crv;
   4370    }
   4371    crv = pFunctionList->C_UnwrapKey(
   4372        hSession, wrapMechanism, hPrivateKey,
   4373        wrappedKey, ulWrappedKeyLen, sKeyTemplate,
   4374        skeyTempSize,
   4375        &hSecretKeyUnwrapped);
   4376    if ((crv == CKR_OK) && (hSecretKeyUnwrapped != CK_INVALID_HANDLE)) {
   4377        PKM_LogIt("C_UnwrapKey succeeded\n");
   4378    } else {
   4379        PKM_Error("C_UnwrapKey failed with 0x%08X, %-26s\n", crv,
   4380                  PKM_CK_RVtoStr(crv));
   4381        return crv;
   4382    }
   4383 
   4384    return crv;
   4385 }
   4386 
   4387 /*
   4388 * Tests if the object's attributes match the expected_attrs
   4389 */
   4390 CK_RV
   4391 PKM_AttributeCheck(CK_FUNCTION_LIST_PTR pFunctionList,
   4392                   CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE obj,
   4393                   CK_ATTRIBUTE_PTR expected_attrs,
   4394                   CK_ULONG expected_attrs_count)
   4395 {
   4396    CK_RV crv;
   4397    CK_ATTRIBUTE_PTR tmp_attrs;
   4398    unsigned int i;
   4399 
   4400    NUMTESTS++; /* increment NUMTESTS */
   4401 
   4402    /* First duplicate the themplate */
   4403    tmp_attrs = malloc(expected_attrs_count * sizeof(CK_ATTRIBUTE));
   4404 
   4405    if (tmp_attrs == NULL) {
   4406        PKM_Error("Internal test memory failure\n");
   4407        return (CKR_HOST_MEMORY);
   4408    }
   4409 
   4410    for (i = 0; i < expected_attrs_count; i++) {
   4411        tmp_attrs[i].type = expected_attrs[i].type;
   4412        tmp_attrs[i].ulValueLen = expected_attrs[i].ulValueLen;
   4413 
   4414        /* Don't give away the expected one. just zeros */
   4415        tmp_attrs[i].pValue = calloc(expected_attrs[i].ulValueLen, 1);
   4416 
   4417        if (tmp_attrs[i].pValue == NULL) {
   4418            unsigned int j;
   4419            for (j = 0; j < i; j++)
   4420                free(tmp_attrs[j].pValue);
   4421 
   4422            free(tmp_attrs);
   4423            printf("Internal test memory failure\n");
   4424            return (CKR_HOST_MEMORY);
   4425        }
   4426    }
   4427 
   4428    /* then get the attributes from the object */
   4429    crv = pFunctionList->C_GetAttributeValue(hSession, obj, tmp_attrs,
   4430                                             expected_attrs_count);
   4431    if (crv != CKR_OK) {
   4432        PKM_Error("C_GetAttributeValue failed with 0x%08X, %-26s\n", crv,
   4433                  PKM_CK_RVtoStr(crv));
   4434        crv = CKR_FUNCTION_FAILED;
   4435        goto out;
   4436    }
   4437 
   4438    /* Finally compare with the expected ones */
   4439    for (i = 0; i < expected_attrs_count; i++) {
   4440 
   4441        if (memcmp(tmp_attrs[i].pValue, expected_attrs[i].pValue,
   4442                   expected_attrs[i].ulValueLen) != 0) {
   4443            PKM_LogIt("comparing attribute type 0x%x with expected  0x%x\n",
   4444                      tmp_attrs[i].type, expected_attrs[i].type);
   4445            PKM_LogIt("comparing attribute type value 0x%x with expected 0x%x\n",
   4446                      tmp_attrs[i].pValue, expected_attrs[i].pValue);
   4447            /* don't report error at this time */
   4448        }
   4449    }
   4450 
   4451 out:
   4452    for (i = 0; i < expected_attrs_count; i++)
   4453        free(tmp_attrs[i].pValue);
   4454    free(tmp_attrs);
   4455    return (crv);
   4456 }
   4457 
   4458 /*
   4459 * Check the validity of a mech
   4460 */
   4461 CK_RV
   4462 PKM_MechCheck(CK_FUNCTION_LIST_PTR pFunctionList, CK_SESSION_HANDLE hSession,
   4463              CK_MECHANISM_TYPE mechType, CK_FLAGS flags,
   4464              CK_BBOOL check_sizes, CK_ULONG minkeysize, CK_ULONG maxkeysize)
   4465 {
   4466    CK_SESSION_INFO sess_info;
   4467    CK_MECHANISM_INFO mech_info;
   4468    CK_RV crv;
   4469 
   4470    NUMTESTS++; /* increment NUMTESTS */
   4471 
   4472    if ((crv = pFunctionList->C_GetSessionInfo(hSession, &sess_info)) !=
   4473        CKR_OK) {
   4474        PKM_Error("C_GetSessionInfo failed with 0x%08X, %-26s\n", crv,
   4475                  PKM_CK_RVtoStr(crv));
   4476        return (CKR_FUNCTION_FAILED);
   4477    }
   4478 
   4479    crv = pFunctionList->C_GetMechanismInfo(0, mechType,
   4480                                            &mech_info);
   4481 
   4482    crv = pFunctionList->C_GetMechanismInfo(sess_info.slotID, mechType,
   4483                                            &mech_info);
   4484 
   4485    if (crv != CKR_OK) {
   4486        PKM_Error("C_GetMechanismInfo failed with 0x%08X, %-26s\n", crv,
   4487                  PKM_CK_RVtoStr(crv));
   4488        return (CKR_FUNCTION_FAILED);
   4489    }
   4490 
   4491    if ((mech_info.flags & flags) == 0) {
   4492        PKM_Error("0x%x flag missing from mech\n", flags);
   4493        return (CKR_MECHANISM_INVALID);
   4494    }
   4495    if (!check_sizes)
   4496        return (CKR_OK);
   4497 
   4498    if (mech_info.ulMinKeySize != minkeysize) {
   4499        PKM_Error("Bad MinKeySize %d expected %d\n", mech_info.ulMinKeySize,
   4500                  minkeysize);
   4501        return (CKR_MECHANISM_INVALID);
   4502    }
   4503    if (mech_info.ulMaxKeySize != maxkeysize) {
   4504        PKM_Error("Bad MaxKeySize %d expected %d\n", mech_info.ulMaxKeySize,
   4505                  maxkeysize);
   4506        return (CKR_MECHANISM_INVALID);
   4507    }
   4508    return (CKR_OK);
   4509 }
   4510 
   4511 /*
   4512 * Can be called with a non-null premaster_key_len for the
   4513 * *_DH mechanisms. In that case, no checking for the matching of
   4514 * the expected results is done.
   4515 * The rnd argument tells which correct/bogus randomInfo to use.
   4516 */
   4517 CK_RV
   4518 PKM_TLSMasterKeyDerive(CK_FUNCTION_LIST_PTR pFunctionList,
   4519                       CK_SLOT_ID *pSlotList, CK_ULONG slotID,
   4520                       CK_UTF8CHAR_PTR pwd, CK_ULONG pwdLen,
   4521                       CK_MECHANISM_TYPE mechType,
   4522                       enum_random_t rnd)
   4523 {
   4524    CK_SESSION_HANDLE hSession;
   4525    CK_RV crv;
   4526    CK_MECHANISM mk_mech;
   4527    CK_VERSION version;
   4528    CK_OBJECT_CLASS class = CKO_SECRET_KEY;
   4529    CK_KEY_TYPE type = CKK_GENERIC_SECRET;
   4530    CK_BBOOL derive_bool = ck_true;
   4531    CK_ATTRIBUTE attrs[4];
   4532    CK_ULONG attrs_count = 4;
   4533    CK_OBJECT_HANDLE pmk_obj = CK_INVALID_HANDLE;
   4534    CK_OBJECT_HANDLE mk_obj = CK_INVALID_HANDLE;
   4535    CK_SSL3_MASTER_KEY_DERIVE_PARAMS mkd_params;
   4536    CK_MECHANISM skmd_mech;
   4537 
   4538    CK_BBOOL isDH = ck_false;
   4539 
   4540    NUMTESTS++; /* increment NUMTESTS */
   4541 
   4542    attrs[0].type = CKA_CLASS;
   4543    attrs[0].pValue = &class;
   4544    attrs[0].ulValueLen = sizeof(class);
   4545    attrs[1].type = CKA_KEY_TYPE;
   4546    attrs[1].pValue = &type;
   4547    attrs[1].ulValueLen = sizeof(type);
   4548    attrs[2].type = CKA_DERIVE;
   4549    attrs[2].pValue = &derive_bool;
   4550    attrs[2].ulValueLen = sizeof(derive_bool);
   4551    attrs[3].type = CKA_VALUE;
   4552    attrs[3].pValue = NULL;
   4553    attrs[3].ulValueLen = 0;
   4554 
   4555    crv = pFunctionList->C_OpenSession(pSlotList[slotID], CKF_SERIAL_SESSION,
   4556                                       NULL, NULL, &hSession);
   4557    if (crv != CKR_OK) {
   4558        PKM_Error("C_OpenSession failed with 0x%08X, %-26s\n", crv,
   4559                  PKM_CK_RVtoStr(crv));
   4560        return crv;
   4561    }
   4562    crv = pFunctionList->C_Login(hSession, CKU_USER, pwd, pwdLen);
   4563    if (crv == CKR_OK) {
   4564        PKM_LogIt("C_Login with correct password succeeded\n");
   4565    } else {
   4566        PKM_Error("C_Login with correct password failed "
   4567                  "with 0x%08X, %-26s\n",
   4568                  crv, PKM_CK_RVtoStr(crv));
   4569        return crv;
   4570    }
   4571 
   4572    /* Before all, check if the mechanism is supported correctly */
   4573    if (MODE == FIPSMODE) {
   4574        crv = PKM_MechCheck(pFunctionList, hSession, mechType, CKF_DERIVE, ck_false,
   4575                            0, 0);
   4576        if (crv != CKR_OK) {
   4577            PKM_Error("PKM_MechCheck failed with 0x%08X, %-26s\n", crv,
   4578                      PKM_CK_RVtoStr(crv));
   4579            return (crv);
   4580        }
   4581    }
   4582 
   4583    mk_mech.mechanism = mechType;
   4584    mk_mech.pParameter = &mkd_params;
   4585    mk_mech.ulParameterLen = sizeof(mkd_params);
   4586 
   4587    switch (mechType) {
   4588        case CKM_TLS_MASTER_KEY_DERIVE_DH:
   4589            isDH = ck_true;
   4590        /* FALLTHRU */
   4591        case CKM_TLS_MASTER_KEY_DERIVE:
   4592            attrs[3].pValue = NULL;
   4593            attrs[3].ulValueLen = 0;
   4594 
   4595            mkd_params.RandomInfo.pClientRandom = (unsigned char *)TLSClientRandom;
   4596            mkd_params.RandomInfo.ulClientRandomLen =
   4597                sizeof(TLSClientRandom);
   4598            mkd_params.RandomInfo.pServerRandom = (unsigned char *)TLSServerRandom;
   4599            mkd_params.RandomInfo.ulServerRandomLen =
   4600                sizeof(TLSServerRandom);
   4601            break;
   4602    }
   4603    mkd_params.pVersion = (!isDH) ? &version : NULL;
   4604 
   4605    /* First create the pre-master secret key */
   4606 
   4607    skmd_mech.mechanism = CKM_SSL3_PRE_MASTER_KEY_GEN;
   4608    skmd_mech.pParameter = &mkd_params;
   4609    skmd_mech.ulParameterLen = sizeof(mkd_params);
   4610 
   4611    crv = pFunctionList->C_GenerateKey(hSession, &skmd_mech,
   4612                                       attrs,
   4613                                       attrs_count,
   4614                                       &pmk_obj);
   4615    if (crv == CKR_OK) {
   4616        PKM_LogIt("C_GenerateKey succeeded\n");
   4617    } else {
   4618        PKM_Error("C_GenerateKey failed with 0x%08X, %-26s\n", crv,
   4619                  PKM_CK_RVtoStr(crv));
   4620        return crv;
   4621    }
   4622    /* Test the bad cases */
   4623    switch (rnd) {
   4624        case CORRECT:
   4625            goto correct;
   4626 
   4627        case BOGUS_CLIENT_RANDOM:
   4628            mkd_params.RandomInfo.pClientRandom = NULL;
   4629            break;
   4630 
   4631        case BOGUS_CLIENT_RANDOM_LEN:
   4632            mkd_params.RandomInfo.ulClientRandomLen = 0;
   4633            break;
   4634 
   4635        case BOGUS_SERVER_RANDOM:
   4636            mkd_params.RandomInfo.pServerRandom = NULL;
   4637            break;
   4638 
   4639        case BOGUS_SERVER_RANDOM_LEN:
   4640            mkd_params.RandomInfo.ulServerRandomLen = 0;
   4641            break;
   4642    }
   4643    crv = pFunctionList->C_DeriveKey(hSession, &mk_mech, pmk_obj, NULL, 0,
   4644                                     &mk_obj);
   4645    if (crv != CKR_MECHANISM_PARAM_INVALID) {
   4646        PKM_LogIt("C_DeriveKey returned as EXPECTED with 0x%08X, %-26s\n", crv,
   4647                  PKM_CK_RVtoStr(crv));
   4648    } else {
   4649        PKM_Error("C_DeriveKey did not fail  with  bad data \n");
   4650    }
   4651    goto out;
   4652 
   4653 correct:
   4654    /* Now derive the master secret key */
   4655    crv = pFunctionList->C_DeriveKey(hSession, &mk_mech, pmk_obj, NULL, 0,
   4656                                     &mk_obj);
   4657    if (crv == CKR_OK) {
   4658        PKM_LogIt("C_DeriveKey succeeded\n");
   4659    } else {
   4660        PKM_Error("C_DeriveKey failed with 0x%08X, %-26s\n", crv,
   4661                  PKM_CK_RVtoStr(crv));
   4662        return crv;
   4663    }
   4664 
   4665 out:
   4666    if (pmk_obj != CK_INVALID_HANDLE)
   4667        (void)pFunctionList->C_DestroyObject(hSession, pmk_obj);
   4668    if (mk_obj != CK_INVALID_HANDLE)
   4669        (void)pFunctionList->C_DestroyObject(hSession, mk_obj);
   4670    crv = pFunctionList->C_Logout(hSession);
   4671 
   4672    if (crv == CKR_OK) {
   4673        PKM_LogIt("C_Logout succeeded\n");
   4674    } else {
   4675        PKM_Error("C_Logout failed with 0x%08X, %-26s\n", crv,
   4676                  PKM_CK_RVtoStr(crv));
   4677        return crv;
   4678    }
   4679 
   4680    crv = pFunctionList->C_CloseSession(hSession);
   4681    if (crv != CKR_OK) {
   4682        PKM_Error("C_CloseSession failed with 0x%08X, %-26s\n", crv,
   4683                  PKM_CK_RVtoStr(crv));
   4684        return crv;
   4685    }
   4686    return (crv);
   4687 }
   4688 
   4689 CK_RV
   4690 PKM_TLSKeyAndMacDerive(CK_FUNCTION_LIST_PTR pFunctionList,
   4691                       CK_SLOT_ID *pSlotList, CK_ULONG slotID,
   4692                       CK_UTF8CHAR_PTR pwd, CK_ULONG pwdLen,
   4693                       CK_MECHANISM_TYPE mechType, enum_random_t rnd)
   4694 {
   4695    CK_SESSION_HANDLE hSession;
   4696    CK_RV crv;
   4697    CK_MECHANISM kmd_mech;
   4698    CK_MECHANISM skmd_mech;
   4699    CK_OBJECT_CLASS class = CKO_SECRET_KEY;
   4700    CK_KEY_TYPE type = CKK_GENERIC_SECRET;
   4701    CK_BBOOL derive_bool = ck_true;
   4702    CK_BBOOL sign_bool = ck_true, verify_bool = ck_true;
   4703    CK_BBOOL encrypt_bool = ck_true, decrypt_bool = ck_true;
   4704    CK_ULONG value_len;
   4705 
   4706    /*
   4707     * We arrange this template so that:
   4708     * . Attributes 0-6 are good for a MAC key comparison template.
   4709     * . Attributes 2-5 are good for the master key creation template.
   4710     * . Attributes 3-8 are good for a cipher key comparison template.
   4711     */
   4712    CK_ATTRIBUTE attrs[9];
   4713 
   4714    CK_OBJECT_HANDLE mk_obj = CK_INVALID_HANDLE;
   4715    CK_OBJECT_HANDLE derive_obj = CK_INVALID_HANDLE;
   4716    CK_SSL3_KEY_MAT_PARAMS km_params;
   4717    CK_SSL3_KEY_MAT_OUT kmo;
   4718    CK_BYTE IVClient[8];
   4719    CK_BYTE IVServer[8];
   4720 
   4721    NUMTESTS++; /* increment NUMTESTS */
   4722 
   4723    attrs[0].type = CKA_SIGN;
   4724    attrs[0].pValue = &sign_bool;
   4725    attrs[0].ulValueLen = sizeof(sign_bool);
   4726    attrs[1].type = CKA_VERIFY;
   4727    attrs[1].pValue = &verify_bool;
   4728    attrs[1].ulValueLen = sizeof(verify_bool);
   4729    attrs[2].type = CKA_KEY_TYPE;
   4730    attrs[2].pValue = &type;
   4731    attrs[2].ulValueLen = sizeof(type);
   4732    attrs[3].type = CKA_CLASS;
   4733    attrs[3].pValue = &class;
   4734    attrs[3].ulValueLen = sizeof(class);
   4735    attrs[4].type = CKA_DERIVE;
   4736    attrs[4].pValue = &derive_bool;
   4737    attrs[4].ulValueLen = sizeof(derive_bool);
   4738    attrs[5].type = CKA_VALUE;
   4739    attrs[5].pValue = NULL;
   4740    attrs[5].ulValueLen = 0;
   4741    attrs[6].type = CKA_VALUE_LEN;
   4742    attrs[6].pValue = &value_len;
   4743    attrs[6].ulValueLen = sizeof(value_len);
   4744    attrs[7].type = CKA_ENCRYPT;
   4745    attrs[7].pValue = &encrypt_bool;
   4746    attrs[7].ulValueLen = sizeof(encrypt_bool);
   4747    attrs[8].type = CKA_DECRYPT;
   4748    attrs[8].pValue = &decrypt_bool;
   4749    attrs[8].ulValueLen = sizeof(decrypt_bool);
   4750 
   4751    crv = pFunctionList->C_OpenSession(pSlotList[slotID], CKF_SERIAL_SESSION,
   4752                                       NULL, NULL, &hSession);
   4753    if (crv != CKR_OK) {
   4754        PKM_Error("C_OpenSession failed with 0x%08X, %-26s\n", crv,
   4755                  PKM_CK_RVtoStr(crv));
   4756        return crv;
   4757    }
   4758    crv = pFunctionList->C_Login(hSession, CKU_USER, pwd, pwdLen);
   4759    if (crv == CKR_OK) {
   4760        PKM_LogIt("C_Login with correct password succeeded\n");
   4761    } else {
   4762        PKM_Error("C_Login with correct password failed "
   4763                  "with 0x%08X, %-26s\n",
   4764                  crv, PKM_CK_RVtoStr(crv));
   4765        return crv;
   4766    }
   4767 
   4768    /* Before all, check if the mechanism is supported correctly */
   4769    if (MODE == FIPSMODE) {
   4770        crv = PKM_MechCheck(pFunctionList, hSession, mechType, CKF_DERIVE,
   4771                            CK_TRUE, 48, 48);
   4772 
   4773        if (crv != CKR_OK) {
   4774            PKM_Error("PKM_MechCheck failed with 0x%08X, %-26s\n", crv,
   4775                      PKM_CK_RVtoStr(crv));
   4776            return (crv);
   4777        }
   4778    }
   4779    kmd_mech.mechanism = mechType;
   4780    kmd_mech.pParameter = &km_params;
   4781    kmd_mech.ulParameterLen = sizeof(km_params);
   4782 
   4783    km_params.ulMacSizeInBits = 128; /* an MD5 based MAC */
   4784    km_params.ulKeySizeInBits = 192; /* 3DES key size */
   4785    km_params.ulIVSizeInBits = 64;   /* 3DES block size */
   4786    km_params.pReturnedKeyMaterial = &kmo;
   4787    km_params.bIsExport = ck_false;
   4788    kmo.hClientMacSecret = CK_INVALID_HANDLE;
   4789    kmo.hServerMacSecret = CK_INVALID_HANDLE;
   4790    kmo.hClientKey = CK_INVALID_HANDLE;
   4791    kmo.hServerKey = CK_INVALID_HANDLE;
   4792    kmo.pIVClient = IVClient;
   4793    kmo.pIVServer = IVServer;
   4794 
   4795    skmd_mech.mechanism = CKM_SSL3_PRE_MASTER_KEY_GEN;
   4796    skmd_mech.pParameter = &km_params;
   4797    skmd_mech.ulParameterLen = sizeof(km_params);
   4798 
   4799    crv = pFunctionList->C_GenerateKey(hSession, &skmd_mech,
   4800                                       &attrs[2],
   4801                                       4,
   4802                                       &mk_obj);
   4803    if (crv == CKR_OK) {
   4804        PKM_LogIt("C_GenerateKey succeeded\n");
   4805    } else {
   4806        PKM_Error("C_GenerateKey failed with 0x%08X, %-26s\n", crv,
   4807                  PKM_CK_RVtoStr(crv));
   4808        return crv;
   4809    }
   4810 
   4811    attrs[5].pValue = NULL;
   4812    attrs[5].ulValueLen = 0;
   4813 
   4814    km_params.RandomInfo.pClientRandom = (unsigned char *)TLSClientRandom;
   4815    km_params.RandomInfo.ulClientRandomLen =
   4816        sizeof(TLSClientRandom);
   4817    km_params.RandomInfo.pServerRandom = (unsigned char *)TLSServerRandom;
   4818    km_params.RandomInfo.ulServerRandomLen =
   4819        sizeof(TLSServerRandom);
   4820 
   4821    /* Test the bad cases */
   4822    switch (rnd) {
   4823        case CORRECT:
   4824            goto correct;
   4825 
   4826        case BOGUS_CLIENT_RANDOM:
   4827            km_params.RandomInfo.pClientRandom = NULL;
   4828            break;
   4829 
   4830        case BOGUS_CLIENT_RANDOM_LEN:
   4831            km_params.RandomInfo.ulClientRandomLen = 0;
   4832            break;
   4833 
   4834        case BOGUS_SERVER_RANDOM:
   4835            km_params.RandomInfo.pServerRandom = NULL;
   4836            break;
   4837 
   4838        case BOGUS_SERVER_RANDOM_LEN:
   4839            km_params.RandomInfo.ulServerRandomLen = 0;
   4840            break;
   4841    }
   4842    crv = pFunctionList->C_DeriveKey(hSession, &kmd_mech, mk_obj, NULL, 0,
   4843                                     &derive_obj);
   4844    if (crv != CKR_MECHANISM_PARAM_INVALID) {
   4845        PKM_Error("key materials derivation returned unexpected "
   4846                  "error 0x%08X, %-26s\n",
   4847                  crv, PKM_CK_RVtoStr(crv));
   4848        (void)pFunctionList->C_DestroyObject(hSession, mk_obj);
   4849        return (CKR_FUNCTION_FAILED);
   4850    }
   4851    return (CKR_OK);
   4852 
   4853 correct:
   4854    /*
   4855     * Then use the master key and the client 'n server random data to
   4856     * derive the key materials
   4857     */
   4858    crv = pFunctionList->C_DeriveKey(hSession, &kmd_mech, mk_obj, NULL, 0,
   4859                                     &derive_obj);
   4860    if (crv != CKR_OK) {
   4861        PKM_Error("Cannot derive the key materials, crv 0x%08X, %-26s\n",
   4862                  crv, PKM_CK_RVtoStr(crv));
   4863        (void)pFunctionList->C_DestroyObject(hSession, mk_obj);
   4864        return (crv);
   4865    }
   4866 
   4867    if (mk_obj != CK_INVALID_HANDLE)
   4868        (void)pFunctionList->C_DestroyObject(hSession, mk_obj);
   4869    if (kmo.hClientMacSecret != CK_INVALID_HANDLE)
   4870        (void)pFunctionList->C_DestroyObject(hSession, kmo.hClientMacSecret);
   4871    if (kmo.hServerMacSecret != CK_INVALID_HANDLE)
   4872        (void)pFunctionList->C_DestroyObject(hSession, kmo.hServerMacSecret);
   4873    if (kmo.hClientKey != CK_INVALID_HANDLE)
   4874        (void)pFunctionList->C_DestroyObject(hSession, kmo.hClientKey);
   4875    if (kmo.hServerKey != CK_INVALID_HANDLE)
   4876        (void)pFunctionList->C_DestroyObject(hSession, kmo.hServerKey);
   4877 
   4878    crv = pFunctionList->C_Logout(hSession);
   4879    if (crv == CKR_OK) {
   4880        PKM_LogIt("C_Logout succeeded\n");
   4881    } else {
   4882        PKM_Error("C_Logout failed with 0x%08X, %-26s\n", crv,
   4883                  PKM_CK_RVtoStr(crv));
   4884        return crv;
   4885    }
   4886    crv = pFunctionList->C_CloseSession(hSession);
   4887    if (crv != CKR_OK) {
   4888        PKM_Error("C_CloseSession failed with 0x%08X, %-26s\n", crv,
   4889                  PKM_CK_RVtoStr(crv));
   4890        return crv;
   4891    }
   4892 
   4893    return (crv);
   4894 }
   4895 
   4896 CK_RV
   4897 PKM_DualFuncSign(CK_FUNCTION_LIST_PTR pFunctionList,
   4898                 CK_SESSION_HANDLE hRwSession,
   4899                 CK_OBJECT_HANDLE publicKey, CK_OBJECT_HANDLE privateKey,
   4900                 CK_MECHANISM *sigMech,
   4901                 CK_OBJECT_HANDLE secretKey, CK_MECHANISM *cryptMech,
   4902                 const CK_BYTE *pData, CK_ULONG pDataLen)
   4903 {
   4904 
   4905    CK_RV crv = CKR_OK;
   4906    CK_BYTE encryptedData[MAX_CIPHER_SZ];
   4907    CK_ULONG ulEncryptedDataLen = 0;
   4908    CK_ULONG ulLastUpdateSize = 0;
   4909    CK_BYTE sig[MAX_SIG_SZ];
   4910    CK_ULONG ulSigLen = 0;
   4911    CK_BYTE data[MAX_DATA_SZ];
   4912    CK_ULONG ulDataLen = 0;
   4913 
   4914    memset(encryptedData, 0, sizeof(encryptedData));
   4915    memset(sig, 0, sizeof(sig));
   4916    memset(data, 0, sizeof(data));
   4917 
   4918    NUMTESTS++; /* increment NUMTESTS */
   4919 
   4920    /* Check that the mechanism is Multi-part */
   4921    if (sigMech->mechanism == CKM_ECDSA || sigMech->mechanism == CKM_RSA_PKCS) {
   4922        PKM_Error("PKM_DualFuncSign must be called with a Multi-part "
   4923                  "operation mechanism\n");
   4924        return CKR_DEVICE_ERROR;
   4925    }
   4926 
   4927    /* Sign and Encrypt */
   4928    if (privateKey == 0 && publicKey == 0) {
   4929        crv = pFunctionList->C_SignInit(hRwSession, sigMech, secretKey);
   4930        if (crv != CKR_OK) {
   4931            PKM_Error("C_SignInit failed with 0x%08X, %-26s\n", crv,
   4932                      PKM_CK_RVtoStr(crv));
   4933            return crv;
   4934        }
   4935    } else {
   4936        crv = pFunctionList->C_SignInit(hRwSession, sigMech, privateKey);
   4937        if (crv != CKR_OK) {
   4938            PKM_Error("C_SignInit failed with 0x%08X, %-26s\n", crv,
   4939                      PKM_CK_RVtoStr(crv));
   4940            return crv;
   4941        }
   4942    }
   4943    crv = pFunctionList->C_EncryptInit(hRwSession, cryptMech, secretKey);
   4944    if (crv != CKR_OK) {
   4945        PKM_Error("C_EncryptInit failed with 0x%08X, %-26s\n", crv,
   4946                  PKM_CK_RVtoStr(crv));
   4947        return crv;
   4948    }
   4949 
   4950    ulEncryptedDataLen = sizeof(encryptedData);
   4951    crv = pFunctionList->C_SignEncryptUpdate(hRwSession, (CK_BYTE *)pData,
   4952                                             pDataLen,
   4953                                             encryptedData,
   4954                                             &ulEncryptedDataLen);
   4955    if (crv != CKR_OK) {
   4956        PKM_Error("C_Sign failed with 0x%08X, %-26s\n", crv,
   4957                  PKM_CK_RVtoStr(crv));
   4958        return crv;
   4959    }
   4960 
   4961    ulLastUpdateSize = sizeof(encryptedData) - ulEncryptedDataLen;
   4962    crv = pFunctionList->C_EncryptFinal(hRwSession,
   4963                                        (CK_BYTE *)&encryptedData[ulEncryptedDataLen], &ulLastUpdateSize);
   4964    if (crv != CKR_OK) {
   4965        PKM_Error("C_EncryptFinal failed with 0x%08X, %-26s\n", crv,
   4966                  PKM_CK_RVtoStr(crv));
   4967        return crv;
   4968    }
   4969    ulEncryptedDataLen = ulEncryptedDataLen + ulLastUpdateSize;
   4970    ulSigLen = sizeof(sig);
   4971    crv = pFunctionList->C_SignFinal(hRwSession, sig, &ulSigLen);
   4972    if (crv != CKR_OK) {
   4973        PKM_Error("C_SignFinal failed with 0x%08X, %-26s\n", crv,
   4974                  PKM_CK_RVtoStr(crv));
   4975        return crv;
   4976    }
   4977 
   4978    /* Decrypt and Verify */
   4979 
   4980    crv = pFunctionList->C_DecryptInit(hRwSession, cryptMech, secretKey);
   4981    if (crv != CKR_OK) {
   4982        PKM_Error("C_DecryptInit failed with 0x%08X, %-26s\n", crv,
   4983                  PKM_CK_RVtoStr(crv));
   4984        return crv;
   4985    }
   4986    crv = pFunctionList->C_VerifyInit(hRwSession, sigMech,
   4987                                      publicKey);
   4988    if (crv != CKR_OK) {
   4989        PKM_Error("C_VerifyInit failed with 0x%08X, %-26s\n", crv,
   4990                  PKM_CK_RVtoStr(crv));
   4991        return crv;
   4992    }
   4993 
   4994    ulDataLen = sizeof(data);
   4995    crv = pFunctionList->C_DecryptVerifyUpdate(hRwSession,
   4996                                               encryptedData,
   4997                                               ulEncryptedDataLen,
   4998                                               data, &ulDataLen);
   4999    if (crv != CKR_OK) {
   5000        PKM_Error("C_DecryptVerifyUpdate failed with 0x%08X, %-26s\n", crv,
   5001                  PKM_CK_RVtoStr(crv));
   5002        return crv;
   5003    }
   5004    ulLastUpdateSize = sizeof(data) - ulDataLen;
   5005    /* Get last little piece of plaintext.  Should have length 0 */
   5006    crv = pFunctionList->C_DecryptFinal(hRwSession, &data[ulDataLen],
   5007                                        &ulLastUpdateSize);
   5008    if (crv != CKR_OK) {
   5009        PKM_Error("C_DecryptFinal failed with 0x%08X, %-26s\n", crv,
   5010                  PKM_CK_RVtoStr(crv));
   5011        return crv;
   5012    }
   5013 
   5014    if (ulLastUpdateSize != 0) {
   5015        crv = pFunctionList->C_VerifyUpdate(hRwSession, &data[ulDataLen],
   5016                                            ulLastUpdateSize);
   5017        if (crv != CKR_OK) {
   5018            PKM_Error("C_DecryptFinal failed with 0x%08X, %-26s\n", crv,
   5019                      PKM_CK_RVtoStr(crv));
   5020            return crv;
   5021        }
   5022    }
   5023    ulDataLen = ulDataLen + ulLastUpdateSize;
   5024 
   5025    /* input for the verify operation is the decrypted data */
   5026    crv = pFunctionList->C_VerifyFinal(hRwSession, sig, ulSigLen);
   5027    if (crv == CKR_OK) {
   5028        PKM_LogIt("C_VerifyFinal succeeded\n");
   5029    } else {
   5030        PKM_Error("C_VerifyFinal failed with 0x%08X, %-26s\n", crv,
   5031                  PKM_CK_RVtoStr(crv));
   5032        return crv;
   5033    }
   5034 
   5035    /* Comparison of Decrypted data with inputed data */
   5036    if ((ulDataLen == pDataLen) &&
   5037        (memcmp(data, pData, pDataLen) == 0)) {
   5038        PKM_LogIt("PKM_DualFuncSign decrypt test case passed\n");
   5039    } else {
   5040        PKM_Error("PKM_DualFuncSign derypt test case failed\n");
   5041    }
   5042 
   5043    return crv;
   5044 }
   5045 
   5046 CK_RV
   5047 PKM_Digest(CK_FUNCTION_LIST_PTR pFunctionList,
   5048           CK_SESSION_HANDLE hSession,
   5049           CK_MECHANISM *digestMech, CK_OBJECT_HANDLE hSecretKey,
   5050           const CK_BYTE *pData, CK_ULONG pDataLen)
   5051 {
   5052    CK_RV crv = CKR_OK;
   5053    CK_BYTE digest1[MAX_DIGEST_SZ];
   5054    CK_ULONG digest1Len = 0;
   5055    CK_BYTE digest2[MAX_DIGEST_SZ];
   5056    CK_ULONG digest2Len = 0;
   5057 
   5058    /* Tested with CKM_SHA_1, CKM_SHA224, CKM_SHA256, CKM_SHA384, CKM_SHA512 */
   5059 
   5060    memset(digest1, 0, sizeof(digest1));
   5061    memset(digest2, 0, sizeof(digest2));
   5062 
   5063    NUMTESTS++; /* increment NUMTESTS */
   5064 
   5065    crv = pFunctionList->C_DigestInit(hSession, digestMech);
   5066    if (crv != CKR_OK) {
   5067        PKM_Error("C_SignInit failed with 0x%08X, %-26s\n", crv,
   5068                  PKM_CK_RVtoStr(crv));
   5069        return crv;
   5070    }
   5071    digest1Len = sizeof(digest1);
   5072    crv = pFunctionList->C_Digest(hSession, (CK_BYTE *)pData, pDataLen,
   5073                                  digest1, &digest1Len);
   5074    if (crv != CKR_OK) {
   5075        PKM_Error("C_Sign failed with 0x%08X, %-26s\n", crv,
   5076                  PKM_CK_RVtoStr(crv));
   5077        return crv;
   5078    }
   5079 
   5080    crv = pFunctionList->C_DigestInit(hSession, digestMech);
   5081    if (crv != CKR_OK) {
   5082        PKM_Error("C_DigestInit failed with 0x%08X, %-26s\n", crv,
   5083                  PKM_CK_RVtoStr(crv));
   5084        return crv;
   5085    }
   5086 
   5087    crv = pFunctionList->C_DigestUpdate(hSession, (CK_BYTE *)pData, pDataLen);
   5088    if (crv != CKR_OK) {
   5089        PKM_Error("C_DigestUpdate failed with 0x%08X, %-26s\n", crv,
   5090                  PKM_CK_RVtoStr(crv));
   5091        return crv;
   5092    }
   5093 
   5094    /* C_DigestKey continues a multiple-part message-digesting operation by*/
   5095    /* digesting the value of a secret key. (only used with C_DigestUpdate)*/
   5096    if (hSecretKey != 0) {
   5097        crv = pFunctionList->C_DigestKey(hSession, hSecretKey);
   5098        if (crv != CKR_OK) {
   5099            PKM_Error("C_DigestKey failed with 0x%08X, %-26s\n", crv,
   5100                      PKM_CK_RVtoStr(crv));
   5101            return crv;
   5102        }
   5103    }
   5104 
   5105    digest2Len = sizeof(digest2);
   5106    crv = pFunctionList->C_DigestFinal(hSession, digest2, &digest2Len);
   5107    if (crv != CKR_OK) {
   5108        PKM_Error("C_DigestFinal failed with 0x%08X, %-26s\n", crv,
   5109                  PKM_CK_RVtoStr(crv));
   5110        return crv;
   5111    }
   5112 
   5113    if (hSecretKey == 0) {
   5114        /* did not digest a secret key so digests should equal */
   5115        if ((digest1Len == digest2Len) &&
   5116            (memcmp(digest1, digest2, digest1Len) == 0)) {
   5117            PKM_LogIt("Single and Multiple-part message digest "
   5118                      "operations successful\n");
   5119        } else {
   5120            PKM_Error("Single and Multiple-part message digest "
   5121                      "operations failed\n");
   5122        }
   5123    } else {
   5124        if (digest1Len == digest2Len) {
   5125            PKM_LogIt("PKM_Digest Single and Multiple-part message digest "
   5126                      "operations successful\n");
   5127        } else {
   5128            PKM_Error("PKM_Digest Single and Multiple-part message digest "
   5129                      "operations failed\n");
   5130        }
   5131    }
   5132 
   5133    return crv;
   5134 }
   5135 
   5136 char *
   5137 PKM_FilePasswd(char *pwFile)
   5138 {
   5139    unsigned char phrase[500];
   5140    PRFileDesc *fd;
   5141    PRInt32 nb;
   5142    int i;
   5143 
   5144    if (!pwFile)
   5145        return 0;
   5146 
   5147    fd = PR_Open(pwFile, PR_RDONLY, 0);
   5148    if (!fd) {
   5149        fprintf(stderr, "No password file \"%s\" exists.\n", pwFile);
   5150        return NULL;
   5151    }
   5152 
   5153    nb = PR_Read(fd, phrase, sizeof(phrase));
   5154 
   5155    PR_Close(fd);
   5156    /* handle the Windows EOL case */
   5157    i = 0;
   5158    while (phrase[i] != '\r' && phrase[i] != '\n' && i < nb)
   5159        i++;
   5160    phrase[i] = '\0';
   5161    if (nb == 0) {
   5162        fprintf(stderr, "password file contains no data\n");
   5163        return NULL;
   5164    }
   5165    return (char *)strdup((char *)phrase);
   5166 }
   5167 
   5168 void
   5169 PKM_Help()
   5170 {
   5171    PRFileDesc *debug_out = PR_GetSpecialFD(PR_StandardError);
   5172    PR_fprintf(debug_out, "pk11mode test program usage:\n");
   5173    PR_fprintf(debug_out, "\t-f <file>   Password File : echo pw > file \n");
   5174    PR_fprintf(debug_out, "\t-F          Disable Unix fork tests\n");
   5175    PR_fprintf(debug_out, "\t-n          Non Fips Mode \n");
   5176    PR_fprintf(debug_out, "\t-d <path>   Database path location\n");
   5177    PR_fprintf(debug_out, "\t-p <prefix> DataBase prefix\n");
   5178    PR_fprintf(debug_out, "\t-v          verbose\n");
   5179    PR_fprintf(debug_out, "\t-h          this help message\n");
   5180    exit(1);
   5181 }
   5182 
   5183 void
   5184 PKM_CheckPath(char *string)
   5185 {
   5186    char *src;
   5187    char *dest;
   5188 
   5189    /*
   5190     * windows support convert any back slashes to
   5191     * forward slashes.
   5192     */
   5193    for (src = string, dest = string; *src; src++, dest++) {
   5194        if (*src == '\\') {
   5195            *dest = '/';
   5196        }
   5197    }
   5198    dest--;
   5199    /* if the last char is a / set it to 0 */
   5200    if (*dest == '/')
   5201        *dest = 0;
   5202 }
   5203 
   5204 CK_RV
   5205 PKM_ForkCheck(int expected, CK_FUNCTION_LIST_PTR fList,
   5206              PRBool forkAssert, CK_C_INITIALIZE_ARGS_NSS *initArgs)
   5207 {
   5208    CK_RV crv = CKR_OK;
   5209 #ifndef NO_FORK_CHECK
   5210    int rc = -1;
   5211    pid_t child, ret;
   5212    NUMTESTS++; /* increment NUMTESTS */
   5213    if (forkAssert) {
   5214        putenv("NSS_STRICT_NOFORK=1");
   5215    } else {
   5216        putenv("NSS_STRICT_NOFORK=0");
   5217    }
   5218    child = fork();
   5219    switch (child) {
   5220        case -1:
   5221            PKM_Error("Fork failed.\n");
   5222            crv = CKR_DEVICE_ERROR;
   5223            break;
   5224        case 0:
   5225            if (fList) {
   5226                if (!initArgs) {
   5227                    /* If softoken is loaded, make a PKCS#11 call to C_GetTokenInfo
   5228                     * in the child. This call should always fail.
   5229                     * If softoken is uninitialized,
   5230                     * it fails with CKR_CRYPTOKI_NOT_INITIALIZED.
   5231                     * If it was initialized in the parent, the fork check should
   5232                     * kick in, and make it return CKR_DEVICE_ERROR.
   5233                     */
   5234                    CK_RV child_crv = fList->C_GetTokenInfo(0, NULL);
   5235                    exit(child_crv & 255);
   5236                } else {
   5237                    /* If softoken is loaded, make a PKCS#11 call to C_Initialize
   5238                     * in the child. This call should always fail.
   5239                     * If softoken is uninitialized, this should succeed.
   5240                     * If it was initialized in the parent, the fork check should
   5241                     * kick in, and make it return CKR_DEVICE_ERROR.
   5242                     */
   5243                    CK_RV child_crv = fList->C_Initialize(initArgs);
   5244                    if (CKR_OK == child_crv) {
   5245                        child_crv = fList->C_Finalize(NULL);
   5246                    }
   5247                    exit(child_crv & 255);
   5248                }
   5249            }
   5250            exit(expected & 255);
   5251        default:
   5252            PKM_LogIt("Fork succeeded.\n");
   5253            ret = wait(&rc);
   5254            if (ret != child || (!WIFEXITED(rc)) ||
   5255                ((expected & 255) != (WEXITSTATUS(rc) & 255))) {
   5256                int retStatus = -1;
   5257                if (WIFEXITED(rc)) {
   5258                    retStatus = WEXITSTATUS(rc);
   5259                }
   5260                PKM_Error("Child misbehaved.\n");
   5261                printf("Child return status : %d.\n", retStatus & 255);
   5262                crv = CKR_DEVICE_ERROR;
   5263            }
   5264            break;
   5265    }
   5266 #endif
   5267    return crv;
   5268 }