diff --git a/tests/include/test/psa_exercise_key.h b/tests/include/test/psa_exercise_key.h index 44f5c08aa9a9..f6be3073ac13 100644 --- a/tests/include/test/psa_exercise_key.h +++ b/tests/include/test/psa_exercise_key.h @@ -123,6 +123,9 @@ * \param input2 The first input to pass. * \param input2_length The length of \p input2 in bytes. * \param capacity The capacity to set. + * \param key_destroyable If set to 1, a failure due to the key not existing + * or the key being destroyed mid-operation will only + * be reported if the error code is unexpected. * * \return \c 1 on success, \c 0 on failure. */ @@ -132,7 +135,7 @@ int mbedtls_test_psa_setup_key_derivation_wrap( psa_algorithm_t alg, const unsigned char *input1, size_t input1_length, const unsigned char *input2, size_t input2_length, - size_t capacity); + size_t capacity, int key_destroyable); /** Perform a key agreement using the given key pair against its public key * using psa_raw_key_agreement(). @@ -143,12 +146,15 @@ int mbedtls_test_psa_setup_key_derivation_wrap( * * \param alg A key agreement algorithm compatible with \p key. * \param key A key that allows key agreement with \p alg. + * \param key_destroyable If set to 1, a failure due to the key not existing + * or the key being destroyed mid-operation will only + * be reported if the error code is unexpected. * * \return \c 1 on success, \c 0 on failure. */ psa_status_t mbedtls_test_psa_raw_key_agreement_with_self( psa_algorithm_t alg, - mbedtls_svc_key_id_t key); + mbedtls_svc_key_id_t key, int key_destroyable); /** Perform a key agreement using the given key pair against its public key * using psa_key_derivation_raw_key(). @@ -162,12 +168,15 @@ psa_status_t mbedtls_test_psa_raw_key_agreement_with_self( * \p key. * \param key A key pair object that is suitable for a key * agreement with \p operation. + * \param key_destroyable If set to 1, a failure due to the key not existing + * or the key being destroyed mid-operation will only + * be reported if the error code is unexpected. * * \return \c 1 on success, \c 0 on failure. */ psa_status_t mbedtls_test_psa_key_agreement_with_self( psa_key_derivation_operation_t *operation, - mbedtls_svc_key_id_t key); + mbedtls_svc_key_id_t key, int key_destroyable); /** Perform sanity checks on the given key representation. * @@ -209,18 +218,34 @@ int mbedtls_test_psa_exported_key_sanity_check( * ``` * if( ! exercise_key( ... ) ) goto exit; * ``` - * - * \param key The key to exercise. It should be capable of performing - * \p alg. - * \param usage The usage flags to assume. - * \param alg The algorithm to exercise. + * To use this function for multi-threaded tests where the key + * may be destroyed at any point: call this function with key_destroyable set + * to 1, while another thread calls psa_destroy_key on the same key; + * this will test whether destroying the key in use leads to any corruption. + * + * There cannot be a set of concurrent calls: + * `mbedtls_test_psa_exercise_key(ki,...)` such that each ki is a unique + * persistent key not loaded into any key slot, and i is greater than the + * number of free key slots. + * This is because such scenarios can lead to unsupported + * `PSA_ERROR_INSUFFICIENT_MEMORY` return codes. + * + * + * \param key The key to exercise. It should be capable of performing + * \p alg. + * \param usage The usage flags to assume. + * \param alg The algorithm to exercise. + * \param key_destroyable If set to 1, a failure due to the key not existing + * or the key being destroyed mid-operation will only + * be reported if the error code is unexpected. * * \retval 0 The key failed the smoke tests. * \retval 1 The key passed the smoke tests. */ int mbedtls_test_psa_exercise_key(mbedtls_svc_key_id_t key, psa_key_usage_t usage, - psa_algorithm_t alg); + psa_algorithm_t alg, + int key_destroyable); psa_key_usage_t mbedtls_test_psa_usage_to_exercise(psa_key_type_t type, psa_algorithm_t alg); diff --git a/tests/src/psa_exercise_key.c b/tests/src/psa_exercise_key.c index 7b81052c8c7b..937bd45d22f3 100644 --- a/tests/src/psa_exercise_key.c +++ b/tests/src/psa_exercise_key.c @@ -38,7 +38,8 @@ static int lifetime_is_dynamic_secure_element(psa_key_lifetime_t lifetime) } #endif -static int check_key_attributes_sanity(mbedtls_svc_key_id_t key) +static int check_key_attributes_sanity(mbedtls_svc_key_id_t key, + int key_destroyable) { int ok = 0; psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; @@ -46,8 +47,13 @@ static int check_key_attributes_sanity(mbedtls_svc_key_id_t key) mbedtls_svc_key_id_t id; psa_key_type_t type; size_t bits; - - PSA_ASSERT(psa_get_key_attributes(key, &attributes)); + psa_status_t status = psa_get_key_attributes(key, &attributes); + if (key_destroyable && status == PSA_ERROR_INVALID_HANDLE) { + /* The key has been destroyed. */ + psa_reset_key_attributes(&attributes); + return 1; + } + PSA_ASSERT(status); lifetime = psa_get_key_lifetime(&attributes); id = psa_get_key_id(&attributes); type = psa_get_key_type(&attributes); @@ -66,17 +72,20 @@ static int check_key_attributes_sanity(mbedtls_svc_key_id_t key) (MBEDTLS_SVC_KEY_ID_GET_KEY_ID(id) <= PSA_KEY_ID_USER_MAX)); } #if defined(MBEDTLS_PSA_CRYPTO_SE_C) - /* randomly-generated 64-bit constant, should never appear in test data */ - psa_key_slot_number_t slot_number = 0xec94d4a5058a1a21; - psa_status_t status = psa_get_key_slot_number(&attributes, &slot_number); - if (lifetime_is_dynamic_secure_element(lifetime)) { - /* Mbed TLS currently always exposes the slot number to - * applications. This is not mandated by the PSA specification - * and may change in future versions. */ - TEST_EQUAL(status, 0); - TEST_ASSERT(slot_number != 0xec94d4a5058a1a21); - } else { - TEST_EQUAL(status, PSA_ERROR_INVALID_ARGUMENT); + /* MBEDTLS_PSA_CRYPTO_SE_C does not support thread safety. */ + if (key_destroyable == 0) { + /* randomly-generated 64-bit constant, should never appear in test data */ + psa_key_slot_number_t slot_number = 0xec94d4a5058a1a21; + status = psa_get_key_slot_number(&attributes, &slot_number); + if (lifetime_is_dynamic_secure_element(lifetime)) { + /* Mbed TLS currently always exposes the slot number to + * applications. This is not mandated by the PSA specification + * and may change in future versions. */ + TEST_EQUAL(status, 0); + TEST_ASSERT(slot_number != 0xec94d4a5058a1a21); + } else { + TEST_EQUAL(status, PSA_ERROR_INVALID_ARGUMENT); + } } #endif @@ -110,20 +119,27 @@ static int check_key_attributes_sanity(mbedtls_svc_key_id_t key) static int exercise_mac_key(mbedtls_svc_key_id_t key, psa_key_usage_t usage, - psa_algorithm_t alg) + psa_algorithm_t alg, + int key_destroyable) { psa_mac_operation_t operation = PSA_MAC_OPERATION_INIT; const unsigned char input[] = "foo"; unsigned char mac[PSA_MAC_MAX_SIZE] = { 0 }; size_t mac_length = sizeof(mac); - + psa_status_t status = PSA_SUCCESS; /* Convert wildcard algorithm to exercisable algorithm */ if (alg & PSA_ALG_MAC_AT_LEAST_THIS_LENGTH_FLAG) { alg = PSA_ALG_TRUNCATED_MAC(alg, PSA_MAC_TRUNCATED_LENGTH(alg)); } if (usage & PSA_KEY_USAGE_SIGN_HASH) { - PSA_ASSERT(psa_mac_sign_setup(&operation, key, alg)); + status = psa_mac_sign_setup(&operation, key, alg); + if (key_destroyable && status == PSA_ERROR_INVALID_HANDLE) { + /* The key has been destroyed. */ + PSA_ASSERT(psa_mac_abort(&operation)); + return 1; + } + PSA_ASSERT(status); PSA_ASSERT(psa_mac_update(&operation, input, sizeof(input))); PSA_ASSERT(psa_mac_sign_finish(&operation, @@ -136,7 +152,13 @@ static int exercise_mac_key(mbedtls_svc_key_id_t key, (usage & PSA_KEY_USAGE_SIGN_HASH ? PSA_SUCCESS : PSA_ERROR_INVALID_SIGNATURE); - PSA_ASSERT(psa_mac_verify_setup(&operation, key, alg)); + status = psa_mac_verify_setup(&operation, key, alg); + if (key_destroyable && status == PSA_ERROR_INVALID_HANDLE) { + /* The key has been destroyed. */ + PSA_ASSERT(psa_mac_abort(&operation)); + return 1; + } + PSA_ASSERT(status); PSA_ASSERT(psa_mac_update(&operation, input, sizeof(input))); TEST_EQUAL(psa_mac_verify_finish(&operation, mac, mac_length), @@ -152,7 +174,8 @@ static int exercise_mac_key(mbedtls_svc_key_id_t key, static int exercise_cipher_key(mbedtls_svc_key_id_t key, psa_key_usage_t usage, - psa_algorithm_t alg) + psa_algorithm_t alg, + int key_destroyable) { psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT; unsigned char iv[PSA_CIPHER_IV_MAX_SIZE] = { 0 }; @@ -164,13 +187,20 @@ static int exercise_cipher_key(mbedtls_svc_key_id_t key, size_t ciphertext_length = sizeof(ciphertext); unsigned char decrypted[sizeof(ciphertext)]; size_t part_length; + psa_status_t status = PSA_SUCCESS; PSA_ASSERT(psa_get_key_attributes(key, &attributes)); key_type = psa_get_key_type(&attributes); iv_length = PSA_CIPHER_IV_LENGTH(key_type, alg); if (usage & PSA_KEY_USAGE_ENCRYPT) { - PSA_ASSERT(psa_cipher_encrypt_setup(&operation, key, alg)); + status = psa_cipher_encrypt_setup(&operation, key, alg); + if (key_destroyable && status == PSA_ERROR_INVALID_HANDLE) { + /* The key has been destroyed. */ + PSA_ASSERT(psa_cipher_abort(&operation)); + return 1; + } + PSA_ASSERT(status); if (iv_length != 0) { PSA_ASSERT(psa_cipher_generate_iv(&operation, iv, sizeof(iv), @@ -188,12 +218,17 @@ static int exercise_cipher_key(mbedtls_svc_key_id_t key, } if (usage & PSA_KEY_USAGE_DECRYPT) { - psa_status_t status; int maybe_invalid_padding = 0; if (!(usage & PSA_KEY_USAGE_ENCRYPT)) { maybe_invalid_padding = !PSA_ALG_IS_STREAM_CIPHER(alg); } - PSA_ASSERT(psa_cipher_decrypt_setup(&operation, key, alg)); + status = psa_cipher_decrypt_setup(&operation, key, alg); + if (key_destroyable && status == PSA_ERROR_INVALID_HANDLE) { + /* The key has been destroyed. */ + PSA_ASSERT(psa_cipher_abort(&operation)); + return 1; + } + PSA_ASSERT(status); if (iv_length != 0) { PSA_ASSERT(psa_cipher_set_iv(&operation, iv, iv_length)); @@ -227,7 +262,8 @@ static int exercise_cipher_key(mbedtls_svc_key_id_t key, static int exercise_aead_key(mbedtls_svc_key_id_t key, psa_key_usage_t usage, - psa_algorithm_t alg) + psa_algorithm_t alg, + int key_destroyable) { unsigned char nonce[PSA_AEAD_NONCE_MAX_SIZE] = { 0 }; size_t nonce_length; @@ -237,6 +273,7 @@ static int exercise_aead_key(mbedtls_svc_key_id_t key, unsigned char ciphertext[48] = "(wabblewebblewibblewobblewubble)"; size_t ciphertext_length = sizeof(ciphertext); size_t plaintext_length = sizeof(ciphertext); + psa_status_t status = PSA_SUCCESS; /* Convert wildcard algorithm to exercisable algorithm */ if (alg & PSA_ALG_AEAD_AT_LEAST_THIS_LENGTH_FLAG) { @@ -248,12 +285,17 @@ static int exercise_aead_key(mbedtls_svc_key_id_t key, nonce_length = PSA_AEAD_NONCE_LENGTH(key_type, alg); if (usage & PSA_KEY_USAGE_ENCRYPT) { - PSA_ASSERT(psa_aead_encrypt(key, alg, - nonce, nonce_length, - NULL, 0, - plaintext, sizeof(plaintext), - ciphertext, sizeof(ciphertext), - &ciphertext_length)); + status = psa_aead_encrypt(key, alg, + nonce, nonce_length, + NULL, 0, + plaintext, sizeof(plaintext), + ciphertext, sizeof(ciphertext), + &ciphertext_length); + if (key_destroyable && status == PSA_ERROR_INVALID_HANDLE) { + /* The key has been destroyed. */ + return 1; + } + PSA_ASSERT(status); } if (usage & PSA_KEY_USAGE_DECRYPT) { @@ -261,13 +303,17 @@ static int exercise_aead_key(mbedtls_svc_key_id_t key, (usage & PSA_KEY_USAGE_ENCRYPT ? PSA_SUCCESS : PSA_ERROR_INVALID_SIGNATURE); - TEST_EQUAL(psa_aead_decrypt(key, alg, - nonce, nonce_length, - NULL, 0, - ciphertext, ciphertext_length, - plaintext, sizeof(plaintext), - &plaintext_length), - verify_status); + status = psa_aead_decrypt(key, alg, + nonce, nonce_length, + NULL, 0, + ciphertext, ciphertext_length, + plaintext, sizeof(plaintext), + &plaintext_length); + if (key_destroyable && status == PSA_ERROR_INVALID_HANDLE) { + /* The key has been destroyed. */ + return 1; + } + TEST_ASSERT(status == verify_status); } return 1; @@ -291,7 +337,8 @@ static int can_sign_or_verify_message(psa_key_usage_t usage, static int exercise_signature_key(mbedtls_svc_key_id_t key, psa_key_usage_t usage, - psa_algorithm_t alg) + psa_algorithm_t alg, + int key_destroyable) { /* If the policy allows signing with any hash, just pick one. */ psa_algorithm_t hash_alg = PSA_ALG_SIGN_GET_HASH(alg); @@ -305,6 +352,7 @@ static int exercise_signature_key(mbedtls_svc_key_id_t key, TEST_FAIL("No hash algorithm for hash-and-sign testing"); #endif } + psa_status_t status = PSA_SUCCESS; if (usage & (PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH) && PSA_ALG_IS_SIGN_HASH(alg)) { @@ -321,10 +369,15 @@ static int exercise_signature_key(mbedtls_svc_key_id_t key, } if (usage & PSA_KEY_USAGE_SIGN_HASH) { - PSA_ASSERT(psa_sign_hash(key, alg, - payload, payload_length, - signature, sizeof(signature), - &signature_length)); + status = psa_sign_hash(key, alg, + payload, payload_length, + signature, sizeof(signature), + &signature_length); + if (key_destroyable && status == PSA_ERROR_INVALID_HANDLE) { + /* The key has been destroyed. */ + return 1; + } + PSA_ASSERT(status); } if (usage & PSA_KEY_USAGE_VERIFY_HASH) { @@ -332,10 +385,14 @@ static int exercise_signature_key(mbedtls_svc_key_id_t key, (usage & PSA_KEY_USAGE_SIGN_HASH ? PSA_SUCCESS : PSA_ERROR_INVALID_SIGNATURE); - TEST_EQUAL(psa_verify_hash(key, alg, - payload, payload_length, - signature, signature_length), - verify_status); + status = psa_verify_hash(key, alg, + payload, payload_length, + signature, signature_length); + if (key_destroyable && status == PSA_ERROR_INVALID_HANDLE) { + /* The key has been destroyed. */ + return 1; + } + TEST_ASSERT(status == verify_status); } } @@ -346,10 +403,15 @@ static int exercise_signature_key(mbedtls_svc_key_id_t key, size_t signature_length = sizeof(signature); if (usage & PSA_KEY_USAGE_SIGN_MESSAGE) { - PSA_ASSERT(psa_sign_message(key, alg, - message, message_length, - signature, sizeof(signature), - &signature_length)); + status = psa_sign_message(key, alg, + message, message_length, + signature, sizeof(signature), + &signature_length); + if (key_destroyable && status == PSA_ERROR_INVALID_HANDLE) { + /* The key has been destroyed. */ + return 1; + } + PSA_ASSERT(status); } if (usage & PSA_KEY_USAGE_VERIFY_MESSAGE) { @@ -357,10 +419,14 @@ static int exercise_signature_key(mbedtls_svc_key_id_t key, (usage & PSA_KEY_USAGE_SIGN_MESSAGE ? PSA_SUCCESS : PSA_ERROR_INVALID_SIGNATURE); - TEST_EQUAL(psa_verify_message(key, alg, - message, message_length, - signature, signature_length), - verify_status); + status = psa_verify_message(key, alg, + message, message_length, + signature, signature_length); + if (key_destroyable && status == PSA_ERROR_INVALID_HANDLE) { + /* The key has been destroyed. */ + return 1; + } + TEST_ASSERT(status == verify_status); } } @@ -372,7 +438,8 @@ static int exercise_signature_key(mbedtls_svc_key_id_t key, static int exercise_asymmetric_encryption_key(mbedtls_svc_key_id_t key, psa_key_usage_t usage, - psa_algorithm_t alg) + psa_algorithm_t alg, + int key_destroyable) { unsigned char plaintext[PSA_ASYMMETRIC_DECRYPT_OUTPUT_MAX_SIZE] = "Hello, world..."; @@ -380,22 +447,30 @@ static int exercise_asymmetric_encryption_key(mbedtls_svc_key_id_t key, "(wabblewebblewibblewobblewubble)"; size_t ciphertext_length = sizeof(ciphertext); size_t plaintext_length = 16; - + psa_status_t status = PSA_SUCCESS; if (usage & PSA_KEY_USAGE_ENCRYPT) { - PSA_ASSERT(psa_asymmetric_encrypt(key, alg, - plaintext, plaintext_length, - NULL, 0, - ciphertext, sizeof(ciphertext), - &ciphertext_length)); + status = psa_asymmetric_encrypt(key, alg, + plaintext, plaintext_length, + NULL, 0, + ciphertext, sizeof(ciphertext), + &ciphertext_length); + if (key_destroyable && status == PSA_ERROR_INVALID_HANDLE) { + /* The key has been destroyed. */ + return 1; + } + PSA_ASSERT(status); } if (usage & PSA_KEY_USAGE_DECRYPT) { - psa_status_t status = - psa_asymmetric_decrypt(key, alg, - ciphertext, ciphertext_length, - NULL, 0, - plaintext, sizeof(plaintext), - &plaintext_length); + status = psa_asymmetric_decrypt(key, alg, + ciphertext, ciphertext_length, + NULL, 0, + plaintext, sizeof(plaintext), + &plaintext_length); + if (key_destroyable && status == PSA_ERROR_INVALID_HANDLE) { + /* The key has been destroyed. */ + return 1; + } TEST_ASSERT(status == PSA_SUCCESS || ((usage & PSA_KEY_USAGE_ENCRYPT) == 0 && (status == PSA_ERROR_INVALID_ARGUMENT || @@ -414,16 +489,22 @@ int mbedtls_test_psa_setup_key_derivation_wrap( psa_algorithm_t alg, const unsigned char *input1, size_t input1_length, const unsigned char *input2, size_t input2_length, - size_t capacity) + size_t capacity, int key_destroyable) { PSA_ASSERT(psa_key_derivation_setup(operation, alg)); + psa_status_t status = PSA_SUCCESS; if (PSA_ALG_IS_HKDF(alg)) { PSA_ASSERT(psa_key_derivation_input_bytes(operation, PSA_KEY_DERIVATION_INPUT_SALT, input1, input1_length)); - PSA_ASSERT(psa_key_derivation_input_key(operation, - PSA_KEY_DERIVATION_INPUT_SECRET, - key)); + status = psa_key_derivation_input_key(operation, + PSA_KEY_DERIVATION_INPUT_SECRET, + key); + if (key_destroyable && status == PSA_ERROR_INVALID_HANDLE) { + /* The key has been destroyed. */ + return 1; + } + PSA_ASSERT(status); PSA_ASSERT(psa_key_derivation_input_bytes(operation, PSA_KEY_DERIVATION_INPUT_INFO, input2, @@ -432,13 +513,23 @@ int mbedtls_test_psa_setup_key_derivation_wrap( PSA_ASSERT(psa_key_derivation_input_bytes(operation, PSA_KEY_DERIVATION_INPUT_SALT, input1, input1_length)); - PSA_ASSERT(psa_key_derivation_input_key(operation, - PSA_KEY_DERIVATION_INPUT_SECRET, - key)); + status = psa_key_derivation_input_key(operation, + PSA_KEY_DERIVATION_INPUT_SECRET, + key); + if (key_destroyable && status == PSA_ERROR_INVALID_HANDLE) { + /* The key has been destroyed. */ + return 1; + } + PSA_ASSERT(status); } else if (PSA_ALG_IS_HKDF_EXPAND(alg)) { - PSA_ASSERT(psa_key_derivation_input_key(operation, - PSA_KEY_DERIVATION_INPUT_SECRET, - key)); + status = psa_key_derivation_input_key(operation, + PSA_KEY_DERIVATION_INPUT_SECRET, + key); + if (key_destroyable && status == PSA_ERROR_INVALID_HANDLE) { + /* The key has been destroyed. */ + return 1; + } + PSA_ASSERT(status); PSA_ASSERT(psa_key_derivation_input_bytes(operation, PSA_KEY_DERIVATION_INPUT_INFO, input2, @@ -448,9 +539,14 @@ int mbedtls_test_psa_setup_key_derivation_wrap( PSA_ASSERT(psa_key_derivation_input_bytes(operation, PSA_KEY_DERIVATION_INPUT_SEED, input1, input1_length)); - PSA_ASSERT(psa_key_derivation_input_key(operation, - PSA_KEY_DERIVATION_INPUT_SECRET, - key)); + status = psa_key_derivation_input_key(operation, + PSA_KEY_DERIVATION_INPUT_SECRET, + key); + if (key_destroyable && status == PSA_ERROR_INVALID_HANDLE) { + /* The key has been destroyed. */ + return 1; + } + PSA_ASSERT(status); PSA_ASSERT(psa_key_derivation_input_bytes(operation, PSA_KEY_DERIVATION_INPUT_LABEL, input2, input2_length)); @@ -462,9 +558,14 @@ int mbedtls_test_psa_setup_key_derivation_wrap( PSA_KEY_DERIVATION_INPUT_SALT, input2, input2_length)); - PSA_ASSERT(psa_key_derivation_input_key(operation, - PSA_KEY_DERIVATION_INPUT_PASSWORD, - key)); + status = psa_key_derivation_input_key(operation, + PSA_KEY_DERIVATION_INPUT_PASSWORD, + key); + if (key_destroyable && status == PSA_ERROR_INVALID_HANDLE) { + /* The key has been destroyed. */ + return 1; + } + PSA_ASSERT(status); } else if (alg == PSA_ALG_TLS12_ECJPAKE_TO_PMS) { PSA_ASSERT(psa_key_derivation_input_bytes(operation, PSA_KEY_DERIVATION_INPUT_SECRET, @@ -486,7 +587,8 @@ int mbedtls_test_psa_setup_key_derivation_wrap( static int exercise_key_derivation_key(mbedtls_svc_key_id_t key, psa_key_usage_t usage, - psa_algorithm_t alg) + psa_algorithm_t alg, + int key_destroyable) { psa_key_derivation_operation_t operation = PSA_KEY_DERIVATION_OPERATION_INIT; unsigned char input1[] = "Input 1"; @@ -500,14 +602,20 @@ static int exercise_key_derivation_key(mbedtls_svc_key_id_t key, if (!mbedtls_test_psa_setup_key_derivation_wrap(&operation, key, alg, input1, input1_length, input2, input2_length, - capacity)) { + capacity, key_destroyable)) { goto exit; } - PSA_ASSERT(psa_key_derivation_output_bytes(&operation, - output, - capacity)); - PSA_ASSERT(psa_key_derivation_abort(&operation)); + psa_status_t status = psa_key_derivation_output_bytes(&operation, + output, + capacity); + if (key_destroyable && status == PSA_ERROR_BAD_STATE) { + /* The key has been destroyed. */ + PSA_ASSERT(psa_key_derivation_abort(&operation)); + } else { + PSA_ASSERT(status); + PSA_ASSERT(psa_key_derivation_abort(&operation)); + } } return 1; @@ -520,31 +628,45 @@ static int exercise_key_derivation_key(mbedtls_svc_key_id_t key, * private key against its own public key. */ psa_status_t mbedtls_test_psa_key_agreement_with_self( psa_key_derivation_operation_t *operation, - mbedtls_svc_key_id_t key) + mbedtls_svc_key_id_t key, int key_destroyable) { psa_key_type_t private_key_type; psa_key_type_t public_key_type; size_t key_bits; uint8_t *public_key = NULL; size_t public_key_length; - /* Return GENERIC_ERROR if something other than the final call to - * psa_key_derivation_key_agreement fails. This isn't fully satisfactory, - * but it's good enough: callers will report it as a failed test anyway. */ - psa_status_t status = PSA_ERROR_GENERIC_ERROR; psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; - PSA_ASSERT(psa_get_key_attributes(key, &attributes)); + psa_status_t status = psa_get_key_attributes(key, &attributes); + if (key_destroyable && status == PSA_ERROR_INVALID_HANDLE) { + /* The key has been destroyed. */ + psa_reset_key_attributes(&attributes); + return PSA_SUCCESS; + } + PSA_ASSERT(status); + private_key_type = psa_get_key_type(&attributes); key_bits = psa_get_key_bits(&attributes); public_key_type = PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(private_key_type); public_key_length = PSA_EXPORT_PUBLIC_KEY_OUTPUT_SIZE(public_key_type, key_bits); TEST_CALLOC(public_key, public_key_length); - PSA_ASSERT(psa_export_public_key(key, public_key, public_key_length, - &public_key_length)); + status = psa_export_public_key(key, public_key, public_key_length, + &public_key_length); + if (key_destroyable && status == PSA_ERROR_INVALID_HANDLE) { + /* The key has been destroyed. */ + status = PSA_SUCCESS; + goto exit; + } + PSA_ASSERT(status); status = psa_key_derivation_key_agreement( operation, PSA_KEY_DERIVATION_INPUT_SECRET, key, public_key, public_key_length); + if (key_destroyable && status == PSA_ERROR_INVALID_HANDLE) { + /* The key has been destroyed. */ + status = PSA_SUCCESS; + goto exit; + } exit: /* * Key attributes may have been returned by psa_get_key_attributes() @@ -560,7 +682,8 @@ psa_status_t mbedtls_test_psa_key_agreement_with_self( * private key against its own public key. */ psa_status_t mbedtls_test_psa_raw_key_agreement_with_self( psa_algorithm_t alg, - mbedtls_svc_key_id_t key) + mbedtls_svc_key_id_t key, + int key_destroyable) { psa_key_type_t private_key_type; psa_key_type_t public_key_type; @@ -569,25 +692,39 @@ psa_status_t mbedtls_test_psa_raw_key_agreement_with_self( size_t public_key_length; uint8_t output[1024]; size_t output_length; - /* Return GENERIC_ERROR if something other than the final call to - * psa_key_derivation_key_agreement fails. This isn't fully satisfactory, - * but it's good enough: callers will report it as a failed test anyway. */ - psa_status_t status = PSA_ERROR_GENERIC_ERROR; psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; - PSA_ASSERT(psa_get_key_attributes(key, &attributes)); + psa_status_t status = psa_get_key_attributes(key, &attributes); + if (key_destroyable && status == PSA_ERROR_INVALID_HANDLE) { + /* The key has been destroyed. */ + psa_reset_key_attributes(&attributes); + return PSA_SUCCESS; + } + PSA_ASSERT(status); + private_key_type = psa_get_key_type(&attributes); key_bits = psa_get_key_bits(&attributes); public_key_type = PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(private_key_type); public_key_length = PSA_EXPORT_PUBLIC_KEY_OUTPUT_SIZE(public_key_type, key_bits); TEST_CALLOC(public_key, public_key_length); - PSA_ASSERT(psa_export_public_key(key, - public_key, public_key_length, - &public_key_length)); + status = psa_export_public_key(key, + public_key, public_key_length, + &public_key_length); + if (key_destroyable && status == PSA_ERROR_INVALID_HANDLE) { + /* The key has been destroyed. */ + status = PSA_SUCCESS; + goto exit; + } + PSA_ASSERT(status); status = psa_raw_key_agreement(alg, key, public_key, public_key_length, output, sizeof(output), &output_length); + if (key_destroyable && status == PSA_ERROR_INVALID_HANDLE) { + /* The key has been destroyed. */ + status = PSA_SUCCESS; + goto exit; + } if (status == PSA_SUCCESS) { TEST_ASSERT(output_length <= PSA_RAW_KEY_AGREEMENT_OUTPUT_SIZE(private_key_type, @@ -609,14 +746,16 @@ psa_status_t mbedtls_test_psa_raw_key_agreement_with_self( static int exercise_raw_key_agreement_key(mbedtls_svc_key_id_t key, psa_key_usage_t usage, - psa_algorithm_t alg) + psa_algorithm_t alg, + int key_destroyable) { int ok = 0; if (usage & PSA_KEY_USAGE_DERIVE) { /* We need two keys to exercise key agreement. Exercise the * private key against its own public key. */ - PSA_ASSERT(mbedtls_test_psa_raw_key_agreement_with_self(alg, key)); + PSA_ASSERT(mbedtls_test_psa_raw_key_agreement_with_self(alg, key, + key_destroyable)); } ok = 1; @@ -626,7 +765,8 @@ static int exercise_raw_key_agreement_key(mbedtls_svc_key_id_t key, static int exercise_key_agreement_key(mbedtls_svc_key_id_t key, psa_key_usage_t usage, - psa_algorithm_t alg) + psa_algorithm_t alg, + int key_destroyable) { psa_key_derivation_operation_t operation = PSA_KEY_DERIVATION_OPERATION_INIT; unsigned char input[1] = { 0 }; @@ -657,7 +797,12 @@ static int exercise_key_agreement_key(mbedtls_svc_key_id_t key, hash length. Otherwise test should fail with INVALID_ARGUMENT. */ if (PSA_ALG_IS_HKDF_EXPAND(kdf_alg)) { psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; - PSA_ASSERT(psa_get_key_attributes(key, &attributes)); + psa_status_t status = psa_get_key_attributes(key, &attributes); + if (key_destroyable && status == PSA_ERROR_INVALID_HANDLE) { + /* The key has been destroyed. */ + ok = 1; + } + PSA_ASSERT(status); size_t key_bits = psa_get_key_bits(&attributes); psa_algorithm_t hash_alg = PSA_ALG_HKDF_GET_HASH(kdf_alg); @@ -666,7 +811,8 @@ static int exercise_key_agreement_key(mbedtls_svc_key_id_t key, } } - TEST_EQUAL(mbedtls_test_psa_key_agreement_with_self(&operation, key), + TEST_EQUAL(mbedtls_test_psa_key_agreement_with_self(&operation, key, + key_destroyable), expected_key_agreement_status); if (expected_key_agreement_status != PSA_SUCCESS) { @@ -857,7 +1003,8 @@ int mbedtls_test_psa_exported_key_sanity_check( } static int exercise_export_key(mbedtls_svc_key_id_t key, - psa_key_usage_t usage) + psa_key_usage_t usage, + int key_destroyable) { psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; uint8_t *exported = NULL; @@ -865,25 +1012,31 @@ static int exercise_export_key(mbedtls_svc_key_id_t key, size_t exported_length = 0; int ok = 0; - PSA_ASSERT(psa_get_key_attributes(key, &attributes)); + psa_status_t status = psa_get_key_attributes(key, &attributes); + if (key_destroyable && status == PSA_ERROR_INVALID_HANDLE) { + /* The key has been destroyed. */ + psa_reset_key_attributes(&attributes); + return 1; + } + PSA_ASSERT(status); exported_size = PSA_EXPORT_KEY_OUTPUT_SIZE( psa_get_key_type(&attributes), psa_get_key_bits(&attributes)); TEST_CALLOC(exported, exported_size); - if ((usage & PSA_KEY_USAGE_EXPORT) == 0 && - !PSA_KEY_TYPE_IS_PUBLIC_KEY(psa_get_key_type(&attributes))) { - TEST_EQUAL(psa_export_key(key, exported, - exported_size, &exported_length), - PSA_ERROR_NOT_PERMITTED); + status = psa_export_key(key, exported, exported_size, &exported_length); + if (key_destroyable && status == PSA_ERROR_INVALID_HANDLE) { + /* The key has been destroyed. */ + ok = 1; + goto exit; + } else if ((usage & PSA_KEY_USAGE_EXPORT) == 0 && + !PSA_KEY_TYPE_IS_PUBLIC_KEY(psa_get_key_type(&attributes))) { + TEST_EQUAL(status, PSA_ERROR_NOT_PERMITTED); ok = 1; goto exit; } - - PSA_ASSERT(psa_export_key(key, - exported, exported_size, - &exported_length)); + PSA_ASSERT(status); ok = mbedtls_test_psa_exported_key_sanity_check( psa_get_key_type(&attributes), psa_get_key_bits(&attributes), exported, exported_length); @@ -899,7 +1052,8 @@ static int exercise_export_key(mbedtls_svc_key_id_t key, return ok; } -static int exercise_export_public_key(mbedtls_svc_key_id_t key) +static int exercise_export_public_key(mbedtls_svc_key_id_t key, + int key_destroyable) { psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; psa_key_type_t public_type; @@ -908,16 +1062,27 @@ static int exercise_export_public_key(mbedtls_svc_key_id_t key) size_t exported_length = 0; int ok = 0; - PSA_ASSERT(psa_get_key_attributes(key, &attributes)); + psa_status_t status = psa_get_key_attributes(key, &attributes); + if (key_destroyable && status == PSA_ERROR_INVALID_HANDLE) { + /* The key has been destroyed. */ + psa_reset_key_attributes(&attributes); + return 1; + } + PSA_ASSERT(status); if (!PSA_KEY_TYPE_IS_ASYMMETRIC(psa_get_key_type(&attributes))) { exported_size = PSA_EXPORT_KEY_OUTPUT_SIZE( psa_get_key_type(&attributes), psa_get_key_bits(&attributes)); TEST_CALLOC(exported, exported_size); - TEST_EQUAL(psa_export_public_key(key, exported, - exported_size, &exported_length), - PSA_ERROR_INVALID_ARGUMENT); + status = psa_export_public_key(key, exported, + exported_size, &exported_length); + if (key_destroyable && status == PSA_ERROR_INVALID_HANDLE) { + /* The key has been destroyed. */ + ok = 1; + goto exit; + } + TEST_EQUAL(status, PSA_ERROR_INVALID_ARGUMENT); ok = 1; goto exit; } @@ -928,9 +1093,14 @@ static int exercise_export_public_key(mbedtls_svc_key_id_t key) psa_get_key_bits(&attributes)); TEST_CALLOC(exported, exported_size); - PSA_ASSERT(psa_export_public_key(key, - exported, exported_size, - &exported_length)); + status = psa_export_public_key(key, exported, + exported_size, &exported_length); + if (key_destroyable && status == PSA_ERROR_INVALID_HANDLE) { + /* The key has been destroyed. */ + ok = 1; + goto exit; + } + PSA_ASSERT(status); ok = mbedtls_test_psa_exported_key_sanity_check( public_type, psa_get_key_bits(&attributes), exported, exported_length); @@ -948,38 +1118,43 @@ static int exercise_export_public_key(mbedtls_svc_key_id_t key) int mbedtls_test_psa_exercise_key(mbedtls_svc_key_id_t key, psa_key_usage_t usage, - psa_algorithm_t alg) + psa_algorithm_t alg, + int key_destroyable) { int ok = 0; - if (!check_key_attributes_sanity(key)) { + if (!check_key_attributes_sanity(key, key_destroyable)) { return 0; } if (alg == 0) { ok = 1; /* If no algorithm, do nothing (used for raw data "keys"). */ } else if (PSA_ALG_IS_MAC(alg)) { - ok = exercise_mac_key(key, usage, alg); + ok = exercise_mac_key(key, usage, alg, key_destroyable); } else if (PSA_ALG_IS_CIPHER(alg)) { - ok = exercise_cipher_key(key, usage, alg); + ok = exercise_cipher_key(key, usage, alg, key_destroyable); } else if (PSA_ALG_IS_AEAD(alg)) { - ok = exercise_aead_key(key, usage, alg); + ok = exercise_aead_key(key, usage, alg, key_destroyable); } else if (PSA_ALG_IS_SIGN(alg)) { - ok = exercise_signature_key(key, usage, alg); + ok = exercise_signature_key(key, usage, alg, key_destroyable); } else if (PSA_ALG_IS_ASYMMETRIC_ENCRYPTION(alg)) { - ok = exercise_asymmetric_encryption_key(key, usage, alg); + ok = exercise_asymmetric_encryption_key(key, usage, alg, + key_destroyable); } else if (PSA_ALG_IS_KEY_DERIVATION(alg)) { - ok = exercise_key_derivation_key(key, usage, alg); + ok = exercise_key_derivation_key(key, usage, alg, key_destroyable); } else if (PSA_ALG_IS_RAW_KEY_AGREEMENT(alg)) { - ok = exercise_raw_key_agreement_key(key, usage, alg); + ok = exercise_raw_key_agreement_key(key, usage, alg, key_destroyable); } else if (PSA_ALG_IS_KEY_AGREEMENT(alg)) { - ok = exercise_key_agreement_key(key, usage, alg); + ok = exercise_key_agreement_key(key, usage, alg, key_destroyable); } else { TEST_FAIL("No code to exercise this category of algorithm"); } - ok = ok && exercise_export_key(key, usage); - ok = ok && exercise_export_public_key(key); + ok = ok && exercise_export_key(key, + usage, + key_destroyable); + ok = ok && exercise_export_public_key(key, + key_destroyable); exit: return ok; diff --git a/tests/suites/test_suite_pkparse.function b/tests/suites/test_suite_pkparse.function index 7dc8413c8500..a06fc30bc848 100644 --- a/tests/suites/test_suite_pkparse.function +++ b/tests/suites/test_suite_pkparse.function @@ -57,7 +57,7 @@ static int test_psa_bridge(const mbedtls_pk_context *ctx, if (mbedtls_test_can_exercise_psa_algorithm(exercise_alg)) { TEST_ASSERT(mbedtls_test_psa_exercise_key(psa_key, exercise_usage, - exercise_alg)); + exercise_alg, 0)); } mbedtls_test_set_step((unsigned long) -1); diff --git a/tests/suites/test_suite_psa_crypto.data b/tests/suites/test_suite_psa_crypto.data index b633c6f60ffc..a3a457da8ae9 100644 --- a/tests/suites/test_suite_psa_crypto.data +++ b/tests/suites/test_suite_psa_crypto.data @@ -4278,6 +4278,50 @@ PSA import/exercise: TLS 1.2 PRF SHA-256 depends_on:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_TLS12_PRF import_and_exercise_key:"c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0":PSA_KEY_TYPE_DERIVE:192:PSA_ALG_TLS12_PRF(PSA_ALG_SHA_256) +PSA concurrently import/exercise same key: RSA keypair, PKCS#1 v1.5 raw +depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_IMPORT +concurrently_use_same_persistent_key:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_KEY_TYPE_RSA_KEY_PAIR:1024:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:100 + +PSA concurrently import/exercise same key: RSA keypair, PSS-SHA-256 +depends_on:PSA_WANT_ALG_RSA_PSS:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_IMPORT +concurrently_use_same_persistent_key:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_KEY_TYPE_RSA_KEY_PAIR:1024:PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):100 + +PSA concurrently import/exercise same key: RSA keypair, PSS-any-salt-SHA-256 +depends_on:PSA_WANT_ALG_RSA_PSS:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_IMPORT +concurrently_use_same_persistent_key:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_KEY_TYPE_RSA_KEY_PAIR:1024:PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):100 + +PSA concurrently import/exercise same key: RSA public key, PKCS#1 v1.5 raw +depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY +concurrently_use_same_persistent_key:"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_KEY_TYPE_RSA_PUBLIC_KEY:1024:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:100 + +PSA concurrently import/exercise same key: RSA public key, PSS-SHA-256 +depends_on:PSA_WANT_ALG_RSA_PSS:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY +concurrently_use_same_persistent_key:"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_KEY_TYPE_RSA_PUBLIC_KEY:1024:PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):100 + +PSA concurrently import/exercise same key: RSA public key, PSS-any-salt-SHA-256 +depends_on:PSA_WANT_ALG_RSA_PSS:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY +concurrently_use_same_persistent_key:"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_KEY_TYPE_RSA_PUBLIC_KEY:1024:PSA_ALG_RSA_PSS_ANY_SALT(PSA_ALG_SHA_256):100 + +PSA concurrently import/exercise same key: ECP SECP256R1 keypair, ECDSA +depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_EXPORT:PSA_WANT_ECC_SECP_R1_256 +concurrently_use_same_persistent_key:"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):256:PSA_ALG_ECDSA_ANY:100 + +PSA concurrently import/exercise same key: ECP SECP256R1 keypair, deterministic ECDSA +depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_EXPORT:PSA_WANT_ECC_SECP_R1_256 +concurrently_use_same_persistent_key:"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):256:PSA_ALG_DETERMINISTIC_ECDSA( PSA_ALG_SHA_256 ):100 + +PSA concurrently import/exercise same key: ECP SECP256R1 keypair, ECDH +depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_EXPORT:PSA_WANT_ECC_SECP_R1_256 +concurrently_use_same_persistent_key:"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):256:PSA_ALG_ECDH:100 + +PSA concurrently import/exercise same key: HKDF SHA-256 +depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256 +concurrently_use_same_persistent_key:"c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0":PSA_KEY_TYPE_DERIVE:192:PSA_ALG_HKDF(PSA_ALG_SHA_256):100 + +PSA concurrently import/exercise same key: TLS 1.2 PRF SHA-256 +depends_on:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_TLS12_PRF +concurrently_use_same_persistent_key:"c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0":PSA_KEY_TYPE_DERIVE:192:PSA_ALG_TLS12_PRF(PSA_ALG_SHA_256):100 + PSA sign hash: RSA PKCS#1 v1.5, raw depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_IMPORT sign_hash_deterministic:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_PKCS1V15_SIGN_RAW:"616263":"2c7744983f023ac7bb1c55529d83ed11a76a7898a1bb5ce191375a4aa7495a633d27879ff58eba5a57371c34feb1180e8b850d552476ebb5634df620261992f12ebee9097041dbbea85a42d45b344be5073ceb772ffc604954b9158ba81ec3dc4d9d65e3ab7aa318165f38c36f841f1c69cb1cfa494aa5cbb4d6c0efbafb043a" diff --git a/tests/suites/test_suite_psa_crypto.function b/tests/suites/test_suite_psa_crypto.function index 114159799dac..7a242fd73d79 100644 --- a/tests/suites/test_suite_psa_crypto.function +++ b/tests/suites/test_suite_psa_crypto.function @@ -1338,6 +1338,126 @@ exit: } #if defined(MBEDTLS_THREADING_PTHREAD) + +typedef struct same_key_context { + data_t *data; + mbedtls_svc_key_id_t key; + psa_key_attributes_t *attributes; + int type; + int bits; + /* The following two parameters are used to ensure that when multiple + * threads attempt to load/destroy the key, exactly one thread succeeds. */ + int key_loaded; + mbedtls_threading_mutex_t MBEDTLS_PRIVATE(key_loaded_mutex); +} +same_key_context; + +/* Attempt to import the key in ctx. This handles any valid error codes + * and reports an error for any invalid codes. This function also insures + * that once imported by some thread, all threads can use the key. */ +void *thread_import_key(void *ctx) +{ + mbedtls_svc_key_id_t returned_key_id; + same_key_context *skc = (struct same_key_context *) ctx; + psa_key_attributes_t got_attributes = PSA_KEY_ATTRIBUTES_INIT; + + /* Import the key, exactly one thread must succeed. */ + psa_status_t status = psa_import_key(skc->attributes, skc->data->x, + skc->data->len, &returned_key_id); + switch (status) { + case PSA_SUCCESS: + if (mbedtls_mutex_lock(&skc->key_loaded_mutex) == 0) { + if (skc->key_loaded) { + mbedtls_mutex_unlock(&skc->key_loaded_mutex); + /* More than one thread has succeeded, report a failure. */ + TEST_FAIL("The same key has been loaded into the key store multiple times."); + } + skc->key_loaded = 1; + mbedtls_mutex_unlock(&skc->key_loaded_mutex); + } + break; + case PSA_ERROR_INSUFFICIENT_MEMORY: + /* If all of the key slots are reserved when a thread + * locks the mutex to reserve a new slot, it will return + * PSA_ERROR_INSUFFICIENT_MEMORY; this is correct behaviour. + * There is a chance for this to occur here when the number of + * threads running this function is larger than the number of + * free key slots. Each thread reserves an empty key slot, + * unlocks the mutex, then relocks it to finalize key creation. + * It is at that point where the thread sees that the key + * already exists, releases the reserved slot, + * and returns PSA_ERROR_ALREADY_EXISTS. + * There is no guarantee that the key is loaded upon this return + * code, so we can't test the key information. Just stop this + * thread from executing, note that this is not an error. */ + goto exit; + break; + case PSA_ERROR_ALREADY_EXISTS: + /* The key has been loaded by a different thread. */ + break; + default: + PSA_ASSERT(status); + } + /* At this point the key must exist, test the key information. */ + status = psa_get_key_attributes(skc->key, &got_attributes); + if (status == PSA_ERROR_INSUFFICIENT_MEMORY) { + /* This is not a test failure. The following sequence of events + * causes this to occur: + * 1: This thread successfuly imports a persistent key skc->key. + * 2: N threads reserve an empty key slot in psa_import_key, + * where N is equal to the number of free key slots. + * 3: A final thread attempts to reserve an empty key slot, kicking + * skc->key (which has no registered readers) out of its slot. + * 4: This thread calls psa_get_key_attributes(skc->key,...): + * it sees that skc->key is not in a slot, attempts to load it and + * finds that there are no free slots. + * This thread returns PSA_ERROR_INSUFFICIENT_MEMORY. + * + * The PSA spec allows this behaviour, it is an unavoidable consequence + * of allowing persistent keys to be kicked out of the key store while + * they are still valid. */ + goto exit; + } + PSA_ASSERT(status); + TEST_EQUAL(psa_get_key_type(&got_attributes), skc->type); + TEST_EQUAL(psa_get_key_bits(&got_attributes), skc->bits); + +exit: + /* Key attributes may have been returned by psa_get_key_attributes(), + * reset them as required. */ + psa_reset_key_attributes(&got_attributes); + return NULL; +} + +void *thread_use_and_destroy_key(void *ctx) +{ + same_key_context *skc = (struct same_key_context *) ctx; + + /* Do something with the key according + * to its type and permitted usage. */ + TEST_ASSERT(mbedtls_test_psa_exercise_key(skc->key, + skc->attributes->policy.usage, + skc->attributes->policy.alg, 1)); + + psa_status_t status = psa_destroy_key(skc->key); + if (status == PSA_SUCCESS) { + if (mbedtls_mutex_lock(&skc->key_loaded_mutex) == 0) { + /* Ensure that we are the only thread to succeed. */ + if (skc->key_loaded != 1) { + mbedtls_mutex_unlock(&skc->key_loaded_mutex); + TEST_FAIL("The same key has been destroyed multiple times."); + } + skc->key_loaded = 0; + mbedtls_mutex_unlock(&skc->key_loaded_mutex); + } + } else { + TEST_EQUAL(status, PSA_ERROR_INVALID_HANDLE); + } + +exit: + return NULL; +} + typedef struct generate_key_context { psa_key_type_t type; psa_key_usage_t usage; @@ -1379,7 +1499,7 @@ void *thread_generate_key(void *ctx) /* Do something with the key according * to its type and permitted usage. */ - if (!mbedtls_test_psa_exercise_key(key, gkc->usage, gkc->alg)) { + if (!mbedtls_test_psa_exercise_key(key, gkc->usage, gkc->alg, 0)) { psa_destroy_key(key); goto exit; } @@ -1715,7 +1835,7 @@ void import_export(data_t *data, * this doesn't directly validate the implementation, but it still helps * by cross-validating the test data with the sanity check code. */ if (!psa_key_lifetime_is_external(lifetime)) { - if (!mbedtls_test_psa_exercise_key(key, usage_arg, 0)) { + if (!mbedtls_test_psa_exercise_key(key, usage_arg, 0, 0)) { goto exit; } } @@ -1824,6 +1944,78 @@ exit: } /* END_CASE */ + +#if defined(MBEDTLS_THREADING_PTHREAD) +/* BEGIN_CASE depends_on:MBEDTLS_THREADING_PTHREAD:MBEDTLS_PSA_CRYPTO_STORAGE_C */ +void concurrently_use_same_persistent_key(data_t *data, + int type_arg, + int bits_arg, + int alg_arg, + int thread_count_arg) +{ + size_t thread_count = (size_t) thread_count_arg; + mbedtls_test_thread_t *threads = NULL; + mbedtls_svc_key_id_t key_id = mbedtls_svc_key_id_make(1, 1); + same_key_context skc; + skc.data = data; + skc.key = key_id; + skc.type = type_arg; + skc.bits = bits_arg; + skc.key_loaded = 0; + mbedtls_mutex_init(&skc.key_loaded_mutex); + psa_key_usage_t usage = mbedtls_test_psa_usage_to_exercise(skc.type, alg_arg); + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + + PSA_ASSERT(psa_crypto_init()); + + psa_set_key_id(&attributes, key_id); + psa_set_key_lifetime(&attributes, PSA_KEY_LIFETIME_PERSISTENT); + psa_set_key_usage_flags(&attributes, usage); + psa_set_key_algorithm(&attributes, alg_arg); + psa_set_key_type(&attributes, type_arg); + psa_set_key_bits(&attributes, bits_arg); + skc.attributes = &attributes; + + TEST_CALLOC(threads, sizeof(mbedtls_test_thread_t) * thread_count); + + /* Test that when multiple threads import the same key, + * exactly one thread succeeds and the rest fail with valid errors. + * Also test that all threads can use the key as soon as it has been + * imported. */ + for (size_t i = 0; i < thread_count; i++) { + TEST_EQUAL( + mbedtls_test_thread_create(&threads[i], thread_import_key, + (void *) &skc), 0); + } + + /* Join threads. */ + for (size_t i = 0; i < thread_count; i++) { + TEST_EQUAL(mbedtls_test_thread_join(&threads[i]), 0); + } + + /* Test that when multiple threads use and destroy a key no corruption + * occurs, and exactly one thread succeeds when destroying the key. */ + for (size_t i = 0; i < thread_count; i++) { + TEST_EQUAL( + mbedtls_test_thread_create(&threads[i], thread_use_and_destroy_key, + (void *) &skc), 0); + } + + /* Join threads. */ + for (size_t i = 0; i < thread_count; i++) { + TEST_EQUAL(mbedtls_test_thread_join(&threads[i]), 0); + } + /* Ensure that one thread succeeded in destroying the key. */ + TEST_ASSERT(!skc.key_loaded); +exit: + psa_reset_key_attributes(&attributes); + mbedtls_mutex_free(&skc.key_loaded_mutex); + mbedtls_free(threads); + PSA_DONE(); +} +/* END_CASE */ +#endif + /* BEGIN_CASE */ void import_and_exercise_key(data_t *data, int type_arg, @@ -1853,7 +2045,7 @@ void import_and_exercise_key(data_t *data, TEST_EQUAL(psa_get_key_bits(&got_attributes), bits); /* Do something with the key according to its type and permitted usage. */ - if (!mbedtls_test_psa_exercise_key(key, usage, alg)) { + if (!mbedtls_test_psa_exercise_key(key, usage, alg, 0)) { goto exit; } @@ -2490,7 +2682,7 @@ void agreement_key_policy(int policy_usage, &key)); PSA_ASSERT(psa_key_derivation_setup(&operation, exercise_alg)); - status = mbedtls_test_psa_key_agreement_with_self(&operation, key); + status = mbedtls_test_psa_key_agreement_with_self(&operation, key, 0); TEST_EQUAL(status, expected_status); @@ -2529,10 +2721,10 @@ void key_policy_alg2(int key_type_arg, data_t *key_data, TEST_EQUAL(psa_get_key_algorithm(&got_attributes), alg); TEST_EQUAL(psa_get_key_enrollment_algorithm(&got_attributes), alg2); - if (!mbedtls_test_psa_exercise_key(key, usage, alg)) { + if (!mbedtls_test_psa_exercise_key(key, usage, alg, 0)) { goto exit; } - if (!mbedtls_test_psa_exercise_key(key, usage, alg2)) { + if (!mbedtls_test_psa_exercise_key(key, usage, alg2, 0)) { goto exit; } @@ -2572,7 +2764,7 @@ void raw_agreement_key_policy(int policy_usage, PSA_ASSERT(psa_import_key(&attributes, key_data->x, key_data->len, &key)); - status = mbedtls_test_psa_raw_key_agreement_with_self(exercise_alg, key); + status = mbedtls_test_psa_raw_key_agreement_with_self(exercise_alg, key, 0); TEST_EQUAL(status, expected_status); @@ -2663,10 +2855,10 @@ void copy_success(int source_usage_arg, } if (!psa_key_lifetime_is_external(target_lifetime)) { - if (!mbedtls_test_psa_exercise_key(target_key, expected_usage, expected_alg)) { + if (!mbedtls_test_psa_exercise_key(target_key, expected_usage, expected_alg, 0)) { goto exit; } - if (!mbedtls_test_psa_exercise_key(target_key, expected_usage, expected_alg2)) { + if (!mbedtls_test_psa_exercise_key(target_key, expected_usage, expected_alg2, 0)) { goto exit; } } @@ -8681,7 +8873,7 @@ void derive_input(int alg_arg, // When taking a private key as secret input, use key agreement // to add the shared secret to the derivation TEST_EQUAL(mbedtls_test_psa_key_agreement_with_self( - &operation, keys[i]), + &operation, keys[i], 0), expected_statuses[i]); } else { TEST_EQUAL(psa_key_derivation_input_key(&operation, steps[i], @@ -8780,7 +8972,7 @@ void derive_over_capacity(int alg_arg) if (!mbedtls_test_psa_setup_key_derivation_wrap(&operation, key, alg, input1, input1_length, input2, input2_length, - capacity)) { + capacity, 0)) { goto exit; } @@ -9099,7 +9291,7 @@ void derive_full(int alg_arg, if (!mbedtls_test_psa_setup_key_derivation_wrap(&operation, key, alg, input1->x, input1->len, input2->x, input2->len, - requested_capacity)) { + requested_capacity, 0)) { goto exit; } @@ -9216,7 +9408,7 @@ void derive_key_exercise(int alg_arg, if (!mbedtls_test_psa_setup_key_derivation_wrap(&operation, base_key, alg, input1->x, input1->len, input2->x, input2->len, - capacity)) { + capacity, 0)) { goto exit; } @@ -9233,7 +9425,7 @@ void derive_key_exercise(int alg_arg, TEST_EQUAL(psa_get_key_bits(&got_attributes), derived_bits); /* Exercise the derived key. */ - if (!mbedtls_test_psa_exercise_key(derived_key, derived_usage, derived_alg)) { + if (!mbedtls_test_psa_exercise_key(derived_key, derived_usage, derived_alg, 0)) { goto exit; } @@ -9286,7 +9478,7 @@ void derive_key_export(int alg_arg, if (!mbedtls_test_psa_setup_key_derivation_wrap(&operation, base_key, alg, input1->x, input1->len, input2->x, input2->len, - capacity)) { + capacity, 0)) { goto exit; } @@ -9299,7 +9491,7 @@ void derive_key_export(int alg_arg, if (!mbedtls_test_psa_setup_key_derivation_wrap(&operation, base_key, alg, input1->x, input1->len, input2->x, input2->len, - capacity)) { + capacity, 0)) { goto exit; } @@ -9370,7 +9562,7 @@ void derive_key_type(int alg_arg, &operation, base_key, alg, input1->x, input1->len, input2->x, input2->len, - PSA_KEY_DERIVATION_UNLIMITED_CAPACITY) == 0) { + PSA_KEY_DERIVATION_UNLIMITED_CAPACITY, 0) == 0) { goto exit; } @@ -9435,7 +9627,7 @@ void derive_key_ext(int alg_arg, &operation, base_key, alg, input1->x, input1->len, input2->x, input2->len, - PSA_KEY_DERIVATION_UNLIMITED_CAPACITY) == 0) { + PSA_KEY_DERIVATION_UNLIMITED_CAPACITY, 0) == 0) { goto exit; } @@ -9499,7 +9691,7 @@ void derive_key(int alg_arg, if (!mbedtls_test_psa_setup_key_derivation_wrap(&operation, base_key, alg, input1->x, input1->len, input2->x, input2->len, - SIZE_MAX)) { + SIZE_MAX, 0)) { goto exit; } @@ -9941,7 +10133,7 @@ void generate_key(int type_arg, TEST_EQUAL(psa_get_key_bits(&got_attributes), bits); /* Do something with the key according to its type and permitted usage. */ - if (!mbedtls_test_psa_exercise_key(key, usage, alg)) { + if (!mbedtls_test_psa_exercise_key(key, usage, alg, 0)) { goto exit; } @@ -10011,7 +10203,7 @@ void generate_key_ext(int type_arg, #endif /* Do something with the key according to its type and permitted usage. */ - if (!mbedtls_test_psa_exercise_key(key, usage, alg)) { + if (!mbedtls_test_psa_exercise_key(key, usage, alg, 0)) { goto exit; } @@ -10162,7 +10354,7 @@ void persistent_key_load_key_from_storage(data_t *data, } /* Do something with the key according to its type and permitted usage. */ - if (!mbedtls_test_psa_exercise_key(key, usage_flags, alg)) { + if (!mbedtls_test_psa_exercise_key(key, usage_flags, alg, 0)) { goto exit; } diff --git a/tests/suites/test_suite_psa_crypto_storage_format.function b/tests/suites/test_suite_psa_crypto_storage_format.function index bb1e2c68c33d..efaaba58a39e 100644 --- a/tests/suites/test_suite_psa_crypto_storage_format.function +++ b/tests/suites/test_suite_psa_crypto_storage_format.function @@ -187,7 +187,7 @@ static int test_read_key(const psa_key_attributes_t *expected_attributes, TEST_ASSERT(mbedtls_test_psa_exercise_key( key_id, psa_get_key_usage_flags(expected_attributes), - psa_get_key_algorithm(expected_attributes))); + psa_get_key_algorithm(expected_attributes), 0)); }