mbedtls/tests/suites/test_suite_psa_crypto_se_driver_hal.function
Gilles Peskine 8b96cad204 SE drivers: implement persistent storage
Store the persistent data of secure element drivers.

This is fully implemented, but not at all tested.
2019-07-23 17:38:08 +02:00

272 lines
8.9 KiB
Text

/* BEGIN_HEADER */
#include "psa_crypto_helpers.h"
#include "psa/crypto_se_driver.h"
#include "psa_crypto_se.h"
#include "psa_crypto_storage.h"
/** The minimum valid lifetime value for a secure element driver. */
#define MIN_DRIVER_LIFETIME 2
/** The driver detected a condition that shouldn't happen.
* This is probably a bug in the library. */
#define PSA_ERROR_DETECTED_BY_DRIVER ((psa_status_t)( -500 ))
/** Like #TEST_ASSERT for use in a driver method.
*
* Use this macro to assert on guarantees provided by the core.
*/
#define DRIVER_ASSERT( TEST ) \
do { \
if( ! (TEST) ) \
{ \
test_fail( #TEST, __LINE__, __FILE__ ); \
return( PSA_ERROR_DETECTED_BY_DRIVER ); \
} \
} while( 0 )
#define RAM_MAX_KEY_SIZE 64
typedef struct
{
psa_key_lifetime_t lifetime;
psa_key_type_t type;
size_t bits;
uint8_t content[RAM_MAX_KEY_SIZE];
} ram_slot_t;
static ram_slot_t ram_slots[16];
/* A type with at least ARRAY_LENGTH(ram_slots) bits, containing a
* bit vector indicating which slots are in use. */
typedef uint16_t ram_slot_usage_t;
static uint8_t ram_min_slot = 0;
static void ram_slots_reset( void )
{
memset( ram_slots, 0, sizeof( ram_slots ) );
ram_min_slot = 0;
}
static psa_status_t ram_import( psa_drv_se_context_t *context,
psa_key_slot_number_t slot_number,
psa_key_lifetime_t lifetime,
psa_key_type_t type,
psa_algorithm_t algorithm,
psa_key_usage_t usage,
const uint8_t *p_data,
size_t data_length )
{
(void) context;
DRIVER_ASSERT( slot_number < ARRAY_LENGTH( ram_slots ) );
if( data_length > sizeof( ram_slots[slot_number].content ) )
return( PSA_ERROR_INSUFFICIENT_STORAGE );
ram_slots[slot_number].lifetime = lifetime;
ram_slots[slot_number].type = type;
ram_slots[slot_number].bits = PSA_BYTES_TO_BITS( data_length );
(void) algorithm;
(void) usage;
memcpy( ram_slots[slot_number].content, p_data, data_length );
return( PSA_SUCCESS );
}
psa_status_t ram_export( psa_drv_se_context_t *context,
psa_key_slot_number_t slot_number,
uint8_t *p_data,
size_t data_size,
size_t *p_data_length )
{
size_t actual_size;
(void) context;
DRIVER_ASSERT( slot_number < ARRAY_LENGTH( ram_slots ) );
actual_size = PSA_BITS_TO_BYTES( ram_slots[slot_number].bits );
if( actual_size > data_size )
return( PSA_ERROR_BUFFER_TOO_SMALL );
*p_data_length = actual_size;
memcpy( p_data, ram_slots[slot_number].content, actual_size );
return( PSA_SUCCESS );
}
psa_status_t ram_destroy( psa_drv_se_context_t *context,
void *persistent_data,
psa_key_slot_number_t slot_number )
{
ram_slot_usage_t *slot_usage = persistent_data;
DRIVER_ASSERT( context->persistent_data_size == sizeof( ram_slot_usage_t ) );
DRIVER_ASSERT( slot_number < ARRAY_LENGTH( ram_slots ) );
memset( &ram_slots[slot_number], 0, sizeof( ram_slots[slot_number] ) );
*slot_usage &= ~(ram_slot_usage_t)( 1 << slot_number );
return( PSA_SUCCESS );
}
psa_status_t ram_allocate( psa_drv_se_context_t *context,
void *persistent_data,
const psa_key_attributes_t *attributes,
psa_key_slot_number_t *slot_number )
{
ram_slot_usage_t *slot_usage = persistent_data;
(void) attributes;
DRIVER_ASSERT( context->persistent_data_size == sizeof( ram_slot_usage_t ) );
for( *slot_number = ram_min_slot;
*slot_number < ARRAY_LENGTH( ram_slots );
++( *slot_number ) )
{
if( ! ( *slot_usage & 1 << *slot_number ) )
return( PSA_SUCCESS );
}
return( PSA_ERROR_INSUFFICIENT_STORAGE );
}
#define MAX_KEY_ID_FOR_TEST 10
void psa_purge_storage( void )
{
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( 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 */
/* BEGIN_DEPENDENCIES
* depends_on:MBEDTLS_PSA_CRYPTO_SE_C
* END_DEPENDENCIES
*/
/* BEGIN_CASE */
void register_one( int lifetime, int version, int expected_status_arg )
{
psa_status_t expected_status = expected_status_arg;
psa_drv_se_t driver;
memset( &driver, 0, sizeof( driver ) );
driver.hal_version = version;
TEST_EQUAL( psa_register_se_driver( lifetime, &driver ),
expected_status );
PSA_ASSERT( psa_crypto_init( ) );
exit:
PSA_DONE( );
}
/* END_CASE */
/* BEGIN_CASE */
void register_twice( int count )
{
psa_drv_se_t driver;
psa_key_lifetime_t lifetime;
psa_key_lifetime_t max = MIN_DRIVER_LIFETIME + count;
memset( &driver, 0, sizeof( driver ) );
driver.hal_version = PSA_DRV_SE_HAL_VERSION;
for( lifetime = MIN_DRIVER_LIFETIME; lifetime < max; lifetime++ )
PSA_ASSERT( psa_register_se_driver( lifetime, &driver ) );
for( lifetime = MIN_DRIVER_LIFETIME; lifetime < max; lifetime++ )
TEST_EQUAL( psa_register_se_driver( lifetime, &driver ),
PSA_ERROR_ALREADY_EXISTS );
PSA_ASSERT( psa_crypto_init( ) );
exit:
PSA_DONE( );
}
/* END_CASE */
/* BEGIN_CASE */
void register_max( )
{
psa_drv_se_t driver;
psa_key_lifetime_t lifetime;
psa_key_lifetime_t max = MIN_DRIVER_LIFETIME + PSA_MAX_SE_DRIVERS;
memset( &driver, 0, sizeof( driver ) );
driver.hal_version = PSA_DRV_SE_HAL_VERSION;
for( lifetime = MIN_DRIVER_LIFETIME; lifetime < max; lifetime++ )
PSA_ASSERT( psa_register_se_driver( lifetime, &driver ) );
TEST_EQUAL( psa_register_se_driver( lifetime, &driver ),
PSA_ERROR_INSUFFICIENT_MEMORY );
PSA_ASSERT( psa_crypto_init( ) );
exit:
PSA_DONE( );
}
/* END_CASE */
/* BEGIN_CASE */
void key_creation_import_export( int min_slot, int restart )
{
psa_drv_se_t driver;
psa_drv_se_key_management_t key_management;
psa_key_lifetime_t lifetime = 2;
psa_key_id_t id = 1;
psa_key_handle_t handle = 0;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
const uint8_t key_material[3] = {0xfa, 0xca, 0xde};
uint8_t exported[sizeof( key_material )];
size_t exported_length;
memset( &driver, 0, sizeof( driver ) );
memset( &key_management, 0, sizeof( key_management ) );
driver.hal_version = PSA_DRV_SE_HAL_VERSION;
driver.key_management = &key_management;
driver.persistent_data_size = sizeof( ram_slot_usage_t );
key_management.p_allocate = ram_allocate;
key_management.p_import = ram_import;
key_management.p_destroy = ram_destroy;
key_management.p_export = ram_export;
ram_min_slot = min_slot;
PSA_ASSERT( psa_register_se_driver( lifetime, &driver ) );
PSA_ASSERT( psa_crypto_init( ) );
/* Create a key. */
psa_set_key_id( &attributes, id );
psa_set_key_lifetime( &attributes, lifetime );
psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_EXPORT );
psa_set_key_type( &attributes, PSA_KEY_TYPE_RAW_DATA );
PSA_ASSERT( psa_import_key( &attributes,
key_material, sizeof( key_material ),
&handle ) );
/* Maybe restart, to check that the information is saved correctly. */
if( restart )
{
mbedtls_psa_crypto_free( );
PSA_ASSERT( psa_register_se_driver( lifetime, &driver ) );
PSA_ASSERT( psa_crypto_init( ) );
PSA_ASSERT( psa_open_key( id, &handle ) );
}
/* Test that the key was created in the expected slot. */
TEST_ASSERT( ram_slots[min_slot].type == PSA_KEY_TYPE_RAW_DATA );
PSA_ASSERT( psa_export_key( handle,
exported, sizeof( exported ),
&exported_length ) );
ASSERT_COMPARE( key_material, sizeof( key_material ),
exported, exported_length );
PSA_ASSERT( psa_destroy_key( handle ) );
/* Test that the key has been erased from the designated slot. */
TEST_ASSERT( ram_slots[min_slot].type == 0 );
exit:
PSA_DONE( );
ram_slots_reset( );
psa_purge_storage( );
}
/* END_CASE */