/* * 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 "pkcs11types.h" #include "regress.h" #include "des3.h" #include "common.c" #include "mech_to_str.h" /** Tests triple DES encryption with published test vectors. **/ CK_RV do_EncryptDES3(struct published_test_suite_info *tsuite) { unsigned int i; // test vector index CK_BYTE expected[BIG_REQUEST]; // encrypted data CK_BYTE actual[BIG_REQUEST]; // encryption buffer CK_ULONG expected_len, actual_len, original_len, k; CK_SLOT_ID slot_id = SLOT_ID; CK_BYTE user_pin[PKCS11_MAX_PIN_LEN]; CK_ULONG user_pin_len; CK_SESSION_HANDLE session; CK_MECHANISM mech; CK_OBJECT_HANDLE h_key; CK_RV rc; CK_FLAGS flags; /** begin testsuite **/ testsuite_begin("%s Encryption.", tsuite->name); testcase_rw_session(); testcase_user_login(); /** skip testsuite if the slot does not support this mechanism **/ if (!mech_supported(slot_id, tsuite->mechanism)) { testsuite_skip(tsuite->tvcount, "Slot %u doesn't support %s (%u)", (unsigned int) slot_id, mech_to_str(tsuite->mechanism), (unsigned int) tsuite->mechanism); goto testcase_cleanup; } /** iterate over test vectors **/ for (i = 0; i < tsuite->tvcount; i++) { testcase_begin("%s Encryption with test vector %d", tsuite->name, i); rc = CKR_OK; // set rc /** clear buffers **/ memset(expected, 0, sizeof(expected)); memset(actual, 0, sizeof(actual)); /** get ciphertext (expected results) **/ memcpy(expected, tsuite->tv[i].ciphertext, tsuite->tv[i].clen); expected_len = tsuite->tv[i].clen; /** get plaintext **/ memcpy(actual, tsuite->tv[i].plaintext, tsuite->tv[i].plen); actual_len = original_len = k = tsuite->tv[i].plen; /** get mech **/ mech.mechanism = tsuite->mechanism; mech.ulParameterLen = tsuite->tv[i].ivlen; mech.pParameter = tsuite->tv[i].iv; /** create key handle. **/ rc = create_DES3Key(session, tsuite->tv[i].key, tsuite->tv[i].klen, &h_key); if (rc != CKR_OK) { testcase_error("C_CreateObject rc=%s", p11_get_ckr(rc)); goto error; } /** initialize single (in-place) encryption **/ rc = funcs->C_EncryptInit(session, &mech, h_key); if (rc != CKR_OK) { testcase_error("C_EncryptInit rc=%s", p11_get_ckr(rc)); goto error; } /** do single (in-place) encryption **/ rc = funcs->C_Encrypt(session, actual, actual_len, actual, &actual_len); if (rc != CKR_OK) { testcase_error("C_Encrypt rc=%s", p11_get_ckr(rc)); goto error; } /** compare encryption results with expected results. **/ rc = 0; testcase_new_assertion(); if (actual_len != expected_len) { testcase_fail("encrypted data length does not match " "test vector's encrypted data length.\n" "expected length=%ld, but found length=" "%ld\n", expected_len, actual_len); } else if (memcmp(actual, expected, expected_len)) { testcase_fail("encrypted data does not match test " "vector's encrypted data.\n"); } else { testcase_pass("%s Encryption with test vector " "%d passed.", tsuite->name, i); } /** 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; } } goto testcase_cleanup; error: rc = funcs->C_DestroyObject(session, h_key); if (rc != CKR_OK) testcase_error("C_DestroyObject rc=%s.", p11_get_ckr(rc)); 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 triple DES multipart encryption with published test vectors. **/ CK_RV do_EncryptUpdateDES3(struct published_test_suite_info * tsuite) { unsigned int i; // test vector index CK_BYTE expected[BIG_REQUEST]; CK_BYTE plaintext[BIG_REQUEST]; CK_BYTE crypt[BIG_REQUEST]; CK_ULONG expected_len, p_len, crypt_len, k; CK_SLOT_ID slot_id = SLOT_ID; CK_BYTE user_pin[PKCS11_MAX_PIN_LEN]; CK_ULONG user_pin_len; CK_SESSION_HANDLE session; CK_MECHANISM mech; CK_OBJECT_HANDLE h_key; CK_RV rc; CK_FLAGS flags; /** begin testsuite **/ testsuite_begin("%s Multipart Encryption.", tsuite->name); testcase_rw_session(); testcase_user_login(); /** skip testuite if the slot does not support this mechanism **/ if (!mech_supported(slot_id, tsuite->mechanism)) { testsuite_skip(tsuite->tvcount, "Slot %u doesn't support %s (%u)", (unsigned int) slot_id, mech_to_str(tsuite->mechanism), (unsigned int) tsuite->mechanism); goto testcase_cleanup; } /** iterate over test vectors **/ for (i = 0; i < tsuite->tvcount; i++) { /** begin testcase **/ testcase_begin("%s Multipart Encryption with test vector %d.", tsuite->name, i); rc = CKR_OK; // set rc /** clear buffers **/ memset(expected, 0, sizeof(expected)); memset(crypt, 0, sizeof(crypt)); memset(plaintext, 0, sizeof(plaintext)); /** get ciphertext (expected results) **/ expected_len = tsuite->tv[i].clen; memcpy(expected, tsuite->tv[i].ciphertext, expected_len); /** get plaintext **/ p_len = k = tsuite->tv[i].plen; memcpy(plaintext, tsuite->tv[i].plaintext, p_len); /** get mech **/ mech.mechanism = tsuite->mechanism; mech.ulParameterLen = tsuite->tv[i].ivlen; mech.pParameter = tsuite->tv[i].iv; /** create key handle. **/ rc = create_DES3Key(session, tsuite->tv[i].key, tsuite->tv[i].klen, &h_key); if (rc != CKR_OK) { testcase_error("C_CreateObject rc=%s", p11_get_ckr(rc)); goto error; } /** initialize multipart (in-place) encryption **/ rc = funcs->C_EncryptInit(session, &mech, h_key); if (rc != CKR_OK) { testcase_error("C_EncryptInit rc=%s", p11_get_ckr(rc)); goto error; } /* do multipart encryption * for chunks, -1 is NULL, and 0 is empty string, * and a value > 0 is amount of data from test vector's * plaintext data. The is way we test input in various sizes. */ if (tsuite->tv[i].num_chunks) { int j; CK_ULONG outlen, len; CK_BYTE *data_chunk = NULL; k = 0; crypt_len = 0; outlen = sizeof(crypt); 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 = plaintext + k; } rc = funcs->C_EncryptUpdate(session, data_chunk, len, &crypt[crypt_len], &outlen); if (rc != CKR_OK) { testcase_error("C_EncryptUpdate rc=%s", p11_get_ckr(rc)); goto error; } k += len; crypt_len += outlen; outlen = sizeof(crypt) - crypt_len; } } else { crypt_len = sizeof(crypt); rc = funcs->C_EncryptUpdate(session, plaintext, p_len, crypt, &crypt_len); if (rc != CKR_OK) { testcase_error("C_EncryptUpdate rc=%s", p11_get_ckr(rc)); goto error; } } k = sizeof(crypt) - crypt_len; rc = funcs->C_EncryptFinal(session, &crypt[crypt_len], &k); if (rc != CKR_OK) { testcase_error("C_EncryptFinal rc=%s", p11_get_ckr(rc)); goto error; } /** compare encryption results with expected results. **/ testcase_new_assertion(); if (crypt_len != expected_len) { testcase_fail("multipart encrypted data length does " "not match test vector's encrypted data length.\n" "expected length=%ld, but found length=%ld\n", expected_len, crypt_len); } else if (memcmp(crypt, expected, expected_len)) { testcase_fail("multipart encrypted data does " "not match test vector's encrypted data.\n"); } else { testcase_pass("%s Multipart Encryption with test vector" " %d passed.", tsuite->name, i); } rc = funcs->C_DestroyObject(session, h_key); if (rc != CKR_OK) { testcase_error("C_DestroyObject rc=%s.", p11_get_ckr(rc)); goto testcase_cleanup; } } goto testcase_cleanup; error: 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 triple DES decryption with published test vectors. **/ CK_RV do_DecryptDES3(struct published_test_suite_info * tsuite) { unsigned int i; // test vector index CK_BYTE expected[BIG_REQUEST]; // decrypted data CK_BYTE actual[BIG_REQUEST]; // decryption buffer CK_ULONG expected_len, actual_len; CK_SLOT_ID slot_id = SLOT_ID; CK_BYTE user_pin[PKCS11_MAX_PIN_LEN]; CK_ULONG user_pin_len; CK_SESSION_HANDLE session; CK_MECHANISM mech; CK_OBJECT_HANDLE h_key; CK_RV rc; CK_FLAGS flags; /** begin testsuite **/ testsuite_begin("%s Decryption.", tsuite->name); testcase_rw_session(); testcase_user_login(); /** skip test if the slot does not support this mechanism **/ if (!mech_supported(slot_id, tsuite->mechanism)) { testsuite_skip(tsuite->tvcount, "Slot %u doesn't support %s (%u)", (unsigned int) slot_id, mech_to_str(tsuite->mechanism), (unsigned int) tsuite->mechanism); goto testcase_cleanup; } /** iterate over test vectors **/ for (i = 0; i < tsuite->tvcount; i++) { /** begin test **/ testcase_begin("%s Decryption with test vector %d.", tsuite->name, i); rc = CKR_OK; // set rc /** clear buffers **/ memset(expected, 0, sizeof(expected)); memset(actual, 0, sizeof(actual)); /** get plaintext (expected result) **/ expected_len = tsuite->tv[i].plen; memcpy(expected, tsuite->tv[i].plaintext, expected_len); /** get ciphertext **/ actual_len = tsuite->tv[i].clen; memcpy(actual, tsuite->tv[i].ciphertext, actual_len); /** get mechanism **/ mech.mechanism = tsuite->mechanism; mech.ulParameterLen = tsuite->tv[i].ivlen; mech.pParameter = tsuite->tv[i].iv; /** create key handle. **/ rc = create_DES3Key(session, tsuite->tv[i].key, tsuite->tv[i].klen, &h_key); if (rc != CKR_OK) { testcase_error("C_CreateObject rc=%s", p11_get_ckr(rc)); goto testcase_cleanup; } /** initialize single (in-place) decryption **/ rc = funcs->C_DecryptInit(session, &mech, h_key); if (rc != CKR_OK) { testcase_error("C_DecryptInit rc=%s", p11_get_ckr(rc)); goto error; } /** do single (in-place) decryption **/ rc = funcs->C_Decrypt(session, actual, actual_len, actual, &actual_len); if (rc != CKR_OK) { testcase_error("C_Decrypt rc=%s", p11_get_ckr(rc)); goto error; } /** compare decryption results with expected results. **/ testcase_new_assertion(); if (actual_len != expected_len) { testcase_fail("decrypted data length does not match test " "vector's decrypted data length.\nexpected length=" "%ld, but found length=%ld\n", expected_len, actual_len); } else if (memcmp(actual, expected, expected_len)) { testcase_fail("decrypted data does not match test " "vector's decrypted data.\n"); } else { testcase_pass("%s Decryption with test vector %d " "passed.", tsuite->name, i); } /** 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; } } goto testcase_cleanup; error: rc = funcs->C_DestroyObject(session, h_key); if (rc != CKR_OK) testcase_error("C_DestroyObject rc=%s", p11_get_ckr(rc)); 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 triple DES multipart decryption with published test vectors **/ CK_RV do_DecryptUpdateDES3(struct published_test_suite_info * tsuite) { unsigned int i; // test vector index CK_BYTE expected[BIG_REQUEST]; CK_BYTE cipher[BIG_REQUEST]; CK_BYTE plaintext[BIG_REQUEST]; CK_ULONG expected_len, p_len, cipher_len, k; CK_SLOT_ID slot_id = SLOT_ID; CK_BYTE user_pin[PKCS11_MAX_PIN_LEN]; CK_ULONG user_pin_len; CK_SESSION_HANDLE session; CK_MECHANISM mech; CK_OBJECT_HANDLE h_key; CK_RV rc; CK_FLAGS flags; /** begin testsuite **/ testsuite_begin("%s Decryption.", tsuite->name); testcase_rw_session(); testcase_user_login(); /** skip test if the slot does not support this mechanism **/ if (!mech_supported(slot_id, tsuite->mechanism)) { testsuite_skip(tsuite->tvcount, "Slot %u doesn't support %s (%u)", (unsigned int) slot_id, mech_to_str(tsuite->mechanism), (unsigned int) tsuite->mechanism); goto testcase_cleanup; } /** iterate over test vectors **/ for (i = 0; i < tsuite->tvcount; i++) { /** begin test **/ testcase_begin("%s Decryption with test vector %d.", tsuite->name, i); rc = CKR_OK; // set rc /** clear buffers **/ memset(expected, 0, sizeof(expected)); memset(cipher, 0, sizeof(cipher)); memset(plaintext, 0, sizeof(plaintext)); p_len = sizeof(plaintext); /** get plaintext (expected results) **/ expected_len = tsuite->tv[i].plen; memcpy(expected, tsuite->tv[i].plaintext, expected_len); /** get ciphertext **/ cipher_len = k = tsuite->tv[i].clen; memcpy(cipher, tsuite->tv[i].ciphertext, cipher_len); /** get mech **/ mech.mechanism = tsuite->mechanism; mech.ulParameterLen = tsuite->tv[i].ivlen; mech.pParameter = tsuite->tv[i].iv; /** create key handle. **/ rc = create_DES3Key(session, tsuite->tv[i].key, tsuite->tv[i].klen, &h_key); if (rc != CKR_OK) { testcase_error("C_CreateObject rc=%s", p11_get_ckr(rc)); goto testcase_cleanup; } /** initialize multipart (in-place) decryption **/ rc = funcs->C_DecryptInit(session, &mech, h_key); if (rc != CKR_OK) { testcase_error("C_DecryptInit rc=%s", p11_get_ckr(rc)); goto error; } /* do multipart encryption * for chunks, -1 is NULL, and 0 is empty string, * and a value > 0 is amount of data from test vector's * plaintext data. The is way we test input in various sizes. */ if (tsuite->tv[i].num_chunks) { int j; CK_ULONG outlen, len; CK_BYTE *data_chunk = NULL; k = 0; p_len = 0; outlen = sizeof(plaintext); 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 = cipher + k; } rc = funcs->C_DecryptUpdate(session, data_chunk, len, &plaintext[p_len], &outlen); if (rc != CKR_OK) { testcase_error("C_DecryptUpdate rc=%s", p11_get_ckr(rc)); goto error; } k += len; p_len += outlen; outlen = sizeof(plaintext) - p_len; } } else { p_len = sizeof(plaintext); rc = funcs->C_DecryptUpdate(session, cipher, cipher_len, plaintext, &p_len); if (rc != CKR_OK) { testcase_error("C_DecryptUpdate rc=%s", p11_get_ckr(rc)); goto error; } } k = sizeof(plaintext) - p_len; rc = funcs->C_DecryptFinal(session, &plaintext[p_len], &k); if (rc != CKR_OK) { testcase_error("C_DecryptFinal rc=%s", p11_get_ckr(rc)); goto error; } /** compare decryption results with expected results. **/ testcase_new_assertion(); if (p_len != expected_len) { testcase_fail("decrypted multipart data length does " "not match test vector's decrypted data " "length.\nexpected length=%ld, but " "found length=%ld\n", expected_len, p_len); } else if (memcmp(plaintext, expected, expected_len)) { testcase_fail("decrypted multipart data does not " "match test vector's decrypted data.\n"); } else { testcase_pass("%s Multipart Decryption with test " "vector %d passed.", tsuite->name, i); } /** 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; } } goto testcase_cleanup; error: rc = funcs->C_DestroyObject(session, h_key); if (rc != CKR_OK) testcase_error("C_DestroyObject rc=%s", p11_get_ckr(rc)); 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 triple DES encryption & decryption using generated keys **/ CK_RV do_EncryptDecryptDES3(struct generated_test_suite_info * tsuite) { unsigned int j; CK_BYTE original[BIG_REQUEST]; CK_BYTE crypt[BIG_REQUEST + DES3_BLOCK_SIZE]; CK_BYTE decrypt[BIG_REQUEST + DES3_BLOCK_SIZE]; CK_ULONG crypt_len, decrypt_len, original_len; CK_SLOT_ID slot_id = SLOT_ID; CK_SESSION_HANDLE session; CK_MECHANISM mech, mechkey; CK_OBJECT_HANDLE h_key; CK_FLAGS flags; CK_BYTE user_pin[PKCS11_MAX_PIN_LEN]; CK_ULONG user_pin_len; CK_RV rc; /** begin test **/ testcase_begin("%s Encryption/Decryption tests with key generation.", tsuite->name); testcase_rw_session(); testcase_user_login(); /** skip test if the slot does not support this mechanism **/ if (!mech_supported(slot_id, tsuite->mech.mechanism)) { testcase_skip("Slot %u doesn't support %s (%u)", (unsigned int) slot_id, mech_to_str(tsuite->mech.mechanism), (unsigned int) tsuite->mech.mechanism); goto testcase_cleanup; } /** clear buffers **/ memset(original, 0, sizeof(original)); memset(crypt, 0, sizeof(crypt)); memset(decrypt, 0, sizeof(decrypt)); /** generate test data **/ original_len = sizeof(original); crypt_len = sizeof(crypt); decrypt_len = sizeof(decrypt); for (j = 0; j < original_len; j++) original[j] = j % 255; /** set mechanism for key gen **/ mechkey = des3_keygen; /** generate key **/ rc = funcs->C_GenerateKey(session, &mechkey, NULL, 0, &h_key); if (rc != CKR_OK) { testcase_error("C_GenerateKey rc=%s", p11_get_ckr(rc)); goto error; } /** set mech for crypto **/ mech = tsuite->mech; /** initialize single encryption **/ rc = funcs->C_EncryptInit(session, &mech, h_key); if (rc != CKR_OK) { testcase_error("C_EncryptInit rc=%s", p11_get_ckr(rc)); goto error; } /** do single encryption **/ rc = funcs->C_Encrypt(session, original, original_len, crypt, &crypt_len); if (rc != CKR_OK) { testcase_error("C_Encrypt rc=%s", p11_get_ckr(rc)); goto error; } /** initialize single decryption **/ rc = funcs->C_DecryptInit(session, &mech, h_key); if (rc != CKR_OK) { testcase_error("C_DecryptInit rc=%s", p11_get_ckr(rc)); goto error; } /** do single decryption **/ rc = funcs->C_Decrypt(session, crypt, crypt_len, decrypt, &decrypt_len); if (rc != CKR_OK) { testcase_error("C_Decrypt rc=%s", p11_get_ckr(rc)); goto error; } /** compare encryption/decryption results with expected results. **/ testcase_new_assertion(); if (decrypt_len != original_len) { testcase_fail("decrypted data length does not match original data " "length.\nexpected length=%ld, but found length=%ld\n", original_len, decrypt_len); } else if (memcmp(decrypt, original, original_len)) { testcase_fail("decrypted data does not match original data"); } else { testcase_pass("%s Encryption/Decryption test passed.", tsuite->name); } /** 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; error: rc = funcs->C_DestroyObject(session, h_key); if (rc != CKR_OK) testcase_error("C_DestroyObject rc=%s.", p11_get_ckr(rc)); 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 triple DES multipart encryption & multipart * decryption using generated keys. */ CK_RV do_EncryptDecryptUpdateDES3(struct generated_test_suite_info * tsuite) { unsigned int i, j, k; CK_BYTE original[BIG_REQUEST]; CK_BYTE crypt[BIG_REQUEST + DES3_BLOCK_SIZE]; CK_BYTE decrypt[BIG_REQUEST + DES3_BLOCK_SIZE]; CK_ULONG crypt_len, decrypt_len, original_len, tmp; CK_SLOT_ID slot_id = SLOT_ID; CK_SESSION_HANDLE session; CK_MECHANISM mech, mechkey; CK_OBJECT_HANDLE h_key; CK_FLAGS flags; CK_BYTE user_pin[PKCS11_MAX_PIN_LEN]; CK_ULONG user_pin_len; CK_RV rc; /** begin test **/ testcase_begin("%s Multipart Encryption/Decryption tests with " "key generation.", tsuite->name); testcase_rw_session(); testcase_user_login(); /** skip test if the slot does not support this mechanism **/ if (!mech_supported(slot_id, tsuite->mech.mechanism)) { testcase_skip("Slot %u doesn't support %s (%u)", (unsigned int) slot_id, mech_to_str(tsuite->mech.mechanism), (unsigned int) tsuite->mech.mechanism); goto testcase_cleanup; } /** clear buffers **/ memset(original, 0, sizeof(original)); memset(crypt, 0, sizeof(crypt)); memset(decrypt, 0, sizeof(decrypt)); /** generate test data **/ original_len = sizeof(original); crypt_len = sizeof(crypt); decrypt_len = sizeof(decrypt); for (j = 0; j < original_len; j++) original[j] = j % 255; /** set mechanism for key gen **/ mechkey = des3_keygen; /** generate key **/ rc = funcs->C_GenerateKey(session, &mechkey, NULL, 0, &h_key); if (rc != CKR_OK) { testcase_error("C_GenerateKey rc=%s", p11_get_ckr(rc)); goto error; } /** set mech for crypto **/ mech = tsuite->mech; /** initialize multipart encryption **/ rc = funcs->C_EncryptInit(session, &mech, h_key); if (rc != CKR_OK) { testcase_error("C_EncryptInit rc=%s", p11_get_ckr(rc)); goto error; } /* do multipart (in-place) encryption for all mechs but CBC_PAD since * it pads and pkcs padding can make it unclear about what is * output at what stage. (See pkcs11v2.20 Section 11.2) */ if (mech.mechanism != CKM_DES3_CBC_PAD) { memcpy(crypt, original, original_len); k = 0; while (k < original_len) { rc = funcs->C_EncryptUpdate(session, &crypt[k], DES3_BLOCK_SIZE, &crypt[k], &crypt_len); if (rc != CKR_OK) { testcase_error("C_EncryptUpdate rc=%s", p11_get_ckr(rc)); goto error; } k += crypt_len; // encrypted amount crypt_len = sizeof(crypt) - k; // space in out buf } } else { i = k = 0; // i indexes source buffer // k indexes destination buffer tmp = 0; while (i < original_len) { tmp = crypt_len - k; // room is left in mpcrypt rc = funcs->C_EncryptUpdate(session, &original[i], DES3_BLOCK_SIZE, &crypt[k], &tmp); if (rc != CKR_OK) { testcase_error("C_EncryptUpdate rc=%s", p11_get_ckr(rc)); goto error; } k += tmp; i += DES3_BLOCK_SIZE; } crypt_len -= k; } rc = funcs->C_EncryptFinal(session, &crypt[k], &crypt_len); if (rc != CKR_OK) { testcase_error("C_EncryptFinal rc=%s", p11_get_ckr(rc)); goto error; } crypt_len += k; /** initialize multipart decryption **/ rc = funcs->C_DecryptInit(session, &mech, h_key); if (rc != CKR_OK) { testcase_error("C_DecryptInit rc=%s", p11_get_ckr(rc)); goto error; } /* do multipart (in-place) encryption for all mechs but CBC_PAD since * it pads and pkcs padding can make it unclear about what is * output at what stage. (See pkcs11v2.20 Section 11.2) */ if (mech.mechanism != CKM_DES3_CBC_PAD) { memcpy(decrypt, crypt, crypt_len); decrypt_len = crypt_len; k = 0; while (k < crypt_len) { rc = funcs->C_DecryptUpdate(session, &decrypt[k], DES3_BLOCK_SIZE, &decrypt[k], &decrypt_len); if (rc != CKR_OK) { testcase_error("C_DecryptUpdate rc=%s", p11_get_ckr(rc)); goto error; } k += decrypt_len; decrypt_len = crypt_len - k; } } else { i = k = 0; while (i < crypt_len) { tmp = decrypt_len - k; // room left in mpdecrypt rc = funcs->C_DecryptUpdate(session, &crypt[i], DES3_BLOCK_SIZE, &decrypt[k], &tmp); if (rc != CKR_OK) { testcase_error("C_DecryptUpdate rc=%s", p11_get_ckr(rc)); goto error; } k += tmp; i += DES3_BLOCK_SIZE; } decrypt_len = sizeof(decrypt) - k; } rc = funcs->C_DecryptFinal(session, &decrypt[k], &decrypt_len); if (rc != CKR_OK) { testcase_error("C_DecryptFinal rc=%s", p11_get_ckr(rc)); goto error; } decrypt_len += k; /* compare multipart encryption/decryption results with expected results */ testcase_new_assertion(); if (decrypt_len != original_len) { testcase_fail("decrypted multipart data length does not match " "original data length.\nexpected length=%ld, but " "found length=%ld\n", original_len, decrypt_len); } else if (memcmp(decrypt, original, original_len)) { testcase_fail("decrypted multipart data does not match " "original data"); } else { testcase_pass("%s Multipart Encryption/Decryption test passed.", tsuite->name); } error: rc = funcs->C_DestroyObject(session, h_key); if (rc != CKR_OK) testcase_error("C_DestroyObject rc=%s.", p11_get_ckr(rc)); 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 triple DES encryption & decryption using * wrapped/unwrapped (generated) keys */ CK_RV do_WrapUnwrapDES3(struct generated_test_suite_info * tsuite) { unsigned int j; CK_BYTE expected[BIG_REQUEST + DES3_BLOCK_SIZE]; CK_BYTE actual[BIG_REQUEST + DES3_BLOCK_SIZE]; CK_ULONG expected_len, actual_len, cipher_len; CK_SLOT_ID slot_id = SLOT_ID; CK_BYTE wrapped_data[BIG_REQUEST + DES3_BLOCK_SIZE]; CK_BYTE user_pin[PKCS11_MAX_PIN_LEN]; CK_SESSION_HANDLE session; CK_MECHANISM mechkey, mech; CK_OBJECT_HANDLE h_key; CK_OBJECT_HANDLE w_key; CK_OBJECT_HANDLE uw_key; CK_ULONG wrapped_data_len; CK_ULONG user_pin_len; CK_ULONG key_size; CK_ULONG tmpl_count = 2; /* Use only the first 2 attrs, except for CCA */ CK_FLAGS flags; CK_RV rc; CK_OBJECT_CLASS key_class = CKO_SECRET_KEY; CK_KEY_TYPE key_type = CKK_DES3; CK_ATTRIBUTE template[] = { {CKA_CLASS, &key_class, sizeof(key_class)}, {CKA_KEY_TYPE, &key_type, sizeof(key_type)}, {CKA_VALUE_LEN, &key_size, sizeof(key_size)} /* For CCA only */ }; CK_ATTRIBUTE key_gen_tmpl[] = { {CKA_VALUE_LEN, &key_size, sizeof(CK_ULONG)} }; /** begin test **/ testcase_begin("%s Wrap/Unwrap key test.", tsuite->name); testcase_rw_session(); testcase_user_login(); /** skip test if the slot does not support this mechanism **/ if (!mech_supported(SLOT_ID, tsuite->mech.mechanism)) { testcase_skip("Slot %u doesn't support %s (%u)", (unsigned int) SLOT_ID, mech_to_str(tsuite->mech.mechanism), (unsigned int) tsuite->mech.mechanism); goto testcase_cleanup; } if (!wrap_supported(SLOT_ID, tsuite->mech)) { testcase_skip("Slot %u doesn't support %s (%u)", (unsigned int) SLOT_ID, mech_to_str(tsuite->mech.mechanism), (unsigned int) tsuite->mech.mechanism); goto testcase_cleanup; } /** clear buffers **/ memset(actual, 0, sizeof(actual)); memset(expected, 0, sizeof(expected)); /** generate data **/ actual_len = expected_len = BIG_REQUEST; cipher_len = BIG_REQUEST + DES3_BLOCK_SIZE; for (j = 0; j < actual_len; j++) { actual[j] = j % 255; expected[j] = j % 255; } /** set crypto mech **/ mech = tsuite->mech; /** set key gen mechanism **/ mechkey = des3_keygen; key_size = 24; /** generate a DES3 Key **/ rc = funcs->C_GenerateKey(session, &mechkey, key_gen_tmpl, 1, &h_key); if (rc != CKR_OK) { testcase_error("C_GenerateKey rc=%s", p11_get_ckr(rc)); goto error; } /** generate wrapping key **/ rc = funcs->C_GenerateKey(session, &mechkey, key_gen_tmpl, 1, &w_key); if (rc != CKR_OK) { testcase_error("C_GenerateKey rc=%s", p11_get_ckr(rc)); goto error; } /** initialize single encryption **/ rc = funcs->C_EncryptInit(session, &mech, h_key); if (rc != CKR_OK) { testcase_error("C_EncryptInit rc=%s", p11_get_ckr(rc)); goto error; } /** do single encryption **/ rc = funcs->C_Encrypt(session, actual, actual_len, actual, &cipher_len); if (rc != CKR_OK) { testcase_error("C_Encrypt rc=%s", p11_get_ckr(rc)); goto error; } /** wrap key **/ wrapped_data_len = 3 * DES3_KEY_SIZE; rc = funcs->C_WrapKey(session, &mech, w_key, h_key, (CK_BYTE *) & wrapped_data, &wrapped_data_len); if (rc != CKR_OK) { testcase_error("C_WrapKey rc=%s", p11_get_ckr(rc)); goto error; } if (is_cca_token(slot_id)) { /* * CCA requires the CKA_VALUE_LEN attribute in the unwrap template, * although the PKCS#11 standard states that it can not be specified * for unwrap. */ tmpl_count = 3; } /** unwrap key **/ rc = funcs->C_UnwrapKey(session, &mech, w_key, wrapped_data, wrapped_data_len, template, tmpl_count, &uw_key); if (rc != CKR_OK) { testcase_error("C_UnwrapKey rc=%s", p11_get_ckr(rc)); goto error; } /** initialize single decryption (with unwrapped key) **/ rc = funcs->C_DecryptInit(session, &mech, uw_key); if (rc != CKR_OK) { testcase_error("C_DecryptInit rc=%s", p11_get_ckr(rc)); goto error; } /** do single decryption (with unwrapped key) **/ rc = funcs->C_Decrypt(session, actual, cipher_len, actual, &actual_len); if (rc != CKR_OK) { testcase_error("C_Decrypt rc=%s", p11_get_ckr(rc)); goto error; } /** compare encrypted/decrypted data with original data **/ testcase_new_assertion(); if (actual_len != expected_len) { testcase_fail("decrypted data length does not match original data " "length.\nexpected length=%ld, but found length=%ld\n", expected_len, actual_len); } else if (memcmp(actual, expected, actual_len)) { testcase_fail("decrypted data does not match original data."); } else { testcase_pass("%s Wrap/UnWrap test passed.", tsuite->name); } goto testcase_cleanup; error: 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; } CK_RV do_SignVerifyMAC(struct published_mac_test_suite_info *tsuite) { unsigned int i; int k; CK_SESSION_HANDLE session; CK_MECHANISM mech; CK_OBJECT_HANDLE h_key; CK_FLAGS flags; CK_RV rc = CKR_OK; CK_SLOT_ID slot_id = SLOT_ID; CK_ULONG user_pin_len; CK_BYTE user_pin[PKCS11_MAX_PIN_LEN]; CK_MAC_GENERAL_PARAMS mac_param; CK_ULONG ofs; CK_BYTE actual[MAX_KEY_SIZE]; CK_ULONG actual_len, mac_len; testsuite_begin("%s Sign/Verify MAC.", tsuite->name); testcase_rw_session(); testcase_user_login(); /** skip tests if the slot doesn't support this mechanism **/ if (!mech_supported(slot_id, tsuite->mech.mechanism)) { testsuite_skip(3, "Slot %u doesn't support %s (%u)", (unsigned int) slot_id, mech_to_str(tsuite->mech.mechanism), (unsigned int) tsuite->mech.mechanism); goto testcase_cleanup; } if (is_ica_token(slot_id) && tsuite->key_type == CKK_DES2) { testsuite_skip(3, "ICA token in slot %u doesn't support DES2 keys when " "compiled in FIPS mode", (unsigned int) slot_id); goto testcase_cleanup; } for (i = 0; i < tsuite->tvcount; i++) { testcase_begin("%s Sign/Verify MAC with published test vector %d.", tsuite->name, i); /** create key handle **/ if (tsuite->key_type == CKK_DES2) rc = create_DES2Key(session, tsuite->tv[i].key, tsuite->tv[i].klen, &h_key); else if (tsuite->key_type == CKK_DES3) rc = create_DES3Key(session, tsuite->tv[i].key, tsuite->tv[i].klen, &h_key); else rc = CKR_KEY_TYPE_INCONSISTENT; if (rc != CKR_OK) { testcase_error("C_CreateObject rc=%s", p11_get_ckr(rc)); goto error; } /** get mech **/ mech = tsuite->mech; switch (mech.mechanism) { case CKM_DES3_CMAC_GENERAL: case CKM_DES3_MAC_GENERAL: mac_param = tsuite->tv[i].tlen; mech.pParameter = &mac_param; mech.ulParameterLen = sizeof(mac_param); mac_len = mac_param; break; case CKM_DES3_CMAC: case CKM_IBM_CMAC: mac_len = DES3_BLOCK_SIZE; break; case CKM_DES3_MAC: mac_len = DES3_BLOCK_SIZE / 2; break; default: testcase_error("Invalid mechanism: %s", p11_get_ckm(mech.mechanism)); 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; } actual_len = sizeof(actual); memset(actual, 0, sizeof(actual)); if (tsuite->tv[i].num_chunks_message > 0) { ofs = 0; for (k = 0; k < tsuite->tv[i].num_chunks_message; k++) { rc = funcs->C_SignUpdate(session, tsuite->tv[i].msg + ofs, tsuite->tv[i].chunks_msg[k]); if (rc != CKR_OK) { testcase_error("C_SignUpdate rc=%s", p11_get_ckr(rc)); goto error; } ofs += tsuite->tv[i].chunks_msg[k]; } rc = funcs->C_SignFinal(session, actual, &actual_len); if (rc != CKR_OK) { testcase_error("C_SignFinal rc=%s", p11_get_ckr(rc)); goto error; } } else { rc = funcs->C_Sign(session, tsuite->tv[i].msg,tsuite->tv[i].mlen, 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 **/ if (tsuite->tv[i].num_chunks_message > 0) { ofs = 0; for (k = 0; k < tsuite->tv[i].num_chunks_message; k++) { rc = funcs->C_VerifyUpdate(session, tsuite->tv[i].msg + ofs, tsuite->tv[i].chunks_msg[k]); if (rc != CKR_OK) { testcase_error("C_VerifyUpdate rc=%s", p11_get_ckr(rc)); goto error; } ofs += tsuite->tv[i].chunks_msg[k]; } rc = funcs->C_VerifyFinal(session, actual, actual_len); if (rc != CKR_OK) { testcase_error("C_VerifyFinal rc=%s", p11_get_ckr(rc)); goto error; } } else { rc = funcs->C_Verify(session, tsuite->tv[i].msg,tsuite->tv[i].mlen, 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 ((mech.mechanism == CKM_DES3_CMAC_GENERAL || mech.mechanism == CKM_DES3_MAC_GENERAL) && actual_len != tsuite->tv[i].tlen) { testcase_fail("signature length does not match test vector's " "signature length\nexpected length=%d, found " "length=%ld", tsuite->tv[i].tlen, actual_len); } else if (mech.mechanism != CKM_DES3_CMAC_GENERAL && mech.mechanism != CKM_DES3_MAC_GENERAL && actual_len != mac_len) { testcase_fail("signature length does not match test vector's " "signature length\nexpected length=%ld, found " "length=%ld", mac_len, actual_len); } else if (memcmp(actual, tsuite->tv[i].mac, tsuite->tv[i].tlen < mac_len ? tsuite->tv[i].tlen : mac_len)) { testcase_fail("signature does not match test vector's signature"); } else { testcase_pass("%s Sign/Verify MAC with test vector %d " "passed.", tsuite->name, i); } rc = funcs->C_DestroyObject(session, h_key); if (rc != CKR_OK) { testcase_error("C_DestroyObject rc=%s", p11_get_ckr(rc)); goto testcase_cleanup; } } goto testcase_cleanup; error: rc = funcs->C_DestroyObject(session, h_key); if (rc != CKR_OK) testcase_error("C_DestroyObject rc=%s", p11_get_ckr(rc)); testcase_cleanup: testcase_close_session(); return rc; } CK_RV des3_funcs() { int i; CK_RV rv; /** published (known answer) tests **/ for (i = 0; i < NUM_OF_PUBLISHED_TESTSUITES; i++) { rv = do_EncryptDES3(&published_test_suites[i]); if (rv != CKR_OK && (!no_stop)) break; rv = do_DecryptDES3(&published_test_suites[i]); if (rv != CKR_OK && (!no_stop)) break; rv = do_EncryptUpdateDES3(&published_test_suites[i]); if (rv != CKR_OK && (!no_stop)) break; rv = do_DecryptUpdateDES3(&published_test_suites[i]); if (rv != CKR_OK && (!no_stop)) break; } /** generated key tests **/ for (i = 0; i < NUM_OF_GENERATED_TESTSUITES; i++) { rv = do_WrapUnwrapDES3(&generated_test_suites[i]); if (rv != CKR_OK && (!no_stop)) break; do_EncryptDecryptDES3(&generated_test_suites[i]); if (rv != CKR_OK && (!no_stop)) break; do_EncryptDecryptUpdateDES3(&generated_test_suites[i]); if (rv != CKR_OK && (!no_stop)) break; } /* MAC test cases */ for (i = 0; i < NUM_OF_PUBLISHED_MAC_TESTSUITES; i++) { rv = do_SignVerifyMAC(&published_mac_test_suites[i]); if (rv != CKR_OK && (!no_stop)) break; } return rv; } int main(int argc, char **argv) { int rc; CK_C_INITIALIZE_ARGS cinit_args; rc = do_ParseArgs(argc, argv); if (rc != 1) { return rc; } printf("Using slot #%lu...\n\n", SLOT_ID); printf("With option: no_stop: %d\n", no_stop); rc = do_GetFunctionList(); if (!rc) { testcase_error("do_GetFunctionList(), rc=%s", p11_get_ckr(rc)); return rc; } memset(&cinit_args, 0x0, sizeof(cinit_args)); cinit_args.flags = CKF_OS_LOCKING_OK; 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 rc = des3_funcs(); testcase_print_result(); funcs->C_Finalize(NULL); return rc; }