Add slot_number attribute

Add a slot_number field to psa_key_attributes_t and getter/setter
functions. Since slot numbers can have the value 0, indicate the
presence of the field via a separate flag.

In psa_get_key_attributes(), report the slot number if the key is in a
secure element.

When creating a key, for now, applications cannot choose a slot
number. A subsequent commit will add this capability in the secure
element HAL.
diff --git a/include/psa/crypto_extra.h b/include/psa/crypto_extra.h
index 6dfaa13..5359b58 100644
--- a/include/psa/crypto_extra.h
+++ b/include/psa/crypto_extra.h
@@ -104,6 +104,67 @@
     return( attributes->core.policy.alg2 );
 }
 
+#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
+
+/** Retrieve the slot number where a key is stored.
+ *
+ * A slot number is only defined for keys that are stored in a secure
+ * element.
+ *
+ * This information is only useful if the secure element is not entirely
+ * managed through the PSA Cryptography API. It is up to the secure
+ * element driver to decide how PSA slot numbers map to any other interface
+ * that the secure element may have.
+ *
+ * \param[in] attributes        The key attribute structure to query.
+ * \param[out] slot_number      On success, the slot number containing the key.
+ *
+ * \retval #PSA_SUCCESS
+ *         The key is located in a secure element, and \p *slot_number
+ *         indicates the slot number that contains it.
+ * \retval #PSA_ERROR_NOT_PERMITTED
+ *         The caller is not permitted to query the slot number.
+ *         Mbed Crypto currently does not return this error.
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ *         The key is not located in a secure element.
+ */
+psa_status_t psa_get_key_slot_number(
+    const psa_key_attributes_t *attributes,
+    psa_key_slot_number_t *slot_number );
+
+/** Choose the slot number where a key is stored.
+ *
+ * This function declares a slot number in the specified attribute
+ * structure.
+ *
+ * A slot number is only meaningful for keys that are stored in a secure
+ * element. It is up to the secure element driver to decide how PSA slot
+ * numbers map to any other interface that the secure element may have.
+ *
+ * \note Setting a slot number in key attributes for a key creation can
+ *       cause the following errors when creating the key:
+ *       - #PSA_ERROR_NOT_SUPPORTED if the selected secure element does
+ *         not support choosing a specific slot number.
+ *       - #PSA_ERROR_NOT_PERMITTED if the caller is not permitted to
+ *         choose slot numbers in general or to choose this specific slot.
+ *       - #PSA_ERROR_INVALID_ARGUMENT if the chosen slot number is not
+ *         valid in general or not valid for this specific key.
+ *       - #PSA_ERROR_ALREADY_EXISTS if there is already a key in the
+ *         selected slot.
+ *
+ * \param[out] attributes       The attribute structure to write to.
+ * \param slot_number           The slot number to set.
+ */
+static inline void psa_set_key_slot_number(
+    psa_key_attributes_t *attributes,
+    psa_key_slot_number_t slot_number )
+{
+    attributes->core.flags |= MBEDTLS_PSA_KA_FLAG_HAS_SLOT_NUMBER;
+    attributes->slot_number = slot_number;
+}
+
+#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
+
 /**@}*/
 
 /**
diff --git a/include/psa/crypto_se_driver.h b/include/psa/crypto_se_driver.h
index f95eaeb..69cdaba 100644
--- a/include/psa/crypto_se_driver.h
+++ b/include/psa/crypto_se_driver.h
@@ -134,10 +134,17 @@
                                           void *persistent_data,
                                           psa_key_lifetime_t lifetime);
 
+#if defined(__DOXYGEN_ONLY__) || !defined(MBEDTLS_PSA_CRYPTO_SE_C)
+/* Mbed Crypto with secure element support enabled defines this type in
+ * crypto_types.h because it is also visible to applications through an
+ * implementation-specific extension.
+ * For the PSA Cryptography specification, this type is only visible
+ * via crypto_se_driver.h. */
 /** An internal designation of a key slot between the core part of the
  * PSA Crypto implementation and the driver. The meaning of this value
  * is driver-dependent. */
 typedef uint64_t psa_key_slot_number_t;
+#endif /* __DOXYGEN_ONLY__ || !MBEDTLS_PSA_CRYPTO_SE_C */
 
 /**@}*/
 
diff --git a/include/psa/crypto_struct.h b/include/psa/crypto_struct.h
index 3bace60..fbfe77e 100644
--- a/include/psa/crypto_struct.h
+++ b/include/psa/crypto_struct.h
@@ -331,11 +331,13 @@
  */
 typedef uint16_t psa_key_attributes_flag_t;
 
-#define MBEDLTS_PSA_KA_FLAG_SLOT_NUMBER ( (psa_key_attributes_flag_t) 0x0001 )
+#define MBEDTLS_PSA_KA_FLAG_HAS_SLOT_NUMBER     \
+    ( (psa_key_attributes_flag_t) 0x0001 )
 
 /* A mask of key attribute flags used externally only.
  * Only meant for internal checks inside the library. */
 #define MBEDTLS_PSA_KA_MASK_EXTERNAL_ONLY (      \
+        MBEDTLS_PSA_KA_FLAG_HAS_SLOT_NUMBER |    \
         0 )
 
 /* A mask of key attribute flags used both internally and externally.
@@ -358,11 +360,19 @@
 struct psa_key_attributes_s
 {
     psa_core_key_attributes_t core;
+#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
+    psa_key_slot_number_t slot_number;
+#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
     void *domain_parameters;
     size_t domain_parameters_size;
 };
 
+#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
+#define PSA_KEY_ATTRIBUTES_INIT {PSA_CORE_KEY_ATTRIBUTES_INIT, 0, NULL, 0}
+#else
 #define PSA_KEY_ATTRIBUTES_INIT {PSA_CORE_KEY_ATTRIBUTES_INIT, NULL, 0}
+#endif
+
 static inline struct psa_key_attributes_s psa_key_attributes_init( void )
 {
     const struct psa_key_attributes_s v = PSA_KEY_ATTRIBUTES_INIT;
diff --git a/include/psa/crypto_types.h b/include/psa/crypto_types.h
index 1944be4..9af4957 100644
--- a/include/psa/crypto_types.h
+++ b/include/psa/crypto_types.h
@@ -244,6 +244,17 @@
  */
 typedef struct psa_key_attributes_s psa_key_attributes_t;
 
+
+#ifndef __DOXYGEN_ONLY__
+#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
+/* Mbed Crypto defines this type in crypto_types.h because it is also
+ * visible to applications through an implementation-specific extension.
+ * For the PSA Cryptography specification, this type is only visible
+ * via crypto_se_driver.h. */
+typedef uint64_t psa_key_slot_number_t;
+#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
+#endif /* !__DOXYGEN_ONLY__ */
+
 /**@}*/
 
 /** \defgroup derivation Key derivation
diff --git a/library/psa_crypto.c b/library/psa_crypto.c
index e043d70..a54cd73 100644
--- a/library/psa_crypto.c
+++ b/library/psa_crypto.c
@@ -1187,6 +1187,13 @@
         return( status );
 
     attributes->core = slot->attr;
+    attributes->core.flags &= ( MBEDTLS_PSA_KA_MASK_EXTERNAL_ONLY |
+                                MBEDTLS_PSA_KA_MASK_DUAL_USE );
+
+#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
+    if( psa_key_slot_is_external( slot ) )
+        psa_set_key_slot_number( attributes, slot->data.se.slot_number );
+#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
 
     switch( slot->attr.type )
     {
@@ -1196,7 +1203,7 @@
 #if defined(MBEDTLS_PSA_CRYPTO_SE_C)
             /* TOnogrepDO: reporting the public exponent for opaque keys
              * is not yet implemented. */
-            if( psa_get_se_driver( slot->attr.lifetime, NULL, NULL ) )
+            if( psa_key_slot_is_external( slot ) )
                 break;
 #endif /* MBEDTLS_PSA_CRYPTO_SE_C */
             status = psa_get_rsa_public_exponent( slot->data.rsa, attributes );
@@ -1212,6 +1219,21 @@
     return( status );
 }
 
+#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
+psa_status_t psa_get_key_slot_number(
+    const psa_key_attributes_t *attributes,
+    psa_key_slot_number_t *slot_number )
+{
+    if( attributes->core.flags & MBEDTLS_PSA_KA_FLAG_HAS_SLOT_NUMBER )
+    {
+        *slot_number = attributes->slot_number;
+        return( PSA_SUCCESS );
+    }
+    else
+        return( PSA_ERROR_INVALID_ARGUMENT );
+}
+#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
+
 #if defined(MBEDTLS_RSA_C) || defined(MBEDTLS_ECP_C)
 static int pk_write_pubkey_simple( mbedtls_pk_context *key,
                                    unsigned char *buf, size_t size )
@@ -1557,6 +1579,10 @@
      * 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 )