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.
diff --git a/library/psa_crypto.c b/library/psa_crypto.c
index 5245e61..65e1e2a 100644
--- a/library/psa_crypto.c
+++ b/library/psa_crypto.c
@@ -1291,9 +1291,11 @@
  * 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_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 @@
     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 @@
  * 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 @@
  * 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 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 @@
     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_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 @@
         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 @@
     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 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 @@
                                                     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 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 @@
             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 900aa41..eb24b6b 100644
--- a/library/psa_crypto_slot_management.c
+++ b/library/psa_crypto_slot_management.c
@@ -168,8 +168,20 @@
 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 @@
     *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 5c1bde1..8111c4a 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 @@
 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 @@
  * 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_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 );