Prevent mbedtls_psa_register_se_key with volatile keys

mbedtls_psa_register_se_key() is not usable with volatile keys, since there
is no way to return the implementation-chosen key identifier which would be
needed to use the key. Document this limitation. Reject an attempt to create
such an unusable key. Fixes #9253.

Signed-off-by: Gilles Peskine <Gilles.Peskine@arm.com>
diff --git a/ChangeLog.d/mbedtls_psa_register_se_key.txt b/ChangeLog.d/mbedtls_psa_register_se_key.txt
new file mode 100644
index 0000000..2fc2751
--- /dev/null
+++ b/ChangeLog.d/mbedtls_psa_register_se_key.txt
@@ -0,0 +1,3 @@
+Bugfix
+   * Document and enforce the limitation of mbedtls_psa_register_se_key()
+     to persistent keys. Resolves #9253.
diff --git a/include/psa/crypto.h b/include/psa/crypto.h
index a2d547f..5096748 100644
--- a/include/psa/crypto.h
+++ b/include/psa/crypto.h
@@ -130,6 +130,9 @@
  *
  * \param[out] attributes  The attribute structure to write to.
  * \param key              The persistent identifier for the key.
+ *                         This can be any value in the range from
+ *                         #PSA_KEY_ID_USER_MIN to #PSA_KEY_ID_USER_MAX
+ *                         inclusive.
  */
 static void psa_set_key_id(psa_key_attributes_t *attributes,
                            mbedtls_svc_key_id_t key);
diff --git a/include/psa/crypto_extra.h b/include/psa/crypto_extra.h
index a1b2af7..4039acf 100644
--- a/include/psa/crypto_extra.h
+++ b/include/psa/crypto_extra.h
@@ -155,6 +155,14 @@
  * specified in \p attributes.
  *
  * \param[in] attributes        The attributes of the existing key.
+ *                              - The lifetime must be a persistent lifetime
+ *                                in a secure element. Volatile lifetimes are
+ *                                not currently supported.
+ *                              - The key identifier must be in the valid
+ *                                range for persistent keys.
+ *                              - The key type and size must be specified and
+ *                                must be consistent with the key material
+ *                                in the secure element.
  *
  * \retval #PSA_SUCCESS
  *         The key was successfully registered.
diff --git a/library/psa_crypto.c b/library/psa_crypto.c
index 45e1aa9..502ddc2 100644
--- a/library/psa_crypto.c
+++ b/library/psa_crypto.c
@@ -2149,6 +2149,14 @@
         return PSA_ERROR_NOT_SUPPORTED;
     }
 
+    /* Not usable with volatile keys, even with an appropriate location,
+     * due to the API design.
+     * https://github.com/Mbed-TLS/mbedtls/issues/9253
+     */
+    if (PSA_KEY_LIFETIME_IS_VOLATILE(psa_get_key_lifetime(attributes))) {
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+
     status = psa_start_key_creation(PSA_KEY_CREATION_REGISTER, attributes,
                                     &slot, &driver);
     if (status != PSA_SUCCESS) {
diff --git a/tests/suites/test_suite_psa_crypto_se_driver_hal.data b/tests/suites/test_suite_psa_crypto_se_driver_hal.data
index 2bcf4e4..dbe22b8 100644
--- a/tests/suites/test_suite_psa_crypto_se_driver_hal.data
+++ b/tests/suites/test_suite_psa_crypto_se_driver_hal.data
@@ -147,7 +147,16 @@
 Key registration: smoke test
 register_key_smoke_test:TEST_SE_PERSISTENT_LIFETIME:7:1:1:PSA_SUCCESS
 
-Key registration: invalid lifetime (volatile internal storage)
+Key registration: invalid lifetime (volatile, in SE, id=0)
+register_key_smoke_test:TEST_SE_VOLATILE_LIFETIME:7:0:0:PSA_ERROR_INVALID_ARGUMENT
+
+Key registration: invalid lifetime (volatile, in SE, id=1)
+register_key_smoke_test:TEST_SE_VOLATILE_LIFETIME:7:1:1:PSA_ERROR_INVALID_ARGUMENT
+
+Key registration: invalid lifetime (volatile, internal, id=0)
+register_key_smoke_test:PSA_KEY_LIFETIME_VOLATILE:7:0:0:PSA_ERROR_INVALID_ARGUMENT
+
+Key registration: invalid lifetime (volatile, internal, id=1)
 register_key_smoke_test:PSA_KEY_LIFETIME_VOLATILE:7:1:1:PSA_ERROR_INVALID_ARGUMENT
 
 Key registration: invalid lifetime (internal storage)