From 39b32a266744b77ace3ca5cdd455f14c272acc39 Mon Sep 17 00:00:00 2001 From: Etienne Carriere Date: Tue, 27 Aug 2024 19:06:58 +0200 Subject: [PATCH 1/9] xtest: add pkcs11_1031 for CKM_RSA_X_509 sign/verify Basic test on signing/verifying with raw RSA mechanism CKM_RSA_X_509. Signed-off-by: Etienne Carriere --- host/xtest/pkcs11_1000.c | 387 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 387 insertions(+) diff --git a/host/xtest/pkcs11_1000.c b/host/xtest/pkcs11_1000.c index baa092cee..67e88714b 100644 --- a/host/xtest/pkcs11_1000.c +++ b/host/xtest/pkcs11_1000.c @@ -10021,3 +10021,390 @@ static void xtest_pkcs11_test_1030(ADBG_Case_t *c) } ADBG_CASE_DEFINE(pkcs11, 1030, xtest_pkcs11_test_1030, "PKCS11: Test AES-GCM Encryption/Decryption"); + +static int test_rsa_raw_operations(ADBG_Case_t *c, + CK_SESSION_HANDLE session, + uint32_t rsa_bits) +{ + CK_RV rv = CKR_GENERAL_ERROR; + CK_OBJECT_HANDLE public_key = CK_INVALID_HANDLE; + CK_OBJECT_HANDLE private_key = CK_INVALID_HANDLE; + CK_MECHANISM mechanism = { + CKM_RSA_PKCS_KEY_PAIR_GEN, NULL, 0 + }; + CK_MECHANISM sign_mechanism = { + CKM_RSA_X_509, NULL, 0 + }; + CK_ULONG modulus_bits = 0; + CK_BYTE id[] = { 123 }; + + CK_ATTRIBUTE public_key_template[] = { + { CKA_ENCRYPT, &(CK_BBOOL){ CK_FALSE }, sizeof(CK_BBOOL) }, + { CKA_VERIFY, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) }, + { CKA_WRAP, &(CK_BBOOL){ CK_FALSE }, sizeof(CK_BBOOL) }, + { CKA_MODULUS_BITS, &modulus_bits, sizeof(CK_ULONG) }, + }; + + CK_ATTRIBUTE private_key_template[] = { + { CKA_TOKEN, &(CK_BBOOL){ CK_FALSE }, sizeof(CK_BBOOL) }, + { CKA_PRIVATE, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) }, + { CKA_SUBJECT, subject_common_name, + sizeof(subject_common_name) }, + { CKA_ID, id, sizeof(id) }, + { CKA_SENSITIVE, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) }, + { CKA_DECRYPT, &(CK_BBOOL){ CK_FALSE }, sizeof(CK_BBOOL) }, + { CKA_SIGN, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) }, + { CKA_UNWRAP, &(CK_BBOOL){ CK_FALSE }, sizeof(CK_BBOOL) } + }; + + CK_OBJECT_CLASS g_class = 0; + CK_KEY_TYPE g_key_type = 0; + CK_BYTE g_id[32] = { 0 }; + CK_BBOOL g_derive = CK_FALSE; + CK_BBOOL g_local = CK_FALSE; + CK_MECHANISM_TYPE g_keygen_mecha = 0; + CK_BYTE g_subject[64] = { 0 }; + CK_BBOOL g_encrypt = CK_FALSE; + CK_BBOOL g_verify = CK_FALSE; + CK_BBOOL g_verify_recover = CK_FALSE; + CK_BBOOL g_wrap = CK_FALSE; + CK_BBOOL g_trusted = CK_FALSE; + CK_BYTE g_public_key_info[1024] = { 0 }; + CK_BBOOL g_sensitive = CK_FALSE; + CK_BBOOL g_decrypt = CK_FALSE; + CK_BBOOL g_sign = CK_FALSE; + CK_BBOOL g_sign_recover = CK_FALSE; + CK_BBOOL g_unwrap = CK_FALSE; + CK_BBOOL g_extract = CK_FALSE; + CK_BBOOL g_asensitive = CK_FALSE; + CK_BBOOL g_nextract = CK_FALSE; + CK_BBOOL g_wrap_with_trusted = CK_FALSE; + CK_BBOOL g_always_authenticate = CK_FALSE; + + /* Note: Tests below expects specific order of elements */ + CK_ATTRIBUTE get_public_template[] = { + { CKA_CLASS, &g_class, sizeof(g_class) }, + { CKA_KEY_TYPE, &g_key_type, sizeof(g_key_type) }, + { CKA_ID, g_id, sizeof(g_id) }, + { CKA_DERIVE, &g_derive, sizeof(g_derive) }, + { CKA_LOCAL, &g_local, sizeof(g_local) }, + { CKA_KEY_GEN_MECHANISM, &g_keygen_mecha, sizeof(g_keygen_mecha) }, + { CKA_SUBJECT, g_subject, sizeof(g_subject) }, + { CKA_ENCRYPT, &g_encrypt, sizeof(g_encrypt) }, + { CKA_VERIFY, &g_verify, sizeof(g_verify) }, + { CKA_VERIFY_RECOVER, &g_verify_recover, sizeof(g_verify_recover) }, + { CKA_WRAP, &g_wrap, sizeof(g_wrap) }, + { CKA_TRUSTED, &g_trusted, sizeof(g_trusted) }, + { CKA_PUBLIC_KEY_INFO, g_public_key_info, sizeof(g_public_key_info) }, + }; + + /* Note: Tests below expects specific order of elements */ + CK_ATTRIBUTE get_private_template[] = { + { CKA_CLASS, &g_class, sizeof(g_class) }, + { CKA_KEY_TYPE, &g_key_type, sizeof(g_key_type) }, + { CKA_ID, g_id, sizeof(g_id) }, + { CKA_DERIVE, &g_derive, sizeof(g_derive) }, + { CKA_LOCAL, &g_local, sizeof(g_local) }, + { CKA_KEY_GEN_MECHANISM, &g_keygen_mecha, sizeof(g_keygen_mecha) }, + { CKA_SUBJECT, g_subject, sizeof(g_subject) }, + { CKA_SENSITIVE, &g_sensitive, sizeof(g_sensitive) }, + { CKA_DECRYPT, &g_decrypt, sizeof(g_decrypt) }, + { CKA_SIGN, &g_sign, sizeof(g_sign) }, + { CKA_SIGN_RECOVER, &g_sign_recover, sizeof(g_sign_recover) }, + { CKA_UNWRAP, &g_unwrap, sizeof(g_unwrap) }, + { CKA_EXTRACTABLE, &g_extract, sizeof(g_extract) }, + { CKA_ALWAYS_SENSITIVE, &g_asensitive, sizeof(g_asensitive) }, + { CKA_NEVER_EXTRACTABLE, &g_nextract, sizeof(g_nextract) }, + { CKA_WRAP_WITH_TRUSTED, &g_wrap_with_trusted, sizeof(g_wrap_with_trusted) }, + { CKA_ALWAYS_AUTHENTICATE, &g_always_authenticate, sizeof(g_always_authenticate) }, + { CKA_PUBLIC_KEY_INFO, g_public_key_info, sizeof(g_public_key_info) }, + }; + + CK_BYTE in_data[1024] = { 0 }; + CK_ULONG in_data_size = 0; + CK_BYTE signature[1024] = { 0 }; + CK_ULONG signature_len = 0; + + Do_ADBG_BeginSubCase(c, "Test CKM_RSA_X_509 %u - Sign/Verify", rsa_bits); + + Do_ADBG_BeginSubCase(c, "Generate key pair and data"); + + modulus_bits = rsa_bits; + rv = C_GenerateKeyPair(session, &mechanism, public_key_template, + ARRAY_SIZE(public_key_template), + private_key_template, + ARRAY_SIZE(private_key_template), + &public_key, &private_key); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err; + + in_data_size = rsa_bits / 8; + + rv = C_GenerateRandom(session, in_data, in_data_size); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err_destr_obj; + + /* + * Ensure input data to be sign look like a not to bad padded message. + * Not be too strict to better reflect the padding that are sometimes + * used in the field. + * + * Reset first bit to 0 to ensure the message is not bigger than the + * key modulus. + * + * If first byte is zero and 2nd byte is low, ensure the 2 next byte + * are big (0xff). This will ensure the generated signature has the + * same size as the key modulus. + */ + in_data[0] &= 0x7f; + if (!in_data[0] & !(in_data[1] & 0xf0)) { + in_data[2] = 0xff; + in_data[3] = 0xff; + } + + rv = C_GetAttributeValue(session, public_key, get_public_template, + ARRAY_SIZE(get_public_template)); + if (!ADBG_EXPECT_CK_OK(c, rv) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_class, ==, CKO_PUBLIC_KEY) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_key_type, ==, CKK_RSA) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_derive, ==, CK_FALSE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_local, ==, CK_TRUE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_keygen_mecha, ==, + CKM_RSA_PKCS_KEY_PAIR_GEN) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_encrypt, ==, CK_FALSE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_verify, ==, CK_TRUE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_verify_recover, ==, CK_FALSE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_wrap, ==, CK_FALSE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_trusted, ==, CK_FALSE)) + goto err_destr_obj; + + rv = C_GetAttributeValue(session, private_key, get_private_template, + ARRAY_SIZE(get_private_template)); + if (!ADBG_EXPECT_CK_OK(c, rv) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_class, ==, CKO_PRIVATE_KEY) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_key_type, ==, CKK_RSA) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_derive, ==, CK_FALSE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_local, ==, CK_TRUE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_keygen_mecha, ==, + CKM_RSA_PKCS_KEY_PAIR_GEN) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_sensitive, ==, CK_TRUE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_decrypt, ==, CK_FALSE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_sign, ==, CK_TRUE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_sign_recover, ==, CK_FALSE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_unwrap, ==, CK_FALSE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_extract, ==, CK_FALSE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_asensitive, ==, CK_TRUE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_nextract, ==, CK_TRUE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_wrap_with_trusted, ==, CK_FALSE) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_always_authenticate, ==, CK_FALSE)) + goto err_destr_obj; + + Do_ADBG_EndSubCase(c, "Generate key pair and data"); + + Do_ADBG_BeginSubCase(c, "Sign with invalid data"); + + /* Test with data wider than expected */ + rv = C_SignInit(session, &sign_mechanism, private_key); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err_destr_obj; + + signature_len = sizeof(signature); + rv = C_Sign(session, in_data, in_data_size + 32, signature, &signature_len); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_DATA_LEN_RANGE, rv)) + goto err_destr_obj; + + /* Test with data shorter than expected */ + rv = C_SignInit(session, &sign_mechanism, private_key); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err_destr_obj; + + signature_len = sizeof(signature); + rv = C_Sign(session, in_data, in_data_size - 32, signature, &signature_len); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_DATA_LEN_RANGE, rv)) + goto err_destr_obj; + + /* Test unintialized C_Sign() operation */ + signature_len = sizeof(signature); + rv = C_Sign(session, in_data, in_data_size, signature, &signature_len); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_OPERATION_NOT_INITIALIZED, rv)) + goto err_destr_obj; + + Do_ADBG_EndSubCase(c, "Sign with invalid data"); + + Do_ADBG_BeginSubCase(c, "Sign/Verify with valid data/signature"); + + /* + * Test C_Sign() with buffer too short, the C_Sign() operaiton should remain + * initialized and final C_Sign() call is expected to succeed. + */ + rv = C_SignInit(session, &sign_mechanism, private_key); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err_destr_obj; + + signature_len = 0; + rv = C_Sign(session, in_data, in_data_size, NULL, &signature_len); + if (!ADBG_EXPECT_CK_OK(c, rv) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, signature_len, ==, in_data_size)) + goto err_destr_obj; + + signature_len = sizeof(signature); + rv = C_Sign(session, in_data, in_data_size, NULL, &signature_len); + if (!ADBG_EXPECT_CK_OK(c, rv) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, signature_len, ==, in_data_size)) + goto err_destr_obj; + + signature_len = 0; + rv = C_Sign(session, in_data, in_data_size, signature, &signature_len); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_BUFFER_TOO_SMALL, rv) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, signature_len, ==, in_data_size)) + goto err_destr_obj; + + signature_len = 32; + rv = C_Sign(session, in_data, in_data_size, signature, &signature_len); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_BUFFER_TOO_SMALL, rv) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, signature_len, ==, in_data_size)) + goto err_destr_obj; + + /* Test effective C_Sign() and C_Verify() operations */ + signature_len = sizeof(signature); + rv = C_Sign(session, in_data, in_data_size, signature, &signature_len); + if (!ADBG_EXPECT_CK_OK(c, rv) || + !ADBG_EXPECT_COMPARE_UNSIGNED(c, signature_len, ==, in_data_size)) + goto err_destr_obj; + + rv = C_VerifyInit(session, &sign_mechanism, public_key); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err_destr_obj; + + rv = C_Verify(session, in_data, in_data_size, signature, signature_len); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err_destr_obj; + + Do_ADBG_EndSubCase(c, "Sign/Verify with valid data/signature"); + + Do_ADBG_BeginSubCase(c, "Verify with altered signature/message"); + + /* Test signature wider than expect */ + rv = C_VerifyInit(session, &sign_mechanism, public_key); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err_destr_obj; + + rv = C_Verify(session, in_data, in_data_size, signature, signature_len + 4); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_SIGNATURE_LEN_RANGE, rv)) + goto err_destr_obj; + + /* Test signature shorter than expect */ + rv = C_VerifyInit(session, &sign_mechanism, public_key); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err_destr_obj; + + rv = C_Verify(session, in_data, in_data_size, signature, signature_len - 4); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_SIGNATURE_LEN_RANGE, rv)) + goto err_destr_obj; + + /* Test altered signature */ + rv = C_VerifyInit(session, &sign_mechanism, public_key); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err_destr_obj; + + signature[32] ^= 1; + rv = C_Verify(session, in_data, in_data_size, signature, signature_len); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_SIGNATURE_INVALID, rv)) + goto err_destr_obj; + signature[32] ^= 1; + + /* Test altered message */ + rv = C_VerifyInit(session, &sign_mechanism, public_key); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err_destr_obj; + + in_data[32] ^= 1; + rv = C_Verify(session, in_data, in_data_size, signature, signature_len); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_SIGNATURE_INVALID, rv)) + goto err_destr_obj; + in_data[32] ^= 1; + + /* Test unintialized C_Verify() operation */ + rv = C_Verify(session, in_data, in_data_size, signature, signature_len); + if (!ADBG_EXPECT_CK_RESULT(c, CKR_OPERATION_NOT_INITIALIZED, rv)) + goto err_destr_obj; + + Do_ADBG_EndSubCase(c, "Verify with altered signature/message"); + + Do_ADBG_BeginSubCase(c, "Destroy key pair"); + + rv = C_DestroyObject(session, private_key); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err_destr_pub_obj; + + rv = C_DestroyObject(session, public_key); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto err; + + Do_ADBG_EndSubCase(c, "Destroy key pair"); + + return 1; + +err_destr_obj: + ADBG_EXPECT_CK_OK(c, C_DestroyObject(session, private_key)); +err_destr_pub_obj: + ADBG_EXPECT_CK_OK(c, C_DestroyObject(session, public_key)); +err: + Do_ADBG_EndSubCase(c, NULL); + + return 0; +} + +static void xtest_pkcs11_test_1031(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; + int ret = 0; + + rv = init_lib_and_find_token_slot(&slot, PIN_AUTH); + if (!ADBG_EXPECT_CK_OK(c, rv)) + return; + + rv = init_test_token_pin_auth(slot); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto close_lib; + + rv = init_user_test_token_pin_auth(slot); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto close_lib; + + rv = C_OpenSession(slot, session_flags, NULL, 0, &session); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto close_lib; + + /* Login to Test Token */ + rv = C_Login(session, CKU_USER, test_token_user_pin, + sizeof(test_token_user_pin)); + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto out; + + ret = test_rsa_raw_operations(c, session, 1024); + if (!ret) + goto out; + + ret = test_rsa_raw_operations(c, session, 2048); + if (!ret) + goto out; + + if (level > 0) { + ret = test_rsa_raw_operations(c, session, 3072); + if (!ret) + goto out; + ret = test_rsa_raw_operations(c, session, 4096); + if (!ret) + goto out; + } +out: + ADBG_EXPECT_CK_OK(c, C_CloseSession(session)); +close_lib: + ADBG_EXPECT_CK_OK(c, close_lib()); +} +ADBG_CASE_DEFINE(pkcs11, 1031, xtest_pkcs11_test_1031, + "PKCS11: raw RSA signing"); From 2e64e7839916862acada03a56537f9ec527ce729 Mon Sep 17 00:00:00 2001 From: Etienne Carriere Date: Fri, 22 Nov 2024 14:48:21 +0100 Subject: [PATCH 2/9] [review] xtest: add pkcs11_1031 for CKM_RSA_X_509 sign/verify Skip the test if CFG_PKCS11_TA_RSA_X_509 is disabled. Signed-off-by: Etienne Carriere --- host/xtest/pkcs11_1000.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/host/xtest/pkcs11_1000.c b/host/xtest/pkcs11_1000.c index 67e88714b..255b7a478 100644 --- a/host/xtest/pkcs11_1000.c +++ b/host/xtest/pkcs11_1000.c @@ -10363,6 +10363,11 @@ static void xtest_pkcs11_test_1031(ADBG_Case_t *c) CK_FLAGS session_flags = CKF_SERIAL_SESSION | CKF_RW_SESSION; int ret = 0; +#ifndef CFG_PKCS11_TA_RSA_X_509 + Do_ADBG_Log("CFG_PKCS11_TA_RSA_X_509 is not enabled, skipping raw RSA tests"); + return; +#endif + rv = init_lib_and_find_token_slot(&slot, PIN_AUTH); if (!ADBG_EXPECT_CK_OK(c, rv)) return; From 3c0d561cf09b28bbe513dcd03b9f736da5b982ba Mon Sep 17 00:00:00 2001 From: Etienne Carriere Date: Fri, 22 Nov 2024 15:45:33 +0100 Subject: [PATCH 3/9] [review] xtest: add pkcs11_1031 for CKM_RSA_X_509 sign/verify Fix missing sub-case end call in test_rsa_raw_operations(). Signed-off-by: Etienne Carriere --- host/xtest/pkcs11_1000.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/host/xtest/pkcs11_1000.c b/host/xtest/pkcs11_1000.c index 255b7a478..233840e7e 100644 --- a/host/xtest/pkcs11_1000.c +++ b/host/xtest/pkcs11_1000.c @@ -10343,6 +10343,8 @@ static int test_rsa_raw_operations(ADBG_Case_t *c, Do_ADBG_EndSubCase(c, "Destroy key pair"); + Do_ADBG_EndSubCase(c, "Test CKM_RSA_X_509 %u - Sign/Verify", rsa_bits); + return 1; err_destr_obj: @@ -10351,6 +10353,7 @@ static int test_rsa_raw_operations(ADBG_Case_t *c, ADBG_EXPECT_CK_OK(c, C_DestroyObject(session, public_key)); err: Do_ADBG_EndSubCase(c, NULL); + Do_ADBG_EndSubCase(c, "Test CKM_RSA_X_509 %u - Sign/Verify", rsa_bits); return 0; } From bc2a22c7cb28eec7050ef80cd13623ae36f560b3 Mon Sep 17 00:00:00 2001 From: Etienne Carriere Date: Wed, 11 Dec 2024 14:31:36 +0100 Subject: [PATCH 4/9] [review] xtest: add pkcs11_1031 for CKM_RSA_X_509 sign/verify Use a well known padding scheme (PKCS#1 v1.5) to ensure the generated signature has to expected size. With the previously implemented padding scheme I found seldom occurrences where the generated signature was 1 byte too short. Signed-off-by: Etienne Carriere --- host/xtest/pkcs11_1000.c | 32 +++++++++++++++----------------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/host/xtest/pkcs11_1000.c b/host/xtest/pkcs11_1000.c index 233840e7e..13c849b14 100644 --- a/host/xtest/pkcs11_1000.c +++ b/host/xtest/pkcs11_1000.c @@ -10124,6 +10124,7 @@ static int test_rsa_raw_operations(ADBG_Case_t *c, CK_ULONG in_data_size = 0; CK_BYTE signature[1024] = { 0 }; CK_ULONG signature_len = 0; + unsigned int n = 0; Do_ADBG_BeginSubCase(c, "Test CKM_RSA_X_509 %u - Sign/Verify", rsa_bits); @@ -10138,29 +10139,26 @@ static int test_rsa_raw_operations(ADBG_Case_t *c, if (!ADBG_EXPECT_CK_OK(c, rv)) goto err; + /* + * Size of the message to sign must be at most the size of the private + * key. If smaller, it is strongly recommended to inserrt padding + * bytes to reach to key size. Lets's use random data and use PKCS v1.5 + * padding scheme to ensure input data to be signed will generate well + * szied signature. + * + * in_data = { 0x00, 0x02, non-zero bytes, 0x00, message } + */ in_data_size = rsa_bits / 8; rv = C_GenerateRandom(session, in_data, in_data_size); if (!ADBG_EXPECT_CK_OK(c, rv)) goto err_destr_obj; - /* - * Ensure input data to be sign look like a not to bad padded message. - * Not be too strict to better reflect the padding that are sometimes - * used in the field. - * - * Reset first bit to 0 to ensure the message is not bigger than the - * key modulus. - * - * If first byte is zero and 2nd byte is low, ensure the 2 next byte - * are big (0xff). This will ensure the generated signature has the - * same size as the key modulus. - */ - in_data[0] &= 0x7f; - if (!in_data[0] & !(in_data[1] & 0xf0)) { - in_data[2] = 0xff; - in_data[3] = 0xff; - } + in_data[0] = 0; + in_data[1] = 2; + for (n = 2; n < 16; n++) + in_data[n] |= 0x80; + in_data[n] = 0; rv = C_GetAttributeValue(session, public_key, get_public_template, ARRAY_SIZE(get_public_template)); From 52066c7f1dee7ec612fd04dbc64ad7251d13bacc Mon Sep 17 00:00:00 2001 From: Etienne Carriere Date: Wed, 11 Dec 2024 15:40:56 +0100 Subject: [PATCH 5/9] [review] xtest: add pkcs11_1031 for CKM_RSA_X_509 sign/verify Fix inline comment typos. Signed-off-by: Etienne Carriere --- host/xtest/pkcs11_1000.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/host/xtest/pkcs11_1000.c b/host/xtest/pkcs11_1000.c index 13c849b14..6b662eaed 100644 --- a/host/xtest/pkcs11_1000.c +++ b/host/xtest/pkcs11_1000.c @@ -10141,10 +10141,10 @@ static int test_rsa_raw_operations(ADBG_Case_t *c, /* * Size of the message to sign must be at most the size of the private - * key. If smaller, it is strongly recommended to inserrt padding - * bytes to reach to key size. Lets's use random data and use PKCS v1.5 + * key. If smaller, it is strongly recommended to insert padding bytes + * to reach the key size. Lets's use random data and use PKCS v1.5 * padding scheme to ensure input data to be signed will generate well - * szied signature. + * sized signature. * * in_data = { 0x00, 0x02, non-zero bytes, 0x00, message } */ From 40b6ff9dcc714aafe3160bb9828c8c79c67a885b Mon Sep 17 00:00:00 2001 From: Etienne Carriere Date: Wed, 11 Dec 2024 16:15:40 +0100 Subject: [PATCH 6/9] [review] xtest: add pkcs11_1031 for CKM_RSA_X_509 sign/verify Discard the padding used here. Whatever the message data, as long as the message has the size of the private key, the PKCS#11 should be able to generate a signature. Signed-off-by: Etienne Carriere --- host/xtest/pkcs11_1000.c | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/host/xtest/pkcs11_1000.c b/host/xtest/pkcs11_1000.c index 6b662eaed..59dbc62c8 100644 --- a/host/xtest/pkcs11_1000.c +++ b/host/xtest/pkcs11_1000.c @@ -10140,13 +10140,10 @@ static int test_rsa_raw_operations(ADBG_Case_t *c, goto err; /* - * Size of the message to sign must be at most the size of the private - * key. If smaller, it is strongly recommended to insert padding bytes - * to reach the key size. Lets's use random data and use PKCS v1.5 - * padding scheme to ensure input data to be signed will generate well - * sized signature. - * - * in_data = { 0x00, 0x02, non-zero bytes, 0x00, message } + * Current implementation of the PKCS#11 TA requires that the + * message to sign has to size of the private key. There is + * no constraint regarding the padding scheme. Lets's use a + * well sized buffer of random data. */ in_data_size = rsa_bits / 8; @@ -10154,12 +10151,6 @@ static int test_rsa_raw_operations(ADBG_Case_t *c, if (!ADBG_EXPECT_CK_OK(c, rv)) goto err_destr_obj; - in_data[0] = 0; - in_data[1] = 2; - for (n = 2; n < 16; n++) - in_data[n] |= 0x80; - in_data[n] = 0; - rv = C_GetAttributeValue(session, public_key, get_public_template, ARRAY_SIZE(get_public_template)); if (!ADBG_EXPECT_CK_OK(c, rv) || From 61400775c8161f9930cf58db466969ef577dc385 Mon Sep 17 00:00:00 2001 From: Etienne Carriere Date: Fri, 13 Dec 2024 14:59:20 +0100 Subject: [PATCH 7/9] [review] xtest: add pkcs11_1031 for CKM_RSA_X_509 sign/verify Remove unused local variable. Signed-off-by: Etienne Carriere --- host/xtest/pkcs11_1000.c | 1 - 1 file changed, 1 deletion(-) diff --git a/host/xtest/pkcs11_1000.c b/host/xtest/pkcs11_1000.c index 59dbc62c8..e534ef47b 100644 --- a/host/xtest/pkcs11_1000.c +++ b/host/xtest/pkcs11_1000.c @@ -10124,7 +10124,6 @@ static int test_rsa_raw_operations(ADBG_Case_t *c, CK_ULONG in_data_size = 0; CK_BYTE signature[1024] = { 0 }; CK_ULONG signature_len = 0; - unsigned int n = 0; Do_ADBG_BeginSubCase(c, "Test CKM_RSA_X_509 %u - Sign/Verify", rsa_bits); From 19d47b25ccc215de8c7fd5dbd0ec2932eba29872 Mon Sep 17 00:00:00 2001 From: Etienne Carriere Date: Fri, 13 Dec 2024 16:08:12 +0100 Subject: [PATCH 8/9] [review] xtest: add pkcs11_1031 for CKM_RSA_X_509 sign/verify I missed a constraint on the input message: it must represent a value smaller than the private key modulus. Clear the message leading bit! Fix inline comment. Remove the part testing the key attribute. RSA keys generation in the PKCS#11 TA is already tested by pkcs11_1021, pkcs1022 and pkcs11_1023. No need to test again RSA keys attributes. Wrap line wider than 80char for consistency of this source file. Signed-off-by: Etienne Carriere --- host/xtest/pkcs11_1000.c | 127 ++++++--------------------------------- 1 file changed, 18 insertions(+), 109 deletions(-) diff --git a/host/xtest/pkcs11_1000.c b/host/xtest/pkcs11_1000.c index e534ef47b..b93735a5c 100644 --- a/host/xtest/pkcs11_1000.c +++ b/host/xtest/pkcs11_1000.c @@ -10057,75 +10057,13 @@ static int test_rsa_raw_operations(ADBG_Case_t *c, { CKA_UNWRAP, &(CK_BBOOL){ CK_FALSE }, sizeof(CK_BBOOL) } }; - CK_OBJECT_CLASS g_class = 0; - CK_KEY_TYPE g_key_type = 0; - CK_BYTE g_id[32] = { 0 }; - CK_BBOOL g_derive = CK_FALSE; - CK_BBOOL g_local = CK_FALSE; - CK_MECHANISM_TYPE g_keygen_mecha = 0; - CK_BYTE g_subject[64] = { 0 }; - CK_BBOOL g_encrypt = CK_FALSE; - CK_BBOOL g_verify = CK_FALSE; - CK_BBOOL g_verify_recover = CK_FALSE; - CK_BBOOL g_wrap = CK_FALSE; - CK_BBOOL g_trusted = CK_FALSE; - CK_BYTE g_public_key_info[1024] = { 0 }; - CK_BBOOL g_sensitive = CK_FALSE; - CK_BBOOL g_decrypt = CK_FALSE; - CK_BBOOL g_sign = CK_FALSE; - CK_BBOOL g_sign_recover = CK_FALSE; - CK_BBOOL g_unwrap = CK_FALSE; - CK_BBOOL g_extract = CK_FALSE; - CK_BBOOL g_asensitive = CK_FALSE; - CK_BBOOL g_nextract = CK_FALSE; - CK_BBOOL g_wrap_with_trusted = CK_FALSE; - CK_BBOOL g_always_authenticate = CK_FALSE; - - /* Note: Tests below expects specific order of elements */ - CK_ATTRIBUTE get_public_template[] = { - { CKA_CLASS, &g_class, sizeof(g_class) }, - { CKA_KEY_TYPE, &g_key_type, sizeof(g_key_type) }, - { CKA_ID, g_id, sizeof(g_id) }, - { CKA_DERIVE, &g_derive, sizeof(g_derive) }, - { CKA_LOCAL, &g_local, sizeof(g_local) }, - { CKA_KEY_GEN_MECHANISM, &g_keygen_mecha, sizeof(g_keygen_mecha) }, - { CKA_SUBJECT, g_subject, sizeof(g_subject) }, - { CKA_ENCRYPT, &g_encrypt, sizeof(g_encrypt) }, - { CKA_VERIFY, &g_verify, sizeof(g_verify) }, - { CKA_VERIFY_RECOVER, &g_verify_recover, sizeof(g_verify_recover) }, - { CKA_WRAP, &g_wrap, sizeof(g_wrap) }, - { CKA_TRUSTED, &g_trusted, sizeof(g_trusted) }, - { CKA_PUBLIC_KEY_INFO, g_public_key_info, sizeof(g_public_key_info) }, - }; - - /* Note: Tests below expects specific order of elements */ - CK_ATTRIBUTE get_private_template[] = { - { CKA_CLASS, &g_class, sizeof(g_class) }, - { CKA_KEY_TYPE, &g_key_type, sizeof(g_key_type) }, - { CKA_ID, g_id, sizeof(g_id) }, - { CKA_DERIVE, &g_derive, sizeof(g_derive) }, - { CKA_LOCAL, &g_local, sizeof(g_local) }, - { CKA_KEY_GEN_MECHANISM, &g_keygen_mecha, sizeof(g_keygen_mecha) }, - { CKA_SUBJECT, g_subject, sizeof(g_subject) }, - { CKA_SENSITIVE, &g_sensitive, sizeof(g_sensitive) }, - { CKA_DECRYPT, &g_decrypt, sizeof(g_decrypt) }, - { CKA_SIGN, &g_sign, sizeof(g_sign) }, - { CKA_SIGN_RECOVER, &g_sign_recover, sizeof(g_sign_recover) }, - { CKA_UNWRAP, &g_unwrap, sizeof(g_unwrap) }, - { CKA_EXTRACTABLE, &g_extract, sizeof(g_extract) }, - { CKA_ALWAYS_SENSITIVE, &g_asensitive, sizeof(g_asensitive) }, - { CKA_NEVER_EXTRACTABLE, &g_nextract, sizeof(g_nextract) }, - { CKA_WRAP_WITH_TRUSTED, &g_wrap_with_trusted, sizeof(g_wrap_with_trusted) }, - { CKA_ALWAYS_AUTHENTICATE, &g_always_authenticate, sizeof(g_always_authenticate) }, - { CKA_PUBLIC_KEY_INFO, g_public_key_info, sizeof(g_public_key_info) }, - }; - CK_BYTE in_data[1024] = { 0 }; CK_ULONG in_data_size = 0; CK_BYTE signature[1024] = { 0 }; CK_ULONG signature_len = 0; - Do_ADBG_BeginSubCase(c, "Test CKM_RSA_X_509 %u - Sign/Verify", rsa_bits); + Do_ADBG_BeginSubCase(c, "Test CKM_RSA_X_509 %u - Sign/Verify", + rsa_bits); Do_ADBG_BeginSubCase(c, "Generate key pair and data"); @@ -10139,10 +10077,12 @@ static int test_rsa_raw_operations(ADBG_Case_t *c, goto err; /* - * Current implementation of the PKCS#11 TA requires that the - * message to sign has to size of the private key. There is - * no constraint regarding the padding scheme. Lets's use a - * well sized buffer of random data. + * Implementation of the PKCS#11 TA requires that messages + * signed with raw RSA (CKM_RSA_X_509) have the size of the + * private key. There is no constraint regarding the padding + * scheme. Lets's use a well sized buffer of random data, + * but clear the leading bit to ensure the message value + * is not bigger than the key modulus. */ in_data_size = rsa_bits / 8; @@ -10150,42 +10090,7 @@ static int test_rsa_raw_operations(ADBG_Case_t *c, if (!ADBG_EXPECT_CK_OK(c, rv)) goto err_destr_obj; - rv = C_GetAttributeValue(session, public_key, get_public_template, - ARRAY_SIZE(get_public_template)); - if (!ADBG_EXPECT_CK_OK(c, rv) || - !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_class, ==, CKO_PUBLIC_KEY) || - !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_key_type, ==, CKK_RSA) || - !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_derive, ==, CK_FALSE) || - !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_local, ==, CK_TRUE) || - !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_keygen_mecha, ==, - CKM_RSA_PKCS_KEY_PAIR_GEN) || - !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_encrypt, ==, CK_FALSE) || - !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_verify, ==, CK_TRUE) || - !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_verify_recover, ==, CK_FALSE) || - !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_wrap, ==, CK_FALSE) || - !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_trusted, ==, CK_FALSE)) - goto err_destr_obj; - - rv = C_GetAttributeValue(session, private_key, get_private_template, - ARRAY_SIZE(get_private_template)); - if (!ADBG_EXPECT_CK_OK(c, rv) || - !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_class, ==, CKO_PRIVATE_KEY) || - !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_key_type, ==, CKK_RSA) || - !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_derive, ==, CK_FALSE) || - !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_local, ==, CK_TRUE) || - !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_keygen_mecha, ==, - CKM_RSA_PKCS_KEY_PAIR_GEN) || - !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_sensitive, ==, CK_TRUE) || - !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_decrypt, ==, CK_FALSE) || - !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_sign, ==, CK_TRUE) || - !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_sign_recover, ==, CK_FALSE) || - !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_unwrap, ==, CK_FALSE) || - !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_extract, ==, CK_FALSE) || - !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_asensitive, ==, CK_TRUE) || - !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_nextract, ==, CK_TRUE) || - !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_wrap_with_trusted, ==, CK_FALSE) || - !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_always_authenticate, ==, CK_FALSE)) - goto err_destr_obj; + in_data[0] &= 0x7f; Do_ADBG_EndSubCase(c, "Generate key pair and data"); @@ -10197,7 +10102,8 @@ static int test_rsa_raw_operations(ADBG_Case_t *c, goto err_destr_obj; signature_len = sizeof(signature); - rv = C_Sign(session, in_data, in_data_size + 32, signature, &signature_len); + rv = C_Sign(session, in_data, in_data_size + 32, signature, + &signature_len); if (!ADBG_EXPECT_CK_RESULT(c, CKR_DATA_LEN_RANGE, rv)) goto err_destr_obj; @@ -10207,7 +10113,8 @@ static int test_rsa_raw_operations(ADBG_Case_t *c, goto err_destr_obj; signature_len = sizeof(signature); - rv = C_Sign(session, in_data, in_data_size - 32, signature, &signature_len); + rv = C_Sign(session, in_data, in_data_size - 32, signature, + &signature_len); if (!ADBG_EXPECT_CK_RESULT(c, CKR_DATA_LEN_RANGE, rv)) goto err_destr_obj; @@ -10277,7 +10184,8 @@ static int test_rsa_raw_operations(ADBG_Case_t *c, if (!ADBG_EXPECT_CK_OK(c, rv)) goto err_destr_obj; - rv = C_Verify(session, in_data, in_data_size, signature, signature_len + 4); + rv = C_Verify(session, in_data, in_data_size, signature, + signature_len + 4); if (!ADBG_EXPECT_CK_RESULT(c, CKR_SIGNATURE_LEN_RANGE, rv)) goto err_destr_obj; @@ -10286,7 +10194,8 @@ static int test_rsa_raw_operations(ADBG_Case_t *c, if (!ADBG_EXPECT_CK_OK(c, rv)) goto err_destr_obj; - rv = C_Verify(session, in_data, in_data_size, signature, signature_len - 4); + rv = C_Verify(session, in_data, in_data_size, signature, + signature_len - 4); if (!ADBG_EXPECT_CK_RESULT(c, CKR_SIGNATURE_LEN_RANGE, rv)) goto err_destr_obj; @@ -10355,7 +10264,7 @@ static void xtest_pkcs11_test_1031(ADBG_Case_t *c) int ret = 0; #ifndef CFG_PKCS11_TA_RSA_X_509 - Do_ADBG_Log("CFG_PKCS11_TA_RSA_X_509 is not enabled, skipping raw RSA tests"); + Do_ADBG_Log("CFG_PKCS11_TA_RSA_X_509 is disabled, skip raw RSA tests"); return; #endif From 32babc6a2fbe1563a4cf4160911c98300b449f87 Mon Sep 17 00:00:00 2001 From: Etienne Carriere Date: Sat, 14 Dec 2024 11:49:13 +0100 Subject: [PATCH 9/9] [review] xtest: add pkcs11_1031 for CKM_RSA_X_509 sign/verify Replace static test on CFG_PKCS11_TA_RSA_X_509 with a runtime test on whether or not the PKCS#11 TA supports CKM_RSA_X_509 for signature computation and verification. This change makes xtest more flexible regarding the tested embedded TA instead of requiring a specific xtest build for a given PKCS#11 TA configuration. Signed-off-by: Etienne Carriere --- host/xtest/pkcs11_1000.c | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/host/xtest/pkcs11_1000.c b/host/xtest/pkcs11_1000.c index b93735a5c..a06587099 100644 --- a/host/xtest/pkcs11_1000.c +++ b/host/xtest/pkcs11_1000.c @@ -10261,13 +10261,9 @@ static void xtest_pkcs11_test_1031(ADBG_Case_t *c) CK_SLOT_ID slot = 0; CK_SESSION_HANDLE session = CK_INVALID_HANDLE; CK_FLAGS session_flags = CKF_SERIAL_SESSION | CKF_RW_SESSION; + CK_MECHANISM_INFO mechanism_info = { }; int ret = 0; -#ifndef CFG_PKCS11_TA_RSA_X_509 - Do_ADBG_Log("CFG_PKCS11_TA_RSA_X_509 is disabled, skip raw RSA tests"); - return; -#endif - rv = init_lib_and_find_token_slot(&slot, PIN_AUTH); if (!ADBG_EXPECT_CK_OK(c, rv)) return; @@ -10280,6 +10276,22 @@ static void xtest_pkcs11_test_1031(ADBG_Case_t *c) if (!ADBG_EXPECT_CK_OK(c, rv)) goto close_lib; + rv = C_GetMechanismInfo(slot, CKM_RSA_X_509, &mechanism_info); + + if (rv == CKR_MECHANISM_INVALID) { + Do_ADBG_Log("CKM_RSA_X_509 not supported, skip raw RSA tests"); + goto close_lib; + } + + if (!ADBG_EXPECT_CK_OK(c, rv)) + goto close_lib; + + if ((mechanism_info.flags & (CKF_SIGN | CKF_VERIFY)) != + (CKF_SIGN | CKF_VERIFY)) { + Do_ADBG_Log("CKM_RSA_X_509 sign/verify not supported, skip raw RSA tests"); + goto close_lib; + } + rv = C_OpenSession(slot, session_flags, NULL, 0, &session); if (!ADBG_EXPECT_CK_OK(c, rv)) goto close_lib;