From 8b96cad20483554ff3d7825d8c94807bdd2ce3ca Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Tue, 23 Jul 2019 17:38:08 +0200 Subject: [PATCH] SE drivers: implement persistent storage Store the persistent data of secure element drivers. This is fully implemented, but not at all tested. --- library/psa_crypto_se.c | 58 ++++++++++++++++--- library/psa_crypto_se.h | 33 +++++++++++ ...st_suite_psa_crypto_se_driver_hal.function | 11 +++- 3 files changed, 92 insertions(+), 10 deletions(-) diff --git a/library/psa_crypto_se.c b/library/psa_crypto_se.c index 7287ac0d7..bae44fa04 100644 --- a/library/psa_crypto_se.c +++ b/library/psa_crypto_se.c @@ -35,6 +35,13 @@ #include "psa_crypto_se.h" +#if defined(MBEDTLS_PSA_ITS_FILE_C) +#include "psa_crypto_its.h" +#else /* Native ITS implementation */ +#include "psa/error.h" +#include "psa/internal_trusted_storage.h" +#endif + #include "mbedtls/platform.h" #if !defined(MBEDTLS_PLATFORM_C) #define mbedtls_calloc calloc @@ -114,20 +121,52 @@ int psa_get_se_driver( psa_key_lifetime_t lifetime, /* Persistent data management */ /****************************************************************/ +static psa_status_t psa_get_se_driver_its_file_uid( + const psa_se_drv_table_entry_t *driver, + psa_storage_uid_t *uid ) +{ + if( driver->lifetime > PSA_MAX_SE_LIFETIME ) + return( PSA_ERROR_NOT_SUPPORTED ); + *uid = PSA_CRYPTO_SE_DRIVER_ITS_UID_BASE + driver->lifetime; + return( PSA_SUCCESS ); +} + psa_status_t psa_load_se_persistent_data( const psa_se_drv_table_entry_t *driver ) { - /*TODO*/ - (void) driver; - return( PSA_SUCCESS ); + psa_status_t status; + psa_storage_uid_t uid; + + status = psa_get_se_driver_its_file_uid( driver, &uid ); + if( status != PSA_SUCCESS ) + return( status ); + + return( psa_its_get( uid, 0, driver->internal.persistent_data_size, + driver->internal.persistent_data ) ); } psa_status_t psa_save_se_persistent_data( const psa_se_drv_table_entry_t *driver ) { - /*TODO*/ - (void) driver; - return( PSA_SUCCESS ); + psa_status_t status; + psa_storage_uid_t uid; + + status = psa_get_se_driver_its_file_uid( driver, &uid ); + if( status != PSA_SUCCESS ) + return( status ); + + return( psa_its_set( uid, driver->internal.persistent_data_size, + driver->internal.persistent_data, + 0 ) ); +} + +psa_status_t psa_destroy_se_persistent_data( psa_key_lifetime_t lifetime ) +{ + psa_storage_uid_t uid; + if( lifetime > PSA_MAX_SE_LIFETIME ) + return( PSA_ERROR_NOT_SUPPORTED ); + uid = PSA_CRYPTO_SE_DRIVER_ITS_UID_BASE + lifetime; + return( psa_its_remove( uid ) ); } psa_status_t psa_find_se_slot_for_key( @@ -201,6 +240,8 @@ psa_status_t psa_register_se_driver( { return( PSA_ERROR_INVALID_ARGUMENT ); } + if( lifetime > PSA_MAX_SE_LIFETIME ) + return( PSA_ERROR_NOT_SUPPORTED ); for( i = 0; i < PSA_MAX_SE_DRIVERS; i++ ) { @@ -227,8 +268,11 @@ psa_status_t psa_register_se_driver( status = PSA_ERROR_INSUFFICIENT_MEMORY; goto error; } + /* Load the driver's persistent data. On first use, the persistent + * data does not exist in storage, and is initialized to + * all-bits-zero by the calloc call just above. */ status = psa_load_se_persistent_data( &driver_table[i] ); - if( status != PSA_SUCCESS ) + if( status != PSA_SUCCESS && status != PSA_ERROR_DOES_NOT_EXIST ) goto error; } driver_table[i].internal.persistent_data_size = diff --git a/library/psa_crypto_se.h b/library/psa_crypto_se.h index f1d7e7c36..08e658cdd 100644 --- a/library/psa_crypto_se.h +++ b/library/psa_crypto_se.h @@ -31,6 +31,30 @@ #include "psa/crypto.h" #include "psa/crypto_se_driver.h" +/** The maximum lifetime value that this implementation supports + * for a secure element. + * + * This is not a characteristic that each PSA implementation has, but a + * limitation of the current implementation due to the constraints imposed + * by storage. See #PSA_CRYPTO_SE_DRIVER_ITS_UID_BASE. + * + * The minimum lifetime value for a secure element is 2, like on any + * PSA implementation (0=volatile and 1=internal-storage are taken). + */ +#define PSA_MAX_SE_LIFETIME 255 + +/** The base of the range of ITS file identifiers for secure element + * driver persistent data. + * + * We use a slice of the implemenation reserved range 0xffff0000..0xffffffff, + * specifically the range 0xfffffe00..0xfffffeff. The length of this range + * drives the value of #PSA_MAX_SE_LIFETIME. + * The identifiers 0xfffffe00 and 0xfffffe01 are actually not used since + * they correspond to #PSA_KEY_LIFETIME_VOLATILE and + * #PSA_KEY_LIFETIME_PERSISTENT which don't have a driver. + */ +#define PSA_CRYPTO_SE_DRIVER_ITS_UID_BASE ( (psa_key_id_t) 0xfffffe00 ) + /** The maximum number of registered secure element driver lifetimes. */ #define PSA_MAX_SE_DRIVERS 4 @@ -138,4 +162,13 @@ psa_status_t psa_load_se_persistent_data( psa_status_t psa_save_se_persistent_data( const psa_se_drv_table_entry_t *driver ); +/** Destroy the persistent data of a secure element driver. + * + * This is currently only used for testing. + * + * \param[in] lifetime The driver lifetime whose persistent data should + * be erased. + */ +psa_status_t psa_destroy_se_persistent_data( psa_key_lifetime_t lifetime ); + #endif /* PSA_CRYPTO_SE_H */ diff --git a/tests/suites/test_suite_psa_crypto_se_driver_hal.function b/tests/suites/test_suite_psa_crypto_se_driver_hal.function index 5a2ebe71b..010f69684 100644 --- a/tests/suites/test_suite_psa_crypto_se_driver_hal.function +++ b/tests/suites/test_suite_psa_crypto_se_driver_hal.function @@ -119,13 +119,18 @@ psa_status_t ram_allocate( psa_drv_se_context_t *context, #define MAX_KEY_ID_FOR_TEST 10 void psa_purge_storage( void ) { - psa_key_id_t i; + psa_key_id_t id; + psa_key_lifetime_t lifetime; /* The tests may have potentially created key ids from 1 to * MAX_KEY_ID_FOR_TEST. In addition, run the destroy function on key id * 0, which file-based storage uses as a temporary file. */ - for( i = 0; i <= MAX_KEY_ID_FOR_TEST; i++ ) - psa_destroy_persistent_key( i ); + for( id = 0; id <= MAX_KEY_ID_FOR_TEST; id++ ) + psa_destroy_persistent_key( id ); + /* Purge the transaction file. */ psa_crypto_stop_transaction( ); + /* Purge driver persistent data. */ + for( lifetime = 0; lifetime < PSA_MAX_SE_LIFETIME; lifetime++ ) + psa_destroy_se_persistent_data( lifetime ); } /* END_HEADER */