diff --git a/include/psa/crypto.h b/include/psa/crypto.h index fff144cabd..af3353c010 100644 --- a/include/psa/crypto.h +++ b/include/psa/crypto.h @@ -583,9 +583,10 @@ psa_status_t psa_close_key(psa_key_handle_t handle); * according to a different format. * * \param[in] attributes The attributes for the new key. - * The key size field in \p attributes is - * ignored; the actual key size is determined - * from the \p data buffer. + * The key size is always determined from the + * \p data buffer. + * If the key size in \p attributes is nonzero, + * it must be equal to the size from \p data. * \param[out] handle On success, a handle to the newly created key. * \c 0 on failure. * \param[in] data Buffer containing the key data. The content of this @@ -612,8 +613,12 @@ psa_status_t psa_close_key(psa_key_handle_t handle); * The key type or key size is not supported, either by the * implementation in general or in this particular persistent location. * \retval #PSA_ERROR_INVALID_ARGUMENT - * The key attributes, as a whole, are invalid, - * or the key data is not correctly formatted. + * The key attributes, as a whole, are invalid. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The key data is not correctly formatted. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The size in \p attributes is nonzero and does not match the size + * of the key data. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY * \retval #PSA_ERROR_INSUFFICIENT_STORAGE * \retval #PSA_ERROR_COMMUNICATION_FAILURE @@ -859,9 +864,12 @@ psa_status_t psa_export_public_key(psa_key_handle_t handle, * occupied slot. * \param[in] attributes The attributes for the new key. * They are used as follows: - * - The key type, key size and domain parameters - * are ignored. This information is copied - * from the source key. + * - The key type and size may be 0. If either is + * nonzero, it must match the corresponding + * attribute of the source key. + * - If \p attributes contains domain parameters, + * they must match the domain parameters of + * the source key. * - The key location (the lifetime and, for * persistent keys, the key identifier) is * used directly. @@ -884,6 +892,9 @@ psa_status_t psa_export_public_key(psa_key_handle_t handle, * \retval #PSA_ERROR_INVALID_ARGUMENT * The policy constraints on the source and specified in * \p attributes are incompatible. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p attributes specifies a key type, domain parameters or key size + * which does not match the attributes of the source key. * \retval #PSA_ERROR_NOT_PERMITTED * The source key is not exportable and its lifetime does not * allow copying it to the target's lifetime. diff --git a/library/psa_crypto.c b/library/psa_crypto.c index 6e01997a48..c8b1931e87 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -1480,6 +1480,58 @@ static void psa_fail_key_creation( psa_key_slot_t *slot ) psa_wipe_key_slot( slot ); } +static psa_status_t psa_check_key_slot_attributes( + const psa_key_slot_t *slot, + const psa_key_attributes_t *attributes ) +{ + if( attributes->type != 0 ) + { + if( attributes->type != slot->type ) + return( PSA_ERROR_INVALID_ARGUMENT ); + } + + if( attributes->domain_parameters_size != 0 ) + { +#if defined(MBEDTLS_RSA_C) + if( PSA_KEY_TYPE_IS_RSA( slot->type ) ) + { + mbedtls_mpi actual, required; + int ret; + mbedtls_mpi_init( &actual ); + mbedtls_mpi_init( &required ); + ret = mbedtls_rsa_export( slot->data.rsa, + NULL, NULL, NULL, NULL, &actual ); + if( ret != 0 ) + goto rsa_exit; + ret = mbedtls_mpi_read_binary( &required, + attributes->domain_parameters, + attributes->domain_parameters_size ); + if( ret != 0 ) + goto rsa_exit; + if( mbedtls_mpi_cmp_mpi( &actual, &required ) != 0 ) + ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA; + rsa_exit: + mbedtls_mpi_free( &actual ); + mbedtls_mpi_free( &required ); + if( ret != 0) + return( mbedtls_to_psa_error( ret ) ); + } + else +#endif + { + return( PSA_ERROR_INVALID_ARGUMENT ); + } + } + + if( attributes->bits != 0 ) + { + if( attributes->bits != psa_get_key_slot_bits( slot ) ) + return( PSA_ERROR_INVALID_ARGUMENT ); + } + + return( PSA_SUCCESS ); +} + psa_status_t psa_import_key( const psa_key_attributes_t *attributes, psa_key_handle_t *handle, const uint8_t *data, @@ -1487,13 +1539,20 @@ psa_status_t psa_import_key( const psa_key_attributes_t *attributes, { psa_status_t status; psa_key_slot_t *slot = NULL; + status = psa_start_key_creation( attributes, handle, &slot ); - if( status == PSA_SUCCESS ) - { - status = psa_import_key_into_slot( slot, data, data_length ); - } - if( status == PSA_SUCCESS ) - status = psa_finish_key_creation( slot ); + if( status != PSA_SUCCESS ) + goto exit; + + status = psa_import_key_into_slot( slot, data, data_length ); + if( status != PSA_SUCCESS ) + goto exit; + status = psa_check_key_slot_attributes( slot, attributes ); + if( status != PSA_SUCCESS ) + goto exit; + + status = psa_finish_key_creation( slot ); +exit: if( status != PSA_SUCCESS ) { psa_fail_key_creation( slot ); @@ -1575,6 +1634,10 @@ psa_status_t psa_copy_key( psa_key_handle_t source_handle, if( status != PSA_SUCCESS ) goto exit; + status = psa_check_key_slot_attributes( source_slot, specified_attributes ); + if( status != PSA_SUCCESS ) + goto exit; + status = psa_restrict_key_policy( &actual_attributes.policy, &source_slot->policy ); if( status != PSA_SUCCESS ) @@ -1586,10 +1649,11 @@ psa_status_t psa_copy_key( psa_key_handle_t source_handle, goto exit; status = psa_copy_key_material( source_slot, target_slot ); + if( status != PSA_SUCCESS ) + goto exit; + status = psa_finish_key_creation( target_slot ); exit: - if( status == PSA_SUCCESS ) - status = psa_finish_key_creation( target_slot ); if( status != PSA_SUCCESS ) { psa_fail_key_creation( target_slot );