From 0dbbf1e27fd702090de5ed56bad83b48fa58535b Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Mon, 30 Nov 2020 18:05:08 +0100 Subject: [PATCH 01/38] psa: Add architecture document Add architecture document explaining how this PR aim to restructure the PSA implementation (only part of it) and why. Signed-off-by: Ronald Cron --- .../psa-crypto-implementation-structure.md | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 docs/architecture/psa-crypto-implementation-structure.md diff --git a/docs/architecture/psa-crypto-implementation-structure.md b/docs/architecture/psa-crypto-implementation-structure.md new file mode 100644 index 000000000..ffc25efdb --- /dev/null +++ b/docs/architecture/psa-crypto-implementation-structure.md @@ -0,0 +1,50 @@ +PSA Cryptograpy API implementation and PSA driver interface +=========================================================== + +## Introduction + +The [PSA Cryptography API specification](https://armmbed.github.io/mbed-crypto/psa/#application-programming-interface) defines an interface to cryptographic operations which the Mbed TLS library provides a reference implementation for. The PSA Cryptography API specification is complemented by the PSA driver interface specification which defines an interface for cryptoprocessor drivers. + +This document describes the high level organization of the Mbed TLS PSA Cryptography API implementation which is tighly related to the PSA driver interface. + +## High level organization of the Mbed TLS PSA Cryptography API implementation +In one sentence, the Mbed TLS PSA Cryptography API implementation is made of a core and PSA drivers as defined in the PSA driver interface. The key point is that software cryptographic operations are organized as PSA drivers: they interact with the core through the PSA driver interface. + +### Rationale + +* Addressing software and hardware cryptographic implementations through the same C interface reduces the core code size and its call graph complexity. The core and its dispatching to software and hardware implementations are consequently easier to test and validate. +* The organization of the software cryptographic implementations in drivers promotes modularization of those implementations. +* As hardware capabilities, software cryptographic functionalities can be described by a JSON driver description file as defined in the PSA driver interface. +* Along with JSON driver description files, the PSA driver specification defines the deliverables for a driver to be included into the Mbed TLS PSA Cryptography implementation. This provides a natural framework to integrate third party or alternative software implementations of cryptographic operations. + +## The Mbed TLS PSA Cryptography API implementation core + +The core implements all the APIs as defined in the PSA Cryptography API specification but do not perform on its own any cryptographic operation. The core relies on PSA drivers to actually +perform the cryptographic operations. The core is responsible of: + +* the key store. +* checking PSA API arguments and translate them into valid arguments for the necessary calls to the PSA driver interface. +* dispatchng the cryptographic operations to the appropriate PSA drivers. + +The sketch of an Mbed TLS PSA cryptographic API implementation is thus: +```C +psa_status_t psa_api( ... ) +{ + psa_status_t status; + + /* Pre driver interface call processing: validation of arguments, building + * of arguments for the call to the driver interface, ... */ + + ... + + /* Call to the driver interface */ + status = psa_driver_wrapper_( ... ); + if( status != PSA_SUCCESS ) + return( status ); + + /* Post driver interface call processing: validation of the values returned + * by the driver, finalization ot the values to return to the caller, + * clean-up in case of error ... */ +} +``` +Obviously, for some PSA APIs the implementation is more complicated with several potential conditionnal calls to different driver entry points but most of PSA API code aimed to be organized along those lines. The implementation of the `psa_driver_wrapper_` function is generated by the build system based on the JSON driver description files of the various PSA drivers making up the Mbed TLS PSA Cryptography API implementation. From ea0f8a6d1a1b6d504a36b2b9d6bfd9edb968025b Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Wed, 25 Nov 2020 17:52:23 +0100 Subject: [PATCH 02/38] psa: se: Create key context in SE key slots In key slots containing the description of a key of a dynamically registered Secure Element (SE), store the key slot number in a key context as defined in the PSA driver interface for opaque drivers. That way transparent key data and slot numbers are , in a key slot, both stored in a dynamically allocated buffer. The `data` union in structures of type psa_key_slot_t to distinguish between the storage of transparent key data and slot numbers is consequently not necessary anymore and thus removed. This alignement of some part of the code dedicated to dynamically registered SE with the PSA driver interface specification is done to ease the support of both dynamically registered and statically defined secure elements. Signed-off-by: Ronald Cron --- library/psa_crypto.c | 173 +++++++++++++-------------- library/psa_crypto_core.h | 36 +++--- library/psa_crypto_driver_wrappers.c | 89 +++++++------- library/psa_crypto_slot_management.c | 7 +- 4 files changed, 153 insertions(+), 152 deletions(-) diff --git a/library/psa_crypto.c b/library/psa_crypto.c index 39144a378..fccb80077 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -749,8 +749,8 @@ exit: } /* On success, store the allocated export-formatted key. */ - slot->data.key.data = output; - slot->data.key.bytes = data_length; + slot->key.data = output; + slot->key.bytes = data_length; return( PSA_SUCCESS ); } @@ -983,8 +983,8 @@ exit: } /* On success, store the allocated export-formatted key. */ - slot->data.key.data = output; - slot->data.key.bytes = data_length; + slot->key.data = output; + slot->key.bytes = data_length; return( PSA_SUCCESS ); } @@ -1017,14 +1017,14 @@ static inline size_t psa_get_key_slot_bits( const psa_key_slot_t *slot ) static psa_status_t psa_allocate_buffer_to_slot( psa_key_slot_t *slot, size_t buffer_length ) { - if( slot->data.key.data != NULL ) + if( slot->key.data != NULL ) return( PSA_ERROR_ALREADY_EXISTS ); - slot->data.key.data = mbedtls_calloc( 1, buffer_length ); - if( slot->data.key.data == NULL ) + slot->key.data = mbedtls_calloc( 1, buffer_length ); + if( slot->key.data == NULL ) return( PSA_ERROR_INSUFFICIENT_MEMORY ); - slot->data.key.bytes = buffer_length; + slot->key.bytes = buffer_length; return( PSA_SUCCESS ); } @@ -1037,7 +1037,7 @@ psa_status_t psa_copy_key_material_into_slot( psa_key_slot_t *slot, if( status != PSA_SUCCESS ) return( status ); - memcpy( slot->data.key.data, data, data_length ); + memcpy( slot->key.data, data, data_length ); return( PSA_SUCCESS ); } @@ -1342,23 +1342,14 @@ static psa_status_t psa_get_and_lock_transparent_key_slot_with_policy( /** Wipe key data from a slot. Preserve metadata such as the policy. */ static psa_status_t psa_remove_key_data_from_memory( psa_key_slot_t *slot ) { -#if defined(MBEDTLS_PSA_CRYPTO_SE_C) - if( psa_get_se_driver( slot->attr.lifetime, NULL, NULL ) && - psa_key_slot_is_external( slot ) ) - { - /* No key material to clean. */ - } - else -#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ - { - /* Data pointer will always be either a valid pointer or NULL in an - * initialized slot, so we can just free it. */ - if( slot->data.key.data != NULL ) - mbedtls_platform_zeroize( slot->data.key.data, slot->data.key.bytes); - mbedtls_free( slot->data.key.data ); - slot->data.key.data = NULL; - slot->data.key.bytes = 0; - } + /* Data pointer will always be either a valid pointer or NULL in an + * initialized slot, so we can just free it. */ + if( slot->key.data != NULL ) + mbedtls_platform_zeroize( slot->key.data, slot->key.bytes); + + mbedtls_free( slot->key.data ); + slot->key.data = NULL; + slot->key.bytes = 0; return( PSA_SUCCESS ); } @@ -1443,7 +1434,7 @@ psa_status_t psa_destroy_key( mbedtls_svc_key_id_t key ) * three actions. */ psa_crypto_prepare_transaction( PSA_CRYPTO_TRANSACTION_DESTROY_KEY ); psa_crypto_transaction.key.lifetime = slot->attr.lifetime; - psa_crypto_transaction.key.slot = slot->data.se.slot_number; + psa_crypto_transaction.key.slot = psa_key_slot_get_slot_number( slot ); psa_crypto_transaction.key.id = slot->attr.id; status = psa_crypto_save_transaction( ); if( status != PSA_SUCCESS ) @@ -1460,7 +1451,8 @@ psa_status_t psa_destroy_key( mbedtls_svc_key_id_t key ) goto exit; } - status = psa_destroy_se_key( driver, slot->data.se.slot_number ); + status = psa_destroy_se_key( driver, + psa_key_slot_get_slot_number( slot ) ); if( overall_status == PSA_SUCCESS ) overall_status = status; } @@ -1616,7 +1608,8 @@ psa_status_t psa_get_key_attributes( mbedtls_svc_key_id_t key, #if defined(MBEDTLS_PSA_CRYPTO_SE_C) if( psa_key_slot_is_external( slot ) ) - psa_set_key_slot_number( attributes, slot->data.se.slot_number ); + psa_set_key_slot_number( attributes, + psa_key_slot_get_slot_number( slot ) ); #endif /* MBEDTLS_PSA_CRYPTO_SE_C */ switch( slot->attr.type ) @@ -1637,8 +1630,8 @@ psa_status_t psa_get_key_attributes( mbedtls_svc_key_id_t key, mbedtls_rsa_context *rsa = NULL; status = psa_load_rsa_representation( slot->attr.type, - slot->data.key.data, - slot->data.key.bytes, + slot->key.data, + slot->key.bytes, &rsa ); if( status != PSA_SUCCESS ) break; @@ -1684,12 +1677,12 @@ static psa_status_t psa_internal_export_key_buffer( const psa_key_slot_t *slot, size_t data_size, size_t *data_length ) { - if( slot->data.key.bytes > data_size ) + if( slot->key.bytes > data_size ) return( PSA_ERROR_BUFFER_TOO_SMALL ); - memcpy( data, slot->data.key.data, slot->data.key.bytes ); - memset( data + slot->data.key.bytes, 0, - data_size - slot->data.key.bytes ); - *data_length = slot->data.key.bytes; + memcpy( data, slot->key.data, slot->key.bytes ); + memset( data + slot->key.bytes, 0, + data_size - slot->key.bytes ); + *data_length = slot->key.bytes; return( PSA_SUCCESS ); } @@ -1727,7 +1720,7 @@ static psa_status_t psa_internal_export_key( const psa_key_slot_t *slot, if( method == NULL ) return( PSA_ERROR_NOT_SUPPORTED ); return( method( drv_context, - slot->data.se.slot_number, + psa_key_slot_get_slot_number( slot ), data, data_size, data_length ) ); } #endif /* MBEDTLS_PSA_CRYPTO_SE_C */ @@ -1768,8 +1761,8 @@ static psa_status_t psa_internal_export_key( const psa_key_slot_t *slot, mbedtls_rsa_context *rsa = NULL; status = psa_load_rsa_representation( slot->attr.type, - slot->data.key.data, - slot->data.key.bytes, + slot->key.data, + slot->key.bytes, &rsa ); if( status != PSA_SUCCESS ) return( status ); @@ -1797,8 +1790,8 @@ static psa_status_t psa_internal_export_key( const psa_key_slot_t *slot, mbedtls_ecp_keypair *ecp = NULL; status = psa_load_ecp_representation( slot->attr.type, - slot->data.key.data, - slot->data.key.bytes, + slot->key.data, + slot->key.bytes, &ecp ); if( status != PSA_SUCCESS ) return( status ); @@ -2071,8 +2064,9 @@ static psa_status_t psa_start_key_creation( * we can roll back to a state where the key doesn't exist. */ if( *p_drv != NULL ) { + psa_key_slot_number_t slot_number; status = psa_find_se_slot_for_key( attributes, method, *p_drv, - &slot->data.se.slot_number ); + &slot_number ); if( status != PSA_SUCCESS ) return( status ); @@ -2080,7 +2074,7 @@ static psa_status_t psa_start_key_creation( { psa_crypto_prepare_transaction( PSA_CRYPTO_TRANSACTION_CREATE_KEY ); psa_crypto_transaction.key.lifetime = slot->attr.lifetime; - psa_crypto_transaction.key.slot = slot->data.se.slot_number; + psa_crypto_transaction.key.slot = slot_number; psa_crypto_transaction.key.id = slot->attr.id; status = psa_crypto_save_transaction( ); if( status != PSA_SUCCESS ) @@ -2089,6 +2083,9 @@ static psa_status_t psa_start_key_creation( return( status ); } } + + status = psa_copy_key_material_into_slot( + slot, (uint8_t *)( &slot_number ), sizeof( slot_number ) ); } if( *p_drv == NULL && method == PSA_KEY_CREATION_REGISTER ) @@ -2140,13 +2137,15 @@ static psa_status_t psa_finish_key_creation( if( driver != NULL ) { psa_se_key_data_storage_t data; + psa_key_slot_number_t slot_number = + psa_key_slot_get_slot_number( slot ) ; + #if defined(static_assert) - static_assert( sizeof( slot->data.se.slot_number ) == + static_assert( sizeof( slot_number ) == sizeof( data.slot_number ), "Slot number 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.slot_number, &slot_number, sizeof( slot_number ) ); status = psa_save_persistent_key( &slot->attr, (uint8_t*) &data, sizeof( data ) ); @@ -2157,8 +2156,8 @@ static psa_status_t psa_finish_key_creation( /* Key material is saved in export representation in the slot, so * just pass the slot buffer for storage. */ status = psa_save_persistent_key( &slot->attr, - slot->data.key.data, - slot->data.key.bytes ); + slot->key.data, + slot->key.bytes ); } } #endif /* defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) */ @@ -2264,8 +2263,8 @@ static psa_status_t psa_validate_optional_attributes( psa_status_t status = psa_load_rsa_representation( slot->attr.type, - slot->data.key.data, - slot->data.key.bytes, + slot->key.data, + slot->key.bytes, &rsa ); if( status != PSA_SUCCESS ) return( status ); @@ -2345,8 +2344,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, attributes, data, data_length, - &bits ); + psa_key_slot_get_slot_number( slot ), + attributes, data, data_length, &bits ); if( status != PSA_SUCCESS ) goto exit; if( bits > PSA_MAX_KEY_BITS ) @@ -2423,8 +2422,8 @@ static psa_status_t psa_copy_key_material( const psa_key_slot_t *source, psa_key_slot_t *target ) { psa_status_t status = psa_copy_key_material_into_slot( target, - source->data.key.data, - source->data.key.bytes ); + source->key.data, + source->key.bytes ); if( status != PSA_SUCCESS ) return( status ); @@ -3236,7 +3235,7 @@ static int psa_cmac_setup( psa_mac_operation_t *operation, return( ret ); ret = mbedtls_cipher_cmac_starts( &operation->ctx.cmac, - slot->data.key.data, + slot->key.data, key_bits ); return( ret ); } @@ -3382,8 +3381,8 @@ static psa_status_t psa_mac_setup( psa_mac_operation_t *operation, } status = psa_hmac_setup_internal( &operation->ctx.hmac, - slot->data.key.data, - slot->data.key.bytes, + slot->key.data, + slot->key.bytes, hash_alg ); } else @@ -3969,8 +3968,8 @@ psa_status_t psa_sign_hash( mbedtls_svc_key_id_t key, mbedtls_rsa_context *rsa = NULL; status = psa_load_rsa_representation( slot->attr.type, - slot->data.key.data, - slot->data.key.bytes, + slot->key.data, + slot->key.bytes, &rsa ); if( status != PSA_SUCCESS ) goto exit; @@ -4001,8 +4000,8 @@ psa_status_t psa_sign_hash( mbedtls_svc_key_id_t key, { mbedtls_ecp_keypair *ecp = NULL; status = psa_load_ecp_representation( slot->attr.type, - slot->data.key.data, - slot->data.key.bytes, + slot->key.data, + slot->key.bytes, &ecp ); if( status != PSA_SUCCESS ) goto exit; @@ -4079,8 +4078,8 @@ psa_status_t psa_verify_hash( mbedtls_svc_key_id_t key, mbedtls_rsa_context *rsa = NULL; status = psa_load_rsa_representation( slot->attr.type, - slot->data.key.data, - slot->data.key.bytes, + slot->key.data, + slot->key.bytes, &rsa ); if( status != PSA_SUCCESS ) goto exit; @@ -4104,8 +4103,8 @@ psa_status_t psa_verify_hash( mbedtls_svc_key_id_t key, { mbedtls_ecp_keypair *ecp = NULL; status = psa_load_ecp_representation( slot->attr.type, - slot->data.key.data, - slot->data.key.bytes, + slot->key.data, + slot->key.bytes, &ecp ); if( status != PSA_SUCCESS ) goto exit; @@ -4188,8 +4187,8 @@ psa_status_t psa_asymmetric_encrypt( mbedtls_svc_key_id_t key, { mbedtls_rsa_context *rsa = NULL; status = psa_load_rsa_representation( slot->attr.type, - slot->data.key.data, - slot->data.key.bytes, + slot->key.data, + slot->key.bytes, &rsa ); if( status != PSA_SUCCESS ) goto rsa_exit; @@ -4294,8 +4293,8 @@ psa_status_t psa_asymmetric_decrypt( mbedtls_svc_key_id_t key, { mbedtls_rsa_context *rsa = NULL; status = psa_load_rsa_representation( slot->attr.type, - slot->data.key.data, - slot->data.key.bytes, + slot->key.data, + slot->key.bytes, &rsa ); if( status != PSA_SUCCESS ) goto exit; @@ -4455,8 +4454,8 @@ static psa_status_t psa_cipher_setup( psa_cipher_operation_t *operation, { /* Two-key Triple-DES is 3-key Triple-DES with K1=K3 */ uint8_t keys[24]; - memcpy( keys, slot->data.key.data, 16 ); - memcpy( keys + 16, slot->data.key.data, 8 ); + memcpy( keys, slot->key.data, 16 ); + memcpy( keys + 16, slot->key.data, 8 ); ret = mbedtls_cipher_setkey( &operation->ctx.cipher, keys, 192, cipher_operation ); @@ -4465,7 +4464,7 @@ static psa_status_t psa_cipher_setup( psa_cipher_operation_t *operation, #endif { ret = mbedtls_cipher_setkey( &operation->ctx.cipher, - slot->data.key.data, + slot->key.data, (int) key_bits, cipher_operation ); } if( ret != 0 ) @@ -4964,7 +4963,7 @@ static psa_status_t psa_aead_setup( aead_operation_t *operation, mbedtls_ccm_init( &operation->ctx.ccm ); status = mbedtls_to_psa_error( mbedtls_ccm_setkey( &operation->ctx.ccm, cipher_id, - operation->slot->data.key.data, + operation->slot->key.data, (unsigned int) key_bits ) ); if( status != 0 ) goto cleanup; @@ -4986,7 +4985,7 @@ static psa_status_t psa_aead_setup( aead_operation_t *operation, mbedtls_gcm_init( &operation->ctx.gcm ); status = mbedtls_to_psa_error( mbedtls_gcm_setkey( &operation->ctx.gcm, cipher_id, - operation->slot->data.key.data, + operation->slot->key.data, (unsigned int) key_bits ) ); if( status != 0 ) goto cleanup; @@ -5006,7 +5005,7 @@ static psa_status_t psa_aead_setup( aead_operation_t *operation, mbedtls_chachapoly_init( &operation->ctx.chachapoly ); status = mbedtls_to_psa_error( mbedtls_chachapoly_setkey( &operation->ctx.chachapoly, - operation->slot->data.key.data ) ); + operation->slot->key.data ) ); if( status != 0 ) goto cleanup; break; @@ -6129,8 +6128,8 @@ psa_status_t psa_key_derivation_input_key( status = psa_key_derivation_input_internal( operation, step, slot->attr.type, - slot->data.key.data, - slot->data.key.bytes ); + slot->key.data, + slot->key.bytes ); unlock_status = psa_unlock_key_slot( slot ); @@ -6215,8 +6214,8 @@ static psa_status_t psa_key_agreement_raw_internal( psa_algorithm_t alg, mbedtls_ecp_keypair *ecp = NULL; psa_status_t status = psa_load_ecp_representation( private_key->attr.type, - private_key->data.key.data, - private_key->data.key.bytes, + private_key->key.data, + private_key->key.bytes, &ecp ); if( status != PSA_SUCCESS ) return( status ); @@ -6558,16 +6557,16 @@ static psa_status_t psa_generate_key_internal( if( status != PSA_SUCCESS ) return( status ); - status = psa_generate_random( slot->data.key.data, - slot->data.key.bytes ); + status = psa_generate_random( slot->key.data, + slot->key.bytes ); if( status != PSA_SUCCESS ) return( status ); slot->attr.bits = (psa_key_bits_t) bits; #if defined(MBEDTLS_DES_C) if( type == PSA_KEY_TYPE_DES ) - psa_des_set_key_parity( slot->data.key.data, - slot->data.key.bytes ); + psa_des_set_key_parity( slot->key.data, + slot->key.bytes ); #endif /* MBEDTLS_DES_C */ } else @@ -6611,9 +6610,9 @@ static psa_status_t psa_generate_key_internal( status = psa_export_rsa_key( type, &rsa, - slot->data.key.data, + slot->key.data, bytes, - &slot->data.key.bytes ); + &slot->key.bytes ); mbedtls_rsa_free( &rsa ); if( status != PSA_SUCCESS ) psa_remove_key_data_from_memory( slot ); @@ -6657,11 +6656,11 @@ static psa_status_t psa_generate_key_internal( } status = mbedtls_to_psa_error( - mbedtls_ecp_write_key( &ecp, slot->data.key.data, bytes ) ); + mbedtls_ecp_write_key( &ecp, slot->key.data, bytes ) ); mbedtls_ecp_keypair_free( &ecp ); if( status != PSA_SUCCESS ) { - memset( slot->data.key.data, 0, bytes ); + memset( slot->key.data, 0, bytes ); psa_remove_key_data_from_memory( slot ); } return( status ); diff --git a/library/psa_crypto_core.h b/library/psa_crypto_core.h index f61ef9550..3f266f392 100644 --- a/library/psa_crypto_core.h +++ b/library/psa_crypto_core.h @@ -62,23 +62,13 @@ typedef struct */ size_t lock_count; - union + /* Dynamically allocated key data buffer. + * Format as specified in psa_export_key(). */ + struct key_data { - /* Dynamically allocated key data buffer. - * Format as specified in psa_export_key(). */ - struct key_data - { - uint8_t *data; - size_t bytes; - } key; -#if defined(MBEDTLS_PSA_CRYPTO_SE_C) - /* Any key type in a secure element */ - struct se - { - psa_key_slot_number_t slot_number; - } se; -#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ - } data; + uint8_t *data; + size_t bytes; + } key; } psa_key_slot_t; /* A mask of key attribute flags used only internally. @@ -163,6 +153,20 @@ static inline void psa_key_slot_clear_bits( psa_key_slot_t *slot, slot->attr.flags &= ~mask; } +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) +/** Get the SE slot number of a key from the key slot storing its description. + * + * \param[in] slot The key slot to query. This must be a key slot storing + * the description of a key of a dynamically registered + * secure element, otherwise the behaviour is undefined. + */ +static inline psa_key_slot_number_t psa_key_slot_get_slot_number( + const psa_key_slot_t *slot ) +{ + return( *( (psa_key_slot_number_t *)( slot->key.data ) ) ); +} +#endif + /** Completely wipe a slot in memory, including its policy. * * Persistent storage is not affected. diff --git a/library/psa_crypto_driver_wrappers.c b/library/psa_crypto_driver_wrappers.c index 1243bd387..2d433830d 100644 --- a/library/psa_crypto_driver_wrappers.c +++ b/library/psa_crypto_driver_wrappers.c @@ -80,7 +80,7 @@ psa_status_t psa_driver_wrapper_sign_hash( psa_key_slot_t *slot, return( PSA_ERROR_NOT_SUPPORTED ); } return( drv->asymmetric->p_sign( drv_context, - slot->data.se.slot_number, + psa_key_slot_get_slot_number( slot ), alg, hash, hash_length, signature, signature_size, @@ -103,8 +103,8 @@ psa_status_t psa_driver_wrapper_sign_hash( psa_key_slot_t *slot, * cycle through all known transparent accelerators */ #if defined(PSA_CRYPTO_DRIVER_TEST) status = test_transparent_signature_sign_hash( &attributes, - slot->data.key.data, - slot->data.key.bytes, + slot->key.data, + slot->key.bytes, alg, hash, hash_length, @@ -121,8 +121,8 @@ psa_status_t psa_driver_wrapper_sign_hash( psa_key_slot_t *slot, #if defined(PSA_CRYPTO_DRIVER_TEST) case PSA_CRYPTO_TEST_DRIVER_LIFETIME: return( test_opaque_signature_sign_hash( &attributes, - slot->data.key.data, - slot->data.key.bytes, + slot->key.data, + slot->key.bytes, alg, hash, hash_length, @@ -172,7 +172,7 @@ psa_status_t psa_driver_wrapper_verify_hash( psa_key_slot_t *slot, return( PSA_ERROR_NOT_SUPPORTED ); } return( drv->asymmetric->p_verify( drv_context, - slot->data.se.slot_number, + psa_key_slot_get_slot_number( slot ), alg, hash, hash_length, signature, signature_length ) ); @@ -194,8 +194,8 @@ psa_status_t psa_driver_wrapper_verify_hash( psa_key_slot_t *slot, * cycle through all known transparent accelerators */ #if defined(PSA_CRYPTO_DRIVER_TEST) status = test_transparent_signature_verify_hash( &attributes, - slot->data.key.data, - slot->data.key.bytes, + slot->key.data, + slot->key.bytes, alg, hash, hash_length, @@ -211,8 +211,8 @@ psa_status_t psa_driver_wrapper_verify_hash( psa_key_slot_t *slot, #if defined(PSA_CRYPTO_DRIVER_TEST) case PSA_CRYPTO_TEST_DRIVER_LIFETIME: return( test_opaque_signature_verify_hash( &attributes, - slot->data.key.data, - slot->data.key.bytes, + slot->key.data, + slot->key.bytes, alg, hash, hash_length, @@ -330,9 +330,8 @@ psa_status_t psa_driver_wrapper_generate_key( const psa_key_attributes_t *attrib return( PSA_ERROR_NOT_SUPPORTED ); } return( drv->key_management->p_generate( - drv_context, - slot->data.se.slot_number, attributes, - NULL, 0, &pubkey_length ) ); + drv_context, psa_key_slot_get_slot_number( slot ), + attributes, NULL, 0, &pubkey_length ) ); } #endif /* MBEDTLS_PSA_CRYPTO_SE_C */ @@ -346,10 +345,10 @@ psa_status_t psa_driver_wrapper_generate_key( const psa_key_attributes_t *attrib if( status != PSA_SUCCESS ) return( status ); - slot->data.key.data = mbedtls_calloc(1, export_size); - if( slot->data.key.data == NULL ) + slot->key.data = mbedtls_calloc(1, export_size); + if( slot->key.data == NULL ) return( PSA_ERROR_INSUFFICIENT_MEMORY ); - slot->data.key.bytes = export_size; + slot->key.bytes = export_size; switch( location ) { @@ -365,9 +364,9 @@ psa_status_t psa_driver_wrapper_generate_key( const psa_key_attributes_t *attrib } #if defined(PSA_CRYPTO_DRIVER_TEST) status = test_transparent_generate_key( attributes, - slot->data.key.data, - slot->data.key.bytes, - &slot->data.key.bytes ); + slot->key.data, + slot->key.bytes, + &slot->key.bytes ); /* Declared with fallback == true */ if( status != PSA_ERROR_NOT_SUPPORTED ) break; @@ -379,9 +378,9 @@ psa_status_t psa_driver_wrapper_generate_key( const psa_key_attributes_t *attrib #if defined(PSA_CRYPTO_DRIVER_TEST) case PSA_CRYPTO_TEST_DRIVER_LIFETIME: status = test_opaque_generate_key( attributes, - slot->data.key.data, - slot->data.key.bytes, - &slot->data.key.bytes ); + slot->key.data, + slot->key.bytes, + &slot->key.bytes ); break; #endif /* PSA_CRYPTO_DRIVER_TEST */ default: @@ -393,9 +392,9 @@ psa_status_t psa_driver_wrapper_generate_key( const psa_key_attributes_t *attrib if( status != PSA_SUCCESS ) { /* free allocated buffer */ - mbedtls_free( slot->data.key.data ); - slot->data.key.data = NULL; - slot->data.key.bytes = 0; + mbedtls_free( slot->key.data ); + slot->key.data = NULL; + slot->key.bytes = 0; } return( status ); @@ -457,8 +456,8 @@ psa_status_t psa_driver_wrapper_export_public_key( const psa_key_slot_t *slot, * cycle through all known transparent accelerators */ #if defined(PSA_CRYPTO_DRIVER_TEST) status = test_transparent_export_public_key( &attributes, - slot->data.key.data, - slot->data.key.bytes, + slot->key.data, + slot->key.bytes, data, data_size, data_length ); @@ -472,8 +471,8 @@ psa_status_t psa_driver_wrapper_export_public_key( const psa_key_slot_t *slot, #if defined(PSA_CRYPTO_DRIVER_TEST) case PSA_CRYPTO_TEST_DRIVER_LIFETIME: return( test_opaque_export_public_key( &attributes, - slot->data.key.data, - slot->data.key.bytes, + slot->key.data, + slot->key.bytes, data, data_size, data_length ) ); @@ -517,8 +516,8 @@ psa_status_t psa_driver_wrapper_cipher_encrypt( * cycle through all known transparent accelerators */ #if defined(PSA_CRYPTO_DRIVER_TEST) status = test_transparent_cipher_encrypt( &attributes, - slot->data.key.data, - slot->data.key.bytes, + slot->key.data, + slot->key.bytes, alg, input, input_length, @@ -535,8 +534,8 @@ psa_status_t psa_driver_wrapper_cipher_encrypt( #if defined(PSA_CRYPTO_DRIVER_TEST) case PSA_CRYPTO_TEST_DRIVER_LIFETIME: return( test_opaque_cipher_encrypt( &attributes, - slot->data.key.data, - slot->data.key.bytes, + slot->key.data, + slot->key.bytes, alg, input, input_length, @@ -584,8 +583,8 @@ psa_status_t psa_driver_wrapper_cipher_decrypt( * cycle through all known transparent accelerators */ #if defined(PSA_CRYPTO_DRIVER_TEST) status = test_transparent_cipher_decrypt( &attributes, - slot->data.key.data, - slot->data.key.bytes, + slot->key.data, + slot->key.bytes, alg, input, input_length, @@ -602,8 +601,8 @@ psa_status_t psa_driver_wrapper_cipher_decrypt( #if defined(PSA_CRYPTO_DRIVER_TEST) case PSA_CRYPTO_TEST_DRIVER_LIFETIME: return( test_opaque_cipher_decrypt( &attributes, - slot->data.key.data, - slot->data.key.bytes, + slot->key.data, + slot->key.bytes, alg, input, input_length, @@ -652,8 +651,8 @@ psa_status_t psa_driver_wrapper_cipher_encrypt_setup( status = test_transparent_cipher_encrypt_setup( operation->ctx, &attributes, - slot->data.key.data, - slot->data.key.bytes, + slot->key.data, + slot->key.bytes, alg ); /* Declared with fallback == true */ if( status == PSA_SUCCESS ) @@ -680,8 +679,8 @@ psa_status_t psa_driver_wrapper_cipher_encrypt_setup( status = test_opaque_cipher_encrypt_setup( operation->ctx, &attributes, - slot->data.key.data, - slot->data.key.bytes, + slot->key.data, + slot->key.bytes, alg ); if( status == PSA_SUCCESS ) operation->id = PSA_CRYPTO_OPAQUE_TEST_DRIVER_ID; @@ -733,8 +732,8 @@ psa_status_t psa_driver_wrapper_cipher_decrypt_setup( status = test_transparent_cipher_decrypt_setup( operation->ctx, &attributes, - slot->data.key.data, - slot->data.key.bytes, + slot->key.data, + slot->key.bytes, alg ); /* Declared with fallback == true */ if( status == PSA_SUCCESS ) @@ -761,8 +760,8 @@ psa_status_t psa_driver_wrapper_cipher_decrypt_setup( status = test_opaque_cipher_decrypt_setup( operation->ctx, &attributes, - slot->data.key.data, - slot->data.key.bytes, + slot->key.data, + slot->key.bytes, alg ); if( status == PSA_SUCCESS ) operation->id = PSA_CRYPTO_OPAQUE_TEST_DRIVER_ID; diff --git a/library/psa_crypto_slot_management.c b/library/psa_crypto_slot_management.c index 39d6dbb36..1188ce6e4 100644 --- a/library/psa_crypto_slot_management.c +++ b/library/psa_crypto_slot_management.c @@ -255,16 +255,15 @@ static psa_status_t psa_load_persistent_key_into_slot( psa_key_slot_t *slot ) if( psa_get_se_driver( slot->attr.lifetime, &drv, &drv_context ) ) { psa_se_key_data_storage_t *data; + if( key_data_length != sizeof( *data ) ) { status = PSA_ERROR_STORAGE_FAILURE; goto exit; } data = (psa_se_key_data_storage_t *) key_data; - memcpy( &slot->data.se.slot_number, &data->slot_number, - sizeof( slot->data.se.slot_number ) ); - - status = PSA_SUCCESS; + status = psa_copy_key_material_into_slot( + slot, data->slot_number, sizeof( data->slot_number ) ); goto exit; } #endif /* MBEDTLS_PSA_CRYPTO_SE_C */ From 83282879562ddd80627a6f244835eeac573870fe Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Sun, 22 Nov 2020 14:02:39 +0100 Subject: [PATCH 03/38] psa: Move from validate_key to import_key entry point In the course of the development of the PSA unified driver interface, the validate_key entry point for opaque drivers has been removed and replaced by an import_key entry point. This commit takes into account this change of specification. Signed-off-by: Ronald Cron --- library/psa_crypto.c | 39 ++++++++++++++------- library/psa_crypto_driver_wrappers.c | 23 +++++++----- library/psa_crypto_driver_wrappers.h | 9 ++--- tests/include/test/drivers/key_management.h | 15 ++++---- tests/src/drivers/key_management.c | 7 ++-- 5 files changed, 60 insertions(+), 33 deletions(-) diff --git a/library/psa_crypto.c b/library/psa_crypto.c index fccb80077..c35b2a644 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -1104,27 +1104,40 @@ static psa_status_t psa_import_key_into_slot( psa_key_slot_t *slot, else if( PSA_KEY_TYPE_IS_ASYMMETRIC( slot->attr.type ) ) { /* Try validation through accelerators first. */ - bit_size = slot->attr.bits; psa_key_attributes_t attributes = { .core = slot->attr }; - status = psa_driver_wrapper_validate_key( &attributes, - data, - data_length, - &bit_size ); + + status = psa_allocate_buffer_to_slot( slot, data_length ); + if( status != PSA_SUCCESS ) + return( status ); + + bit_size = slot->attr.bits; + status = psa_driver_wrapper_import_key( &attributes, + data, data_length, + slot->key.data, + slot->key.bytes, + &slot->key.bytes, + &bit_size ); if( status == PSA_SUCCESS ) { - /* Key has been validated successfully by an accelerator. - * Copy key material into slot. */ - status = psa_copy_key_material_into_slot( slot, data, data_length ); - if( status != PSA_SUCCESS ) - return( status ); + if( slot->attr.bits == 0 ) + slot->attr.bits = (psa_key_bits_t) bit_size; + else if( bit_size != slot->attr.bits ) + return( PSA_ERROR_INVALID_ARGUMENT ); - slot->attr.bits = (psa_key_bits_t) bit_size; return( PSA_SUCCESS ); } - else if( status != PSA_ERROR_NOT_SUPPORTED ) - return( status ); + else + { + if( status != PSA_ERROR_NOT_SUPPORTED ) + return( status ); + } + + mbedtls_platform_zeroize( slot->key.data, data_length ); + mbedtls_free( slot->key.data ); + slot->key.data = NULL; + slot->key.bytes = 0; /* Key format is not supported by any accelerator, try software fallback * if present. */ diff --git a/library/psa_crypto_driver_wrappers.c b/library/psa_crypto_driver_wrappers.c index 2d433830d..0562756e2 100644 --- a/library/psa_crypto_driver_wrappers.c +++ b/library/psa_crypto_driver_wrappers.c @@ -409,19 +409,23 @@ psa_status_t psa_driver_wrapper_generate_key( const psa_key_attributes_t *attrib #endif /* PSA_CRYPTO_DRIVER_PRESENT */ } -psa_status_t psa_driver_wrapper_validate_key( const psa_key_attributes_t *attributes, - const uint8_t *data, - size_t data_length, - size_t *bits ) +psa_status_t psa_driver_wrapper_import_key( + const psa_key_attributes_t *attributes, + const uint8_t *data, + size_t data_length, + uint8_t *key_buffer, + size_t key_buffer_size, + size_t *key_buffer_length, + size_t *bits ) { #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; /* Try accelerators in turn */ #if defined(PSA_CRYPTO_DRIVER_TEST) - status = test_transparent_validate_key( attributes, - data, - data_length, - bits ); + status = test_transparent_import_key( attributes, + data, data_length, + key_buffer, key_buffer_size, + key_buffer_length, bits ); /* Declared with fallback == true */ if( status != PSA_ERROR_NOT_SUPPORTED ) return( status ); @@ -432,6 +436,9 @@ psa_status_t psa_driver_wrapper_validate_key( const psa_key_attributes_t *attrib (void) attributes; (void) data; (void) data_length; + (void) key_buffer; + (void) key_buffer_size; + (void) key_buffer_length; (void) bits; return( PSA_ERROR_NOT_SUPPORTED ); #endif /* PSA_CRYPTO_DRIVER_PRESENT */ diff --git a/library/psa_crypto_driver_wrappers.h b/library/psa_crypto_driver_wrappers.h index 6b5143781..4c6cce95b 100644 --- a/library/psa_crypto_driver_wrappers.h +++ b/library/psa_crypto_driver_wrappers.h @@ -50,10 +50,11 @@ psa_status_t psa_driver_wrapper_verify_hash( psa_key_slot_t *slot, psa_status_t psa_driver_wrapper_generate_key( const psa_key_attributes_t *attributes, psa_key_slot_t *slot ); -psa_status_t psa_driver_wrapper_validate_key( const psa_key_attributes_t *attributes, - const uint8_t *data, - size_t data_length, - size_t *bits ); +psa_status_t psa_driver_wrapper_import_key( + const psa_key_attributes_t *attributes, + const uint8_t *data, size_t data_length, + uint8_t *key_buffer, size_t key_buffer_size, + size_t *key_buffer_length, size_t *bits ); psa_status_t psa_driver_wrapper_export_public_key( const psa_key_slot_t *slot, uint8_t *data, diff --git a/tests/include/test/drivers/key_management.h b/tests/include/test/drivers/key_management.h index 90f8c587c..7811fb439 100644 --- a/tests/include/test/drivers/key_management.h +++ b/tests/include/test/drivers/key_management.h @@ -58,12 +58,6 @@ psa_status_t test_opaque_generate_key( const psa_key_attributes_t *attributes, uint8_t *key, size_t key_size, size_t *key_length ); -psa_status_t test_transparent_validate_key( - const psa_key_attributes_t *attributes, - const uint8_t *data, - size_t data_length, - size_t *bits); - psa_status_t test_transparent_export_public_key( const psa_key_attributes_t *attributes, const uint8_t *key, size_t key_length, @@ -74,5 +68,14 @@ psa_status_t test_opaque_export_public_key( const uint8_t *key, size_t key_length, uint8_t *data, size_t data_size, size_t *data_length ); +psa_status_t test_transparent_import_key( + const psa_key_attributes_t *attributes, + const uint8_t *data, + size_t data_length, + uint8_t *key_buffer, + size_t key_buffer_size, + size_t *key_buffer_length, + size_t *bits); + #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_TEST_DRIVERS_KEY_MANAGEMENT_H */ diff --git a/tests/src/drivers/key_management.c b/tests/src/drivers/key_management.c index 00d2b4519..ab3210b71 100644 --- a/tests/src/drivers/key_management.c +++ b/tests/src/drivers/key_management.c @@ -137,11 +137,14 @@ psa_status_t test_opaque_generate_key( return( PSA_ERROR_NOT_SUPPORTED ); } -psa_status_t test_transparent_validate_key( +psa_status_t test_transparent_import_key( const psa_key_attributes_t *attributes, const uint8_t *data, size_t data_length, - size_t *bits ) + uint8_t *key_buffer, + size_t key_buffer_size, + size_t *key_buffer_length, + size_t *bits) { ++test_driver_key_management_hooks.hits; From 84cc99420cd088c2a513eeb0ea7bda67b08adc6e Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Wed, 25 Nov 2020 14:30:05 +0100 Subject: [PATCH 04/38] psa: Change psa_driver_wrapper_export_public_key() signature Change psa_driver_wrapper_export_public_key() signature to the signature of an export_public_key driver entry point. Signed-off-by: Ronald Cron --- library/psa_crypto.c | 10 +++++---- library/psa_crypto_driver_wrappers.c | 31 ++++++++++++++-------------- library/psa_crypto_driver_wrappers.h | 15 +++++++------- 3 files changed, 30 insertions(+), 26 deletions(-) diff --git a/library/psa_crypto.c b/library/psa_crypto.c index c35b2a644..adc730b57 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -1758,10 +1758,12 @@ static psa_status_t psa_internal_export_key( const psa_key_slot_t *slot, /* Need to export the public part of a private key, * so conversion is needed. Try the accelerators first. */ - psa_status_t status = psa_driver_wrapper_export_public_key( slot, - data, - data_size, - data_length ); + psa_key_attributes_t attributes = { + .core = slot->attr + }; + psa_status_t status = psa_driver_wrapper_export_public_key( + &attributes, slot->key.data, slot->key.bytes, + data, data_size, data_length ); if( status != PSA_ERROR_NOT_SUPPORTED || psa_key_lifetime_is_external( slot->attr.lifetime ) ) diff --git a/library/psa_crypto_driver_wrappers.c b/library/psa_crypto_driver_wrappers.c index 0562756e2..a58967a1d 100644 --- a/library/psa_crypto_driver_wrappers.c +++ b/library/psa_crypto_driver_wrappers.c @@ -444,17 +444,16 @@ psa_status_t psa_driver_wrapper_import_key( #endif /* PSA_CRYPTO_DRIVER_PRESENT */ } -psa_status_t psa_driver_wrapper_export_public_key( const psa_key_slot_t *slot, - uint8_t *data, - size_t data_size, - size_t *data_length ) +psa_status_t psa_driver_wrapper_export_public_key( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, size_t key_buffer_size, + uint8_t *data, size_t data_size, size_t *data_length ) + { #if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) psa_status_t status = PSA_ERROR_INVALID_ARGUMENT; - psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION(slot->attr.lifetime); - psa_key_attributes_t attributes = { - .core = slot->attr - }; + psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( + psa_get_key_lifetime( attributes ) ); switch( location ) { @@ -462,9 +461,9 @@ psa_status_t psa_driver_wrapper_export_public_key( const psa_key_slot_t *slot, /* Key is stored in the slot in export representation, so * cycle through all known transparent accelerators */ #if defined(PSA_CRYPTO_DRIVER_TEST) - status = test_transparent_export_public_key( &attributes, - slot->key.data, - slot->key.bytes, + status = test_transparent_export_public_key( attributes, + key_buffer, + key_buffer_size, data, data_size, data_length ); @@ -477,9 +476,9 @@ psa_status_t psa_driver_wrapper_export_public_key( const psa_key_slot_t *slot, /* Add cases for opaque driver here */ #if defined(PSA_CRYPTO_DRIVER_TEST) case PSA_CRYPTO_TEST_DRIVER_LIFETIME: - return( test_opaque_export_public_key( &attributes, - slot->key.data, - slot->key.bytes, + return( test_opaque_export_public_key( attributes, + key_buffer, + key_buffer_size, data, data_size, data_length ) ); @@ -489,7 +488,9 @@ psa_status_t psa_driver_wrapper_export_public_key( const psa_key_slot_t *slot, return( status ); } #else /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ - (void) slot; + (void) attributes; + (void) key_buffer; + (void) key_buffer_size; (void) data; (void) data_size; (void) data_length; diff --git a/library/psa_crypto_driver_wrappers.h b/library/psa_crypto_driver_wrappers.h index 4c6cce95b..fb32b8d14 100644 --- a/library/psa_crypto_driver_wrappers.h +++ b/library/psa_crypto_driver_wrappers.h @@ -47,19 +47,20 @@ psa_status_t psa_driver_wrapper_verify_hash( psa_key_slot_t *slot, * Key handling functions */ -psa_status_t psa_driver_wrapper_generate_key( const psa_key_attributes_t *attributes, - psa_key_slot_t *slot ); - psa_status_t psa_driver_wrapper_import_key( const psa_key_attributes_t *attributes, const uint8_t *data, size_t data_length, uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length, size_t *bits ); -psa_status_t psa_driver_wrapper_export_public_key( const psa_key_slot_t *slot, - uint8_t *data, - size_t data_size, - size_t *data_length ); +psa_status_t psa_driver_wrapper_export_public_key( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, size_t key_buffer_size, + uint8_t *data, size_t data_size, size_t *data_length ); + +psa_status_t psa_driver_wrapper_generate_key( + const psa_key_attributes_t *attributes, + psa_key_slot_t *slot ); /* * Cipher functions From 90857083713306c3981f99f83e2bc152d3cddd25 Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Wed, 25 Nov 2020 14:58:33 +0100 Subject: [PATCH 05/38] psa: Rename psa_load_rsa/ecp_representation Rename psa_load_rsa/ecp_representation to mbedtls_psa_rsa/ecp_load_representation before to move them in their RSA/ECP specific PSA crypto C modules. Signed-off-by: Ronald Cron --- library/psa_crypto.c | 134 +++++++++++++++++++++---------------------- 1 file changed, 66 insertions(+), 68 deletions(-) diff --git a/library/psa_crypto.c b/library/psa_crypto.c index adc730b57..78f9f272f 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -570,10 +570,9 @@ static psa_status_t psa_check_rsa_key_byte_aligned( * contents of the context and the context itself * when done. */ -static psa_status_t psa_load_rsa_representation( psa_key_type_t type, - const uint8_t *data, - size_t data_length, - mbedtls_rsa_context **p_rsa ) +static psa_status_t mbedtls_psa_rsa_load_representation( + psa_key_type_t type, const uint8_t *data, size_t data_length, + mbedtls_rsa_context **p_rsa ) { psa_status_t status; mbedtls_pk_context ctx; @@ -710,10 +709,10 @@ static psa_status_t psa_import_rsa_key( psa_key_slot_t *slot, mbedtls_rsa_context *rsa = NULL; /* Parse input */ - status = psa_load_rsa_representation( slot->attr.type, - data, - data_length, - &rsa ); + status = mbedtls_psa_rsa_load_representation( slot->attr.type, + data, + data_length, + &rsa ); if( status != PSA_SUCCESS ) goto exit; @@ -773,10 +772,9 @@ exit: * contents of the context and the context itself * when done. */ -static psa_status_t psa_load_ecp_representation( psa_key_type_t type, - const uint8_t *data, - size_t data_length, - mbedtls_ecp_keypair **p_ecp ) +static psa_status_t mbedtls_psa_ecp_load_representation( + psa_key_type_t type, const uint8_t *data, size_t data_length, + mbedtls_ecp_keypair **p_ecp ) { mbedtls_ecp_group_id grp_id = MBEDTLS_ECP_DP_NONE; psa_status_t status; @@ -943,10 +941,10 @@ static psa_status_t psa_import_ecp_key( psa_key_slot_t *slot, mbedtls_ecp_keypair *ecp = NULL; /* Parse input */ - status = psa_load_ecp_representation( slot->attr.type, - data, - data_length, - &ecp ); + status = mbedtls_psa_ecp_load_representation( slot->attr.type, + data, + data_length, + &ecp ); if( status != PSA_SUCCESS ) goto exit; @@ -1642,10 +1640,11 @@ psa_status_t psa_get_key_attributes( mbedtls_svc_key_id_t key, { mbedtls_rsa_context *rsa = NULL; - status = psa_load_rsa_representation( slot->attr.type, - slot->key.data, - slot->key.bytes, - &rsa ); + status = mbedtls_psa_rsa_load_representation( + slot->attr.type, + slot->key.data, + slot->key.bytes, + &rsa ); if( status != PSA_SUCCESS ) break; @@ -1774,11 +1773,10 @@ static psa_status_t psa_internal_export_key( const psa_key_slot_t *slot, #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) || \ defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) mbedtls_rsa_context *rsa = NULL; - status = psa_load_rsa_representation( - slot->attr.type, - slot->key.data, - slot->key.bytes, - &rsa ); + status = mbedtls_psa_rsa_load_representation( slot->attr.type, + slot->key.data, + slot->key.bytes, + &rsa ); if( status != PSA_SUCCESS ) return( status ); @@ -1803,11 +1801,10 @@ static psa_status_t psa_internal_export_key( const psa_key_slot_t *slot, #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) || \ defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) mbedtls_ecp_keypair *ecp = NULL; - status = psa_load_ecp_representation( - slot->attr.type, - slot->key.data, - slot->key.bytes, - &ecp ); + status = mbedtls_psa_ecp_load_representation( slot->attr.type, + slot->key.data, + slot->key.bytes, + &ecp ); if( status != PSA_SUCCESS ) return( status ); @@ -2276,11 +2273,11 @@ static psa_status_t psa_validate_optional_attributes( mbedtls_mpi actual, required; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - psa_status_t status = psa_load_rsa_representation( - slot->attr.type, - slot->key.data, - slot->key.bytes, - &rsa ); + psa_status_t status = mbedtls_psa_rsa_load_representation( + slot->attr.type, + slot->key.data, + slot->key.bytes, + &rsa ); if( status != PSA_SUCCESS ) return( status ); @@ -3982,10 +3979,10 @@ psa_status_t psa_sign_hash( mbedtls_svc_key_id_t key, { mbedtls_rsa_context *rsa = NULL; - status = psa_load_rsa_representation( slot->attr.type, - slot->key.data, - slot->key.bytes, - &rsa ); + status = mbedtls_psa_rsa_load_representation( slot->attr.type, + slot->key.data, + slot->key.bytes, + &rsa ); if( status != PSA_SUCCESS ) goto exit; @@ -4014,10 +4011,10 @@ psa_status_t psa_sign_hash( mbedtls_svc_key_id_t key, ) { mbedtls_ecp_keypair *ecp = NULL; - status = psa_load_ecp_representation( slot->attr.type, - slot->key.data, - slot->key.bytes, - &ecp ); + status = mbedtls_psa_ecp_load_representation( slot->attr.type, + slot->key.data, + slot->key.bytes, + &ecp ); if( status != PSA_SUCCESS ) goto exit; status = psa_ecdsa_sign( ecp, @@ -4092,10 +4089,10 @@ psa_status_t psa_verify_hash( mbedtls_svc_key_id_t key, { mbedtls_rsa_context *rsa = NULL; - status = psa_load_rsa_representation( slot->attr.type, - slot->key.data, - slot->key.bytes, - &rsa ); + status = mbedtls_psa_rsa_load_representation( slot->attr.type, + slot->key.data, + slot->key.bytes, + &rsa ); if( status != PSA_SUCCESS ) goto exit; @@ -4117,10 +4114,10 @@ psa_status_t psa_verify_hash( mbedtls_svc_key_id_t key, if( PSA_ALG_IS_ECDSA( alg ) ) { mbedtls_ecp_keypair *ecp = NULL; - status = psa_load_ecp_representation( slot->attr.type, - slot->key.data, - slot->key.bytes, - &ecp ); + status = mbedtls_psa_ecp_load_representation( slot->attr.type, + slot->key.data, + slot->key.bytes, + &ecp ); if( status != PSA_SUCCESS ) goto exit; status = psa_ecdsa_verify( ecp, @@ -4201,10 +4198,10 @@ psa_status_t psa_asymmetric_encrypt( mbedtls_svc_key_id_t key, if( PSA_KEY_TYPE_IS_RSA( slot->attr.type ) ) { mbedtls_rsa_context *rsa = NULL; - status = psa_load_rsa_representation( slot->attr.type, - slot->key.data, - slot->key.bytes, - &rsa ); + status = mbedtls_psa_rsa_load_representation( slot->attr.type, + slot->key.data, + slot->key.bytes, + &rsa ); if( status != PSA_SUCCESS ) goto rsa_exit; @@ -4307,10 +4304,10 @@ psa_status_t psa_asymmetric_decrypt( mbedtls_svc_key_id_t key, if( slot->attr.type == PSA_KEY_TYPE_RSA_KEY_PAIR ) { mbedtls_rsa_context *rsa = NULL; - status = psa_load_rsa_representation( slot->attr.type, - slot->key.data, - slot->key.bytes, - &rsa ); + status = mbedtls_psa_rsa_load_representation( slot->attr.type, + slot->key.data, + slot->key.bytes, + &rsa ); if( status != PSA_SUCCESS ) goto exit; @@ -6172,10 +6169,11 @@ static psa_status_t psa_key_agreement_ecdh( const uint8_t *peer_key, psa_ecc_family_t curve = mbedtls_ecc_group_to_psa( our_key->grp.id, &bits ); mbedtls_ecdh_init( &ecdh ); - status = psa_load_ecp_representation( PSA_KEY_TYPE_ECC_PUBLIC_KEY(curve), - peer_key, - peer_key_length, - &their_key ); + status = mbedtls_psa_ecp_load_representation( + PSA_KEY_TYPE_ECC_PUBLIC_KEY(curve), + peer_key, + peer_key_length, + &their_key ); if( status != PSA_SUCCESS ) goto exit; @@ -6227,11 +6225,11 @@ static psa_status_t psa_key_agreement_raw_internal( psa_algorithm_t alg, if( ! PSA_KEY_TYPE_IS_ECC_KEY_PAIR( private_key->attr.type ) ) return( PSA_ERROR_INVALID_ARGUMENT ); mbedtls_ecp_keypair *ecp = NULL; - psa_status_t status = psa_load_ecp_representation( - private_key->attr.type, - private_key->key.data, - private_key->key.bytes, - &ecp ); + psa_status_t status = mbedtls_psa_ecp_load_representation( + private_key->attr.type, + private_key->key.data, + private_key->key.bytes, + &ecp ); if( status != PSA_SUCCESS ) return( status ); status = psa_key_agreement_ecdh( peer_key, peer_key_length, From 3c8ca3ad00c666c6eb1d5beb1c4fbb90b764ba0c Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Thu, 26 Nov 2020 16:45:24 +0100 Subject: [PATCH 06/38] psa: Rename psa_export_rsa/ecp_key to mbedtls_psa_rsa/ecp_export_key Rename psa_export_rsa/ecp_key to mbedtls_psa_rsa/ecp_export_key before to move them to RSA/ECP specific PSA crypto C files. Signed-off-by: Ronald Cron --- library/psa_crypto.c | 74 ++++++++++++++++++++++---------------------- 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/library/psa_crypto.c b/library/psa_crypto.c index 78f9f272f..fa27a64a6 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -638,11 +638,11 @@ exit: * \param[in] data_size The length of the buffer to export to * \param[out] data_length The amount of bytes written to \p data */ -static psa_status_t psa_export_rsa_key( psa_key_type_t type, - mbedtls_rsa_context *rsa, - uint8_t *data, - size_t data_size, - size_t *data_length ) +static psa_status_t mbedtls_psa_rsa_export_key( psa_key_type_t type, + mbedtls_rsa_context *rsa, + uint8_t *data, + size_t data_size, + size_t *data_length ) { #if defined(MBEDTLS_PK_WRITE_C) int ret; @@ -730,11 +730,11 @@ static psa_status_t psa_import_rsa_key( psa_key_slot_t *slot, goto exit; } - status = psa_export_rsa_key( slot->attr.type, - rsa, - output, - data_length, - &data_length); + status = mbedtls_psa_rsa_export_key( slot->attr.type, + rsa, + output, + data_length, + &data_length); exit: /* Always free the RSA object */ mbedtls_rsa_free( rsa ); @@ -876,11 +876,11 @@ exit: * \param[in] data_size The length of the buffer to export to * \param[out] data_length The amount of bytes written to \p data */ -static psa_status_t psa_export_ecp_key( psa_key_type_t type, - mbedtls_ecp_keypair *ecp, - uint8_t *data, - size_t data_size, - size_t *data_length ) +static psa_status_t mbedtls_psa_ecp_export_key( psa_key_type_t type, + mbedtls_ecp_keypair *ecp, + uint8_t *data, + size_t data_size, + size_t *data_length ) { psa_status_t status; @@ -963,11 +963,11 @@ static psa_status_t psa_import_ecp_key( psa_key_slot_t *slot, goto exit; } - status = psa_export_ecp_key( slot->attr.type, - ecp, - output, - data_length, - &data_length); + status = mbedtls_psa_ecp_export_key( slot->attr.type, + ecp, + output, + data_length, + &data_length); exit: /* Always free the PK object (will also free contained ECP context) */ mbedtls_ecp_keypair_free( ecp ); @@ -1780,11 +1780,11 @@ static psa_status_t psa_internal_export_key( const psa_key_slot_t *slot, if( status != PSA_SUCCESS ) return( status ); - status = psa_export_rsa_key( PSA_KEY_TYPE_RSA_PUBLIC_KEY, - rsa, - data, - data_size, - data_length ); + status = mbedtls_psa_rsa_export_key( PSA_KEY_TYPE_RSA_PUBLIC_KEY, + rsa, + data, + data_size, + data_length ); mbedtls_rsa_free( rsa ); mbedtls_free( rsa ); @@ -1808,13 +1808,13 @@ static psa_status_t psa_internal_export_key( const psa_key_slot_t *slot, if( status != PSA_SUCCESS ) return( status ); - status = psa_export_ecp_key( PSA_KEY_TYPE_ECC_PUBLIC_KEY( - PSA_KEY_TYPE_ECC_GET_FAMILY( - slot->attr.type ) ), - ecp, - data, - data_size, - data_length ); + status = mbedtls_psa_ecp_export_key( + PSA_KEY_TYPE_ECC_PUBLIC_KEY( + PSA_KEY_TYPE_ECC_GET_FAMILY( slot->attr.type ) ), + ecp, + data, + data_size, + data_length ); mbedtls_ecp_keypair_free( ecp ); mbedtls_free( ecp ); @@ -6621,11 +6621,11 @@ static psa_status_t psa_generate_key_internal( return( status ); } - status = psa_export_rsa_key( type, - &rsa, - slot->key.data, - bytes, - &slot->key.bytes ); + status = mbedtls_psa_rsa_export_key( type, + &rsa, + slot->key.data, + bytes, + &slot->key.bytes ); mbedtls_rsa_free( &rsa ); if( status != PSA_SUCCESS ) psa_remove_key_data_from_memory( slot ); From 00b7bfc2c4d969dc08ea42c61fc4b5728cf957e3 Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Wed, 25 Nov 2020 15:25:26 +0100 Subject: [PATCH 07/38] psa: Move xxx_load_representation functions to RSA/ECP specific modules Signed-off-by: Ronald Cron --- library/CMakeLists.txt | 2 + library/Makefile | 2 + library/psa_crypto.c | 207 +-------------------------------- library/psa_crypto_ecp.c | 139 ++++++++++++++++++++++ library/psa_crypto_ecp.h | 41 +++++++ library/psa_crypto_rsa.c | 128 ++++++++++++++++++++ library/psa_crypto_rsa.h | 41 +++++++ visualc/VS2010/mbedTLS.vcxproj | 4 + 8 files changed, 359 insertions(+), 205 deletions(-) create mode 100644 library/psa_crypto_ecp.c create mode 100644 library/psa_crypto_ecp.h create mode 100644 library/psa_crypto_rsa.c create mode 100644 library/psa_crypto_rsa.h diff --git a/library/CMakeLists.txt b/library/CMakeLists.txt index b309b6e65..3ecbf9a7e 100644 --- a/library/CMakeLists.txt +++ b/library/CMakeLists.txt @@ -62,6 +62,8 @@ set(src_crypto poly1305.c psa_crypto.c psa_crypto_driver_wrappers.c + psa_crypto_ecp.c + psa_crypto_rsa.c psa_crypto_se.c psa_crypto_slot_management.c psa_crypto_storage.c diff --git a/library/Makefile b/library/Makefile index ae33bf2cc..5ef292320 100644 --- a/library/Makefile +++ b/library/Makefile @@ -119,6 +119,8 @@ OBJS_CRYPTO= \ poly1305.o \ psa_crypto.o \ psa_crypto_driver_wrappers.o \ + psa_crypto_ecp.o \ + psa_crypto_rsa.o \ psa_crypto_se.o \ psa_crypto_slot_management.o \ psa_crypto_storage.o \ diff --git a/library/psa_crypto.c b/library/psa_crypto.c index fa27a64a6..0d3ae4789 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -32,6 +32,8 @@ #include "psa_crypto_core.h" #include "psa_crypto_invasive.h" #include "psa_crypto_driver_wrappers.h" +#include "psa_crypto_ecp.h" +#include "psa_crypto_rsa.h" #if defined(MBEDTLS_PSA_CRYPTO_SE_C) #include "psa_crypto_se.h" #endif @@ -531,102 +533,6 @@ static psa_status_t validate_unstructured_key_bit_size( psa_key_type_t type, return( PSA_SUCCESS ); } -#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) || \ - defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) || \ - defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) || \ - defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS) || \ - defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) || \ - defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) - -/* Mbed TLS doesn't support non-byte-aligned key sizes (i.e. key sizes - * that are not a multiple of 8) well. For example, there is only - * mbedtls_rsa_get_len(), which returns a number of bytes, and no - * way to return the exact bit size of a key. - * To keep things simple, reject non-byte-aligned key sizes. */ -static psa_status_t psa_check_rsa_key_byte_aligned( - const mbedtls_rsa_context *rsa ) -{ - mbedtls_mpi n; - psa_status_t status; - mbedtls_mpi_init( &n ); - status = mbedtls_to_psa_error( - mbedtls_rsa_export( rsa, &n, NULL, NULL, NULL, NULL ) ); - if( status == PSA_SUCCESS ) - { - if( mbedtls_mpi_bitlen( &n ) % 8 != 0 ) - status = PSA_ERROR_NOT_SUPPORTED; - } - mbedtls_mpi_free( &n ); - return( status ); -} - -/** Load the contents of a key buffer into an internal RSA representation - * - * \param[in] type The type of key contained in \p data. - * \param[in] data The buffer from which to load the representation. - * \param[in] data_length The size in bytes of \p data. - * \param[out] p_rsa Returns a pointer to an RSA context on success. - * The caller is responsible for freeing both the - * contents of the context and the context itself - * when done. - */ -static psa_status_t mbedtls_psa_rsa_load_representation( - psa_key_type_t type, const uint8_t *data, size_t data_length, - mbedtls_rsa_context **p_rsa ) -{ - psa_status_t status; - mbedtls_pk_context ctx; - size_t bits; - mbedtls_pk_init( &ctx ); - - /* Parse the data. */ - if( PSA_KEY_TYPE_IS_KEY_PAIR( type ) ) - status = mbedtls_to_psa_error( - mbedtls_pk_parse_key( &ctx, data, data_length, NULL, 0 ) ); - else - status = mbedtls_to_psa_error( - mbedtls_pk_parse_public_key( &ctx, data, data_length ) ); - if( status != PSA_SUCCESS ) - goto exit; - - /* We have something that the pkparse module recognizes. If it is a - * valid RSA key, store it. */ - if( mbedtls_pk_get_type( &ctx ) != MBEDTLS_PK_RSA ) - { - status = PSA_ERROR_INVALID_ARGUMENT; - goto exit; - } - - /* The size of an RSA key doesn't have to be a multiple of 8. Mbed TLS - * supports non-byte-aligned key sizes, but not well. For example, - * mbedtls_rsa_get_len() returns the key size in bytes, not in bits. */ - bits = PSA_BYTES_TO_BITS( mbedtls_rsa_get_len( mbedtls_pk_rsa( ctx ) ) ); - if( bits > PSA_VENDOR_RSA_MAX_KEY_BITS ) - { - status = PSA_ERROR_NOT_SUPPORTED; - goto exit; - } - status = psa_check_rsa_key_byte_aligned( mbedtls_pk_rsa( ctx ) ); - if( status != PSA_SUCCESS ) - goto exit; - - /* Copy out the pointer to the RSA context, and reset the PK context - * such that pk_free doesn't free the RSA context we just grabbed. */ - *p_rsa = mbedtls_pk_rsa( ctx ); - ctx.pk_info = NULL; - -exit: - mbedtls_pk_free( &ctx ); - return( status ); -} - -#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) || - * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) || - * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) || - * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS) || - * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) || - * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) */ - #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) || \ defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) @@ -757,115 +663,6 @@ exit: #endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) || * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) */ -#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) || \ - defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) || \ - defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \ - defined(MBEDTLS_PSA_BUILTIN_ALG_ECDH) || \ - defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) -/** Load the contents of a key buffer into an internal ECP representation - * - * \param[in] type The type of key contained in \p data. - * \param[in] data The buffer from which to load the representation. - * \param[in] data_length The size in bytes of \p data. - * \param[out] p_ecp Returns a pointer to an ECP context on success. - * The caller is responsible for freeing both the - * contents of the context and the context itself - * when done. - */ -static psa_status_t mbedtls_psa_ecp_load_representation( - psa_key_type_t type, const uint8_t *data, size_t data_length, - mbedtls_ecp_keypair **p_ecp ) -{ - mbedtls_ecp_group_id grp_id = MBEDTLS_ECP_DP_NONE; - psa_status_t status; - mbedtls_ecp_keypair *ecp = NULL; - size_t curve_size = data_length; - - if( PSA_KEY_TYPE_IS_PUBLIC_KEY( type ) && - PSA_KEY_TYPE_ECC_GET_FAMILY( type ) != PSA_ECC_FAMILY_MONTGOMERY ) - { - /* A Weierstrass public key is represented as: - * - The byte 0x04; - * - `x_P` as a `ceiling(m/8)`-byte string, big-endian; - * - `y_P` as a `ceiling(m/8)`-byte string, big-endian. - * So its data length is 2m+1 where m is the curve size in bits. - */ - if( ( data_length & 1 ) == 0 ) - return( PSA_ERROR_INVALID_ARGUMENT ); - curve_size = data_length / 2; - - /* Montgomery public keys are represented in compressed format, meaning - * their curve_size is equal to the amount of input. */ - - /* Private keys are represented in uncompressed private random integer - * format, meaning their curve_size is equal to the amount of input. */ - } - - /* Allocate and initialize a key representation. */ - ecp = mbedtls_calloc( 1, sizeof( mbedtls_ecp_keypair ) ); - if( ecp == NULL ) - return( PSA_ERROR_INSUFFICIENT_MEMORY ); - mbedtls_ecp_keypair_init( ecp ); - - /* Load the group. */ - grp_id = mbedtls_ecc_group_of_psa( PSA_KEY_TYPE_ECC_GET_FAMILY( type ), - curve_size ); - if( grp_id == MBEDTLS_ECP_DP_NONE ) - { - status = PSA_ERROR_INVALID_ARGUMENT; - goto exit; - } - - status = mbedtls_to_psa_error( - mbedtls_ecp_group_load( &ecp->grp, grp_id ) ); - if( status != PSA_SUCCESS ) - goto exit; - - /* Load the key material. */ - if( PSA_KEY_TYPE_IS_PUBLIC_KEY( type ) ) - { - /* Load the public value. */ - status = mbedtls_to_psa_error( - mbedtls_ecp_point_read_binary( &ecp->grp, &ecp->Q, - data, - data_length ) ); - if( status != PSA_SUCCESS ) - goto exit; - - /* Check that the point is on the curve. */ - status = mbedtls_to_psa_error( - mbedtls_ecp_check_pubkey( &ecp->grp, &ecp->Q ) ); - if( status != PSA_SUCCESS ) - goto exit; - } - else - { - /* Load and validate the secret value. */ - status = mbedtls_to_psa_error( - mbedtls_ecp_read_key( ecp->grp.id, - ecp, - data, - data_length ) ); - if( status != PSA_SUCCESS ) - goto exit; - } - - *p_ecp = ecp; -exit: - if( status != PSA_SUCCESS ) - { - mbedtls_ecp_keypair_free( ecp ); - mbedtls_free( ecp ); - } - - return( status ); -} -#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) || - * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) || - * defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || - * defined(MBEDTLS_PSA_BUILTIN_ALG_ECDH) || - * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) */ - #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) || \ defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) /** Export an ECP key to export representation diff --git a/library/psa_crypto_ecp.c b/library/psa_crypto_ecp.c new file mode 100644 index 000000000..a4c6e140a --- /dev/null +++ b/library/psa_crypto_ecp.c @@ -0,0 +1,139 @@ +/* + * PSA ECP layer on top of Mbed TLS crypto + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "common.h" + +#if defined(MBEDTLS_PSA_CRYPTO_C) + +#include +#include "psa_crypto_core.h" +#include "psa_crypto_ecp.h" + +#include +#include +#include "mbedtls/platform.h" +#if !defined(MBEDTLS_PLATFORM_C) +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#include +#include + +#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) || \ + defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_ECDH) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) +psa_status_t mbedtls_psa_ecp_load_representation( + psa_key_type_t type, const uint8_t *data, size_t data_length, + mbedtls_ecp_keypair **p_ecp ) +{ + mbedtls_ecp_group_id grp_id = MBEDTLS_ECP_DP_NONE; + psa_status_t status; + mbedtls_ecp_keypair *ecp = NULL; + size_t curve_size = data_length; + + if( PSA_KEY_TYPE_IS_PUBLIC_KEY( type ) && + PSA_KEY_TYPE_ECC_GET_FAMILY( type ) != PSA_ECC_FAMILY_MONTGOMERY ) + { + /* A Weierstrass public key is represented as: + * - The byte 0x04; + * - `x_P` as a `ceiling(m/8)`-byte string, big-endian; + * - `y_P` as a `ceiling(m/8)`-byte string, big-endian. + * So its data length is 2m+1 where m is the curve size in bits. + */ + if( ( data_length & 1 ) == 0 ) + return( PSA_ERROR_INVALID_ARGUMENT ); + curve_size = data_length / 2; + + /* Montgomery public keys are represented in compressed format, meaning + * their curve_size is equal to the amount of input. */ + + /* Private keys are represented in uncompressed private random integer + * format, meaning their curve_size is equal to the amount of input. */ + } + + /* Allocate and initialize a key representation. */ + ecp = mbedtls_calloc( 1, sizeof( mbedtls_ecp_keypair ) ); + if( ecp == NULL ) + return( PSA_ERROR_INSUFFICIENT_MEMORY ); + mbedtls_ecp_keypair_init( ecp ); + + /* Load the group. */ + grp_id = mbedtls_ecc_group_of_psa( PSA_KEY_TYPE_ECC_GET_FAMILY( type ), + curve_size ); + if( grp_id == MBEDTLS_ECP_DP_NONE ) + { + status = PSA_ERROR_INVALID_ARGUMENT; + goto exit; + } + + status = mbedtls_to_psa_error( + mbedtls_ecp_group_load( &ecp->grp, grp_id ) ); + if( status != PSA_SUCCESS ) + goto exit; + + /* Load the key material. */ + if( PSA_KEY_TYPE_IS_PUBLIC_KEY( type ) ) + { + /* Load the public value. */ + status = mbedtls_to_psa_error( + mbedtls_ecp_point_read_binary( &ecp->grp, &ecp->Q, + data, + data_length ) ); + if( status != PSA_SUCCESS ) + goto exit; + + /* Check that the point is on the curve. */ + status = mbedtls_to_psa_error( + mbedtls_ecp_check_pubkey( &ecp->grp, &ecp->Q ) ); + if( status != PSA_SUCCESS ) + goto exit; + } + else + { + /* Load and validate the secret value. */ + status = mbedtls_to_psa_error( + mbedtls_ecp_read_key( ecp->grp.id, + ecp, + data, + data_length ) ); + if( status != PSA_SUCCESS ) + goto exit; + } + + *p_ecp = ecp; +exit: + if( status != PSA_SUCCESS ) + { + mbedtls_ecp_keypair_free( ecp ); + mbedtls_free( ecp ); + } + + return( status ); +} +#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) || + * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) || + * defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || + * defined(MBEDTLS_PSA_BUILTIN_ALG_ECDH) || + * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) */ + +#endif /* MBEDTLS_PSA_CRYPTO_C */ diff --git a/library/psa_crypto_ecp.h b/library/psa_crypto_ecp.h new file mode 100644 index 000000000..517933f52 --- /dev/null +++ b/library/psa_crypto_ecp.h @@ -0,0 +1,41 @@ +/* + * PSA ECP layer on top of Mbed TLS crypto + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef PSA_CRYPTO_ECP_H +#define PSA_CRYPTO_ECP_H + +#include +#include + +/** Load the contents of a key buffer into an internal ECP representation + * + * \param[in] type The type of key contained in \p data. + * \param[in] data The buffer from which to load the representation. + * \param[in] data_length The size in bytes of \p data. + * \param[out] p_ecp Returns a pointer to an ECP context on success. + * The caller is responsible for freeing both the + * contents of the context and the context itself + * when done. + */ +psa_status_t mbedtls_psa_ecp_load_representation( psa_key_type_t type, + const uint8_t *data, + size_t data_length, + mbedtls_ecp_keypair **p_ecp ); +#endif /* PSA_CRYPTO_ECP */ diff --git a/library/psa_crypto_rsa.c b/library/psa_crypto_rsa.c new file mode 100644 index 000000000..b4ea86a72 --- /dev/null +++ b/library/psa_crypto_rsa.c @@ -0,0 +1,128 @@ +/* + * PSA RSA layer on top of Mbed TLS crypto + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "common.h" + +#if defined(MBEDTLS_PSA_CRYPTO_C) + +#include +#include "psa_crypto_core.h" +#include "psa_crypto_rsa.h" + +#include +#include +#include "mbedtls/platform.h" +#if !defined(MBEDTLS_PLATFORM_C) +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#include +#include +#include +#include + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS) || \ + defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) || \ + defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) + +/* Mbed TLS doesn't support non-byte-aligned key sizes (i.e. key sizes + * that are not a multiple of 8) well. For example, there is only + * mbedtls_rsa_get_len(), which returns a number of bytes, and no + * way to return the exact bit size of a key. + * To keep things simple, reject non-byte-aligned key sizes. */ +static psa_status_t psa_check_rsa_key_byte_aligned( + const mbedtls_rsa_context *rsa ) +{ + mbedtls_mpi n; + psa_status_t status; + mbedtls_mpi_init( &n ); + status = mbedtls_to_psa_error( + mbedtls_rsa_export( rsa, &n, NULL, NULL, NULL, NULL ) ); + if( status == PSA_SUCCESS ) + { + if( mbedtls_mpi_bitlen( &n ) % 8 != 0 ) + status = PSA_ERROR_NOT_SUPPORTED; + } + mbedtls_mpi_free( &n ); + return( status ); +} + +psa_status_t mbedtls_psa_rsa_load_representation( + psa_key_type_t type, const uint8_t *data, size_t data_length, + mbedtls_rsa_context **p_rsa ) +{ + psa_status_t status; + mbedtls_pk_context ctx; + size_t bits; + mbedtls_pk_init( &ctx ); + + /* Parse the data. */ + if( PSA_KEY_TYPE_IS_KEY_PAIR( type ) ) + status = mbedtls_to_psa_error( + mbedtls_pk_parse_key( &ctx, data, data_length, NULL, 0 ) ); + else + status = mbedtls_to_psa_error( + mbedtls_pk_parse_public_key( &ctx, data, data_length ) ); + if( status != PSA_SUCCESS ) + goto exit; + + /* We have something that the pkparse module recognizes. If it is a + * valid RSA key, store it. */ + if( mbedtls_pk_get_type( &ctx ) != MBEDTLS_PK_RSA ) + { + status = PSA_ERROR_INVALID_ARGUMENT; + goto exit; + } + + /* The size of an RSA key doesn't have to be a multiple of 8. Mbed TLS + * supports non-byte-aligned key sizes, but not well. For example, + * mbedtls_rsa_get_len() returns the key size in bytes, not in bits. */ + bits = PSA_BYTES_TO_BITS( mbedtls_rsa_get_len( mbedtls_pk_rsa( ctx ) ) ); + if( bits > PSA_VENDOR_RSA_MAX_KEY_BITS ) + { + status = PSA_ERROR_NOT_SUPPORTED; + goto exit; + } + status = psa_check_rsa_key_byte_aligned( mbedtls_pk_rsa( ctx ) ); + if( status != PSA_SUCCESS ) + goto exit; + + /* Copy out the pointer to the RSA context, and reset the PK context + * such that pk_free doesn't free the RSA context we just grabbed. */ + *p_rsa = mbedtls_pk_rsa( ctx ); + ctx.pk_info = NULL; + +exit: + mbedtls_pk_free( &ctx ); + return( status ); +} + +#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) || + * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) || + * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) || + * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS) || + * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) || + * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) */ + +#endif /* MBEDTLS_PSA_CRYPTO_C */ diff --git a/library/psa_crypto_rsa.h b/library/psa_crypto_rsa.h new file mode 100644 index 000000000..2f6474c42 --- /dev/null +++ b/library/psa_crypto_rsa.h @@ -0,0 +1,41 @@ +/* + * PSA RSA layer on top of Mbed TLS crypto + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef PSA_CRYPTO_RSA_H +#define PSA_CRYPTO_RSA_H + +#include +#include + +/** Load the contents of a key buffer into an internal RSA representation + * + * \param[in] type The type of key contained in \p data. + * \param[in] data The buffer from which to load the representation. + * \param[in] data_length The size in bytes of \p data. + * \param[out] p_rsa Returns a pointer to an RSA context on success. + * The caller is responsible for freeing both the + * contents of the context and the context itself + * when done. + */ +psa_status_t mbedtls_psa_rsa_load_representation( psa_key_type_t type, + const uint8_t *data, + size_t data_length, + mbedtls_rsa_context **p_rsa ); +#endif /* PSA_CRYPTO_RSA_H */ diff --git a/visualc/VS2010/mbedTLS.vcxproj b/visualc/VS2010/mbedTLS.vcxproj index 78832eb6c..42cca8901 100644 --- a/visualc/VS2010/mbedTLS.vcxproj +++ b/visualc/VS2010/mbedTLS.vcxproj @@ -248,9 +248,11 @@ + + @@ -318,6 +320,8 @@ + + From 200a52c246046e7339cf4c547a347d1a8d41fa11 Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Wed, 25 Nov 2020 15:55:46 +0100 Subject: [PATCH 08/38] psa: Align naming of export internal functions Align naming of export internal functions with the way other psa_crypto.c internal functions are named, ending with _internal. Signed-off-by: Ronald Cron --- library/psa_crypto.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/library/psa_crypto.c b/library/psa_crypto.c index 0d3ae4789..faccca6a1 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -1481,7 +1481,7 @@ psa_status_t psa_get_key_slot_number( } #endif /* MBEDTLS_PSA_CRYPTO_SE_C */ -static psa_status_t psa_internal_export_key_buffer( const psa_key_slot_t *slot, +static psa_status_t psa_export_key_buffer_internal( const psa_key_slot_t *slot, uint8_t *data, size_t data_size, size_t *data_length ) @@ -1495,7 +1495,7 @@ static psa_status_t psa_internal_export_key_buffer( const psa_key_slot_t *slot, return( PSA_SUCCESS ); } -static psa_status_t psa_internal_export_key( const psa_key_slot_t *slot, +static psa_status_t psa_export_key_internal( const psa_key_slot_t *slot, uint8_t *data, size_t data_size, size_t *data_length, @@ -1536,7 +1536,7 @@ static psa_status_t psa_internal_export_key( const psa_key_slot_t *slot, if( key_type_is_raw_bytes( slot->attr.type ) ) { - return( psa_internal_export_key_buffer( slot, data, data_size, data_length ) ); + return( psa_export_key_buffer_internal( slot, data, data_size, data_length ) ); } else if( PSA_KEY_TYPE_IS_RSA( slot->attr.type ) || PSA_KEY_TYPE_IS_ECC( slot->attr.type ) ) @@ -1544,12 +1544,12 @@ static psa_status_t psa_internal_export_key( const psa_key_slot_t *slot, if( PSA_KEY_TYPE_IS_PUBLIC_KEY( slot->attr.type ) ) { /* Exporting public -> public */ - return( psa_internal_export_key_buffer( slot, data, data_size, data_length ) ); + return( psa_export_key_buffer_internal( slot, data, data_size, data_length ) ); } else if( !export_public_key ) { /* Exporting private -> private */ - return( psa_internal_export_key_buffer( slot, data, data_size, data_length ) ); + return( psa_export_key_buffer_internal( slot, data, data_size, data_length ) ); } /* Need to export the public part of a private key, @@ -1656,7 +1656,7 @@ psa_status_t psa_export_key( mbedtls_svc_key_id_t key, if( status != PSA_SUCCESS ) return( status ); - status = psa_internal_export_key( slot, data, data_size, data_length, 0 ); + status = psa_export_key_internal( slot, data, data_size, data_length, 0 ); unlock_status = psa_unlock_key_slot( slot ); return( ( status == PSA_SUCCESS ) ? unlock_status : status ); @@ -1682,7 +1682,7 @@ psa_status_t psa_export_public_key( mbedtls_svc_key_id_t key, if( status != PSA_SUCCESS ) return( status ); - status = psa_internal_export_key( slot, data, data_size, data_length, 1 ); + status = psa_export_key_internal( slot, data, data_size, data_length, 1 ); unlock_status = psa_unlock_key_slot( slot ); return( ( status == PSA_SUCCESS ) ? unlock_status : status ); From 9486f9d8f00e5c16009b7ba0bdf8669afc184131 Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Thu, 26 Nov 2020 13:36:23 +0100 Subject: [PATCH 09/38] psa: Disentangle public export and export code Disentangle public export and export code to be able to move the call to export and public export operations to the driver wrapper. Signed-off-by: Ronald Cron --- library/psa_crypto.c | 161 +++++++++++++++++++++++++++---------------- 1 file changed, 102 insertions(+), 59 deletions(-) diff --git a/library/psa_crypto.c b/library/psa_crypto.c index faccca6a1..e047489b5 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -1498,58 +1498,114 @@ static psa_status_t psa_export_key_buffer_internal( const psa_key_slot_t *slot, static psa_status_t psa_export_key_internal( const psa_key_slot_t *slot, uint8_t *data, size_t data_size, - size_t *data_length, - int export_public_key ) + size_t *data_length ) { #if defined(MBEDTLS_PSA_CRYPTO_SE_C) const psa_drv_se_t *drv; psa_drv_se_context_t *drv_context; #endif /* MBEDTLS_PSA_CRYPTO_SE_C */ +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + if( psa_get_se_driver( slot->attr.lifetime, &drv, &drv_context ) ) + { + if( ( drv->key_management == NULL ) || + ( drv->key_management->p_export == NULL ) ) + return( PSA_ERROR_NOT_SUPPORTED ); + + return( drv->key_management->p_export( + drv_context, psa_key_slot_get_slot_number( slot ), + data, data_size, data_length ) ); + } +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + + if( key_type_is_raw_bytes( slot->attr.type ) || + PSA_KEY_TYPE_IS_RSA( slot->attr.type ) || + PSA_KEY_TYPE_IS_ECC( slot->attr.type ) ) + { + return( psa_export_key_buffer_internal( + slot, data, data_size, data_length ) ); + } + else + { + /* This shouldn't happen in the reference implementation, but + it is valid for a special-purpose implementation to omit + support for exporting certain key types. */ + return( PSA_ERROR_NOT_SUPPORTED ); + } +} + +psa_status_t psa_export_key( mbedtls_svc_key_id_t key, + uint8_t *data, + size_t data_size, + size_t *data_length ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_slot_t *slot; + + /* Set the key to empty now, so that even when there are errors, we always + * set data_length to a value between 0 and data_size. On error, setting + * the key to empty is a good choice because an empty key representation is + * unlikely to be accepted anywhere. */ *data_length = 0; - if( export_public_key && ! PSA_KEY_TYPE_IS_ASYMMETRIC( slot->attr.type ) ) - return( PSA_ERROR_INVALID_ARGUMENT ); + /* Export requires the EXPORT flag. There is an exception for public keys, + * which don't require any flag, but + * psa_get_and_lock_key_slot_with_policy() takes care of this. + */ + status = psa_get_and_lock_key_slot_with_policy( key, &slot, + PSA_KEY_USAGE_EXPORT, 0 ); + if( status != PSA_SUCCESS ) + return( status ); /* Reject a zero-length output buffer now, since this can never be a * valid key representation. This way we know that data must be a valid * pointer and we can do things like memset(data, ..., data_size). */ if( data_size == 0 ) - return( PSA_ERROR_BUFFER_TOO_SMALL ); + { + status = PSA_ERROR_BUFFER_TOO_SMALL; + goto exit; + } + + status = psa_export_key_internal( slot, data, data_size, data_length ); + +exit: + unlock_status = psa_unlock_key_slot( slot ); + + return( ( status == PSA_SUCCESS ) ? unlock_status : status ); +} + +static psa_status_t psa_export_public_key_internal( const psa_key_slot_t *slot, + uint8_t *data, + size_t data_size, + size_t *data_length ) +{ +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + const psa_drv_se_t *drv; + psa_drv_se_context_t *drv_context; +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ #if defined(MBEDTLS_PSA_CRYPTO_SE_C) if( psa_get_se_driver( slot->attr.lifetime, &drv, &drv_context ) ) { - psa_drv_se_export_key_t method; - if( drv->key_management == NULL ) + if( ( drv->key_management == NULL ) || + ( drv->key_management->p_export_public == NULL ) ) return( PSA_ERROR_NOT_SUPPORTED ); - method = ( export_public_key ? - drv->key_management->p_export_public : - drv->key_management->p_export ); - if( method == NULL ) - return( PSA_ERROR_NOT_SUPPORTED ); - return( method( drv_context, - psa_key_slot_get_slot_number( slot ), - data, data_size, data_length ) ); - } -#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ - if( key_type_is_raw_bytes( slot->attr.type ) ) - { - return( psa_export_key_buffer_internal( slot, data, data_size, data_length ) ); + return( drv->key_management->p_export_public( + drv_context, psa_key_slot_get_slot_number( slot ), + data, data_size, data_length ) ); } - else if( PSA_KEY_TYPE_IS_RSA( slot->attr.type ) || + else +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + if( PSA_KEY_TYPE_IS_RSA( slot->attr.type ) || PSA_KEY_TYPE_IS_ECC( slot->attr.type ) ) { if( PSA_KEY_TYPE_IS_PUBLIC_KEY( slot->attr.type ) ) { /* Exporting public -> public */ - return( psa_export_key_buffer_internal( slot, data, data_size, data_length ) ); - } - else if( !export_public_key ) - { - /* Exporting private -> private */ - return( psa_export_key_buffer_internal( slot, data, data_size, data_length ) ); + return( psa_export_key_buffer_internal( + slot, data, data_size, data_length ) ); } /* Need to export the public part of a private key, @@ -1631,37 +1687,6 @@ static psa_status_t psa_export_key_internal( const psa_key_slot_t *slot, return( PSA_ERROR_NOT_SUPPORTED ); } } - -psa_status_t psa_export_key( mbedtls_svc_key_id_t key, - uint8_t *data, - size_t data_size, - size_t *data_length ) -{ - psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; - psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED; - psa_key_slot_t *slot; - - /* Set the key to empty now, so that even when there are errors, we always - * set data_length to a value between 0 and data_size. On error, setting - * the key to empty is a good choice because an empty key representation is - * unlikely to be accepted anywhere. */ - *data_length = 0; - - /* Export requires the EXPORT flag. There is an exception for public keys, - * which don't require any flag, but - * psa_get_and_lock_key_slot_with_policy() takes care of this. - */ - status = psa_get_and_lock_key_slot_with_policy( key, &slot, - PSA_KEY_USAGE_EXPORT, 0 ); - if( status != PSA_SUCCESS ) - return( status ); - - status = psa_export_key_internal( slot, data, data_size, data_length, 0 ); - unlock_status = psa_unlock_key_slot( slot ); - - return( ( status == PSA_SUCCESS ) ? unlock_status : status ); -} - psa_status_t psa_export_public_key( mbedtls_svc_key_id_t key, uint8_t *data, size_t data_size, @@ -1682,7 +1707,25 @@ psa_status_t psa_export_public_key( mbedtls_svc_key_id_t key, if( status != PSA_SUCCESS ) return( status ); - status = psa_export_key_internal( slot, data, data_size, data_length, 1 ); + if( ! PSA_KEY_TYPE_IS_ASYMMETRIC( slot->attr.type ) ) + { + status = PSA_ERROR_INVALID_ARGUMENT; + goto exit; + } + + /* Reject a zero-length output buffer now, since this can never be a + * valid key representation. This way we know that data must be a valid + * pointer and we can do things like memset(data, ..., data_size). */ + if( data_size == 0 ) + { + status = PSA_ERROR_BUFFER_TOO_SMALL; + goto exit; + } + + status = psa_export_public_key_internal( + slot, data, data_size, data_length ); + +exit: unlock_status = psa_unlock_key_slot( slot ); return( ( status == PSA_SUCCESS ) ? unlock_status : status ); From d18b5f84c6ca4c330ffd251cf2d7456ef9e91fca Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Wed, 25 Nov 2020 16:46:05 +0100 Subject: [PATCH 10/38] psa: Change psa_export_(public_)key_internal signature Change psa_export_(public_)key_internal signature to the signature of an export_(public_)key driver entry point. This is a preparatory commit to be able to call the software implementations as a driver. Signed-off-by: Ronald Cron --- library/psa_crypto.c | 146 +++++++++++++++++++++++++++++++------------ 1 file changed, 105 insertions(+), 41 deletions(-) diff --git a/library/psa_crypto.c b/library/psa_crypto.c index e047489b5..76d1a990e 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -1481,49 +1481,76 @@ psa_status_t psa_get_key_slot_number( } #endif /* MBEDTLS_PSA_CRYPTO_SE_C */ -static psa_status_t psa_export_key_buffer_internal( const psa_key_slot_t *slot, +static psa_status_t psa_export_key_buffer_internal( const uint8_t *key_buffer, + size_t key_buffer_size, uint8_t *data, size_t data_size, size_t *data_length ) { - if( slot->key.bytes > data_size ) + if( key_buffer_size > data_size ) return( PSA_ERROR_BUFFER_TOO_SMALL ); - memcpy( data, slot->key.data, slot->key.bytes ); - memset( data + slot->key.bytes, 0, - data_size - slot->key.bytes ); - *data_length = slot->key.bytes; + memcpy( data, key_buffer, key_buffer_size ); + memset( data + key_buffer_size, 0, + data_size - key_buffer_size ); + *data_length = key_buffer_size; return( PSA_SUCCESS ); } -static psa_status_t psa_export_key_internal( const psa_key_slot_t *slot, - uint8_t *data, - size_t data_size, - size_t *data_length ) +/** Export a key in binary format + * + * \note The signature of this function is that of a PSA driver export_key + * entry point. This function behaves as an export_key entry point as + * defined in the PSA driver interface specification. + * + * \param[in] attributes The attributes for the key to export. + * \param[in] key_buffer Material or context of the key to export. + * \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes. + * \param[out] data Buffer where the key data is to be written. + * \param[in] data_size Size of the \p data buffer in bytes. + * \param[out] data_length On success, the number of bytes written in + * \p data + * + * \retval #PSA_SUCCESS The key was exported successfully. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + */ +static psa_status_t psa_export_key_internal( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, size_t key_buffer_size, + uint8_t *data, size_t data_size, size_t *data_length ) { + psa_key_type_t type = attributes->core.type; + #if defined(MBEDTLS_PSA_CRYPTO_SE_C) const psa_drv_se_t *drv; psa_drv_se_context_t *drv_context; #endif /* MBEDTLS_PSA_CRYPTO_SE_C */ #if defined(MBEDTLS_PSA_CRYPTO_SE_C) - if( psa_get_se_driver( slot->attr.lifetime, &drv, &drv_context ) ) + if( psa_get_se_driver( attributes->core.lifetime, &drv, &drv_context ) ) { if( ( drv->key_management == NULL ) || ( drv->key_management->p_export == NULL ) ) return( PSA_ERROR_NOT_SUPPORTED ); return( drv->key_management->p_export( - drv_context, psa_key_slot_get_slot_number( slot ), + drv_context, + *( (psa_key_slot_number_t *)key_buffer ), data, data_size, data_length ) ); } #endif /* MBEDTLS_PSA_CRYPTO_SE_C */ - if( key_type_is_raw_bytes( slot->attr.type ) || - PSA_KEY_TYPE_IS_RSA( slot->attr.type ) || - PSA_KEY_TYPE_IS_ECC( slot->attr.type ) ) + if( key_type_is_raw_bytes( type ) || + PSA_KEY_TYPE_IS_RSA( type ) || + PSA_KEY_TYPE_IS_ECC( type ) ) { return( psa_export_key_buffer_internal( - slot, data, data_size, data_length ) ); + key_buffer, key_buffer_size, + data, data_size, data_length ) ); } else { @@ -1567,7 +1594,12 @@ psa_status_t psa_export_key( mbedtls_svc_key_id_t key, goto exit; } - status = psa_export_key_internal( slot, data, data_size, data_length ); + psa_key_attributes_t attributes = { + .core = slot->attr + }; + status = psa_export_key_internal( &attributes, + slot->key.data, slot->key.bytes, + data, data_size, data_length ); exit: unlock_status = psa_unlock_key_slot( slot ); @@ -1575,60 +1607,87 @@ exit: return( ( status == PSA_SUCCESS ) ? unlock_status : status ); } -static psa_status_t psa_export_public_key_internal( const psa_key_slot_t *slot, - uint8_t *data, - size_t data_size, - size_t *data_length ) +/** Export a public key or the public part of a key pair in binary format. + * + * \note The signature of this function is that of a PSA driver + * export_public_key entry point. This function behaves as an + * export_public_key entry point as defined in the PSA driver interface + * specification. + * + * \param[in] attributes The attributes for the key to export. + * \param[in] key_buffer Material or context of the key to export. + * \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes. + * \param[out] data Buffer where the key data is to be written. + * \param[in] data_size Size of the \p data buffer in bytes. + * \param[out] data_length On success, the number of bytes written in + * \p data + * + * \retval #PSA_SUCCESS The public key was exported successfully. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + */ +static psa_status_t psa_export_public_key_internal( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, + size_t key_buffer_size, + uint8_t *data, + size_t data_size, + size_t *data_length ) { + psa_key_type_t type = attributes->core.type; + psa_key_lifetime_t lifetime = attributes->core.lifetime; + #if defined(MBEDTLS_PSA_CRYPTO_SE_C) const psa_drv_se_t *drv; psa_drv_se_context_t *drv_context; #endif /* MBEDTLS_PSA_CRYPTO_SE_C */ #if defined(MBEDTLS_PSA_CRYPTO_SE_C) - if( psa_get_se_driver( slot->attr.lifetime, &drv, &drv_context ) ) + if( psa_get_se_driver( lifetime, &drv, &drv_context ) ) { if( ( drv->key_management == NULL ) || ( drv->key_management->p_export_public == NULL ) ) return( PSA_ERROR_NOT_SUPPORTED ); return( drv->key_management->p_export_public( - drv_context, psa_key_slot_get_slot_number( slot ), + drv_context, + *( (psa_key_slot_number_t *)key_buffer ), data, data_size, data_length ) ); } else #endif /* MBEDTLS_PSA_CRYPTO_SE_C */ - if( PSA_KEY_TYPE_IS_RSA( slot->attr.type ) || - PSA_KEY_TYPE_IS_ECC( slot->attr.type ) ) + if( PSA_KEY_TYPE_IS_RSA( type ) || PSA_KEY_TYPE_IS_ECC( type ) ) { - if( PSA_KEY_TYPE_IS_PUBLIC_KEY( slot->attr.type ) ) + if( PSA_KEY_TYPE_IS_PUBLIC_KEY( type ) ) { /* Exporting public -> public */ return( psa_export_key_buffer_internal( - slot, data, data_size, data_length ) ); + key_buffer, key_buffer_size, + data, data_size, data_length ) ); } /* Need to export the public part of a private key, * so conversion is needed. Try the accelerators first. */ - psa_key_attributes_t attributes = { - .core = slot->attr - }; psa_status_t status = psa_driver_wrapper_export_public_key( - &attributes, slot->key.data, slot->key.bytes, + attributes, key_buffer, key_buffer_size, data, data_size, data_length ); if( status != PSA_ERROR_NOT_SUPPORTED || - psa_key_lifetime_is_external( slot->attr.lifetime ) ) + psa_key_lifetime_is_external( lifetime ) ) return( status ); - if( PSA_KEY_TYPE_IS_RSA( slot->attr.type ) ) + if( PSA_KEY_TYPE_IS_RSA( type ) ) { #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) || \ defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) mbedtls_rsa_context *rsa = NULL; - status = mbedtls_psa_rsa_load_representation( slot->attr.type, - slot->key.data, - slot->key.bytes, + status = mbedtls_psa_rsa_load_representation( type, + key_buffer, + key_buffer_size, &rsa ); if( status != PSA_SUCCESS ) return( status ); @@ -1654,16 +1713,16 @@ static psa_status_t psa_export_public_key_internal( const psa_key_slot_t *slot, #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) || \ defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) mbedtls_ecp_keypair *ecp = NULL; - status = mbedtls_psa_ecp_load_representation( slot->attr.type, - slot->key.data, - slot->key.bytes, + status = mbedtls_psa_ecp_load_representation( type, + key_buffer, + key_buffer_size, &ecp ); if( status != PSA_SUCCESS ) return( status ); status = mbedtls_psa_ecp_export_key( PSA_KEY_TYPE_ECC_PUBLIC_KEY( - PSA_KEY_TYPE_ECC_GET_FAMILY( slot->attr.type ) ), + PSA_KEY_TYPE_ECC_GET_FAMILY( type ) ), ecp, data, data_size, @@ -1687,6 +1746,7 @@ static psa_status_t psa_export_public_key_internal( const psa_key_slot_t *slot, return( PSA_ERROR_NOT_SUPPORTED ); } } + psa_status_t psa_export_public_key( mbedtls_svc_key_id_t key, uint8_t *data, size_t data_size, @@ -1722,8 +1782,12 @@ psa_status_t psa_export_public_key( mbedtls_svc_key_id_t key, goto exit; } + psa_key_attributes_t attributes = { + .core = slot->attr + }; status = psa_export_public_key_internal( - slot, data, data_size, data_length ); + &attributes, slot->key.data, slot->key.bytes, + data, data_size, data_length ); exit: unlock_status = psa_unlock_key_slot( slot ); From 7285cda3873b7cb26385d6a7f4bd9fba72f0df9f Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Thu, 26 Nov 2020 14:46:37 +0100 Subject: [PATCH 11/38] psa: Export internally psa_export_(public_)key_internal Export psa_export_(public_)key_internal from psa_crypto.c to make it available to the driver wrapper. Signed-off-by: Ronald Cron --- library/psa_crypto.c | 49 ++-------------------------------- library/psa_crypto_core.h | 55 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 47 deletions(-) diff --git a/library/psa_crypto.c b/library/psa_crypto.c index 76d1a990e..2a4369aeb 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -1496,29 +1496,7 @@ static psa_status_t psa_export_key_buffer_internal( const uint8_t *key_buffer, return( PSA_SUCCESS ); } -/** Export a key in binary format - * - * \note The signature of this function is that of a PSA driver export_key - * entry point. This function behaves as an export_key entry point as - * defined in the PSA driver interface specification. - * - * \param[in] attributes The attributes for the key to export. - * \param[in] key_buffer Material or context of the key to export. - * \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes. - * \param[out] data Buffer where the key data is to be written. - * \param[in] data_size Size of the \p data buffer in bytes. - * \param[out] data_length On success, the number of bytes written in - * \p data - * - * \retval #PSA_SUCCESS The key was exported successfully. - * \retval #PSA_ERROR_NOT_SUPPORTED - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - */ -static psa_status_t psa_export_key_internal( +psa_status_t psa_export_key_internal( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, uint8_t *data, size_t data_size, size_t *data_length ) @@ -1607,30 +1585,7 @@ exit: return( ( status == PSA_SUCCESS ) ? unlock_status : status ); } -/** Export a public key or the public part of a key pair in binary format. - * - * \note The signature of this function is that of a PSA driver - * export_public_key entry point. This function behaves as an - * export_public_key entry point as defined in the PSA driver interface - * specification. - * - * \param[in] attributes The attributes for the key to export. - * \param[in] key_buffer Material or context of the key to export. - * \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes. - * \param[out] data Buffer where the key data is to be written. - * \param[in] data_size Size of the \p data buffer in bytes. - * \param[out] data_length On success, the number of bytes written in - * \p data - * - * \retval #PSA_SUCCESS The public key was exported successfully. - * \retval #PSA_ERROR_NOT_SUPPORTED - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_CORRUPTION_DETECTED - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - */ -static psa_status_t psa_export_public_key_internal( +psa_status_t psa_export_public_key_internal( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, diff --git a/library/psa_crypto_core.h b/library/psa_crypto_core.h index 3f266f392..ca8cd6bee 100644 --- a/library/psa_crypto_core.h +++ b/library/psa_crypto_core.h @@ -212,4 +212,59 @@ psa_status_t psa_copy_key_material_into_slot( psa_key_slot_t *slot, */ psa_status_t mbedtls_to_psa_error( int ret ); +/** Export a key in binary format + * + * \note The signature of this function is that of a PSA driver export_key + * entry point. This function behaves as an export_key entry point as + * defined in the PSA driver interface specification. + * + * \param[in] attributes The attributes for the key to export. + * \param[in] key_buffer Material or context of the key to export. + * \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes. + * \param[out] data Buffer where the key data is to be written. + * \param[in] data_size Size of the \p data buffer in bytes. + * \param[out] data_length On success, the number of bytes written in + * \p data + * + * \retval #PSA_SUCCESS The key was exported successfully. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + */ +psa_status_t psa_export_key_internal( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, size_t key_buffer_size, + uint8_t *data, size_t data_size, size_t *data_length ); + +/** Export a public key or the public part of a key pair in binary format. + * + * \note The signature of this function is that of a PSA driver + * export_public_key entry point. This function behaves as an + * export_public_key entry point as defined in the PSA driver interface + * specification. + * + * \param[in] attributes The attributes for the key to export. + * \param[in] key_buffer Material or context of the key to export. + * \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes. + * \param[out] data Buffer where the key data is to be written. + * \param[in] data_size Size of the \p data buffer in bytes. + * \param[out] data_length On success, the number of bytes written in + * \p data + * + * \retval #PSA_SUCCESS The public key was exported successfully. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + */ +psa_status_t psa_export_public_key_internal( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, size_t key_buffer_size, + uint8_t *data, size_t data_size, size_t *data_length ); + #endif /* PSA_CRYPTO_CORE_H */ From 672279829a891d3a663f71b506d3cf603d51b819 Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Thu, 26 Nov 2020 15:16:05 +0100 Subject: [PATCH 12/38] psa: Call export software implementation as a driver Signed-off-by: Ronald Cron --- library/psa_crypto.c | 16 ++---- library/psa_crypto_driver_wrappers.c | 60 +++++++++++++++++---- library/psa_crypto_driver_wrappers.h | 5 ++ tests/include/test/drivers/key_management.h | 5 ++ tests/src/drivers/key_management.c | 13 +++++ 5 files changed, 75 insertions(+), 24 deletions(-) diff --git a/library/psa_crypto.c b/library/psa_crypto.c index 2a4369aeb..10b55b8a9 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -1575,7 +1575,7 @@ psa_status_t psa_export_key( mbedtls_svc_key_id_t key, psa_key_attributes_t attributes = { .core = slot->attr }; - status = psa_export_key_internal( &attributes, + status = psa_driver_wrapper_export_key( &attributes, slot->key.data, slot->key.bytes, data, data_size, data_length ); @@ -1593,8 +1593,8 @@ psa_status_t psa_export_public_key_internal( size_t data_size, size_t *data_length ) { + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_type_t type = attributes->core.type; - psa_key_lifetime_t lifetime = attributes->core.lifetime; #if defined(MBEDTLS_PSA_CRYPTO_SE_C) const psa_drv_se_t *drv; @@ -1625,16 +1625,6 @@ psa_status_t psa_export_public_key_internal( data, data_size, data_length ) ); } - /* Need to export the public part of a private key, - * so conversion is needed. Try the accelerators first. */ - psa_status_t status = psa_driver_wrapper_export_public_key( - attributes, key_buffer, key_buffer_size, - data, data_size, data_length ); - - if( status != PSA_ERROR_NOT_SUPPORTED || - psa_key_lifetime_is_external( lifetime ) ) - return( status ); - if( PSA_KEY_TYPE_IS_RSA( type ) ) { #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) || \ @@ -1740,7 +1730,7 @@ psa_status_t psa_export_public_key( mbedtls_svc_key_id_t key, psa_key_attributes_t attributes = { .core = slot->attr }; - status = psa_export_public_key_internal( + status = psa_driver_wrapper_export_public_key( &attributes, slot->key.data, slot->key.bytes, data, data_size, data_length ); diff --git a/library/psa_crypto_driver_wrappers.c b/library/psa_crypto_driver_wrappers.c index a58967a1d..766cf108a 100644 --- a/library/psa_crypto_driver_wrappers.c +++ b/library/psa_crypto_driver_wrappers.c @@ -444,13 +444,50 @@ psa_status_t psa_driver_wrapper_import_key( #endif /* PSA_CRYPTO_DRIVER_PRESENT */ } +psa_status_t psa_driver_wrapper_export_key( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, size_t key_buffer_size, + uint8_t *data, size_t data_size, size_t *data_length ) + +{ + psa_status_t status = PSA_ERROR_INVALID_ARGUMENT; + psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( + psa_get_key_lifetime( attributes ) ); + + switch( location ) + { + case PSA_KEY_LOCATION_LOCAL_STORAGE: + return( psa_export_key_internal( attributes, + key_buffer, + key_buffer_size, + data, + data_size, + data_length ) ); + + /* Add cases for opaque driver here */ +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +#if defined(PSA_CRYPTO_DRIVER_TEST) + case PSA_CRYPTO_TEST_DRIVER_LIFETIME: + return( test_opaque_export_key( attributes, + key_buffer, + key_buffer_size, + data, + data_size, + data_length ) ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + default: + /* Key is declared with a lifetime not known to us */ + return( status ); + } +} + psa_status_t psa_driver_wrapper_export_public_key( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, uint8_t *data, size_t data_size, size_t *data_length ) { -#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) psa_status_t status = PSA_ERROR_INVALID_ARGUMENT; psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime( attributes ) ); @@ -460,6 +497,7 @@ psa_status_t psa_driver_wrapper_export_public_key( case PSA_KEY_LOCATION_LOCAL_STORAGE: /* Key is stored in the slot in export representation, so * cycle through all known transparent accelerators */ +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) status = test_transparent_export_public_key( attributes, key_buffer, @@ -471,9 +509,17 @@ psa_status_t psa_driver_wrapper_export_public_key( if( status != PSA_ERROR_NOT_SUPPORTED ) return( status ); #endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ /* Fell through, meaning no accelerator supports this operation */ - return( PSA_ERROR_NOT_SUPPORTED ); + return( psa_export_public_key_internal( attributes, + key_buffer, + key_buffer_size, + data, + data_size, + data_length ) ); + /* Add cases for opaque driver here */ +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) #if defined(PSA_CRYPTO_DRIVER_TEST) case PSA_CRYPTO_TEST_DRIVER_LIFETIME: return( test_opaque_export_public_key( attributes, @@ -483,19 +529,11 @@ psa_status_t psa_driver_wrapper_export_public_key( data_size, data_length ) ); #endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ default: /* Key is declared with a lifetime not known to us */ return( status ); } -#else /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ - (void) attributes; - (void) key_buffer; - (void) key_buffer_size; - (void) data; - (void) data_size; - (void) data_length; - return( PSA_ERROR_NOT_SUPPORTED ); -#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ } /* diff --git a/library/psa_crypto_driver_wrappers.h b/library/psa_crypto_driver_wrappers.h index fb32b8d14..27d8b64ea 100644 --- a/library/psa_crypto_driver_wrappers.h +++ b/library/psa_crypto_driver_wrappers.h @@ -53,6 +53,11 @@ psa_status_t psa_driver_wrapper_import_key( uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length, size_t *bits ); +psa_status_t psa_driver_wrapper_export_key( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, size_t key_buffer_size, + uint8_t *data, size_t data_size, size_t *data_length ); + psa_status_t psa_driver_wrapper_export_public_key( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, diff --git a/tests/include/test/drivers/key_management.h b/tests/include/test/drivers/key_management.h index 7811fb439..9d5175815 100644 --- a/tests/include/test/drivers/key_management.h +++ b/tests/include/test/drivers/key_management.h @@ -58,6 +58,11 @@ psa_status_t test_opaque_generate_key( const psa_key_attributes_t *attributes, uint8_t *key, size_t key_size, size_t *key_length ); +psa_status_t test_opaque_export_key( + const psa_key_attributes_t *attributes, + const uint8_t *key, size_t key_length, + uint8_t *data, size_t data_size, size_t *data_length ); + psa_status_t test_transparent_export_public_key( const psa_key_attributes_t *attributes, const uint8_t *key, size_t key_length, diff --git a/tests/src/drivers/key_management.c b/tests/src/drivers/key_management.c index ab3210b71..76d2b3fee 100644 --- a/tests/src/drivers/key_management.c +++ b/tests/src/drivers/key_management.c @@ -252,6 +252,19 @@ ecp_exit: * MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_PUBLIC_KEY */ } +psa_status_t test_opaque_export_key( + const psa_key_attributes_t *attributes, + const uint8_t *key, size_t key_length, + uint8_t *data, size_t data_size, size_t *data_length ) +{ + (void) attributes; + (void) key; + (void) key_length; + (void) data; + (void) data_size; + (void) data_length; + return( PSA_ERROR_NOT_SUPPORTED ); +} psa_status_t test_transparent_export_public_key( const psa_key_attributes_t *attributes, const uint8_t *key, size_t key_length, From 152e3f82e77a86831c22068360c0e74741c50d1b Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Thu, 26 Nov 2020 16:06:41 +0100 Subject: [PATCH 13/38] psa: export: Move registered SE support to the driver wrapper Signed-off-by: Ronald Cron --- library/psa_crypto.c | 38 ---------------------------- library/psa_crypto_driver_wrappers.c | 36 ++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 38 deletions(-) diff --git a/library/psa_crypto.c b/library/psa_crypto.c index 10b55b8a9..27cc3c4f1 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -1503,25 +1503,6 @@ psa_status_t psa_export_key_internal( { psa_key_type_t type = attributes->core.type; -#if defined(MBEDTLS_PSA_CRYPTO_SE_C) - const psa_drv_se_t *drv; - psa_drv_se_context_t *drv_context; -#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ - -#if defined(MBEDTLS_PSA_CRYPTO_SE_C) - if( psa_get_se_driver( attributes->core.lifetime, &drv, &drv_context ) ) - { - if( ( drv->key_management == NULL ) || - ( drv->key_management->p_export == NULL ) ) - return( PSA_ERROR_NOT_SUPPORTED ); - - return( drv->key_management->p_export( - drv_context, - *( (psa_key_slot_number_t *)key_buffer ), - data, data_size, data_length ) ); - } -#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ - if( key_type_is_raw_bytes( type ) || PSA_KEY_TYPE_IS_RSA( type ) || PSA_KEY_TYPE_IS_ECC( type ) ) @@ -1596,25 +1577,6 @@ psa_status_t psa_export_public_key_internal( psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_type_t type = attributes->core.type; -#if defined(MBEDTLS_PSA_CRYPTO_SE_C) - const psa_drv_se_t *drv; - psa_drv_se_context_t *drv_context; -#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ - -#if defined(MBEDTLS_PSA_CRYPTO_SE_C) - if( psa_get_se_driver( lifetime, &drv, &drv_context ) ) - { - if( ( drv->key_management == NULL ) || - ( drv->key_management->p_export_public == NULL ) ) - return( PSA_ERROR_NOT_SUPPORTED ); - - return( drv->key_management->p_export_public( - drv_context, - *( (psa_key_slot_number_t *)key_buffer ), - data, data_size, data_length ) ); - } - else -#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ if( PSA_KEY_TYPE_IS_RSA( type ) || PSA_KEY_TYPE_IS_ECC( type ) ) { if( PSA_KEY_TYPE_IS_PUBLIC_KEY( type ) ) diff --git a/library/psa_crypto_driver_wrappers.c b/library/psa_crypto_driver_wrappers.c index 766cf108a..0cc89fe7f 100644 --- a/library/psa_crypto_driver_wrappers.c +++ b/library/psa_crypto_driver_wrappers.c @@ -454,6 +454,24 @@ psa_status_t psa_driver_wrapper_export_key( psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime( attributes ) ); + /* Try dynamically-registered SE interface first */ +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + const psa_drv_se_t *drv; + psa_drv_se_context_t *drv_context; + + if( psa_get_se_driver( attributes->core.lifetime, &drv, &drv_context ) ) + { + if( ( drv->key_management == NULL ) || + ( drv->key_management->p_export == NULL ) ) + return( PSA_ERROR_NOT_SUPPORTED ); + + return( drv->key_management->p_export( + drv_context, + *( (psa_key_slot_number_t *)key_buffer ), + data, data_size, data_length ) ); + } +#endif /* PSA_CRYPTO_SE_C */ + switch( location ) { case PSA_KEY_LOCATION_LOCAL_STORAGE: @@ -492,6 +510,24 @@ psa_status_t psa_driver_wrapper_export_public_key( psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime( attributes ) ); + /* Try dynamically-registered SE interface first */ +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + const psa_drv_se_t *drv; + psa_drv_se_context_t *drv_context; + + if( psa_get_se_driver( attributes->core.lifetime, &drv, &drv_context ) ) + { + if( ( drv->key_management == NULL ) || + ( drv->key_management->p_export_public == NULL ) ) + return( PSA_ERROR_NOT_SUPPORTED ); + + return( drv->key_management->p_export_public( + drv_context, + *( (psa_key_slot_number_t *)key_buffer ), + data, data_size, data_length ) ); + } +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + switch( location ) { case PSA_KEY_LOCATION_LOCAL_STORAGE: From e5ca3d853370117636b4d3fbbd785a8138e182a4 Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Thu, 26 Nov 2020 16:36:16 +0100 Subject: [PATCH 14/38] psa: Move RSA/ECP export code to RSA/ECP specific C file Signed-off-by: Ronald Cron --- library/psa_crypto.c | 171 +++------------------------------------ library/psa_crypto_ecp.c | 80 ++++++++++++++++++ library/psa_crypto_ecp.h | 46 ++++++++++- library/psa_crypto_rsa.c | 86 +++++++++++++++++++- library/psa_crypto_rsa.h | 44 ++++++++++ 5 files changed, 266 insertions(+), 161 deletions(-) diff --git a/library/psa_crypto.c b/library/psa_crypto.c index 27cc3c4f1..5323bb3d4 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -536,70 +536,6 @@ static psa_status_t validate_unstructured_key_bit_size( psa_key_type_t type, #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) || \ defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) -/** Export an RSA key to export representation - * - * \param[in] type The type of key (public/private) to export - * \param[in] rsa The internal RSA representation from which to export - * \param[out] data The buffer to export to - * \param[in] data_size The length of the buffer to export to - * \param[out] data_length The amount of bytes written to \p data - */ -static psa_status_t mbedtls_psa_rsa_export_key( psa_key_type_t type, - mbedtls_rsa_context *rsa, - uint8_t *data, - size_t data_size, - size_t *data_length ) -{ -#if defined(MBEDTLS_PK_WRITE_C) - int ret; - mbedtls_pk_context pk; - uint8_t *pos = data + data_size; - - mbedtls_pk_init( &pk ); - pk.pk_info = &mbedtls_rsa_info; - pk.pk_ctx = rsa; - - /* PSA Crypto API defines the format of an RSA key as a DER-encoded - * representation of the non-encrypted PKCS#1 RSAPrivateKey for a - * private key and of the RFC3279 RSAPublicKey for a public key. */ - if( PSA_KEY_TYPE_IS_KEY_PAIR( type ) ) - ret = mbedtls_pk_write_key_der( &pk, data, data_size ); - else - ret = mbedtls_pk_write_pubkey( &pos, data, &pk ); - - if( ret < 0 ) - { - /* Clean up in case pk_write failed halfway through. */ - memset( data, 0, data_size ); - return( mbedtls_to_psa_error( ret ) ); - } - - /* The mbedtls_pk_xxx functions write to the end of the buffer. - * Move the data to the beginning and erase remaining data - * at the original location. */ - if( 2 * (size_t) ret <= data_size ) - { - memcpy( data, data + data_size - ret, ret ); - memset( data + data_size - ret, 0, ret ); - } - else if( (size_t) ret < data_size ) - { - memmove( data, data + data_size - ret, ret ); - memset( data + ret, 0, data_size - ret ); - } - - *data_length = ret; - return( PSA_SUCCESS ); -#else - (void) type; - (void) rsa; - (void) data; - (void) data_size; - (void) data_length; - return( PSA_ERROR_NOT_SUPPORTED ); -#endif /* MBEDTLS_PK_WRITE_C */ -} - /** Import an RSA key from import representation to a slot * * \param[in,out] slot The slot where to store the export representation to @@ -665,63 +601,6 @@ exit: #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) || \ defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) -/** Export an ECP key to export representation - * - * \param[in] type The type of key (public/private) to export - * \param[in] ecp The internal ECP representation from which to export - * \param[out] data The buffer to export to - * \param[in] data_size The length of the buffer to export to - * \param[out] data_length The amount of bytes written to \p data - */ -static psa_status_t mbedtls_psa_ecp_export_key( psa_key_type_t type, - mbedtls_ecp_keypair *ecp, - uint8_t *data, - size_t data_size, - size_t *data_length ) -{ - psa_status_t status; - - if( PSA_KEY_TYPE_IS_PUBLIC_KEY( type ) ) - { - /* Check whether the public part is loaded */ - if( mbedtls_ecp_is_zero( &ecp->Q ) ) - { - /* Calculate the public key */ - status = mbedtls_to_psa_error( - mbedtls_ecp_mul( &ecp->grp, &ecp->Q, &ecp->d, &ecp->grp.G, - mbedtls_psa_get_random, MBEDTLS_PSA_RANDOM_STATE ) ); - if( status != PSA_SUCCESS ) - return( status ); - } - - status = mbedtls_to_psa_error( - mbedtls_ecp_point_write_binary( &ecp->grp, &ecp->Q, - MBEDTLS_ECP_PF_UNCOMPRESSED, - data_length, - data, - data_size ) ); - if( status != PSA_SUCCESS ) - memset( data, 0, data_size ); - - return( status ); - } - else - { - if( data_size < PSA_BITS_TO_BYTES( ecp->grp.nbits ) ) - return( PSA_ERROR_BUFFER_TOO_SMALL ); - - status = mbedtls_to_psa_error( - mbedtls_ecp_write_key( ecp, - data, - PSA_BITS_TO_BYTES( ecp->grp.nbits ) ) ); - if( status == PSA_SUCCESS ) - *data_length = PSA_BITS_TO_BYTES( ecp->grp.nbits ); - else - memset( data, 0, data_size ); - - return( status ); - } -} /** Import an ECP key from import representation to a slot * @@ -1574,7 +1453,6 @@ psa_status_t psa_export_public_key_internal( size_t data_size, size_t *data_length ) { - psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_type_t type = attributes->core.type; if( PSA_KEY_TYPE_IS_RSA( type ) || PSA_KEY_TYPE_IS_ECC( type ) ) @@ -1591,24 +1469,12 @@ psa_status_t psa_export_public_key_internal( { #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) || \ defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) - mbedtls_rsa_context *rsa = NULL; - status = mbedtls_psa_rsa_load_representation( type, - key_buffer, - key_buffer_size, - &rsa ); - if( status != PSA_SUCCESS ) - return( status ); - - status = mbedtls_psa_rsa_export_key( PSA_KEY_TYPE_RSA_PUBLIC_KEY, - rsa, - data, - data_size, - data_length ); - - mbedtls_rsa_free( rsa ); - mbedtls_free( rsa ); - - return( status ); + return( mbedtls_psa_rsa_export_public_key( attributes, + key_buffer, + key_buffer_size, + data, + data_size, + data_length ) ); #else /* We don't know how to convert a private RSA key to public. */ return( PSA_ERROR_NOT_SUPPORTED ); @@ -1619,25 +1485,12 @@ psa_status_t psa_export_public_key_internal( { #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) || \ defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) - mbedtls_ecp_keypair *ecp = NULL; - status = mbedtls_psa_ecp_load_representation( type, - key_buffer, - key_buffer_size, - &ecp ); - if( status != PSA_SUCCESS ) - return( status ); - - status = mbedtls_psa_ecp_export_key( - PSA_KEY_TYPE_ECC_PUBLIC_KEY( - PSA_KEY_TYPE_ECC_GET_FAMILY( type ) ), - ecp, - data, - data_size, - data_length ); - - mbedtls_ecp_keypair_free( ecp ); - mbedtls_free( ecp ); - return( status ); + return( mbedtls_psa_ecp_export_public_key( attributes, + key_buffer, + key_buffer_size, + data, + data_size, + data_length ) ); #else /* We don't know how to convert a private ECC key to public */ return( PSA_ERROR_NOT_SUPPORTED ); diff --git a/library/psa_crypto_ecp.c b/library/psa_crypto_ecp.c index a4c6e140a..4f206214c 100644 --- a/library/psa_crypto_ecp.c +++ b/library/psa_crypto_ecp.c @@ -25,6 +25,7 @@ #include #include "psa_crypto_core.h" #include "psa_crypto_ecp.h" +#include "psa_crypto_random_impl.h" #include #include @@ -136,4 +137,83 @@ exit: * defined(MBEDTLS_PSA_BUILTIN_ALG_ECDH) || * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) */ +#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) || \ + defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) +psa_status_t mbedtls_psa_ecp_export_key( psa_key_type_t type, + mbedtls_ecp_keypair *ecp, + uint8_t *data, + size_t data_size, + size_t *data_length ) +{ + psa_status_t status; + + if( PSA_KEY_TYPE_IS_PUBLIC_KEY( type ) ) + { + /* Check whether the public part is loaded */ + if( mbedtls_ecp_is_zero( &ecp->Q ) ) + { + /* Calculate the public key */ + status = mbedtls_to_psa_error( + mbedtls_ecp_mul( &ecp->grp, &ecp->Q, &ecp->d, &ecp->grp.G, + mbedtls_psa_get_random, + MBEDTLS_PSA_RANDOM_STATE ) ); + if( status != PSA_SUCCESS ) + return( status ); + } + + status = mbedtls_to_psa_error( + mbedtls_ecp_point_write_binary( &ecp->grp, &ecp->Q, + MBEDTLS_ECP_PF_UNCOMPRESSED, + data_length, + data, + data_size ) ); + if( status != PSA_SUCCESS ) + memset( data, 0, data_size ); + + return( status ); + } + else + { + if( data_size < PSA_BITS_TO_BYTES( ecp->grp.nbits ) ) + return( PSA_ERROR_BUFFER_TOO_SMALL ); + + status = mbedtls_to_psa_error( + mbedtls_ecp_write_key( ecp, + data, + PSA_BITS_TO_BYTES( ecp->grp.nbits ) ) ); + if( status == PSA_SUCCESS ) + *data_length = PSA_BITS_TO_BYTES( ecp->grp.nbits ); + else + memset( data, 0, data_size ); + + return( status ); + } +} + +psa_status_t mbedtls_psa_ecp_export_public_key( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, size_t key_buffer_size, + uint8_t *data, size_t data_size, size_t *data_length ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + mbedtls_ecp_keypair *ecp = NULL; + + status = mbedtls_psa_ecp_load_representation( + attributes->core.type, key_buffer, key_buffer_size, &ecp ); + if( status != PSA_SUCCESS ) + return( status ); + + status = mbedtls_psa_ecp_export_key( + PSA_KEY_TYPE_ECC_PUBLIC_KEY( + PSA_KEY_TYPE_ECC_GET_FAMILY( attributes->core.type ) ), + ecp, data, data_size, data_length ); + + mbedtls_ecp_keypair_free( ecp ); + mbedtls_free( ecp ); + + return( status ); +} +#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) || + * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) */ + #endif /* MBEDTLS_PSA_CRYPTO_C */ diff --git a/library/psa_crypto_ecp.h b/library/psa_crypto_ecp.h index 517933f52..c6d8437a8 100644 --- a/library/psa_crypto_ecp.h +++ b/library/psa_crypto_ecp.h @@ -38,4 +38,48 @@ psa_status_t mbedtls_psa_ecp_load_representation( psa_key_type_t type, const uint8_t *data, size_t data_length, mbedtls_ecp_keypair **p_ecp ); -#endif /* PSA_CRYPTO_ECP */ + +/** Export an ECP key to export representation + * + * \param[in] type The type of key (public/private) to export + * \param[in] ecp The internal ECP representation from which to export + * \param[out] data The buffer to export to + * \param[in] data_size The length of the buffer to export to + * \param[out] data_length The amount of bytes written to \p data + */ +psa_status_t mbedtls_psa_ecp_export_key( psa_key_type_t type, + mbedtls_ecp_keypair *ecp, + uint8_t *data, + size_t data_size, + size_t *data_length ); + +/** Export an ECP public key or the public part of an ECP key pair in binary + * format. + * + * \note The signature of this function is that of a PSA driver + * export_public_key entry point. This function behaves as an + * export_public_key entry point as defined in the PSA driver interface + * specification. + * + * \param[in] attributes The attributes for the key to export. + * \param[in] key_buffer Material or context of the key to export. + * \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes. + * \param[out] data Buffer where the key data is to be written. + * \param[in] data_size Size of the \p data buffer in bytes. + * \param[out] data_length On success, the number of bytes written in + * \p data + * + * \retval #PSA_SUCCESS The ECP public key was exported successfully. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + */ +psa_status_t mbedtls_psa_ecp_export_public_key( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, size_t key_buffer_size, + uint8_t *data, size_t data_size, size_t *data_length ); + +#endif /* PSA_CRYPTO_ECP_H */ diff --git a/library/psa_crypto_rsa.c b/library/psa_crypto_rsa.c index b4ea86a72..3e5d1b41b 100644 --- a/library/psa_crypto_rsa.c +++ b/library/psa_crypto_rsa.c @@ -117,7 +117,6 @@ exit: mbedtls_pk_free( &ctx ); return( status ); } - #endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) || * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) || * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) || @@ -125,4 +124,89 @@ exit: * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) || * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) */ +#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) || \ + defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) +psa_status_t mbedtls_psa_rsa_export_key( psa_key_type_t type, + mbedtls_rsa_context *rsa, + uint8_t *data, + size_t data_size, + size_t *data_length ) +{ +#if defined(MBEDTLS_PK_WRITE_C) + int ret; + mbedtls_pk_context pk; + uint8_t *pos = data + data_size; + + mbedtls_pk_init( &pk ); + pk.pk_info = &mbedtls_rsa_info; + pk.pk_ctx = rsa; + + /* PSA Crypto API defines the format of an RSA key as a DER-encoded + * representation of the non-encrypted PKCS#1 RSAPrivateKey for a + * private key and of the RFC3279 RSAPublicKey for a public key. */ + if( PSA_KEY_TYPE_IS_KEY_PAIR( type ) ) + ret = mbedtls_pk_write_key_der( &pk, data, data_size ); + else + ret = mbedtls_pk_write_pubkey( &pos, data, &pk ); + + if( ret < 0 ) + { + /* Clean up in case pk_write failed halfway through. */ + memset( data, 0, data_size ); + return( mbedtls_to_psa_error( ret ) ); + } + + /* The mbedtls_pk_xxx functions write to the end of the buffer. + * Move the data to the beginning and erase remaining data + * at the original location. */ + if( 2 * (size_t) ret <= data_size ) + { + memcpy( data, data + data_size - ret, ret ); + memset( data + data_size - ret, 0, ret ); + } + else if( (size_t) ret < data_size ) + { + memmove( data, data + data_size - ret, ret ); + memset( data + ret, 0, data_size - ret ); + } + + *data_length = ret; + return( PSA_SUCCESS ); +#else + (void) type; + (void) rsa; + (void) data; + (void) data_size; + (void) data_length; + return( PSA_ERROR_NOT_SUPPORTED ); +#endif /* MBEDTLS_PK_WRITE_C */ +} + +psa_status_t mbedtls_psa_rsa_export_public_key( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, size_t key_buffer_size, + uint8_t *data, size_t data_size, size_t *data_length ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + mbedtls_rsa_context *rsa = NULL; + + status = mbedtls_psa_rsa_load_representation( + attributes->core.type, key_buffer, key_buffer_size, &rsa ); + if( status != PSA_SUCCESS ) + return( status ); + + status = mbedtls_psa_rsa_export_key( PSA_KEY_TYPE_RSA_PUBLIC_KEY, + rsa, + data, + data_size, + data_length ); + + mbedtls_rsa_free( rsa ); + mbedtls_free( rsa ); + + return( status ); +} +#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) || + * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) */ + #endif /* MBEDTLS_PSA_CRYPTO_C */ diff --git a/library/psa_crypto_rsa.h b/library/psa_crypto_rsa.h index 2f6474c42..2fb544239 100644 --- a/library/psa_crypto_rsa.h +++ b/library/psa_crypto_rsa.h @@ -38,4 +38,48 @@ psa_status_t mbedtls_psa_rsa_load_representation( psa_key_type_t type, const uint8_t *data, size_t data_length, mbedtls_rsa_context **p_rsa ); + +/** Export an RSA key to export representation + * + * \param[in] type The type of key (public/private) to export + * \param[in] rsa The internal RSA representation from which to export + * \param[out] data The buffer to export to + * \param[in] data_size The length of the buffer to export to + * \param[out] data_length The amount of bytes written to \p data + */ +psa_status_t mbedtls_psa_rsa_export_key( psa_key_type_t type, + mbedtls_rsa_context *rsa, + uint8_t *data, + size_t data_size, + size_t *data_length ); + +/** Export a public RSA key or the public part of an RSA key pair in binary + * format. + * + * \note The signature of this function is that of a PSA driver + * export_public_key entry point. This function behaves as an + * export_public_key entry point as defined in the PSA driver interface + * specification. + * + * \param[in] attributes The attributes for the key to export. + * \param[in] key_buffer Material or context of the key to export. + * \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes. + * \param[out] data Buffer where the key data is to be written. + * \param[in] data_size Size of the \p data buffer in bytes. + * \param[out] data_length On success, the number of bytes written in + * \p data. + * + * \retval #PSA_SUCCESS The RSA public key was exported successfully. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + */ +psa_status_t mbedtls_psa_rsa_export_public_key( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, size_t key_buffer_size, + uint8_t *data, size_t data_size, size_t *data_length ); + #endif /* PSA_CRYPTO_RSA_H */ From f1057d35895c519294b53459aa507c321a6b9179 Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Thu, 26 Nov 2020 19:19:10 +0100 Subject: [PATCH 15/38] psa: Add ECP/RSA transparent test driver export_public_key entry point Add ECP/RSA transparent test driver export_public_key entry point and use it in the transparent test driver supporting both ECP and RSA. Signed-off-by: Ronald Cron --- library/psa_crypto_ecp.c | 62 +++++++++++++++++--- library/psa_crypto_ecp.h | 11 ++++ library/psa_crypto_rsa.c | 62 +++++++++++++++++--- library/psa_crypto_rsa.h | 13 +++++ tests/src/drivers/key_management.c | 93 ++++++++++-------------------- 5 files changed, 165 insertions(+), 76 deletions(-) diff --git a/library/psa_crypto_ecp.c b/library/psa_crypto_ecp.c index 4f206214c..265d1ac4d 100644 --- a/library/psa_crypto_ecp.c +++ b/library/psa_crypto_ecp.c @@ -38,8 +38,20 @@ #include #include -#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) || \ - defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) || \ +#if ( defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) || \ + ( defined(PSA_CRYPTO_DRIVER_TEST) && \ + defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR) ) ) +#define BUILTIN_KEY_TYPE_ECC_KEY_PAIR 1 +#endif + +#if ( defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) || \ + ( defined(PSA_CRYPTO_DRIVER_TEST) && \ + defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_PUBLIC_KEY) ) ) +#define BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY 1 +#endif + +#if defined(BUILTIN_KEY_TYPE_ECC_KEY_PAIR) || \ + defined(BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_ECDH) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) @@ -131,14 +143,14 @@ exit: return( status ); } -#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) || - * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) || +#endif /* defined(BUILTIN_KEY_TYPE_ECC_KEY_PAIR) || + * defined(BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) || * defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || * defined(MBEDTLS_PSA_BUILTIN_ALG_ECDH) || * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) */ -#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) || \ - defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) +#if defined(BUILTIN_KEY_TYPE_ECC_KEY_PAIR) || \ + defined(BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) psa_status_t mbedtls_psa_ecp_export_key( psa_key_type_t type, mbedtls_ecp_keypair *ecp, uint8_t *data, @@ -190,7 +202,7 @@ psa_status_t mbedtls_psa_ecp_export_key( psa_key_type_t type, } } -psa_status_t mbedtls_psa_ecp_export_public_key( +static psa_status_t ecp_export_public_key( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, uint8_t *data, size_t data_size, size_t *data_length ) @@ -213,7 +225,43 @@ psa_status_t mbedtls_psa_ecp_export_public_key( return( status ); } +#endif /* defined(BUILTIN_KEY_TYPE_ECC_KEY_PAIR) || + * defined(BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) */ + +#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) || \ + defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) + +psa_status_t mbedtls_psa_ecp_export_public_key( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, size_t key_buffer_size, + uint8_t *data, size_t data_size, size_t *data_length ) +{ + return( ecp_export_public_key( attributes, key_buffer, key_buffer_size, + data, data_size, data_length ) ); +} + #endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) || * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) */ +/* + * BEYOND THIS POINT, TEST DRIVER ENTRY POINTS ONLY. + */ + +#if defined(PSA_CRYPTO_DRIVER_TEST) + +#if defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR) || \ + defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_PUBLIC_KEY) +psa_status_t mbedtls_transparent_test_driver_ecp_export_public_key( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, size_t key_buffer_size, + uint8_t *data, size_t data_size, size_t *data_length ) +{ + return( ecp_export_public_key( attributes, key_buffer, key_buffer_size, + data, data_size, data_length ) ); +} +#endif /* defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR) || + defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_PUBLIC_KEY) */ + +#endif /* PSA_CRYPTO_DRIVER_TEST */ + #endif /* MBEDTLS_PSA_CRYPTO_C */ diff --git a/library/psa_crypto_ecp.h b/library/psa_crypto_ecp.h index c6d8437a8..1083c9bea 100644 --- a/library/psa_crypto_ecp.h +++ b/library/psa_crypto_ecp.h @@ -82,4 +82,15 @@ psa_status_t mbedtls_psa_ecp_export_public_key( const uint8_t *key_buffer, size_t key_buffer_size, uint8_t *data, size_t data_size, size_t *data_length ); +/* + * BEYOND THIS POINT, TEST DRIVER ENTRY POINTS ONLY. + */ + +#if defined(PSA_CRYPTO_DRIVER_TEST) +psa_status_t mbedtls_transparent_test_driver_ecp_export_public_key( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, size_t key_buffer_size, + uint8_t *data, size_t data_size, size_t *data_length ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ + #endif /* PSA_CRYPTO_ECP_H */ diff --git a/library/psa_crypto_rsa.c b/library/psa_crypto_rsa.c index 3e5d1b41b..18147732d 100644 --- a/library/psa_crypto_rsa.c +++ b/library/psa_crypto_rsa.c @@ -39,12 +39,24 @@ #include #include +#if ( defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) || \ + ( defined(PSA_CRYPTO_DRIVER_TEST) && \ + defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR) ) ) +#define BUILTIN_KEY_TYPE_RSA_KEY_PAIR 1 +#endif + +#if ( defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) || \ + ( defined(PSA_CRYPTO_DRIVER_TEST) && \ + defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_PUBLIC_KEY) ) ) +#define BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY 1 +#endif + #if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS) || \ - defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) || \ - defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) + defined(BUILTIN_KEY_TYPE_RSA_KEY_PAIR) || \ + defined(BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) /* Mbed TLS doesn't support non-byte-aligned key sizes (i.e. key sizes * that are not a multiple of 8) well. For example, there is only @@ -121,11 +133,11 @@ exit: * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) || * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) || * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS) || - * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) || - * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) */ + * defined(BUILTIN_KEY_TYPE_RSA_KEY_PAIR) || + * defined(BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) */ -#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) || \ - defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) +#if defined(BUILTIN_KEY_TYPE_RSA_KEY_PAIR) || \ + defined(BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) psa_status_t mbedtls_psa_rsa_export_key( psa_key_type_t type, mbedtls_rsa_context *rsa, uint8_t *data, @@ -182,7 +194,7 @@ psa_status_t mbedtls_psa_rsa_export_key( psa_key_type_t type, #endif /* MBEDTLS_PK_WRITE_C */ } -psa_status_t mbedtls_psa_rsa_export_public_key( +static psa_status_t rsa_export_public_key( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, uint8_t *data, size_t data_size, size_t *data_length ) @@ -206,7 +218,43 @@ psa_status_t mbedtls_psa_rsa_export_public_key( return( status ); } +#endif /* defined(BUILTIN_KEY_TYPE_RSA_KEY_PAIR) || + * defined(BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) */ + +#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) || \ + defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) + +psa_status_t mbedtls_psa_rsa_export_public_key( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, size_t key_buffer_size, + uint8_t *data, size_t data_size, size_t *data_length ) +{ + return( rsa_export_public_key( attributes, key_buffer, key_buffer_size, + data, data_size, data_length ) ); +} + #endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) || * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) */ +/* + * BEYOND THIS POINT, TEST DRIVER ENTRY POINTS ONLY. + */ + +#if defined(PSA_CRYPTO_DRIVER_TEST) + +#if defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR) || \ + defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_PUBLIC_KEY) +psa_status_t mbedtls_transparent_test_driver_rsa_export_public_key( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, size_t key_buffer_size, + uint8_t *data, size_t data_size, size_t *data_length ) +{ + return( rsa_export_public_key( attributes, key_buffer, key_buffer_size, + data, data_size, data_length ) ); +} +#endif /* defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR) || + defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_PUBLIC_KEY) */ + +#endif /* PSA_CRYPTO_DRIVER_TEST */ + #endif /* MBEDTLS_PSA_CRYPTO_C */ diff --git a/library/psa_crypto_rsa.h b/library/psa_crypto_rsa.h index 2fb544239..36756ed7f 100644 --- a/library/psa_crypto_rsa.h +++ b/library/psa_crypto_rsa.h @@ -82,4 +82,17 @@ psa_status_t mbedtls_psa_rsa_export_public_key( const uint8_t *key_buffer, size_t key_buffer_size, uint8_t *data, size_t data_size, size_t *data_length ); +/* + * BEYOND THIS POINT, TEST DRIVER ENTRY POINTS ONLY. + */ + +#if defined(PSA_CRYPTO_DRIVER_TEST) + +psa_status_t mbedtls_transparent_test_driver_rsa_export_public_key( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, size_t key_buffer_size, + uint8_t *data, size_t data_size, size_t *data_length ); + +#endif /* PSA_CRYPTO_DRIVER_TEST */ + #endif /* PSA_CRYPTO_RSA_H */ diff --git a/tests/src/drivers/key_management.c b/tests/src/drivers/key_management.c index 76d2b3fee..aef3b8939 100644 --- a/tests/src/drivers/key_management.c +++ b/tests/src/drivers/key_management.c @@ -27,6 +27,8 @@ #if defined(MBEDTLS_PSA_CRYPTO_DRIVERS) && defined(PSA_CRYPTO_DRIVER_TEST) #include "psa/crypto.h" #include "psa_crypto_core.h" +#include "psa_crypto_ecp.h" +#include "psa_crypto_rsa.h" #include "mbedtls/ecp.h" #include "mbedtls/error.h" @@ -265,9 +267,10 @@ psa_status_t test_opaque_export_key( (void) data_length; return( PSA_ERROR_NOT_SUPPORTED ); } + psa_status_t test_transparent_export_public_key( const psa_key_attributes_t *attributes, - const uint8_t *key, size_t key_length, + const uint8_t *key_buffer, size_t key_buffer_size, uint8_t *data, size_t data_size, size_t *data_length ) { ++test_driver_key_management_hooks.hits; @@ -285,73 +288,39 @@ psa_status_t test_transparent_export_public_key( return( PSA_SUCCESS ); } - if( key == NULL || key_length == 0 ) - return( PSA_ERROR_INVALID_ARGUMENT ); - - psa_key_type_t keytype = psa_get_key_type( attributes ); - (void) keytype; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_type_t key_type = psa_get_key_type( attributes ); #if defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR) || \ defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_PUBLIC_KEY) - if( PSA_KEY_TYPE_IS_ECC( keytype ) ) + if( PSA_KEY_TYPE_IS_ECC( key_type ) ) { - if( !PSA_KEY_TYPE_IS_KEY_PAIR( keytype ) ) - return( PSA_ERROR_INVALID_ARGUMENT ); - - /* Mostly copied from psa_crypto.c */ - mbedtls_ecp_group_id grp_id = MBEDTLS_ECP_DP_NONE; - psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; - mbedtls_ecp_keypair ecp; - mbedtls_test_rnd_pseudo_info rnd_info; - memset( &rnd_info, 0x5A, sizeof( mbedtls_test_rnd_pseudo_info ) ); - - if( attributes->domain_parameters_size != 0 ) - return( PSA_ERROR_NOT_SUPPORTED ); - - grp_id = mbedtls_ecc_group_of_psa( PSA_KEY_TYPE_ECC_GET_FAMILY( keytype ), - PSA_BITS_TO_BYTES( psa_get_key_bits( attributes ) ) ); - if( grp_id == MBEDTLS_ECP_DP_NONE ) - return( PSA_ERROR_NOT_SUPPORTED ); - - mbedtls_ecp_keypair_init( &ecp ); - - status = mbedtls_to_psa_error( - mbedtls_ecp_group_load( &ecp.grp, grp_id ) ); - if( status != PSA_SUCCESS ) - goto ecp_exit; - - status = mbedtls_to_psa_error( - mbedtls_ecp_read_key( ecp.grp.id, - &ecp, - key, - key_length ) ); - if( status != PSA_SUCCESS ) - goto ecp_exit; - - /* Calculate the public key */ - status = mbedtls_to_psa_error( - mbedtls_ecp_mul( &ecp.grp, &ecp.Q, &ecp.d, &ecp.grp.G, - &mbedtls_test_rnd_pseudo_rand, - &rnd_info ) ); - if( status != PSA_SUCCESS ) - goto ecp_exit; - - status = mbedtls_to_psa_error( - mbedtls_ecp_point_write_binary( &ecp.grp, &ecp.Q, - MBEDTLS_ECP_PF_UNCOMPRESSED, - data_length, - data, - data_size ) ); - if( status != PSA_SUCCESS ) - memset( data, 0, data_size ); -ecp_exit: - mbedtls_ecp_keypair_free( &ecp ); - return( status ); + status = mbedtls_transparent_test_driver_ecp_export_public_key( + attributes, + key_buffer, key_buffer_size, + data, data_size, data_length ); + } + else +#endif +#if defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR) || \ + defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_PUBLIC_KEY) + if( PSA_KEY_TYPE_IS_RSA( key_type ) ) + { + status = mbedtls_transparent_test_driver_rsa_export_public_key( + attributes, + key_buffer, key_buffer_size, + data, data_size, data_length ); + } + else +#endif + { + status = PSA_ERROR_NOT_SUPPORTED; + (void)key_buffer; + (void)key_buffer_size; + (void)key_type; } -#endif /* MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR || - * MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_PUBLIC_KEY */ - return( PSA_ERROR_NOT_SUPPORTED ); + return( status ); } psa_status_t test_opaque_export_public_key( From 8f813ee8d82a740ebcefc8913060c02eec22495c Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Sat, 7 Nov 2020 18:22:09 +0100 Subject: [PATCH 16/38] psa: rsa: import: Move key buffer allocation Move key buffer allocation from RSA specific importation function up to psa_import_key_into_slot(). Signed-off-by: Ronald Cron --- library/psa_crypto.c | 46 ++++++++++++++++++++------------------------ 1 file changed, 21 insertions(+), 25 deletions(-) diff --git a/library/psa_crypto.c b/library/psa_crypto.c index 5323bb3d4..960c69824 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -541,13 +541,19 @@ static psa_status_t validate_unstructured_key_bit_size( psa_key_type_t type, * \param[in,out] slot The slot where to store the export representation to * \param[in] data The buffer containing the import representation * \param[in] data_length The amount of bytes in \p data + * \param[out] key_buffer The buffer containing the export representation + * \param[in] key_buffer_size The size of \p key_buffer in bytes + * \param[out] key_buffer_length The length of the data written in the key + * buffer in bytes. */ static psa_status_t psa_import_rsa_key( psa_key_slot_t *slot, const uint8_t *data, - size_t data_length ) + size_t data_length, + uint8_t *key_buffer, + size_t key_buffer_size, + size_t *key_buffer_length ) { psa_status_t status; - uint8_t* output = NULL; mbedtls_rsa_context *rsa = NULL; /* Parse input */ @@ -565,35 +571,17 @@ static psa_status_t psa_import_rsa_key( psa_key_slot_t *slot, * representation in the key slot. Export representation in case of RSA is * the smallest representation that's allowed as input, so a straight-up * allocation of the same size as the input buffer will be large enough. */ - output = mbedtls_calloc( 1, data_length ); - if( output == NULL ) - { - status = PSA_ERROR_INSUFFICIENT_MEMORY; - goto exit; - } - status = mbedtls_psa_rsa_export_key( slot->attr.type, rsa, - output, - data_length, - &data_length); + key_buffer, + key_buffer_size, + key_buffer_length ); exit: /* Always free the RSA object */ mbedtls_rsa_free( rsa ); mbedtls_free( rsa ); - /* Free the allocated buffer only on error. */ - if( status != PSA_SUCCESS ) - { - mbedtls_free( output ); - return( status ); - } - - /* On success, store the allocated export-formatted key. */ - slot->key.data = output; - slot->key.bytes = data_length; - - return( PSA_SUCCESS ); + return( status ); } #endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) || @@ -827,7 +815,15 @@ static psa_status_t psa_import_key_into_slot( psa_key_slot_t *slot, defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) if( PSA_KEY_TYPE_IS_RSA( slot->attr.type ) ) { - return( psa_import_rsa_key( slot, data, data_length ) ); + status = psa_allocate_buffer_to_slot( slot, data_length ); + if( status != PSA_SUCCESS ) + return( status ); + + status = psa_import_rsa_key( slot, + data, data_length, + slot->key.data, data_length, + &slot->key.bytes ); + return( status ); } #endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) || * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) */ From 4f2a7f0190c0fc43a974132e9f3ef7e6eb985000 Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Sun, 8 Nov 2020 14:09:44 +0100 Subject: [PATCH 17/38] psa: Change psa_import_rsa_key() signature Change psa_import_rsa_key() signature to the signature of an import_key driver entry point. Signed-off-by: Ronald Cron --- library/psa_crypto.c | 56 ++++++++++++++++++++++++++++---------------- 1 file changed, 36 insertions(+), 20 deletions(-) diff --git a/library/psa_crypto.c b/library/psa_crypto.c index 960c69824..d65be17ed 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -536,42 +536,56 @@ static psa_status_t validate_unstructured_key_bit_size( psa_key_type_t type, #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) || \ defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) -/** Import an RSA key from import representation to a slot +/** Import an RSA key in binary format. * - * \param[in,out] slot The slot where to store the export representation to - * \param[in] data The buffer containing the import representation - * \param[in] data_length The amount of bytes in \p data - * \param[out] key_buffer The buffer containing the export representation - * \param[in] key_buffer_size The size of \p key_buffer in bytes - * \param[out] key_buffer_length The length of the data written in the key - * buffer in bytes. + * \note The signature of this function is that of a PSA driver + * import_key entry point. This function behaves as an import_key + * entry point as defined in the PSA driver interface specification for + * transparent drivers. + * + * \param[in] attributes The attributes for the key to import. + * \param[in] data The buffer containing the key data in import + * format. + * \param[in] data_length Size of the \p data buffer in bytes. + * \param[out] key_buffer The buffer containing the key data in output + * format. + * \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes. This + * size is greater or equal to \p data_length. + * \param[out] key_buffer_length The length of the data written in \p + * key_buffer in bytes. + * \param[out] bits The key size in number of bits. + * + * \retval #PSA_SUCCESS The RSA key was imported successfully. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The key data is not correctly formatted. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_CORRUPTION_DETECTED */ -static psa_status_t psa_import_rsa_key( psa_key_slot_t *slot, - const uint8_t *data, - size_t data_length, - uint8_t *key_buffer, - size_t key_buffer_size, - size_t *key_buffer_length ) +static psa_status_t psa_import_rsa_key( + const psa_key_attributes_t *attributes, + const uint8_t *data, size_t data_length, + uint8_t *key_buffer, size_t key_buffer_size, + size_t *key_buffer_length, size_t *bits ) { psa_status_t status; mbedtls_rsa_context *rsa = NULL; /* Parse input */ - status = mbedtls_psa_rsa_load_representation( slot->attr.type, + status = mbedtls_psa_rsa_load_representation( attributes->core.type, data, data_length, &rsa ); if( status != PSA_SUCCESS ) goto exit; - slot->attr.bits = (psa_key_bits_t) PSA_BYTES_TO_BITS( - mbedtls_rsa_get_len( rsa ) ); + *bits = (psa_key_bits_t) PSA_BYTES_TO_BITS( mbedtls_rsa_get_len( rsa ) ); /* Re-export the data to PSA export format, such that we can store export * representation in the key slot. Export representation in case of RSA is * the smallest representation that's allowed as input, so a straight-up * allocation of the same size as the input buffer will be large enough. */ - status = mbedtls_psa_rsa_export_key( slot->attr.type, + status = mbedtls_psa_rsa_export_key( attributes->core.type, rsa, key_buffer, key_buffer_size, @@ -819,10 +833,12 @@ static psa_status_t psa_import_key_into_slot( psa_key_slot_t *slot, if( status != PSA_SUCCESS ) return( status ); - status = psa_import_rsa_key( slot, + status = psa_import_rsa_key( &attributes, data, data_length, slot->key.data, data_length, - &slot->key.bytes ); + &slot->key.bytes, + &bit_size ); + slot->attr.bits = (psa_key_bits_t) bit_size; return( status ); } #endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) || From b6420e3797b80fde455da4f64631aa178feb35c0 Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Sun, 22 Nov 2020 16:15:38 +0100 Subject: [PATCH 18/38] psa: Rename psa_import_rsa_key to mbedtls_psa_rsa_import_key Rename psa_import_rsa_key to mbedtls_psa_rsa_import_key to align its name with the naming conventions of exported functions in psa_crypto_rsa.c. Signed-off-by: Ronald Cron --- library/psa_crypto.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/library/psa_crypto.c b/library/psa_crypto.c index d65be17ed..3b484a895 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -562,7 +562,7 @@ static psa_status_t validate_unstructured_key_bit_size( psa_key_type_t type, * \retval #PSA_ERROR_INSUFFICIENT_MEMORY * \retval #PSA_ERROR_CORRUPTION_DETECTED */ -static psa_status_t psa_import_rsa_key( +static psa_status_t mbedtls_psa_rsa_import_key( const psa_key_attributes_t *attributes, const uint8_t *data, size_t data_length, uint8_t *key_buffer, size_t key_buffer_size, @@ -833,11 +833,11 @@ static psa_status_t psa_import_key_into_slot( psa_key_slot_t *slot, if( status != PSA_SUCCESS ) return( status ); - status = psa_import_rsa_key( &attributes, - data, data_length, - slot->key.data, data_length, - &slot->key.bytes, - &bit_size ); + status = mbedtls_psa_rsa_import_key( &attributes, + data, data_length, + slot->key.data, data_length, + &slot->key.bytes, + &bit_size ); slot->attr.bits = (psa_key_bits_t) bit_size; return( status ); } @@ -6270,7 +6270,7 @@ static psa_status_t psa_generate_key_internal( if( bits > PSA_VENDOR_RSA_MAX_KEY_BITS ) return( PSA_ERROR_NOT_SUPPORTED ); /* Accept only byte-aligned keys, for the same reasons as - * in psa_import_rsa_key(). */ + * in mbedtls_psa_rsa_import_key(). */ if( bits % 8 != 0 ) return( PSA_ERROR_NOT_SUPPORTED ); status = psa_read_rsa_exponent( domain_parameters, From abf2aef90fb0e48d71e311936d53c28efef24c0a Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Fri, 27 Nov 2020 18:13:44 +0100 Subject: [PATCH 19/38] psa: Move RSA key import to psa_crypto_rsa.c Signed-off-by: Ronald Cron --- library/psa_crypto.c | 68 ---------------------------------------- library/psa_crypto_rsa.c | 37 ++++++++++++++++++++++ library/psa_crypto_rsa.h | 32 +++++++++++++++++++ 3 files changed, 69 insertions(+), 68 deletions(-) diff --git a/library/psa_crypto.c b/library/psa_crypto.c index 3b484a895..2854cd2d6 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -533,74 +533,6 @@ static psa_status_t validate_unstructured_key_bit_size( psa_key_type_t type, return( PSA_SUCCESS ); } -#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) || \ - defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) - -/** Import an RSA key in binary format. - * - * \note The signature of this function is that of a PSA driver - * import_key entry point. This function behaves as an import_key - * entry point as defined in the PSA driver interface specification for - * transparent drivers. - * - * \param[in] attributes The attributes for the key to import. - * \param[in] data The buffer containing the key data in import - * format. - * \param[in] data_length Size of the \p data buffer in bytes. - * \param[out] key_buffer The buffer containing the key data in output - * format. - * \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes. This - * size is greater or equal to \p data_length. - * \param[out] key_buffer_length The length of the data written in \p - * key_buffer in bytes. - * \param[out] bits The key size in number of bits. - * - * \retval #PSA_SUCCESS The RSA key was imported successfully. - * \retval #PSA_ERROR_INVALID_ARGUMENT - * The key data is not correctly formatted. - * \retval #PSA_ERROR_NOT_SUPPORTED - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_CORRUPTION_DETECTED - */ -static psa_status_t mbedtls_psa_rsa_import_key( - const psa_key_attributes_t *attributes, - const uint8_t *data, size_t data_length, - uint8_t *key_buffer, size_t key_buffer_size, - size_t *key_buffer_length, size_t *bits ) -{ - psa_status_t status; - mbedtls_rsa_context *rsa = NULL; - - /* Parse input */ - status = mbedtls_psa_rsa_load_representation( attributes->core.type, - data, - data_length, - &rsa ); - if( status != PSA_SUCCESS ) - goto exit; - - *bits = (psa_key_bits_t) PSA_BYTES_TO_BITS( mbedtls_rsa_get_len( rsa ) ); - - /* Re-export the data to PSA export format, such that we can store export - * representation in the key slot. Export representation in case of RSA is - * the smallest representation that's allowed as input, so a straight-up - * allocation of the same size as the input buffer will be large enough. */ - status = mbedtls_psa_rsa_export_key( attributes->core.type, - rsa, - key_buffer, - key_buffer_size, - key_buffer_length ); -exit: - /* Always free the RSA object */ - mbedtls_rsa_free( rsa ); - mbedtls_free( rsa ); - - return( status ); -} - -#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) || - * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) */ - #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) || \ defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) diff --git a/library/psa_crypto_rsa.c b/library/psa_crypto_rsa.c index 18147732d..e5095bee7 100644 --- a/library/psa_crypto_rsa.c +++ b/library/psa_crypto_rsa.c @@ -138,6 +138,43 @@ exit: #if defined(BUILTIN_KEY_TYPE_RSA_KEY_PAIR) || \ defined(BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) + +psa_status_t mbedtls_psa_rsa_import_key( + const psa_key_attributes_t *attributes, + const uint8_t *data, size_t data_length, + uint8_t *key_buffer, size_t key_buffer_size, + size_t *key_buffer_length, size_t *bits ) +{ + psa_status_t status; + mbedtls_rsa_context *rsa = NULL; + + /* Parse input */ + status = mbedtls_psa_rsa_load_representation( attributes->core.type, + data, + data_length, + &rsa ); + if( status != PSA_SUCCESS ) + goto exit; + + *bits = (psa_key_bits_t) PSA_BYTES_TO_BITS( mbedtls_rsa_get_len( rsa ) ); + + /* Re-export the data to PSA export format, such that we can store export + * representation in the key slot. Export representation in case of RSA is + * the smallest representation that's allowed as input, so a straight-up + * allocation of the same size as the input buffer will be large enough. */ + status = mbedtls_psa_rsa_export_key( attributes->core.type, + rsa, + key_buffer, + key_buffer_size, + key_buffer_length ); +exit: + /* Always free the RSA object */ + mbedtls_rsa_free( rsa ); + mbedtls_free( rsa ); + + return( status ); +} + psa_status_t mbedtls_psa_rsa_export_key( psa_key_type_t type, mbedtls_rsa_context *rsa, uint8_t *data, diff --git a/library/psa_crypto_rsa.h b/library/psa_crypto_rsa.h index 36756ed7f..7fd61abef 100644 --- a/library/psa_crypto_rsa.h +++ b/library/psa_crypto_rsa.h @@ -39,6 +39,38 @@ psa_status_t mbedtls_psa_rsa_load_representation( psa_key_type_t type, size_t data_length, mbedtls_rsa_context **p_rsa ); +/** Import an RSA key in binary format. + * + * \note The signature of this function is that of a PSA driver + * import_key entry point. This function behaves as an import_key + * entry point as defined in the PSA driver interface specification for + * transparent drivers. + * + * \param[in] attributes The attributes for the key to import. + * \param[in] data The buffer containing the key data in import + * format. + * \param[in] data_length Size of the \p data buffer in bytes. + * \param[out] key_buffer The buffer containing the key data in output + * format. + * \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes. This + * size is greater or equal to \p data_length. + * \param[out] key_buffer_length The length of the data written in \p + * key_buffer in bytes. + * \param[out] bits The key size in number of bits. + * + * \retval #PSA_SUCCESS The RSA key was imported successfully. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The key data is not correctly formatted. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_CORRUPTION_DETECTED + */ +psa_status_t mbedtls_psa_rsa_import_key( + const psa_key_attributes_t *attributes, + const uint8_t *data, size_t data_length, + uint8_t *key_buffer, size_t key_buffer_size, + size_t *key_buffer_length, size_t *bits ); + /** Export an RSA key to export representation * * \param[in] type The type of key (public/private) to export From 13f8b098cbe4517a3d2638a214c4eec74fbdff44 Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Sun, 29 Nov 2020 10:48:58 +0100 Subject: [PATCH 20/38] psa: ecp: import: Move key buffer allocation Move key buffer allocation from ECP specific importation function up to psa_import_key_into_slot(). Signed-off-by: Ronald Cron --- library/psa_crypto.c | 46 ++++++++++++++++++++------------------------ 1 file changed, 21 insertions(+), 25 deletions(-) diff --git a/library/psa_crypto.c b/library/psa_crypto.c index 2854cd2d6..26575efc5 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -541,13 +541,19 @@ static psa_status_t validate_unstructured_key_bit_size( psa_key_type_t type, * \param[in,out] slot The slot where to store the export representation to * \param[in] data The buffer containing the import representation * \param[in] data_length The amount of bytes in \p data + * \param[out] key_buffer The buffer containing the export representation + * \param[in] key_buffer_size The size of \p key_buffer in bytes + * \param[out] key_buffer_length The length of the data written in the key + * buffer in bytes. */ static psa_status_t psa_import_ecp_key( psa_key_slot_t *slot, const uint8_t *data, - size_t data_length ) + size_t data_length, + uint8_t *key_buffer, + size_t key_buffer_size, + size_t *key_buffer_length ) { psa_status_t status; - uint8_t* output = NULL; mbedtls_ecp_keypair *ecp = NULL; /* Parse input */ @@ -566,35 +572,17 @@ static psa_status_t psa_import_ecp_key( psa_key_slot_t *slot, /* Re-export the data to PSA export format. There is currently no support * for other input formats then the export format, so this is a 1-1 * copy operation. */ - output = mbedtls_calloc( 1, data_length ); - if( output == NULL ) - { - status = PSA_ERROR_INSUFFICIENT_MEMORY; - goto exit; - } - status = mbedtls_psa_ecp_export_key( slot->attr.type, ecp, - output, - data_length, - &data_length); + key_buffer, + key_buffer_size, + key_buffer_length ); exit: /* Always free the PK object (will also free contained ECP context) */ mbedtls_ecp_keypair_free( ecp ); mbedtls_free( ecp ); - /* Free the allocated buffer only on error. */ - if( status != PSA_SUCCESS ) - { - mbedtls_free( output ); - return( status ); - } - - /* On success, store the allocated export-formatted key. */ - slot->key.data = output; - slot->key.bytes = data_length; - - return( PSA_SUCCESS ); + return( status ); } #endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) || * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) */ @@ -753,7 +741,15 @@ static psa_status_t psa_import_key_into_slot( psa_key_slot_t *slot, defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) if( PSA_KEY_TYPE_IS_ECC( slot->attr.type ) ) { - return( psa_import_ecp_key( slot, data, data_length ) ); + status = psa_allocate_buffer_to_slot( slot, data_length ); + if( status != PSA_SUCCESS ) + return( status ); + + status = psa_import_ecp_key( slot, + data, data_length, + slot->key.data, data_length, + &slot->key.bytes ); + return( status ); } #endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) || * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) */ From 79cc548cf20680d1bb98fc9a1c048b2cbc3f47d2 Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Sun, 8 Nov 2020 14:54:25 +0100 Subject: [PATCH 21/38] psa: Change psa_import_ecp_key() signature Change psa_import_ecp_key() signature to the signature of an import_key driver entry point. Signed-off-by: Ronald Cron --- library/psa_crypto.c | 60 ++++++++++++++++++++++++++++---------------- 1 file changed, 39 insertions(+), 21 deletions(-) diff --git a/library/psa_crypto.c b/library/psa_crypto.c index 26575efc5..5f2b6c347 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -536,43 +536,59 @@ static psa_status_t validate_unstructured_key_bit_size( psa_key_type_t type, #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) || \ defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) -/** Import an ECP key from import representation to a slot +/** Import an ECP key in binary format. * - * \param[in,out] slot The slot where to store the export representation to - * \param[in] data The buffer containing the import representation - * \param[in] data_length The amount of bytes in \p data - * \param[out] key_buffer The buffer containing the export representation - * \param[in] key_buffer_size The size of \p key_buffer in bytes - * \param[out] key_buffer_length The length of the data written in the key - * buffer in bytes. + * \note The signature of this function is that of a PSA driver + * import_key entry point. This function behaves as an import_key + * entry point as defined in the PSA driver interface specification for + * transparent drivers. + * + * \param[in] attributes The attributes for the key to import. + * \param[in] data The buffer containing the key data in import + * format. + * \param[in] data_length Size of the \p data buffer in bytes. + * \param[out] key_buffer The buffer containing the key data in output + * format. + * \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes. This + * size is greater or equal to \p data_length. + * \param[out] key_buffer_length The length of the data written in \p + * key_buffer in bytes. + * \param[out] bits The key size in number of bits. + * + * \retval #PSA_SUCCESS The ECP key was imported successfully. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The key data is not correctly formatted. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_CORRUPTION_DETECTED */ -static psa_status_t psa_import_ecp_key( psa_key_slot_t *slot, - const uint8_t *data, - size_t data_length, - uint8_t *key_buffer, - size_t key_buffer_size, - size_t *key_buffer_length ) +static psa_status_t psa_import_ecp_key( + const psa_key_attributes_t *attributes, + const uint8_t *data, size_t data_length, + uint8_t *key_buffer, size_t key_buffer_size, + size_t *key_buffer_length, size_t *bits ) { psa_status_t status; mbedtls_ecp_keypair *ecp = NULL; /* Parse input */ - status = mbedtls_psa_ecp_load_representation( slot->attr.type, + status = mbedtls_psa_ecp_load_representation( attributes->core.type, data, data_length, &ecp ); if( status != PSA_SUCCESS ) goto exit; - if( PSA_KEY_TYPE_ECC_GET_FAMILY( slot->attr.type ) == PSA_ECC_FAMILY_MONTGOMERY) - slot->attr.bits = (psa_key_bits_t) ecp->grp.nbits + 1; + if( PSA_KEY_TYPE_ECC_GET_FAMILY( attributes->core.type ) == + PSA_ECC_FAMILY_MONTGOMERY ) + *bits = ecp->grp.nbits + 1; else - slot->attr.bits = (psa_key_bits_t) ecp->grp.nbits; + *bits = ecp->grp.nbits; /* Re-export the data to PSA export format. There is currently no support * for other input formats then the export format, so this is a 1-1 * copy operation. */ - status = mbedtls_psa_ecp_export_key( slot->attr.type, + status = mbedtls_psa_ecp_export_key( attributes->core.type, ecp, key_buffer, key_buffer_size, @@ -745,10 +761,12 @@ static psa_status_t psa_import_key_into_slot( psa_key_slot_t *slot, if( status != PSA_SUCCESS ) return( status ); - status = psa_import_ecp_key( slot, + status = psa_import_ecp_key( &attributes, data, data_length, slot->key.data, data_length, - &slot->key.bytes ); + &slot->key.bytes, + &bit_size ); + slot->attr.bits = (psa_key_bits_t) bit_size; return( status ); } #endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) || From b14dbbeb922bc166d5d7c2c98b4bb7ff10a3d731 Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Sun, 22 Nov 2020 16:36:49 +0100 Subject: [PATCH 22/38] psa: Rename ECP key import function Rename ECP key import function before to move it to psa_crypto_ecp.c to adapt to the naming of exported functions in psa_crypto_ecp.c. Signed-off-by: Ronald Cron --- library/psa_crypto.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/library/psa_crypto.c b/library/psa_crypto.c index 5f2b6c347..96d25b3e8 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -562,7 +562,7 @@ static psa_status_t validate_unstructured_key_bit_size( psa_key_type_t type, * \retval #PSA_ERROR_INSUFFICIENT_MEMORY * \retval #PSA_ERROR_CORRUPTION_DETECTED */ -static psa_status_t psa_import_ecp_key( +static psa_status_t mbedtls_psa_ecp_import_key( const psa_key_attributes_t *attributes, const uint8_t *data, size_t data_length, uint8_t *key_buffer, size_t key_buffer_size, @@ -761,11 +761,11 @@ static psa_status_t psa_import_key_into_slot( psa_key_slot_t *slot, if( status != PSA_SUCCESS ) return( status ); - status = psa_import_ecp_key( &attributes, - data, data_length, - slot->key.data, data_length, - &slot->key.bytes, - &bit_size ); + status = mbedtls_psa_ecp_import_key( &attributes, + data, data_length, + slot->key.data, data_length, + &slot->key.bytes, + &bit_size ); slot->attr.bits = (psa_key_bits_t) bit_size; return( status ); } From d6ec3035a402094f7fd6a56ec18bcaf7fe464c6f Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Fri, 27 Nov 2020 18:54:57 +0100 Subject: [PATCH 23/38] psa: Move ECP key import to psa_crypto_ecp.c Signed-off-by: Ronald Cron --- library/psa_crypto.c | 70 ---------------------------------------- library/psa_crypto_ecp.c | 40 +++++++++++++++++++++++ library/psa_crypto_ecp.h | 32 ++++++++++++++++++ 3 files changed, 72 insertions(+), 70 deletions(-) diff --git a/library/psa_crypto.c b/library/psa_crypto.c index 96d25b3e8..d55599e9e 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -533,76 +533,6 @@ static psa_status_t validate_unstructured_key_bit_size( psa_key_type_t type, return( PSA_SUCCESS ); } -#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) || \ - defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) - -/** Import an ECP key in binary format. - * - * \note The signature of this function is that of a PSA driver - * import_key entry point. This function behaves as an import_key - * entry point as defined in the PSA driver interface specification for - * transparent drivers. - * - * \param[in] attributes The attributes for the key to import. - * \param[in] data The buffer containing the key data in import - * format. - * \param[in] data_length Size of the \p data buffer in bytes. - * \param[out] key_buffer The buffer containing the key data in output - * format. - * \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes. This - * size is greater or equal to \p data_length. - * \param[out] key_buffer_length The length of the data written in \p - * key_buffer in bytes. - * \param[out] bits The key size in number of bits. - * - * \retval #PSA_SUCCESS The ECP key was imported successfully. - * \retval #PSA_ERROR_INVALID_ARGUMENT - * The key data is not correctly formatted. - * \retval #PSA_ERROR_NOT_SUPPORTED - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_CORRUPTION_DETECTED - */ -static psa_status_t mbedtls_psa_ecp_import_key( - const psa_key_attributes_t *attributes, - const uint8_t *data, size_t data_length, - uint8_t *key_buffer, size_t key_buffer_size, - size_t *key_buffer_length, size_t *bits ) -{ - psa_status_t status; - mbedtls_ecp_keypair *ecp = NULL; - - /* Parse input */ - status = mbedtls_psa_ecp_load_representation( attributes->core.type, - data, - data_length, - &ecp ); - if( status != PSA_SUCCESS ) - goto exit; - - if( PSA_KEY_TYPE_ECC_GET_FAMILY( attributes->core.type ) == - PSA_ECC_FAMILY_MONTGOMERY ) - *bits = ecp->grp.nbits + 1; - else - *bits = ecp->grp.nbits; - - /* Re-export the data to PSA export format. There is currently no support - * for other input formats then the export format, so this is a 1-1 - * copy operation. */ - status = mbedtls_psa_ecp_export_key( attributes->core.type, - ecp, - key_buffer, - key_buffer_size, - key_buffer_length ); -exit: - /* Always free the PK object (will also free contained ECP context) */ - mbedtls_ecp_keypair_free( ecp ); - mbedtls_free( ecp ); - - return( status ); -} -#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) || - * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) */ - /** Return the size of the key in the given slot, in bits. * * \param[in] slot A key slot. diff --git a/library/psa_crypto_ecp.c b/library/psa_crypto_ecp.c index 265d1ac4d..03ba14dd7 100644 --- a/library/psa_crypto_ecp.c +++ b/library/psa_crypto_ecp.c @@ -151,6 +151,46 @@ exit: #if defined(BUILTIN_KEY_TYPE_ECC_KEY_PAIR) || \ defined(BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) + +psa_status_t mbedtls_psa_ecp_import_key( + const psa_key_attributes_t *attributes, + const uint8_t *data, size_t data_length, + uint8_t *key_buffer, size_t key_buffer_size, + size_t *key_buffer_length, size_t *bits ) +{ + psa_status_t status; + mbedtls_ecp_keypair *ecp = NULL; + + /* Parse input */ + status = mbedtls_psa_ecp_load_representation( attributes->core.type, + data, + data_length, + &ecp ); + if( status != PSA_SUCCESS ) + goto exit; + + if( PSA_KEY_TYPE_ECC_GET_FAMILY( attributes->core.type ) == + PSA_ECC_FAMILY_MONTGOMERY ) + *bits = ecp->grp.nbits + 1; + else + *bits = ecp->grp.nbits; + + /* Re-export the data to PSA export format. There is currently no support + * for other input formats then the export format, so this is a 1-1 + * copy operation. */ + status = mbedtls_psa_ecp_export_key( attributes->core.type, + ecp, + key_buffer, + key_buffer_size, + key_buffer_length ); +exit: + /* Always free the PK object (will also free contained ECP context) */ + mbedtls_ecp_keypair_free( ecp ); + mbedtls_free( ecp ); + + return( status ); +} + psa_status_t mbedtls_psa_ecp_export_key( psa_key_type_t type, mbedtls_ecp_keypair *ecp, uint8_t *data, diff --git a/library/psa_crypto_ecp.h b/library/psa_crypto_ecp.h index 1083c9bea..c4915b5c0 100644 --- a/library/psa_crypto_ecp.h +++ b/library/psa_crypto_ecp.h @@ -39,6 +39,38 @@ psa_status_t mbedtls_psa_ecp_load_representation( psa_key_type_t type, size_t data_length, mbedtls_ecp_keypair **p_ecp ); +/** Import an ECP key in binary format. + * + * \note The signature of this function is that of a PSA driver + * import_key entry point. This function behaves as an import_key + * entry point as defined in the PSA driver interface specification for + * transparent drivers. + * + * \param[in] attributes The attributes for the key to import. + * \param[in] data The buffer containing the key data in import + * format. + * \param[in] data_length Size of the \p data buffer in bytes. + * \param[out] key_buffer The buffer containing the key data in output + * format. + * \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes. This + * size is greater or equal to \p data_length. + * \param[out] key_buffer_length The length of the data written in \p + * key_buffer in bytes. + * \param[out] bits The key size in number of bits. + * + * \retval #PSA_SUCCESS The ECP key was imported successfully. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The key data is not correctly formatted. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_CORRUPTION_DETECTED + */ +psa_status_t mbedtls_psa_ecp_import_key( + const psa_key_attributes_t *attributes, + const uint8_t *data, size_t data_length, + uint8_t *key_buffer, size_t key_buffer_size, + size_t *key_buffer_length, size_t *bits ); + /** Export an ECP key to export representation * * \param[in] type The type of key (public/private) to export From dd04d423b5b8df7d3df34fc318bce09712b6fb94 Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Sat, 28 Nov 2020 15:14:42 +0100 Subject: [PATCH 24/38] psa: import: Move key buffer allocation Move key buffer allocation from psa_import_key_into_slot() function up to the two functions calling it. Signed-off-by: Ronald Cron --- library/psa_crypto.c | 80 ++++++++++++++++++++++++-------------------- 1 file changed, 44 insertions(+), 36 deletions(-) diff --git a/library/psa_crypto.c b/library/psa_crypto.c index d55599e9e..411010c60 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -591,12 +591,18 @@ psa_status_t psa_copy_key_material_into_slot( psa_key_slot_t *slot, * * Persistent storage is not affected. * - * \param[in,out] slot The key slot to import data into. - * Its `type` field must have previously been set to - * the desired key type. - * It must not contain any key material yet. - * \param[in] data Buffer containing the key material to parse and import. - * \param data_length Size of \p data in bytes. + * \param[in,out] slot The key slot to import data into. + * Its `type` field must have previously been set to + * the desired key type. + * It must not contain any key material yet. + * \param[in] data Buffer containing the key material to parse and + * import. + * \param data_length Size of \p data in bytes. + * \param[out] key_buffer The buffer containing the export representation. + * \param[in] key_buffer_size The size of \p key_buffer in bytes. The size + * is greater or equal to \p data_length. + * \param[out] key_buffer_length The length of the data written in \p + * key_buffer in bytes. * * \retval #PSA_SUCCESS * \retval #PSA_ERROR_INVALID_ARGUMENT @@ -605,7 +611,10 @@ psa_status_t psa_copy_key_material_into_slot( psa_key_slot_t *slot, */ static psa_status_t psa_import_key_into_slot( psa_key_slot_t *slot, const uint8_t *data, - size_t data_length ) + size_t data_length, + uint8_t *key_buffer, + size_t key_buffer_size, + size_t *key_buffer_length ) { psa_status_t status = PSA_SUCCESS; size_t bit_size; @@ -631,10 +640,10 @@ static psa_status_t psa_import_key_into_slot( psa_key_slot_t *slot, if( status != PSA_SUCCESS ) return( status ); - /* Allocate memory for the key */ - status = psa_copy_key_material_into_slot( slot, data, data_length ); - if( status != PSA_SUCCESS ) - return( status ); + /* Copy the key material. */ + memcpy( key_buffer, data, data_length ); + *key_buffer_length = data_length; + (void)key_buffer_size; /* Write the actual key size to the slot. * psa_start_key_creation() wrote the size declared by the @@ -650,16 +659,12 @@ static psa_status_t psa_import_key_into_slot( psa_key_slot_t *slot, .core = slot->attr }; - status = psa_allocate_buffer_to_slot( slot, data_length ); - if( status != PSA_SUCCESS ) - return( status ); - bit_size = slot->attr.bits; status = psa_driver_wrapper_import_key( &attributes, data, data_length, - slot->key.data, - slot->key.bytes, - &slot->key.bytes, + key_buffer, + key_buffer_size, + key_buffer_length, &bit_size ); if( status == PSA_SUCCESS ) { @@ -676,10 +681,7 @@ static psa_status_t psa_import_key_into_slot( psa_key_slot_t *slot, return( status ); } - mbedtls_platform_zeroize( slot->key.data, data_length ); - mbedtls_free( slot->key.data ); - slot->key.data = NULL; - slot->key.bytes = 0; + mbedtls_platform_zeroize( key_buffer, key_buffer_size ); /* Key format is not supported by any accelerator, try software fallback * if present. */ @@ -687,14 +689,10 @@ static psa_status_t psa_import_key_into_slot( psa_key_slot_t *slot, defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) if( PSA_KEY_TYPE_IS_ECC( slot->attr.type ) ) { - status = psa_allocate_buffer_to_slot( slot, data_length ); - if( status != PSA_SUCCESS ) - return( status ); - status = mbedtls_psa_ecp_import_key( &attributes, data, data_length, - slot->key.data, data_length, - &slot->key.bytes, + key_buffer, key_buffer_size, + key_buffer_length, &bit_size ); slot->attr.bits = (psa_key_bits_t) bit_size; return( status ); @@ -705,14 +703,10 @@ static psa_status_t psa_import_key_into_slot( psa_key_slot_t *slot, defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) if( PSA_KEY_TYPE_IS_RSA( slot->attr.type ) ) { - status = psa_allocate_buffer_to_slot( slot, data_length ); - if( status != PSA_SUCCESS ) - return( status ); - status = mbedtls_psa_rsa_import_key( &attributes, data, data_length, - slot->key.data, data_length, - &slot->key.bytes, + key_buffer, key_buffer_size, + key_buffer_length, &bit_size ); slot->attr.bits = (psa_key_bits_t) bit_size; return( status ); @@ -1931,7 +1925,14 @@ psa_status_t psa_import_key( const psa_key_attributes_t *attributes, } else { - status = psa_import_key_into_slot( slot, data, data_length ); + status = psa_allocate_buffer_to_slot( slot, data_length ); + if( status != PSA_SUCCESS ) + goto exit; + + status = psa_import_key_into_slot( slot, data, data_length, + slot->key.data, + slot->key.bytes, + &slot->key.bytes ); if( status != PSA_SUCCESS ) goto exit; } @@ -5234,7 +5235,14 @@ static psa_status_t psa_generate_derived_key_internal( 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 ); + + status = psa_allocate_buffer_to_slot( slot, bytes ); + if( status != PSA_SUCCESS ) + return( status ); + + status = psa_import_key_into_slot( slot, data, bytes, + slot->key.data, slot->key.bytes, + &slot->key.bytes ); exit: mbedtls_free( data ); From 2ebfdcce0e5d2e198b314200fd728397d092b6e3 Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Sat, 28 Nov 2020 15:54:54 +0100 Subject: [PATCH 25/38] psa: Change psa_import_key_into_slot() signature Change psa_import_key_into_slot() signature to the signature of an import_key driver entry point. Signed-off-by: Ronald Cron --- library/psa_crypto.c | 154 +++++++++++++++++++------------------------ 1 file changed, 69 insertions(+), 85 deletions(-) diff --git a/library/psa_crypto.c b/library/psa_crypto.c index 411010c60..4cdfd9948 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -583,49 +583,48 @@ psa_status_t psa_copy_key_material_into_slot( psa_key_slot_t *slot, return( PSA_SUCCESS ); } -/** Import key data into a slot. +/** Import a key in binary format. * - * `slot->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. + * \note The signature of this function is that of a PSA driver + * import_key entry point. This function behaves as an import_key + * entry point as defined in the PSA driver interface specification for + * transparent drivers. * - * Persistent storage is not affected. - * - * \param[in,out] slot The key slot to import data into. - * Its `type` field must have previously been set to - * the desired key type. - * It must not contain any key material yet. - * \param[in] data Buffer containing the key material to parse and - * import. - * \param data_length Size of \p data in bytes. - * \param[out] key_buffer The buffer containing the export representation. - * \param[in] key_buffer_size The size of \p key_buffer in bytes. The size - * is greater or equal to \p data_length. + * \param[in] attributes The attributes for the key to import. + * \param[in] data The buffer containing the key data in import + * format. + * \param[in] data_length Size of the \p data buffer in bytes. + * \param[out] key_buffer The buffer containing the key data in output + * format. + * \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes. This + * size is greater or equal to \p data_length. * \param[out] key_buffer_length The length of the data written in \p * key_buffer in bytes. + * \param[out] bits The key size in number of bits. * - * \retval #PSA_SUCCESS + * \retval #PSA_SUCCESS The key was imported successfully. * \retval #PSA_ERROR_INVALID_ARGUMENT + * The key data is not correctly formatted. * \retval #PSA_ERROR_NOT_SUPPORTED * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_CORRUPTION_DETECTED */ -static psa_status_t psa_import_key_into_slot( psa_key_slot_t *slot, - const uint8_t *data, - size_t data_length, - uint8_t *key_buffer, - size_t key_buffer_size, - size_t *key_buffer_length ) +static psa_status_t psa_import_key_into_slot( + const psa_key_attributes_t *attributes, + const uint8_t *data, size_t data_length, + uint8_t *key_buffer, size_t key_buffer_size, + size_t *key_buffer_length, size_t *bits ) { - psa_status_t status = PSA_SUCCESS; - size_t bit_size; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_type_t type = attributes->core.type; /* zero-length keys are never supported. */ if( data_length == 0 ) return( PSA_ERROR_NOT_SUPPORTED ); - if( key_type_is_raw_bytes( slot->attr.type ) ) + if( key_type_is_raw_bytes( type ) ) { - bit_size = PSA_BYTES_TO_BITS( data_length ); + *bits = PSA_BYTES_TO_BITS( data_length ); /* Ensure that the bytes-to-bits conversion hasn't overflown. */ if( data_length > SIZE_MAX / 8 ) @@ -633,10 +632,10 @@ static psa_status_t psa_import_key_into_slot( psa_key_slot_t *slot, /* Enforce a size limit, and in particular ensure that the bit * size fits in its representation type. */ - if( bit_size > PSA_MAX_KEY_BITS ) + if( ( *bits ) > PSA_MAX_KEY_BITS ) return( PSA_ERROR_NOT_SUPPORTED ); - status = validate_unstructured_key_bit_size( slot->attr.type, bit_size ); + status = validate_unstructured_key_bit_size( type, *bits ); if( status != PSA_SUCCESS ) return( status ); @@ -645,41 +644,18 @@ static psa_status_t psa_import_key_into_slot( psa_key_slot_t *slot, *key_buffer_length = data_length; (void)key_buffer_size; - /* 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_key_bits_t) bit_size; - return( PSA_SUCCESS ); } - else if( PSA_KEY_TYPE_IS_ASYMMETRIC( slot->attr.type ) ) + else if( PSA_KEY_TYPE_IS_ASYMMETRIC( type ) ) { - /* Try validation through accelerators first. */ - psa_key_attributes_t attributes = { - .core = slot->attr - }; - - bit_size = slot->attr.bits; - status = psa_driver_wrapper_import_key( &attributes, + status = psa_driver_wrapper_import_key( attributes, data, data_length, key_buffer, key_buffer_size, key_buffer_length, - &bit_size ); - if( status == PSA_SUCCESS ) - { - if( slot->attr.bits == 0 ) - slot->attr.bits = (psa_key_bits_t) bit_size; - else if( bit_size != slot->attr.bits ) - return( PSA_ERROR_INVALID_ARGUMENT ); - - return( PSA_SUCCESS ); - } - else - { - if( status != PSA_ERROR_NOT_SUPPORTED ) - return( status ); - } + bits ); + if( status != PSA_ERROR_NOT_SUPPORTED ) + return( status ); mbedtls_platform_zeroize( key_buffer, key_buffer_size ); @@ -687,41 +663,31 @@ static psa_status_t psa_import_key_into_slot( psa_key_slot_t *slot, * if present. */ #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) || \ defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) - if( PSA_KEY_TYPE_IS_ECC( slot->attr.type ) ) + if( PSA_KEY_TYPE_IS_ECC( type ) ) { - status = mbedtls_psa_ecp_import_key( &attributes, - data, data_length, - key_buffer, key_buffer_size, - key_buffer_length, - &bit_size ); - slot->attr.bits = (psa_key_bits_t) bit_size; - return( status ); + return( mbedtls_psa_ecp_import_key( attributes, + data, data_length, + key_buffer, key_buffer_size, + key_buffer_length, + bits ) ); } #endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) || * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) */ #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) || \ defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) - if( PSA_KEY_TYPE_IS_RSA( slot->attr.type ) ) + if( PSA_KEY_TYPE_IS_RSA( type ) ) { - status = mbedtls_psa_rsa_import_key( &attributes, - data, data_length, - key_buffer, key_buffer_size, - key_buffer_length, - &bit_size ); - slot->attr.bits = (psa_key_bits_t) bit_size; - return( status ); + return( mbedtls_psa_rsa_import_key( attributes, + data, data_length, + key_buffer, key_buffer_size, + key_buffer_length, + bits ) ); } #endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) || * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) */ + } - /* Fell through the fallback as well, so have nothing else to try. */ - return( PSA_ERROR_NOT_SUPPORTED ); - } - else - { - /* Unknown key type */ - return( PSA_ERROR_NOT_SUPPORTED ); - } + return( PSA_ERROR_NOT_SUPPORTED ); } /** Calculate the intersection of two algorithm usage policies. @@ -1929,13 +1895,24 @@ psa_status_t psa_import_key( const psa_key_attributes_t *attributes, if( status != PSA_SUCCESS ) goto exit; - status = psa_import_key_into_slot( slot, data, data_length, + size_t bits = slot->attr.bits; + status = psa_import_key_into_slot( attributes, + data, data_length, slot->key.data, slot->key.bytes, - &slot->key.bytes ); + &slot->key.bytes, &bits ); if( status != PSA_SUCCESS ) goto exit; + + if( slot->attr.bits == 0 ) + slot->attr.bits = (psa_key_bits_t) bits; + else if( bits != slot->attr.bits ) + { + status = PSA_ERROR_INVALID_ARGUMENT; + goto exit; + } } + status = psa_validate_optional_attributes( slot, attributes ); if( status != PSA_SUCCESS ) goto exit; @@ -5240,9 +5217,16 @@ static psa_status_t psa_generate_derived_key_internal( if( status != PSA_SUCCESS ) return( status ); - status = psa_import_key_into_slot( slot, data, bytes, + psa_key_attributes_t attributes = { + .core = slot->attr + }; + + status = psa_import_key_into_slot( &attributes, + data, bytes, slot->key.data, slot->key.bytes, - &slot->key.bytes ); + &slot->key.bytes, + &bits ); + slot->attr.bits = (psa_key_bits_t) bits; exit: mbedtls_free( data ); From a0fe59f7385ef4475d3f0d4aaf0c7afa5605586f Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Sun, 29 Nov 2020 11:14:53 +0100 Subject: [PATCH 26/38] psa: Export internally psa_import_key_into_slot() Export psa_import_key_into_slot from psa_crypto.c to make it available to the driver wrapper. Signed-off-by: Ronald Cron --- library/psa_crypto.c | 28 +--------------------------- library/psa_crypto_core.h | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 27 deletions(-) diff --git a/library/psa_crypto.c b/library/psa_crypto.c index 4cdfd9948..5463a5f1e 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -583,33 +583,7 @@ psa_status_t psa_copy_key_material_into_slot( psa_key_slot_t *slot, return( PSA_SUCCESS ); } -/** Import a key in binary format. - * - * \note The signature of this function is that of a PSA driver - * import_key entry point. This function behaves as an import_key - * entry point as defined in the PSA driver interface specification for - * transparent drivers. - * - * \param[in] attributes The attributes for the key to import. - * \param[in] data The buffer containing the key data in import - * format. - * \param[in] data_length Size of the \p data buffer in bytes. - * \param[out] key_buffer The buffer containing the key data in output - * format. - * \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes. This - * size is greater or equal to \p data_length. - * \param[out] key_buffer_length The length of the data written in \p - * key_buffer in bytes. - * \param[out] bits The key size in number of bits. - * - * \retval #PSA_SUCCESS The key was imported successfully. - * \retval #PSA_ERROR_INVALID_ARGUMENT - * The key data is not correctly formatted. - * \retval #PSA_ERROR_NOT_SUPPORTED - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_CORRUPTION_DETECTED - */ -static psa_status_t psa_import_key_into_slot( +psa_status_t psa_import_key_into_slot( const psa_key_attributes_t *attributes, const uint8_t *data, size_t data_length, uint8_t *key_buffer, size_t key_buffer_size, diff --git a/library/psa_crypto_core.h b/library/psa_crypto_core.h index ca8cd6bee..4263a77b0 100644 --- a/library/psa_crypto_core.h +++ b/library/psa_crypto_core.h @@ -212,6 +212,38 @@ psa_status_t psa_copy_key_material_into_slot( psa_key_slot_t *slot, */ psa_status_t mbedtls_to_psa_error( int ret ); +/** Import a key in binary format. + * + * \note The signature of this function is that of a PSA driver + * import_key entry point. This function behaves as an import_key + * entry point as defined in the PSA driver interface specification for + * transparent drivers. + * + * \param[in] attributes The attributes for the key to import. + * \param[in] data The buffer containing the key data in import + * format. + * \param[in] data_length Size of the \p data buffer in bytes. + * \param[out] key_buffer The buffer containing the key data in output + * format. + * \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes. This + * size is greater or equal to \p data_length. + * \param[out] key_buffer_length The length of the data written in \p + * key_buffer in bytes. + * \param[out] bits The key size in number of bits. + * + * \retval #PSA_SUCCESS The key was imported successfully. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The key data is not correctly formatted. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_CORRUPTION_DETECTED + */ +psa_status_t psa_import_key_into_slot( + const psa_key_attributes_t *attributes, + const uint8_t *data, size_t data_length, + uint8_t *key_buffer, size_t key_buffer_size, + size_t *key_buffer_length, size_t *bits ); + /** Export a key in binary format * * \note The signature of this function is that of a PSA driver export_key From bf33c93717adbcc673839b19cc1eac18b543aec7 Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Sat, 28 Nov 2020 18:06:53 +0100 Subject: [PATCH 27/38] psa: Call import software implementation as a driver Signed-off-by: Ronald Cron --- library/psa_crypto.c | 50 ++++++++++++-------------- library/psa_crypto_driver_wrappers.c | 52 ++++++++++++++++------------ 2 files changed, 53 insertions(+), 49 deletions(-) diff --git a/library/psa_crypto.c b/library/psa_crypto.c index 5463a5f1e..6e80cec3d 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -622,19 +622,6 @@ psa_status_t psa_import_key_into_slot( } else if( PSA_KEY_TYPE_IS_ASYMMETRIC( type ) ) { - status = psa_driver_wrapper_import_key( attributes, - data, data_length, - key_buffer, - key_buffer_size, - key_buffer_length, - bits ); - if( status != PSA_ERROR_NOT_SUPPORTED ) - return( status ); - - mbedtls_platform_zeroize( key_buffer, key_buffer_size ); - - /* Key format is not supported by any accelerator, try software fallback - * if present. */ #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) || \ defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) if( PSA_KEY_TYPE_IS_ECC( type ) ) @@ -1865,16 +1852,23 @@ psa_status_t psa_import_key( const psa_key_attributes_t *attributes, } else { - status = psa_allocate_buffer_to_slot( slot, data_length ); - if( status != PSA_SUCCESS ) - goto exit; + /* In the case of a transparent key or an opaque key stored in local + * storage (thus not in the case of generating a key in a secure element + * or cryptoprocessor with storage), we have to allocate a buffer to + * hold the generated key material. */ + if( slot->key.data == NULL ) + { + status = psa_allocate_buffer_to_slot( slot, data_length ); + if( status != PSA_SUCCESS ) + goto exit; + } size_t bits = slot->attr.bits; - status = psa_import_key_into_slot( attributes, - data, data_length, - slot->key.data, - slot->key.bytes, - &slot->key.bytes, &bits ); + status = psa_driver_wrapper_import_key( attributes, + data, data_length, + slot->key.data, + slot->key.bytes, + &slot->key.bytes, &bits ); if( status != PSA_SUCCESS ) goto exit; @@ -5191,16 +5185,18 @@ static psa_status_t psa_generate_derived_key_internal( if( status != PSA_SUCCESS ) return( status ); + slot->attr.bits = (psa_key_bits_t) bits; psa_key_attributes_t attributes = { .core = slot->attr }; - status = psa_import_key_into_slot( &attributes, - data, bytes, - slot->key.data, slot->key.bytes, - &slot->key.bytes, - &bits ); - slot->attr.bits = (psa_key_bits_t) bits; + status = psa_driver_wrapper_import_key( &attributes, + data, bytes, + slot->key.data, + slot->key.bytes, + &slot->key.bytes, &bits ); + if( bits != slot->attr.bits ) + status = PSA_ERROR_INVALID_ARGUMENT; exit: mbedtls_free( data ); diff --git a/library/psa_crypto_driver_wrappers.c b/library/psa_crypto_driver_wrappers.c index 0cc89fe7f..fe54b7b97 100644 --- a/library/psa_crypto_driver_wrappers.c +++ b/library/psa_crypto_driver_wrappers.c @@ -418,30 +418,38 @@ psa_status_t psa_driver_wrapper_import_key( size_t *key_buffer_length, size_t *bits ) { -#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; - /* Try accelerators in turn */ -#if defined(PSA_CRYPTO_DRIVER_TEST) - status = test_transparent_import_key( attributes, - data, data_length, - key_buffer, key_buffer_size, - key_buffer_length, bits ); - /* Declared with fallback == true */ - if( status != PSA_ERROR_NOT_SUPPORTED ) - return( status ); -#endif /* PSA_CRYPTO_DRIVER_TEST */ + psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( + psa_get_key_lifetime( attributes ) ); + + switch( location ) + { + case PSA_KEY_LOCATION_LOCAL_STORAGE: + /* Key is stored in the slot in export representation, so + * cycle through all known transparent accelerators */ +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +#if defined(PSA_CRYPTO_DRIVER_TEST) + status = test_transparent_import_key( attributes, + data, data_length, + key_buffer, key_buffer_size, + key_buffer_length, bits ); + /* Declared with fallback == true */ + if( status != PSA_ERROR_NOT_SUPPORTED ) + return( status ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + /* Fell through, meaning no accelerator supports this operation */ + return( psa_import_key_into_slot( attributes, + data, data_length, + key_buffer, key_buffer_size, + key_buffer_length, bits ) ); + + default: + /* Key is declared with a lifetime not known to us */ + (void)status; + return( PSA_ERROR_NOT_SUPPORTED ); + } - return( PSA_ERROR_NOT_SUPPORTED ); -#else /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ - (void) attributes; - (void) data; - (void) data_length; - (void) key_buffer; - (void) key_buffer_size; - (void) key_buffer_length; - (void) bits; - return( PSA_ERROR_NOT_SUPPORTED ); -#endif /* PSA_CRYPTO_DRIVER_PRESENT */ } psa_status_t psa_driver_wrapper_export_key( From fb2ed5bb05bbbfb3291786a4176d5a447f7509f0 Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Mon, 30 Nov 2020 12:11:01 +0100 Subject: [PATCH 28/38] psa: import: Move registered SE support to the driver wrapper Signed-off-by: Ronald Cron --- library/psa_crypto.c | 78 +++++++--------------------- library/psa_crypto_driver_wrappers.c | 34 +++++++++++- 2 files changed, 52 insertions(+), 60 deletions(-) diff --git a/library/psa_crypto.c b/library/psa_crypto.c index 6e80cec3d..55b7d2f5b 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -1800,6 +1800,7 @@ psa_status_t psa_import_key( const psa_key_attributes_t *attributes, psa_status_t status; psa_key_slot_t *slot = NULL; psa_se_drv_table_entry_t *driver = NULL; + size_t bits; *key = MBEDTLS_SVC_KEY_ID_INIT; @@ -1814,72 +1815,33 @@ psa_status_t psa_import_key( const psa_key_attributes_t *attributes, if( status != PSA_SUCCESS ) goto exit; -#if defined(MBEDTLS_PSA_CRYPTO_SE_C) - if( driver != NULL ) + /* In the case of a transparent key or an opaque key stored in local + * storage (thus not in the case of generating a key in a secure element + * or cryptoprocessor with storage), we have to allocate a buffer to + * hold the generated key material. */ + if( slot->key.data == NULL ) { - const psa_drv_se_t *drv = psa_get_se_driver_methods( driver ); - /* The driver should set the number of key bits, however in - * case it doesn't, we initialize bits to an invalid value. */ - size_t bits = PSA_MAX_KEY_BITS + 1; - if( drv->key_management == NULL || - drv->key_management->p_import == NULL ) - { - status = PSA_ERROR_NOT_SUPPORTED; - goto exit; - } - status = drv->key_management->p_import( - psa_get_se_driver_context( driver ), - psa_key_slot_get_slot_number( slot ), - attributes, data, data_length, &bits ); + status = psa_allocate_buffer_to_slot( slot, data_length ); 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 */ - if( psa_key_lifetime_is_external( psa_get_key_lifetime( attributes ) ) ) + + bits = slot->attr.bits; + status = psa_driver_wrapper_import_key( attributes, + data, data_length, + slot->key.data, + slot->key.bytes, + &slot->key.bytes, &bits ); + if( status != PSA_SUCCESS ) + goto exit; + + if( slot->attr.bits == 0 ) + slot->attr.bits = (psa_key_bits_t) bits; + else if( bits != slot->attr.bits ) { - /* Importing a key with external lifetime through the driver wrapper - * interface is not yet supported. Return as if this was an invalid - * lifetime. */ status = PSA_ERROR_INVALID_ARGUMENT; goto exit; } - else - { - /* In the case of a transparent key or an opaque key stored in local - * storage (thus not in the case of generating a key in a secure element - * or cryptoprocessor with storage), we have to allocate a buffer to - * hold the generated key material. */ - if( slot->key.data == NULL ) - { - status = psa_allocate_buffer_to_slot( slot, data_length ); - if( status != PSA_SUCCESS ) - goto exit; - } - - size_t bits = slot->attr.bits; - status = psa_driver_wrapper_import_key( attributes, - data, data_length, - slot->key.data, - slot->key.bytes, - &slot->key.bytes, &bits ); - if( status != PSA_SUCCESS ) - goto exit; - - if( slot->attr.bits == 0 ) - slot->attr.bits = (psa_key_bits_t) bits; - else if( bits != slot->attr.bits ) - { - status = PSA_ERROR_INVALID_ARGUMENT; - goto exit; - } - } status = psa_validate_optional_attributes( slot, attributes ); if( status != PSA_SUCCESS ) diff --git a/library/psa_crypto_driver_wrappers.c b/library/psa_crypto_driver_wrappers.c index fe54b7b97..fd03ed2bf 100644 --- a/library/psa_crypto_driver_wrappers.c +++ b/library/psa_crypto_driver_wrappers.c @@ -422,6 +422,35 @@ psa_status_t psa_driver_wrapper_import_key( psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime( attributes ) ); + /* Try dynamically-registered SE interface first */ +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + const psa_drv_se_t *drv; + psa_drv_se_context_t *drv_context; + + if( psa_get_se_driver( attributes->core.lifetime, &drv, &drv_context ) ) + { + if( drv->key_management == NULL || + drv->key_management->p_import == NULL ) + return( PSA_ERROR_NOT_SUPPORTED ); + + /* The driver should set the number of key bits, however in + * case it doesn't, we initialize bits to an invalid value. */ + *bits = PSA_MAX_KEY_BITS + 1; + status = drv->key_management->p_import( + drv_context, + *( (psa_key_slot_number_t *)key_buffer ), + attributes, data, data_length, bits ); + + if( status != PSA_SUCCESS ) + return( status ); + + if( (*bits) > PSA_MAX_KEY_BITS ) + return( PSA_ERROR_NOT_SUPPORTED ); + + return( PSA_SUCCESS ); + } +#endif /* PSA_CRYPTO_SE_C */ + switch( location ) { case PSA_KEY_LOCATION_LOCAL_STORAGE: @@ -445,9 +474,10 @@ psa_status_t psa_driver_wrapper_import_key( key_buffer_length, bits ) ); default: - /* Key is declared with a lifetime not known to us */ + /* Importing a key with external storage in not yet supported. + * Return in error indicating that the lifetime is not valid. */ (void)status; - return( PSA_ERROR_NOT_SUPPORTED ); + return( PSA_ERROR_INVALID_ARGUMENT ); } } From 784fb326aeb862cbcf8caeda7d05973ac4dedd39 Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Mon, 30 Nov 2020 13:55:05 +0100 Subject: [PATCH 29/38] psa: Add ECP/RSA transparent test driver import_key entry point Add ECP/RSA transparent test driver import_key entry point and use it in the transparent test driver entry supporting both ECP and RSA. Signed-off-by: Ronald Cron --- library/psa_crypto_ecp.c | 26 +++++- library/psa_crypto_ecp.h | 7 ++ library/psa_crypto_rsa.c | 26 +++++- library/psa_crypto_rsa.h | 6 ++ tests/src/drivers/key_management.c | 130 ++++++++--------------------- 5 files changed, 98 insertions(+), 97 deletions(-) diff --git a/library/psa_crypto_ecp.c b/library/psa_crypto_ecp.c index 03ba14dd7..bfc9674c9 100644 --- a/library/psa_crypto_ecp.c +++ b/library/psa_crypto_ecp.c @@ -152,7 +152,7 @@ exit: #if defined(BUILTIN_KEY_TYPE_ECC_KEY_PAIR) || \ defined(BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) -psa_status_t mbedtls_psa_ecp_import_key( +static psa_status_t ecp_import_key( const psa_key_attributes_t *attributes, const uint8_t *data, size_t data_length, uint8_t *key_buffer, size_t key_buffer_size, @@ -271,6 +271,17 @@ static psa_status_t ecp_export_public_key( #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) || \ defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) +psa_status_t mbedtls_psa_ecp_import_key( + const psa_key_attributes_t *attributes, + const uint8_t *data, size_t data_length, + uint8_t *key_buffer, size_t key_buffer_size, + size_t *key_buffer_length, size_t *bits ) +{ + return( ecp_import_key( attributes, data, data_length, + key_buffer, key_buffer_size, + key_buffer_length, bits ) ); +} + psa_status_t mbedtls_psa_ecp_export_public_key( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, @@ -291,6 +302,18 @@ psa_status_t mbedtls_psa_ecp_export_public_key( #if defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR) || \ defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_PUBLIC_KEY) + +psa_status_t mbedtls_transparent_test_driver_ecp_import_key( + const psa_key_attributes_t *attributes, + const uint8_t *data, size_t data_length, + uint8_t *key_buffer, size_t key_buffer_size, + size_t *key_buffer_length, size_t *bits ) +{ + return( ecp_import_key( attributes, data, data_length, + key_buffer, key_buffer_size, + key_buffer_length, bits ) ); +} + psa_status_t mbedtls_transparent_test_driver_ecp_export_public_key( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, @@ -299,6 +322,7 @@ psa_status_t mbedtls_transparent_test_driver_ecp_export_public_key( return( ecp_export_public_key( attributes, key_buffer, key_buffer_size, data, data_size, data_length ) ); } + #endif /* defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR) || defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_PUBLIC_KEY) */ diff --git a/library/psa_crypto_ecp.h b/library/psa_crypto_ecp.h index c4915b5c0..695f07ec4 100644 --- a/library/psa_crypto_ecp.h +++ b/library/psa_crypto_ecp.h @@ -119,10 +119,17 @@ psa_status_t mbedtls_psa_ecp_export_public_key( */ #if defined(PSA_CRYPTO_DRIVER_TEST) +psa_status_t mbedtls_transparent_test_driver_ecp_import_key( + const psa_key_attributes_t *attributes, + const uint8_t *data, size_t data_length, + uint8_t *key_buffer, size_t key_buffer_size, + size_t *key_buffer_length, size_t *bits ); + psa_status_t mbedtls_transparent_test_driver_ecp_export_public_key( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, uint8_t *data, size_t data_size, size_t *data_length ); + #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_ECP_H */ diff --git a/library/psa_crypto_rsa.c b/library/psa_crypto_rsa.c index e5095bee7..aae1d056a 100644 --- a/library/psa_crypto_rsa.c +++ b/library/psa_crypto_rsa.c @@ -139,7 +139,7 @@ exit: #if defined(BUILTIN_KEY_TYPE_RSA_KEY_PAIR) || \ defined(BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) -psa_status_t mbedtls_psa_rsa_import_key( +static psa_status_t rsa_import_key( const psa_key_attributes_t *attributes, const uint8_t *data, size_t data_length, uint8_t *key_buffer, size_t key_buffer_size, @@ -261,6 +261,17 @@ static psa_status_t rsa_export_public_key( #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) || \ defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) +psa_status_t mbedtls_psa_rsa_import_key( + const psa_key_attributes_t *attributes, + const uint8_t *data, size_t data_length, + uint8_t *key_buffer, size_t key_buffer_size, + size_t *key_buffer_length, size_t *bits ) +{ + return( rsa_import_key( attributes, data, data_length, + key_buffer, key_buffer_size, + key_buffer_length, bits ) ); +} + psa_status_t mbedtls_psa_rsa_export_public_key( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, @@ -281,6 +292,18 @@ psa_status_t mbedtls_psa_rsa_export_public_key( #if defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR) || \ defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_PUBLIC_KEY) + +psa_status_t mbedtls_transparent_test_driver_rsa_import_key( + const psa_key_attributes_t *attributes, + const uint8_t *data, size_t data_length, + uint8_t *key_buffer, size_t key_buffer_size, + size_t *key_buffer_length, size_t *bits ) +{ + return( rsa_import_key( attributes, data, data_length, + key_buffer, key_buffer_size, + key_buffer_length, bits ) ); +} + psa_status_t mbedtls_transparent_test_driver_rsa_export_public_key( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, @@ -289,6 +312,7 @@ psa_status_t mbedtls_transparent_test_driver_rsa_export_public_key( return( rsa_export_public_key( attributes, key_buffer, key_buffer_size, data, data_size, data_length ) ); } + #endif /* defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR) || defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_PUBLIC_KEY) */ diff --git a/library/psa_crypto_rsa.h b/library/psa_crypto_rsa.h index 7fd61abef..64013df73 100644 --- a/library/psa_crypto_rsa.h +++ b/library/psa_crypto_rsa.h @@ -120,6 +120,12 @@ psa_status_t mbedtls_psa_rsa_export_public_key( #if defined(PSA_CRYPTO_DRIVER_TEST) +psa_status_t mbedtls_transparent_test_driver_rsa_import_key( + const psa_key_attributes_t *attributes, + const uint8_t *data, size_t data_length, + uint8_t *key_buffer, size_t key_buffer_size, + size_t *key_buffer_length, size_t *bits ); + psa_status_t mbedtls_transparent_test_driver_rsa_export_public_key( const psa_key_attributes_t *attributes, const uint8_t *key_buffer, size_t key_buffer_size, diff --git a/tests/src/drivers/key_management.c b/tests/src/drivers/key_management.c index aef3b8939..98990d108 100644 --- a/tests/src/drivers/key_management.c +++ b/tests/src/drivers/key_management.c @@ -153,105 +153,45 @@ psa_status_t test_transparent_import_key( if( test_driver_key_management_hooks.forced_status != PSA_SUCCESS ) return( test_driver_key_management_hooks.forced_status ); + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_type_t type = psa_get_key_type( attributes ); + #if defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR) || \ defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_PUBLIC_KEY) - psa_key_type_t type = psa_get_key_type( attributes ); - if ( PSA_KEY_TYPE_IS_ECC( type ) ) + if( PSA_KEY_TYPE_IS_ECC( type ) ) { - // Code mostly copied from psa_load_ecp_representation - psa_ecc_family_t curve = PSA_KEY_TYPE_ECC_GET_FAMILY( type ); - mbedtls_ecp_group_id grp_id; - mbedtls_ecp_keypair ecp; - psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; - - if( psa_get_key_bits( attributes ) == 0 ) - { - // Attempt auto-detect of curve bit size - size_t curve_size = data_length; - - if( PSA_KEY_TYPE_IS_PUBLIC_KEY( type ) && - PSA_KEY_TYPE_ECC_GET_FAMILY( type ) != PSA_ECC_FAMILY_MONTGOMERY ) - { - /* A Weierstrass public key is represented as: - * - The byte 0x04; - * - `x_P` as a `ceiling(m/8)`-byte string, big-endian; - * - `y_P` as a `ceiling(m/8)`-byte string, big-endian. - * So its data length is 2m+1 where m is the curve size in bits. - */ - if( ( data_length & 1 ) == 0 ) - return( PSA_ERROR_INVALID_ARGUMENT ); - curve_size = data_length / 2; - - /* Montgomery public keys are represented in compressed format, meaning - * their curve_size is equal to the amount of input. */ - - /* Private keys are represented in uncompressed private random integer - * format, meaning their curve_size is equal to the amount of input. */ - } - - grp_id = mbedtls_ecc_group_of_psa( curve, curve_size ); - } - else - { - grp_id = mbedtls_ecc_group_of_psa( curve, - PSA_BITS_TO_BYTES( psa_get_key_bits( attributes ) ) ); - } - - const mbedtls_ecp_curve_info *curve_info = - mbedtls_ecp_curve_info_from_grp_id( grp_id ); - - if( attributes->domain_parameters_size != 0 ) - return( PSA_ERROR_NOT_SUPPORTED ); - if( grp_id == MBEDTLS_ECP_DP_NONE || curve_info == NULL ) - return( PSA_ERROR_NOT_SUPPORTED ); - - *bits = curve_info->bit_size; - - mbedtls_ecp_keypair_init( &ecp ); - - status = mbedtls_to_psa_error( - mbedtls_ecp_group_load( &ecp.grp, grp_id ) ); - if( status != PSA_SUCCESS ) - goto ecp_exit; - - /* Load the key material. */ - if( PSA_KEY_TYPE_IS_PUBLIC_KEY( type ) ) - { - /* Load the public value. */ - status = mbedtls_to_psa_error( - mbedtls_ecp_point_read_binary( &ecp.grp, &ecp.Q, - data, - data_length ) ); - if( status != PSA_SUCCESS ) - goto ecp_exit; - - /* Check that the point is on the curve. */ - status = mbedtls_to_psa_error( - mbedtls_ecp_check_pubkey( &ecp.grp, &ecp.Q ) ); - } - else - { - /* Load and validate the secret value. */ - status = mbedtls_to_psa_error( - mbedtls_ecp_read_key( ecp.grp.id, - &ecp, - data, - data_length ) ); - } - -ecp_exit: - mbedtls_ecp_keypair_free( &ecp ); - return( status ); + status = mbedtls_transparent_test_driver_ecp_import_key( + attributes, + data, data_length, + key_buffer, key_buffer_size, + key_buffer_length, bits ); } - return( PSA_ERROR_NOT_SUPPORTED ); -#else - (void) attributes; - (void) data; - (void) data_length; - (void) bits; - return( PSA_ERROR_NOT_SUPPORTED ); -#endif /* MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR || - * MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_PUBLIC_KEY */ + else +#endif +#if defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR) || \ + defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_PUBLIC_KEY) + if( PSA_KEY_TYPE_IS_RSA( type ) ) + { + status = mbedtls_transparent_test_driver_rsa_import_key( + attributes, + data, data_length, + key_buffer, key_buffer_size, + key_buffer_length, bits ); + } + else +#endif + { + status = PSA_ERROR_NOT_SUPPORTED; + (void)data; + (void)data_length; + (void)key_buffer; + (void)key_buffer_size; + (void)key_buffer_length; + (void)bits; + (void)type; + } + + return( status ); } psa_status_t test_opaque_export_key( From 84a3fa10c4d968ed29ba35c03f23a24be8a1313a Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Tue, 1 Dec 2020 09:35:17 +0100 Subject: [PATCH 30/38] tests: psa: Change key management test driver default forced return value Change key management test driver default forced return value from PSA_ERROR_NOT_SUPPORTED to PSA_SUCCESS to be able to run the PSA unit tests with the cryptographic key management operations being handled by the transparent test driver. Signed-off-by: Ronald Cron --- tests/include/test/drivers/key_management.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/include/test/drivers/key_management.h b/tests/include/test/drivers/key_management.h index 9d5175815..b30baa205 100644 --- a/tests/include/test/drivers/key_management.h +++ b/tests/include/test/drivers/key_management.h @@ -41,7 +41,7 @@ typedef struct { unsigned long hits; } test_driver_key_management_hooks_t; -#define TEST_DRIVER_KEY_MANAGEMENT_INIT { NULL, 0, PSA_ERROR_NOT_SUPPORTED, 0 } +#define TEST_DRIVER_KEY_MANAGEMENT_INIT { NULL, 0, PSA_SUCCESS, 0 } static inline test_driver_key_management_hooks_t test_driver_key_management_hooks_init( void ) { const test_driver_key_management_hooks_t v = TEST_DRIVER_KEY_MANAGEMENT_INIT; From c9066e44884334715e344eef95bbd140827f871d Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Mon, 7 Dec 2020 16:18:21 +0100 Subject: [PATCH 31/38] psa: driver wrapper: Fix generate key unit test dependency In test_suite_psa_crypto_driver_wrappers test suite, the generate key with software fallback test should be run only if the software fallback is available. Signed-off-by: Ronald Cron --- tests/suites/test_suite_psa_crypto_driver_wrappers.data | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/suites/test_suite_psa_crypto_driver_wrappers.data b/tests/suites/test_suite_psa_crypto_driver_wrappers.data index a85861cc1..1fd449fb8 100644 --- a/tests/suites/test_suite_psa_crypto_driver_wrappers.data +++ b/tests/suites/test_suite_psa_crypto_driver_wrappers.data @@ -35,6 +35,7 @@ generate_key through transparent driver: in-driver generate_key:PSA_SUCCESS:"":PSA_SUCCESS generate_key through transparent driver: fallback +depends_on:MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR generate_key:PSA_ERROR_NOT_SUPPORTED:"":PSA_SUCCESS generate_key through transparent driver: error From 80eaa93b5914c08bc3b714fbca0ff68bdea3d585 Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Tue, 1 Dec 2020 14:19:33 +0100 Subject: [PATCH 32/38] tests: psa: Reactivate and expand key management through test driver The compilation guards in key_management.c are now accelerator compilation guards (MBEDTLS_PSA_ACCEL_KEY_TYPE_xyz). As a consequence when running the PSA driver wrapper tests as part of test_psa_crypto_config_basic and test_psa_crypto_drivers all.sh components all key management cryptographic operations were handled by the software builtin fallback, and not by the test driver as intended in the first place. This commits fixes this issue by: . declaring an accelerator for ECC key pairs in test_psa_crypto_config_basic. . declaring an accelerator for both ECC and RSA key pairs in test_psa_crypto_drivers. It is possible to declare an accelerator for both ECC and RSA key pairs in test_psa_crypto_drivers and not in test_psa_crypto_config_basic because in the case of test_psa_crypto_drivers the new PSA configuration is not activated. That way, the builtin fallback software implementation is present to supply the transparent test driver when some support is missing in it (mainly RSA key generation). Note that the declaration of accelerators does much more than just "fixing" the execution flow of driver wrapper tests, it makes all import and public key export cryptographic operations in all unit tests being handled by the transparent test driver (provided that it supports the key type). One test case related to key generation is partially disabled. This will be fixed with the rework of psa_generate_key along the lines described in psa-crypto-implementation-structure.md. Signed-off-by: Ronald Cron --- tests/scripts/all.sh | 4 ++-- tests/suites/test_suite_psa_crypto.data | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/scripts/all.sh b/tests/scripts/all.sh index 676c80449..a4c7a7417 100755 --- a/tests/scripts/all.sh +++ b/tests/scripts/all.sh @@ -1360,7 +1360,7 @@ component_test_psa_crypto_config_basic() { scripts/config.py set MBEDTLS_PSA_CRYPTO_DRIVERS scripts/config.py unset MBEDTLS_USE_PSA_CRYPTO # Need to define the correct symbol and include the test driver header path in order to build with the test driver - make CC=gcc CFLAGS="$ASAN_CFLAGS -DPSA_CRYPTO_DRIVER_TEST -I../tests/include -O2" LDFLAGS="$ASAN_CFLAGS" + make CC=gcc CFLAGS="$ASAN_CFLAGS -DPSA_CRYPTO_DRIVER_TEST -DMBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR -I../tests/include -O2" LDFLAGS="$ASAN_CFLAGS" msg "test: full + MBEDTLS_PSA_CRYPTO_CONFIG" make test @@ -2128,7 +2128,7 @@ component_test_psa_crypto_drivers () { msg "build: MBEDTLS_PSA_CRYPTO_DRIVERS w/ driver hooks" scripts/config.py set MBEDTLS_PSA_CRYPTO_DRIVERS # Need to define the correct symbol and include the test driver header path in order to build with the test driver - make CC=gcc CFLAGS="$ASAN_CFLAGS -DPSA_CRYPTO_DRIVER_TEST -I../tests/include -O2" LDFLAGS="$ASAN_CFLAGS" + make CC=gcc CFLAGS="$ASAN_CFLAGS -DPSA_CRYPTO_DRIVER_TEST -DMBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR -DMBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR -I../tests/include -O2" LDFLAGS="$ASAN_CFLAGS" msg "test: MBEDTLS_PSA_CRYPTO_DRIVERS, signature" make test diff --git a/tests/suites/test_suite_psa_crypto.data b/tests/suites/test_suite_psa_crypto.data index 99e2e8c18..3f2da76ef 100644 --- a/tests/suites/test_suite_psa_crypto.data +++ b/tests/suites/test_suite_psa_crypto.data @@ -2757,7 +2757,7 @@ depends_on:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECDSA_C generate_key:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):128:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH:PSA_ALG_ECDSA_ANY:PSA_ERROR_NOT_SUPPORTED PSA generate key: ECC, Curve25519, good -depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_ECP_DP_CURVE25519_ENABLED +depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_ECP_DP_CURVE25519_ENABLED:!MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR generate_key:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_MONTGOMERY):255:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_DERIVE:PSA_ALG_ECDH:PSA_SUCCESS PSA generate key: RSA, default e From 31520b4b1cc45b64c8371a0df76de6e1279fe17a Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Mon, 18 Jan 2021 11:57:58 +0100 Subject: [PATCH 33/38] Fix psa-crypto-implementation-structure.md Signed-off-by: Ronald Cron --- .../psa-crypto-implementation-structure.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/docs/architecture/psa-crypto-implementation-structure.md b/docs/architecture/psa-crypto-implementation-structure.md index ffc25efdb..c56346899 100644 --- a/docs/architecture/psa-crypto-implementation-structure.md +++ b/docs/architecture/psa-crypto-implementation-structure.md @@ -3,9 +3,9 @@ PSA Cryptograpy API implementation and PSA driver interface ## Introduction -The [PSA Cryptography API specification](https://armmbed.github.io/mbed-crypto/psa/#application-programming-interface) defines an interface to cryptographic operations which the Mbed TLS library provides a reference implementation for. The PSA Cryptography API specification is complemented by the PSA driver interface specification which defines an interface for cryptoprocessor drivers. +The [PSA Cryptography API specification](https://armmbed.github.io/mbed-crypto/psa/#application-programming-interface) defines an interface to cryptographic operations for which the Mbed TLS library provides a reference implementation. The PSA Cryptography API specification is complemented by the PSA driver interface specification which defines an interface for cryptoprocessor drivers. -This document describes the high level organization of the Mbed TLS PSA Cryptography API implementation which is tighly related to the PSA driver interface. +This document describes the high level organization of the Mbed TLS PSA Cryptography API implementation which is tightly related to the PSA driver interface. ## High level organization of the Mbed TLS PSA Cryptography API implementation In one sentence, the Mbed TLS PSA Cryptography API implementation is made of a core and PSA drivers as defined in the PSA driver interface. The key point is that software cryptographic operations are organized as PSA drivers: they interact with the core through the PSA driver interface. @@ -19,12 +19,12 @@ In one sentence, the Mbed TLS PSA Cryptography API implementation is made of a c ## The Mbed TLS PSA Cryptography API implementation core -The core implements all the APIs as defined in the PSA Cryptography API specification but do not perform on its own any cryptographic operation. The core relies on PSA drivers to actually -perform the cryptographic operations. The core is responsible of: +The core implements all the APIs as defined in the PSA Cryptography API specification but does not perform on its own any cryptographic operation. The core relies on PSA drivers to actually +perform the cryptographic operations. The core is responsible for: * the key store. -* checking PSA API arguments and translate them into valid arguments for the necessary calls to the PSA driver interface. -* dispatchng the cryptographic operations to the appropriate PSA drivers. +* checking PSA API arguments and translating them into valid arguments for the necessary calls to the PSA driver interface. +* dispatching the cryptographic operations to the appropriate PSA drivers. The sketch of an Mbed TLS PSA cryptographic API implementation is thus: ```C @@ -43,8 +43,8 @@ psa_status_t psa_api( ... ) return( status ); /* Post driver interface call processing: validation of the values returned - * by the driver, finalization ot the values to return to the caller, + * by the driver, finalization of the values to return to the caller, * clean-up in case of error ... */ } ``` -Obviously, for some PSA APIs the implementation is more complicated with several potential conditionnal calls to different driver entry points but most of PSA API code aimed to be organized along those lines. The implementation of the `psa_driver_wrapper_` function is generated by the build system based on the JSON driver description files of the various PSA drivers making up the Mbed TLS PSA Cryptography API implementation. +Obviously, for some PSA APIs the implementation is more complicated with several potential conditional calls to different driver entry points but most of PSA API code aims to be organized along those lines. The implementation of the `psa_driver_wrapper_` function is generated by the build system based on the JSON driver description files of the various PSA drivers making up the Mbed TLS PSA Cryptography API implementation. From 9cfdf6ebe71a6956abd2f0c0b7ec83b1362eb76e Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Mon, 18 Jan 2021 11:58:39 +0100 Subject: [PATCH 34/38] Fix coding style issues Signed-off-by: Ronald Cron --- library/psa_crypto_driver_wrappers.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/library/psa_crypto_driver_wrappers.c b/library/psa_crypto_driver_wrappers.c index fd03ed2bf..1eb9ebe80 100644 --- a/library/psa_crypto_driver_wrappers.c +++ b/library/psa_crypto_driver_wrappers.c @@ -501,7 +501,9 @@ psa_status_t psa_driver_wrapper_export_key( { if( ( drv->key_management == NULL ) || ( drv->key_management->p_export == NULL ) ) + { return( PSA_ERROR_NOT_SUPPORTED ); + } return( drv->key_management->p_export( drv_context, @@ -557,7 +559,9 @@ psa_status_t psa_driver_wrapper_export_public_key( { if( ( drv->key_management == NULL ) || ( drv->key_management->p_export_public == NULL ) ) + { return( PSA_ERROR_NOT_SUPPORTED ); + } return( drv->key_management->p_export_public( drv_context, From e907e55f39deb3c82a9f8817c1f433b5572397a5 Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Mon, 18 Jan 2021 13:22:38 +0100 Subject: [PATCH 35/38] psa: export: Check output buffer size earlier Check output buffer size before doing anything that requires a clean-up if a failure happens. Signed-off-by: Ronald Cron --- library/psa_crypto.c | 31 ++++++++++++------------------- 1 file changed, 12 insertions(+), 19 deletions(-) diff --git a/library/psa_crypto.c b/library/psa_crypto.c index 55b7d2f5b..2d933979a 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -1217,6 +1217,12 @@ psa_status_t psa_export_key( mbedtls_svc_key_id_t key, psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_slot_t *slot; + /* Reject a zero-length output buffer now, since this can never be a + * valid key representation. This way we know that data must be a valid + * pointer and we can do things like memset(data, ..., data_size). */ + if( data_size == 0 ) + return( PSA_ERROR_BUFFER_TOO_SMALL ); + /* Set the key to empty now, so that even when there are errors, we always * set data_length to a value between 0 and data_size. On error, setting * the key to empty is a good choice because an empty key representation is @@ -1232,15 +1238,6 @@ psa_status_t psa_export_key( mbedtls_svc_key_id_t key, if( status != PSA_SUCCESS ) return( status ); - /* Reject a zero-length output buffer now, since this can never be a - * valid key representation. This way we know that data must be a valid - * pointer and we can do things like memset(data, ..., data_size). */ - if( data_size == 0 ) - { - status = PSA_ERROR_BUFFER_TOO_SMALL; - goto exit; - } - psa_key_attributes_t attributes = { .core = slot->attr }; @@ -1248,7 +1245,6 @@ psa_status_t psa_export_key( mbedtls_svc_key_id_t key, slot->key.data, slot->key.bytes, data, data_size, data_length ); -exit: unlock_status = psa_unlock_key_slot( slot ); return( ( status == PSA_SUCCESS ) ? unlock_status : status ); @@ -1325,6 +1321,12 @@ psa_status_t psa_export_public_key( mbedtls_svc_key_id_t key, psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED; psa_key_slot_t *slot; + /* Reject a zero-length output buffer now, since this can never be a + * valid key representation. This way we know that data must be a valid + * pointer and we can do things like memset(data, ..., data_size). */ + if( data_size == 0 ) + return( PSA_ERROR_BUFFER_TOO_SMALL ); + /* Set the key to empty now, so that even when there are errors, we always * set data_length to a value between 0 and data_size. On error, setting * the key to empty is a good choice because an empty key representation is @@ -1342,15 +1344,6 @@ psa_status_t psa_export_public_key( mbedtls_svc_key_id_t key, goto exit; } - /* Reject a zero-length output buffer now, since this can never be a - * valid key representation. This way we know that data must be a valid - * pointer and we can do things like memset(data, ..., data_size). */ - if( data_size == 0 ) - { - status = PSA_ERROR_BUFFER_TOO_SMALL; - goto exit; - } - psa_key_attributes_t attributes = { .core = slot->attr }; From 1e87d5ba1df95b7e4974a331f5a4516e88b7fcb4 Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Mon, 18 Jan 2021 13:32:28 +0100 Subject: [PATCH 36/38] tests: psa: Fix export related tests Fix some export related tests that were relying on the fact that the size of the output buffer was checked after other parameters. Signed-off-by: Ronald Cron --- tests/suites/test_suite_psa_crypto.data | 2 +- tests/suites/test_suite_psa_crypto.function | 23 +++++++++++++------ ..._suite_psa_crypto_slot_management.function | 5 ++-- 3 files changed, 20 insertions(+), 10 deletions(-) diff --git a/tests/suites/test_suite_psa_crypto.data b/tests/suites/test_suite_psa_crypto.data index 3f2da76ef..307b2c171 100644 --- a/tests/suites/test_suite_psa_crypto.data +++ b/tests/suites/test_suite_psa_crypto.data @@ -244,7 +244,7 @@ import_export_public_key:"70076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fb PSA import/export-public: cannot export-public a symmetric key depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C -import_export_public_key:"2b7e151628aed2a6abf7158809cf4f3c":PSA_KEY_TYPE_AES:PSA_ALG_CBC_NO_PADDING:0:PSA_ERROR_INVALID_ARGUMENT:"" +import_export_public_key:"2b7e151628aed2a6abf7158809cf4f3c":PSA_KEY_TYPE_AES:PSA_ALG_CBC_NO_PADDING:0:PSA_ERROR_INVALID_ARGUMENT:"2b7e151628aed2a6abf7158809cf4f3c" PSA import/export EC secp256r1 public key: good depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED diff --git a/tests/suites/test_suite_psa_crypto.function b/tests/suites/test_suite_psa_crypto.function index 82514d679..a65c482a5 100644 --- a/tests/suites/test_suite_psa_crypto.function +++ b/tests/suites/test_suite_psa_crypto.function @@ -1028,19 +1028,21 @@ static int exercise_export_key( mbedtls_svc_key_id_t key, PSA_ASSERT( psa_get_key_attributes( key, &attributes ) ); + exported_size = PSA_EXPORT_KEY_OUTPUT_SIZE( + psa_get_key_type( &attributes ), + psa_get_key_bits( &attributes ) ); + ASSERT_ALLOC( exported, exported_size ); + if( ( usage & PSA_KEY_USAGE_EXPORT ) == 0 && ! PSA_KEY_TYPE_IS_PUBLIC_KEY( psa_get_key_type( &attributes ) ) ) { - TEST_EQUAL( psa_export_key( key, NULL, 0, &exported_length ), + TEST_EQUAL( psa_export_key( key, exported, + exported_size, &exported_length ), PSA_ERROR_NOT_PERMITTED ); ok = 1; goto exit; } - exported_size = PSA_EXPORT_KEY_OUTPUT_SIZE( psa_get_key_type( &attributes ), - psa_get_key_bits( &attributes ) ); - ASSERT_ALLOC( exported, exported_size ); - PSA_ASSERT( psa_export_key( key, exported, exported_size, &exported_length ) ); @@ -1071,9 +1073,16 @@ static int exercise_export_public_key( mbedtls_svc_key_id_t key ) PSA_ASSERT( psa_get_key_attributes( key, &attributes ) ); if( ! PSA_KEY_TYPE_IS_ASYMMETRIC( psa_get_key_type( &attributes ) ) ) { - TEST_EQUAL( psa_export_public_key( key, NULL, 0, &exported_length ), + exported_size = PSA_EXPORT_KEY_OUTPUT_SIZE( + psa_get_key_type( &attributes ), + psa_get_key_bits( &attributes ) ); + ASSERT_ALLOC( exported, exported_size ); + + TEST_EQUAL( psa_export_public_key( key, exported, + exported_size, &exported_length ), PSA_ERROR_INVALID_ARGUMENT ); - return( 1 ); + ok = 1; + goto exit; } public_type = PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR( diff --git a/tests/suites/test_suite_psa_crypto_slot_management.function b/tests/suites/test_suite_psa_crypto_slot_management.function index b0c660b46..d14dfbb74 100644 --- a/tests/suites/test_suite_psa_crypto_slot_management.function +++ b/tests/suites/test_suite_psa_crypto_slot_management.function @@ -343,9 +343,9 @@ void persistent_slot_lifecycle( int lifetime_arg, int owner_id_arg, int id_arg, psa_get_key_type( &read_attributes ) ); TEST_EQUAL( psa_get_key_bits( &attributes ), psa_get_key_bits( &read_attributes ) ); + ASSERT_ALLOC( reexported, key_data->len ); if( usage_flags & PSA_KEY_USAGE_EXPORT ) { - ASSERT_ALLOC( reexported, key_data->len ); PSA_ASSERT( psa_export_key( id, reexported, key_data->len, &reexported_length ) ); ASSERT_COMPARE( key_data->x, key_data->len, @@ -353,7 +353,8 @@ void persistent_slot_lifecycle( int lifetime_arg, int owner_id_arg, int id_arg, } else { - TEST_EQUAL( psa_export_key( id, NULL, 0, &reexported_length ), + TEST_EQUAL( psa_export_key( id, reexported, + key_data->len, &reexported_length ), PSA_ERROR_NOT_PERMITTED ); } PSA_ASSERT( psa_close_key( handle ) ); From d9763466b78a1a2a29b533c1c4c1c117d15137a1 Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Mon, 18 Jan 2021 18:11:19 +0100 Subject: [PATCH 37/38] Expand and improve psa-crypto-implementation-structure.md Signed-off-by: Ronald Cron --- .../psa-crypto-implementation-structure.md | 25 ++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/docs/architecture/psa-crypto-implementation-structure.md b/docs/architecture/psa-crypto-implementation-structure.md index c56346899..025a6235f 100644 --- a/docs/architecture/psa-crypto-implementation-structure.md +++ b/docs/architecture/psa-crypto-implementation-structure.md @@ -47,4 +47,27 @@ psa_status_t psa_api( ... ) * clean-up in case of error ... */ } ``` -Obviously, for some PSA APIs the implementation is more complicated with several potential conditional calls to different driver entry points but most of PSA API code aims to be organized along those lines. The implementation of the `psa_driver_wrapper_` function is generated by the build system based on the JSON driver description files of the various PSA drivers making up the Mbed TLS PSA Cryptography API implementation. +The code of most PSA APIs is expected to match precisely the above layout. However, it is likely that the code structure of some APIs will be more complicated with several calls to the driver interface, mainly to encompass a larger variety of hardware designs. For example, to encompass hardware accelerators that are capable of verifying a MAC and those that are only capable of computing a MAC, the psa_mac_verify() API could call first psa_driver_wrapper_mac_verify() and then fallback to psa_driver_wrapper_mac_compute(). + +The implementations of `psa_driver_wrapper_` functions are generated by the build system based on the JSON driver description files of the various PSA drivers making up the Mbed TLS PSA Cryptography API implementation. The implementations are generated in a psa_crypto_driver_wrappers.c C file and the function prototypes declared in a psa_crypto_driver_wrappers.h header file. + +The psa_driver_wrapper_() functions dispatch cryptographic operations to accelerator drivers, secure element drivers as well as to the software implementations of cryptographic operations. + +Note that the implementation allows to build the library with only a C compiler by shipping a generated file corresponding to a pure software implementation. The driver entry points and their code in this generated file are guarded by pre-processor directives based on PSA_WANT_xyz macros (see [Conditional inclusion of cryptographic mechanism through the PSA API in Mbed TLS](psa-conditional-inclusion-c.html). That way, it is possible to compile and include in the library only the desired cryptographic operations. + +### Key creation + +Key creation implementation in Mbed TLS PSA core is articulated around three internal functions: psa_start_key_creation(), psa_finish_key_creation() and psa_fail_key_creation(). Implementations of key creation PSA APIs, namely psa_import_key(), psa_generate_key(), psa_key_derivation_output_key() and psa_copy_key() go by the following sequence: + 1. Check the input parameters. + 2. Call psa_start_key_creation() that allocates a key slot, prepares it with the specified key attributes, and in case of a volatile key assign it a volatile key identifier. + 3. Generate or copy the key material into the key slot. This entails the allocation of the buffer to store the key material. + 4. Call psa_finish_key_creation() that mostly saves persistent keys into persistent storage. + +In case of any error occuring at step 3 or 4, psa_fail_key_creation() is called. It wipes and cleans the slot especially the key material: reset to zero of the RAM memory that contained the key material, free the allocated buffer. + + +## Mbed TLS PSA Cryptography API implementation drivers + +A driver of the Mbed TLS PSA Cryptography API implementation (Mbed TLS PSA driver in the following) is a driver in the sense that it is compliant with the PSA driver interface specification. But it is not an actual driver that drives some hardware. It implements cryptographic operations purely in software. + +An Mbed TLS PSA driver C file is named psa_crypto_.c and its associated header file psa_crypto_.h. The functions implementing a driver entry point as defined in the PSA driver interface specification are named as mbedtls_psa__(). As an example, the psa_crypto_rsa.c and psa_crypto_rsa.h are the files containing the Mbed TLS PSA driver implementing RSA cryptographic operations. This RSA driver implements among other entry points the "import_key" entry point. The function implementing this entry point is named mbedtls_psa_rsa_import_key(). From 1bf4c55fd717b9aee45b0659750e4af2469518fc Mon Sep 17 00:00:00 2001 From: Ronald Cron Date: Mon, 1 Feb 2021 11:37:53 +0100 Subject: [PATCH 38/38] psa: Improve psa_import_key_into_slot() documentation Signed-off-by: Ronald Cron --- library/psa_crypto_core.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/psa_crypto_core.h b/library/psa_crypto_core.h index 4263a77b0..cf9d6d0eb 100644 --- a/library/psa_crypto_core.h +++ b/library/psa_crypto_core.h @@ -223,8 +223,8 @@ psa_status_t mbedtls_to_psa_error( int ret ); * \param[in] data The buffer containing the key data in import * format. * \param[in] data_length Size of the \p data buffer in bytes. - * \param[out] key_buffer The buffer containing the key data in output - * format. + * \param[out] key_buffer The buffer to contain the key data in output + * format upon successful return. * \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes. This * size is greater or equal to \p data_length. * \param[out] key_buffer_length The length of the data written in \p