diff --git a/include/test/psa_exercise_key.h b/include/test/psa_exercise_key.h index 44f5c08aa..f6be3073a 100644 --- a/include/test/psa_exercise_key.h +++ b/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; * ``` + * 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. * - * \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. + * 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/include/test/ssl_helpers.h b/include/test/ssl_helpers.h index 335386be1..77f85c496 100644 --- a/include/test/ssl_helpers.h +++ b/include/test/ssl_helpers.h @@ -78,6 +78,10 @@ enum { #undef MBEDTLS_SSL_TLS1_3_LABEL }; +#if defined(MBEDTLS_SSL_ALPN) +#define MBEDTLS_TEST_MAX_ALPN_LIST_SIZE 10 +#endif + typedef struct mbedtls_test_ssl_log_pattern { const char *pattern; size_t counter; @@ -118,6 +122,9 @@ typedef struct mbedtls_test_handshake_test_options { #if defined(MBEDTLS_SSL_CACHE_C) mbedtls_ssl_cache_context *cache; #endif +#if defined(MBEDTLS_SSL_ALPN) + const char *alpn_list[MBEDTLS_TEST_MAX_ALPN_LIST_SIZE]; +#endif } mbedtls_test_handshake_test_options; /* diff --git a/src/psa_crypto_stubs.c b/src/psa_crypto_stubs.c index f3ca85074..81d7f4b32 100644 --- a/src/psa_crypto_stubs.c +++ b/src/psa_crypto_stubs.c @@ -22,4 +22,54 @@ psa_status_t psa_generate_random(uint8_t *output, return PSA_ERROR_COMMUNICATION_FAILURE; } +psa_status_t psa_export_key(mbedtls_svc_key_id_t key, + uint8_t *data, + size_t data_size, + size_t *data_length) +{ + (void) key; + (void) data; + (void) data_size; + (void) data_length; + return PSA_ERROR_COMMUNICATION_FAILURE; +} + +psa_status_t psa_export_public_key(mbedtls_svc_key_id_t key, + uint8_t *data, + size_t data_size, + size_t *data_length) +{ + (void) key; + (void) data; + (void) data_size; + (void) data_length; + return PSA_ERROR_COMMUNICATION_FAILURE; +} + +psa_status_t psa_get_key_attributes(mbedtls_svc_key_id_t key, + psa_key_attributes_t *attributes) +{ + (void) key; + (void) attributes; + return PSA_ERROR_COMMUNICATION_FAILURE; +} + +psa_status_t psa_hash_abort(psa_hash_operation_t *operation) +{ + (void) operation; + return PSA_ERROR_COMMUNICATION_FAILURE; +} + +psa_status_t psa_import_key(const psa_key_attributes_t *attributes, + const uint8_t *data, + size_t data_length, + mbedtls_svc_key_id_t *key) +{ + (void) attributes; + (void) data; + (void) data_length; + (void) key; + return PSA_ERROR_COMMUNICATION_FAILURE; +} + #endif /* MBEDTLS_PSA_CRYPTO_CLIENT && !MBEDTLS_PSA_CRYPTO_C */ diff --git a/src/psa_exercise_key.c b/src/psa_exercise_key.c index 7b81052c8..937bd45d2 100644 --- a/src/psa_exercise_key.c +++ b/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 @@ exit: 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 @@ exit: 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 @@ exit: 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 @@ exit: 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 @@ exit: 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 @@ exit: * 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 @@ exit: * 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 @@ exit: 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 @@ exit: 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 @@ exit: } 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 @@ exit: 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 @@ exit: 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/src/test_helpers/ssl_helpers.c b/src/test_helpers/ssl_helpers.c index 56e03f109..55201c0b7 100644 --- a/src/test_helpers/ssl_helpers.c +++ b/src/test_helpers/ssl_helpers.c @@ -833,6 +833,12 @@ int mbedtls_test_ssl_endpoint_init( options->max_early_data_size); } #endif +#if defined(MBEDTLS_SSL_ALPN) + /* check that alpn_list contains at least one valid entry */ + if (options->alpn_list[0] != NULL) { + mbedtls_ssl_conf_alpn_protocols(&(ep->conf), options->alpn_list); + } +#endif #endif #if defined(MBEDTLS_SSL_CACHE_C) && defined(MBEDTLS_SSL_SRV_C) @@ -1793,7 +1799,13 @@ int mbedtls_test_ssl_tls13_populate_session(mbedtls_ssl_session *session, #if defined(MBEDTLS_SSL_EARLY_DATA) session->max_early_data_size = 0x87654321; -#endif +#if defined(MBEDTLS_SSL_ALPN) && defined(MBEDTLS_SSL_SRV_C) + int ret = mbedtls_ssl_session_set_ticket_alpn(session, "ALPNExample"); + if (ret != 0) { + return -1; + } +#endif /* MBEDTLS_SSL_ALPN && MBEDTLS_SSL_SRV_C */ +#endif /* MBEDTLS_SSL_EARLY_DATA */ #if defined(MBEDTLS_HAVE_TIME) && defined(MBEDTLS_SSL_SRV_C) if (session->endpoint == MBEDTLS_SSL_IS_SERVER) {