Check unused attributes in import and copy

In psa_import_key and psa_copy_key, some information comes from the
key data (input buffer or source key) rather than from the attributes:
key size for import, key size and type and domain parameters for copy.
If an unused attribute is nonzero in the attribute structure, check
that it matches the correct value. This protects against application
errors.
This commit is contained in:
Gilles Peskine 2019-05-03 16:57:15 +02:00
parent 971bd69696
commit 4ce2a9dcbf
2 changed files with 91 additions and 16 deletions

View File

@ -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.

View File

@ -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 );