1
0
mirror of https://github.com/Mbed-TLS/mbedtls.git synced 2025-07-29 11:41:15 +03:00

Merge pull request #157 from gilles-peskine-arm/psa-se_driver-create_key

Secure element key creation foundation
This commit is contained in:
Gilles Peskine
2019-07-26 14:39:55 +02:00
committed by GitHub
20 changed files with 2194 additions and 360 deletions

View File

@ -363,6 +363,13 @@ static psa_status_t mbedtls_to_psa_error( int ret )
/* Key management */
/****************************************************************/
#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
static inline int psa_key_slot_is_external( const psa_key_slot_t *slot )
{
return( psa_key_lifetime_is_external( slot->lifetime ) );
}
#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
#if defined(MBEDTLS_ECP_C)
static psa_ecc_curve_t mbedtls_ecc_group_to_psa( mbedtls_ecp_group_id grpid )
{
@ -864,9 +871,46 @@ static psa_status_t psa_get_key_from_slot( psa_key_handle_t handle,
return( PSA_SUCCESS );
}
/** Retrieve a slot which must contain a transparent key.
*
* A transparent key is a key for which the key material is directly
* available, as opposed to a key in a secure element.
*
* This is a temporary function to use instead of psa_get_key_from_slot()
* until secure element support is fully implemented.
*/
#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
static psa_status_t psa_get_transparent_key( psa_key_handle_t handle,
psa_key_slot_t **p_slot,
psa_key_usage_t usage,
psa_algorithm_t alg )
{
psa_status_t status = psa_get_key_from_slot( handle, p_slot, usage, alg );
if( status != PSA_SUCCESS )
return( status );
if( psa_key_slot_is_external( *p_slot ) )
{
*p_slot = NULL;
return( PSA_ERROR_NOT_SUPPORTED );
}
return( PSA_SUCCESS );
}
#else /* MBEDTLS_PSA_CRYPTO_SE_C */
/* With no secure element support, all keys are transparent. */
#define psa_get_transparent_key( handle, p_slot, usage, alg ) \
psa_get_key_from_slot( handle, p_slot, usage, alg )
#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
/** 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_key_slot_is_external( slot ) )
{
/* No key material to clean. */
}
else
#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
if( slot->type == PSA_KEY_TYPE_NONE )
{
/* No key material to clean. */
@ -925,10 +969,39 @@ psa_status_t psa_destroy_key( psa_key_handle_t handle )
psa_key_slot_t *slot;
psa_status_t status = PSA_SUCCESS;
psa_status_t storage_status = PSA_SUCCESS;
#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
psa_se_drv_table_entry_t *driver;
#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
status = psa_get_key_slot( handle, &slot );
if( status != PSA_SUCCESS )
return( status );
#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
driver = psa_get_se_driver_entry( slot->lifetime );
if( driver != NULL )
{
/* For a key in a secure element, we need to do three things:
* remove the key file in internal storage, destroy the
* key inside the secure element, and update the driver's
* persistent data. Start a transaction that will encompass these
* three actions. */
psa_crypto_prepare_transaction( PSA_CRYPTO_TRANSACTION_DESTROY_KEY );
psa_crypto_transaction.key.lifetime = slot->lifetime;
psa_crypto_transaction.key.slot = slot->data.se.slot_number;
psa_crypto_transaction.key.id = slot->persistent_storage_id;
status = psa_crypto_save_transaction( );
if( status != PSA_SUCCESS )
{
(void) psa_crypto_stop_transaction( );
/* TOnogrepDO: destroy what can be destroyed anyway */
return( status );
}
status = psa_destroy_se_key( driver, slot->data.se.slot_number );
}
#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C)
if( slot->lifetime == PSA_KEY_LIFETIME_PERSISTENT )
{
@ -936,6 +1009,23 @@ psa_status_t psa_destroy_key( psa_key_handle_t handle )
psa_destroy_persistent_key( slot->persistent_storage_id );
}
#endif /* defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) */
#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
if( driver != NULL )
{
psa_status_t status2;
status = psa_save_se_persistent_data( driver );
status2 = psa_crypto_stop_transaction( );
if( status == PSA_SUCCESS )
status = status2;
if( status != PSA_SUCCESS )
{
/* TOnogrepDO: destroy what can be destroyed anyway */
return( status );
}
}
#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
status = psa_wipe_key_slot( slot );
if( status != PSA_SUCCESS )
return( status );
@ -1050,6 +1140,22 @@ exit:
}
#endif /* MBEDTLS_RSA_C */
/** Retrieve the readily-accessible attributes of a key in a slot.
*
* This function does not compute attributes that are not directly
* stored in the slot, such as the bit size of a transparent key.
*/
static void psa_get_key_slot_attributes( psa_key_slot_t *slot,
psa_key_attributes_t *attributes )
{
attributes->id = slot->persistent_storage_id;
attributes->lifetime = slot->lifetime;
attributes->policy = slot->policy;
attributes->type = slot->type;
}
/** Retrieve all the publicly-accessible attributes of a key.
*/
psa_status_t psa_get_key_attributes( psa_key_handle_t handle,
psa_key_attributes_t *attributes )
{
@ -1058,14 +1164,11 @@ psa_status_t psa_get_key_attributes( psa_key_handle_t handle,
psa_reset_key_attributes( attributes );
status = psa_get_key_slot( handle, &slot );
status = psa_get_transparent_key( handle, &slot, 0, 0 );
if( status != PSA_SUCCESS )
return( status );
attributes->id = slot->persistent_storage_id;
attributes->lifetime = slot->lifetime;
attributes->policy = slot->policy;
attributes->type = slot->type;
psa_get_key_slot_attributes( slot, attributes );
attributes->bits = psa_get_key_slot_bits( slot );
switch( slot->type )
@ -1108,11 +1211,33 @@ static psa_status_t psa_internal_export_key( const psa_key_slot_t *slot,
size_t *data_length,
int export_public_key )
{
#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 */
*data_length = 0;
if( export_public_key && ! PSA_KEY_TYPE_IS_ASYMMETRIC( slot->type ) )
return( PSA_ERROR_INVALID_ARGUMENT );
#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
if( psa_get_se_driver( slot->lifetime, &drv, &drv_context ) )
{
psa_drv_se_export_key_t method;
if( drv->key_management == 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,
slot->data.se.slot_number,
data, data_size, data_length ) );
}
#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
if( key_type_is_raw_bytes( slot->type ) )
{
if( slot->data.raw.bytes > data_size )
@ -1291,9 +1416,11 @@ static psa_status_t psa_set_key_policy_internal(
* In case of failure at any step, stop the sequence and call
* psa_fail_key_creation().
*
* \param attributes Key attributes for the new key.
* \param handle On success, a handle for the allocated slot.
* \param p_slot On success, a pointer to the prepared slot.
* \param[in] attributes Key attributes for the new key.
* \param[out] handle On success, a handle for the allocated slot.
* \param[out] p_slot On success, a pointer to the prepared slot.
* \param[out] p_drv On any return, the driver for the key, if any.
* NULL for a transparent key.
*
* \retval #PSA_SUCCESS
* The key slot is ready to receive key material.
@ -1303,11 +1430,14 @@ static psa_status_t psa_set_key_policy_internal(
static psa_status_t psa_start_key_creation(
const psa_key_attributes_t *attributes,
psa_key_handle_t *handle,
psa_key_slot_t **p_slot )
psa_key_slot_t **p_slot,
psa_se_drv_table_entry_t **p_drv )
{
psa_status_t status;
psa_key_slot_t *slot;
*p_drv = NULL;
status = psa_internal_allocate_key_slot( handle, p_slot );
if( status != PSA_SUCCESS )
return( status );
@ -1317,16 +1447,51 @@ static psa_status_t psa_start_key_creation(
if( status != PSA_SUCCESS )
return( status );
slot->lifetime = attributes->lifetime;
if( attributes->lifetime != PSA_KEY_LIFETIME_VOLATILE )
{
status = psa_validate_persistent_key_parameters( attributes->lifetime,
attributes->id, 1 );
attributes->id,
p_drv, 1 );
if( status != PSA_SUCCESS )
return( status );
slot->persistent_storage_id = attributes->id;
}
slot->type = attributes->type;
#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
/* For a key in a secure element, we need to do three things:
* create the key file in internal storage, create the
* key inside the secure element, and update the driver's
* persistent data. Start a transaction that will encompass these
* three actions. */
/* The first thing to do is to find a slot number for the new key.
* We save the slot number in persistent storage as part of the
* transaction data. It will be needed to recover if the power
* fails during the key creation process, to clean up on the secure
* element side after restarting. Obtaining a slot number from the
* secure element driver updates its persistent state, but we do not yet
* save the driver's persistent state, so that if the power fails,
* we can roll back to a state where the key doesn't exist. */
if( *p_drv != NULL )
{
status = psa_find_se_slot_for_key( attributes, *p_drv,
&slot->data.se.slot_number );
if( status != PSA_SUCCESS )
return( status );
psa_crypto_prepare_transaction( PSA_CRYPTO_TRANSACTION_CREATE_KEY );
psa_crypto_transaction.key.lifetime = slot->lifetime;
psa_crypto_transaction.key.slot = slot->data.se.slot_number;
psa_crypto_transaction.key.id = slot->persistent_storage_id;
status = psa_crypto_save_transaction( );
if( status != PSA_SUCCESS )
{
(void) psa_crypto_stop_transaction( );
return( status );
}
}
#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
return( status );
}
@ -1338,47 +1503,82 @@ static psa_status_t psa_start_key_creation(
* See the documentation of psa_start_key_creation() for the intended use
* of this function.
*
* \param slot Pointer to the slot with key material.
* \param[in,out] slot Pointer to the slot with key material.
* \param[in] driver The secure element driver for the key,
* or NULL for a transparent key.
*
* \retval #PSA_SUCCESS
* The key was successfully created. The handle is now valid.
* \return If this function fails, the key slot is an invalid state.
* You must call psa_fail_key_creation() to wipe and free the slot.
*/
static psa_status_t psa_finish_key_creation( psa_key_slot_t *slot )
static psa_status_t psa_finish_key_creation(
psa_key_slot_t *slot,
psa_se_drv_table_entry_t *driver )
{
psa_status_t status = PSA_SUCCESS;
(void) slot;
(void) driver;
#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C)
if( slot->lifetime == PSA_KEY_LIFETIME_PERSISTENT )
if( slot->lifetime != PSA_KEY_LIFETIME_VOLATILE )
{
uint8_t *buffer = NULL;
size_t buffer_size = 0;
size_t length;
size_t length = 0;
buffer_size = PSA_KEY_EXPORT_MAX_SIZE( slot->type,
psa_get_key_slot_bits( slot ) );
buffer = mbedtls_calloc( 1, buffer_size );
if( buffer == NULL && buffer_size != 0 )
return( PSA_ERROR_INSUFFICIENT_MEMORY );
status = psa_internal_export_key( slot,
buffer, buffer_size, &length,
0 );
#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
if( driver != NULL )
{
buffer = (uint8_t*) &slot->data.se.slot_number;
length = sizeof( slot->data.se.slot_number );
}
else
#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
{
buffer_size = PSA_KEY_EXPORT_MAX_SIZE( slot->type,
psa_get_key_slot_bits( slot ) );
buffer = mbedtls_calloc( 1, buffer_size );
if( buffer == NULL && buffer_size != 0 )
return( PSA_ERROR_INSUFFICIENT_MEMORY );
status = psa_internal_export_key( slot,
buffer, buffer_size, &length,
0 );
}
if( status == PSA_SUCCESS )
{
status = psa_save_persistent_key( slot->persistent_storage_id,
slot->type, &slot->policy,
buffer, length );
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_get_key_slot_attributes( slot, &attributes );
status = psa_save_persistent_key( &attributes, buffer, length );
}
if( buffer_size != 0 )
mbedtls_platform_zeroize( buffer, buffer_size );
mbedtls_free( buffer );
#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
if( driver == NULL )
#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
{
if( buffer_size != 0 )
mbedtls_platform_zeroize( buffer, buffer_size );
mbedtls_free( buffer );
}
}
#endif /* defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) */
#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
if( driver != NULL )
{
status = psa_save_se_persistent_data( driver );
if( status != PSA_SUCCESS )
{
psa_destroy_persistent_key( slot->persistent_storage_id );
return( status );
}
status = psa_crypto_stop_transaction( );
if( status != PSA_SUCCESS )
return( status );
}
#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
return( status );
}
@ -1390,12 +1590,30 @@ static psa_status_t psa_finish_key_creation( psa_key_slot_t *slot )
* See the documentation of psa_start_key_creation() for the intended use
* of this function.
*
* \param slot Pointer to the slot with key material.
* \param[in,out] slot Pointer to the slot with key material.
* \param[in] driver The secure element driver for the key,
* or NULL for a transparent key.
*/
static void psa_fail_key_creation( psa_key_slot_t *slot )
static void psa_fail_key_creation( psa_key_slot_t *slot,
psa_se_drv_table_entry_t *driver )
{
(void) driver;
if( slot == NULL )
return;
#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
/* TOnogrepDO: If the key has already been created in the secure
* element, and the failure happened later (when saving metadata
* to internal storage), we need to destroy the key in the secure
* element. */
/* Abort the ongoing transaction if any. We already did what it
* takes to undo any partial creation. All that's left is to update
* the transaction data itself. */
(void) psa_crypto_stop_transaction( );
#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
psa_wipe_key_slot( slot );
}
@ -1458,23 +1676,45 @@ 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;
status = psa_start_key_creation( attributes, handle, &slot );
status = psa_start_key_creation( attributes, handle, &slot, &driver );
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;
#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
if( driver != NULL )
{
const psa_drv_se_t *drv = psa_get_se_driver_methods( driver );
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 ),
slot->data.se.slot_number,
slot->lifetime, slot->type, slot->policy.alg, slot->policy.usage,
data, data_length );
/* TOnogrepDO: psa_check_key_slot_attributes? */
}
else
#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
{
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 );
status = psa_finish_key_creation( slot, driver );
exit:
if( status != PSA_SUCCESS )
{
psa_fail_key_creation( slot );
psa_fail_key_creation( slot, driver );
*handle = 0;
}
return( status );
@ -1514,9 +1754,10 @@ psa_status_t psa_copy_key( psa_key_handle_t source_handle,
psa_key_slot_t *source_slot = NULL;
psa_key_slot_t *target_slot = NULL;
psa_key_attributes_t actual_attributes = *specified_attributes;
psa_se_drv_table_entry_t *driver = NULL;
status = psa_get_key_from_slot( source_handle, &source_slot,
PSA_KEY_USAGE_COPY, 0 );
status = psa_get_transparent_key( source_handle, &source_slot,
PSA_KEY_USAGE_COPY, 0 );
if( status != PSA_SUCCESS )
goto exit;
@ -1530,19 +1771,28 @@ psa_status_t psa_copy_key( psa_key_handle_t source_handle,
goto exit;
status = psa_start_key_creation( &actual_attributes,
target_handle, &target_slot );
target_handle, &target_slot, &driver );
if( status != PSA_SUCCESS )
goto exit;
#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
if( driver != NULL )
{
/* Copying to a secure element is not implemented yet. */
status = PSA_ERROR_NOT_SUPPORTED;
goto exit;
}
#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
status = psa_copy_key_material( source_slot, target_slot );
if( status != PSA_SUCCESS )
goto exit;
status = psa_finish_key_creation( target_slot );
status = psa_finish_key_creation( target_slot, driver );
exit:
if( status != PSA_SUCCESS )
{
psa_fail_key_creation( target_slot );
psa_fail_key_creation( target_slot, driver );
*target_handle = 0;
}
return( status );
@ -2296,7 +2546,7 @@ static psa_status_t psa_mac_setup( psa_mac_operation_t *operation,
if( is_sign )
operation->is_sign = 1;
status = psa_get_key_from_slot( handle, &slot, usage, alg );
status = psa_get_transparent_key( handle, &slot, usage, alg );
if( status != PSA_SUCCESS )
goto exit;
key_bits = psa_get_key_slot_bits( slot );
@ -2875,7 +3125,7 @@ psa_status_t psa_asymmetric_sign( psa_key_handle_t handle,
*signature_length = signature_size;
status = psa_get_key_from_slot( handle, &slot, PSA_KEY_USAGE_SIGN, alg );
status = psa_get_transparent_key( handle, &slot, PSA_KEY_USAGE_SIGN, alg );
if( status != PSA_SUCCESS )
goto exit;
if( ! PSA_KEY_TYPE_IS_KEY_PAIR( slot->type ) )
@ -2948,7 +3198,7 @@ psa_status_t psa_asymmetric_verify( psa_key_handle_t handle,
psa_key_slot_t *slot;
psa_status_t status;
status = psa_get_key_from_slot( handle, &slot, PSA_KEY_USAGE_VERIFY, alg );
status = psa_get_transparent_key( handle, &slot, PSA_KEY_USAGE_VERIFY, alg );
if( status != PSA_SUCCESS )
return( status );
@ -3018,7 +3268,7 @@ psa_status_t psa_asymmetric_encrypt( psa_key_handle_t handle,
if( ! PSA_ALG_IS_RSA_OAEP( alg ) && salt_length != 0 )
return( PSA_ERROR_INVALID_ARGUMENT );
status = psa_get_key_from_slot( handle, &slot, PSA_KEY_USAGE_ENCRYPT, alg );
status = psa_get_transparent_key( handle, &slot, PSA_KEY_USAGE_ENCRYPT, alg );
if( status != PSA_SUCCESS )
return( status );
if( ! ( PSA_KEY_TYPE_IS_PUBLIC_KEY( slot->type ) ||
@ -3098,7 +3348,7 @@ psa_status_t psa_asymmetric_decrypt( psa_key_handle_t handle,
if( ! PSA_ALG_IS_RSA_OAEP( alg ) && salt_length != 0 )
return( PSA_ERROR_INVALID_ARGUMENT );
status = psa_get_key_from_slot( handle, &slot, PSA_KEY_USAGE_DECRYPT, alg );
status = psa_get_transparent_key( handle, &slot, PSA_KEY_USAGE_DECRYPT, alg );
if( status != PSA_SUCCESS )
return( status );
if( ! PSA_KEY_TYPE_IS_KEY_PAIR( slot->type ) )
@ -3207,7 +3457,7 @@ static psa_status_t psa_cipher_setup( psa_cipher_operation_t *operation,
if( status != PSA_SUCCESS )
return( status );
status = psa_get_key_from_slot( handle, &slot, usage, alg);
status = psa_get_transparent_key( handle, &slot, usage, alg);
if( status != PSA_SUCCESS )
goto exit;
key_bits = psa_get_key_slot_bits( slot );
@ -3544,7 +3794,7 @@ static psa_status_t psa_aead_setup( aead_operation_t *operation,
size_t key_bits;
mbedtls_cipher_id_t cipher_id;
status = psa_get_key_from_slot( handle, &operation->slot, usage, alg );
status = psa_get_transparent_key( handle, &operation->slot, usage, alg );
if( status != PSA_SUCCESS )
return( status );
@ -4437,7 +4687,15 @@ psa_status_t psa_key_derivation_output_key( const psa_key_attributes_t *attribut
{
psa_status_t status;
psa_key_slot_t *slot = NULL;
status = psa_start_key_creation( attributes, handle, &slot );
psa_se_drv_table_entry_t *driver = NULL;
status = psa_start_key_creation( attributes, handle, &slot, &driver );
#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
if( driver != NULL )
{
/* Deriving a key in a secure element is not implemented yet. */
status = PSA_ERROR_NOT_SUPPORTED;
}
#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
if( status == PSA_SUCCESS )
{
status = psa_generate_derived_key_internal( slot,
@ -4445,10 +4703,10 @@ psa_status_t psa_key_derivation_output_key( const psa_key_attributes_t *attribut
operation );
}
if( status == PSA_SUCCESS )
status = psa_finish_key_creation( slot );
status = psa_finish_key_creation( slot, driver );
if( status != PSA_SUCCESS )
{
psa_fail_key_creation( slot );
psa_fail_key_creation( slot, driver );
*handle = 0;
}
return( status );
@ -4718,7 +4976,7 @@ psa_status_t psa_key_derivation( psa_key_derivation_operation_t *operation,
if( ! PSA_ALG_IS_KEY_DERIVATION( alg ) )
return( PSA_ERROR_INVALID_ARGUMENT );
status = psa_get_key_from_slot( handle, &slot, PSA_KEY_USAGE_DERIVE, alg );
status = psa_get_transparent_key( handle, &slot, PSA_KEY_USAGE_DERIVE, alg );
if( status != PSA_SUCCESS )
return( status );
@ -5092,9 +5350,9 @@ psa_status_t psa_key_derivation_input_key(
{
psa_key_slot_t *slot;
psa_status_t status;
status = psa_get_key_from_slot( handle, &slot,
PSA_KEY_USAGE_DERIVE,
operation->alg );
status = psa_get_transparent_key( handle, &slot,
PSA_KEY_USAGE_DERIVE,
operation->alg );
if( status != PSA_SUCCESS )
return( status );
if( slot->type != PSA_KEY_TYPE_DERIVE )
@ -5241,8 +5499,8 @@ psa_status_t psa_key_derivation_key_agreement( psa_key_derivation_operation_t *o
psa_status_t status;
if( ! PSA_ALG_IS_KEY_AGREEMENT( operation->alg ) )
return( PSA_ERROR_INVALID_ARGUMENT );
status = psa_get_key_from_slot( private_key, &slot,
PSA_KEY_USAGE_DERIVE, operation->alg );
status = psa_get_transparent_key( private_key, &slot,
PSA_KEY_USAGE_DERIVE, operation->alg );
if( status != PSA_SUCCESS )
return( status );
status = psa_key_agreement_internal( operation, step,
@ -5269,8 +5527,8 @@ psa_status_t psa_raw_key_agreement( psa_algorithm_t alg,
status = PSA_ERROR_INVALID_ARGUMENT;
goto exit;
}
status = psa_get_key_from_slot( private_key, &slot,
PSA_KEY_USAGE_DERIVE, alg );
status = psa_get_transparent_key( private_key, &slot,
PSA_KEY_USAGE_DERIVE, alg );
if( status != PSA_SUCCESS )
goto exit;
@ -5467,7 +5725,15 @@ psa_status_t psa_generate_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 );
psa_se_drv_table_entry_t *driver = NULL;
status = psa_start_key_creation( attributes, handle, &slot, &driver );
#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
if( driver != NULL )
{
/* Generating a key in a secure element is not implemented yet. */
status = PSA_ERROR_NOT_SUPPORTED;
}
#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
if( status == PSA_SUCCESS )
{
status = psa_generate_key_internal(
@ -5475,10 +5741,10 @@ psa_status_t psa_generate_key( const psa_key_attributes_t *attributes,
attributes->domain_parameters, attributes->domain_parameters_size );
}
if( status == PSA_SUCCESS )
status = psa_finish_key_creation( slot );
status = psa_finish_key_creation( slot, driver );
if( status != PSA_SUCCESS )
{
psa_fail_key_creation( slot );
psa_fail_key_creation( slot, driver );
*handle = 0;
}
return( status );
@ -5520,6 +5786,30 @@ void mbedtls_psa_crypto_free( void )
#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
}
#if defined(PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS)
/** Recover a transaction that was interrupted by a power failure.
*
* This function is called during initialization, before psa_crypto_init()
* returns. If this function returns a failure status, the initialization
* fails.
*/
static psa_status_t psa_crypto_recover_transaction(
const psa_crypto_transaction_t *transaction )
{
switch( transaction->unknown.type )
{
case PSA_CRYPTO_TRANSACTION_CREATE_KEY:
case PSA_CRYPTO_TRANSACTION_DESTROY_KEY:
/* TOnogrepDO - fall through to the failure case until this
* is implemented */
default:
/* We found an unsupported transaction in the storage.
* We don't know what state the storage is in. Give up. */
return( PSA_ERROR_STORAGE_FAILURE );
}
}
#endif /* PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS */
psa_status_t psa_crypto_init( void )
{
psa_status_t status;
@ -5553,6 +5843,22 @@ psa_status_t psa_crypto_init( void )
if( status != PSA_SUCCESS )
goto exit;
#if defined(PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS)
status = psa_crypto_load_transaction( );
if( status == PSA_SUCCESS )
{
status = psa_crypto_recover_transaction( &psa_crypto_transaction );
if( status != PSA_SUCCESS )
goto exit;
status = psa_crypto_stop_transaction( );
}
else if( status == PSA_ERROR_DOES_NOT_EXIST )
{
/* There's no transaction to complete. It's all good. */
status = PSA_SUCCESS;
}
#endif /* PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS */
/* All done. */
global_data.initialized = 1;