/* * COPYRIGHT (c) International Business Machines Corp. 2005-2017 * * This program is provided under the terms of the Common Public License, * version 1.0 (CPL-1.0). Any use, reproduction or distribution for this * software constitutes recipient's acceptance of CPL-1.0 terms which can be * found in the file LICENSE file or at * https://opensource.org/licenses/cpl1.0.php */ #include #include #include #include #include #include #include "pkcs11types.h" #include "regress.h" #include "digest.h" #include "common.c" #define DIGEST_UPDATE_SIZE 32 /** Tests messge digest with published test vectors. **/ CK_RV do_Digest(struct digest_test_suite_info *tsuite) { unsigned int i; CK_BYTE data[MAX_DATA_SIZE]; CK_ULONG data_len; CK_BYTE actual[MAX_HASH_SIZE]; CK_ULONG actual_len; CK_BYTE expected[MAX_HASH_SIZE]; CK_ULONG expected_len; CK_MECHANISM mech; CK_SESSION_HANDLE session; CK_SLOT_ID slot_id = SLOT_ID; CK_ULONG flags; CK_RV rc; /** begin test suite **/ testsuite_begin("%s Digest.", tsuite->name); testcase_rw_session(); /** skip test if mech is not supported with this slot **/ if (!mech_supported(slot_id, tsuite->mech.mechanism)) { testsuite_skip(tsuite->tvcount, "mechanism %s is not supported with slot %ld", tsuite->name, slot_id); goto testcase_cleanup; } /** iterate over test vectors **/ for (i = 0; i < tsuite->tvcount; i++) { /** begin test **/ testcase_begin("Starting %s Digest with test vector %d.", tsuite->name, i); rc = CKR_OK; // set rc /** clear buffers **/ memset(data, 0, sizeof(data)); memset(actual, 0, sizeof(actual)); memset(expected, 0, sizeof(expected)); /** get test vector info **/ data_len = tsuite->tv[i].data_len; expected_len = tsuite->tv[i].hash_len; memcpy(data, tsuite->tv[i].data, data_len); memcpy(expected, tsuite->tv[i].hash, expected_len); /** get mech **/ mech = tsuite->mech; /** initialize single digest **/ rc = funcs->C_DigestInit(session, &mech); if (rc != CKR_OK) { testcase_error("C_DigestInit rc=%s", p11_get_ckr(rc)); goto testcase_cleanup; } actual_len = sizeof(actual); // set digest buffer size /** do single digest **/ rc = funcs->C_Digest(session, data, data_len, actual, &actual_len); if (rc != CKR_OK) { testcase_error("C_Digest rc=%s", p11_get_ckr(rc)); goto testcase_cleanup; } /** compare digest results with expected results **/ testcase_new_assertion(); if (actual_len != expected_len) { testcase_fail("hashed data length does not match test " "vector's hashed data length.\n expected" " length=%ld, found length=%ld.", expected_len, actual_len); } else if (memcmp(actual, expected, expected_len)) { testcase_fail("hashed data does not match test vector's" " hashed data."); } else { testcase_pass("%s Digest with test vector %d passed.", tsuite->name, i); } } testcase_cleanup: rc = funcs->C_CloseAllSessions(slot_id); if (rc != CKR_OK) { testcase_error("C_CloseAllSessions rc=%s", p11_get_ckr(rc)); } return rc; } /** Tests multipart message digest with published test vectors. **/ CK_RV do_DigestUpdate(struct digest_test_suite_info * tsuite) { unsigned int i; CK_BYTE data[MAX_DATA_SIZE]; CK_ULONG data_len, data_done; CK_BYTE actual[MAX_HASH_SIZE]; CK_ULONG actual_len; CK_BYTE expected[MAX_HASH_SIZE]; CK_ULONG len, expected_len; CK_MECHANISM mech; CK_SESSION_HANDLE session; CK_SLOT_ID slot_id = SLOT_ID; CK_ULONG flags; CK_RV rc; /** begin test **/ testsuite_begin("Starting %s Multipart Digest.", tsuite->name); testcase_rw_session(); /** skip test if mech is not supported with this slot **/ if (!mech_supported(slot_id, tsuite->mech.mechanism)) { testsuite_skip(tsuite->tvcount, "mechanism %s is not supported with slot %ld", tsuite->name, slot_id); goto testcase_cleanup; } /** iterate over test vectors **/ for (i = 0; i < tsuite->tvcount; i++) { /** begin test **/ testcase_begin("Starting %s Multipart Digest with test vector %d.", tsuite->name, i); rc = CKR_OK; // set rc /** clear buffers **/ memset(data, 0, sizeof(data)); memset(actual, 0, sizeof(actual)); memset(expected, 0, sizeof(expected)); /** get test vector info **/ data_done = 0; data_len = tsuite->tv[i].data_len; expected_len = tsuite->tv[i].hash_len; memcpy(data, tsuite->tv[i].data, data_len); memcpy(expected, tsuite->tv[i].hash, expected_len); /** get mechanism **/ mech = tsuite->mech; /** initialize multipart digest **/ rc = funcs->C_DigestInit(session, &mech); if (rc != CKR_OK) { testcase_error("C_DigestInit rc=%s", p11_get_ckr(rc)); goto testcase_cleanup; } actual_len = sizeof(actual); /* do multipart digest * if test vector contains chunks, use that. * Otherwise, just call update on entire data. * * Note: for chunks, -1 is NULL, and 0 is empty string, * and a value > 0 is amount of data from test vector's * plaintext data. This way we test chunks that * are NULL or empty string when updating. */ if (tsuite->tv[i].num_chunks) { int j; CK_BYTE *data_chunk = NULL; for (j = 0; j < tsuite->tv[i].num_chunks; j++) { if (tsuite->tv[i].chunks[j] == -1) { len = 0; data_chunk = NULL; } else if (tsuite->tv[i].chunks[j] == 0) { len = 0; data_chunk = (CK_BYTE *) ""; } else { len = tsuite->tv[i].chunks[j]; data_chunk = data + data_done; } rc = funcs->C_DigestUpdate(session, data_chunk, len); if (rc != CKR_OK) { testcase_error("C_DigestUpdate rc=%s", p11_get_ckr(rc)); goto testcase_cleanup; } data_done += len; } } else { rc = funcs->C_DigestUpdate(session, data, data_len); if (rc != CKR_OK) { testcase_error("C_DigestUpdate rc=%s", p11_get_ckr(rc)); goto testcase_cleanup; } } /** finalize multipart digest **/ rc = funcs->C_DigestFinal(session, actual, &actual_len); if (rc != CKR_OK) { testcase_error("C_DigestFinal rc=%s", p11_get_ckr(rc)); goto testcase_cleanup; } /** compare multipart digest results with expected results **/ testcase_new_assertion(); if (actual_len != expected_len) { testcase_fail("hashed multipart data length does not " "match test vector's hashed data length.\n"); } else if (memcmp(actual, expected, expected_len)) { testcase_fail("hashed multipart data does not match " "test vector's hashed data.\n"); } else { testcase_pass("%s Multipart Digest with test vector " "%d passed.", tsuite->name, i); } } testcase_cleanup: rc = funcs->C_CloseAllSessions(slot_id); if (rc != CKR_OK) { testcase_error("C_CloseAllSessions rc=%s", p11_get_ckr(rc)); } return rc; } /** Tests signature verification with published test vectors. **/ CK_RV do_Sign_FIPS_HMAC_GENERAL(struct HMAC_TEST_SUITE_INFO * tsuite) { unsigned int i; CK_MECHANISM mech; CK_BYTE key[MAX_KEY_SIZE], data[MAX_DATA_SIZE]; CK_ULONG key_len, data_len, actual_mac_len, expected_mac_len, mac_size; CK_BYTE actual_mac[MAX_HASH_SIZE], expected_mac[MAX_HASH_SIZE]; CK_SESSION_HANDLE session; CK_SLOT_ID slot_id = SLOT_ID; CK_ULONG flags; CK_RV rc; CK_OBJECT_HANDLE h_key; CK_BYTE user_pin[PKCS11_MAX_PIN_LEN]; CK_ULONG user_pin_len; /** begin testsuite **/ testsuite_begin("%s Sign.", tsuite->name); testcase_rw_session(); testcase_user_login(); rc = CKR_OK; // set rc /** skip test if mech is not supported with this slot **/ if (!mech_supported(SLOT_ID, tsuite->mech.mechanism)) { testsuite_skip(tsuite->tvcount, "mechanism %s is not supported with slot %ld", tsuite->name, slot_id); goto testcase_cleanup; } /** iterate over test vectors **/ for (i = 0; i < tsuite->tvcount; i++) { /** begin test **/ testcase_begin("Sign %s with test vector %d.", tsuite->name, i); /** get mechanism and set parameter **/ mech = tsuite->mech; mac_size = tsuite->tv[i].mac_len; mech.ulParameterLen = sizeof(CK_ULONG); mech.pParameter = &mac_size; /** clear buffers **/ memset(key, 0, sizeof(key)); memset(data, 0, sizeof(data)); memset(actual_mac, 0, sizeof(actual_mac)); memset(expected_mac, 0, sizeof(expected_mac)); /** get test vector info **/ data_len = tsuite->tv[i].data_len; actual_mac_len = sizeof(actual_mac); expected_mac_len = tsuite->tv[i].mac_len; key_len = tsuite->tv[i].key_len; memcpy(key, tsuite->tv[i].key, key_len); memcpy(data, tsuite->tv[i].data, data_len); memcpy(expected_mac, tsuite->tv[i].mac, expected_mac_len); /** create key object **/ rc = create_GenericSecretKey(session, key, key_len, &h_key); if (rc != CKR_OK) { testcase_error("create_GenericSecretKey rc=%s", p11_get_ckr(rc)); goto error; } /** initialize signing **/ rc = funcs->C_SignInit(session, &mech, h_key); if (rc != CKR_OK) { testcase_error("C_SignInit rc=%s", p11_get_ckr(rc)); goto error; } /** do signing **/ rc = funcs->C_Sign(session, data, data_len, actual_mac, &actual_mac_len); if (rc != CKR_OK) { testcase_error("C_Sign rc=%s", p11_get_ckr(rc)); goto error; } /** compare sign/verify results with expected results **/ testcase_new_assertion(); if (actual_mac_len != expected_mac_len) { testcase_fail("hashed data length does not match test " "vector's hashed data length\nexpected " "length=%ld, found length=%ld", expected_mac_len, actual_mac_len); goto error; } else if (memcmp(actual_mac, expected_mac, expected_mac_len)) { testcase_fail("hashed data does not match test " "vector's hashed data"); goto error; } else { testcase_pass("%s Sign with test vector %d passed", tsuite->name, i); } error: /** clean up **/ rc = funcs->C_DestroyObject(session, h_key); if (rc != CKR_OK) { testcase_error("C_DestroyObject rc=%s.", p11_get_ckr(rc)); goto testcase_cleanup; } } testcase_cleanup: testcase_user_logout(); rc = funcs->C_CloseAllSessions(slot_id); if (rc != CKR_OK) { testcase_error("C_CloseAllSessions rc=%s", p11_get_ckr(rc)); } return rc; } /** Tests signature verification with published test vectors. **/ CK_RV do_Verify_FIPS_HMAC_GENERAL(struct HMAC_TEST_SUITE_INFO * tsuite) { unsigned int i; CK_MECHANISM mech; CK_BYTE key[MAX_KEY_SIZE], data[MAX_DATA_SIZE]; CK_ULONG key_len, data_len, expected_mac_len, mac_size; CK_BYTE expected_mac[MAX_HASH_SIZE]; CK_SESSION_HANDLE session; CK_SLOT_ID slot_id = SLOT_ID; CK_ULONG flags; CK_RV rc; CK_OBJECT_HANDLE h_key; CK_BYTE user_pin[PKCS11_MAX_PIN_LEN]; CK_ULONG user_pin_len; /** begin testsuite **/ testsuite_begin("%s Verify.", tsuite->name); testcase_rw_session(); testcase_user_login(); rc = CKR_OK; // set rc /** skip test if mech is not supported with this slot **/ if (!mech_supported(SLOT_ID, tsuite->mech.mechanism)) { testsuite_skip(tsuite->tvcount, "mechanism %s is not supported with slot %ld", tsuite->name, slot_id); goto testcase_cleanup; } /** iterate over test vectors **/ for (i = 0; i < tsuite->tvcount; i++) { /** begin test **/ testcase_begin("Verify %s with test vector %d.", tsuite->name, i); /** get mechanism and set parameter **/ mech = tsuite->mech; mac_size = tsuite->tv[i].mac_len; mech.ulParameterLen = sizeof(CK_ULONG); mech.pParameter = &mac_size; /** clear buffers **/ memset(key, 0, sizeof(key)); memset(data, 0, sizeof(data)); memset(expected_mac, 0, sizeof(expected_mac)); /** get test vector info **/ data_len = tsuite->tv[i].data_len; expected_mac_len = tsuite->tv[i].mac_len; key_len = tsuite->tv[i].key_len; memcpy(key, tsuite->tv[i].key, key_len); memcpy(data, tsuite->tv[i].data, data_len); memcpy(expected_mac, tsuite->tv[i].mac, expected_mac_len); /** create key object **/ rc = create_GenericSecretKey(session, key, key_len, &h_key); if (rc != CKR_OK) { testcase_error("create_GenericSecretKey rc=%s", p11_get_ckr(rc)); goto error; } /** initilaize verification **/ rc = funcs->C_VerifyInit(session, &mech, h_key); if (rc != CKR_OK) { testcase_error("C_VerifyInit rc=%s", p11_get_ckr(rc)); goto error; } /** see if signature verifies **/ testcase_new_assertion(); /** do verification **/ rc = funcs->C_Verify(session, data, data_len, expected_mac, expected_mac_len); if (rc != CKR_OK) testcase_fail("C_Verify rc=%s", p11_get_ckr(rc)); else testcase_pass("%s C_Verify with test vector %d passed", tsuite->name, i); error: /** clean up **/ rc = funcs->C_DestroyObject(session, h_key); if (rc != CKR_OK) { testcase_error("C_DestroyObject rc=%s.", p11_get_ckr(rc)); goto testcase_cleanup; } } testcase_cleanup: testcase_user_logout(); rc = funcs->C_CloseAllSessions(slot_id); if (rc != CKR_OK) { testcase_error("C_CloseAllSessions rc=%s", p11_get_ckr(rc)); } return rc; } /** Tests signature generation with published test vectors. **/ CK_RV do_Sign_FIPS_HMAC(struct HMAC_TEST_SUITE_INFO * tsuite) { unsigned int i; CK_MECHANISM mech; CK_BYTE key[MAX_KEY_SIZE], data[MAX_DATA_SIZE]; CK_ULONG key_len, data_len, actual_mac_len, expected_mac_len; CK_BYTE actual_mac[MAX_HASH_SIZE], expected_mac[MAX_HASH_SIZE]; CK_SESSION_HANDLE session; CK_SLOT_ID slot_id = SLOT_ID; CK_ULONG flags; CK_RV rc; CK_OBJECT_HANDLE h_key; CK_BYTE user_pin[PKCS11_MAX_PIN_LEN]; CK_ULONG user_pin_len; /** begin testsuite **/ testsuite_begin("%s Sign.", tsuite->name); testcase_rw_session(); testcase_user_login(); rc = CKR_OK; // set rc /** skip test if mech is not supported with this slot **/ if (!mech_supported(SLOT_ID, tsuite->mech.mechanism)) { testsuite_skip(tsuite->tvcount, "mechanism %s is not supported with slot %ld", tsuite->name, slot_id); goto testcase_cleanup; } /** iterate over test vectors **/ for (i = 0; i < tsuite->tvcount; i++) { /** begin test **/ testcase_begin("Sign %s with test vector %d.", tsuite->name, i); /** get mechanism **/ mech = tsuite->mech; /* only run hmac testcases with appropriate mac length */ switch (mech.mechanism) { case CKM_SHA_1_HMAC: if (tsuite->tv[i].mac_len != 20) { testcase_skip("Skip, this testcase is not" " for SHA1 HMAC"); continue; } break; case CKM_SHA224_HMAC: if (tsuite->tv[i].mac_len != 28) { testcase_skip("Skip, this testcase is not" " for SHA224 HMAC"); continue; } break; case CKM_SHA256_HMAC: if (tsuite->tv[i].mac_len != 32) { testcase_skip("Skip, this testcase is not" " for SHA256 HMAC"); continue; } break; case CKM_SHA384_HMAC: if (tsuite->tv[i].mac_len != 48) { testcase_skip("Skip, this testcase is not" " for SHA384 HMAC"); continue; } break; case CKM_SHA512_HMAC: if (tsuite->tv[i].mac_len != 64) { testcase_skip("Skip, this testcase is not" " for SHA512 HMAC"); continue; } break; default: testcase_error("Invalid Mechanism\n"); goto testcase_cleanup; } /** clear buffers **/ memset(key, 0, sizeof(key)); memset(data, 0, sizeof(data)); memset(actual_mac, 0, sizeof(actual_mac)); memset(expected_mac, 0, sizeof(expected_mac)); /** get test vector info **/ data_len = tsuite->tv[i].data_len; actual_mac_len = sizeof(actual_mac); expected_mac_len = tsuite->tv[i].mac_len; key_len = tsuite->tv[i].key_len; memcpy(key, tsuite->tv[i].key, key_len); memcpy(data, tsuite->tv[i].data, data_len); memcpy(expected_mac, tsuite->tv[i].mac, expected_mac_len); /** create key object **/ rc = create_GenericSecretKey(session, key, key_len, &h_key); if (rc != CKR_OK) { testcase_error("create_GenericSecretKey rc=%s", p11_get_ckr(rc)); goto error; } /** initialize signing **/ rc = funcs->C_SignInit(session, &mech, h_key); if (rc != CKR_OK) { testcase_error("C_SignInit rc=%s", p11_get_ckr(rc)); goto error; } /** do signing **/ rc = funcs->C_Sign(session, data, data_len, actual_mac, &actual_mac_len); if (rc != CKR_OK) { testcase_error("C_Sign rc=%s", p11_get_ckr(rc)); goto error; } /** compare sign results with expected results **/ testcase_new_assertion(); if (actual_mac_len != expected_mac_len) { testcase_fail("hashed data length does not match test " "vector's hashed data length\nexpected " "length=%ld, found length=%ld", expected_mac_len, actual_mac_len); } else if (memcmp(actual_mac, expected_mac, expected_mac_len)) { testcase_fail("hashed data does not match test " "vector's hashed data"); } else { testcase_pass("%s C_Sign with test vector %d passed.", tsuite->name, i); } error: /** clean up **/ rc = funcs->C_DestroyObject(session, h_key); if (rc != CKR_OK) { testcase_error("C_DestroyObject rc=%s.", p11_get_ckr(rc)); goto testcase_cleanup; } } testcase_cleanup: testcase_user_logout(); rc = funcs->C_CloseAllSessions(slot_id); if (rc != CKR_OK) { testcase_error("C_CloseAllSessions rc=%s", p11_get_ckr(rc)); } return rc; } /** Tests signature generation with published test vectors. **/ CK_RV do_Verify_FIPS_HMAC(struct HMAC_TEST_SUITE_INFO * tsuite) { unsigned int i; CK_MECHANISM mech; CK_BYTE key[MAX_KEY_SIZE], data[MAX_DATA_SIZE]; CK_ULONG key_len, data_len, expected_mac_len; CK_BYTE expected_mac[MAX_HASH_SIZE]; CK_SESSION_HANDLE session; CK_SLOT_ID slot_id = SLOT_ID; CK_ULONG flags; CK_RV rc; CK_OBJECT_HANDLE h_key; CK_BYTE user_pin[PKCS11_MAX_PIN_LEN]; CK_ULONG user_pin_len; /** begin testsuite **/ testsuite_begin("%s Verify.", tsuite->name); testcase_rw_session(); testcase_user_login(); rc = CKR_OK; // set rc /** skip test if mech is not supported with this slot **/ if (!mech_supported(SLOT_ID, tsuite->mech.mechanism)) { testsuite_skip(tsuite->tvcount, "mechanism %s is not supported with slot %ld", tsuite->name, slot_id); goto testcase_cleanup; } /** iterate over test vectors **/ for (i = 0; i < tsuite->tvcount; i++) { /** begin test **/ testcase_begin("Verify %s with test vector %d.", tsuite->name, i); /** get mechanism **/ mech = tsuite->mech; /* only run hmac testcases with appropriate mac length */ switch (mech.mechanism) { case CKM_SHA_1_HMAC: if (tsuite->tv[i].mac_len != 20) { testcase_skip("Skip, this testcase is not" " for SHA1 HMAC"); continue; } break; case CKM_SHA224_HMAC: if (tsuite->tv[i].mac_len != 28) { testcase_skip("Skip, this testcase is not" " for SHA224 HMAC"); continue; } break; case CKM_SHA256_HMAC: if (tsuite->tv[i].mac_len != 32) { testcase_skip("Skip, this testcase is not" " for SHA256 HMAC"); continue; } break; case CKM_SHA384_HMAC: if (tsuite->tv[i].mac_len != 48) { testcase_skip("Skip, this testcase is not" " for SHA384 HMAC"); continue; } break; case CKM_SHA512_HMAC: if (tsuite->tv[i].mac_len != 64) { testcase_skip("Skip, this testcase is not" " for SHA512 HMAC"); continue; } break; default: testcase_error("Invalid Mechanism\n"); goto testcase_cleanup; } /** clear buffers **/ memset(key, 0, sizeof(key)); memset(data, 0, sizeof(data)); memset(expected_mac, 0, sizeof(expected_mac)); /** get test vector info **/ data_len = tsuite->tv[i].data_len; expected_mac_len = tsuite->tv[i].mac_len; key_len = tsuite->tv[i].key_len; memcpy(key, tsuite->tv[i].key, key_len); memcpy(data, tsuite->tv[i].data, data_len); memcpy(expected_mac, tsuite->tv[i].mac, expected_mac_len); /** create key object **/ rc = create_GenericSecretKey(session, key, key_len, &h_key); if (rc != CKR_OK) { testcase_error("create_GenericSecretKey rc=%s", p11_get_ckr(rc)); goto error; } /** initilaize verification **/ rc = funcs->C_VerifyInit(session, &mech, h_key); if (rc != CKR_OK) { testcase_error("C_VerifyInit rc=%s", p11_get_ckr(rc)); goto error; } testcase_new_assertion(); /** do verification **/ rc = funcs->C_Verify(session, data, data_len, expected_mac, expected_mac_len); if (rc != CKR_OK) testcase_fail("C_Verify rc=%s", p11_get_ckr(rc)); else testcase_pass("%s C_Verify with test vector %d passed.", tsuite->name, i); error: /** clean up **/ rc = funcs->C_DestroyObject(session, h_key); if (rc != CKR_OK) { testcase_error("C_DestroyObject rc=%s.", p11_get_ckr(rc)); goto testcase_cleanup; } } testcase_cleanup: testcase_user_logout(); rc = funcs->C_CloseAllSessions(slot_id); if (rc != CKR_OK) { testcase_error("C_CloseAllSessions rc=%s", p11_get_ckr(rc)); } return rc; } /** Tests signature generation with published test vectors. **/ CK_RV do_SignUpdate_FIPS_HMAC(struct HMAC_TEST_SUITE_INFO * tsuite) { unsigned int i; CK_MECHANISM mech; CK_BYTE key[MAX_KEY_SIZE], data[MAX_DATA_SIZE]; CK_ULONG key_len, data_len, actual_mac_len, expected_mac_len; CK_BYTE actual_mac[MAX_HASH_SIZE], expected_mac[MAX_HASH_SIZE]; CK_SESSION_HANDLE session; CK_SLOT_ID slot_id = SLOT_ID; CK_ULONG flags; CK_RV rc; CK_OBJECT_HANDLE h_key; CK_BYTE user_pin[PKCS11_MAX_PIN_LEN]; CK_ULONG user_pin_len; /** begin testsuite **/ testsuite_begin("%s SignUpdate.", tsuite->name); testcase_rw_session(); testcase_user_login(); rc = CKR_OK; // set rc /** skip test if mech is not supported with this slot **/ if (!mech_supported(SLOT_ID, tsuite->mech.mechanism)) { testsuite_skip(tsuite->tvcount, "mechanism %s is not supported with slot %ld", tsuite->name, slot_id); goto testcase_cleanup; } /** iterate over test vectors **/ for (i = 0; i < tsuite->tvcount; i++) { /** begin test **/ testcase_begin("Multipart SignUpdate %s with test vector %d.", tsuite->name, i); /** get mechanism and set parameter **/ mech = tsuite->mech; /* only run hmac testcases with appropriate mac length */ switch (mech.mechanism) { case CKM_SHA_1_HMAC: if (tsuite->tv[i].mac_len != 20) { testcase_skip("Skip, testcase not applicable" " to SHA1 HMAC"); continue; } break; case CKM_SHA224_HMAC: if (tsuite->tv[i].mac_len != 28) { testcase_skip("Skip, testcase not applicable" " to SHA224 HMAC"); continue; } break; case CKM_SHA256_HMAC: if (tsuite->tv[i].mac_len != 32) { testcase_skip("Skip, testcase not applicable" " to SHA256 HMAC"); continue; } break; case CKM_SHA384_HMAC: if (tsuite->tv[i].mac_len != 48) { testcase_skip("Skip, testcase not applicable" " to SHA384 HMAC"); continue; } break; case CKM_SHA512_HMAC: if (tsuite->tv[i].mac_len != 64) { testcase_skip("Skip, testcase not applicable" " to SHA512 HMAC"); continue; } break; default: testcase_error("Invalid Mechanism\n"); goto testcase_cleanup; } /** clear buffers **/ memset(key, 0, sizeof(key)); memset(data, 0, sizeof(data)); memset(actual_mac, 0, sizeof(actual_mac)); memset(expected_mac, 0, sizeof(expected_mac)); /** get test vector info **/ data_len = tsuite->tv[i].data_len; actual_mac_len = sizeof(actual_mac); expected_mac_len = tsuite->tv[i].mac_len; key_len = tsuite->tv[i].key_len; memcpy(key, tsuite->tv[i].key, key_len); memcpy(data, tsuite->tv[i].data, data_len); memcpy(expected_mac, tsuite->tv[i].mac, expected_mac_len); /** create key object **/ rc = create_GenericSecretKey(session, key, key_len, &h_key); if (rc != CKR_OK) { testcase_error("create_GenericSecretKey rc=%s", p11_get_ckr(rc)); goto error; } /** initialize signing **/ rc = funcs->C_SignInit(session, &mech, h_key); if (rc != CKR_OK) { testcase_error("C_SignInit rc=%s", p11_get_ckr(rc)); goto error; } /* for chunks, -1 is NULL, and 0 is empty string, * and a value > 0 is amount of data from test vector's * plaintext data. This way we test vary-sized chunks. */ if (tsuite->tv[i].num_chunks) { int j, k = 0; CK_ULONG len; CK_BYTE *data_chunk = NULL; for (j = 0; j < tsuite->tv[i].num_chunks; j++) { if (tsuite->tv[i].chunks[j] == -1) { len = 0; data_chunk = NULL; } else if (tsuite->tv[i].chunks[j] == 0) { len = 0; data_chunk = (CK_BYTE *) ""; } else { len = tsuite->tv[i].chunks[j]; data_chunk = data + k; } rc = funcs->C_SignUpdate(session, data_chunk, len); if (rc != CKR_OK) { testcase_error("C_SignUpdate rc=%s", p11_get_ckr(rc)); goto error; } k += len; } } else { rc = funcs->C_SignUpdate(session, data, data_len); if (rc != CKR_OK) { testcase_error("C_SignUpdate rc=%s", p11_get_ckr(rc)); goto error; } } rc = funcs->C_SignFinal(session, actual_mac, &actual_mac_len); if (rc != CKR_OK) { testcase_error("C_SignFinal rc=%s", p11_get_ckr(rc)); goto error; } /** compare results with expected results **/ testcase_new_assertion(); if (actual_mac_len != expected_mac_len) { testcase_fail("hashed data length does not match test " "vector's hashed data length\nexpected " "length=%ld, found length=%ld", expected_mac_len, actual_mac_len); } else if (memcmp(actual_mac, expected_mac, expected_mac_len)) { testcase_fail("hashed data does not match test " "vector's hashed data"); } else { testcase_pass("%s Sign with test vector %d passed.", tsuite->name, i); } error: /** clean up **/ rc = funcs->C_DestroyObject(session, h_key); if (rc != CKR_OK) { testcase_error("C_DestroyObject rc=%s.", p11_get_ckr(rc)); goto testcase_cleanup; } } testcase_cleanup: testcase_user_logout(); rc = funcs->C_CloseAllSessions(slot_id); if (rc != CKR_OK) testcase_error("C_CloseAllSessions rc=%s", p11_get_ckr(rc)); return rc; } /** Tests signature verification with published test vectors. **/ CK_RV do_VerifyUpdate_FIPS_HMAC(struct HMAC_TEST_SUITE_INFO * tsuite) { unsigned int i; CK_MECHANISM mech; CK_BYTE key[MAX_KEY_SIZE], data[MAX_DATA_SIZE]; CK_ULONG key_len, data_len, expected_mac_len; CK_BYTE expected_mac[MAX_HASH_SIZE]; CK_SESSION_HANDLE session; CK_SLOT_ID slot_id = SLOT_ID; CK_ULONG flags; CK_RV rc; CK_OBJECT_HANDLE h_key; CK_BYTE user_pin[PKCS11_MAX_PIN_LEN]; CK_ULONG user_pin_len; /** begin testsuite **/ testsuite_begin("%s VerifyUpdate.", tsuite->name); testcase_rw_session(); testcase_user_login(); rc = CKR_OK; // set rc /** skip test if mech is not supported with this slot **/ if (!mech_supported(SLOT_ID, tsuite->mech.mechanism)) { testsuite_skip(tsuite->tvcount, "mechanism %s is not supported with slot %ld", tsuite->name, slot_id); goto testcase_cleanup; } /** iterate over test vectors **/ for (i = 0; i < tsuite->tvcount; i++) { /** begin test **/ testcase_begin("Multipart VerifyUpdate %s with test vector %d.", tsuite->name, i); /** get mechanism and set parameter **/ mech = tsuite->mech; /* only run hmac testcases with appropriate mac length */ switch (mech.mechanism) { case CKM_SHA_1_HMAC: if (tsuite->tv[i].mac_len != 20) { testcase_skip("Skip, testcase not applicable" " to SHA1 HMAC"); continue; } break; case CKM_SHA224_HMAC: if (tsuite->tv[i].mac_len != 28) { testcase_skip("Skip, testcase not applicable" " to SHA224 HMAC"); continue; } break; case CKM_SHA256_HMAC: if (tsuite->tv[i].mac_len != 32) { testcase_skip("Skip, testcase not applicable" " to SHA256 HMAC"); continue; } break; case CKM_SHA384_HMAC: if (tsuite->tv[i].mac_len != 48) { testcase_skip("Skip, testcase not applicable" " to SHA384 HMAC"); continue; } break; case CKM_SHA512_HMAC: if (tsuite->tv[i].mac_len != 64) { testcase_skip("Skip, testcase not applicable" " to SHA512 HMAC"); continue; } break; default: testcase_error("Invalid Mechanism\n"); goto testcase_cleanup; } /** clear buffers **/ memset(key, 0, sizeof(key)); memset(data, 0, sizeof(data)); memset(expected_mac, 0, sizeof(expected_mac)); /** get test vector info **/ data_len = tsuite->tv[i].data_len; expected_mac_len = tsuite->tv[i].mac_len; key_len = tsuite->tv[i].key_len; memcpy(key, tsuite->tv[i].key, key_len); memcpy(data, tsuite->tv[i].data, data_len); memcpy(expected_mac, tsuite->tv[i].mac, expected_mac_len); /** create key object **/ rc = create_GenericSecretKey(session, key, key_len, &h_key); if (rc != CKR_OK) { testcase_error("create_GenericSecretKey rc=%s", p11_get_ckr(rc)); goto error; } /** initialize signing **/ rc = funcs->C_VerifyInit(session, &mech, h_key); if (rc != CKR_OK) { testcase_error("C_SignInit rc=%s", p11_get_ckr(rc)); goto error; } /* for chunks, -1 is NULL, and 0 is empty string, * and a value > 0 is amount of data from test vector's * plaintext data. This way we test vary-sized chunks. */ if (tsuite->tv[i].num_chunks) { int j, k = 0; CK_ULONG len; CK_BYTE *data_chunk = NULL; for (j = 0; j < tsuite->tv[i].num_chunks; j++) { if (tsuite->tv[i].chunks[j] == -1) { len = 0; data_chunk = NULL; } else if (tsuite->tv[i].chunks[j] == 0) { len = 0; data_chunk = (CK_BYTE *) ""; } else { len = tsuite->tv[i].chunks[j]; data_chunk = data + k; } rc = funcs->C_VerifyUpdate(session, data_chunk, len); if (rc != CKR_OK) { testcase_error("C_VerifyUpdate rc=%s", p11_get_ckr(rc)); goto error; } k += len; } } else { rc = funcs->C_VerifyUpdate(session, data, data_len); if (rc != CKR_OK) { testcase_error("C_SignUpdate rc=%s", p11_get_ckr(rc)); goto error; } } testcase_new_assertion(); rc = funcs->C_VerifyFinal(session, expected_mac, expected_mac_len); if (rc != CKR_OK) testcase_fail("C_VerifyFinal rc=%s", p11_get_ckr(rc)); else testcase_pass("%s Verfied with test vector %d passed.", tsuite->name, i); error: /** clean up **/ rc = funcs->C_DestroyObject(session, h_key); if (rc != CKR_OK) { testcase_error("C_DestroyObject rc=%s.", p11_get_ckr(rc)); goto testcase_cleanup; } } testcase_cleanup: testcase_user_logout(); rc = funcs->C_CloseAllSessions(slot_id); if (rc != CKR_OK) testcase_error("C_CloseAllSessions rc=%s", p11_get_ckr(rc)); return rc; } /** Tests signature verification with published test vectors. **/ CK_RV do_SignVerify_HMAC(struct HMAC_TEST_SUITE_INFO * tsuite) { unsigned int i; CK_MECHANISM mech; CK_BYTE key[MAX_KEY_SIZE]; CK_ULONG key_len; CK_BYTE data[MAX_DATA_SIZE]; CK_ULONG data_len; CK_BYTE actual[MAX_HASH_SIZE]; CK_ULONG actual_len; CK_BYTE expected[MAX_HASH_SIZE]; CK_ULONG expected_len; CK_SESSION_HANDLE session; CK_SLOT_ID slot_id = SLOT_ID; CK_ULONG flags; CK_RV rc; CK_OBJECT_HANDLE h_key; CK_BYTE user_pin[PKCS11_MAX_PIN_LEN]; CK_ULONG user_pin_len; /** begin testsuite **/ testsuite_begin("%s Sign Verify.", tsuite->name); testcase_rw_session(); testcase_user_login(); rc = CKR_OK; // set rc /** skip test if mech is not supported with this slot **/ if (!mech_supported(SLOT_ID, tsuite->mech.mechanism)) { testsuite_skip(tsuite->tvcount, "mechanism %s is not supported with slot %ld", tsuite->name, slot_id); goto testcase_cleanup; } /** iterate over test vectors **/ for (i = 0; i < tsuite->tvcount; i++) { /** begin test **/ testcase_begin("Sign Verify %s with test vector %d.", tsuite->name, i); /** get mechanism **/ mech = tsuite->mech; /* for ep11, check if key len is supported */ key_len = tsuite->tv[i].key_len; if ((is_ep11_token(SLOT_ID) || is_cca_token(SLOT_ID)) && (!check_supp_keysize(SLOT_ID, mech.mechanism, key_len * 8))) { testcase_skip("keysize %d is not supported in slot %ld", (unsigned int) key_len, slot_id); continue; } /** clear buffers **/ memset(key, 0, sizeof(key)); memset(data, 0, sizeof(data)); memset(actual, 0, sizeof(actual)); memset(expected, 0, sizeof(expected)); /** get test vector info **/ data_len = tsuite->tv[i].data_len; actual_len = sizeof(actual); expected_len = tsuite->tv[i].mac_len; memcpy(key, tsuite->tv[i].key, key_len); memcpy(data, tsuite->tv[i].data, data_len); memcpy(expected, tsuite->tv[i].mac, expected_len); /** create key object **/ rc = create_GenericSecretKey(session, key, key_len, &h_key); if (rc != CKR_OK) { testcase_error("create_GenericSecretKey rc=%s", p11_get_ckr(rc)); goto error; } /** initialize signing **/ rc = funcs->C_SignInit(session, &mech, h_key); if (rc != CKR_OK) { testcase_error("C_SignInit rc=%s", p11_get_ckr(rc)); goto error; } /** do signing **/ rc = funcs->C_Sign(session, data, data_len, actual, &actual_len); if (rc != CKR_OK) { testcase_error("C_Sign rc=%s", p11_get_ckr(rc)); goto error; } /** initilaize verification **/ rc = funcs->C_VerifyInit(session, &mech, h_key); if (rc != CKR_OK) { testcase_error("C_VerifyInit rc=%s", p11_get_ckr(rc)); goto error; } /** do verification **/ rc = funcs->C_Verify(session, data, data_len, actual, actual_len); if (rc != CKR_OK) { testcase_error("C_Verify rc=%s", p11_get_ckr(rc)); goto error; } /** compare sign/verify results with expected results **/ testcase_new_assertion(); if (actual_len != expected_len) { testcase_fail("hashed data length does not match test " "vector's hashed data length\nexpected length=" "%ld, found length=%ld", expected_len, actual_len); } else if (memcmp(actual, expected, expected_len)) { testcase_fail("hashed data does not match test " "vector's hashed data"); } else { testcase_pass("%s Sign Verify with test vector %d " "passed.", tsuite->name, i); } error: /** clean up **/ rc = funcs->C_DestroyObject(session, h_key); if (rc != CKR_OK) { testcase_error("C_DestroyObject rc=%s.", p11_get_ckr(rc)); goto testcase_cleanup; } } testcase_cleanup: testcase_user_logout(); rc = funcs->C_CloseAllSessions(slot_id); if (rc != CKR_OK) { testcase_error("C_CloseAllSessions rc=%s", p11_get_ckr(rc)); } return rc; } /** Tests signature verification with published test vectors. **/ CK_RV do_SignVerify_HMAC_Update(struct HMAC_TEST_SUITE_INFO * tsuite) { int len1 = 0, len2 = 0; unsigned int i; CK_MECHANISM mech; CK_BYTE key[MAX_KEY_SIZE]; CK_ULONG key_len; CK_BYTE data[MAX_DATA_SIZE]; CK_ULONG data_len; CK_BYTE actual[MAX_HASH_SIZE]; CK_ULONG actual_len; CK_BYTE expected[MAX_HASH_SIZE]; CK_ULONG expected_len; CK_SESSION_HANDLE session; CK_SLOT_ID slot_id = SLOT_ID; CK_ULONG flags; CK_RV rc; CK_OBJECT_HANDLE h_key; CK_BYTE user_pin[PKCS11_MAX_PIN_LEN]; CK_ULONG user_pin_len; /** begin testsuite **/ testsuite_begin("%s Sign Verify.", tsuite->name); testcase_rw_session(); testcase_user_login(); rc = CKR_OK; // set rc /** skip test if mech is not supported with this slot **/ if (!mech_supported(SLOT_ID, tsuite->mech.mechanism)) { testsuite_skip(tsuite->tvcount, "mechanism %s is not supported with slot %ld", tsuite->name, slot_id); goto testcase_cleanup; } /** iterate over test vectors **/ for (i = 0; i < tsuite->tvcount; i++) { /** begin test **/ testcase_begin("Multipart Sign Verify %s with test vector %d.", tsuite->name, i); /** get mechanism **/ mech = tsuite->mech; /* for ep11, check if key len is supported */ key_len = tsuite->tv[i].key_len; if ((is_ep11_token(SLOT_ID) || is_cca_token(SLOT_ID)) && (!check_supp_keysize(SLOT_ID, mech.mechanism, key_len * 8))) { testcase_skip("keysize %d is not supported in slot %ld", (unsigned int) key_len, slot_id); continue; } /** clear buffers **/ memset(key, 0, sizeof(key)); memset(data, 0, sizeof(data)); memset(actual, 0, sizeof(actual)); memset(expected, 0, sizeof(expected)); /** get test vector info **/ data_len = tsuite->tv[i].data_len; actual_len = sizeof(actual); expected_len = tsuite->tv[i].mac_len; memcpy(key, tsuite->tv[i].key, key_len); memcpy(data, tsuite->tv[i].data, data_len); memcpy(expected, tsuite->tv[i].mac, expected_len); /** create key object **/ rc = create_GenericSecretKey(session, key, key_len, &h_key); if (rc != CKR_OK) { testcase_error("create_GenericSecretKey rc=%s", p11_get_ckr(rc)); goto error; } /** initialize signing **/ rc = funcs->C_SignInit(session, &mech, h_key); if (rc != CKR_OK) { testcase_error("C_SignInit rc=%s", p11_get_ckr(rc)); goto error; } /** do multipart signing **/ if (data_len > 0) { /* do in 2 parts */ if (data_len < 20) { len1 = data_len; } else { len1 = data_len - 20; len2 = 20; } rc = funcs->C_SignUpdate(session, data, len1); if (rc != CKR_OK) { testcase_error("C_SignUpdate rc=%s", p11_get_ckr(rc)); goto error; } if (len2) { rc = funcs->C_SignUpdate(session, data + len1, len2); if (rc != CKR_OK) { testcase_error("C_SignUpdate rc=%s", p11_get_ckr(rc)); goto error; } } } rc = funcs->C_SignFinal(session, actual, &actual_len); if (rc != CKR_OK) { testcase_error("C_SignFinal rc=%s", p11_get_ckr(rc)); goto error; } /** initilaize verification **/ rc = funcs->C_VerifyInit(session, &mech, h_key); if (rc != CKR_OK) { testcase_error("C_VerifyInit rc=%s", p11_get_ckr(rc)); goto error; } /** do verification **/ if (data_len > 0) { rc = funcs->C_VerifyUpdate(session, data, len1); if (rc != CKR_OK) { testcase_error("C_VerifyUpdate rc=%s", p11_get_ckr(rc)); goto error; } if (len2) { rc = funcs->C_VerifyUpdate(session, data + len1, len2); if (rc != CKR_OK) { testcase_error("C_VerifyUpdate rc=%s", p11_get_ckr(rc)); goto error; } } } rc = funcs->C_VerifyFinal(session, actual, actual_len); if (rc != CKR_OK) { testcase_error("C_VerifyFinal rc=%s", p11_get_ckr(rc)); goto error; } /** compare sign/verify results with expected results **/ testcase_new_assertion(); if (actual_len != expected_len) { testcase_fail("hashed data length does not match test " "vector's hashed data length\nexpected length=" "%ld, found length=%ld", expected_len, actual_len); } else if (memcmp(actual, expected, expected_len)) { testcase_fail("hashed data does not match test " "vector's hashed data"); } else { testcase_pass("%s Sign Verify Multipart with test vector %d " "passed.", tsuite->name, i); } error: /** clean up **/ rc = funcs->C_DestroyObject(session, h_key); if (rc != CKR_OK) { testcase_error("C_DestroyObject rc=%s.", p11_get_ckr(rc)); goto testcase_cleanup; } } testcase_cleanup: testcase_user_logout(); rc = funcs->C_CloseAllSessions(slot_id); if (rc != CKR_OK) { testcase_error("C_CloseAllSessions rc=%s", p11_get_ckr(rc)); } return rc; } /* This function tests generating a generic secret key to be used * with hmac sign and verify. */ CK_RV do_HMAC_SignVerify_WithGenKey(void) { CK_MECHANISM secret_mech = { CKM_GENERIC_SECRET_KEY_GEN, 0, 0 }; CK_MECHANISM hash_mech = { CKM_SHA_1_HMAC, 0, 0 }; CK_ULONG key_len = 20; CK_BYTE data[] = { "Hi There" }; CK_ULONG data_len = 8; CK_BYTE actual[MAX_HASH_SIZE]; CK_ULONG actual_len; CK_SESSION_HANDLE session; CK_SLOT_ID slot_id = SLOT_ID; CK_ULONG flags; CK_RV rc; CK_OBJECT_HANDLE h_key; CK_BYTE user_pin[PKCS11_MAX_PIN_LEN]; CK_ULONG user_pin_len; /** begin test **/ testsuite_begin("do_HMAC_SignVerify_WithGenKey"); testcase_begin("Generate Generic Secret Key And Sign/Verify with it."); testcase_rw_session(); testcase_user_login(); rc = CKR_OK; // set rc /* skip test if mech is not supported with this slot, * checking for generic secret key mechanism * and also sha1-hmac mechanism */ if (!mech_supported(SLOT_ID, secret_mech.mechanism)) { testsuite_skip(1, "mechanism %ld not supported with slot %ld", secret_mech.mechanism, slot_id); goto testcase_cleanup; } if (!mech_supported(SLOT_ID, hash_mech.mechanism)) { testsuite_skip(1, "mechanism %ld not supported with slot %ld", hash_mech.mechanism, slot_id); goto testcase_cleanup; } /** clear buffers **/ memset(actual, 0, sizeof(actual)); /** get test vector info **/ actual_len = sizeof(actual); /** generate key object **/ rc = generate_SecretKey(session, key_len, &secret_mech, &h_key); if (rc != CKR_OK) { testcase_error("generate_SecretKey rc=%s", p11_get_ckr(rc)); goto testcase_cleanup; } /** initialize signing **/ rc = funcs->C_SignInit(session, &hash_mech, h_key); if (rc != CKR_OK) { testcase_error("C_SignInit rc=%s", p11_get_ckr(rc)); goto error; } /** do signing **/ rc = funcs->C_Sign(session, data, data_len, actual, &actual_len); if (rc != CKR_OK) { testcase_error("C_Sign rc=%s", p11_get_ckr(rc)); goto error; } /* Ensure the generated key can verify what it signed */ testcase_new_assertion(); /** initilaize verification **/ rc = funcs->C_VerifyInit(session, &hash_mech, h_key); if (rc != CKR_OK) { testcase_error("C_VerifyInit rc=%s", p11_get_ckr(rc)); goto error; } /** do verification **/ rc = funcs->C_Verify(session, data, data_len, actual, actual_len); if (rc != CKR_OK) testcase_fail("C_Verify rc=%s", p11_get_ckr(rc)); else testcase_pass("Sign Verify with generated generic secret key " "passed."); error: if (funcs->C_DestroyObject(session, h_key) != CKR_OK) testcase_error("C_DestroyObject rc=%s.", p11_get_ckr(rc)); testcase_cleanup: testcase_user_logout(); if (funcs->C_CloseAllSessions(slot_id) != CKR_OK) testcase_error("C_CloseAllSessions rc=%s", p11_get_ckr(rc)); return rc; } CK_RV digest_funcs() { CK_RV rc; unsigned int i; /** Digest tests **/ for (i = 0; i < NUM_DIGEST_TEST_SUITES; i++) { rc = do_Digest(&digest_test_suites[i]); if (rc && !no_stop) { return rc; } } /** Multipart Digest tests **/ for (i = 0; i < NUM_DIGEST_TEST_SUITES; i++) { rc = do_DigestUpdate(&digest_test_suites[i]); if (rc && !no_stop) { return rc; } } /** RFC HMAC tests **/ for (i = 0; i < NUM_OF_HMAC_TEST_SUITES; i++) { rc = do_SignVerify_HMAC(&hmac_test_suites[i]); if (rc && !no_stop) return rc; } /** FIPS HMAC tests **/ for (i = 0; i < NUM_OF_FIPS_HMAC_TEST_SUITES; i++) { rc = do_Sign_FIPS_HMAC(&fips_hmac_test_suites[i]); if (rc && !no_stop) break; rc = do_Verify_FIPS_HMAC(&fips_hmac_test_suites[i]); if (rc && !no_stop) break; rc = do_Sign_FIPS_HMAC_GENERAL(&fips_hmac_general_test_suites[i]); if (rc && !no_stop) break; rc = do_Verify_FIPS_HMAC_GENERAL(&fips_hmac_general_test_suites[i]); if (rc && !no_stop) break; } /** HMAC Multipart tests **/ /* ica and tpm tokens do not yet support multipart hmac right now. */ if (!(is_ica_token(SLOT_ID)) && !(is_tpm_token(SLOT_ID))) { for (i = 0; i < NUM_OF_FIPS_HMAC_TEST_SUITES; i++) { rc = do_SignUpdate_FIPS_HMAC(&fips_hmac_test_suites[i]); if (rc && !no_stop) break; rc = do_VerifyUpdate_FIPS_HMAC(&fips_hmac_test_suites[i]); if (rc && !no_stop) break; } } /* HMAC test with a generated generic secret key */ rc = do_HMAC_SignVerify_WithGenKey(); return rc; } int main(int argc, char **argv) { CK_C_INITIALIZE_ARGS cinit_args; int rc; CK_BBOOL no_init; CK_RV rv; SLOT_ID = 0; no_init = FALSE; rc = do_ParseArgs(argc, argv); if (rc != 1) return rc; printf("Using slot #%lu...\n\n", SLOT_ID); printf("With option: no_init: %d\n", no_init); rc = do_GetFunctionList(); if (!rc) { PRINT_ERR("ERROR do_GetFunctionList() Failed , rc = 0x%0x\n", rc); return rc; } memset(&cinit_args, 0x0, sizeof(cinit_args)); cinit_args.flags = CKF_OS_LOCKING_OK; // SAB Add calls to ALL functions before the C_Initialize gets hit funcs->C_Initialize(&cinit_args); { CK_SESSION_HANDLE hsess = 0; rc = funcs->C_GetFunctionStatus(hsess); if (rc != CKR_FUNCTION_NOT_PARALLEL) return rc; rc = funcs->C_CancelFunction(hsess); if (rc != CKR_FUNCTION_NOT_PARALLEL) return rc; } testcase_setup(0); //TODO rv = digest_funcs(); testcase_print_result(); funcs->C_Finalize(NULL); /* make sure we return non-zero if rv is non-zero */ return ((rv == 0) || (rv % 256) ? (int)rv : -1); }