diff --git a/library/psa_crypto.c b/library/psa_crypto.c index 77acf2edd..c482747b7 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -950,7 +950,20 @@ psa_status_t psa_destroy_key( psa_key_handle_t handle ) #if defined(MBEDTLS_PSA_CRYPTO_SE_C) driver = psa_get_se_driver_entry( slot->lifetime ); if( driver != NULL ) + { + 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 ) + { + /* 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) @@ -961,6 +974,18 @@ psa_status_t psa_destroy_key( psa_key_handle_t handle ) } #endif /* defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) */ +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + if( driver != NULL ) + { + status = psa_crypto_stop_transaction( ); + 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 ); @@ -1382,8 +1407,10 @@ static psa_status_t psa_start_key_creation( slot->type = attributes->type; #if defined(MBEDTLS_PSA_CRYPTO_SE_C) - /* Find a slot number. Don't yet mark it as allocated in case - * the key creation fails or there is a power failure. */ + /* Find a slot number for the new key. Save the slot number in + * persistent storage, but do not yet save the driver's persistent + * state, so that if the power fails during the key creation process, + * 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, @@ -1391,6 +1418,13 @@ static psa_status_t psa_start_key_creation( 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 ) + return( status ); #endif /* MBEDTLS_PSA_CRYPTO_SE_C */ return( status ); @@ -1459,6 +1493,9 @@ static psa_status_t psa_finish_key_creation( 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 */ @@ -1490,6 +1527,11 @@ static void psa_fail_key_creation( psa_key_slot_t *slot, * 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 ); @@ -5674,6 +5716,19 @@ psa_status_t psa_crypto_init( void ) if( status != PSA_SUCCESS ) goto exit; +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + status = psa_crypto_load_transaction( ); + if( status == PSA_SUCCESS ) + { + /*TOnogrepDO: complete or abort the transaction*/ + } + else if( status == PSA_ERROR_DOES_NOT_EXIST ) + { + /* There's no transaction to complete. It's all good. */ + status = PSA_SUCCESS; + } +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + /* All done. */ global_data.initialized = 1; diff --git a/library/psa_crypto_storage.h b/library/psa_crypto_storage.h index 16f5d5cac..2e4079f7d 100644 --- a/library/psa_crypto_storage.h +++ b/library/psa_crypto_storage.h @@ -29,15 +29,9 @@ extern "C" { #endif -/* Include the Mbed TLS configuration file, the way Mbed TLS does it - * in each of its header files. */ -#if defined(MBEDTLS_CONFIG_FILE) -#include MBEDTLS_CONFIG_FILE -#else -#include "mbedtls/config.h" -#endif - #include "psa/crypto.h" +#include "psa/crypto_se_driver.h" + #include #include @@ -223,6 +217,22 @@ typedef uint16_t psa_crypto_transaction_type_t; */ #define PSA_CRYPTO_TRANSACTION_NONE ( (psa_crypto_transaction_type_t) 0x0000 ) +/** A key creation transaction. + * + * This is only used for keys in an external cryptoprocessor (secure element). + * Keys in RAM or in internal storage are created atomically in storage + * (simple file creation), so they do not need a transaction mechanism. + */ +#define PSA_CRYPTO_TRANSACTION_CREATE_KEY ( (psa_crypto_transaction_type_t) 0x0001 ) + +/** A key destruction transaction. + * + * This is only used for keys in an external cryptoprocessor (secure element). + * Keys in RAM or in internal storage are destroyed atomically in storage + * (simple file deletion), so they do not need a transaction mechanism. + */ +#define PSA_CRYPTO_TRANSACTION_DESTROY_KEY ( (psa_crypto_transaction_type_t) 0x0002 ) + /** Transaction data. * * This type is designed to be serialized by writing the memory representation @@ -266,7 +276,21 @@ typedef union struct psa_crypto_transaction_unknown_s { psa_crypto_transaction_type_t type; + uint16_t unused1; + uint32_t unused2; + uint64_t unused3; + uint64_t unused4; } unknown; + /* ::type is #PSA_CRYPTO_TRANSACTION_CREATE_KEY or + * #PSA_CRYPTO_TRANSACTION_DESTROY_KEY. */ + struct psa_crypto_transaction_key_s + { + psa_crypto_transaction_type_t type; + uint16_t unused1; + psa_key_lifetime_t lifetime; + psa_key_slot_number_t slot; + psa_key_id_t id; + } key; } psa_crypto_transaction_t; /** The single active transaction.