diff --git a/host/xtest/pkcs11_1000.c b/host/xtest/pkcs11_1000.c index 0282332af..3bd198b5b 100644 --- a/host/xtest/pkcs11_1000.c +++ b/host/xtest/pkcs11_1000.c @@ -8888,3 +8888,231 @@ static void xtest_pkcs11_test_1028(ADBG_Case_t *c) } ADBG_CASE_DEFINE(pkcs11, 1028, xtest_pkcs11_test_1028, "PKCS11: destroy PKCS#11 objects handled by another session"); + +/* + * This test involves PKCS11_CKA_CHECK_VALUE when enabled, as per the spec, + * the attribute can be either the legitimate value recomputed by the PKCS#11 + * token or a zero-sized value called a no-value for when client does not want + * the attribute to set in an object. This test invokes Cryptoki API functions + * C_GenerateKey(), C_CreateObject(), C_CopyObject(), C_SetAttributeValue(), + * C_UnwrapKey() and C_DeriveKey() to perform check value computation and + * This test query the value using C_GetAttributeValue(). + */ +static void xtest_pkcs11_test_1029(ADBG_Case_t *c) +{ + CK_RV rv = CKR_GENERAL_ERROR; + CK_SLOT_ID slot = 0; + CK_SESSION_HANDLE session = CK_INVALID_HANDLE; + CK_FLAGS session_flags = CKF_SERIAL_SESSION | CKF_RW_SESSION; + CK_OBJECT_HANDLE key_handle = CK_INVALID_HANDLE; + CK_OBJECT_HANDLE key_handle_cp = CK_INVALID_HANDLE; + CK_OBJECT_HANDLE unwrapped_key_handle = CK_INVALID_HANDLE; + CK_OBJECT_HANDLE derived_key_handle = CK_INVALID_HANDLE; + uint8_t ciphertext[16] = { 0 }; + CK_ULONG ciphertext_len = 0; + uint8_t plaintext[16] = { 0 }; + CK_BYTE kcv[3] = { 0 }; + CK_BYTE import_aes128_key[] = { + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x09, 0x0a, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06 + }; + CK_BYTE import_aes128_kcv_valid[] = { 0x08, 0xbd, 0x28 }; + CK_BYTE import_aes128_kcv_invalid[] = { 0xba, 0xaa, 0xad }; + CK_BYTE unwrapped_key_kcv_valid[] = { 0xa2, 0x25, 0x17 }; + CK_ATTRIBUTE import_aes_key_template[] = { + { CKA_TOKEN, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) }, + { CKA_PRIVATE, &(CK_BBOOL){ CK_FALSE }, sizeof(CK_BBOOL) }, + { CKA_SENSITIVE, &(CK_BBOOL){ CK_FALSE }, sizeof(CK_BBOOL) }, + { CKA_EXTRACTABLE, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) }, + { CKA_CLASS, &(CK_OBJECT_CLASS){CKO_SECRET_KEY}, + sizeof(CK_OBJECT_CLASS) }, + { CKA_KEY_TYPE, &(CK_KEY_TYPE){CKK_AES}, sizeof(CK_KEY_TYPE) }, + { CKA_ENCRYPT, &(CK_BBOOL){CK_FALSE}, sizeof(CK_BBOOL) }, + { CKA_DECRYPT, &(CK_BBOOL){CK_FALSE}, sizeof(CK_BBOOL) }, + { CKA_DERIVE, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) }, + { CKA_WRAP, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) }, + { CKA_UNWRAP, &(CK_BBOOL){CK_TRUE}, sizeof(CK_BBOOL) }, + { CKA_VALUE, &import_aes128_key, sizeof(import_aes128_key) }, + { CKA_CHECK_VALUE, &import_aes128_kcv_valid, + sizeof(import_aes128_kcv_valid) }, + }; + CK_ATTRIBUTE kcv_attr_template[] = { + { CKA_CHECK_VALUE, &kcv, sizeof(kcv) }, + }; + CK_ATTRIBUTE cp_attr_template_cka[] = { + { CKA_CHECK_VALUE, &import_aes128_kcv_invalid, + sizeof(import_aes128_kcv_invalid) }, + }; + CK_KEY_DERIVATION_STRING_DATA key_derv_param = { 0 }; + uint8_t derive_buf[16] = { 0 }; + size_t derive_buf_size = sizeof(derive_buf); + CK_MECHANISM mech_derive = { 0 }; + CK_ATTRIBUTE derived_key_template[] = { + { CKA_CLASS, &(CK_OBJECT_CLASS){ CKO_SECRET_KEY }, + sizeof(CK_OBJECT_CLASS) }, + { CKA_KEY_TYPE, &(CK_KEY_TYPE){ CKK_GENERIC_SECRET }, + sizeof(CK_KEY_TYPE) }, + { CKA_PRIVATE, &(CK_BBOOL){ CK_FALSE }, sizeof(CK_BBOOL) }, + { CKA_SENSITIVE, &(CK_BBOOL){ CK_FALSE }, sizeof(CK_BBOOL) }, + { CKA_EXTRACTABLE, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) }, + { CKA_VALUE_LEN, &(CK_ULONG){16}, sizeof(CK_ULONG) }, + { CKA_CHECK_VALUE, NULL, 0 }, + }; + CK_ATTRIBUTE unwrap_template[] = { + { CKA_CLASS, &(CK_OBJECT_CLASS){ CKO_SECRET_KEY }, + sizeof(CK_OBJECT_CLASS) }, + { CKA_KEY_TYPE, &(CK_KEY_TYPE){ CKK_GENERIC_SECRET }, + sizeof(CK_KEY_TYPE) }, + { CKA_EXTRACTABLE, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) }, + { CKA_SENSITIVE, &(CK_BBOOL){ CK_FALSE}, sizeof(CK_BBOOL) }, + { CKA_CHECK_VALUE, &unwrapped_key_kcv_valid, + sizeof(unwrapped_key_kcv_valid)}, + }; + uint8_t buf[WRAPPED_TEST_KEY_SIZE] = { 0 }; + CK_ULONG size = 0; + + rv = init_lib_and_find_token_slot(&slot, PIN_AUTH); + if (!ADBG_EXPECT_CK_OK(c, rv)) + return; + + rv = C_OpenSession(slot, session_flags, NULL, 0, &session); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto close_lib; + + Do_ADBG_BeginSubCase(c, "Compute KCV on C_GenerateKey()"); + + rv = C_GenerateKey(session, &cktest_aes_keygen_mechanism, + cktest_generate_aes_object, + ARRAY_SIZE(cktest_generate_aes_object), + &key_handle); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err; + + rv = C_GetAttributeValue(session, key_handle, kcv_attr_template, + ARRAY_SIZE(kcv_attr_template)); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + rv = C_EncryptInit(session, &cktest_aes_ecb_mechanism, key_handle); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err_destr_obj; + + memset(ciphertext, 0, sizeof(ciphertext)); + memset(plaintext, 0, sizeof(plaintext)); + + ciphertext_len = sizeof(ciphertext); + + rv = C_Encrypt(session, plaintext, sizeof(plaintext), ciphertext, + &ciphertext_len); + + if (!ADBG_EXPECT_CK_OK(c, rv) || + !ADBG_EXPECT_BUFFER(c, ciphertext, sizeof(kcv), + kcv, sizeof(kcv))) + goto err_destr_obj; + + rv = C_DestroyObject(session, key_handle); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err; + + Do_ADBG_EndSubCase(c, NULL); + + Do_ADBG_BeginSubCase(c, "Set KCV on C_CreateObject()"); + + rv = C_CreateObject(session, import_aes_key_template, + ARRAY_SIZE(import_aes_key_template), &key_handle); + + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err_destr_obj; + + Do_ADBG_EndSubCase(c, NULL); + + Do_ADBG_BeginSubCase(c, "Compute KCV on C_CopyObject()"); + + rv = C_CopyObject(session, key_handle, cp_attr_template_cka, + ARRAY_SIZE(cp_attr_template_cka), &key_handle_cp); + + if (!ADBG_EXPECT_CK_RESULT(c, CKR_ATTRIBUTE_VALUE_INVALID, rv)) + goto err_destr_obj; + + Do_ADBG_EndSubCase(c, NULL); + + Do_ADBG_BeginSubCase(c, "Compute KCV on C_DeriveKey()"); + + key_derv_param.pData = derive_buf; + key_derv_param.ulLen = derive_buf_size; + mech_derive.mechanism = CKM_AES_ECB_ENCRYPT_DATA; + mech_derive.pParameter = &key_derv_param; + mech_derive.ulParameterLen = sizeof(key_derv_param); + + rv = C_DeriveKey(session, &mech_derive, key_handle, + derived_key_template, + ARRAY_SIZE(derived_key_template), + &derived_key_handle); + + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err_destr_obj; + + memset(&kcv, 0, sizeof(kcv)); + rv = C_GetAttributeValue(session, derived_key_handle, kcv_attr_template, + ARRAY_SIZE(kcv_attr_template)); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err_destr_obj; + + if (!ADBG_EXPECT_COMPARE_UNSIGNED(c, + kcv_attr_template[0].ulValueLen, ==, 0)) + goto err_destr_obj; + + Do_ADBG_EndSubCase(c, NULL); + + Do_ADBG_BeginSubCase(c, "Compute KCV on C_UnwrapKey()"); + + size = sizeof(buf); + + rv = C_WrapKey(session, &cktest_aes_ecb_mechanism, key_handle, + derived_key_handle, buf, &size); + if (!ADBG_EXPECT_CK_OK(c, rv) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, size, <=, sizeof(buf))) + goto err_destr_obj; + + rv = C_UnwrapKey(session, &cktest_aes_ecb_mechanism, key_handle, buf, + size, unwrap_template, ARRAY_SIZE(unwrap_template), + &unwrapped_key_handle); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err_destr_obj; + + Do_ADBG_EndSubCase(c, NULL); + + Do_ADBG_BeginSubCase(c, "Destroy KCV using C_SetAttributeValue()"); + + kcv_attr_template[0].pValue = NULL; + kcv_attr_template[0].ulValueLen = 0; + + rv = C_SetAttributeValue(session, unwrapped_key_handle, + kcv_attr_template, + ARRAY_SIZE(kcv_attr_template)); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err_destr_obj; + + kcv_attr_template[0].pValue = &kcv; + kcv_attr_template[0].ulValueLen = sizeof(kcv); + + rv = C_GetAttributeValue(session, unwrapped_key_handle, kcv_attr_template, + ARRAY_SIZE(kcv_attr_template)); + + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err_destr_obj; + ADBG_EXPECT_COMPARE_UNSIGNED(c, kcv_attr_template[0].ulValueLen, ==, 0); + +err_destr_obj: + ADBG_EXPECT_CK_OK(c, C_DestroyObject(session, unwrapped_key_handle)); + ADBG_EXPECT_CK_OK(c, C_DestroyObject(session, derived_key_handle)); + ADBG_EXPECT_CK_OK(c, C_DestroyObject(session, key_handle)); +err: + Do_ADBG_EndSubCase(c, NULL); +out: + ADBG_EXPECT_CK_OK(c, C_CloseSession(session)); +close_lib: + ADBG_EXPECT_CK_OK(c, close_lib()); +} +ADBG_CASE_DEFINE(pkcs11, 1029, xtest_pkcs11_test_1029, + "PKCS11: Test support for object checksum value computation");