Support slot_number attribute when creating a key

Allow the application to choose the slot number in a secure element,
rather than always letting the driver choose.

With this commit, any application may request any slot. In an
implementation with isolation, it's up to the service to filter key
creation requests and apply policies to limit which applications can
request which slot.
This commit is contained in:
Gilles Peskine 2019-08-05 14:55:50 +02:00
parent ae9964d3ef
commit 46d9439a5e
4 changed files with 105 additions and 15 deletions

View file

@ -1582,10 +1582,6 @@ static psa_status_t psa_start_key_creation(
* we can roll back to a state where the key doesn't exist. */
if( *p_drv != NULL )
{
/* Choosing a slot number is not supported yet. */
if( attributes->core.flags & MBEDTLS_PSA_KA_FLAG_HAS_SLOT_NUMBER )
return( PSA_ERROR_NOT_SUPPORTED );
status = psa_find_se_slot_for_key( attributes, *p_drv,
&slot->data.se.slot_number );
if( status != PSA_SUCCESS )

View file

@ -201,7 +201,6 @@ psa_status_t psa_find_se_slot_for_key(
psa_key_slot_number_t *slot_number )
{
psa_status_t status;
psa_drv_se_allocate_key_t p_allocate = NULL;
/* If the lifetime is wrong, it's a bug in the library. */
if( driver->lifetime != psa_get_key_lifetime( attributes ) )
@ -210,17 +209,33 @@ psa_status_t psa_find_se_slot_for_key(
/* If the driver doesn't support key creation in any way, give up now. */
if( driver->methods->key_management == NULL )
return( PSA_ERROR_NOT_SUPPORTED );
p_allocate = driver->methods->key_management->p_allocate;
/* If the driver doesn't tell us how to allocate a slot, that's
* not supported for the time being. */
if( psa_get_key_slot_number( attributes, slot_number ) == PSA_SUCCESS )
{
/* The application wants to use a specific slot. Allow it if
* the driver supports it. On a system with isolation,
* the crypto service must check that the application is
* permitted to request this slot. */
psa_drv_se_validate_slot_number_t p_validate_slot_number =
driver->methods->key_management->p_validate_slot_number;
if( p_validate_slot_number == NULL )
return( PSA_ERROR_NOT_SUPPORTED );
status = p_validate_slot_number( &driver->context, attributes,
*slot_number );
}
else
{
/* The application didn't tell us which slot to use. Let the driver
* choose. This is the normal case. */
psa_drv_se_allocate_key_t p_allocate =
driver->methods->key_management->p_allocate;
if( p_allocate == NULL )
return( PSA_ERROR_NOT_SUPPORTED );
status = p_allocate( &driver->context,
driver->internal.persistent_data,
attributes,
slot_number );
}
return( status );
}

View file

@ -39,6 +39,15 @@ key_creation_import_export:0:1
SE key import-export, check after restart (slot 3)
key_creation_import_export:3:1
Key creation in a specific slot (0)
key_creation_in_chosen_slot:0:PSA_SUCCESS
Key creation in a specific slot (max)
key_creation_in_chosen_slot:ARRAY_LENGTH( ram_slots ) - 1:PSA_SUCCESS
Key creation in a specific slot (too large)
key_creation_in_chosen_slot:ARRAY_LENGTH( ram_slots ):PSA_ERROR_INVALID_ARGUMENT
Key creation smoke test: AES-CTR
key_creation_smoke:PSA_KEY_TYPE_AES:PSA_ALG_CTR:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"

View file

@ -177,6 +177,18 @@ static psa_status_t ram_allocate( psa_drv_se_context_t *context,
return( PSA_ERROR_INSUFFICIENT_STORAGE );
}
static psa_status_t ram_validate_slot_number(
psa_drv_se_context_t *context,
const psa_key_attributes_t *attributes,
psa_key_slot_number_t slot_number )
{
(void) context;
(void) attributes;
if( slot_number >= ARRAY_LENGTH( ram_slots ) )
return( PSA_ERROR_INVALID_ARGUMENT );
return( PSA_SUCCESS );
}
/****************************************************************/
@ -536,6 +548,64 @@ exit:
}
/* END_CASE */
/* BEGIN_CASE */
void key_creation_in_chosen_slot( int slot_arg,
int expected_status_arg )
{
psa_key_slot_number_t wanted_slot = slot_arg;
psa_status_t expected_status = expected_status_arg;
psa_status_t status;
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};
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_validate_slot_number = ram_validate_slot_number;
key_management.p_import = ram_import;
key_management.p_destroy = ram_destroy;
key_management.p_export = ram_export;
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_set_key_slot_number( &attributes, wanted_slot );
status = psa_import_key( &attributes,
key_material, sizeof( key_material ),
&handle );
TEST_EQUAL( status, expected_status );
if( status == PSA_SUCCESS )
{
/* Test that the key was created in the expected slot. */
TEST_EQUAL( ram_slots[wanted_slot].type, PSA_KEY_TYPE_RAW_DATA );
/* Test that the key is reported with the correct attributes,
* including the expected slot. */
PSA_ASSERT( psa_get_key_attributes( handle, &attributes ) );
PSA_ASSERT( psa_destroy_key( handle ) );
}
exit:
PSA_DONE( );
ram_slots_reset( );
psa_purge_storage( );
}
/* END_CASE */
/* BEGIN_CASE */
void key_creation_smoke( int type_arg, int alg_arg,
data_t *key_material )