Skip to content

Commit 5a2d152

Browse files
Merge pull request #183 from gilles-peskine-arm/psa-se_driver-register_key
Secure element key registration
2 parents b231d99 + 49bd582 commit 5a2d152

7 files changed

+313
-25
lines changed

include/psa/crypto_extra.h

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,44 @@ static inline void psa_clear_key_slot_number(
175175
attributes->core.flags &= ~MBEDTLS_PSA_KA_FLAG_HAS_SLOT_NUMBER;
176176
}
177177

178+
/** Register a key that is already present in a secure element.
179+
*
180+
* The key must be located in a secure element designated by the
181+
* lifetime field in \p attributes, in the slot set with
182+
* psa_set_key_slot_number() in the attribute structure.
183+
* This function makes the key available through the key identifier
184+
* specified in \p attributes.
185+
*
186+
* \param[in] attributes The attributes of the existing key.
187+
*
188+
* \retval #PSA_SUCCESS
189+
* The key was successfully registered.
190+
* Note that depending on the design of the driver, this may or may
191+
* not guarantee that a key actually exists in the designated slot
192+
* and is compatible with the specified attributes.
193+
* \retval #PSA_ERROR_ALREADY_EXISTS
194+
* There is already a key with the identifier specified in
195+
* \p attributes.
196+
* \retval #PSA_ERROR_INVALID_ARGUMENT
197+
* \p attributes specifies a lifetime which is not located
198+
* in a secure element.
199+
* \retval #PSA_ERROR_INVALID_ARGUMENT
200+
* No slot number is specified in \p attributes,
201+
* or the specified slot number is not valid.
202+
* \retval #PSA_ERROR_NOT_PERMITTED
203+
* The caller is not authorized to register the specified key slot.
204+
* \retval #PSA_ERROR_INSUFFICIENT_MEMORY
205+
* \retval #PSA_ERROR_COMMUNICATION_FAILURE
206+
* \retval #PSA_ERROR_HARDWARE_FAILURE
207+
* \retval #PSA_ERROR_CORRUPTION_DETECTED
208+
* \retval #PSA_ERROR_BAD_STATE
209+
* The library has not been previously initialized by psa_crypto_init().
210+
* It is implementation-dependent whether a failure to initialize
211+
* results in this error code.
212+
*/
213+
psa_status_t mbedtls_psa_register_se_key(
214+
const psa_key_attributes_t *attributes);
215+
178216
#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
179217

180218
/**@}*/

include/psa/crypto_se_driver.h

Lines changed: 57 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -810,25 +810,66 @@ typedef struct {
810810
*/
811811
/**@{*/
812812

813+
/** An enumeration indicating how a key is created.
814+
*/
815+
typedef enum
816+
{
817+
PSA_KEY_CREATION_IMPORT, /**< During psa_import_key() */
818+
PSA_KEY_CREATION_GENERATE, /**< During psa_generate_key() */
819+
PSA_KEY_CREATION_DERIVE, /**< During psa_key_derivation_output_key() */
820+
PSA_KEY_CREATION_COPY, /**< During psa_copy_key() */
821+
822+
#ifndef __DOXYGEN_ONLY__
823+
/** A key is being registered with mbedtls_psa_register_se_key().
824+
*
825+
* The core only passes this value to
826+
* psa_drv_se_key_management_t::p_validate_slot_number, not to
827+
* psa_drv_se_key_management_t::p_allocate. The call to
828+
* `p_validate_slot_number` is not followed by any other call to the
829+
* driver: the key is considered successfully registered if the call to
830+
* `p_validate_slot_number` succeeds, or if `p_validate_slot_number` is
831+
* null.
832+
*
833+
* With this creation method, the driver must return #PSA_SUCCESS if
834+
* the given attributes are compatible with the existing key in the slot,
835+
* and #PSA_ERROR_DOES_NOT_EXIST if the driver can determine that there
836+
* is no key with the specified slot number.
837+
*
838+
* This is an Mbed Crypto extension.
839+
*/
840+
PSA_KEY_CREATION_REGISTER,
841+
#endif
842+
} psa_key_creation_method_t;
843+
813844
/** \brief A function that allocates a slot for a key.
814845
*
815846
* To create a key in a specific slot in a secure element, the core
816847
* first calls this function to determine a valid slot number,
817848
* then calls a function to create the key material in that slot.
818-
* For example, in nominal conditions (that is, if no error occurs),
819-
* the effect of a call to psa_import_key() with a lifetime that places
820-
* the key in a secure element is the following:
849+
* In nominal conditions (that is, if no error occurs),
850+
* the effect of a call to a key creation function in the PSA Cryptography
851+
* API with a lifetime that places the key in a secure element is the
852+
* following:
821853
* -# The core calls psa_drv_se_key_management_t::p_allocate
822854
* (or in some implementations
823855
* psa_drv_se_key_management_t::p_validate_slot_number). The driver
824856
* selects (or validates) a suitable slot number given the key attributes
825857
* and the state of the secure element.
826-
* -# The core calls psa_drv_se_key_management_t::p_import to import
827-
* the key material in the selected slot.
828-
*
829-
* Other key creation methods lead to similar sequences. For example, the
830-
* sequence for psa_generate_key() is the same except that the second step
831-
* is a call to psa_drv_se_key_management_t::p_generate.
858+
* -# The core calls a key creation function in the driver.
859+
*
860+
* The key creation functions in the PSA Cryptography API are:
861+
* - psa_import_key(), which causes
862+
* a call to `p_allocate` with \p method = #PSA_KEY_CREATION_IMPORT
863+
* then a call to psa_drv_se_key_management_t::p_import.
864+
* - psa_generate_key(), which causes
865+
* a call to `p_allocate` with \p method = #PSA_KEY_CREATION_GENERATE
866+
* then a call to psa_drv_se_key_management_t::p_import.
867+
* - psa_key_derivation_output_key(), which causes
868+
* a call to `p_allocate` with \p method = #PSA_KEY_CREATION_DERIVE
869+
* then a call to psa_drv_se_key_derivation_t::p_derive.
870+
* - psa_copy_key(), which causes
871+
* a call to `p_allocate` with \p method = #PSA_KEY_CREATION_COPY
872+
* then a call to psa_drv_se_key_management_t::p_export.
832873
*
833874
* In case of errors, other behaviors are possible.
834875
* - If the PSA Cryptography subsystem dies after the first step,
@@ -852,6 +893,7 @@ typedef struct {
852893
* \param[in,out] persistent_data A pointer to the persistent data
853894
* that allows writing.
854895
* \param[in] attributes Attributes of the key.
896+
* \param method The way in which the key is being created.
855897
* \param[out] key_slot Slot where the key will be stored.
856898
* This must be a valid slot for a key of the
857899
* chosen type. It must be unoccupied.
@@ -867,6 +909,7 @@ typedef psa_status_t (*psa_drv_se_allocate_key_t)(
867909
psa_drv_se_context_t *drv_context,
868910
void *persistent_data,
869911
const psa_key_attributes_t *attributes,
912+
psa_key_creation_method_t method,
870913
psa_key_slot_number_t *key_slot);
871914

872915
/** \brief A function that determines whether a slot number is valid
@@ -884,9 +927,10 @@ typedef psa_status_t (*psa_drv_se_allocate_key_t)(
884927
* sake of initial device provisioning or onboarding. Such a mechanism may
885928
* be added to a future version of the PSA Cryptography API specification.
886929
*
887-
* \param[in,out] drv_context The driver context structure.
888-
* \param[in] attributes Attributes of the key.
889-
* \param[in] key_slot Slot where the key is to be stored.
930+
* \param[in,out] drv_context The driver context structure.
931+
* \param[in] attributes Attributes of the key.
932+
* \param method The way in which the key is being created.
933+
* \param[in] key_slot Slot where the key is to be stored.
890934
*
891935
* \retval #PSA_SUCCESS
892936
* The given slot number is valid for a key with the given
@@ -903,6 +947,7 @@ typedef psa_status_t (*psa_drv_se_allocate_key_t)(
903947
typedef psa_status_t (*psa_drv_se_validate_slot_number_t)(
904948
psa_drv_se_context_t *drv_context,
905949
const psa_key_attributes_t *attributes,
950+
psa_key_creation_method_t method,
906951
psa_key_slot_number_t key_slot);
907952

908953
/** \brief A function that imports a key into a secure element in binary format

library/psa_crypto.c

Lines changed: 96 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1520,6 +1520,7 @@ static psa_status_t psa_validate_key_attributes(
15201520
* In case of failure at any step, stop the sequence and call
15211521
* psa_fail_key_creation().
15221522
*
1523+
* \param method An identification of the calling function.
15231524
* \param[in] attributes Key attributes for the new key.
15241525
* \param[out] handle On success, a handle for the allocated slot.
15251526
* \param[out] p_slot On success, a pointer to the prepared slot.
@@ -1532,6 +1533,7 @@ static psa_status_t psa_validate_key_attributes(
15321533
* You must call psa_fail_key_creation() to wipe and free the slot.
15331534
*/
15341535
static psa_status_t psa_start_key_creation(
1536+
psa_key_creation_method_t method,
15351537
const psa_key_attributes_t *attributes,
15361538
psa_key_handle_t *handle,
15371539
psa_key_slot_t **p_slot,
@@ -1540,6 +1542,7 @@ static psa_status_t psa_start_key_creation(
15401542
psa_status_t status;
15411543
psa_key_slot_t *slot;
15421544

1545+
(void) method;
15431546
*p_drv = NULL;
15441547

15451548
status = psa_validate_key_attributes( attributes, p_drv );
@@ -1567,7 +1570,8 @@ static psa_status_t psa_start_key_creation(
15671570
slot->attr.flags &= ~MBEDTLS_PSA_KA_MASK_EXTERNAL_ONLY;
15681571

15691572
#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
1570-
/* For a key in a secure element, we need to do three things:
1573+
/* For a key in a secure element, we need to do three things
1574+
* when creating a key (but not when registering an existing key):
15711575
* create the key file in internal storage, create the
15721576
* key inside the secure element, and update the driver's
15731577
* persistent data. Start a transaction that will encompass these
@@ -1580,9 +1584,9 @@ static psa_status_t psa_start_key_creation(
15801584
* secure element driver updates its persistent state, but we do not yet
15811585
* save the driver's persistent state, so that if the power fails,
15821586
* we can roll back to a state where the key doesn't exist. */
1583-
if( *p_drv != NULL )
1587+
if( *p_drv != NULL && method != PSA_KEY_CREATION_REGISTER )
15841588
{
1585-
status = psa_find_se_slot_for_key( attributes, *p_drv,
1589+
status = psa_find_se_slot_for_key( attributes, method, *p_drv,
15861590
&slot->data.se.slot_number );
15871591
if( status != PSA_SUCCESS )
15881592
return( status );
@@ -1674,7 +1678,13 @@ static psa_status_t psa_finish_key_creation(
16741678
#endif /* defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) */
16751679

16761680
#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
1677-
if( driver != NULL )
1681+
/* Finish the transaction for a key creation. This does not
1682+
* happen when registering an existing key. Detect this case
1683+
* by checking whether a transaction is in progress (actual
1684+
* creation of a key in a secure element requires a transaction,
1685+
* but registration doesn't use one). */
1686+
if( driver != NULL &&
1687+
psa_crypto_transaction.unknown.type == PSA_CRYPTO_TRANSACTION_CREATE_KEY )
16781688
{
16791689
status = psa_save_se_persistent_data( driver );
16801690
if( status != PSA_SUCCESS )
@@ -1717,9 +1727,12 @@ static void psa_fail_key_creation( psa_key_slot_t *slot,
17171727
* to internal storage), we need to destroy the key in the secure
17181728
* element. */
17191729

1720-
/* Abort the ongoing transaction if any. We already did what it
1721-
* takes to undo any partial creation. All that's left is to update
1722-
* the transaction data itself. */
1730+
/* Abort the ongoing transaction if any (there may not be one if
1731+
* the creation process failed before starting one, or if the
1732+
* key creation is a registration of a key in a secure element).
1733+
* Earlier functions must already have done what it takes to undo any
1734+
* partial creation. All that's left is to update the transaction data
1735+
* itself. */
17231736
(void) psa_crypto_stop_transaction( );
17241737
#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
17251738

@@ -1796,7 +1809,8 @@ psa_status_t psa_import_key( const psa_key_attributes_t *attributes,
17961809
psa_key_slot_t *slot = NULL;
17971810
psa_se_drv_table_entry_t *driver = NULL;
17981811

1799-
status = psa_start_key_creation( attributes, handle, &slot, &driver );
1812+
status = psa_start_key_creation( PSA_KEY_CREATION_IMPORT, attributes,
1813+
handle, &slot, &driver );
18001814
if( status != PSA_SUCCESS )
18011815
goto exit;
18021816

@@ -1848,6 +1862,74 @@ psa_status_t psa_import_key( const psa_key_attributes_t *attributes,
18481862
return( status );
18491863
}
18501864

1865+
#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
1866+
psa_status_t mbedtls_psa_register_se_key(
1867+
const psa_key_attributes_t *attributes )
1868+
{
1869+
psa_status_t status;
1870+
psa_key_slot_t *slot = NULL;
1871+
psa_se_drv_table_entry_t *driver = NULL;
1872+
const psa_drv_se_t *drv;
1873+
psa_key_handle_t handle = 0;
1874+
1875+
/* Leaving attributes unspecified is not currently supported.
1876+
* It could make sense to query the key type and size from the
1877+
* secure element, but not all secure elements support this
1878+
* and the driver HAL doesn't currently support it. */
1879+
if( psa_get_key_type( attributes ) == PSA_KEY_TYPE_NONE )
1880+
return( PSA_ERROR_NOT_SUPPORTED );
1881+
if( psa_get_key_bits( attributes ) == 0 )
1882+
return( PSA_ERROR_NOT_SUPPORTED );
1883+
1884+
status = psa_start_key_creation( PSA_KEY_CREATION_REGISTER, attributes,
1885+
&handle, &slot, &driver );
1886+
if( status != PSA_SUCCESS )
1887+
goto exit;
1888+
1889+
if( driver == NULL )
1890+
{
1891+
status = PSA_ERROR_INVALID_ARGUMENT;
1892+
goto exit;
1893+
}
1894+
drv = psa_get_se_driver_methods( driver );
1895+
1896+
if ( psa_get_key_slot_number( attributes,
1897+
&slot->data.se.slot_number ) != PSA_SUCCESS )
1898+
{
1899+
/* The application didn't specify a slot number. This doesn't
1900+
* make sense when registering a slot. */
1901+
status = PSA_ERROR_INVALID_ARGUMENT;
1902+
goto exit;
1903+
}
1904+
1905+
/* If the driver has a slot number validation method, call it.
1906+
* If it doesn't, it means the secure element is unable to validate
1907+
* anything and so we have to trust the application. */
1908+
if( drv->key_management != NULL &&
1909+
drv->key_management->p_validate_slot_number != NULL )
1910+
{
1911+
status = drv->key_management->p_validate_slot_number(
1912+
psa_get_se_driver_context( driver ),
1913+
attributes,
1914+
PSA_KEY_CREATION_REGISTER,
1915+
slot->data.se.slot_number );
1916+
if( status != PSA_SUCCESS )
1917+
goto exit;
1918+
}
1919+
1920+
status = psa_finish_key_creation( slot, driver );
1921+
1922+
exit:
1923+
if( status != PSA_SUCCESS )
1924+
{
1925+
psa_fail_key_creation( slot, driver );
1926+
}
1927+
/* Registration doesn't keep the key in RAM. */
1928+
psa_close_key( handle );
1929+
return( status );
1930+
}
1931+
#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
1932+
18511933
static psa_status_t psa_copy_key_material( const psa_key_slot_t *source,
18521934
psa_key_slot_t *target )
18531935
{
@@ -1899,7 +1981,8 @@ psa_status_t psa_copy_key( psa_key_handle_t source_handle,
18991981
if( status != PSA_SUCCESS )
19001982
goto exit;
19011983

1902-
status = psa_start_key_creation( &actual_attributes,
1984+
status = psa_start_key_creation( PSA_KEY_CREATION_COPY,
1985+
&actual_attributes,
19031986
target_handle, &target_slot, &driver );
19041987
if( status != PSA_SUCCESS )
19051988
goto exit;
@@ -4817,7 +4900,8 @@ psa_status_t psa_key_derivation_output_key( const psa_key_attributes_t *attribut
48174900
psa_status_t status;
48184901
psa_key_slot_t *slot = NULL;
48194902
psa_se_drv_table_entry_t *driver = NULL;
4820-
status = psa_start_key_creation( attributes, handle, &slot, &driver );
4903+
status = psa_start_key_creation( PSA_KEY_CREATION_DERIVE,
4904+
attributes, handle, &slot, &driver );
48214905
#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
48224906
if( driver != NULL )
48234907
{
@@ -5863,7 +5947,8 @@ psa_status_t psa_generate_key( const psa_key_attributes_t *attributes,
58635947
psa_status_t status;
58645948
psa_key_slot_t *slot = NULL;
58655949
psa_se_drv_table_entry_t *driver = NULL;
5866-
status = psa_start_key_creation( attributes, handle, &slot, &driver );
5950+
status = psa_start_key_creation( PSA_KEY_CREATION_GENERATE,
5951+
attributes, handle, &slot, &driver );
58675952
#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
58685953
if( driver != NULL )
58695954
{

library/psa_crypto_se.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,7 @@ psa_status_t psa_destroy_se_persistent_data( psa_key_lifetime_t lifetime )
197197

198198
psa_status_t psa_find_se_slot_for_key(
199199
const psa_key_attributes_t *attributes,
200+
psa_key_creation_method_t method,
200201
psa_se_drv_table_entry_t *driver,
201202
psa_key_slot_number_t *slot_number )
202203
{
@@ -220,7 +221,8 @@ psa_status_t psa_find_se_slot_for_key(
220221
driver->methods->key_management->p_validate_slot_number;
221222
if( p_validate_slot_number == NULL )
222223
return( PSA_ERROR_NOT_SUPPORTED );
223-
status = p_validate_slot_number( &driver->context, attributes,
224+
status = p_validate_slot_number( &driver->context,
225+
attributes, method,
224226
*slot_number );
225227
}
226228
else
@@ -233,7 +235,7 @@ psa_status_t psa_find_se_slot_for_key(
233235
return( PSA_ERROR_NOT_SUPPORTED );
234236
status = p_allocate( &driver->context,
235237
driver->internal.persistent_data,
236-
attributes,
238+
attributes, method,
237239
slot_number );
238240
}
239241
return( status );

library/psa_crypto_se.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@ psa_drv_se_context_t *psa_get_se_driver_context(
135135
*/
136136
psa_status_t psa_find_se_slot_for_key(
137137
const psa_key_attributes_t *attributes,
138+
psa_key_creation_method_t method,
138139
psa_se_drv_table_entry_t *driver,
139140
psa_key_slot_number_t *slot_number );
140141

0 commit comments

Comments
 (0)