From 011e4284a1709bd8306c016ee9040922af45a24b Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Wed, 26 Jun 2019 18:34:38 +0200 Subject: [PATCH] Look up the SE driver when creating a key When creating a key with a lifetime that places it in a secure element, retrieve the appropriate driver table entry. This commit doesn't yet achieve behavior: so far the code only retrieves the driver, it doesn't call the driver. --- library/psa_crypto.c | 71 ++++++++++++++++++++-------- library/psa_crypto_slot_management.c | 14 +++++- library/psa_crypto_slot_management.h | 30 ++++++++++++ 3 files changed, 93 insertions(+), 22 deletions(-) diff --git a/library/psa_crypto.c b/library/psa_crypto.c index 5245e61bf..65e1e2a74 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -1291,9 +1291,11 @@ static psa_status_t psa_set_key_policy_internal( * In case of failure at any step, stop the sequence and call * psa_fail_key_creation(). * - * \param attributes Key attributes for the new key. - * \param handle On success, a handle for the allocated slot. - * \param p_slot On success, a pointer to the prepared slot. + * \param[in] attributes Key attributes for the new key. + * \param[out] handle On success, a handle for the allocated slot. + * \param[out] p_slot On success, a pointer to the prepared slot. + * \param[out] p_drv On any return, the driver for the key, if any. + * NULL for a transparent key. * * \retval #PSA_SUCCESS * The key slot is ready to receive key material. @@ -1303,11 +1305,14 @@ static psa_status_t psa_set_key_policy_internal( static psa_status_t psa_start_key_creation( const psa_key_attributes_t *attributes, psa_key_handle_t *handle, - psa_key_slot_t **p_slot ) + psa_key_slot_t **p_slot, + const psa_se_drv_table_entry_t **p_drv ) { psa_status_t status; psa_key_slot_t *slot; + *p_drv = NULL; + status = psa_internal_allocate_key_slot( handle, p_slot ); if( status != PSA_SUCCESS ) return( status ); @@ -1317,10 +1322,12 @@ static psa_status_t psa_start_key_creation( if( status != PSA_SUCCESS ) return( status ); slot->lifetime = attributes->lifetime; + if( attributes->lifetime != PSA_KEY_LIFETIME_VOLATILE ) { status = psa_validate_persistent_key_parameters( attributes->lifetime, - attributes->id, 1 ); + attributes->id, + p_drv, 1 ); if( status != PSA_SUCCESS ) return( status ); slot->persistent_storage_id = attributes->id; @@ -1338,17 +1345,22 @@ static psa_status_t psa_start_key_creation( * See the documentation of psa_start_key_creation() for the intended use * of this function. * - * \param slot Pointer to the slot with key material. + * \param[in,out] slot Pointer to the slot with key material. + * \param[in] driver The secure element driver for the key, + * or NULL for a transparent key. * * \retval #PSA_SUCCESS * The key was successfully created. The handle is now valid. * \return If this function fails, the key slot is an invalid state. * You must call psa_fail_key_creation() to wipe and free the slot. */ -static psa_status_t psa_finish_key_creation( psa_key_slot_t *slot ) +static psa_status_t psa_finish_key_creation( + psa_key_slot_t *slot, + const psa_se_drv_table_entry_t *driver ) { psa_status_t status = PSA_SUCCESS; (void) slot; + (void) driver; #if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) if( slot->lifetime == PSA_KEY_LIFETIME_PERSISTENT ) @@ -1390,12 +1402,25 @@ static psa_status_t psa_finish_key_creation( psa_key_slot_t *slot ) * See the documentation of psa_start_key_creation() for the intended use * of this function. * - * \param slot Pointer to the slot with key material. + * \param[in,out] slot Pointer to the slot with key material. + * \param[in] driver The secure element driver for the key, + * or NULL for a transparent key. */ -static void psa_fail_key_creation( psa_key_slot_t *slot ) +static void psa_fail_key_creation( psa_key_slot_t *slot, + const psa_se_drv_table_entry_t *driver ) { + (void) driver; + if( slot == NULL ) return; + +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + /* TOnogrepDO: If the key has already been created in the secure + * element, and the failure happened later (when saving metadata + * to internal storage), we need to destroy the key in the secure + * element. */ +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + psa_wipe_key_slot( slot ); } @@ -1458,8 +1483,9 @@ psa_status_t psa_import_key( const psa_key_attributes_t *attributes, { psa_status_t status; psa_key_slot_t *slot = NULL; + const psa_se_drv_table_entry_t *driver = NULL; - status = psa_start_key_creation( attributes, handle, &slot ); + status = psa_start_key_creation( attributes, handle, &slot, &driver ); if( status != PSA_SUCCESS ) goto exit; @@ -1470,11 +1496,11 @@ psa_status_t psa_import_key( const psa_key_attributes_t *attributes, if( status != PSA_SUCCESS ) goto exit; - status = psa_finish_key_creation( slot ); + status = psa_finish_key_creation( slot, driver ); exit: if( status != PSA_SUCCESS ) { - psa_fail_key_creation( slot ); + psa_fail_key_creation( slot, driver ); *handle = 0; } return( status ); @@ -1514,6 +1540,7 @@ psa_status_t psa_copy_key( psa_key_handle_t source_handle, psa_key_slot_t *source_slot = NULL; psa_key_slot_t *target_slot = NULL; psa_key_attributes_t actual_attributes = *specified_attributes; + const psa_se_drv_table_entry_t *driver = NULL; status = psa_get_key_from_slot( source_handle, &source_slot, PSA_KEY_USAGE_COPY, 0 ); @@ -1530,7 +1557,7 @@ psa_status_t psa_copy_key( psa_key_handle_t source_handle, goto exit; status = psa_start_key_creation( &actual_attributes, - target_handle, &target_slot ); + target_handle, &target_slot, &driver ); if( status != PSA_SUCCESS ) goto exit; @@ -1538,11 +1565,11 @@ psa_status_t psa_copy_key( psa_key_handle_t source_handle, if( status != PSA_SUCCESS ) goto exit; - status = psa_finish_key_creation( target_slot ); + status = psa_finish_key_creation( target_slot, driver ); exit: if( status != PSA_SUCCESS ) { - psa_fail_key_creation( target_slot ); + psa_fail_key_creation( target_slot, driver ); *target_handle = 0; } return( status ); @@ -4437,7 +4464,8 @@ psa_status_t psa_key_derivation_output_key( const psa_key_attributes_t *attribut { psa_status_t status; psa_key_slot_t *slot = NULL; - status = psa_start_key_creation( attributes, handle, &slot ); + const psa_se_drv_table_entry_t *driver = NULL; + status = psa_start_key_creation( attributes, handle, &slot, &driver ); if( status == PSA_SUCCESS ) { status = psa_generate_derived_key_internal( slot, @@ -4445,10 +4473,10 @@ psa_status_t psa_key_derivation_output_key( const psa_key_attributes_t *attribut operation ); } if( status == PSA_SUCCESS ) - status = psa_finish_key_creation( slot ); + status = psa_finish_key_creation( slot, driver ); if( status != PSA_SUCCESS ) { - psa_fail_key_creation( slot ); + psa_fail_key_creation( slot, driver ); *handle = 0; } return( status ); @@ -5467,7 +5495,8 @@ psa_status_t psa_generate_key( const psa_key_attributes_t *attributes, { psa_status_t status; psa_key_slot_t *slot = NULL; - status = psa_start_key_creation( attributes, handle, &slot ); + const psa_se_drv_table_entry_t *driver = NULL; + status = psa_start_key_creation( attributes, handle, &slot, &driver ); if( status == PSA_SUCCESS ) { status = psa_generate_key_internal( @@ -5475,10 +5504,10 @@ psa_status_t psa_generate_key( const psa_key_attributes_t *attributes, attributes->domain_parameters, attributes->domain_parameters_size ); } if( status == PSA_SUCCESS ) - status = psa_finish_key_creation( slot ); + status = psa_finish_key_creation( slot, driver ); if( status != PSA_SUCCESS ) { - psa_fail_key_creation( slot ); + psa_fail_key_creation( slot, driver ); *handle = 0; } return( status ); diff --git a/library/psa_crypto_slot_management.c b/library/psa_crypto_slot_management.c index 900aa41a5..eb24b6b4c 100644 --- a/library/psa_crypto_slot_management.c +++ b/library/psa_crypto_slot_management.c @@ -168,8 +168,20 @@ static int psa_is_key_id_valid( psa_key_file_id_t file_id, psa_status_t psa_validate_persistent_key_parameters( psa_key_lifetime_t lifetime, psa_key_file_id_t id, + const psa_se_drv_table_entry_t **p_drv, int creating ) { + if( p_drv != NULL ) + *p_drv = NULL; +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + if( psa_key_lifetime_is_external( lifetime ) ) + { + *p_drv = psa_get_se_driver_entry( lifetime ); + if( *p_drv == NULL ) + return( PSA_ERROR_INVALID_ARGUMENT ); + } + else +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ if( lifetime != PSA_KEY_LIFETIME_PERSISTENT ) return( PSA_ERROR_INVALID_ARGUMENT ); @@ -194,7 +206,7 @@ psa_status_t psa_open_key( psa_key_file_id_t id, psa_key_handle_t *handle ) *handle = 0; status = psa_validate_persistent_key_parameters( - PSA_KEY_LIFETIME_PERSISTENT, id, 0 ); + PSA_KEY_LIFETIME_PERSISTENT, id, NULL, 0 ); if( status != PSA_SUCCESS ) return( status ); diff --git a/library/psa_crypto_slot_management.h b/library/psa_crypto_slot_management.h index 5c1bde146..8111c4a62 100644 --- a/library/psa_crypto_slot_management.h +++ b/library/psa_crypto_slot_management.h @@ -22,6 +22,9 @@ #ifndef PSA_CRYPTO_SLOT_MANAGEMENT_H #define PSA_CRYPTO_SLOT_MANAGEMENT_H +#include "psa/crypto.h" +#include "psa_crypto_se.h" + /* Number of key slots (plus one because 0 is not used). * The value is a compile-time constant for now, for simplicity. */ #define PSA_KEY_SLOT_COUNT 32 @@ -71,6 +74,24 @@ void psa_wipe_all_key_slots( void ); psa_status_t psa_internal_allocate_key_slot( psa_key_handle_t *handle, psa_key_slot_t **p_slot ); +/** Test whether a lifetime designates a key in an external cryptoprocessor. + * + * \param lifetime The lifetime to test. + * + * \retval 1 + * The lifetime designates an external key. There should be a + * registered driver for this lifetime, otherwise the key cannot + * be created or manipulated. + * \retval 0 + * The lifetime designates a key that is volatile or in internal + * storage. + */ +static inline int psa_key_lifetime_is_external( psa_key_lifetime_t lifetime ) +{ + return( lifetime != PSA_KEY_LIFETIME_VOLATILE && + lifetime != PSA_KEY_LIFETIME_PERSISTENT ); +} + /** Test whether the given parameters are acceptable for a persistent key. * * This function does not access the storage in any way. It only tests @@ -78,8 +99,16 @@ psa_status_t psa_internal_allocate_key_slot( psa_key_handle_t *handle, * It does not test whether the a file by the given id exists or could be * created. * + * If the key is in external storage, this function returns the corresponding + * driver. + * * \param lifetime The lifetime to test. * \param id The key id to test. + * \param[out] p_drv On output, if \p lifetime designates a key + * in an external processor, \c *p_drv is a pointer + * to the driver table entry fot this lifetime. + * If \p lifetime designates a transparent key, + * \c *p_drv is \c NULL. * \param creating 0 if attempting to open an existing key. * Nonzero if attempting to create a key. * @@ -93,6 +122,7 @@ psa_status_t psa_internal_allocate_key_slot( psa_key_handle_t *handle, psa_status_t psa_validate_persistent_key_parameters( psa_key_lifetime_t lifetime, psa_key_file_id_t id, + const psa_se_drv_table_entry_t **p_drv, int creating );