From 7e0cff90b9bb6ed0295919e79512902dfe51ed79 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Tue, 30 Jul 2019 13:48:52 +0200 Subject: [PATCH 01/20] Move attribute fields to a substructure Move the "core attributes" to a substructure of psa_key_attribute_t. The motivation is to be able to use the new structure psa_core_key_attributes_t internally. --- include/psa/crypto_extra.h | 4 +- include/psa/crypto_struct.h | 49 ++++++++++++--------- library/psa_crypto.c | 40 ++++++++--------- library/psa_crypto_core.h | 2 +- library/psa_crypto_se.c | 2 +- library/psa_crypto_slot_management.c | 2 +- library/psa_crypto_storage.c | 10 ++--- tests/suites/test_suite_psa_crypto.function | 2 +- 8 files changed, 59 insertions(+), 52 deletions(-) diff --git a/include/psa/crypto_extra.h b/include/psa/crypto_extra.h index b2d4633de..6dfaa1300 100644 --- a/include/psa/crypto_extra.h +++ b/include/psa/crypto_extra.h @@ -89,7 +89,7 @@ static inline void psa_set_key_enrollment_algorithm( psa_key_attributes_t *attributes, psa_algorithm_t alg2) { - attributes->policy.alg2 = alg2; + attributes->core.policy.alg2 = alg2; } /** Retrieve the enrollment algorithm policy from key attributes. @@ -101,7 +101,7 @@ static inline void psa_set_key_enrollment_algorithm( static inline psa_algorithm_t psa_get_key_enrollment_algorithm( const psa_key_attributes_t *attributes) { - return( attributes->policy.alg2 ); + return( attributes->core.policy.alg2 ); } /**@}*/ diff --git a/include/psa/crypto_struct.h b/include/psa/crypto_struct.h index 0ddc7a3eb..fea59df37 100644 --- a/include/psa/crypto_struct.h +++ b/include/psa/crypto_struct.h @@ -309,18 +309,25 @@ static inline struct psa_key_policy_s psa_key_policy_init( void ) return( v ); } +typedef struct +{ + psa_key_type_t type; + psa_key_lifetime_t lifetime; + psa_key_id_t id; + psa_key_policy_t policy; + size_t bits; +} psa_core_key_attributes_t; + +#define PSA_CORE_KEY_ATTRIBUTES_INIT {0, 0, 0, {0, 0, 0}, 0} + struct psa_key_attributes_s { - psa_key_id_t id; - psa_key_lifetime_t lifetime; - psa_key_policy_t policy; - psa_key_type_t type; - size_t bits; + psa_core_key_attributes_t core; void *domain_parameters; size_t domain_parameters_size; }; -#define PSA_KEY_ATTRIBUTES_INIT {0, 0, {0, 0, 0}, 0, 0, NULL, 0} +#define PSA_KEY_ATTRIBUTES_INIT {PSA_CORE_KEY_ATTRIBUTES_INIT, NULL, 0} static inline struct psa_key_attributes_s psa_key_attributes_init( void ) { const struct psa_key_attributes_s v = PSA_KEY_ATTRIBUTES_INIT; @@ -330,53 +337,53 @@ static inline struct psa_key_attributes_s psa_key_attributes_init( void ) static inline void psa_set_key_id(psa_key_attributes_t *attributes, psa_key_id_t id) { - attributes->id = id; - if( attributes->lifetime == PSA_KEY_LIFETIME_VOLATILE ) - attributes->lifetime = PSA_KEY_LIFETIME_PERSISTENT; + attributes->core.id = id; + if( attributes->core.lifetime == PSA_KEY_LIFETIME_VOLATILE ) + attributes->core.lifetime = PSA_KEY_LIFETIME_PERSISTENT; } static inline psa_key_id_t psa_get_key_id( const psa_key_attributes_t *attributes) { - return( attributes->id ); + return( attributes->core.id ); } static inline void psa_set_key_lifetime(psa_key_attributes_t *attributes, psa_key_lifetime_t lifetime) { - attributes->lifetime = lifetime; + attributes->core.lifetime = lifetime; if( lifetime == PSA_KEY_LIFETIME_VOLATILE ) - attributes->id = 0; + attributes->core.id = 0; } static inline psa_key_lifetime_t psa_get_key_lifetime( const psa_key_attributes_t *attributes) { - return( attributes->lifetime ); + return( attributes->core.lifetime ); } static inline void psa_set_key_usage_flags(psa_key_attributes_t *attributes, psa_key_usage_t usage_flags) { - attributes->policy.usage = usage_flags; + attributes->core.policy.usage = usage_flags; } static inline psa_key_usage_t psa_get_key_usage_flags( const psa_key_attributes_t *attributes) { - return( attributes->policy.usage ); + return( attributes->core.policy.usage ); } static inline void psa_set_key_algorithm(psa_key_attributes_t *attributes, psa_algorithm_t alg) { - attributes->policy.alg = alg; + attributes->core.policy.alg = alg; } static inline psa_algorithm_t psa_get_key_algorithm( const psa_key_attributes_t *attributes) { - return( attributes->policy.alg ); + return( attributes->core.policy.alg ); } /* This function is declared in crypto_extra.h, which comes after this @@ -392,7 +399,7 @@ static inline void psa_set_key_type(psa_key_attributes_t *attributes, if( attributes->domain_parameters == NULL ) { /* Common case: quick path */ - attributes->type = type; + attributes->core.type = type; } else { @@ -407,19 +414,19 @@ static inline void psa_set_key_type(psa_key_attributes_t *attributes, static inline psa_key_type_t psa_get_key_type( const psa_key_attributes_t *attributes) { - return( attributes->type ); + return( attributes->core.type ); } static inline void psa_set_key_bits(psa_key_attributes_t *attributes, size_t bits) { - attributes->bits = bits; + attributes->core.bits = bits; } static inline size_t psa_get_key_bits( const psa_key_attributes_t *attributes) { - return( attributes->bits ); + return( attributes->core.bits ); } #endif /* PSA_CRYPTO_STRUCT_H */ diff --git a/library/psa_crypto.c b/library/psa_crypto.c index 875252803..4721f6bfe 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -1086,7 +1086,7 @@ psa_status_t psa_set_key_domain_parameters( psa_key_attributes_t *attributes, attributes->domain_parameters = copy; attributes->domain_parameters_size = data_length; - attributes->type = type; + attributes->core.type = type; return( PSA_SUCCESS ); } @@ -1153,11 +1153,11 @@ exit: static void psa_get_key_slot_attributes( psa_key_slot_t *slot, psa_key_attributes_t *attributes ) { - attributes->id = slot->persistent_storage_id; - attributes->lifetime = slot->lifetime; - attributes->policy = slot->policy; - attributes->type = slot->type; - attributes->bits = psa_get_key_slot_bits( slot ); + attributes->core.id = slot->persistent_storage_id; + attributes->core.lifetime = slot->lifetime; + attributes->core.policy = slot->policy; + attributes->core.type = slot->type; + attributes->core.bits = psa_get_key_slot_bits( slot ); } /** Retrieve all the publicly-accessible attributes of a key. @@ -1454,21 +1454,21 @@ static psa_status_t psa_start_key_creation( return( status ); slot = *p_slot; - status = psa_set_key_policy_internal( slot, &attributes->policy ); + status = psa_set_key_policy_internal( slot, &attributes->core.policy ); if( status != PSA_SUCCESS ) return( status ); - slot->lifetime = attributes->lifetime; + slot->lifetime = attributes->core.lifetime; - if( attributes->lifetime != PSA_KEY_LIFETIME_VOLATILE ) + if( attributes->core.lifetime != PSA_KEY_LIFETIME_VOLATILE ) { - status = psa_validate_persistent_key_parameters( attributes->lifetime, - attributes->id, + status = psa_validate_persistent_key_parameters( attributes->core.lifetime, + attributes->core.id, p_drv, 1 ); if( status != PSA_SUCCESS ) return( status ); - slot->persistent_storage_id = attributes->id; + slot->persistent_storage_id = attributes->core.id; } - slot->type = attributes->type; + slot->type = attributes->core.type; #if defined(MBEDTLS_PSA_CRYPTO_SE_C) /* For a key in a secure element, we need to do three things: @@ -1628,9 +1628,9 @@ static psa_status_t psa_check_key_slot_attributes( const psa_key_slot_t *slot, const psa_key_attributes_t *attributes ) { - if( attributes->type != 0 ) + if( attributes->core.type != 0 ) { - if( attributes->type != slot->type ) + if( attributes->core.type != slot->type ) return( PSA_ERROR_INVALID_ARGUMENT ); } @@ -1667,9 +1667,9 @@ static psa_status_t psa_check_key_slot_attributes( } } - if( attributes->bits != 0 ) + if( attributes->core.bits != 0 ) { - if( attributes->bits != psa_get_key_slot_bits( slot ) ) + if( attributes->core.bits != psa_get_key_slot_bits( slot ) ) return( PSA_ERROR_INVALID_ARGUMENT ); } @@ -1772,7 +1772,7 @@ psa_status_t psa_copy_key( psa_key_handle_t source_handle, if( status != PSA_SUCCESS ) goto exit; - status = psa_restrict_key_policy( &actual_attributes.policy, + status = psa_restrict_key_policy( &actual_attributes.core.policy, &source_slot->policy ); if( status != PSA_SUCCESS ) goto exit; @@ -4706,7 +4706,7 @@ psa_status_t psa_key_derivation_output_key( const psa_key_attributes_t *attribut if( status == PSA_SUCCESS ) { status = psa_generate_derived_key_internal( slot, - attributes->bits, + attributes->core.bits, operation ); } if( status == PSA_SUCCESS ) @@ -5744,7 +5744,7 @@ psa_status_t psa_generate_key( const psa_key_attributes_t *attributes, if( status == PSA_SUCCESS ) { status = psa_generate_key_internal( - slot, attributes->bits, + slot, attributes->core.bits, attributes->domain_parameters, attributes->domain_parameters_size ); } if( status == PSA_SUCCESS ) diff --git a/library/psa_crypto_core.h b/library/psa_crypto_core.h index 86584907c..d335b758e 100644 --- a/library/psa_crypto_core.h +++ b/library/psa_crypto_core.h @@ -40,9 +40,9 @@ typedef struct { psa_key_type_t type; - psa_key_policy_t policy; psa_key_lifetime_t lifetime; psa_key_file_id_t persistent_storage_id; + psa_key_policy_t policy; unsigned allocated : 1; union { diff --git a/library/psa_crypto_se.c b/library/psa_crypto_se.c index aece47d01..58b0f3807 100644 --- a/library/psa_crypto_se.c +++ b/library/psa_crypto_se.c @@ -198,7 +198,7 @@ psa_status_t psa_find_se_slot_for_key( psa_drv_se_allocate_key_t p_allocate = NULL; /* If the lifetime is wrong, it's a bug in the library. */ - if( driver->lifetime != attributes->lifetime ) + if( driver->lifetime != psa_get_key_lifetime( attributes ) ) return( PSA_ERROR_CORRUPTION_DETECTED ); /* If the driver doesn't support key creation in any way, give up now. */ diff --git a/library/psa_crypto_slot_management.c b/library/psa_crypto_slot_management.c index e63dcdae6..6add6b860 100644 --- a/library/psa_crypto_slot_management.c +++ b/library/psa_crypto_slot_management.c @@ -133,7 +133,7 @@ static psa_status_t psa_load_persistent_key_into_slot( psa_key_slot_t *p_slot ) goto exit; p_slot->lifetime = psa_get_key_lifetime( &attributes ); p_slot->type = psa_get_key_type( &attributes ); - p_slot->policy = attributes.policy; + p_slot->policy = attributes.core.policy; #if defined(MBEDTLS_PSA_CRYPTO_SE_C) if( psa_key_lifetime_is_external( p_slot->lifetime ) ) diff --git a/library/psa_crypto_storage.c b/library/psa_crypto_storage.c index b8569beb8..4113fb7e1 100644 --- a/library/psa_crypto_storage.c +++ b/library/psa_crypto_storage.c @@ -328,11 +328,11 @@ psa_status_t psa_parse_key_data_from_storage( const uint8_t *storage_data, memcpy( *key_data, storage_format->key_data, *key_data_length ); } - GET_UINT32_LE( attributes->lifetime, storage_format->lifetime, 0 ); - GET_UINT32_LE( attributes->type, storage_format->type, 0 ); - GET_UINT32_LE( attributes->policy.usage, storage_format->policy, 0 ); - GET_UINT32_LE( attributes->policy.alg, storage_format->policy, sizeof( uint32_t ) ); - GET_UINT32_LE( attributes->policy.alg2, storage_format->policy, 2 * sizeof( uint32_t ) ); + GET_UINT32_LE( attributes->core.lifetime, storage_format->lifetime, 0 ); + GET_UINT32_LE( attributes->core.type, storage_format->type, 0 ); + GET_UINT32_LE( attributes->core.policy.usage, storage_format->policy, 0 ); + GET_UINT32_LE( attributes->core.policy.alg, storage_format->policy, sizeof( uint32_t ) ); + GET_UINT32_LE( attributes->core.policy.alg2, storage_format->policy, 2 * sizeof( uint32_t ) ); return( PSA_SUCCESS ); } diff --git a/tests/suites/test_suite_psa_crypto.function b/tests/suites/test_suite_psa_crypto.function index 1d06d62e7..887ff84d1 100644 --- a/tests/suites/test_suite_psa_crypto.function +++ b/tests/suites/test_suite_psa_crypto.function @@ -1225,7 +1225,7 @@ void import( data_t *data, int type_arg, PSA_ASSERT( psa_get_key_attributes( handle, &got_attributes ) ); TEST_EQUAL( psa_get_key_type( &got_attributes ), type ); if( attr_bits != 0 ) - TEST_EQUAL( attr_bits, got_attributes.bits ); + TEST_EQUAL( attr_bits, psa_get_key_bits( &got_attributes ) ); PSA_ASSERT( psa_destroy_key( handle ) ); test_operations_on_invalid_handle( handle ); From c744d99386adda801ea879814e47a08f73a94cc0 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Tue, 30 Jul 2019 17:26:54 +0200 Subject: [PATCH 02/20] Limit keys to 65528 bits 65528 bits is more than any reasonable key until we start supporting post-quantum cryptography. This limit is chosen to allow bit-sizes to be stored in 16 bits, with 65535 left to indicate an invalid value. It's a whole number of bytes, which facilitates some calculations, in particular allowing a key of exactly PSA_CRYPTO_MAX_STORAGE_SIZE to be created but not one bit more. As a resource usage limit, this is arguably too large, but that's out of scope of the current commit. Test that key import, generation and derivation reject overly large sizes. --- include/psa/crypto_struct.h | 6 ++ library/psa_crypto.c | 16 ++- library/psa_crypto_storage.h | 11 +- tests/suites/test_suite_psa_crypto.data | 26 +++++ tests/suites/test_suite_psa_crypto.function | 102 +++++++++++++++++- .../test_suite_psa_crypto_persistent_key.data | 4 +- ...t_suite_psa_crypto_persistent_key.function | 7 +- 7 files changed, 158 insertions(+), 14 deletions(-) diff --git a/include/psa/crypto_struct.h b/include/psa/crypto_struct.h index fea59df37..b37b0b5cc 100644 --- a/include/psa/crypto_struct.h +++ b/include/psa/crypto_struct.h @@ -309,6 +309,12 @@ static inline struct psa_key_policy_s psa_key_policy_init( void ) return( v ); } +/* The maximum size of a key in bits. + * This is a whole number of bytes, to facilitate some calculations + * such as the maximum size of key data in storage. + */ +#define PSA_MAX_KEY_BITS 0xfff8 + typedef struct { psa_key_type_t type; diff --git a/library/psa_crypto.c b/library/psa_crypto.c index 4721f6bfe..4c93dd0ad 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -706,11 +706,14 @@ psa_status_t psa_import_key_into_slot( psa_key_slot_t *slot, if( key_type_is_raw_bytes( slot->type ) ) { - /* Ensure that a bytes-to-bit conversion won't overflow. */ + size_t bit_size = PSA_BYTES_TO_BITS( data_length ); + /* Ensure that the bytes-to-bit conversion doesn't overflow. */ if( data_length > SIZE_MAX / 8 ) return( PSA_ERROR_NOT_SUPPORTED ); - status = prepare_raw_data_slot( slot->type, - PSA_BYTES_TO_BITS( data_length ), + /* Ensure that the key is not overly large. */ + if( bit_size > PSA_MAX_KEY_BITS ) + return( PSA_ERROR_NOT_SUPPORTED ); + status = prepare_raw_data_slot( slot->type, bit_size, &slot->data.raw ); if( status != PSA_SUCCESS ) return( status ); @@ -1470,6 +1473,13 @@ static psa_status_t psa_start_key_creation( } slot->type = attributes->core.type; + /* Refuse to create overly large keys. + * Note that this doesn't trigger on import if the attributes don't + * explicitly specify a size (so psa_get_key_bits returns 0), so + * psa_import_key() needs its own checks. */ + if( psa_get_key_bits( attributes ) > PSA_MAX_KEY_BITS ) + return( PSA_ERROR_NOT_SUPPORTED ); + #if defined(MBEDTLS_PSA_CRYPTO_SE_C) /* For a key in a secure element, we need to do three things: * create the key file in internal storage, create the diff --git a/library/psa_crypto_storage.h b/library/psa_crypto_storage.h index 8fe20ac32..938cc4f89 100644 --- a/library/psa_crypto_storage.h +++ b/library/psa_crypto_storage.h @@ -35,9 +35,14 @@ extern "C" { #include #include -/* Limit the maximum key size to 30kB (just in case someone tries to - * inadvertently store an obscene amount of data) */ -#define PSA_CRYPTO_MAX_STORAGE_SIZE ( 30 * 1024 ) +/* Limit the maximum key size in storage. This should have no effect + * since the key size is limited in memory. */ +#define PSA_CRYPTO_MAX_STORAGE_SIZE ( PSA_BITS_TO_BYTES( PSA_MAX_KEY_BITS ) ) +/* Sanity check: a file size must fit in 32 bits. Allow a generous + * 64kB of metadata. */ +#if PSA_CRYPTO_MAX_STORAGE_SIZE > 0xffff0000 +#error PSA_CRYPTO_MAX_STORAGE_SIZE > 0xffff0000 +#endif /** The maximum permitted persistent slot number. * diff --git a/tests/suites/test_suite_psa_crypto.data b/tests/suites/test_suite_psa_crypto.data index 53f842201..a0e7f7a90 100644 --- a/tests/suites/test_suite_psa_crypto.data +++ b/tests/suites/test_suite_psa_crypto.data @@ -314,6 +314,14 @@ PSA import AES: bits=128 wrong depends_on:MBEDTLS_AES_C import:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_KEY_TYPE_AES:128:PSA_ERROR_INVALID_ARGUMENT +PSA import large key: raw, 65528 bits (ok) +depends_on:HAVE_RAM_AVAILABLE_128k +import_large_key:PSA_KEY_TYPE_RAW_DATA:8191:PSA_SUCCESS + +PSA import large key: raw, 65536 bits (not supported) +depends_on:HAVE_RAM_AVAILABLE_128k +import_large_key:PSA_KEY_TYPE_RAW_DATA:8192:PSA_ERROR_NOT_SUPPORTED + PSA import RSA key pair: maximum size exceeded depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C import_rsa_made_up:PSA_VENDOR_RSA_MAX_KEY_BITS+8:1:PSA_ERROR_NOT_SUPPORTED @@ -2075,6 +2083,17 @@ PSA key derivation: TLS 1.2 PRF SHA-256, derive key export, 1+41 depends_on:MBEDTLS_MD_C:MBEDTLS_SHA256_C:!PSA_PRE_1_0_KEY_DERIVATION derive_key_export:PSA_ALG_TLS12_PRF(PSA_ALG_SHA_256):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":1:41 +# This test assumes that PSA_MAX_KEY_BITS (currently 65536-8 bits = 8191 bytes +# and not expected to be raised any time soon) is less than the maximum +# output from HKDF-SHA512 (255*64 = 16320 bytes). +PSA key derivation: largest possible key +depends_on:MBEDTLS_MD_C:MBEDTLS_SHA512_C:!PSA_PRE_1_0_KEY_DERIVATION +derive_large_key:PSA_ALG_HKDF(PSA_ALG_SHA_512):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":PSA_MAX_KEY_BITS:PSA_SUCCESS + +PSA key derivation: key too large +depends_on:MBEDTLS_MD_C:MBEDTLS_SHA512_C:!PSA_PRE_1_0_KEY_DERIVATION +derive_large_key:PSA_ALG_HKDF(PSA_ALG_SHA_512):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":PSA_MAX_KEY_BITS + 1:PSA_ERROR_NOT_SUPPORTED + PSA key agreement setup: ECDH + HKDF-SHA-256: good depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECDH_C:MBEDTLS_MD_C:MBEDTLS_SHA256_C key_agreement_setup:PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_HKDF(PSA_ALG_SHA_256)):PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_CURVE_SECP256R1):"c88f01f510d9ac3f70a292daa2316de544e9aab8afe84049c62a9c57862d1433":"04d12dfb5289c8d4f81208b70270398c342296970a0bccb74c736fc7554494bf6356fbf3ca366cc23e8157854c13c58d6aac23f046ada30f8353e74f33039872ab":PSA_SUCCESS @@ -2188,6 +2207,13 @@ generate_key:PSA_KEY_TYPE_RAW_DATA:7:PSA_KEY_USAGE_EXPORT:0:PSA_ERROR_INVALID_AR PSA generate key: raw data, 8 bits generate_key:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0:PSA_SUCCESS +PSA generate key: raw data, 65528 bits (ok) +depends_on:HAVE_RAM_AVAILABLE_128k +generate_key:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0:PSA_SUCCESS + +PSA generate key: raw data, 65536 bits (not supported) +generate_key:PSA_KEY_TYPE_RAW_DATA:65536:PSA_KEY_USAGE_EXPORT:0:PSA_ERROR_NOT_SUPPORTED + PSA generate key: AES, 128 bits, CTR depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR generate_key:PSA_KEY_TYPE_AES:128:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_CTR:PSA_SUCCESS diff --git a/tests/suites/test_suite_psa_crypto.function b/tests/suites/test_suite_psa_crypto.function index 887ff84d1..8ed7a7d5c 100644 --- a/tests/suites/test_suite_psa_crypto.function +++ b/tests/suites/test_suite_psa_crypto.function @@ -7,6 +7,13 @@ #include "psa_crypto_helpers.h" +/* Tests that require more than 128kB of RAM plus change have this symbol + * as a dependency. Currently we always define this symbol, so the tests + * are always executed. In the future we should make this conditional + * so that tests that require a lot of memory are skipped on constrained + * platforms. */ +#define HAVE_RAM_AVAILABLE_128k + /** An invalid export length that will never be set by psa_export_key(). */ static const size_t INVALID_EXPORT_LENGTH = ~0U; @@ -556,7 +563,8 @@ static int setup_key_derivation_wrap( psa_key_derivation_operation_t* operation, TEST_ASSERT( ! "Key derivation algorithm not supported" ); } - PSA_ASSERT( psa_key_derivation_set_capacity( operation, capacity ) ); + if( capacity != SIZE_MAX ) + PSA_ASSERT( psa_key_derivation_set_capacity( operation, capacity ) ); return( 1 ); @@ -1237,6 +1245,54 @@ exit: } /* END_CASE */ +/* BEGIN_CASE */ +void import_large_key( int type_arg, int byte_size_arg, + int expected_status_arg ) +{ + psa_key_type_t type = type_arg; + size_t byte_size = byte_size_arg; + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_status_t expected_status = expected_status_arg; + psa_key_handle_t handle = 0; + psa_status_t status; + uint8_t *buffer = NULL; + size_t buffer_size = byte_size + 1; + size_t n; + + /* It would be better to skip the test than fail it if the allocation + * fails, but the test framework doesn't support this yet. */ + ASSERT_ALLOC( buffer, buffer_size ); + memset( buffer, 'K', byte_size ); + + PSA_ASSERT( psa_crypto_init( ) ); + + /* Try importing the key */ + psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_EXPORT ); + psa_set_key_type( &attributes, type ); + status = psa_import_key( &attributes, buffer, byte_size, &handle ); + TEST_EQUAL( status, expected_status ); + + if( status == PSA_SUCCESS ) + { + PSA_ASSERT( psa_get_key_attributes( handle, &attributes ) ); + TEST_EQUAL( psa_get_key_type( &attributes ), type ); + TEST_EQUAL( psa_get_key_bits( &attributes ), + PSA_BYTES_TO_BITS( byte_size ) ); + memset( buffer, 0, byte_size + 1 ); + PSA_ASSERT( psa_export_key( handle, buffer, byte_size, &n ) ); + for( n = 0; n < byte_size; n++ ) + TEST_EQUAL( buffer[n], 'K' ); + for( n = byte_size; n < buffer_size; n++ ) + TEST_EQUAL( buffer[n], 0 ); + } + +exit: + psa_destroy_key( handle ); + PSA_DONE( ); + mbedtls_free( buffer ); +} +/* END_CASE */ + /* BEGIN_CASE */ void import_rsa_made_up( int bits_arg, int keypair, int expected_status_arg ) { @@ -4563,6 +4619,50 @@ exit: } /* END_CASE */ +/* BEGIN_CASE */ +void derive_large_key( int alg_arg, + data_t *key_data, data_t *input1, data_t *input2, + int bits_arg, + int expected_status_arg ) +{ + psa_key_handle_t base_handle = 0; + psa_key_handle_t derived_handle = 0; + psa_algorithm_t alg = alg_arg; + size_t bits = bits_arg; + psa_status_t expected_status = expected_status_arg; + psa_key_derivation_operation_t operation = PSA_KEY_DERIVATION_OPERATION_INIT; + psa_key_attributes_t base_attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_key_attributes_t derived_attributes = PSA_KEY_ATTRIBUTES_INIT; + + PSA_ASSERT( psa_crypto_init( ) ); + + psa_set_key_usage_flags( &base_attributes, PSA_KEY_USAGE_DERIVE ); + psa_set_key_algorithm( &base_attributes, alg ); + psa_set_key_type( &base_attributes, PSA_KEY_TYPE_DERIVE ); + PSA_ASSERT( psa_import_key( &base_attributes, key_data->x, key_data->len, + &base_handle ) ); + + if( !setup_key_derivation_wrap( &operation, base_handle, alg, + input1->x, input1->len, + input2->x, input2->len, SIZE_MAX ) ) + goto exit; + + psa_set_key_usage_flags( &derived_attributes, PSA_KEY_USAGE_EXPORT ); + psa_set_key_algorithm( &derived_attributes, 0 ); + psa_set_key_type( &derived_attributes, PSA_KEY_TYPE_RAW_DATA ); + psa_set_key_bits( &derived_attributes, bits ); + TEST_EQUAL( psa_key_derivation_output_key( &derived_attributes, &operation, + &derived_handle ), + expected_status ); + +exit: + psa_key_derivation_abort( &operation ); + psa_destroy_key( base_handle ); + psa_destroy_key( derived_handle ); + PSA_DONE( ); +} +/* END_CASE */ + /* BEGIN_CASE */ void key_agreement_setup( int alg_arg, int our_key_type_arg, data_t *our_key_data, diff --git a/tests/suites/test_suite_psa_crypto_persistent_key.data b/tests/suites/test_suite_psa_crypto_persistent_key.data index 925c0f54a..3f40d35c7 100644 --- a/tests/suites/test_suite_psa_crypto_persistent_key.data +++ b/tests/suites/test_suite_psa_crypto_persistent_key.data @@ -19,10 +19,10 @@ parse_storage_data_check:"505341004b4559":"":PSA_KEY_LIFETIME_PERSISTENT:PSA_KEY # Not specific to files, but only run this test in an environment where the maximum size could be reached. Save maximum size persistent raw key depends_on:MBEDTLS_PSA_ITS_FILE_C -save_large_persistent_key:0:PSA_SUCCESS +save_large_persistent_key:PSA_CRYPTO_MAX_STORAGE_SIZE:PSA_SUCCESS Save larger than maximum size persistent raw key, should fail -save_large_persistent_key:1:PSA_ERROR_INSUFFICIENT_STORAGE +save_large_persistent_key:PSA_CRYPTO_MAX_STORAGE_SIZE + 1:PSA_ERROR_NOT_SUPPORTED Persistent key destroy depends_on:MBEDTLS_PK_C:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C diff --git a/tests/suites/test_suite_psa_crypto_persistent_key.function b/tests/suites/test_suite_psa_crypto_persistent_key.function index b76c7330a..61f7f886a 100644 --- a/tests/suites/test_suite_psa_crypto_persistent_key.function +++ b/tests/suites/test_suite_psa_crypto_persistent_key.function @@ -96,17 +96,14 @@ exit: /* END_CASE */ /* BEGIN_CASE */ -void save_large_persistent_key( int data_too_large, int expected_status ) +void save_large_persistent_key( int data_length_arg, int expected_status ) { psa_key_id_t key_id = 42; psa_key_handle_t handle = 0; uint8_t *data = NULL; - size_t data_length = PSA_CRYPTO_MAX_STORAGE_SIZE; + size_t data_length = data_length_arg; psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; - if( data_too_large ) - data_length += 1; - ASSERT_ALLOC( data, data_length ); PSA_ASSERT( psa_crypto_init() ); From 68cc433b5b1e03a066af0088ffdd728909ddd45c Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Tue, 30 Jul 2019 17:42:47 +0200 Subject: [PATCH 03/20] Store key sizes in 16 bits in attributes This is larger than the maximum key size introduced in the previous commit, by design. Make some room for flags (not used yet). --- include/psa/crypto_struct.h | 23 +++++++++++++++++------ library/psa_crypto.c | 2 +- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/include/psa/crypto_struct.h b/include/psa/crypto_struct.h index b37b0b5cc..453c83565 100644 --- a/include/psa/crypto_struct.h +++ b/include/psa/crypto_struct.h @@ -309,10 +309,17 @@ static inline struct psa_key_policy_s psa_key_policy_init( void ) return( v ); } +/* The type used internally for key sizes. + * Public interfaces use size_t, but internally we use a smaller type. */ +typedef uint16_t psa_key_bits_t; +/* The maximum value of the type used to represent bit-sizes. + * This is used to mark an invalid key size. */ +#define PSA_KEY_BITS_TOO_LARGE ( (psa_key_bits_t) ( -1 ) ) /* The maximum size of a key in bits. - * This is a whole number of bytes, to facilitate some calculations - * such as the maximum size of key data in storage. - */ + * Currently defined as the maximum that can be represented, rounded down + * to a whole number of bytes. + * This is an uncast value so that it can be used in preprocessor + * conditionals. */ #define PSA_MAX_KEY_BITS 0xfff8 typedef struct @@ -321,10 +328,11 @@ typedef struct psa_key_lifetime_t lifetime; psa_key_id_t id; psa_key_policy_t policy; - size_t bits; + psa_key_bits_t bits; + uint16_t flags; } psa_core_key_attributes_t; -#define PSA_CORE_KEY_ATTRIBUTES_INIT {0, 0, 0, {0, 0, 0}, 0} +#define PSA_CORE_KEY_ATTRIBUTES_INIT {0, 0, 0, {0, 0, 0}, 0, 0} struct psa_key_attributes_s { @@ -426,7 +434,10 @@ static inline psa_key_type_t psa_get_key_type( static inline void psa_set_key_bits(psa_key_attributes_t *attributes, size_t bits) { - attributes->core.bits = bits; + if( bits > PSA_MAX_KEY_BITS ) + attributes->core.bits = PSA_KEY_BITS_TOO_LARGE; + else + attributes->core.bits = (psa_key_bits_t) bits; } static inline size_t psa_get_key_bits( diff --git a/library/psa_crypto.c b/library/psa_crypto.c index 4c93dd0ad..1b2fa209e 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -710,7 +710,7 @@ psa_status_t psa_import_key_into_slot( psa_key_slot_t *slot, /* Ensure that the bytes-to-bit conversion doesn't overflow. */ if( data_length > SIZE_MAX / 8 ) return( PSA_ERROR_NOT_SUPPORTED ); - /* Ensure that the key is not overly large. */ + /* Ensure that the bit size fits in its representation type. */ if( bit_size > PSA_MAX_KEY_BITS ) return( PSA_ERROR_NOT_SUPPORTED ); status = prepare_raw_data_slot( slot->type, bit_size, From 8e3387029d292f18b473d5d6cc242a1f99b0f152 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Tue, 30 Jul 2019 20:06:31 +0200 Subject: [PATCH 04/20] Use psa_core_key_attributes_t in key slots in memory Change the type of key slots in memory to use psa_core_key_attributes_t rather than separate fields. The goal is to simplify some parts of the code. This commit only does the mechanical replacement, not the substitution. The bit-field `allocate` is now a flag `PSA_KEY_SLOT_FLAG_ALLOCATED` in the `flags` field. Write accessor functions for flags. Key slots now contain a bit size field which is currently unused. Subsequent commits will make use of it. --- library/psa_crypto.c | 163 ++++++++++++++------------- library/psa_crypto_core.h | 60 +++++++++- library/psa_crypto_slot_management.c | 37 +++--- 3 files changed, 156 insertions(+), 104 deletions(-) diff --git a/library/psa_crypto.c b/library/psa_crypto.c index 1b2fa209e..1646ae584 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -366,7 +366,7 @@ static psa_status_t mbedtls_to_psa_error( int ret ) #if defined(MBEDTLS_PSA_CRYPTO_SE_C) static inline int psa_key_slot_is_external( const psa_key_slot_t *slot ) { - return( psa_key_lifetime_is_external( slot->lifetime ) ); + return( psa_key_lifetime_is_external( slot->attr.lifetime ) ); } #endif /* MBEDTLS_PSA_CRYPTO_SE_C */ @@ -695,7 +695,7 @@ exit: } #endif /* defined(MBEDTLS_ECP_C) */ -/** Import key data into a slot. `slot->type` must have been set +/** Import key data into a slot. `slot->attr.type` must have been set * previously. This function assumes that the slot does not contain * any key material yet. On failure, the slot content is unchanged. */ psa_status_t psa_import_key_into_slot( psa_key_slot_t *slot, @@ -704,7 +704,7 @@ psa_status_t psa_import_key_into_slot( psa_key_slot_t *slot, { psa_status_t status = PSA_SUCCESS; - if( key_type_is_raw_bytes( slot->type ) ) + if( key_type_is_raw_bytes( slot->attr.type ) ) { size_t bit_size = PSA_BYTES_TO_BITS( data_length ); /* Ensure that the bytes-to-bit conversion doesn't overflow. */ @@ -713,7 +713,7 @@ psa_status_t psa_import_key_into_slot( psa_key_slot_t *slot, /* Ensure that the bit size fits in its representation type. */ if( bit_size > PSA_MAX_KEY_BITS ) return( PSA_ERROR_NOT_SUPPORTED ); - status = prepare_raw_data_slot( slot->type, bit_size, + status = prepare_raw_data_slot( slot->attr.type, bit_size, &slot->data.raw ); if( status != PSA_SUCCESS ) return( status ); @@ -722,25 +722,25 @@ psa_status_t psa_import_key_into_slot( psa_key_slot_t *slot, } else #if defined(MBEDTLS_ECP_C) - if( PSA_KEY_TYPE_IS_ECC_KEY_PAIR( slot->type ) ) + if( PSA_KEY_TYPE_IS_ECC_KEY_PAIR( slot->attr.type ) ) { - status = psa_import_ec_private_key( PSA_KEY_TYPE_GET_CURVE( slot->type ), + status = psa_import_ec_private_key( PSA_KEY_TYPE_GET_CURVE( slot->attr.type ), data, data_length, &slot->data.ecp ); } - else if( PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY( slot->type ) ) + else if( PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY( slot->attr.type ) ) { status = psa_import_ec_public_key( - PSA_KEY_TYPE_GET_CURVE( slot->type ), + PSA_KEY_TYPE_GET_CURVE( slot->attr.type ), data, data_length, &slot->data.ecp ); } else #endif /* MBEDTLS_ECP_C */ #if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_PK_PARSE_C) - if( PSA_KEY_TYPE_IS_RSA( slot->type ) ) + if( PSA_KEY_TYPE_IS_RSA( slot->attr.type ) ) { - status = psa_import_rsa_key( slot->type, + status = psa_import_rsa_key( slot->attr.type, data, data_length, &slot->data.rsa ); } @@ -854,20 +854,20 @@ static psa_status_t psa_get_key_from_slot( psa_key_handle_t handle, status = psa_get_key_slot( handle, &slot ); if( status != PSA_SUCCESS ) return( status ); - if( slot->type == PSA_KEY_TYPE_NONE ) + if( slot->attr.type == PSA_KEY_TYPE_NONE ) return( PSA_ERROR_DOES_NOT_EXIST ); /* Enforce that usage policy for the key slot contains all the flags * required by the usage parameter. There is one exception: public * keys can always be exported, so we treat public key objects as * if they had the export flag. */ - if( PSA_KEY_TYPE_IS_PUBLIC_KEY( slot->type ) ) + if( PSA_KEY_TYPE_IS_PUBLIC_KEY( slot->attr.type ) ) usage &= ~PSA_KEY_USAGE_EXPORT; - if( ( slot->policy.usage & usage ) != usage ) + if( ( slot->attr.policy.usage & usage ) != usage ) return( PSA_ERROR_NOT_PERMITTED ); /* Enforce that the usage policy permits the requested algortihm. */ - if( alg != 0 && ! psa_key_policy_permits( &slot->policy, alg ) ) + if( alg != 0 && ! psa_key_policy_permits( &slot->attr.policy, alg ) ) return( PSA_ERROR_NOT_PERMITTED ); *p_slot = slot; @@ -914,17 +914,17 @@ static psa_status_t psa_remove_key_data_from_memory( psa_key_slot_t *slot ) } else #endif /* MBEDTLS_PSA_CRYPTO_SE_C */ - if( slot->type == PSA_KEY_TYPE_NONE ) + if( slot->attr.type == PSA_KEY_TYPE_NONE ) { /* No key material to clean. */ } - else if( key_type_is_raw_bytes( slot->type ) ) + else if( key_type_is_raw_bytes( slot->attr.type ) ) { mbedtls_free( slot->data.raw.data ); } else #if defined(MBEDTLS_RSA_C) - if( PSA_KEY_TYPE_IS_RSA( slot->type ) ) + if( PSA_KEY_TYPE_IS_RSA( slot->attr.type ) ) { mbedtls_rsa_free( slot->data.rsa ); mbedtls_free( slot->data.rsa ); @@ -932,7 +932,7 @@ static psa_status_t psa_remove_key_data_from_memory( psa_key_slot_t *slot ) else #endif /* defined(MBEDTLS_RSA_C) */ #if defined(MBEDTLS_ECP_C) - if( PSA_KEY_TYPE_IS_ECC( slot->type ) ) + if( PSA_KEY_TYPE_IS_ECC( slot->attr.type ) ) { mbedtls_ecp_keypair_free( slot->data.ecp ); mbedtls_free( slot->data.ecp ); @@ -981,7 +981,7 @@ psa_status_t psa_destroy_key( psa_key_handle_t handle ) return( status ); #if defined(MBEDTLS_PSA_CRYPTO_SE_C) - driver = psa_get_se_driver_entry( slot->lifetime ); + driver = psa_get_se_driver_entry( slot->attr.lifetime ); if( driver != NULL ) { /* For a key in a secure element, we need to do three things: @@ -990,9 +990,9 @@ psa_status_t psa_destroy_key( psa_key_handle_t handle ) * persistent data. Start a transaction that will encompass these * three actions. */ psa_crypto_prepare_transaction( PSA_CRYPTO_TRANSACTION_DESTROY_KEY ); - psa_crypto_transaction.key.lifetime = slot->lifetime; + psa_crypto_transaction.key.lifetime = slot->attr.lifetime; psa_crypto_transaction.key.slot = slot->data.se.slot_number; - psa_crypto_transaction.key.id = slot->persistent_storage_id; + psa_crypto_transaction.key.id = slot->attr.id; status = psa_crypto_save_transaction( ); if( status != PSA_SUCCESS ) { @@ -1006,10 +1006,10 @@ psa_status_t psa_destroy_key( psa_key_handle_t handle ) #endif /* MBEDTLS_PSA_CRYPTO_SE_C */ #if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) - if( slot->lifetime == PSA_KEY_LIFETIME_PERSISTENT ) + if( slot->attr.lifetime == PSA_KEY_LIFETIME_PERSISTENT ) { storage_status = - psa_destroy_persistent_key( slot->persistent_storage_id ); + psa_destroy_persistent_key( slot->attr.id ); } #endif /* defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) */ @@ -1039,18 +1039,18 @@ psa_status_t psa_destroy_key( psa_key_handle_t handle ) static size_t psa_get_key_slot_bits( const psa_key_slot_t *slot ) { #if defined(MBEDTLS_PSA_CRYPTO_SE_C) - if( psa_get_se_driver( slot->lifetime, NULL, NULL ) ) + if( psa_get_se_driver( slot->attr.lifetime, NULL, NULL ) ) return( slot->data.se.bits ); #endif /* defined(MBEDTLS_PSA_CRYPTO_SE_C) */ - if( key_type_is_raw_bytes( slot->type ) ) + if( key_type_is_raw_bytes( slot->attr.type ) ) return( slot->data.raw.bytes * 8 ); #if defined(MBEDTLS_RSA_C) - if( PSA_KEY_TYPE_IS_RSA( slot->type ) ) + if( PSA_KEY_TYPE_IS_RSA( slot->attr.type ) ) return( PSA_BYTES_TO_BITS( mbedtls_rsa_get_len( slot->data.rsa ) ) ); #endif /* defined(MBEDTLS_RSA_C) */ #if defined(MBEDTLS_ECP_C) - if( PSA_KEY_TYPE_IS_ECC( slot->type ) ) + if( PSA_KEY_TYPE_IS_ECC( slot->attr.type ) ) return( slot->data.ecp->grp.pbits ); #endif /* defined(MBEDTLS_ECP_C) */ /* Shouldn't happen except on an empty slot. */ @@ -1156,10 +1156,10 @@ exit: static void psa_get_key_slot_attributes( psa_key_slot_t *slot, psa_key_attributes_t *attributes ) { - attributes->core.id = slot->persistent_storage_id; - attributes->core.lifetime = slot->lifetime; - attributes->core.policy = slot->policy; - attributes->core.type = slot->type; + attributes->core.id = slot->attr.id; + attributes->core.lifetime = slot->attr.lifetime; + attributes->core.policy = slot->attr.policy; + attributes->core.type = slot->attr.type; attributes->core.bits = psa_get_key_slot_bits( slot ); } @@ -1179,7 +1179,7 @@ psa_status_t psa_get_key_attributes( psa_key_handle_t handle, psa_get_key_slot_attributes( slot, attributes ); - switch( slot->type ) + switch( slot->attr.type ) { #if defined(MBEDTLS_RSA_C) case PSA_KEY_TYPE_RSA_KEY_PAIR: @@ -1187,7 +1187,7 @@ psa_status_t psa_get_key_attributes( psa_key_handle_t handle, #if defined(MBEDTLS_PSA_CRYPTO_SE_C) /* TOnogrepDO: reporting the public exponent for opaque keys * is not yet implemented. */ - if( psa_get_se_driver( slot->lifetime, NULL, NULL ) ) + if( psa_get_se_driver( slot->attr.lifetime, NULL, NULL ) ) break; #endif /* MBEDTLS_PSA_CRYPTO_SE_C */ status = psa_get_rsa_public_exponent( slot->data.rsa, attributes ); @@ -1232,11 +1232,11 @@ static psa_status_t psa_internal_export_key( const psa_key_slot_t *slot, *data_length = 0; - if( export_public_key && ! PSA_KEY_TYPE_IS_ASYMMETRIC( slot->type ) ) + if( export_public_key && ! PSA_KEY_TYPE_IS_ASYMMETRIC( slot->attr.type ) ) return( PSA_ERROR_INVALID_ARGUMENT ); #if defined(MBEDTLS_PSA_CRYPTO_SE_C) - if( psa_get_se_driver( slot->lifetime, &drv, &drv_context ) ) + if( psa_get_se_driver( slot->attr.lifetime, &drv, &drv_context ) ) { psa_drv_se_export_key_t method; if( drv->key_management == NULL ) @@ -1252,7 +1252,7 @@ static psa_status_t psa_internal_export_key( const psa_key_slot_t *slot, } #endif /* MBEDTLS_PSA_CRYPTO_SE_C */ - if( key_type_is_raw_bytes( slot->type ) ) + if( key_type_is_raw_bytes( slot->attr.type ) ) { if( slot->data.raw.bytes > data_size ) return( PSA_ERROR_BUFFER_TOO_SMALL ); @@ -1266,7 +1266,7 @@ static psa_status_t psa_internal_export_key( const psa_key_slot_t *slot, return( PSA_SUCCESS ); } #if defined(MBEDTLS_ECP_C) - if( PSA_KEY_TYPE_IS_ECC_KEY_PAIR( slot->type ) && !export_public_key ) + if( PSA_KEY_TYPE_IS_ECC_KEY_PAIR( slot->attr.type ) && !export_public_key ) { psa_status_t status; @@ -1285,12 +1285,12 @@ static psa_status_t psa_internal_export_key( const psa_key_slot_t *slot, else { #if defined(MBEDTLS_PK_WRITE_C) - if( PSA_KEY_TYPE_IS_RSA( slot->type ) || - PSA_KEY_TYPE_IS_ECC( slot->type ) ) + if( PSA_KEY_TYPE_IS_RSA( slot->attr.type ) || + PSA_KEY_TYPE_IS_ECC( slot->attr.type ) ) { mbedtls_pk_context pk; int ret; - if( PSA_KEY_TYPE_IS_RSA( slot->type ) ) + if( PSA_KEY_TYPE_IS_RSA( slot->attr.type ) ) { #if defined(MBEDTLS_RSA_C) mbedtls_pk_init( &pk ); @@ -1310,7 +1310,7 @@ static psa_status_t psa_internal_export_key( const psa_key_slot_t *slot, return( PSA_ERROR_NOT_SUPPORTED ); #endif } - if( export_public_key || PSA_KEY_TYPE_IS_PUBLIC_KEY( slot->type ) ) + if( export_public_key || PSA_KEY_TYPE_IS_PUBLIC_KEY( slot->attr.type ) ) { ret = pk_write_pubkey_simple( &pk, data, data_size ); } @@ -1412,7 +1412,7 @@ static psa_status_t psa_set_key_policy_internal( PSA_KEY_USAGE_DERIVE ) ) != 0 ) return( PSA_ERROR_INVALID_ARGUMENT ); - slot->policy = *policy; + slot->attr.policy = *policy; return( PSA_SUCCESS ); } @@ -1460,7 +1460,7 @@ static psa_status_t psa_start_key_creation( status = psa_set_key_policy_internal( slot, &attributes->core.policy ); if( status != PSA_SUCCESS ) return( status ); - slot->lifetime = attributes->core.lifetime; + slot->attr.lifetime = attributes->core.lifetime; if( attributes->core.lifetime != PSA_KEY_LIFETIME_VOLATILE ) { @@ -1469,9 +1469,9 @@ static psa_status_t psa_start_key_creation( p_drv, 1 ); if( status != PSA_SUCCESS ) return( status ); - slot->persistent_storage_id = attributes->core.id; + slot->attr.id = attributes->core.id; } - slot->type = attributes->core.type; + slot->attr.type = attributes->core.type; /* Refuse to create overly large keys. * Note that this doesn't trigger on import if the attributes don't @@ -1501,9 +1501,9 @@ static psa_status_t psa_start_key_creation( if( status != PSA_SUCCESS ) return( status ); psa_crypto_prepare_transaction( PSA_CRYPTO_TRANSACTION_CREATE_KEY ); - psa_crypto_transaction.key.lifetime = slot->lifetime; + psa_crypto_transaction.key.lifetime = slot->attr.lifetime; psa_crypto_transaction.key.slot = slot->data.se.slot_number; - psa_crypto_transaction.key.id = slot->persistent_storage_id; + psa_crypto_transaction.key.id = slot->attr.id; status = psa_crypto_save_transaction( ); if( status != PSA_SUCCESS ) { @@ -1546,7 +1546,7 @@ static psa_status_t psa_finish_key_creation( (void) driver; #if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) - if( slot->lifetime != PSA_KEY_LIFETIME_VOLATILE ) + if( slot->attr.lifetime != PSA_KEY_LIFETIME_VOLATILE ) { psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; psa_get_key_slot_attributes( slot, &attributes ); @@ -1562,7 +1562,7 @@ static psa_status_t psa_finish_key_creation( #endif /* MBEDTLS_PSA_CRYPTO_SE_C */ { size_t buffer_size = - PSA_KEY_EXPORT_MAX_SIZE( slot->type, + PSA_KEY_EXPORT_MAX_SIZE( slot->attr.type, psa_get_key_bits( &attributes ) ); uint8_t *buffer = mbedtls_calloc( 1, buffer_size ); size_t length = 0; @@ -1587,7 +1587,7 @@ static psa_status_t psa_finish_key_creation( status = psa_save_se_persistent_data( driver ); if( status != PSA_SUCCESS ) { - psa_destroy_persistent_key( slot->persistent_storage_id ); + psa_destroy_persistent_key( slot->attr.id ); return( status ); } status = psa_crypto_stop_transaction( ); @@ -1640,14 +1640,14 @@ static psa_status_t psa_check_key_slot_attributes( { if( attributes->core.type != 0 ) { - if( attributes->core.type != slot->type ) + if( attributes->core.type != slot->attr.type ) return( PSA_ERROR_INVALID_ARGUMENT ); } if( attributes->domain_parameters_size != 0 ) { #if defined(MBEDTLS_RSA_C) - if( PSA_KEY_TYPE_IS_RSA( slot->type ) ) + if( PSA_KEY_TYPE_IS_RSA( slot->attr.type ) ) { mbedtls_mpi actual, required; int ret; @@ -1712,7 +1712,8 @@ psa_status_t psa_import_key( const psa_key_attributes_t *attributes, status = drv->key_management->p_import( psa_get_se_driver_context( driver ), slot->data.se.slot_number, - slot->lifetime, slot->type, slot->policy.alg, slot->policy.usage, + slot->attr.lifetime, slot->attr.type, + slot->attr.policy.alg, slot->attr.policy.usage, data, data_length, &slot->data.se.bits ); } @@ -1745,7 +1746,7 @@ static psa_status_t psa_copy_key_material( const psa_key_slot_t *source, size_t buffer_size = 0; size_t length; - buffer_size = PSA_KEY_EXPORT_MAX_SIZE( source->type, + buffer_size = PSA_KEY_EXPORT_MAX_SIZE( source->attr.type, psa_get_key_slot_bits( source ) ); buffer = mbedtls_calloc( 1, buffer_size ); if( buffer == NULL && buffer_size != 0 ) @@ -1753,7 +1754,7 @@ static psa_status_t psa_copy_key_material( const psa_key_slot_t *source, status = psa_internal_export_key( source, buffer, buffer_size, &length, 0 ); if( status != PSA_SUCCESS ) goto exit; - target->type = source->type; + target->attr.type = source->attr.type; status = psa_import_key_into_slot( target, buffer, length ); exit: @@ -1783,7 +1784,7 @@ psa_status_t psa_copy_key( psa_key_handle_t source_handle, goto exit; status = psa_restrict_key_policy( &actual_attributes.core.policy, - &source_slot->policy ); + &source_slot->attr.policy ); if( status != PSA_SUCCESS ) goto exit; @@ -2573,7 +2574,7 @@ static psa_status_t psa_mac_setup( psa_mac_operation_t *operation, { const mbedtls_cipher_info_t *cipher_info = mbedtls_cipher_info_from_psa( full_length_alg, - slot->type, key_bits, NULL ); + slot->attr.type, key_bits, NULL ); int ret; if( cipher_info == NULL ) { @@ -2605,7 +2606,7 @@ static psa_status_t psa_mac_setup( psa_mac_operation_t *operation, goto exit; } - if( slot->type != PSA_KEY_TYPE_HMAC ) + if( slot->attr.type != PSA_KEY_TYPE_HMAC ) { status = PSA_ERROR_INVALID_ARGUMENT; goto exit; @@ -3145,14 +3146,14 @@ psa_status_t psa_asymmetric_sign( psa_key_handle_t handle, status = psa_get_transparent_key( handle, &slot, PSA_KEY_USAGE_SIGN, alg ); if( status != PSA_SUCCESS ) goto exit; - if( ! PSA_KEY_TYPE_IS_KEY_PAIR( slot->type ) ) + if( ! PSA_KEY_TYPE_IS_KEY_PAIR( slot->attr.type ) ) { status = PSA_ERROR_INVALID_ARGUMENT; goto exit; } #if defined(MBEDTLS_RSA_C) - if( slot->type == PSA_KEY_TYPE_RSA_KEY_PAIR ) + if( slot->attr.type == PSA_KEY_TYPE_RSA_KEY_PAIR ) { status = psa_rsa_sign( slot->data.rsa, alg, @@ -3163,7 +3164,7 @@ psa_status_t psa_asymmetric_sign( psa_key_handle_t handle, else #endif /* defined(MBEDTLS_RSA_C) */ #if defined(MBEDTLS_ECP_C) - if( PSA_KEY_TYPE_IS_ECC( slot->type ) ) + if( PSA_KEY_TYPE_IS_ECC( slot->attr.type ) ) { #if defined(MBEDTLS_ECDSA_C) if( @@ -3220,7 +3221,7 @@ psa_status_t psa_asymmetric_verify( psa_key_handle_t handle, return( status ); #if defined(MBEDTLS_RSA_C) - if( PSA_KEY_TYPE_IS_RSA( slot->type ) ) + if( PSA_KEY_TYPE_IS_RSA( slot->attr.type ) ) { return( psa_rsa_verify( slot->data.rsa, alg, @@ -3230,7 +3231,7 @@ psa_status_t psa_asymmetric_verify( psa_key_handle_t handle, else #endif /* defined(MBEDTLS_RSA_C) */ #if defined(MBEDTLS_ECP_C) - if( PSA_KEY_TYPE_IS_ECC( slot->type ) ) + if( PSA_KEY_TYPE_IS_ECC( slot->attr.type ) ) { #if defined(MBEDTLS_ECDSA_C) if( PSA_ALG_IS_ECDSA( alg ) ) @@ -3288,12 +3289,12 @@ psa_status_t psa_asymmetric_encrypt( psa_key_handle_t handle, status = psa_get_transparent_key( handle, &slot, PSA_KEY_USAGE_ENCRYPT, alg ); if( status != PSA_SUCCESS ) return( status ); - if( ! ( PSA_KEY_TYPE_IS_PUBLIC_KEY( slot->type ) || - PSA_KEY_TYPE_IS_KEY_PAIR( slot->type ) ) ) + if( ! ( PSA_KEY_TYPE_IS_PUBLIC_KEY( slot->attr.type ) || + PSA_KEY_TYPE_IS_KEY_PAIR( slot->attr.type ) ) ) return( PSA_ERROR_INVALID_ARGUMENT ); #if defined(MBEDTLS_RSA_C) - if( PSA_KEY_TYPE_IS_RSA( slot->type ) ) + if( PSA_KEY_TYPE_IS_RSA( slot->attr.type ) ) { mbedtls_rsa_context *rsa = slot->data.rsa; int ret; @@ -3368,11 +3369,11 @@ psa_status_t psa_asymmetric_decrypt( psa_key_handle_t handle, status = psa_get_transparent_key( handle, &slot, PSA_KEY_USAGE_DECRYPT, alg ); if( status != PSA_SUCCESS ) return( status ); - if( ! PSA_KEY_TYPE_IS_KEY_PAIR( slot->type ) ) + if( ! PSA_KEY_TYPE_IS_KEY_PAIR( slot->attr.type ) ) return( PSA_ERROR_INVALID_ARGUMENT ); #if defined(MBEDTLS_RSA_C) - if( slot->type == PSA_KEY_TYPE_RSA_KEY_PAIR ) + if( slot->attr.type == PSA_KEY_TYPE_RSA_KEY_PAIR ) { mbedtls_rsa_context *rsa = slot->data.rsa; int ret; @@ -3479,7 +3480,7 @@ static psa_status_t psa_cipher_setup( psa_cipher_operation_t *operation, goto exit; key_bits = psa_get_key_slot_bits( slot ); - cipher_info = mbedtls_cipher_info_from_psa( alg, slot->type, key_bits, NULL ); + cipher_info = mbedtls_cipher_info_from_psa( alg, slot->attr.type, key_bits, NULL ); if( cipher_info == NULL ) { status = PSA_ERROR_NOT_SUPPORTED; @@ -3491,7 +3492,7 @@ static psa_status_t psa_cipher_setup( psa_cipher_operation_t *operation, goto exit; #if defined(MBEDTLS_DES_C) - if( slot->type == PSA_KEY_TYPE_DES && key_bits == 128 ) + if( slot->attr.type == PSA_KEY_TYPE_DES && key_bits == 128 ) { /* Two-key Triple-DES is 3-key Triple-DES with K1=K3 */ uint8_t keys[24]; @@ -3533,10 +3534,10 @@ static psa_status_t psa_cipher_setup( psa_cipher_operation_t *operation, operation->key_set = 1; operation->block_size = ( PSA_ALG_IS_STREAM_CIPHER( alg ) ? 1 : - PSA_BLOCK_CIPHER_BLOCK_SIZE( slot->type ) ); + PSA_BLOCK_CIPHER_BLOCK_SIZE( slot->attr.type ) ); if( alg & PSA_ALG_CIPHER_FROM_BLOCK_FLAG ) { - operation->iv_size = PSA_BLOCK_CIPHER_BLOCK_SIZE( slot->type ); + operation->iv_size = PSA_BLOCK_CIPHER_BLOCK_SIZE( slot->attr.type ); } #if defined(MBEDTLS_CHACHA20_C) else @@ -3818,7 +3819,7 @@ static psa_status_t psa_aead_setup( aead_operation_t *operation, key_bits = psa_get_key_slot_bits( operation->slot ); operation->cipher_info = - mbedtls_cipher_info_from_psa( alg, operation->slot->type, key_bits, + mbedtls_cipher_info_from_psa( alg, operation->slot->attr.type, key_bits, &cipher_id ); if( operation->cipher_info == NULL ) return( PSA_ERROR_NOT_SUPPORTED ); @@ -3832,7 +3833,7 @@ static psa_status_t psa_aead_setup( aead_operation_t *operation, /* CCM allows the following tag lengths: 4, 6, 8, 10, 12, 14, 16. * The call to mbedtls_ccm_encrypt_and_tag or * mbedtls_ccm_auth_decrypt will validate the tag length. */ - if( PSA_BLOCK_CIPHER_BLOCK_SIZE( operation->slot->type ) != 16 ) + if( PSA_BLOCK_CIPHER_BLOCK_SIZE( operation->slot->attr.type ) != 16 ) return( PSA_ERROR_INVALID_ARGUMENT ); mbedtls_ccm_init( &operation->ctx.ccm ); status = mbedtls_to_psa_error( @@ -3851,7 +3852,7 @@ static psa_status_t psa_aead_setup( aead_operation_t *operation, /* GCM allows the following tag lengths: 4, 8, 12, 13, 14, 15, 16. * The call to mbedtls_gcm_crypt_and_tag or * mbedtls_gcm_auth_decrypt will validate the tag length. */ - if( PSA_BLOCK_CIPHER_BLOCK_SIZE( operation->slot->type ) != 16 ) + if( PSA_BLOCK_CIPHER_BLOCK_SIZE( operation->slot->attr.type ) != 16 ) return( PSA_ERROR_INVALID_ARGUMENT ); mbedtls_gcm_init( &operation->ctx.gcm ); status = mbedtls_to_psa_error( @@ -4676,7 +4677,7 @@ static psa_status_t psa_generate_derived_key_internal( size_t bytes = PSA_BITS_TO_BYTES( bits ); psa_status_t status; - if( ! key_type_is_raw_bytes( slot->type ) ) + if( ! key_type_is_raw_bytes( slot->attr.type ) ) return( PSA_ERROR_INVALID_ARGUMENT ); if( bits % 8 != 0 ) return( PSA_ERROR_INVALID_ARGUMENT ); @@ -4688,7 +4689,7 @@ static psa_status_t psa_generate_derived_key_internal( if( status != PSA_SUCCESS ) goto exit; #if defined(MBEDTLS_DES_C) - if( slot->type == PSA_KEY_TYPE_DES ) + if( slot->attr.type == PSA_KEY_TYPE_DES ) psa_des_set_key_parity( data, bytes ); #endif /* MBEDTLS_DES_C */ status = psa_import_key_into_slot( slot, data, bytes ); @@ -4997,7 +4998,7 @@ psa_status_t psa_key_derivation( psa_key_derivation_operation_t *operation, if( status != PSA_SUCCESS ) return( status ); - if( slot->type != PSA_KEY_TYPE_DERIVE ) + if( slot->attr.type != PSA_KEY_TYPE_DERIVE ) return( PSA_ERROR_INVALID_ARGUMENT ); status = psa_key_derivation_internal( operation, @@ -5372,7 +5373,7 @@ psa_status_t psa_key_derivation_input_key( operation->alg ); if( status != PSA_SUCCESS ) return( status ); - if( slot->type != PSA_KEY_TYPE_DERIVE ) + if( slot->attr.type != PSA_KEY_TYPE_DERIVE ) return( PSA_ERROR_INVALID_ARGUMENT ); /* Don't allow a key to be used as an input that is usually public. * This is debatable. It's ok from a cryptographic perspective to @@ -5452,7 +5453,7 @@ static psa_status_t psa_key_agreement_raw_internal( psa_algorithm_t alg, { #if defined(MBEDTLS_ECDH_C) case PSA_ALG_ECDH: - if( ! PSA_KEY_TYPE_IS_ECC_KEY_PAIR( private_key->type ) ) + if( ! PSA_KEY_TYPE_IS_ECC_KEY_PAIR( private_key->attr.type ) ) return( PSA_ERROR_INVALID_ARGUMENT ); return( psa_key_agreement_ecdh( peer_key, peer_key_length, private_key->data.ecp, @@ -5635,7 +5636,7 @@ static psa_status_t psa_generate_key_internal( psa_key_slot_t *slot, size_t bits, const uint8_t *domain_parameters, size_t domain_parameters_size ) { - psa_key_type_t type = slot->type; + psa_key_type_t type = slot->attr.type; if( domain_parameters == NULL && domain_parameters_size != 0 ) return( PSA_ERROR_INVALID_ARGUMENT ); diff --git a/library/psa_crypto_core.h b/library/psa_crypto_core.h index d335b758e..88a328983 100644 --- a/library/psa_crypto_core.h +++ b/library/psa_crypto_core.h @@ -39,11 +39,7 @@ */ typedef struct { - psa_key_type_t type; - psa_key_lifetime_t lifetime; - psa_key_file_id_t persistent_storage_id; - psa_key_policy_t policy; - unsigned allocated : 1; + psa_core_key_attributes_t attr; union { /* Raw-data key (key_type_is_raw_bytes() in psa_crypto.c) */ @@ -69,6 +65,60 @@ typedef struct } data; } psa_key_slot_t; +/** Flag for psa_key_slot_t::attr::core::flags indicating that the + * slot is in use. */ +#define PSA_KEY_SLOT_FLAG_ALLOCATED ( (uint16_t) 0x0001 ) + +/** Retrieve flags from psa_key_slot_t::attr::core::flags. + * + * \param[in] slot The key slot to query. + * \param mask The mask of bits to extract. + * + * \return The key attribute flags in the given slot, + * bitwise-anded with \p mask. + */ +static inline uint16_t psa_key_slot_get_flags( const psa_key_slot_t *slot, + uint16_t mask ) +{ + return( slot->attr.flags & mask ); +} + +/** Set flags in psa_key_slot_t::attr::core::flags. + * + * \param[in,out] slot The key slot to modify. + * \param mask The mask of bits to modify. + * \param value The new value of the selected bits. + */ +static inline void psa_key_slot_set_flags( psa_key_slot_t *slot, + uint16_t mask, + uint16_t value ) +{ + slot->attr.flags = ( ( ~mask & slot->attr.flags ) | + ( mask & value ) ); +} + +/** Turn on flags in psa_key_slot_t::attr::core::flags. + * + * \param[in,out] slot The key slot to modify. + * \param mask The mask of bits to set. + */ +static inline void psa_key_slot_set_bits_in_flags( psa_key_slot_t *slot, + uint16_t mask ) +{ + slot->attr.flags |= mask; +} + +/** Turn off flags in psa_key_slot_t::attr::core::flags. + * + * \param[in,out] slot The key slot to modify. + * \param mask The mask of bits to clear. + */ +static inline void psa_key_slot_clear_bits( psa_key_slot_t *slot, + uint16_t mask ) +{ + slot->attr.flags &= ~mask; +} + /** Completely wipe a slot in memory, including its policy. * * Persistent storage is not affected. diff --git a/library/psa_crypto_slot_management.c b/library/psa_crypto_slot_management.c index 6add6b860..bfa7baaa5 100644 --- a/library/psa_crypto_slot_management.c +++ b/library/psa_crypto_slot_management.c @@ -72,7 +72,7 @@ psa_status_t psa_get_key_slot( psa_key_handle_t handle, slot = &global_data.key_slots[handle - 1]; /* If the slot hasn't been allocated, the handle is invalid. */ - if( ! slot->allocated ) + if( ! psa_key_slot_get_flags( slot, PSA_KEY_SLOT_FLAG_ALLOCATED ) ) return( PSA_ERROR_INVALID_HANDLE ); *p_slot = slot; @@ -108,9 +108,10 @@ psa_status_t psa_internal_allocate_key_slot( psa_key_handle_t *handle, for( *handle = PSA_KEY_SLOT_COUNT; *handle != 0; --( *handle ) ) { *p_slot = &global_data.key_slots[*handle - 1]; - if( ! ( *p_slot )->allocated ) + if( ! psa_key_slot_get_flags( *p_slot, PSA_KEY_SLOT_FLAG_ALLOCATED ) ) { - ( *p_slot )->allocated = 1; + psa_key_slot_set_bits_in_flags( *p_slot, + PSA_KEY_SLOT_FLAG_ALLOCATED ); return( PSA_SUCCESS ); } } @@ -126,17 +127,17 @@ static psa_status_t psa_load_persistent_key_into_slot( psa_key_slot_t *p_slot ) size_t key_data_length = 0; psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; - psa_set_key_id( &attributes, p_slot->persistent_storage_id ); + psa_set_key_id( &attributes, p_slot->attr.id ); status = psa_load_persistent_key( &attributes, &key_data, &key_data_length ); if( status != PSA_SUCCESS ) goto exit; - p_slot->lifetime = psa_get_key_lifetime( &attributes ); - p_slot->type = psa_get_key_type( &attributes ); - p_slot->policy = attributes.core.policy; + p_slot->attr.lifetime = psa_get_key_lifetime( &attributes ); + p_slot->attr.type = psa_get_key_type( &attributes ); + p_slot->attr.policy = attributes.core.policy; #if defined(MBEDTLS_PSA_CRYPTO_SE_C) - if( psa_key_lifetime_is_external( p_slot->lifetime ) ) + if( psa_key_lifetime_is_external( p_slot->attr.lifetime ) ) { if( key_data_length != sizeof( p_slot->data.se ) ) { @@ -233,8 +234,8 @@ psa_status_t psa_open_key( psa_key_file_id_t id, psa_key_handle_t *handle ) if( status != PSA_SUCCESS ) return( status ); - slot->lifetime = PSA_KEY_LIFETIME_PERSISTENT; - slot->persistent_storage_id = id; + slot->attr.lifetime = PSA_KEY_LIFETIME_PERSISTENT; + slot->attr.id = id; status = psa_load_persistent_key_into_slot( slot ); if( status != PSA_SUCCESS ) @@ -270,27 +271,27 @@ void mbedtls_psa_get_stats( mbedtls_psa_stats_t *stats ) for( key = 1; key <= PSA_KEY_SLOT_COUNT; key++ ) { psa_key_slot_t *slot = &global_data.key_slots[key - 1]; - if( slot->type == PSA_KEY_TYPE_NONE ) + if( slot->attr.type == PSA_KEY_TYPE_NONE ) { - if( slot->allocated ) + if( psa_key_slot_get_flags( slot, PSA_KEY_SLOT_FLAG_ALLOCATED ) ) ++stats->half_filled_slots; else ++stats->empty_slots; continue; } - if( slot->lifetime == PSA_KEY_LIFETIME_VOLATILE ) + if( slot->attr.lifetime == PSA_KEY_LIFETIME_VOLATILE ) ++stats->volatile_slots; - else if( slot->lifetime == PSA_KEY_LIFETIME_PERSISTENT ) + else if( slot->attr.lifetime == PSA_KEY_LIFETIME_PERSISTENT ) { ++stats->persistent_slots; - if( slot->persistent_storage_id > stats->max_open_internal_key_id ) - stats->max_open_internal_key_id = slot->persistent_storage_id; + if( slot->attr.id > stats->max_open_internal_key_id ) + stats->max_open_internal_key_id = slot->attr.id; } else { ++stats->external_slots; - if( slot->persistent_storage_id > stats->max_open_external_key_id ) - stats->max_open_external_key_id = slot->persistent_storage_id; + if( slot->attr.id > stats->max_open_external_key_id ) + stats->max_open_external_key_id = slot->attr.id; } } } From 4ed0e6f11a6526896b3b17e82d0f04e0b88d741c Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Tue, 30 Jul 2019 20:22:33 +0200 Subject: [PATCH 05/20] Switch storage functions over to psa_core_key_attributes_t --- library/psa_crypto.c | 5 ++- library/psa_crypto_slot_management.c | 2 +- library/psa_crypto_storage.c | 37 +++++++++---------- library/psa_crypto_storage.h | 17 ++++----- ...t_suite_psa_crypto_persistent_key.function | 4 +- 5 files changed, 32 insertions(+), 33 deletions(-) diff --git a/library/psa_crypto.c b/library/psa_crypto.c index 1646ae584..03e56a1c0 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -1554,7 +1554,7 @@ static psa_status_t psa_finish_key_creation( #if defined(MBEDTLS_PSA_CRYPTO_SE_C) if( driver != NULL ) { - status = psa_save_persistent_key( &attributes, + status = psa_save_persistent_key( &attributes.core, (uint8_t*) &slot->data.se, sizeof( slot->data.se ) ); } @@ -1572,7 +1572,8 @@ static psa_status_t psa_finish_key_creation( buffer, buffer_size, &length, 0 ); if( status == PSA_SUCCESS ) - status = psa_save_persistent_key( &attributes, buffer, length ); + status = psa_save_persistent_key( &attributes.core, + buffer, length ); if( buffer_size != 0 ) mbedtls_platform_zeroize( buffer, buffer_size ); diff --git a/library/psa_crypto_slot_management.c b/library/psa_crypto_slot_management.c index bfa7baaa5..2cfc4a9e8 100644 --- a/library/psa_crypto_slot_management.c +++ b/library/psa_crypto_slot_management.c @@ -128,7 +128,7 @@ static psa_status_t psa_load_persistent_key_into_slot( psa_key_slot_t *p_slot ) psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; psa_set_key_id( &attributes, p_slot->attr.id ); - status = psa_load_persistent_key( &attributes, + status = psa_load_persistent_key( &attributes.core, &key_data, &key_data_length ); if( status != PSA_SUCCESS ) goto exit; diff --git a/library/psa_crypto_storage.c b/library/psa_crypto_storage.c index 4113fb7e1..55fd65af9 100644 --- a/library/psa_crypto_storage.c +++ b/library/psa_crypto_storage.c @@ -264,7 +264,7 @@ typedef struct { void psa_format_key_data_for_storage( const uint8_t *data, const size_t data_length, - const psa_key_attributes_t *attributes, + const psa_core_key_attributes_t *attr, uint8_t *storage_data ) { psa_persistent_key_storage_format *storage_format = @@ -272,11 +272,11 @@ void psa_format_key_data_for_storage( const uint8_t *data, memcpy( storage_format->magic, PSA_KEY_STORAGE_MAGIC_HEADER, PSA_KEY_STORAGE_MAGIC_HEADER_LENGTH ); PUT_UINT32_LE( 0, storage_format->version, 0 ); - PUT_UINT32_LE( psa_get_key_lifetime( attributes ), storage_format->lifetime, 0 ); - PUT_UINT32_LE( psa_get_key_type( attributes ), storage_format->type, 0 ); - PUT_UINT32_LE( psa_get_key_usage_flags( attributes ), storage_format->policy, 0 ); - PUT_UINT32_LE( psa_get_key_algorithm( attributes ), storage_format->policy, sizeof( uint32_t ) ); - PUT_UINT32_LE( psa_get_key_enrollment_algorithm( attributes ), storage_format->policy, 2 * sizeof( uint32_t ) ); + PUT_UINT32_LE( attr->lifetime, storage_format->lifetime, 0 ); + PUT_UINT32_LE( attr->type, storage_format->type, 0 ); + PUT_UINT32_LE( attr->policy.usage, storage_format->policy, 0 ); + PUT_UINT32_LE( attr->policy.alg, storage_format->policy, sizeof( uint32_t ) ); + PUT_UINT32_LE( attr->policy.alg2, storage_format->policy, 2 * sizeof( uint32_t ) ); PUT_UINT32_LE( data_length, storage_format->data_len, 0 ); memcpy( storage_format->key_data, data, data_length ); } @@ -293,7 +293,7 @@ psa_status_t psa_parse_key_data_from_storage( const uint8_t *storage_data, size_t storage_data_length, uint8_t **key_data, size_t *key_data_length, - psa_key_attributes_t *attributes ) + psa_core_key_attributes_t *attr ) { psa_status_t status; const psa_persistent_key_storage_format *storage_format = @@ -328,16 +328,16 @@ psa_status_t psa_parse_key_data_from_storage( const uint8_t *storage_data, memcpy( *key_data, storage_format->key_data, *key_data_length ); } - GET_UINT32_LE( attributes->core.lifetime, storage_format->lifetime, 0 ); - GET_UINT32_LE( attributes->core.type, storage_format->type, 0 ); - GET_UINT32_LE( attributes->core.policy.usage, storage_format->policy, 0 ); - GET_UINT32_LE( attributes->core.policy.alg, storage_format->policy, sizeof( uint32_t ) ); - GET_UINT32_LE( attributes->core.policy.alg2, storage_format->policy, 2 * sizeof( uint32_t ) ); + GET_UINT32_LE( attr->lifetime, storage_format->lifetime, 0 ); + GET_UINT32_LE( attr->type, storage_format->type, 0 ); + GET_UINT32_LE( attr->policy.usage, storage_format->policy, 0 ); + GET_UINT32_LE( attr->policy.alg, storage_format->policy, sizeof( uint32_t ) ); + GET_UINT32_LE( attr->policy.alg2, storage_format->policy, 2 * sizeof( uint32_t ) ); return( PSA_SUCCESS ); } -psa_status_t psa_save_persistent_key( const psa_key_attributes_t *attributes, +psa_status_t psa_save_persistent_key( const psa_core_key_attributes_t *attr, const uint8_t *data, const size_t data_length ) { @@ -353,10 +353,9 @@ psa_status_t psa_save_persistent_key( const psa_key_attributes_t *attributes, if( storage_data == NULL ) return( PSA_ERROR_INSUFFICIENT_MEMORY ); - psa_format_key_data_for_storage( data, data_length, attributes, - storage_data ); + psa_format_key_data_for_storage( data, data_length, attr, storage_data ); - status = psa_crypto_storage_store( psa_get_key_id( attributes ), + status = psa_crypto_storage_store( attr->id, storage_data, storage_data_length ); mbedtls_free( storage_data ); @@ -373,14 +372,14 @@ void psa_free_persistent_key_data( uint8_t *key_data, size_t key_data_length ) mbedtls_free( key_data ); } -psa_status_t psa_load_persistent_key( psa_key_attributes_t *attributes, +psa_status_t psa_load_persistent_key( psa_core_key_attributes_t *attr, uint8_t **data, size_t *data_length ) { psa_status_t status = PSA_SUCCESS; uint8_t *loaded_data; size_t storage_data_length = 0; - psa_key_id_t key = psa_get_key_id( attributes ); + psa_key_id_t key = attr->id; status = psa_crypto_storage_get_data_length( key, &storage_data_length ); if( status != PSA_SUCCESS ) @@ -396,7 +395,7 @@ psa_status_t psa_load_persistent_key( psa_key_attributes_t *attributes, goto exit; status = psa_parse_key_data_from_storage( loaded_data, storage_data_length, - data, data_length, attributes ); + data, data_length, attr ); exit: mbedtls_free( loaded_data ); diff --git a/library/psa_crypto_storage.h b/library/psa_crypto_storage.h index 938cc4f89..1b7dbd67c 100644 --- a/library/psa_crypto_storage.h +++ b/library/psa_crypto_storage.h @@ -88,7 +88,7 @@ int psa_is_key_present_in_storage( const psa_key_file_id_t key ); * already occupied non-persistent key, as well as validating the key data. * * - * \param[in] attributes The attributes of the key to save. + * \param[in] attr The attributes of the key to save. * The key identifier field in the attributes * determines the key's location. * \param[in] data Buffer containing the key data. @@ -100,7 +100,7 @@ int psa_is_key_present_in_storage( const psa_key_file_id_t key ); * \retval PSA_ERROR_STORAGE_FAILURE * \retval PSA_ERROR_ALREADY_EXISTS */ -psa_status_t psa_save_persistent_key( const psa_key_attributes_t *attributes, +psa_status_t psa_save_persistent_key( const psa_core_key_attributes_t *attr, const uint8_t *data, const size_t data_length ); @@ -116,8 +116,7 @@ psa_status_t psa_save_persistent_key( const psa_key_attributes_t *attributes, * this function to zeroize and free this buffer, regardless of whether this * function succeeds or fails. * - * \param[in,out] attributes - * On input, the key identifier field identifies + * \param[in,out] attr On input, the key identifier field identifies * the key to load. Other fields are ignored. * On success, the attribute structure contains * the key metadata that was loaded from storage. @@ -129,7 +128,7 @@ psa_status_t psa_save_persistent_key( const psa_key_attributes_t *attributes, * \retval PSA_ERROR_STORAGE_FAILURE * \retval PSA_ERROR_DOES_NOT_EXIST */ -psa_status_t psa_load_persistent_key( psa_key_attributes_t *attributes, +psa_status_t psa_load_persistent_key( psa_core_key_attributes_t *attr, uint8_t **data, size_t *data_length ); @@ -163,13 +162,13 @@ void psa_free_persistent_key_data( uint8_t *key_data, size_t key_data_length ); * * \param[in] data Buffer containing the key data. * \param data_length Length of the key data buffer. - * \param[in] attributes The attributes of the key. + * \param[in] attr The core attributes of the key. * \param[out] storage_data Output buffer for the formatted data. * */ void psa_format_key_data_for_storage( const uint8_t *data, const size_t data_length, - const psa_key_attributes_t *attributes, + const psa_core_key_attributes_t *attr, uint8_t *storage_data ); /** @@ -181,7 +180,7 @@ void psa_format_key_data_for_storage( const uint8_t *data, * containing the key data. This must be freed * using psa_free_persistent_key_data() * \param[out] key_data_length Length of the key data buffer - * \param[out] attributes On success, the attribute structure is filled + * \param[out] attr On success, the attribute structure is filled * with the loaded key metadata. * * \retval PSA_SUCCESS @@ -193,7 +192,7 @@ psa_status_t psa_parse_key_data_from_storage( const uint8_t *storage_data, size_t storage_data_length, uint8_t **key_data, size_t *key_data_length, - psa_key_attributes_t *attributes ); + psa_core_key_attributes_t *attr ); #if defined(MBEDTLS_PSA_CRYPTO_SE_C) /** This symbol is defined if transaction support is required. */ diff --git a/tests/suites/test_suite_psa_crypto_persistent_key.function b/tests/suites/test_suite_psa_crypto_persistent_key.function index 61f7f886a..115bfea5d 100644 --- a/tests/suites/test_suite_psa_crypto_persistent_key.function +++ b/tests/suites/test_suite_psa_crypto_persistent_key.function @@ -45,7 +45,7 @@ void format_storage_data_check( data_t *key_data, file_data_length = key_data->len + sizeof( psa_persistent_key_storage_format ); file_data = mbedtls_calloc( 1, file_data_length ); psa_format_key_data_for_storage( key_data->x, key_data->len, - &attributes, + &attributes.core, file_data ); ASSERT_COMPARE( expected_file_data->x, expected_file_data->len, @@ -71,7 +71,7 @@ void parse_storage_data_check( data_t *file_data, status = psa_parse_key_data_from_storage( file_data->x, file_data->len, &key_data, &key_data_length, - &attributes ); + &attributes.core ); TEST_EQUAL( status, expected_status ); if( status != PSA_SUCCESS ) From 2431859dc77400eef4b5aedceebd34f76df35f22 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Tue, 30 Jul 2019 20:30:51 +0200 Subject: [PATCH 06/20] Take advantage of psa_core_key_attributes_t internally: key loading --- library/psa_crypto_slot_management.c | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/library/psa_crypto_slot_management.c b/library/psa_crypto_slot_management.c index 2cfc4a9e8..f3a438996 100644 --- a/library/psa_crypto_slot_management.c +++ b/library/psa_crypto_slot_management.c @@ -120,37 +120,31 @@ psa_status_t psa_internal_allocate_key_slot( psa_key_handle_t *handle, } #if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) -static psa_status_t psa_load_persistent_key_into_slot( psa_key_slot_t *p_slot ) +static psa_status_t psa_load_persistent_key_into_slot( psa_key_slot_t *slot ) { psa_status_t status = PSA_SUCCESS; uint8_t *key_data = NULL; size_t key_data_length = 0; - psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; - psa_set_key_id( &attributes, p_slot->attr.id ); - status = psa_load_persistent_key( &attributes.core, + status = psa_load_persistent_key( &slot->attr, &key_data, &key_data_length ); if( status != PSA_SUCCESS ) goto exit; - p_slot->attr.lifetime = psa_get_key_lifetime( &attributes ); - p_slot->attr.type = psa_get_key_type( &attributes ); - p_slot->attr.policy = attributes.core.policy; #if defined(MBEDTLS_PSA_CRYPTO_SE_C) - if( psa_key_lifetime_is_external( p_slot->attr.lifetime ) ) + if( psa_key_lifetime_is_external( slot->attr.lifetime ) ) { - if( key_data_length != sizeof( p_slot->data.se ) ) + if( key_data_length != sizeof( slot->data.se ) ) { status = PSA_ERROR_STORAGE_FAILURE; goto exit; } - memcpy( &p_slot->data.se, key_data, sizeof( p_slot->data.se ) ); + memcpy( &slot->data.se, key_data, sizeof( slot->data.se ) ); } else #endif /* MBEDTLS_PSA_CRYPTO_SE_C */ { - status = psa_import_key_into_slot( p_slot, - key_data, key_data_length ); + status = psa_import_key_into_slot( slot, key_data, key_data_length ); } exit: From b46bef2f76eb00cd8af7a9fe1864c5602037fa7f Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Tue, 30 Jul 2019 21:32:04 +0200 Subject: [PATCH 07/20] Store the key size in the slot in memory There is now a field for the key size in the key slot in memory. Use it. This makes psa_get_key_attributes() marginally faster at the expense of memory that is available anyway in the current memory layout (16 bits for the size, 16 bits for flags). That's not the goal, though: the goal is to simplify the code, in particular to make it more uniform between transparent keys (whose size can be recomputed) and keys in secure elements (whose size cannot be recomputed). For keys in a secure element, the bit size is now saved by serializing the type psa_key_bits_t (which is an alias for uint16_t) rather than size_t. --- library/psa_crypto.c | 108 +++++++++++++++++++-------- library/psa_crypto_core.h | 1 - library/psa_crypto_se.h | 9 +++ library/psa_crypto_slot_management.c | 12 ++- 4 files changed, 95 insertions(+), 35 deletions(-) diff --git a/library/psa_crypto.c b/library/psa_crypto.c index 03e56a1c0..dacb80e79 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -40,6 +40,7 @@ * stored keys. */ #include "psa_crypto_storage.h" +#include #include #include #include "mbedtls/platform.h" @@ -695,6 +696,40 @@ exit: } #endif /* defined(MBEDTLS_ECP_C) */ + +/** Return the size of the key in the given slot, in bits. + * + * \param[in] slot A key slot. + * + * \return The key size in bits, read from the metadata in the slot. + */ +static inline size_t psa_get_key_slot_bits( const psa_key_slot_t *slot ) +{ + return( slot->attr.bits ); +} + +/** Calculate the size of the key in the given slot, in bits. + * + * \param[in] slot A key slot containing a transparent key. + * + * \return The key size in bits, calculated from the key data. + */ +static size_t psa_calculate_key_bits( const psa_key_slot_t *slot ) +{ + if( key_type_is_raw_bytes( slot->attr.type ) ) + return( slot->data.raw.bytes * 8 ); +#if defined(MBEDTLS_RSA_C) + if( PSA_KEY_TYPE_IS_RSA( slot->attr.type ) ) + return( PSA_BYTES_TO_BITS( mbedtls_rsa_get_len( slot->data.rsa ) ) ); +#endif /* defined(MBEDTLS_RSA_C) */ +#if defined(MBEDTLS_ECP_C) + if( PSA_KEY_TYPE_IS_ECC( slot->attr.type ) ) + return( slot->data.ecp->grp.pbits ); +#endif /* defined(MBEDTLS_ECP_C) */ + /* Shouldn't happen except on an empty slot. */ + return( 0 ); +} + /** Import key data into a slot. `slot->attr.type` must have been set * previously. This function assumes that the slot does not contain * any key material yet. On failure, the slot content is unchanged. */ @@ -749,6 +784,14 @@ psa_status_t psa_import_key_into_slot( psa_key_slot_t *slot, { return( PSA_ERROR_NOT_SUPPORTED ); } + + if( status == PSA_SUCCESS ) + { + /* Write the actual key size to the slot. + * psa_start_key_creation() wrote the size declared by the + * caller, which may be 0 (meaning unspecified) or wrong. */ + slot->attr.bits = psa_calculate_key_bits( slot ); + } return( status ); } @@ -1035,28 +1078,6 @@ psa_status_t psa_destroy_key( psa_key_handle_t handle ) return( storage_status ); } -/* Return the size of the key in the given slot, in bits. */ -static size_t psa_get_key_slot_bits( const psa_key_slot_t *slot ) -{ -#if defined(MBEDTLS_PSA_CRYPTO_SE_C) - if( psa_get_se_driver( slot->attr.lifetime, NULL, NULL ) ) - return( slot->data.se.bits ); -#endif /* defined(MBEDTLS_PSA_CRYPTO_SE_C) */ - - if( key_type_is_raw_bytes( slot->attr.type ) ) - return( slot->data.raw.bytes * 8 ); -#if defined(MBEDTLS_RSA_C) - if( PSA_KEY_TYPE_IS_RSA( slot->attr.type ) ) - return( PSA_BYTES_TO_BITS( mbedtls_rsa_get_len( slot->data.rsa ) ) ); -#endif /* defined(MBEDTLS_RSA_C) */ -#if defined(MBEDTLS_ECP_C) - if( PSA_KEY_TYPE_IS_ECC( slot->attr.type ) ) - return( slot->data.ecp->grp.pbits ); -#endif /* defined(MBEDTLS_ECP_C) */ - /* Shouldn't happen except on an empty slot. */ - return( 0 ); -} - void psa_reset_key_attributes( psa_key_attributes_t *attributes ) { mbedtls_free( attributes->domain_parameters ); @@ -1160,7 +1181,7 @@ static void psa_get_key_slot_attributes( psa_key_slot_t *slot, attributes->core.lifetime = slot->attr.lifetime; attributes->core.policy = slot->attr.policy; attributes->core.type = slot->attr.type; - attributes->core.bits = psa_get_key_slot_bits( slot ); + attributes->core.bits = slot->attr.bits; } /** Retrieve all the publicly-accessible attributes of a key. @@ -1270,7 +1291,7 @@ static psa_status_t psa_internal_export_key( const psa_key_slot_t *slot, { psa_status_t status; - size_t bytes = PSA_BITS_TO_BYTES( psa_get_key_slot_bits( slot ) ); + size_t bytes = PSA_BITS_TO_BYTES( slot->attr.bits ); if( bytes > data_size ) return( PSA_ERROR_BUFFER_TOO_SMALL ); status = mbedtls_to_psa_error( @@ -1479,6 +1500,12 @@ static psa_status_t psa_start_key_creation( * psa_import_key() needs its own checks. */ if( psa_get_key_bits( attributes ) > PSA_MAX_KEY_BITS ) return( PSA_ERROR_NOT_SUPPORTED ); + /* Store the declared bit-size of the key. It's up to each creation + * mechanism to verify that this information is correct. It's + * automatically correct for mechanisms that use the bit-size as + * an input (generate, device) but not for those where the bit-size + * is optional (import, copy). */ + slot->attr.bits = psa_get_key_bits( attributes ); #if defined(MBEDTLS_PSA_CRYPTO_SE_C) /* For a key in a secure element, we need to do three things: @@ -1510,10 +1537,6 @@ static psa_status_t psa_start_key_creation( (void) psa_crypto_stop_transaction( ); return( status ); } - - /* TOnogrepDO: validate bits. How to do this depends on the key - * creation method, so setting bits might not belong here. */ - slot->data.se.bits = psa_get_key_bits( attributes ); } #endif /* MBEDTLS_PSA_CRYPTO_SE_C */ @@ -1554,9 +1577,21 @@ static psa_status_t psa_finish_key_creation( #if defined(MBEDTLS_PSA_CRYPTO_SE_C) if( driver != NULL ) { + psa_se_key_data_storage_t data; +#if defined(static_assert) + static_assert( sizeof( slot->data.se.slot_number ) == + sizeof( data.slot_number ), + "Slot number size does not match psa_se_key_data_storage_t" ); + static_assert( sizeof( slot->attr.bits ) == sizeof( data.bits ), + "Bit-size size does not match psa_se_key_data_storage_t" ); +#endif + memcpy( &data.slot_number, &slot->data.se.slot_number, + sizeof( slot->data.se.slot_number ) ); + memcpy( &data.bits, &slot->attr.bits, + sizeof( slot->attr.bits ) ); status = psa_save_persistent_key( &attributes.core, - (uint8_t*) &slot->data.se, - sizeof( slot->data.se ) ); + (uint8_t*) &data, + sizeof( data ) ); } else #endif /* MBEDTLS_PSA_CRYPTO_SE_C */ @@ -1680,7 +1715,7 @@ static psa_status_t psa_check_key_slot_attributes( if( attributes->core.bits != 0 ) { - if( attributes->core.bits != psa_get_key_slot_bits( slot ) ) + if( attributes->core.bits != slot->attr.bits ) return( PSA_ERROR_INVALID_ARGUMENT ); } @@ -1704,6 +1739,7 @@ psa_status_t psa_import_key( const psa_key_attributes_t *attributes, if( driver != NULL ) { const psa_drv_se_t *drv = psa_get_se_driver_methods( driver ); + size_t bits; if( drv->key_management == NULL || drv->key_management->p_import == NULL ) { @@ -1716,7 +1752,15 @@ psa_status_t psa_import_key( const psa_key_attributes_t *attributes, slot->attr.lifetime, slot->attr.type, slot->attr.policy.alg, slot->attr.policy.usage, data, data_length, - &slot->data.se.bits ); + &bits ); + if( status != PSA_SUCCESS ) + goto exit; + if( bits > PSA_MAX_KEY_BITS ) + { + status = PSA_ERROR_NOT_SUPPORTED; + goto exit; + } + slot->attr.bits = (psa_key_bits_t) bits; } else #endif /* MBEDTLS_PSA_CRYPTO_SE_C */ diff --git a/library/psa_crypto_core.h b/library/psa_crypto_core.h index 88a328983..1ae298e5f 100644 --- a/library/psa_crypto_core.h +++ b/library/psa_crypto_core.h @@ -60,7 +60,6 @@ typedef struct struct se { psa_key_slot_number_t slot_number; - size_t bits; } se; } data; } psa_key_slot_t; diff --git a/library/psa_crypto_se.h b/library/psa_crypto_se.h index 08e658cdd..378c78ffe 100644 --- a/library/psa_crypto_se.h +++ b/library/psa_crypto_se.h @@ -171,4 +171,13 @@ psa_status_t psa_save_se_persistent_data( */ psa_status_t psa_destroy_se_persistent_data( psa_key_lifetime_t lifetime ); + +/** The storage representation of a key whose data is in a secure element. + */ +typedef struct +{ + uint8_t slot_number[sizeof( psa_key_slot_number_t )]; + uint8_t bits[sizeof( psa_key_bits_t )]; +} psa_se_key_data_storage_t; + #endif /* PSA_CRYPTO_SE_H */ diff --git a/library/psa_crypto_slot_management.c b/library/psa_crypto_slot_management.c index f3a438996..43ba4123c 100644 --- a/library/psa_crypto_slot_management.c +++ b/library/psa_crypto_slot_management.c @@ -33,6 +33,9 @@ #include "psa_crypto_core.h" #include "psa_crypto_slot_management.h" #include "psa_crypto_storage.h" +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) +#include "psa_crypto_se.h" +#endif #include #include @@ -134,12 +137,17 @@ static psa_status_t psa_load_persistent_key_into_slot( psa_key_slot_t *slot ) #if defined(MBEDTLS_PSA_CRYPTO_SE_C) if( psa_key_lifetime_is_external( slot->attr.lifetime ) ) { - if( key_data_length != sizeof( slot->data.se ) ) + psa_se_key_data_storage_t *data; + if( key_data_length != sizeof( *data ) ) { status = PSA_ERROR_STORAGE_FAILURE; goto exit; } - memcpy( &slot->data.se, key_data, sizeof( slot->data.se ) ); + data = (psa_se_key_data_storage_t *) key_data; + memcpy( &slot->data.se.slot_number, &data->slot_number, + sizeof( slot->data.se.slot_number ) ); + memcpy( &slot->attr.bits, &data->bits, + sizeof( slot->attr.bits ) ); } else #endif /* MBEDTLS_PSA_CRYPTO_SE_C */ From 76aa09c9a96f38e46e387d84935983d1245a99cd Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Wed, 31 Jul 2019 14:15:34 +0200 Subject: [PATCH 08/20] Take advantage of psa_core_key_attributes_t internally #2 Key creation and psa_get_key_attributes --- library/psa_crypto.c | 56 +++++++++++++++----------------------------- 1 file changed, 19 insertions(+), 37 deletions(-) diff --git a/library/psa_crypto.c b/library/psa_crypto.c index dacb80e79..cb8054681 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -1169,21 +1169,6 @@ exit: } #endif /* MBEDTLS_RSA_C */ -/** Retrieve the generic attributes of a key in a slot. - * - * This function does not retrieve domain parameters, which require - * additional memory management. - */ -static void psa_get_key_slot_attributes( psa_key_slot_t *slot, - psa_key_attributes_t *attributes ) -{ - attributes->core.id = slot->attr.id; - attributes->core.lifetime = slot->attr.lifetime; - attributes->core.policy = slot->attr.policy; - attributes->core.type = slot->attr.type; - attributes->core.bits = slot->attr.bits; -} - /** Retrieve all the publicly-accessible attributes of a key. */ psa_status_t psa_get_key_attributes( psa_key_handle_t handle, @@ -1198,7 +1183,7 @@ psa_status_t psa_get_key_attributes( psa_key_handle_t handle, if( status != PSA_SUCCESS ) return( status ); - psa_get_key_slot_attributes( slot, attributes ); + attributes->core = slot->attr; switch( slot->attr.type ) { @@ -1420,10 +1405,10 @@ psa_status_t psa_export_public_key( psa_key_handle_t handle, data_length, 1 ) ); } -static psa_status_t psa_set_key_policy_internal( - psa_key_slot_t *slot, - const psa_key_policy_t *policy ) +static psa_status_t psa_check_key_slot_policy( + const psa_key_slot_t *slot ) { + const psa_key_policy_t *policy = &slot->attr.policy; if( ( policy->usage & ~( PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_ENCRYPT | @@ -1433,7 +1418,6 @@ static psa_status_t psa_set_key_policy_internal( PSA_KEY_USAGE_DERIVE ) ) != 0 ) return( PSA_ERROR_INVALID_ARGUMENT ); - slot->attr.policy = *policy; return( PSA_SUCCESS ); } @@ -1478,11 +1462,6 @@ static psa_status_t psa_start_key_creation( return( status ); slot = *p_slot; - status = psa_set_key_policy_internal( slot, &attributes->core.policy ); - if( status != PSA_SUCCESS ) - return( status ); - slot->attr.lifetime = attributes->core.lifetime; - if( attributes->core.lifetime != PSA_KEY_LIFETIME_VOLATILE ) { status = psa_validate_persistent_key_parameters( attributes->core.lifetime, @@ -1490,9 +1469,11 @@ static psa_status_t psa_start_key_creation( p_drv, 1 ); if( status != PSA_SUCCESS ) return( status ); - slot->attr.id = attributes->core.id; } - slot->attr.type = attributes->core.type; + + status = psa_check_key_slot_policy( slot ); + if( status != PSA_SUCCESS ) + return( status ); /* Refuse to create overly large keys. * Note that this doesn't trigger on import if the attributes don't @@ -1500,12 +1481,16 @@ static psa_status_t psa_start_key_creation( * psa_import_key() needs its own checks. */ if( psa_get_key_bits( attributes ) > PSA_MAX_KEY_BITS ) return( PSA_ERROR_NOT_SUPPORTED ); - /* Store the declared bit-size of the key. It's up to each creation - * mechanism to verify that this information is correct. It's - * automatically correct for mechanisms that use the bit-size as + /* We're storing the declared bit-size of the key. It's up to each + * creation mechanism to verify that this information is correct. + * It's automatically correct for mechanisms that use the bit-size as * an input (generate, device) but not for those where the bit-size * is optional (import, copy). */ - slot->attr.bits = psa_get_key_bits( attributes ); + + slot->attr = attributes->core; + /* This is awkward... Copying the attributes has overwritten the + * flag that marks this slot as used. Restore it. */ + psa_key_slot_set_bits_in_flags( slot, PSA_KEY_SLOT_FLAG_ALLOCATED ); #if defined(MBEDTLS_PSA_CRYPTO_SE_C) /* For a key in a secure element, we need to do three things: @@ -1571,9 +1556,6 @@ static psa_status_t psa_finish_key_creation( #if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) if( slot->attr.lifetime != PSA_KEY_LIFETIME_VOLATILE ) { - psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; - psa_get_key_slot_attributes( slot, &attributes ); - #if defined(MBEDTLS_PSA_CRYPTO_SE_C) if( driver != NULL ) { @@ -1589,7 +1571,7 @@ static psa_status_t psa_finish_key_creation( sizeof( slot->data.se.slot_number ) ); memcpy( &data.bits, &slot->attr.bits, sizeof( slot->attr.bits ) ); - status = psa_save_persistent_key( &attributes.core, + status = psa_save_persistent_key( &slot->attr, (uint8_t*) &data, sizeof( data ) ); } @@ -1598,7 +1580,7 @@ static psa_status_t psa_finish_key_creation( { size_t buffer_size = PSA_KEY_EXPORT_MAX_SIZE( slot->attr.type, - psa_get_key_bits( &attributes ) ); + slot->attr.bits ); uint8_t *buffer = mbedtls_calloc( 1, buffer_size ); size_t length = 0; if( buffer == NULL && buffer_size != 0 ) @@ -1607,7 +1589,7 @@ static psa_status_t psa_finish_key_creation( buffer, buffer_size, &length, 0 ); if( status == PSA_SUCCESS ) - status = psa_save_persistent_key( &attributes.core, + status = psa_save_persistent_key( &slot->attr, buffer, length ); if( buffer_size != 0 ) From 41e50d26eac2fefff81c374731c53838480d598b Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Wed, 31 Jul 2019 15:01:55 +0200 Subject: [PATCH 09/20] Remove "allocated" flag from key slots The flag to mark key slots as allocated was introduced to mark slots that are claimed and in use, but do not have key material yet, at a time when creating a key used several API functions: allocate a slot, then progressively set its metadata, and finally create the key material. Now that all of these steps are combined into a single API function call, the notion of allocated-but-not-filled slot is no longer relevant. So remove the corresponding flag. A slot is occupied iff there is a key in it. (For a key in a secure element, the key material is not present, but the slot contains the key metadata.) This key must have a type which is nonzero, so use this as an indicator that a slot is in use. --- library/psa_crypto.c | 5 ----- library/psa_crypto_core.h | 16 +++++++++++++--- library/psa_crypto_slot_management.c | 19 ++++++------------- library/psa_crypto_slot_management.h | 10 +++++----- 4 files changed, 24 insertions(+), 26 deletions(-) diff --git a/library/psa_crypto.c b/library/psa_crypto.c index cb8054681..f1ddb147e 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -897,8 +897,6 @@ static psa_status_t psa_get_key_from_slot( psa_key_handle_t handle, status = psa_get_key_slot( handle, &slot ); if( status != PSA_SUCCESS ) return( status ); - if( slot->attr.type == PSA_KEY_TYPE_NONE ) - return( PSA_ERROR_DOES_NOT_EXIST ); /* Enforce that usage policy for the key slot contains all the flags * required by the usage parameter. There is one exception: public @@ -1488,9 +1486,6 @@ static psa_status_t psa_start_key_creation( * is optional (import, copy). */ slot->attr = attributes->core; - /* This is awkward... Copying the attributes has overwritten the - * flag that marks this slot as used. Restore it. */ - psa_key_slot_set_bits_in_flags( slot, PSA_KEY_SLOT_FLAG_ALLOCATED ); #if defined(MBEDTLS_PSA_CRYPTO_SE_C) /* For a key in a secure element, we need to do three things: diff --git a/library/psa_crypto_core.h b/library/psa_crypto_core.h index 1ae298e5f..fbfb6daef 100644 --- a/library/psa_crypto_core.h +++ b/library/psa_crypto_core.h @@ -64,9 +64,19 @@ typedef struct } data; } psa_key_slot_t; -/** Flag for psa_key_slot_t::attr::core::flags indicating that the - * slot is in use. */ -#define PSA_KEY_SLOT_FLAG_ALLOCATED ( (uint16_t) 0x0001 ) +/** Test whether a key slot is occupied. + * + * A key slot is occupied iff the key type is nonzero. This works because + * no valid key can have 0 as its key type. + * + * \param[in] slot The key slot to test. + * + * \return 1 if the slot is occupied, 0 otherwise. + */ +static inline int psa_is_key_slot_occupied( const psa_key_slot_t *slot ) +{ + return( slot->attr.type != 0 ); +} /** Retrieve flags from psa_key_slot_t::attr::core::flags. * diff --git a/library/psa_crypto_slot_management.c b/library/psa_crypto_slot_management.c index 43ba4123c..073400988 100644 --- a/library/psa_crypto_slot_management.c +++ b/library/psa_crypto_slot_management.c @@ -74,8 +74,8 @@ psa_status_t psa_get_key_slot( psa_key_handle_t handle, return( PSA_ERROR_INVALID_HANDLE ); slot = &global_data.key_slots[handle - 1]; - /* If the slot hasn't been allocated, the handle is invalid. */ - if( ! psa_key_slot_get_flags( slot, PSA_KEY_SLOT_FLAG_ALLOCATED ) ) + /* If the slot isn't occupied, the handle is invalid. */ + if( ! psa_is_key_slot_occupied( slot ) ) return( PSA_ERROR_INVALID_HANDLE ); *p_slot = slot; @@ -111,12 +111,8 @@ psa_status_t psa_internal_allocate_key_slot( psa_key_handle_t *handle, for( *handle = PSA_KEY_SLOT_COUNT; *handle != 0; --( *handle ) ) { *p_slot = &global_data.key_slots[*handle - 1]; - if( ! psa_key_slot_get_flags( *p_slot, PSA_KEY_SLOT_FLAG_ALLOCATED ) ) - { - psa_key_slot_set_bits_in_flags( *p_slot, - PSA_KEY_SLOT_FLAG_ALLOCATED ); + if( ! psa_is_key_slot_occupied( *p_slot ) ) return( PSA_SUCCESS ); - } } *p_slot = NULL; return( PSA_ERROR_INSUFFICIENT_MEMORY ); @@ -272,13 +268,10 @@ void mbedtls_psa_get_stats( mbedtls_psa_stats_t *stats ) memset( stats, 0, sizeof( *stats ) ); for( key = 1; key <= PSA_KEY_SLOT_COUNT; key++ ) { - psa_key_slot_t *slot = &global_data.key_slots[key - 1]; - if( slot->attr.type == PSA_KEY_TYPE_NONE ) + const psa_key_slot_t *slot = &global_data.key_slots[key - 1]; + if( ! psa_is_key_slot_occupied( slot ) ) { - if( psa_key_slot_get_flags( slot, PSA_KEY_SLOT_FLAG_ALLOCATED ) ) - ++stats->half_filled_slots; - else - ++stats->empty_slots; + ++stats->empty_slots; continue; } if( slot->attr.lifetime == PSA_KEY_LIFETIME_VOLATILE ) diff --git a/library/psa_crypto_slot_management.h b/library/psa_crypto_slot_management.h index 049520d4b..cde590fc5 100644 --- a/library/psa_crypto_slot_management.h +++ b/library/psa_crypto_slot_management.h @@ -58,13 +58,13 @@ psa_status_t psa_initialize_key_slots( void ); * This does not affect persistent storage. */ void psa_wipe_all_key_slots( void ); -/** Find a free key slot and mark it as in use. +/** Find a free key slot. + * + * This function returns a key slot that is available for use and is in its + * ground state (all-bits-zero). * * \param[out] handle On success, a slot number that can be used as a - * handle to the slot. The selected slot was not - * in use before. This function marks it as in use - * and otherwise leaves it in a freshly-initialized - * state. + * handle to the slot. * \param[out] p_slot On success, a pointer to the slot. * * \retval #PSA_SUCCESS From 7c227aee5ee53e7b99dfc795a76f4898b8425879 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Wed, 31 Jul 2019 15:14:44 +0200 Subject: [PATCH 10/20] Test key creation with an invalid type (0 and nonzero) --- tests/suites/test_suite_psa_crypto.data | 21 +++++++++++++++++++-- tests/suites/test_suite_psa_crypto.function | 11 ++++++----- 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/tests/suites/test_suite_psa_crypto.data b/tests/suites/test_suite_psa_crypto.data index a0e7f7a90..53aa41a6b 100644 --- a/tests/suites/test_suite_psa_crypto.data +++ b/tests/suites/test_suite_psa_crypto.data @@ -52,6 +52,12 @@ invalid_handle:1 PSA invalid handle (largest plausible handle) invalid_handle:-1 +PSA import: invalid type (0) +import:"0123":PSA_KEY_TYPE_NONE:0:PSA_ERROR_NOT_SUPPORTED + +PSA import: invalid type (PSA_KEY_TYPE_CATEGORY_MASK) +import:"0123":PSA_KEY_TYPE_CATEGORY_MASK:0:PSA_ERROR_NOT_SUPPORTED + PSA import AES: bad key size depends_on:MBEDTLS_AES_C import:"0123456789abcdef":PSA_KEY_TYPE_AES:0:PSA_ERROR_INVALID_ARGUMENT @@ -2083,16 +2089,24 @@ PSA key derivation: TLS 1.2 PRF SHA-256, derive key export, 1+41 depends_on:MBEDTLS_MD_C:MBEDTLS_SHA256_C:!PSA_PRE_1_0_KEY_DERIVATION derive_key_export:PSA_ALG_TLS12_PRF(PSA_ALG_SHA_256):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":1:41 +PSA key derivation: invalid type (0) +depends_on:MBEDTLS_MD_C:MBEDTLS_SHA256_C:!PSA_PRE_1_0_KEY_DERIVATION +derive_key:PSA_ALG_HKDF(PSA_ALG_SHA_256):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":PSA_KEY_TYPE_NONE:128:PSA_ERROR_NOT_SUPPORTED + +PSA key derivation: invalid type (PSA_KEY_TYPE_CATEGORY_MASK) +depends_on:MBEDTLS_MD_C:MBEDTLS_SHA256_C:!PSA_PRE_1_0_KEY_DERIVATION +derive_key:PSA_ALG_HKDF(PSA_ALG_SHA_256):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":PSA_KEY_TYPE_CATEGORY_MASK:128:PSA_ERROR_NOT_SUPPORTED + # This test assumes that PSA_MAX_KEY_BITS (currently 65536-8 bits = 8191 bytes # and not expected to be raised any time soon) is less than the maximum # output from HKDF-SHA512 (255*64 = 16320 bytes). PSA key derivation: largest possible key depends_on:MBEDTLS_MD_C:MBEDTLS_SHA512_C:!PSA_PRE_1_0_KEY_DERIVATION -derive_large_key:PSA_ALG_HKDF(PSA_ALG_SHA_512):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":PSA_MAX_KEY_BITS:PSA_SUCCESS +derive_key:PSA_ALG_HKDF(PSA_ALG_SHA_512):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":PSA_KEY_TYPE_RAW_DATA:PSA_MAX_KEY_BITS:PSA_SUCCESS PSA key derivation: key too large depends_on:MBEDTLS_MD_C:MBEDTLS_SHA512_C:!PSA_PRE_1_0_KEY_DERIVATION -derive_large_key:PSA_ALG_HKDF(PSA_ALG_SHA_512):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":PSA_MAX_KEY_BITS + 1:PSA_ERROR_NOT_SUPPORTED +derive_key:PSA_ALG_HKDF(PSA_ALG_SHA_512):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":PSA_KEY_TYPE_RAW_DATA:PSA_MAX_KEY_BITS + 1:PSA_ERROR_NOT_SUPPORTED PSA key agreement setup: ECDH + HKDF-SHA-256: good depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECDH_C:MBEDTLS_MD_C:MBEDTLS_SHA256_C @@ -2192,6 +2206,9 @@ generate_random:19 PSA generate random: 260 bytes generate_random:260 +PSA generate key: bad type (0) +generate_key:PSA_KEY_TYPE_NONE:128:PSA_KEY_USAGE_EXPORT:0:PSA_ERROR_NOT_SUPPORTED + PSA generate key: bad type (PSA_KEY_TYPE_CATEGORY_MASK) generate_key:PSA_KEY_TYPE_CATEGORY_MASK:128:PSA_KEY_USAGE_EXPORT:0:PSA_ERROR_NOT_SUPPORTED diff --git a/tests/suites/test_suite_psa_crypto.function b/tests/suites/test_suite_psa_crypto.function index 8ed7a7d5c..60514f854 100644 --- a/tests/suites/test_suite_psa_crypto.function +++ b/tests/suites/test_suite_psa_crypto.function @@ -4620,14 +4620,15 @@ exit: /* END_CASE */ /* BEGIN_CASE */ -void derive_large_key( int alg_arg, - data_t *key_data, data_t *input1, data_t *input2, - int bits_arg, - int expected_status_arg ) +void derive_key( int alg_arg, + data_t *key_data, data_t *input1, data_t *input2, + int type_arg, int bits_arg, + int expected_status_arg ) { psa_key_handle_t base_handle = 0; psa_key_handle_t derived_handle = 0; psa_algorithm_t alg = alg_arg; + psa_key_type_t type = type_arg; size_t bits = bits_arg; psa_status_t expected_status = expected_status_arg; psa_key_derivation_operation_t operation = PSA_KEY_DERIVATION_OPERATION_INIT; @@ -4649,7 +4650,7 @@ void derive_large_key( int alg_arg, psa_set_key_usage_flags( &derived_attributes, PSA_KEY_USAGE_EXPORT ); psa_set_key_algorithm( &derived_attributes, 0 ); - psa_set_key_type( &derived_attributes, PSA_KEY_TYPE_RAW_DATA ); + psa_set_key_type( &derived_attributes, type ); psa_set_key_bits( &derived_attributes, bits ); TEST_EQUAL( psa_key_derivation_output_key( &derived_attributes, &operation, &derived_handle ), From 6edfa293c2b638a19a0b10a360ae5c1a1431a3c1 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Wed, 31 Jul 2019 15:53:45 +0200 Subject: [PATCH 11/20] Add test function for import with a bad policy --- tests/suites/test_suite_psa_crypto.data | 50 ++++++++++----------- tests/suites/test_suite_psa_crypto.function | 50 +++++++++++++++++++-- 2 files changed, 72 insertions(+), 28 deletions(-) diff --git a/tests/suites/test_suite_psa_crypto.data b/tests/suites/test_suite_psa_crypto.data index 53aa41a6b..9bf2290f2 100644 --- a/tests/suites/test_suite_psa_crypto.data +++ b/tests/suites/test_suite_psa_crypto.data @@ -53,14 +53,14 @@ PSA invalid handle (largest plausible handle) invalid_handle:-1 PSA import: invalid type (0) -import:"0123":PSA_KEY_TYPE_NONE:0:PSA_ERROR_NOT_SUPPORTED +import_with_policy:PSA_KEY_TYPE_NONE:0:0:PSA_ERROR_NOT_SUPPORTED PSA import: invalid type (PSA_KEY_TYPE_CATEGORY_MASK) -import:"0123":PSA_KEY_TYPE_CATEGORY_MASK:0:PSA_ERROR_NOT_SUPPORTED +import_with_policy:PSA_KEY_TYPE_CATEGORY_MASK:0:0:PSA_ERROR_NOT_SUPPORTED PSA import AES: bad key size depends_on:MBEDTLS_AES_C -import:"0123456789abcdef":PSA_KEY_TYPE_AES:0:PSA_ERROR_INVALID_ARGUMENT +import_with_data:"0123456789abcdef":PSA_KEY_TYPE_AES:0:PSA_ERROR_INVALID_ARGUMENT PSA import/export RSA public key: good, 1024-bit depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_RSA_C @@ -116,19 +116,19 @@ import_export:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa24 PSA import RSA keypair: truncated depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C -import:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b":PSA_KEY_TYPE_RSA_KEY_PAIR:0:PSA_ERROR_INVALID_ARGUMENT +import_with_data:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b":PSA_KEY_TYPE_RSA_KEY_PAIR:0:PSA_ERROR_INVALID_ARGUMENT PSA import RSA keypair: public key depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C -import:"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_KEY_TYPE_RSA_KEY_PAIR:0:PSA_ERROR_INVALID_ARGUMENT +import_with_data:"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_KEY_TYPE_RSA_KEY_PAIR:0:PSA_ERROR_INVALID_ARGUMENT PSA import RSA public key: key pair depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C -import:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b":PSA_KEY_TYPE_RSA_PUBLIC_KEY:0:PSA_ERROR_INVALID_ARGUMENT +import_with_data:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b":PSA_KEY_TYPE_RSA_PUBLIC_KEY:0:PSA_ERROR_INVALID_ARGUMENT PSA import RSA keypair: valid key but EC depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C -import:"3077020101042049c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eeea00a06082a8648ce3d030107a144034200047772656f814b399279d5e1f1781fac6f099a3c5ca1b0e35351834b08b65e0b572590cdaf8f769361bcf34acfc11e5e074e8426bdde04be6e653945449617de45":PSA_KEY_TYPE_RSA_KEY_PAIR:0:PSA_ERROR_INVALID_ARGUMENT +import_with_data:"3077020101042049c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eeea00a06082a8648ce3d030107a144034200047772656f814b399279d5e1f1781fac6f099a3c5ca1b0e35351834b08b65e0b572590cdaf8f769361bcf34acfc11e5e074e8426bdde04be6e653945449617de45":PSA_KEY_TYPE_RSA_KEY_PAIR:0:PSA_ERROR_INVALID_ARGUMENT PSA import/export-public RSA public key: good, 1024-bit depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_RSA_C @@ -156,19 +156,19 @@ import_export:"3082025802010002818000cde684f1aee96917b89c8a0a72523cfce4686ed5a5f PSA import RSA public key: 1022-bit (not supported) depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_RSA_C -import:"30818802818036e4b95f847dcd7a91b0972b7ba096e040ec04e42d59f733029fb2600b8ae9e4fd8ea76f3d7ec576288102285b612db7abc53770006046fef321172a6ad84053710d48528a8d51b6481db53c09e1524d6704b58bd30313016535eefe9bcff89eb599608daaa0a72ab7720af31486b51020421fdd3c6974cc445a78dd134450230203010001":PSA_KEY_TYPE_RSA_PUBLIC_KEY:0:PSA_ERROR_NOT_SUPPORTED +import_with_data:"30818802818036e4b95f847dcd7a91b0972b7ba096e040ec04e42d59f733029fb2600b8ae9e4fd8ea76f3d7ec576288102285b612db7abc53770006046fef321172a6ad84053710d48528a8d51b6481db53c09e1524d6704b58bd30313016535eefe9bcff89eb599608daaa0a72ab7720af31486b51020421fdd3c6974cc445a78dd134450230203010001":PSA_KEY_TYPE_RSA_PUBLIC_KEY:0:PSA_ERROR_NOT_SUPPORTED PSA import RSA keypair: 1022-bit (not supported) depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_RSA_C -import:"3082025802010002818036e4b95f847dcd7a91b0972b7ba096e040ec04e42d59f733029fb2600b8ae9e4fd8ea76f3d7ec576288102285b612db7abc53770006046fef321172a6ad84053710d48528a8d51b6481db53c09e1524d6704b58bd30313016535eefe9bcff89eb599608daaa0a72ab7720af31486b51020421fdd3c6974cc445a78dd1344502302030100010281800ad9700e01e8bf68ff4c90c4465dfa13fea0e76295d817349ccb257d382acf89b3d7b31e18606af4ac92baf3710426fe0b54225ddfa527c31218b3346e03a9cae5395a780ade880b996f4061fad65689393fc8e77f46a4c1a29b0450cdaaef0710e523cd1028abe1653d23f0d5ec805a629bdf1fc4c1c00737760e1714f6b7f102407d5e545484b546bd61972b446a04af0cf17b126a8872b977da5035ca82dd0e4fef1381a6480f60db07628348602f86ba89a271563d9a3fb613b9b39703498f9902407017641093065eed178ff848b5f8a2b502a187511db28549ea7646f3e7b3ea171f4c34c0ecf0566adc4d172c057be077a45fcf8019a36a4588c4de3b8c0a631b02407cc7fccbbae2eb2be80c9c8615b7dfbbd4469907ec13b44274cacd1f69ad38679b2021352e18106131327e54f5579893e6160714bd6fdfe60c30136e45595c51024055250f779f96f94873db82a808c24325e847b6b8212cd81e9ba118a8715ab2f8b96773b310c8477c88b76e609c11cb22569408d4afa4f836b57b85ac09e661fd02400e5fc5df9614c95d77e9bc2df63d48e7a08a0034174f0f745eef4413ee36d929f194557e6990e148b7438e949a41e92bc9d9136c3e6563904151a578a2f4fc1b":PSA_KEY_TYPE_RSA_KEY_PAIR:0:PSA_ERROR_NOT_SUPPORTED +import_with_data:"3082025802010002818036e4b95f847dcd7a91b0972b7ba096e040ec04e42d59f733029fb2600b8ae9e4fd8ea76f3d7ec576288102285b612db7abc53770006046fef321172a6ad84053710d48528a8d51b6481db53c09e1524d6704b58bd30313016535eefe9bcff89eb599608daaa0a72ab7720af31486b51020421fdd3c6974cc445a78dd1344502302030100010281800ad9700e01e8bf68ff4c90c4465dfa13fea0e76295d817349ccb257d382acf89b3d7b31e18606af4ac92baf3710426fe0b54225ddfa527c31218b3346e03a9cae5395a780ade880b996f4061fad65689393fc8e77f46a4c1a29b0450cdaaef0710e523cd1028abe1653d23f0d5ec805a629bdf1fc4c1c00737760e1714f6b7f102407d5e545484b546bd61972b446a04af0cf17b126a8872b977da5035ca82dd0e4fef1381a6480f60db07628348602f86ba89a271563d9a3fb613b9b39703498f9902407017641093065eed178ff848b5f8a2b502a187511db28549ea7646f3e7b3ea171f4c34c0ecf0566adc4d172c057be077a45fcf8019a36a4588c4de3b8c0a631b02407cc7fccbbae2eb2be80c9c8615b7dfbbd4469907ec13b44274cacd1f69ad38679b2021352e18106131327e54f5579893e6160714bd6fdfe60c30136e45595c51024055250f779f96f94873db82a808c24325e847b6b8212cd81e9ba118a8715ab2f8b96773b310c8477c88b76e609c11cb22569408d4afa4f836b57b85ac09e661fd02400e5fc5df9614c95d77e9bc2df63d48e7a08a0034174f0f745eef4413ee36d929f194557e6990e148b7438e949a41e92bc9d9136c3e6563904151a578a2f4fc1b":PSA_KEY_TYPE_RSA_KEY_PAIR:0:PSA_ERROR_NOT_SUPPORTED PSA import RSA public key: 1023-bit (not supported) depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_RSA_C -import:"3081880281806c49704e91f3df44fc99e9b3c0fee5025cc04d09529a1dd05754f2da2751d7a9aa5a79f7070132f2c47b31963e37cd74675f9c93ee7c85a143fefe303e94d1ee0e4d30898d17ab3a229e8457ef21fd179039f748305babe7f134f6d58ce5d721a1a5da98f63503d2466c6a515e53494a41180a91e535bd5b55d4dce2c17419870203010001":PSA_KEY_TYPE_RSA_PUBLIC_KEY:0:PSA_ERROR_NOT_SUPPORTED +import_with_data:"3081880281806c49704e91f3df44fc99e9b3c0fee5025cc04d09529a1dd05754f2da2751d7a9aa5a79f7070132f2c47b31963e37cd74675f9c93ee7c85a143fefe303e94d1ee0e4d30898d17ab3a229e8457ef21fd179039f748305babe7f134f6d58ce5d721a1a5da98f63503d2466c6a515e53494a41180a91e535bd5b55d4dce2c17419870203010001":PSA_KEY_TYPE_RSA_PUBLIC_KEY:0:PSA_ERROR_NOT_SUPPORTED PSA import RSA keypair: 1023-bit (not supported) depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_RSA_C -import:"3082025a0201000281806c49704e91f3df44fc99e9b3c0fee5025cc04d09529a1dd05754f2da2751d7a9aa5a79f7070132f2c47b31963e37cd74675f9c93ee7c85a143fefe303e94d1ee0e4d30898d17ab3a229e8457ef21fd179039f748305babe7f134f6d58ce5d721a1a5da98f63503d2466c6a515e53494a41180a91e535bd5b55d4dce2c17419870203010001028180491b277413fb35efe82dace68b544a9dd6aa8917d329731955ec66ec3b0178fcf5a29196e1a6c093bf6c8064b36a8f0d9840a78003d11392754a70a77788975515a1442a6c806cafa2f07fe99cac78a86fa868888d654cec4baf205352cf8255acaa47e2455f23b58c0e5ae43fa297bbffe5b970caa80f71e82084fd35425479024100ef27f3fb2df90ac4910ed95fdde4877d09b0dc4e95079f12a7e2041300a8884a39372a1c79691338cd5c3965bcf3a24f2ce9e10de19d4cb87c7546d60ca0aa0d024073e9e1283475e9ab3075da0b005ca7c7b05e76325f8deb648238831c8353041d594307f784cd527cfee9187b997713d71c0ff98f01beac4d1a85583be52e90e302402f0c801e311c2677274671933f96fee4a56c6adaf6ccaa09c4875d5fd3a8542fadf3e14ffabea62e6d90302688b6b17ebc0a42e1353a79e66d6db102d9371e5d02406731ef3c8607fbf266806590a9cfd3a79a435ee355e2d9906fc6b4236c5f3a288ed178844a7d295512f49ed15b3d82325e4f729478af3262aa9bd083f273d49502410090a32c0e8ca3bcd4c66f092cdc369cd1abb4a05b9a6f0e65e5a51da1d96d5aca8c1525b3f11322c0588062fc8592ebf25b7950f918d39018e82b8acccc8f7e7a":PSA_KEY_TYPE_RSA_KEY_PAIR:0:PSA_ERROR_NOT_SUPPORTED +import_with_data:"3082025a0201000281806c49704e91f3df44fc99e9b3c0fee5025cc04d09529a1dd05754f2da2751d7a9aa5a79f7070132f2c47b31963e37cd74675f9c93ee7c85a143fefe303e94d1ee0e4d30898d17ab3a229e8457ef21fd179039f748305babe7f134f6d58ce5d721a1a5da98f63503d2466c6a515e53494a41180a91e535bd5b55d4dce2c17419870203010001028180491b277413fb35efe82dace68b544a9dd6aa8917d329731955ec66ec3b0178fcf5a29196e1a6c093bf6c8064b36a8f0d9840a78003d11392754a70a77788975515a1442a6c806cafa2f07fe99cac78a86fa868888d654cec4baf205352cf8255acaa47e2455f23b58c0e5ae43fa297bbffe5b970caa80f71e82084fd35425479024100ef27f3fb2df90ac4910ed95fdde4877d09b0dc4e95079f12a7e2041300a8884a39372a1c79691338cd5c3965bcf3a24f2ce9e10de19d4cb87c7546d60ca0aa0d024073e9e1283475e9ab3075da0b005ca7c7b05e76325f8deb648238831c8353041d594307f784cd527cfee9187b997713d71c0ff98f01beac4d1a85583be52e90e302402f0c801e311c2677274671933f96fee4a56c6adaf6ccaa09c4875d5fd3a8542fadf3e14ffabea62e6d90302688b6b17ebc0a42e1353a79e66d6db102d9371e5d02406731ef3c8607fbf266806590a9cfd3a79a435ee355e2d9906fc6b4236c5f3a288ed178844a7d295512f49ed15b3d82325e4f729478af3262aa9bd083f273d49502410090a32c0e8ca3bcd4c66f092cdc369cd1abb4a05b9a6f0e65e5a51da1d96d5aca8c1525b3f11322c0588062fc8592ebf25b7950f918d39018e82b8acccc8f7e7a":PSA_KEY_TYPE_RSA_KEY_PAIR:0:PSA_ERROR_NOT_SUPPORTED PSA import/export EC secp224r1 key pair: good depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP224R1_ENABLED @@ -262,31 +262,31 @@ import_export:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa24 PSA import EC keypair: DER format depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED -import:"3077020101042049c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eeea00a06082a8648ce3d030107a144034200047772656f814b399279d5e1f1781fac6f099a3c5ca1b0e35351834b08b65e0b572590cdaf8f769361bcf34acfc11e5e074e8426bdde04be6e653945449617de45":PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_CURVE_SECP256R1):0:PSA_ERROR_INVALID_ARGUMENT +import_with_data:"3077020101042049c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eeea00a06082a8648ce3d030107a144034200047772656f814b399279d5e1f1781fac6f099a3c5ca1b0e35351834b08b65e0b572590cdaf8f769361bcf34acfc11e5e074e8426bdde04be6e653945449617de45":PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_CURVE_SECP256R1):0:PSA_ERROR_INVALID_ARGUMENT PSA import EC keypair: too short depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED -import:"0123456789abcdef0123456789abcdef":PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_CURVE_SECP256R1):0:PSA_ERROR_INVALID_ARGUMENT +import_with_data:"0123456789abcdef0123456789abcdef":PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_CURVE_SECP256R1):0:PSA_ERROR_INVALID_ARGUMENT PSA import EC keypair: public key depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED -import:"04dea5e45d0ea37fc566232a508f4ad20ea13d47e4bf5fa4d54a57a0ba012042087097496efc583fed8b24a5b9be9a51de063f5a00a8b698a16fd7f29b5485f320":PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_CURVE_SECP256R1):0:PSA_ERROR_INVALID_ARGUMENT +import_with_data:"04dea5e45d0ea37fc566232a508f4ad20ea13d47e4bf5fa4d54a57a0ba012042087097496efc583fed8b24a5b9be9a51de063f5a00a8b698a16fd7f29b5485f320":PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_CURVE_SECP256R1):0:PSA_ERROR_INVALID_ARGUMENT PSA import EC keypair: secp256r1, all-bits-zero (bad) depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED -import:"0000000000000000000000000000000000000000000000000000000000000000":PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_CURVE_SECP256R1):0:PSA_ERROR_INVALID_ARGUMENT +import_with_data:"0000000000000000000000000000000000000000000000000000000000000000":PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_CURVE_SECP256R1):0:PSA_ERROR_INVALID_ARGUMENT PSA import EC keypair: secp256r1, d == n - 1 (good) depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED -import:"ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632550":PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_CURVE_SECP256R1):0:PSA_SUCCESS +import_with_data:"ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632550":PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_CURVE_SECP256R1):0:PSA_SUCCESS PSA import EC keypair: secp256r1, d == n (bad) depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED -import:"ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551":PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_CURVE_SECP256R1):0:PSA_ERROR_INVALID_ARGUMENT +import_with_data:"ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551":PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_CURVE_SECP256R1):0:PSA_ERROR_INVALID_ARGUMENT PSA import EC keypair: secp256r1, d > n (bad) depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED -import:"ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632552":PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_CURVE_SECP256R1):0:PSA_ERROR_INVALID_ARGUMENT +import_with_data:"ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632552":PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_CURVE_SECP256R1):0:PSA_ERROR_INVALID_ARGUMENT PSA import EC public key: key pair depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED @@ -294,31 +294,31 @@ depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED # one would expect the status to be PSA_ERROR_INVALID_ARGUMENT. But the # Mbed TLS pkparse module returns MBEDTLS_ERR_PK_INVALID_ALG, I think because # it's looking for an OID where there is no OID. -import:"3078020101042100ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3aa00a06082a8648ce3d030107a14403420004dea5e45d0ea37fc566232a508f4ad20ea13d47e4bf5fa4d54a57a0ba012042087097496efc583fed8b24a5b9be9a51de063f5a00a8b698a16fd7f29b5485f320":PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_CURVE_SECP256R1):0:PSA_ERROR_NOT_SUPPORTED +import_with_data:"3078020101042100ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3aa00a06082a8648ce3d030107a14403420004dea5e45d0ea37fc566232a508f4ad20ea13d47e4bf5fa4d54a57a0ba012042087097496efc583fed8b24a5b9be9a51de063f5a00a8b698a16fd7f29b5485f320":PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_CURVE_SECP256R1):0:PSA_ERROR_NOT_SUPPORTED PSA import EC keypair: valid key but RSA depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_BP512R1_ENABLED:MBEDTLS_RSA_C -import:"3082013b020100024100ee2b131d6b1818a94ca8e91c42387eb15a7c271f57b89e7336b144d4535b16c83097ecdefbbb92d1b5313b5a37214d0e8f25922dca778b424b25295fc8a1a7070203010001024100978ac8eadb0dc6035347d6aba8671215ff21283385396f7897c04baf5e2a835f3b53ef80a82ed36ae687a925380b55a0c73eb85656e989dcf0ed7fb4887024e1022100fdad8e1c6853563f8b921d2d112462ae7d6b176082d2ba43e87e1a37fc1a8b33022100f0592cf4c55ba44307b18981bcdbda376c51e590ffa5345ba866f6962dca94dd02201995f1a967d44ff4a4cd1de837bc65bf97a2bf7eda730a9a62cea53254591105022027f96cf4b8ee68ff8d04062ec1ce7f18c0b74e4b3379b29f9bfea3fc8e592731022100cefa6d220496b43feb83194255d8fb930afcf46f36606e3aa0eb7a93ad88c10c":PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_CURVE_BRAINPOOL_P512R1):0:PSA_ERROR_INVALID_ARGUMENT +import_with_data:"3082013b020100024100ee2b131d6b1818a94ca8e91c42387eb15a7c271f57b89e7336b144d4535b16c83097ecdefbbb92d1b5313b5a37214d0e8f25922dca778b424b25295fc8a1a7070203010001024100978ac8eadb0dc6035347d6aba8671215ff21283385396f7897c04baf5e2a835f3b53ef80a82ed36ae687a925380b55a0c73eb85656e989dcf0ed7fb4887024e1022100fdad8e1c6853563f8b921d2d112462ae7d6b176082d2ba43e87e1a37fc1a8b33022100f0592cf4c55ba44307b18981bcdbda376c51e590ffa5345ba866f6962dca94dd02201995f1a967d44ff4a4cd1de837bc65bf97a2bf7eda730a9a62cea53254591105022027f96cf4b8ee68ff8d04062ec1ce7f18c0b74e4b3379b29f9bfea3fc8e592731022100cefa6d220496b43feb83194255d8fb930afcf46f36606e3aa0eb7a93ad88c10c":PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_CURVE_BRAINPOOL_P512R1):0:PSA_ERROR_INVALID_ARGUMENT PSA import AES: bits=0 ok depends_on:MBEDTLS_AES_C -import:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_KEY_TYPE_AES:0:PSA_SUCCESS +import_with_data:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_KEY_TYPE_AES:0:PSA_SUCCESS PSA import AES: bits=128 ok depends_on:MBEDTLS_AES_C -import:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_KEY_TYPE_AES:128:PSA_SUCCESS +import_with_data:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_KEY_TYPE_AES:128:PSA_SUCCESS PSA import AES: bits=256 wrong depends_on:MBEDTLS_AES_C -import:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_KEY_TYPE_AES:256:PSA_ERROR_INVALID_ARGUMENT +import_with_data:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_KEY_TYPE_AES:256:PSA_ERROR_INVALID_ARGUMENT PSA import AES: bits=256 ok depends_on:MBEDTLS_AES_C -import:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_KEY_TYPE_AES:256:PSA_SUCCESS +import_with_data:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_KEY_TYPE_AES:256:PSA_SUCCESS PSA import AES: bits=128 wrong depends_on:MBEDTLS_AES_C -import:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_KEY_TYPE_AES:128:PSA_ERROR_INVALID_ARGUMENT +import_with_data:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_KEY_TYPE_AES:128:PSA_ERROR_INVALID_ARGUMENT PSA import large key: raw, 65528 bits (ok) depends_on:HAVE_RAM_AVAILABLE_128k diff --git a/tests/suites/test_suite_psa_crypto.function b/tests/suites/test_suite_psa_crypto.function index 60514f854..f6447520e 100644 --- a/tests/suites/test_suite_psa_crypto.function +++ b/tests/suites/test_suite_psa_crypto.function @@ -1209,9 +1209,52 @@ void persistence_attributes( int id1_arg, int lifetime_arg, int id2_arg, /* END_CASE */ /* BEGIN_CASE */ -void import( data_t *data, int type_arg, - int attr_bits_arg, - int expected_status_arg ) +void import_with_policy( int type_arg, + int usage_arg, int alg_arg, + int expected_status_arg ) +{ + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_key_attributes_t got_attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_key_handle_t handle = 0; + psa_key_type_t type = type_arg; + psa_key_usage_t usage = usage_arg; + psa_algorithm_t alg = alg_arg; + psa_status_t expected_status = expected_status_arg; + const uint8_t key_material[16] = {0}; + psa_status_t status; + + PSA_ASSERT( psa_crypto_init( ) ); + + psa_set_key_type( &attributes, type ); + psa_set_key_usage_flags( &attributes, usage ); + psa_set_key_algorithm( &attributes, alg ); + + status = psa_import_key( &attributes, + key_material, sizeof( key_material ), + &handle ); + TEST_EQUAL( status, expected_status ); + if( status != PSA_SUCCESS ) + goto exit; + + PSA_ASSERT( psa_get_key_attributes( handle, &got_attributes ) ); + TEST_EQUAL( psa_get_key_type( &got_attributes ), type ); + TEST_EQUAL( psa_get_key_usage_flags( &got_attributes ), usage ); + TEST_EQUAL( psa_get_key_algorithm( &got_attributes ), alg ); + + PSA_ASSERT( psa_destroy_key( handle ) ); + test_operations_on_invalid_handle( handle ); + +exit: + psa_destroy_key( handle ); + psa_reset_key_attributes( &got_attributes ); + PSA_DONE( ); +} +/* END_CASE */ + +/* BEGIN_CASE */ +void import_with_data( data_t *data, int type_arg, + int attr_bits_arg, + int expected_status_arg ) { psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; psa_key_attributes_t got_attributes = PSA_KEY_ATTRIBUTES_INIT; @@ -1225,6 +1268,7 @@ void import( data_t *data, int type_arg, psa_set_key_type( &attributes, type ); psa_set_key_bits( &attributes, attr_bits ); + status = psa_import_key( &attributes, data->x, data->len, &handle ); TEST_EQUAL( status, expected_status ); if( status != PSA_SUCCESS ) From 3825e14e65186b26709876dc389d6630a192664e Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Wed, 31 Jul 2019 15:54:33 +0200 Subject: [PATCH 12/20] Fix policy validity check on key creation. Add a non-regression test. --- library/psa_crypto.c | 8 ++++---- tests/suites/test_suite_psa_crypto.data | 3 +++ 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/library/psa_crypto.c b/library/psa_crypto.c index f1ddb147e..258caad59 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -1469,10 +1469,6 @@ static psa_status_t psa_start_key_creation( return( status ); } - status = psa_check_key_slot_policy( slot ); - if( status != PSA_SUCCESS ) - return( status ); - /* Refuse to create overly large keys. * Note that this doesn't trigger on import if the attributes don't * explicitly specify a size (so psa_get_key_bits returns 0), so @@ -1487,6 +1483,10 @@ static psa_status_t psa_start_key_creation( slot->attr = attributes->core; + status = psa_check_key_slot_policy( slot ); + if( status != PSA_SUCCESS ) + return( status ); + #if defined(MBEDTLS_PSA_CRYPTO_SE_C) /* For a key in a secure element, we need to do three things: * create the key file in internal storage, create the diff --git a/tests/suites/test_suite_psa_crypto.data b/tests/suites/test_suite_psa_crypto.data index 9bf2290f2..e04fdf8b2 100644 --- a/tests/suites/test_suite_psa_crypto.data +++ b/tests/suites/test_suite_psa_crypto.data @@ -52,6 +52,9 @@ invalid_handle:1 PSA invalid handle (largest plausible handle) invalid_handle:-1 +PSA import: bad usage flag +import_with_policy:PSA_KEY_TYPE_RAW_DATA:0x40000000:0:PSA_ERROR_INVALID_ARGUMENT + PSA import: invalid type (0) import_with_policy:PSA_KEY_TYPE_NONE:0:0:PSA_ERROR_NOT_SUPPORTED From 1b8594a218c840248d81562e30e2dbc6610843f9 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Wed, 31 Jul 2019 17:21:46 +0200 Subject: [PATCH 13/20] More refactoring: consolidate attribute validation Consolidate attribute validation at the beginning of key creation into a single function. Improve comments. --- library/psa_crypto.c | 91 ++++++++++++++++++++++++++++++++------------ 1 file changed, 66 insertions(+), 25 deletions(-) diff --git a/library/psa_crypto.c b/library/psa_crypto.c index 258caad59..3f5f371f8 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -1403,10 +1403,14 @@ psa_status_t psa_export_public_key( psa_key_handle_t handle, data_length, 1 ) ); } -static psa_status_t psa_check_key_slot_policy( - const psa_key_slot_t *slot ) +/** Validate that a key policy is internally well-formed. + * + * This function only rejects invalid policies. It does not validate the + * consistency of the policy with respect to other attributes of the key + * such as the key type. + */ +static psa_status_t psa_validate_key_policy( const psa_key_policy_t *policy ) { - const psa_key_policy_t *policy = &slot->attr.policy; if( ( policy->usage & ~( PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_ENCRYPT | @@ -1419,6 +1423,48 @@ static psa_status_t psa_check_key_slot_policy( return( PSA_SUCCESS ); } +/** Validate the internal consistency of key attributes. + * + * This function only rejects invalid attribute values. If does not + * validate the consistency of the attributes with any key data that may + * be involved in the creation of the key. + * + * Call this function early in the key creation process. + * + * \param[in] attributes Key attributes for the new key. + * \param[out] p_drv On any return, the driver for the key, if any. + * NULL for a transparent key. + * + */ +static psa_status_t psa_validate_key_attributes( + const psa_key_attributes_t *attributes, + psa_se_drv_table_entry_t **p_drv ) +{ + psa_status_t status; + + if( attributes->core.lifetime != PSA_KEY_LIFETIME_VOLATILE ) + { + status = psa_validate_persistent_key_parameters( + attributes->core.lifetime, attributes->core.id, + p_drv, 1 ); + if( status != PSA_SUCCESS ) + return( status ); + } + + status = psa_validate_key_policy( &attributes->core.policy ); + if( status != PSA_SUCCESS ) + return( status ); + + /* Refuse to create overly large keys. + * Note that this doesn't trigger on import if the attributes don't + * explicitly specify a size (so psa_get_key_bits returns 0), so + * psa_import_key() needs its own checks. */ + if( psa_get_key_bits( attributes ) > PSA_MAX_KEY_BITS ) + return( PSA_ERROR_NOT_SUPPORTED ); + + return( PSA_SUCCESS ); +} + /** Prepare a key slot to receive key material. * * This function allocates a key slot and sets its metadata. @@ -1455,26 +1501,15 @@ static psa_status_t psa_start_key_creation( *p_drv = NULL; + status = psa_validate_key_attributes( attributes, p_drv ); + if( status != PSA_SUCCESS ) + return( status ); + status = psa_internal_allocate_key_slot( handle, p_slot ); if( status != PSA_SUCCESS ) return( status ); slot = *p_slot; - if( attributes->core.lifetime != PSA_KEY_LIFETIME_VOLATILE ) - { - status = psa_validate_persistent_key_parameters( attributes->core.lifetime, - attributes->core.id, - p_drv, 1 ); - if( status != PSA_SUCCESS ) - return( status ); - } - - /* Refuse to create overly large keys. - * Note that this doesn't trigger on import if the attributes don't - * explicitly specify a size (so psa_get_key_bits returns 0), so - * psa_import_key() needs its own checks. */ - if( psa_get_key_bits( attributes ) > PSA_MAX_KEY_BITS ) - return( PSA_ERROR_NOT_SUPPORTED ); /* We're storing the declared bit-size of the key. It's up to each * creation mechanism to verify that this information is correct. * It's automatically correct for mechanisms that use the bit-size as @@ -1483,10 +1518,6 @@ static psa_status_t psa_start_key_creation( slot->attr = attributes->core; - status = psa_check_key_slot_policy( slot ); - if( status != PSA_SUCCESS ) - return( status ); - #if defined(MBEDTLS_PSA_CRYPTO_SE_C) /* For a key in a secure element, we need to do three things: * create the key file in internal storage, create the @@ -1647,7 +1678,16 @@ static void psa_fail_key_creation( psa_key_slot_t *slot, psa_wipe_key_slot( slot ); } -static psa_status_t psa_check_key_slot_attributes( +/** Validate optional attributes during key creation. + * + * Some key attributes are optional during key creation. If they are + * specified in the attributes structure, check that they are consistent + * with the data in the slot. + * + * This function should be called near the end of key creation, after + * the slot in memory is fully populated but before saving persistent data. + */ +static psa_status_t psa_validate_optional_attributes( const psa_key_slot_t *slot, const psa_key_attributes_t *attributes ) { @@ -1746,7 +1786,7 @@ psa_status_t psa_import_key( const psa_key_attributes_t *attributes, if( status != PSA_SUCCESS ) goto exit; } - status = psa_check_key_slot_attributes( slot, attributes ); + status = psa_validate_optional_attributes( slot, attributes ); if( status != PSA_SUCCESS ) goto exit; @@ -1801,7 +1841,8 @@ psa_status_t psa_copy_key( psa_key_handle_t source_handle, if( status != PSA_SUCCESS ) goto exit; - status = psa_check_key_slot_attributes( source_slot, specified_attributes ); + status = psa_validate_optional_attributes( source_slot, + specified_attributes ); if( status != PSA_SUCCESS ) goto exit; From 8908c5e81c8bf2f109feef843bc2981de2f86cca Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Wed, 31 Jul 2019 18:55:00 +0200 Subject: [PATCH 14/20] Make psa_calculate_key_bits return psa_key_bits_t This is cleaner and solves a complaint from MSVC about truncation from size_t to psa_key_bits_t. --- library/psa_crypto.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/library/psa_crypto.c b/library/psa_crypto.c index 3f5f371f8..cbe326126 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -714,20 +714,24 @@ static inline size_t psa_get_key_slot_bits( const psa_key_slot_t *slot ) * * \return The key size in bits, calculated from the key data. */ -static size_t psa_calculate_key_bits( const psa_key_slot_t *slot ) +static psa_key_bits_t psa_calculate_key_bits( const psa_key_slot_t *slot ) { + size_t bits = 0; /* return 0 on an empty slot */ + if( key_type_is_raw_bytes( slot->attr.type ) ) - return( slot->data.raw.bytes * 8 ); + bits = PSA_BYTES_TO_BITS( slot->data.raw.bytes ); #if defined(MBEDTLS_RSA_C) - if( PSA_KEY_TYPE_IS_RSA( slot->attr.type ) ) - return( PSA_BYTES_TO_BITS( mbedtls_rsa_get_len( slot->data.rsa ) ) ); + else if( PSA_KEY_TYPE_IS_RSA( slot->attr.type ) ) + bits = PSA_BYTES_TO_BITS( mbedtls_rsa_get_len( slot->data.rsa ) ); #endif /* defined(MBEDTLS_RSA_C) */ #if defined(MBEDTLS_ECP_C) - if( PSA_KEY_TYPE_IS_ECC( slot->attr.type ) ) - return( slot->data.ecp->grp.pbits ); + else if( PSA_KEY_TYPE_IS_ECC( slot->attr.type ) ) + bits = slot->data.ecp->grp.pbits; #endif /* defined(MBEDTLS_ECP_C) */ - /* Shouldn't happen except on an empty slot. */ - return( 0 ); + + /* We know that the size fits in psa_key_bits_t thanks to checks + * when the key was created. */ + return( (psa_key_bits_t) bits ); } /** Import key data into a slot. `slot->attr.type` must have been set From 1b9505c451eaf8cd2eef93efaa9e734946bb97bd Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Wed, 7 Aug 2019 10:59:45 +0200 Subject: [PATCH 15/20] Correct some comments --- library/psa_crypto.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/library/psa_crypto.c b/library/psa_crypto.c index cbe326126..f01a4c084 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -746,10 +746,11 @@ psa_status_t psa_import_key_into_slot( psa_key_slot_t *slot, if( key_type_is_raw_bytes( slot->attr.type ) ) { size_t bit_size = PSA_BYTES_TO_BITS( data_length ); - /* Ensure that the bytes-to-bit conversion doesn't overflow. */ + /* Ensure that the bytes-to-bit conversion didn't overflow. */ if( data_length > SIZE_MAX / 8 ) return( PSA_ERROR_NOT_SUPPORTED ); - /* Ensure that the bit size fits in its representation type. */ + /* Enforce a size limit, and in particular ensure that the bit + * size fits in its representation type. */ if( bit_size > PSA_MAX_KEY_BITS ) return( PSA_ERROR_NOT_SUPPORTED ); status = prepare_raw_data_slot( slot->attr.type, bit_size, From 49232e8b0677cf699026d056a6d880547590a4b8 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Wed, 7 Aug 2019 11:01:30 +0200 Subject: [PATCH 16/20] Avoid a lowercase letter in a macro name --- tests/suites/test_suite_psa_crypto.data | 6 +++--- tests/suites/test_suite_psa_crypto.function | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/suites/test_suite_psa_crypto.data b/tests/suites/test_suite_psa_crypto.data index e04fdf8b2..c8d803864 100644 --- a/tests/suites/test_suite_psa_crypto.data +++ b/tests/suites/test_suite_psa_crypto.data @@ -324,11 +324,11 @@ depends_on:MBEDTLS_AES_C import_with_data:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_KEY_TYPE_AES:128:PSA_ERROR_INVALID_ARGUMENT PSA import large key: raw, 65528 bits (ok) -depends_on:HAVE_RAM_AVAILABLE_128k +depends_on:HAVE_RAM_AVAILABLE_128K import_large_key:PSA_KEY_TYPE_RAW_DATA:8191:PSA_SUCCESS PSA import large key: raw, 65536 bits (not supported) -depends_on:HAVE_RAM_AVAILABLE_128k +depends_on:HAVE_RAM_AVAILABLE_128K import_large_key:PSA_KEY_TYPE_RAW_DATA:8192:PSA_ERROR_NOT_SUPPORTED PSA import RSA key pair: maximum size exceeded @@ -2228,7 +2228,7 @@ PSA generate key: raw data, 8 bits generate_key:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0:PSA_SUCCESS PSA generate key: raw data, 65528 bits (ok) -depends_on:HAVE_RAM_AVAILABLE_128k +depends_on:HAVE_RAM_AVAILABLE_128K generate_key:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0:PSA_SUCCESS PSA generate key: raw data, 65536 bits (not supported) diff --git a/tests/suites/test_suite_psa_crypto.function b/tests/suites/test_suite_psa_crypto.function index f6447520e..69b49f35c 100644 --- a/tests/suites/test_suite_psa_crypto.function +++ b/tests/suites/test_suite_psa_crypto.function @@ -12,7 +12,7 @@ * are always executed. In the future we should make this conditional * so that tests that require a lot of memory are skipped on constrained * platforms. */ -#define HAVE_RAM_AVAILABLE_128k +#define HAVE_RAM_AVAILABLE_128K /** An invalid export length that will never be set by psa_export_key(). */ static const size_t INVALID_EXPORT_LENGTH = ~0U; From b1f6c5fd4d281c6d93600ff3601f7340ab79dfb5 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Wed, 7 Aug 2019 13:37:22 +0200 Subject: [PATCH 17/20] Fix copypasta in test data --- tests/suites/test_suite_psa_crypto.data | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/suites/test_suite_psa_crypto.data b/tests/suites/test_suite_psa_crypto.data index c8d803864..ccbffffbc 100644 --- a/tests/suites/test_suite_psa_crypto.data +++ b/tests/suites/test_suite_psa_crypto.data @@ -2229,7 +2229,7 @@ generate_key:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0:PSA_SUCCESS PSA generate key: raw data, 65528 bits (ok) depends_on:HAVE_RAM_AVAILABLE_128K -generate_key:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0:PSA_SUCCESS +generate_key:PSA_KEY_TYPE_RAW_DATA:65528:PSA_KEY_USAGE_EXPORT:0:PSA_SUCCESS PSA generate key: raw data, 65536 bits (not supported) generate_key:PSA_KEY_TYPE_RAW_DATA:65536:PSA_KEY_USAGE_EXPORT:0:PSA_ERROR_NOT_SUPPORTED From a6b2f60b4c2ce28991e2b5f1f860c901ab6f8ab8 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Wed, 7 Aug 2019 13:37:33 +0200 Subject: [PATCH 18/20] Fix double free in psa_generate_key when psa_generate_random fails When psa_generate_random fails, psa_generate_key_internal frees the key buffer but a the pointer to the now-freed buffer in the slot. Then psa_generate_key calls psa_fail_key_creation which sees the pointer and calls free() again. This bug was introduced by ff5f0e7221d54e5a11db13c5198093a6b6bf4d53 "Implement atomic-creation psa_{generate,generator_import}_key" which changed how psa_generate_key() cleans up on errors. I went through the code and could not find a similar bug in cleanup on an error during key creation. Fix #207 --- library/psa_crypto.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/library/psa_crypto.c b/library/psa_crypto.c index f01a4c084..c6bc7a267 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -5718,10 +5718,7 @@ static psa_status_t psa_generate_key_internal( status = psa_generate_random( slot->data.raw.data, slot->data.raw.bytes ); if( status != PSA_SUCCESS ) - { - mbedtls_free( slot->data.raw.data ); return( status ); - } #if defined(MBEDTLS_DES_C) if( type == PSA_KEY_TYPE_DES ) psa_des_set_key_parity( slot->data.raw.data, From bdc96fd636c71d4adf2034f09fe7097ee4573caa Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Wed, 7 Aug 2019 12:08:04 +0200 Subject: [PATCH 19/20] Add tests to generate more random than MBEDTLS_CTR_DRBG_MAX_REQUEST Add tests that call psa_generate_random() (possibly via psa_generate_key()) with a size that's larger than MBEDTLS_CTR_DRBG_MAX_REQUEST. This causes psa_generate_random() to fail because it calls mbedtls_ctr_drbg_random() without taking the maximum request size of CTR_DRBG into account. Non-regression test for #206 --- tests/suites/test_suite_psa_crypto.data | 15 +++++++++++++++ tests/suites/test_suite_psa_crypto.function | 6 ++++++ 2 files changed, 21 insertions(+) diff --git a/tests/suites/test_suite_psa_crypto.data b/tests/suites/test_suite_psa_crypto.data index ccbffffbc..b04984024 100644 --- a/tests/suites/test_suite_psa_crypto.data +++ b/tests/suites/test_suite_psa_crypto.data @@ -2209,6 +2209,15 @@ generate_random:19 PSA generate random: 260 bytes generate_random:260 +PSA generate random: MBEDTLS_CTR_DRBG_MAX_REQUEST bytes +generate_random:MBEDTLS_CTR_DRBG_MAX_REQUEST + +PSA generate random: MBEDTLS_CTR_DRBG_MAX_REQUEST+1 bytes +generate_random:MBEDTLS_CTR_DRBG_MAX_REQUEST + 1 + +PSA generate random: 2*MBEDTLS_CTR_DRBG_MAX_REQUEST+1 bytes +generate_random:2 * MBEDTLS_CTR_DRBG_MAX_REQUEST + 1 + PSA generate key: bad type (0) generate_key:PSA_KEY_TYPE_NONE:128:PSA_KEY_USAGE_EXPORT:0:PSA_ERROR_NOT_SUPPORTED @@ -2227,6 +2236,12 @@ generate_key:PSA_KEY_TYPE_RAW_DATA:7:PSA_KEY_USAGE_EXPORT:0:PSA_ERROR_INVALID_AR PSA generate key: raw data, 8 bits generate_key:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0:PSA_SUCCESS +PSA generate key: raw data, (MBEDTLS_CTR_DRBG_MAX_REQUEST + 1) * 8 bits +generate_key:PSA_KEY_TYPE_RAW_DATA:(MBEDTLS_CTR_DRBG_MAX_REQUEST + 1) * 8:PSA_KEY_USAGE_EXPORT:0:PSA_SUCCESS + +PSA generate key: raw data, (2 * MBEDTLS_CTR_DRBG_MAX_REQUEST + 1) * 8 bits +generate_key:PSA_KEY_TYPE_RAW_DATA:(2 * MBEDTLS_CTR_DRBG_MAX_REQUEST + 1) * 8:PSA_KEY_USAGE_EXPORT:0:PSA_SUCCESS + PSA generate key: raw data, 65528 bits (ok) depends_on:HAVE_RAM_AVAILABLE_128K generate_key:PSA_KEY_TYPE_RAW_DATA:65528:PSA_KEY_USAGE_EXPORT:0:PSA_SUCCESS diff --git a/tests/suites/test_suite_psa_crypto.function b/tests/suites/test_suite_psa_crypto.function index 69b49f35c..81ccb4ce3 100644 --- a/tests/suites/test_suite_psa_crypto.function +++ b/tests/suites/test_suite_psa_crypto.function @@ -5,6 +5,10 @@ #include "mbedtls/asn1write.h" #include "mbedtls/oid.h" +/* For MBEDTLS_CTR_DRBG_MAX_REQUEST, knowing that psa_generate_random() + * uses mbedtls_ctr_drbg internally. */ +#include "mbedtls/ctr_drbg.h" + #include "psa_crypto_helpers.h" /* Tests that require more than 128kB of RAM plus change have this symbol @@ -14,6 +18,8 @@ * platforms. */ #define HAVE_RAM_AVAILABLE_128K +#include "psa/crypto.h" + /** An invalid export length that will never be set by psa_export_key(). */ static const size_t INVALID_EXPORT_LENGTH = ~0U; From f181eca3503e85a84171b60fa747f1f2b3cbf0c8 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Wed, 7 Aug 2019 13:49:00 +0200 Subject: [PATCH 20/20] Fix psa_generate_random for >1024 bytes mbedtls_ctr_drbg_random can only return up to MBEDTLS_CTR_DRBG_MAX_REQUEST (normally 1024) bytes at a time. So if more than that is requested, call mbedtls_ctr_drbg_random in a loop. --- library/psa_crypto.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/library/psa_crypto.c b/library/psa_crypto.c index c6bc7a267..b602f1961 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -5650,6 +5650,17 @@ psa_status_t psa_generate_random( uint8_t *output, int ret; GUARD_MODULE_INITIALIZED; + while( output_size > MBEDTLS_CTR_DRBG_MAX_REQUEST ) + { + ret = mbedtls_ctr_drbg_random( &global_data.ctr_drbg, + output, + MBEDTLS_CTR_DRBG_MAX_REQUEST ); + if( ret != 0 ) + return( mbedtls_to_psa_error( ret ) ); + output += MBEDTLS_CTR_DRBG_MAX_REQUEST; + output_size -= MBEDTLS_CTR_DRBG_MAX_REQUEST; + } + ret = mbedtls_ctr_drbg_random( &global_data.ctr_drbg, output, output_size ); return( mbedtls_to_psa_error( ret ) ); }