mirror of
https://github.com/Mbed-TLS/mbedtls.git
synced 2025-02-27 15:40:02 +00:00
Merge pull request #202 from gilles-peskine-arm/psa-se_driver-choose_key_slot_number
Let applications create a key in a specific secure element slot
This commit is contained in:
commit
b231d996a0
@ -811,6 +811,42 @@ typedef struct {
|
||||
/**@{*/
|
||||
|
||||
/** \brief A function that allocates a slot for a key.
|
||||
*
|
||||
* To create a key in a specific slot in a secure element, the core
|
||||
* first calls this function to determine a valid slot number,
|
||||
* then calls a function to create the key material in that slot.
|
||||
* For example, in nominal conditions (that is, if no error occurs),
|
||||
* the effect of a call to psa_import_key() with a lifetime that places
|
||||
* the key in a secure element is the following:
|
||||
* -# The core calls psa_drv_se_key_management_t::p_allocate
|
||||
* (or in some implementations
|
||||
* psa_drv_se_key_management_t::p_validate_slot_number). The driver
|
||||
* selects (or validates) a suitable slot number given the key attributes
|
||||
* and the state of the secure element.
|
||||
* -# The core calls psa_drv_se_key_management_t::p_import to import
|
||||
* the key material in the selected slot.
|
||||
*
|
||||
* Other key creation methods lead to similar sequences. For example, the
|
||||
* sequence for psa_generate_key() is the same except that the second step
|
||||
* is a call to psa_drv_se_key_management_t::p_generate.
|
||||
*
|
||||
* In case of errors, other behaviors are possible.
|
||||
* - If the PSA Cryptography subsystem dies after the first step,
|
||||
* for example because the device has lost power abruptly,
|
||||
* the second step may never happen, or may happen after a reset
|
||||
* and re-initialization. Alternatively, after a reset and
|
||||
* re-initialization, the core may call
|
||||
* psa_drv_se_key_management_t::p_destroy on the slot number that
|
||||
* was allocated (or validated) instead of calling a key creation function.
|
||||
* - If an error occurs, the core may call
|
||||
* psa_drv_se_key_management_t::p_destroy on the slot number that
|
||||
* was allocated (or validated) instead of calling a key creation function.
|
||||
*
|
||||
* Errors and system resets also have an impact on the driver's persistent
|
||||
* data. If a reset happens before the overall key creation process is
|
||||
* completed (before or after the second step above), it is unspecified
|
||||
* whether the persistent data after the reset is identical to what it
|
||||
* was before or after the call to `p_allocate` (or `p_validate_slot_number`).
|
||||
*
|
||||
* \param[in,out] drv_context The driver context structure.
|
||||
* \param[in,out] persistent_data A pointer to the persistent data
|
||||
@ -833,6 +869,42 @@ typedef psa_status_t (*psa_drv_se_allocate_key_t)(
|
||||
const psa_key_attributes_t *attributes,
|
||||
psa_key_slot_number_t *key_slot);
|
||||
|
||||
/** \brief A function that determines whether a slot number is valid
|
||||
* for a key.
|
||||
*
|
||||
* To create a key in a specific slot in a secure element, the core
|
||||
* first calls this function to validate the choice of slot number,
|
||||
* then calls a function to create the key material in that slot.
|
||||
* See the documentation of #psa_drv_se_allocate_key_t for more details.
|
||||
*
|
||||
* As of the PSA Cryptography API specification version 1.0, there is no way
|
||||
* for applications to trigger a call to this function. However some
|
||||
* implementations offer the capability to create or declare a key in
|
||||
* a specific slot via implementation-specific means, generally for the
|
||||
* sake of initial device provisioning or onboarding. Such a mechanism may
|
||||
* be added to a future version of the PSA Cryptography API specification.
|
||||
*
|
||||
* \param[in,out] drv_context The driver context structure.
|
||||
* \param[in] attributes Attributes of the key.
|
||||
* \param[in] key_slot Slot where the key is to be stored.
|
||||
*
|
||||
* \retval #PSA_SUCCESS
|
||||
* The given slot number is valid for a key with the given
|
||||
* attributes.
|
||||
* \retval #PSA_ERROR_INVALID_ARGUMENT
|
||||
* The given slot number is not valid for a key with the
|
||||
* given attributes. This includes the case where the slot
|
||||
* number is not valid at all.
|
||||
* \retval #PSA_ERROR_ALREADY_EXISTS
|
||||
* There is already a key with the specified slot number.
|
||||
* Drivers may choose to return this error from the key
|
||||
* creation function instead.
|
||||
*/
|
||||
typedef psa_status_t (*psa_drv_se_validate_slot_number_t)(
|
||||
psa_drv_se_context_t *drv_context,
|
||||
const psa_key_attributes_t *attributes,
|
||||
psa_key_slot_number_t key_slot);
|
||||
|
||||
/** \brief A function that imports a key into a secure element in binary format
|
||||
*
|
||||
* This function can support any output from psa_export_key(). Refer to the
|
||||
@ -977,8 +1049,10 @@ typedef psa_status_t (*psa_drv_se_generate_key_t)(psa_drv_se_context_t *drv_cont
|
||||
* If one of the functions is not implemented, it should be set to NULL.
|
||||
*/
|
||||
typedef struct {
|
||||
/** Function that allocates a slot. */
|
||||
/** Function that allocates a slot for a key. */
|
||||
psa_drv_se_allocate_key_t p_allocate;
|
||||
/** Function that checks the validity of a slot for a key. */
|
||||
psa_drv_se_validate_slot_number_t p_validate_slot_number;
|
||||
/** Function that performs a key import operation */
|
||||
psa_drv_se_import_key_t p_import;
|
||||
/** Function that performs a generation */
|
||||
|
@ -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 )
|
||||
|
@ -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( p_allocate == NULL )
|
||||
return( PSA_ERROR_NOT_SUPPORTED );
|
||||
|
||||
status = p_allocate( &driver->context,
|
||||
driver->internal.persistent_data,
|
||||
attributes,
|
||||
slot_number );
|
||||
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 );
|
||||
}
|
||||
|
||||
|
@ -39,6 +39,21 @@ 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:0:PSA_SUCCESS
|
||||
|
||||
Key creation in a specific slot (max)
|
||||
key_creation_in_chosen_slot:ARRAY_LENGTH( ram_slots ) - 1:0:PSA_SUCCESS
|
||||
|
||||
Key creation in a specific slot (0, restart)
|
||||
key_creation_in_chosen_slot:0:1:PSA_SUCCESS
|
||||
|
||||
Key creation in a specific slot (max, restart)
|
||||
key_creation_in_chosen_slot:ARRAY_LENGTH( ram_slots ) - 1:1:PSA_SUCCESS
|
||||
|
||||
Key creation in a specific slot (too large)
|
||||
key_creation_in_chosen_slot:ARRAY_LENGTH( ram_slots ):0:PSA_ERROR_INVALID_ARGUMENT
|
||||
|
||||
Key creation smoke test: AES-CTR
|
||||
key_creation_smoke:PSA_KEY_TYPE_AES:PSA_ALG_CTR:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
|
||||
|
@ -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,74 @@ exit:
|
||||
}
|
||||
/* END_CASE */
|
||||
|
||||
/* BEGIN_CASE */
|
||||
void key_creation_in_chosen_slot( int slot_arg,
|
||||
int restart,
|
||||
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 )
|
||||
goto exit;
|
||||
|
||||
/* 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_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 )
|
||||
|
Loading…
x
Reference in New Issue
Block a user