diff --git a/library/psa_crypto.c b/library/psa_crypto.c index e3ba1d38b..f304950e0 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -34,6 +34,7 @@ #include "psa_crypto_driver_wrappers.h" #include "psa_crypto_ecp.h" #include "psa_crypto_rsa.h" +#include "psa_crypto_ecp.h" #if defined(MBEDTLS_PSA_CRYPTO_SE_C) #include "psa_crypto_se.h" #endif @@ -5956,66 +5957,80 @@ psa_status_t mbedtls_psa_inject_entropy( const uint8_t *seed, } #endif /* MBEDTLS_PSA_INJECT_ENTROPY */ -#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) -static psa_status_t psa_read_rsa_exponent( const uint8_t *domain_parameters, - size_t domain_parameters_size, - int *exponent ) +/** Validate the key type and size for key generation + * + * \param type The key type + * \param bits The number of bits of the key + * + * \retval #PSA_SUCCESS + * The key type and size are valid. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The size in bits of the key is not valid. + * \retval #PSA_ERROR_NOT_SUPPORTED + * The type and/or the size in bits of the key or the combination of + * the two is not supported. + */ +static psa_status_t psa_validate_key_type_and_size_for_key_generation( + psa_key_type_t type, size_t bits ) { - size_t i; - uint32_t acc = 0; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; - if( domain_parameters_size == 0 ) + if( key_type_is_raw_bytes( type ) ) { - *exponent = 65537; + status = validate_unstructured_key_bit_size( type, bits ); + if( status != PSA_SUCCESS ) + return( status ); + } + else +#if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR) + if( PSA_KEY_TYPE_IS_RSA( type ) && PSA_KEY_TYPE_IS_KEY_PAIR( type ) ) + { + 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(). */ + if( bits % 8 != 0 ) + return( PSA_ERROR_NOT_SUPPORTED ); + } + else +#endif /* defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR) */ + +#if defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR) + if( PSA_KEY_TYPE_IS_ECC( type ) && PSA_KEY_TYPE_IS_KEY_PAIR( type ) ) + { + /* To avoid empty block, return successfully here. */ return( PSA_SUCCESS ); } + else +#endif /* defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR) */ + { + return( PSA_ERROR_NOT_SUPPORTED ); + } - /* Mbed TLS encodes the public exponent as an int. For simplicity, only - * support values that fit in a 32-bit integer, which is larger than - * int on just about every platform anyway. */ - if( domain_parameters_size > sizeof( acc ) ) - return( PSA_ERROR_NOT_SUPPORTED ); - for( i = 0; i < domain_parameters_size; i++ ) - acc = ( acc << 8 ) | domain_parameters[i]; - if( acc > INT_MAX ) - return( PSA_ERROR_NOT_SUPPORTED ); - *exponent = acc; return( PSA_SUCCESS ); } -#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) */ -static psa_status_t psa_generate_key_internal( - psa_key_slot_t *slot, size_t bits, - const uint8_t *domain_parameters, size_t domain_parameters_size ) +psa_status_t psa_generate_key_internal( + const psa_key_attributes_t *attributes, + uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length ) { - psa_key_type_t type = slot->attr.type; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_type_t type = attributes->core.type; - if( domain_parameters == NULL && domain_parameters_size != 0 ) + if( ( attributes->domain_parameters == NULL ) && + ( attributes->domain_parameters_size != 0 ) ) return( PSA_ERROR_INVALID_ARGUMENT ); if( key_type_is_raw_bytes( type ) ) { - psa_status_t status; - - status = validate_unstructured_key_bit_size( slot->attr.type, bits ); + status = psa_generate_random( key_buffer, key_buffer_size ); if( status != PSA_SUCCESS ) return( status ); - /* Allocate memory for the key */ - status = psa_allocate_buffer_to_slot( slot, PSA_BITS_TO_BYTES( bits ) ); - if( status != PSA_SUCCESS ) - return( status ); - - 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->key.data, - slot->key.bytes ); + psa_des_set_key_parity( key_buffer, key_buffer_size ); #endif /* MBEDTLS_DES_C */ } else @@ -6023,49 +6038,10 @@ static psa_status_t psa_generate_key_internal( #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) if ( type == PSA_KEY_TYPE_RSA_KEY_PAIR ) { - mbedtls_rsa_context rsa; - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - int exponent; - psa_status_t status; - if( bits > PSA_VENDOR_RSA_MAX_KEY_BITS ) - return( PSA_ERROR_NOT_SUPPORTED ); - /* Accept only byte-aligned keys, for the same reasons as - * in mbedtls_psa_rsa_import_key(). */ - if( bits % 8 != 0 ) - return( PSA_ERROR_NOT_SUPPORTED ); - status = psa_read_rsa_exponent( domain_parameters, - domain_parameters_size, - &exponent ); - if( status != PSA_SUCCESS ) - return( status ); - mbedtls_rsa_init( &rsa, MBEDTLS_RSA_PKCS_V15, MBEDTLS_MD_NONE ); - ret = mbedtls_rsa_gen_key( &rsa, - mbedtls_psa_get_random, - MBEDTLS_PSA_RANDOM_STATE, - (unsigned int) bits, - exponent ); - if( ret != 0 ) - return( mbedtls_to_psa_error( ret ) ); - - /* Make sure to always have an export representation available */ - size_t bytes = PSA_KEY_EXPORT_RSA_KEY_PAIR_MAX_SIZE( bits ); - - status = psa_allocate_buffer_to_slot( slot, bytes ); - if( status != PSA_SUCCESS ) - { - mbedtls_rsa_free( &rsa ); - return( status ); - } - - 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 ); - return( status ); + return( mbedtls_psa_rsa_generate_key( attributes, + key_buffer, + key_buffer_size, + key_buffer_length ) ); } else #endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) */ @@ -6073,50 +6049,15 @@ static psa_status_t psa_generate_key_internal( #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) if ( PSA_KEY_TYPE_IS_ECC( type ) && PSA_KEY_TYPE_IS_KEY_PAIR( type ) ) { - psa_ecc_family_t curve = PSA_KEY_TYPE_ECC_GET_FAMILY( type ); - mbedtls_ecp_group_id grp_id = - mbedtls_ecc_group_of_psa( curve, bits, 0 ); - const mbedtls_ecp_curve_info *curve_info = - mbedtls_ecp_curve_info_from_grp_id( grp_id ); - mbedtls_ecp_keypair ecp; - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - if( domain_parameters_size != 0 ) - return( PSA_ERROR_NOT_SUPPORTED ); - if( grp_id == MBEDTLS_ECP_DP_NONE || curve_info == NULL ) - return( PSA_ERROR_NOT_SUPPORTED ); - mbedtls_ecp_keypair_init( &ecp ); - ret = mbedtls_ecp_gen_key( grp_id, &ecp, - mbedtls_psa_get_random, - MBEDTLS_PSA_RANDOM_STATE ); - if( ret != 0 ) - { - mbedtls_ecp_keypair_free( &ecp ); - return( mbedtls_to_psa_error( ret ) ); - } - - - /* Make sure to always have an export representation available */ - size_t bytes = PSA_BITS_TO_BYTES( bits ); - psa_status_t status = psa_allocate_buffer_to_slot( slot, bytes ); - if( status != PSA_SUCCESS ) - { - mbedtls_ecp_keypair_free( &ecp ); - return( status ); - } - - status = mbedtls_to_psa_error( - mbedtls_ecp_write_key( &ecp, slot->key.data, bytes ) ); - - mbedtls_ecp_keypair_free( &ecp ); - if( status != PSA_SUCCESS ) { - memset( slot->key.data, 0, bytes ); - psa_remove_key_data_from_memory( slot ); - } - return( status ); + return( mbedtls_psa_ecp_generate_key( attributes, + key_buffer, + key_buffer_size, + key_buffer_length ) ); } else #endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) */ { + (void)key_buffer_length; return( PSA_ERROR_NOT_SUPPORTED ); } @@ -6129,6 +6070,7 @@ psa_status_t psa_generate_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 key_buffer_size; *key = MBEDTLS_SVC_KEY_ID_INIT; @@ -6142,15 +6084,42 @@ psa_status_t psa_generate_key( const psa_key_attributes_t *attributes, if( status != PSA_SUCCESS ) goto exit; - status = psa_driver_wrapper_generate_key( attributes, - slot ); - if( status != PSA_ERROR_NOT_SUPPORTED || - psa_key_lifetime_is_external( attributes->core.lifetime ) ) - 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 ) + { + if ( PSA_KEY_LIFETIME_GET_LOCATION( attributes->core.lifetime ) == + PSA_KEY_LOCATION_LOCAL_STORAGE ) + { + status = psa_validate_key_type_and_size_for_key_generation( + attributes->core.type, attributes->core.bits ); + if( status != PSA_SUCCESS ) + goto exit; - status = psa_generate_key_internal( - slot, attributes->core.bits, - attributes->domain_parameters, attributes->domain_parameters_size ); + key_buffer_size = PSA_EXPORT_KEY_OUTPUT_SIZE( + attributes->core.type, + attributes->core.bits ); + } + else + { + status = psa_driver_wrapper_get_key_buffer_size( + attributes, &key_buffer_size ); + if( status != PSA_SUCCESS ) + goto exit; + } + + status = psa_allocate_buffer_to_slot( slot, key_buffer_size ); + if( status != PSA_SUCCESS ) + goto exit; + } + + status = psa_driver_wrapper_generate_key( attributes, + slot->key.data, slot->key.bytes, &slot->key.bytes ); + + if( status != PSA_SUCCESS ) + psa_remove_key_data_from_memory( slot ); exit: if( status == PSA_SUCCESS ) @@ -6161,8 +6130,6 @@ exit: return( status ); } - - /****************************************************************/ /* Module setup */ /****************************************************************/ diff --git a/library/psa_crypto_core.h b/library/psa_crypto_core.h index cf9d6d0eb..9f108681a 100644 --- a/library/psa_crypto_core.h +++ b/library/psa_crypto_core.h @@ -299,4 +299,29 @@ psa_status_t psa_export_public_key_internal( const uint8_t *key_buffer, size_t key_buffer_size, uint8_t *data, size_t data_size, size_t *data_length ); +/** + * \brief Generate a key. + * + * \note The signature of the function is that of a PSA driver generate_key + * entry point. + * + * \param[in] attributes The attributes for the key to generate. + * \param[out] key_buffer Buffer where the key data is to be written. + * \param[in] key_buffer_size Size of \p key_buffer in bytes. + * \param[out] key_buffer_length On success, the number of bytes written in + * \p key_buffer. + * + * \retval #PSA_SUCCESS + * The key was generated successfully. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \retval #PSA_ERROR_NOT_SUPPORTED + * Key size in bits or type not supported. + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of \p key_buffer is too small. + */ +psa_status_t psa_generate_key_internal( const psa_key_attributes_t *attributes, + uint8_t *key_buffer, + size_t key_buffer_size, + size_t *key_buffer_length ); + #endif /* PSA_CRYPTO_CORE_H */ diff --git a/library/psa_crypto_driver_wrappers.c b/library/psa_crypto_driver_wrappers.c index 1eb9ebe80..3cb75576e 100644 --- a/library/psa_crypto_driver_wrappers.c +++ b/library/psa_crypto_driver_wrappers.c @@ -238,62 +238,56 @@ psa_status_t psa_driver_wrapper_verify_hash( psa_key_slot_t *slot, #endif /* PSA_CRYPTO_DRIVER_PRESENT */ } -#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) -/** Calculate the size to allocate for buffering a key with given attributes. +/** Get the key buffer size for the key material of a generated key in the + * case of an opaque driver without storage. * - * This function provides a way to get the expected size for storing a key with - * the given attributes. This will be the size of the export representation for - * cleartext keys, and a driver-defined size for keys stored by opaque drivers. - * - * \param[in] attributes The key attribute structure of the key to store. - * \param[out] expected_size On success, a byte size large enough to contain - * the declared key. + * \param[in] attributes The key attributes. + * \param[out] key_buffer_size Minimum buffer size to contain the key material * * \retval #PSA_SUCCESS + * The minimum size for a buffer to contain the key material has been + * returned successfully. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The size in bits of the key is not valid. * \retval #PSA_ERROR_NOT_SUPPORTED + * The type and/or the size in bits of the key or the combination of + * the two is not supported. */ -static psa_status_t get_expected_key_size( const psa_key_attributes_t *attributes, - size_t *expected_size ) +psa_status_t psa_driver_wrapper_get_key_buffer_size( + const psa_key_attributes_t *attributes, + size_t *key_buffer_size ) { - size_t buffer_size = 0; psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( attributes->core.lifetime ); psa_key_type_t key_type = attributes->core.type; size_t key_bits = attributes->core.bits; + *key_buffer_size = 0; switch( location ) { - case PSA_KEY_LOCATION_LOCAL_STORAGE: - buffer_size = PSA_EXPORT_KEY_OUTPUT_SIZE( key_type, key_bits ); - - if( buffer_size == 0 ) - return( PSA_ERROR_NOT_SUPPORTED ); - - *expected_size = buffer_size; - return( PSA_SUCCESS ); - #if defined(PSA_CRYPTO_DRIVER_TEST) case PSA_CRYPTO_TEST_DRIVER_LIFETIME: #ifdef TEST_DRIVER_KEY_CONTEXT_SIZE_FUNCTION - *expected_size = test_size_function( key_type, key_bits ); + *key_buffer_size = test_size_function( key_type, key_bits ); return( PSA_SUCCESS ); #else /* TEST_DRIVER_KEY_CONTEXT_SIZE_FUNCTION */ if( PSA_KEY_TYPE_IS_KEY_PAIR( key_type ) ) { - int public_key_overhead = ( ( TEST_DRIVER_KEY_CONTEXT_STORE_PUBLIC_KEY == 1 ) ? - PSA_EXPORT_KEY_OUTPUT_SIZE( key_type, key_bits ) : 0 ); - *expected_size = TEST_DRIVER_KEY_CONTEXT_BASE_SIZE + int public_key_overhead = + ( ( TEST_DRIVER_KEY_CONTEXT_STORE_PUBLIC_KEY == 1 ) ? + PSA_EXPORT_KEY_OUTPUT_SIZE( key_type, key_bits ) : 0 ); + *key_buffer_size = TEST_DRIVER_KEY_CONTEXT_BASE_SIZE + TEST_DRIVER_KEY_CONTEXT_PUBLIC_KEY_SIZE + public_key_overhead; } - else if( PSA_KEY_TYPE_IS_PUBLIC_KEY( attributes->core.type ) ) + else if( PSA_KEY_TYPE_IS_PUBLIC_KEY( key_type ) ) { - *expected_size = TEST_DRIVER_KEY_CONTEXT_BASE_SIZE + *key_buffer_size = TEST_DRIVER_KEY_CONTEXT_BASE_SIZE + TEST_DRIVER_KEY_CONTEXT_PUBLIC_KEY_SIZE; } else if ( !PSA_KEY_TYPE_IS_KEY_PAIR( key_type ) && - !PSA_KEY_TYPE_IS_PUBLIC_KEY ( attributes->core.type ) ) + !PSA_KEY_TYPE_IS_PUBLIC_KEY ( key_type ) ) { - *expected_size = TEST_DRIVER_KEY_CONTEXT_BASE_SIZE + *key_buffer_size = TEST_DRIVER_KEY_CONTEXT_BASE_SIZE + TEST_DRIVER_KEY_CONTEXT_SYMMETRIC_FACTOR * ( ( key_bits + 7 ) / 8 ); } @@ -306,21 +300,26 @@ static psa_status_t get_expected_key_size( const psa_key_attributes_t *attribute #endif /* PSA_CRYPTO_DRIVER_TEST */ default: + (void)key_type; + (void)key_bits; return( PSA_ERROR_NOT_SUPPORTED ); } } -#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ -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_generate_key( + const psa_key_attributes_t *attributes, + uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length ) { -#if defined(PSA_CRYPTO_DRIVER_PRESENT) + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_location_t location = + PSA_KEY_LIFETIME_GET_LOCATION(attributes->core.lifetime); + /* 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( slot->attr.lifetime, &drv, &drv_context ) ) + if( psa_get_se_driver( attributes->core.lifetime, &drv, &drv_context ) ) { size_t pubkey_length = 0; /* We don't support this feature yet */ if( drv->key_management == NULL || @@ -330,83 +329,53 @@ 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, psa_key_slot_get_slot_number( slot ), + drv_context, + *( (psa_key_slot_number_t *)key_buffer ), attributes, NULL, 0, &pubkey_length ) ); } #endif /* MBEDTLS_PSA_CRYPTO_SE_C */ - /* Then try accelerator API */ -#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); - size_t export_size = 0; - - status = get_expected_key_size( attributes, &export_size ); - if( status != PSA_SUCCESS ) - return( status ); - - slot->key.data = mbedtls_calloc(1, export_size); - if( slot->key.data == NULL ) - return( PSA_ERROR_INSUFFICIENT_MEMORY ); - slot->key.bytes = export_size; - 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) /* Transparent drivers are limited to generating asymmetric keys */ - if( ! PSA_KEY_TYPE_IS_ASYMMETRIC( slot->attr.type ) ) + if( PSA_KEY_TYPE_IS_ASYMMETRIC( attributes->core.type ) ) { - status = PSA_ERROR_NOT_SUPPORTED; - break; - } + /* Cycle through all known transparent accelerators */ #if defined(PSA_CRYPTO_DRIVER_TEST) - status = test_transparent_generate_key( attributes, - slot->key.data, - slot->key.bytes, - &slot->key.bytes ); - /* Declared with fallback == true */ - if( status != PSA_ERROR_NOT_SUPPORTED ) - break; + status = test_transparent_generate_key( + attributes, key_buffer, key_buffer_size, + key_buffer_length ); + /* Declared with fallback == true */ + if( status != PSA_ERROR_NOT_SUPPORTED ) + break; #endif /* PSA_CRYPTO_DRIVER_TEST */ - /* Fell through, meaning no accelerator supports this operation */ - status = PSA_ERROR_NOT_SUPPORTED; + } +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + + /* Software fallback */ + status = psa_generate_key_internal( + attributes, key_buffer, key_buffer_size, key_buffer_length ); break; + /* 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: - status = test_opaque_generate_key( attributes, - slot->key.data, - slot->key.bytes, - &slot->key.bytes ); + status = test_opaque_generate_key( + attributes, key_buffer, key_buffer_size, key_buffer_length ); break; #endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + default: /* Key is declared with a lifetime not known to us */ status = PSA_ERROR_INVALID_ARGUMENT; break; } - if( status != PSA_SUCCESS ) - { - /* free allocated buffer */ - mbedtls_free( slot->key.data ); - slot->key.data = NULL; - slot->key.bytes = 0; - } - return( status ); -#else /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ - return( PSA_ERROR_NOT_SUPPORTED ); -#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ -#else /* PSA_CRYPTO_DRIVER_PRESENT */ - (void) attributes; - (void) slot; - - return( PSA_ERROR_NOT_SUPPORTED ); -#endif /* PSA_CRYPTO_DRIVER_PRESENT */ } psa_status_t psa_driver_wrapper_import_key( diff --git a/library/psa_crypto_driver_wrappers.h b/library/psa_crypto_driver_wrappers.h index 27d8b64ea..ad16cddea 100644 --- a/library/psa_crypto_driver_wrappers.h +++ b/library/psa_crypto_driver_wrappers.h @@ -63,9 +63,13 @@ psa_status_t psa_driver_wrapper_export_public_key( 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_get_key_buffer_size( + const psa_key_attributes_t *attributes, + size_t *key_buffer_size ); + psa_status_t psa_driver_wrapper_generate_key( const psa_key_attributes_t *attributes, - psa_key_slot_t *slot ); + uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length ); /* * Cipher functions diff --git a/library/psa_crypto_ecp.c b/library/psa_crypto_ecp.c index 1a8f15ede..23ec6acef 100644 --- a/library/psa_crypto_ecp.c +++ b/library/psa_crypto_ecp.c @@ -292,6 +292,51 @@ static psa_status_t ecp_export_public_key( #endif /* defined(BUILTIN_KEY_TYPE_ECC_KEY_PAIR) || * defined(BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) */ +#if defined(BUILTIN_KEY_TYPE_ECC_KEY_PAIR) +static psa_status_t ecp_generate_key( + const psa_key_attributes_t *attributes, + uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + psa_ecc_family_t curve = PSA_KEY_TYPE_ECC_GET_FAMILY( + attributes->core.type ); + mbedtls_ecp_group_id grp_id = + mbedtls_ecc_group_of_psa( curve, attributes->core.bits, 0 ); + + const mbedtls_ecp_curve_info *curve_info = + mbedtls_ecp_curve_info_from_grp_id( grp_id ); + mbedtls_ecp_keypair ecp; + + 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 ); + + mbedtls_ecp_keypair_init( &ecp ); + ret = mbedtls_ecp_gen_key( grp_id, &ecp, + mbedtls_psa_get_random, + MBEDTLS_PSA_RANDOM_STATE ); + if( ret != 0 ) + { + mbedtls_ecp_keypair_free( &ecp ); + return( mbedtls_to_psa_error( ret ) ); + } + + status = mbedtls_to_psa_error( + mbedtls_ecp_write_key( &ecp, key_buffer, key_buffer_size ) ); + + mbedtls_ecp_keypair_free( &ecp ); + + if( status == PSA_SUCCESS ) + *key_buffer_length = key_buffer_size; + + return( status ); +} +#endif /* defined(BUILTIN_KEY_TYPE_ECC_KEY_PAIR) */ + #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) || \ defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) @@ -318,6 +363,16 @@ psa_status_t mbedtls_psa_ecp_export_public_key( #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_ECC_KEY_PAIR) +psa_status_t mbedtls_psa_ecp_generate_key( + const psa_key_attributes_t *attributes, + uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length ) +{ + return( ecp_generate_key( attributes, key_buffer, key_buffer_size, + key_buffer_length ) ); +} +#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) */ + /* * BEYOND THIS POINT, TEST DRIVER ENTRY POINTS ONLY. */ @@ -350,6 +405,18 @@ psa_status_t mbedtls_transparent_test_driver_ecp_export_public_key( #endif /* defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR) || defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_PUBLIC_KEY) */ +#if defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR) && \ + defined(MBEDTLS_GENPRIME) +psa_status_t mbedtls_transparent_test_driver_ecp_generate_key( + const psa_key_attributes_t *attributes, + uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length ) +{ + return( ecp_generate_key( attributes, key_buffer, key_buffer_size, + key_buffer_length ) ); +} +#endif /* defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR) && + defined(MBEDTLS_GENPRIME) */ + #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 59b61b9e5..5c9b63c39 100644 --- a/library/psa_crypto_ecp.h +++ b/library/psa_crypto_ecp.h @@ -123,11 +123,35 @@ 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 ); +/** + * \brief Generate an ECP key. + * + * \note The signature of the function is that of a PSA driver generate_key + * entry point. + * + * \param[in] attributes The attributes for the ECP key to generate. + * \param[out] key_buffer Buffer where the key data is to be written. + * \param[in] key_buffer_size Size of \p key_buffer in bytes. + * \param[out] key_buffer_length On success, the number of bytes written in + * \p key_buffer. + * + * \retval #PSA_SUCCESS + * The key was successfully generated. + * \retval #PSA_ERROR_NOT_SUPPORTED + * Key length or type not supported. + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of \p key_buffer is too small. + */ +psa_status_t mbedtls_psa_ecp_generate_key( + const psa_key_attributes_t *attributes, + uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length ); + /* * BEYOND THIS POINT, TEST DRIVER ENTRY POINTS ONLY. */ #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, @@ -139,6 +163,10 @@ psa_status_t mbedtls_transparent_test_driver_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 ); +psa_status_t mbedtls_transparent_test_driver_ecp_generate_key( + const psa_key_attributes_t *attributes, + uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_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 aae1d056a..fa64001ed 100644 --- a/library/psa_crypto_rsa.c +++ b/library/psa_crypto_rsa.c @@ -24,6 +24,7 @@ #include <psa/crypto.h> #include "psa_crypto_core.h" +#include "psa_crypto_random_impl.h" #include "psa_crypto_rsa.h" #include <stdlib.h> @@ -258,6 +259,66 @@ static psa_status_t rsa_export_public_key( #endif /* defined(BUILTIN_KEY_TYPE_RSA_KEY_PAIR) || * defined(BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) */ +#if defined(BUILTIN_KEY_TYPE_RSA_KEY_PAIR) +static psa_status_t psa_rsa_read_exponent( const uint8_t *domain_parameters, + size_t domain_parameters_size, + int *exponent ) +{ + size_t i; + uint32_t acc = 0; + + if( domain_parameters_size == 0 ) + { + *exponent = 65537; + return( PSA_SUCCESS ); + } + + /* Mbed TLS encodes the public exponent as an int. For simplicity, only + * support values that fit in a 32-bit integer, which is larger than + * int on just about every platform anyway. */ + if( domain_parameters_size > sizeof( acc ) ) + return( PSA_ERROR_NOT_SUPPORTED ); + for( i = 0; i < domain_parameters_size; i++ ) + acc = ( acc << 8 ) | domain_parameters[i]; + if( acc > INT_MAX ) + return( PSA_ERROR_NOT_SUPPORTED ); + *exponent = acc; + return( PSA_SUCCESS ); +} + +static psa_status_t rsa_generate_key( + const psa_key_attributes_t *attributes, + uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length ) +{ + psa_status_t status; + mbedtls_rsa_context rsa; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + int exponent; + + status = psa_rsa_read_exponent( attributes->domain_parameters, + attributes->domain_parameters_size, + &exponent ); + if( status != PSA_SUCCESS ) + return( status ); + + mbedtls_rsa_init( &rsa, MBEDTLS_RSA_PKCS_V15, MBEDTLS_MD_NONE ); + ret = mbedtls_rsa_gen_key( &rsa, + mbedtls_psa_get_random, + MBEDTLS_PSA_RANDOM_STATE, + (unsigned int)attributes->core.bits, + exponent ); + if( ret != 0 ) + return( mbedtls_to_psa_error( ret ) ); + + status = mbedtls_psa_rsa_export_key( attributes->core.type, + &rsa, key_buffer, key_buffer_size, + key_buffer_length ); + mbedtls_rsa_free( &rsa ); + + return( status ); +} +#endif /* defined(BUILTIN_KEY_TYPE_RSA_KEY_PAIR) */ + #if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) || \ defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) @@ -284,6 +345,16 @@ psa_status_t mbedtls_psa_rsa_export_public_key( #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_RSA_KEY_PAIR) +psa_status_t mbedtls_psa_rsa_generate_key( + const psa_key_attributes_t *attributes, + uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length ) +{ + return( rsa_generate_key( attributes, key_buffer, key_buffer_size, + key_buffer_length ) ); +} +#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) */ + /* * BEYOND THIS POINT, TEST DRIVER ENTRY POINTS ONLY. */ @@ -316,6 +387,16 @@ psa_status_t mbedtls_transparent_test_driver_rsa_export_public_key( #endif /* defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR) || defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_PUBLIC_KEY) */ +#if defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR) +psa_status_t mbedtls_transparent_test_driver_rsa_generate_key( + const psa_key_attributes_t *attributes, + uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length ) +{ + return( rsa_generate_key( attributes, key_buffer, key_buffer_size, + key_buffer_length ) ); +} +#endif /* defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR) */ + #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 64013df73..08182a7f2 100644 --- a/library/psa_crypto_rsa.h +++ b/library/psa_crypto_rsa.h @@ -114,6 +114,29 @@ 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 ); +/** + * \brief Generate an RSA key. + * + * \note The signature of the function is that of a PSA driver generate_key + * entry point. + * + * \param[in] attributes The attributes for the RSA key to generate. + * \param[out] key_buffer Buffer where the key data is to be written. + * \param[in] key_buffer_size Size of \p key_buffer in bytes. + * \param[out] key_buffer_length On success, the number of bytes written in + * \p key_buffer. + * + * \retval #PSA_SUCCESS + * The key was successfully generated. + * \retval #PSA_ERROR_NOT_SUPPORTED + * Key length or type not supported. + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of \p key_buffer is too small. + */ +psa_status_t mbedtls_psa_rsa_generate_key( + const psa_key_attributes_t *attributes, + uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length ); + /* * BEYOND THIS POINT, TEST DRIVER ENTRY POINTS ONLY. */ @@ -131,6 +154,10 @@ psa_status_t mbedtls_transparent_test_driver_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 ); +psa_status_t mbedtls_transparent_test_driver_rsa_generate_key( + const psa_key_attributes_t *attributes, + uint8_t *key, size_t key_size, size_t *key_length ); + #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* PSA_CRYPTO_RSA_H */ diff --git a/tests/scripts/all.sh b/tests/scripts/all.sh index e9d15e4ed..1036a7cfd 100755 --- a/tests/scripts/all.sh +++ b/tests/scripts/all.sh @@ -1371,7 +1371,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 -DMBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR -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 -DMBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR -I../tests/include -O2" LDFLAGS="$ASAN_CFLAGS" msg "test: full + MBEDTLS_PSA_CRYPTO_CONFIG" make test diff --git a/tests/src/drivers/key_management.c b/tests/src/drivers/key_management.c index be6a81492..10a40c37d 100644 --- a/tests/src/drivers/key_management.c +++ b/tests/src/drivers/key_management.c @@ -45,11 +45,6 @@ psa_status_t test_transparent_generate_key( const psa_key_attributes_t *attributes, uint8_t *key, size_t key_size, size_t *key_length ) { -#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR) && \ - !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_PUBLIC_KEY) - (void)attributes; -#endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR && - * !MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_PUBLIC_KEY */ ++test_driver_key_management_hooks.hits; if( test_driver_key_management_hooks.forced_status != PSA_SUCCESS ) @@ -66,66 +61,26 @@ psa_status_t test_transparent_generate_key( } /* Copied from psa_crypto.c */ -#if defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR) || \ - defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_PUBLIC_KEY) +#if defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR) if ( PSA_KEY_TYPE_IS_ECC( psa_get_key_type( attributes ) ) && PSA_KEY_TYPE_IS_KEY_PAIR( psa_get_key_type( attributes ) ) ) { - psa_ecc_family_t curve = PSA_KEY_TYPE_ECC_GET_FAMILY( - psa_get_key_type( attributes ) ); - mbedtls_ecp_group_id grp_id = - mbedtls_ecc_group_of_psa( - curve, - psa_get_key_bits( attributes ), 0 ); - const mbedtls_ecp_curve_info *curve_info = - mbedtls_ecp_curve_info_from_grp_id( grp_id ); - mbedtls_ecp_keypair ecp; - mbedtls_test_rnd_pseudo_info rnd_info; - memset( &rnd_info, 0x5A, sizeof( mbedtls_test_rnd_pseudo_info ) ); - - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - 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 ); - if( curve_info->bit_size != psa_get_key_bits( attributes ) ) - return( PSA_ERROR_INVALID_ARGUMENT ); - mbedtls_ecp_keypair_init( &ecp ); - ret = mbedtls_ecp_gen_key( grp_id, &ecp, - &mbedtls_test_rnd_pseudo_rand, - &rnd_info ); - if( ret != 0 ) - { - mbedtls_ecp_keypair_free( &ecp ); - return( mbedtls_to_psa_error( ret ) ); - } - - /* Make sure to use export representation */ - size_t bytes = PSA_BITS_TO_BYTES( psa_get_key_bits( attributes ) ); - if( key_size < bytes ) - { - mbedtls_ecp_keypair_free( &ecp ); - return( PSA_ERROR_BUFFER_TOO_SMALL ); - } - psa_status_t status = mbedtls_to_psa_error( - mbedtls_mpi_write_binary( &ecp.d, key, bytes ) ); - - if( status == PSA_SUCCESS ) - { - *key_length = bytes; - } - else - { - memset( key, 0, bytes ); - } - - mbedtls_ecp_keypair_free( &ecp ); - return( status ); + return( mbedtls_transparent_test_driver_ecp_generate_key( + attributes, key, key_size, key_length ) ); } else -#endif /* MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR || - * MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_PUBLIC_KEY */ - return( PSA_ERROR_NOT_SUPPORTED ); +#endif /* defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR) */ + +#if defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR) + if ( psa_get_key_type( attributes ) == PSA_KEY_TYPE_RSA_KEY_PAIR ) + return( mbedtls_transparent_test_driver_rsa_generate_key( + attributes, key, key_size, key_length ) ); + else +#endif /* defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR) */ + { + (void)attributes; + return( PSA_ERROR_NOT_SUPPORTED ); + } } psa_status_t test_opaque_generate_key( diff --git a/tests/suites/test_suite_psa_crypto.data b/tests/suites/test_suite_psa_crypto.data index c37bdceda..c981e98a8 100644 --- a/tests/suites/test_suite_psa_crypto.data +++ b/tests/suites/test_suite_psa_crypto.data @@ -2915,7 +2915,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:0 PSA generate key: ECC, Curve25519, good -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 +depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_ECP_DP_CURVE25519_ENABLED 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:0 PSA generate key: RSA, default e diff --git a/tests/suites/test_suite_psa_crypto_driver_wrappers.data b/tests/suites/test_suite_psa_crypto_driver_wrappers.data index 1fd449fb8..14f84c023 100644 --- a/tests/suites/test_suite_psa_crypto_driver_wrappers.data +++ b/tests/suites/test_suite_psa_crypto_driver_wrappers.data @@ -38,6 +38,10 @@ 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: fallback not available +depends_on:!MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR +generate_key:PSA_ERROR_NOT_SUPPORTED:"":PSA_ERROR_NOT_SUPPORTED + generate_key through transparent driver: error generate_key:PSA_ERROR_GENERIC_ERROR:"":PSA_ERROR_GENERIC_ERROR