Merge remote-tracking branch 'psa/pr/230' into feature-psa

Implement a key handle mechanism
diff --git a/include/psa/crypto.h b/include/psa/crypto.h
index 1ca6492..c58d22a 100644
--- a/include/psa/crypto.h
+++ b/include/psa/crypto.h
@@ -36,19 +36,15 @@
  * @{
  */
 
-/** \brief Key slot number.
+/** \brief Key handle.
  *
- * This type represents key slots. It must be an unsigned integral
+ * This type represents open handles to keys. It must be an unsigned integral
  * type. The choice of type is implementation-dependent.
- * 0 is not a valid key slot number. The meaning of other values is
- * implementation dependent.
  *
- * At any given point in time, each key slot either contains a
- * cryptographic object, or is empty. Key slots are persistent:
- * once set, the cryptographic object remains in the key slot until
- * explicitly destroyed.
+ * 0 is not a valid key handle. How other handle values are assigned is
+ * implementation-dependent.
  */
-typedef _unsigned_integral_type_ psa_key_slot_t;
+typedef _unsigned_integral_type_ psa_key_handle_t;
 
 /**@}*/
 #endif /* __DOXYGEN_ONLY__ */
@@ -133,17 +129,17 @@
 /** A slot is occupied, but must be empty to carry out the
  * requested action.
  *
- * If the slot number is invalid (i.e. the requested action could
- * not be performed even after erasing the slot's content),
- * implementations shall return #PSA_ERROR_INVALID_ARGUMENT instead. */
+ * If a handle is invalid, it does not designate an occupied slot.
+ * The error for an invalid handle is #PSA_ERROR_INVALID_HANDLE.
+ */
 #define PSA_ERROR_OCCUPIED_SLOT         ((psa_status_t)5)
 
 /** A slot is empty, but must be occupied to carry out the
  * requested action.
  *
- * If the slot number is invalid (i.e. the requested action could
- * not be performed even after creating appropriate content in the slot),
- * implementations shall return #PSA_ERROR_INVALID_ARGUMENT instead. */
+ * If a handle is invalid, it does not designate an empty slot.
+ * The error for an invalid handle is #PSA_ERROR_INVALID_HANDLE.
+ */
 #define PSA_ERROR_EMPTY_SLOT            ((psa_status_t)6)
 
 /** The requested action cannot be performed in the current state.
@@ -166,7 +162,12 @@
  * Implementations shall not return this error code to indicate
  * that a key slot is occupied when it needs to be free or vice versa,
  * but shall return #PSA_ERROR_OCCUPIED_SLOT or #PSA_ERROR_EMPTY_SLOT
- * as applicable. */
+ * as applicable.
+ *
+ * Implementation shall not return this error code to indicate that a
+ * key handle is invalid, but shall return #PSA_ERROR_INVALID_HANDLE
+ * instead.
+ */
 #define PSA_ERROR_INVALID_ARGUMENT      ((psa_status_t)8)
 
 /** There is not enough runtime memory.
@@ -314,6 +315,10 @@
  * generator will always return this error. */
 #define PSA_ERROR_INSUFFICIENT_CAPACITY ((psa_status_t)18)
 
+/** The key handle is not valid.
+ */
+#define PSA_ERROR_INVALID_HANDLE        ((psa_status_t)19)
+
 /**
  * \brief Library initialization.
  *
@@ -1401,6 +1406,181 @@
  * @{
  */
 
+/** Encoding of key lifetimes.
+ */
+typedef uint32_t psa_key_lifetime_t;
+
+/** Encoding of identifiers of persistent keys.
+ */
+typedef uint32_t psa_key_id_t;
+
+/** A volatile key only exists as long as the handle to it is not closed.
+ * The key material is guaranteed to be erased on a power reset.
+ */
+#define PSA_KEY_LIFETIME_VOLATILE               ((psa_key_lifetime_t)0x00000000)
+
+/** The default storage area for persistent keys.
+ *
+ * A persistent key remains in storage until it is explicitly destroyed or
+ * until the corresponding storage area is wiped. This specification does
+ * not define any mechanism to wipe a storage area, but implementations may
+ * provide their own mechanism (for example to perform a factory reset,
+ * to prepare for device refurbishment, or to uninstall an application).
+ *
+ * This lifetime value is the default storage area for the calling
+ * application. Implementations may offer other storage areas designated
+ * by other lifetime values as implementation-specific extensions.
+ */
+#define PSA_KEY_LIFETIME_PERSISTENT             ((psa_key_lifetime_t)0x00000001)
+
+/** \brief Retrieve the lifetime of an open key.
+ *
+ * \param handle        Handle to query.
+ * \param[out] lifetime On success, the lifetime value.
+ *
+ * \retval #PSA_SUCCESS
+ *         Success.
+ * \retval #PSA_ERROR_INVALID_HANDLE
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval #PSA_ERROR_HARDWARE_FAILURE
+ * \retval #PSA_ERROR_TAMPERING_DETECTED
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The library has not been previously initialized by psa_crypto_init().
+ *         It is implementation-dependent whether a failure to initialize
+ *         results in this error code.
+ */
+psa_status_t psa_get_key_lifetime(psa_key_handle_t handle,
+                                  psa_key_lifetime_t *lifetime);
+
+
+/** Allocate a key slot for a transient key, i.e. a key which is only stored
+ * in volatile memory.
+ *
+ * The allocated key slot and its handle remain valid until the
+ * application calls psa_close_key() or psa_destroy_key() or until the
+ * application terminates.
+ *
+ * This function takes a key type and maximum size as arguments so that
+ * the implementation can reserve a corresponding amount of memory.
+ * Implementations are not required to enforce this limit: if the application
+ * later tries to create a larger key or a key of a different type, it
+ * is implementation-defined whether this may succeed.
+ *
+ * \param type          The type of key that the slot will contain.
+ * \param max_bits      The maximum key size that the slot will contain.
+ * \param[out] handle   On success, a handle to a volatile key slot.
+ *
+ * \retval #PSA_SUCCESS
+ *         Success. The application can now use the value of `*handle`
+ *         to access the newly allocated key slot.
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ *         There was not enough memory, or the maximum number of key slots
+ *         has been reached.
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ *         This implementation does not support this key type.
+ */
+
+psa_status_t psa_allocate_key(psa_key_type_t type,
+                              size_t max_bits,
+                              psa_key_handle_t *handle);
+
+/** Open a handle to an existing persistent key.
+ *
+ * Open a handle to a key which was previously created with psa_create_key().
+ *
+ * \param lifetime      The lifetime of the key. This designates a storage
+ *                      area where the key material is stored. This must not
+ *                      be #PSA_KEY_LIFETIME_VOLATILE.
+ * \param id            The persistent identifier of the key.
+ * \param[out] handle   On success, a handle to a key slot which contains
+ *                      the data and metadata loaded from the specified
+ *                      persistent location.
+ *
+ * \retval #PSA_SUCCESS
+ *         Success. The application can now use the value of `*handle`
+ *         to access the newly allocated key slot.
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_EMPTY_SLOT
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ *         \p lifetime is invalid, for example #PSA_KEY_LIFETIME_VOLATILE.
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ *         \p id is invalid for the specified lifetime.
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ *         \p lifetime is not supported.
+ * \retval #PSA_ERROR_NOT_PERMITTED
+ *         The specified key exists, but the application does not have the
+ *         permission to access it. Note that this specification does not
+ *         define any way to create such a key, but it may be possible
+ *         through implementation-specific means.
+ */
+psa_status_t psa_open_key(psa_key_lifetime_t lifetime,
+                          psa_key_id_t id,
+                          psa_key_handle_t *handle);
+
+/** Create a new persistent key slot.
+ *
+ * Create a new persistent key slot and return a handle to it. The handle
+ * remains valid until the application calls psa_close_key() or terminates.
+ * The application can open the key again with psa_open_key() until it
+ * removes the key by calling psa_destroy_key().
+ *
+ * \param lifetime      The lifetime of the key. This designates a storage
+ *                      area where the key material is stored. This must not
+ *                      be #PSA_KEY_LIFETIME_VOLATILE.
+ * \param id            The persistent identifier of the key.
+ * \param type          The type of key that the slot will contain.
+ * \param max_bits      The maximum key size that the slot will contain.
+ * \param[out] handle   On success, a handle to the newly created key slot.
+ *                      When key material is later created in this key slot,
+ *                      it will be saved to the specified persistent location.
+ *
+ * \retval #PSA_SUCCESS
+ *         Success. The application can now use the value of `*handle`
+ *         to access the newly allocated key slot.
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_INSUFFICIENT_STORAGE
+ * \retval #PSA_ERROR_OCCUPIED_SLOT
+ *         There is already a key with the identifier \p id in the storage
+ *         area designated by \p lifetime.
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ *         \p lifetime is invalid, for example #PSA_KEY_LIFETIME_VOLATILE.
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ *         \p id is invalid for the specified lifetime.
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ *         \p lifetime is not supported.
+ * \retval #PSA_ERROR_NOT_PERMITTED
+ *         \p lifetime is valid, but the application does not have the
+ *         permission to create a key there.
+ */
+psa_status_t psa_create_key(psa_key_lifetime_t lifetime,
+                            psa_key_id_t id,
+                            psa_key_type_t type,
+                            size_t max_bits,
+                            psa_key_handle_t *handle);
+
+/** Close a key handle.
+ *
+ * If the handle designates a volatile key, destroy the key material and
+ * free all associated resources, just like psa_destroy_key().
+ *
+ * If the handle designates a persistent key, free all resources associated
+ * with the key in volatile memory. The key slot in persistent storage is
+ * not affected and can be opened again later with psa_open_key().
+ *
+ * \param handle        The key handle to close.
+ *
+ * \retval #PSA_SUCCESS
+ * \retval #PSA_ERROR_INVALID_HANDLE
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ */
+psa_status_t psa_close_key(psa_key_handle_t handle);
+
+/**@}*/
+
+/** \defgroup import_export Key import and export
+ * @{
+ */
+
 /**
  * \brief Import a key in binary format.
  *
@@ -1416,9 +1596,12 @@
  * minimize the risk that an invalid input is accidentally interpreted
  * according to a different format.
  *
- * \param key         Slot where the key will be stored. This must be a
- *                    valid slot for a key of the chosen type. It must
- *                    be unoccupied.
+ * \param handle      Handle to the slot where the key will be stored.
+ *                    This must be a valid slot for a key of the chosen
+ *                    type: it must have been obtained by calling
+ *                    psa_allocate_key() or psa_create_key() with the
+ *                    correct \p type and with a maximum size that is
+ *                    compatible with \p data.
  * \param type        Key type (a \c PSA_KEY_TYPE_XXX value). On a successful
  *                    import, the key slot will contain a key of this type.
  * \param[in] data    Buffer containing the key data. The content of this
@@ -1430,6 +1613,9 @@
  *
  * \retval #PSA_SUCCESS
  *         Success.
+ *         If the key is persistent, the key material and the key's metadata
+ *         have been saved to persistent storage.
+ * \retval #PSA_ERROR_INVALID_HANDLE
  * \retval #PSA_ERROR_NOT_SUPPORTED
  *         The key type or key size is not supported, either by the
  *         implementation in general or in this particular slot.
@@ -1449,31 +1635,30 @@
  *         It is implementation-dependent whether a failure to initialize
  *         results in this error code.
  */
-psa_status_t psa_import_key(psa_key_slot_t key,
+psa_status_t psa_import_key(psa_key_handle_t handle,
                             psa_key_type_t type,
                             const uint8_t *data,
                             size_t data_length);
 
 /**
- * \brief Destroy a key and restore the slot to its default state.
+ * \brief Destroy a key.
  *
  * This function destroys the content of the key slot from both volatile
  * memory and, if applicable, non-volatile storage. Implementations shall
  * make a best effort to ensure that any previous content of the slot is
  * unrecoverable.
  *
- * This function also erases any metadata such as policies. It returns the
- * specified slot to its default state.
+ * This function also erases any metadata such as policies and frees all
+ * resources associated with the key.
  *
- * \param key           The key slot to erase.
+ * \param handle        Handle to the key slot to erase.
  *
  * \retval #PSA_SUCCESS
  *         The slot's content, if any, has been erased.
  * \retval #PSA_ERROR_NOT_PERMITTED
  *         The slot holds content and cannot be erased because it is
  *         read-only, either due to a policy or due to physical restrictions.
- * \retval #PSA_ERROR_INVALID_ARGUMENT
- *         The specified slot number does not designate a valid slot.
+ * \retval #PSA_ERROR_INVALID_HANDLE
  * \retval #PSA_ERROR_COMMUNICATION_FAILURE
  *         There was an failure in communication with the cryptoprocessor.
  *         The key material may still be present in the cryptoprocessor.
@@ -1491,13 +1676,12 @@
  *         It is implementation-dependent whether a failure to initialize
  *         results in this error code.
  */
-psa_status_t psa_destroy_key(psa_key_slot_t key);
+psa_status_t psa_destroy_key(psa_key_handle_t handle);
 
 /**
  * \brief Get basic metadata about a key.
  *
- * \param key           Slot whose content is queried. This must
- *                      be an occupied key slot.
+ * \param handle        Handle to the key slot to query.
  * \param[out] type     On success, the key type (a \c PSA_KEY_TYPE_XXX value).
  *                      This may be a null pointer, in which case the key type
  *                      is not written.
@@ -1506,7 +1690,9 @@
  *                      is not written.
  *
  * \retval #PSA_SUCCESS
+ * \retval #PSA_ERROR_INVALID_HANDLE
  * \retval #PSA_ERROR_EMPTY_SLOT
+ *         The handle is to a key slot which does not contain key material yet.
  * \retval #PSA_ERROR_COMMUNICATION_FAILURE
  * \retval #PSA_ERROR_HARDWARE_FAILURE
  * \retval #PSA_ERROR_TAMPERING_DETECTED
@@ -1515,7 +1701,7 @@
  *         It is implementation-dependent whether a failure to initialize
  *         results in this error code.
  */
-psa_status_t psa_get_key_information(psa_key_slot_t key,
+psa_status_t psa_get_key_information(psa_key_handle_t handle,
                                      psa_key_type_t *type,
                                      size_t *bits);
 
@@ -1581,14 +1767,14 @@
  * - For public keys (key types for which #PSA_KEY_TYPE_IS_PUBLIC_KEY is
  *   true), the format is the same as for psa_export_public_key().
  *
- * \param key               Slot whose content is to be exported. This must
- *                          be an occupied key slot.
+ * \param handle            Handle to the key to export.
  * \param[out] data         Buffer where the key data is to be written.
  * \param data_size         Size of the \p data buffer in bytes.
  * \param[out] data_length  On success, the number of bytes
  *                          that make up the key data.
  *
  * \retval #PSA_SUCCESS
+ * \retval #PSA_ERROR_INVALID_HANDLE
  * \retval #PSA_ERROR_EMPTY_SLOT
  * \retval #PSA_ERROR_NOT_PERMITTED
  * \retval #PSA_ERROR_NOT_SUPPORTED
@@ -1606,7 +1792,7 @@
  *         It is implementation-dependent whether a failure to initialize
  *         results in this error code.
  */
-psa_status_t psa_export_key(psa_key_slot_t key,
+psa_status_t psa_export_key(psa_key_handle_t handle,
                             uint8_t *data,
                             size_t data_size,
                             size_t *data_length);
@@ -1683,14 +1869,14 @@
  *      namedCurve    OBJECT IDENTIFIER }
  *   ```
  *
- * \param key               Slot whose content is to be exported. This must
- *                          be an occupied key slot.
+ * \param handle            Handle to the key to export.
  * \param[out] data         Buffer where the key data is to be written.
  * \param data_size         Size of the \p data buffer in bytes.
  * \param[out] data_length  On success, the number of bytes
  *                          that make up the key data.
  *
  * \retval #PSA_SUCCESS
+ * \retval #PSA_ERROR_INVALID_HANDLE
  * \retval #PSA_ERROR_EMPTY_SLOT
  * \retval #PSA_ERROR_INVALID_ARGUMENT
  *         The key is neither a public key nor a key pair.
@@ -1709,7 +1895,7 @@
  *         It is implementation-dependent whether a failure to initialize
  *         results in this error code.
  */
-psa_status_t psa_export_public_key(psa_key_slot_t key,
+psa_status_t psa_export_public_key(psa_key_handle_t handle,
                                    uint8_t *data,
                                    size_t data_size,
                                    size_t *data_length);
@@ -1835,10 +2021,15 @@
  * Implementations may set restrictions on supported key policies
  * depending on the key type and the key slot.
  *
- * \param key           The key slot whose policy is to be changed.
+ * \param handle        Handle to the key whose policy is to be changed.
  * \param[in] policy    The policy object to query.
  *
  * \retval #PSA_SUCCESS
+ *         Success.
+ *         If the key is persistent, it is implementation-defined whether
+ *         the policy has been saved to persistent storage. Implementations
+ *         may defer saving the policy until the key material is created.
+ * \retval #PSA_ERROR_INVALID_HANDLE
  * \retval #PSA_ERROR_OCCUPIED_SLOT
  * \retval #PSA_ERROR_NOT_SUPPORTED
  * \retval #PSA_ERROR_INVALID_ARGUMENT
@@ -1850,15 +2041,16 @@
  *         It is implementation-dependent whether a failure to initialize
  *         results in this error code.
  */
-psa_status_t psa_set_key_policy(psa_key_slot_t key,
+psa_status_t psa_set_key_policy(psa_key_handle_t handle,
                                 const psa_key_policy_t *policy);
 
 /** \brief Get the usage policy for a key slot.
  *
- * \param key           The key slot whose policy is being queried.
+ * \param handle        Handle to the key slot whose policy is being queried.
  * \param[out] policy   On success, the key's policy.
  *
  * \retval #PSA_SUCCESS
+ * \retval #PSA_ERROR_INVALID_HANDLE
  * \retval #PSA_ERROR_COMMUNICATION_FAILURE
  * \retval #PSA_ERROR_HARDWARE_FAILURE
  * \retval #PSA_ERROR_TAMPERING_DETECTED
@@ -1867,99 +2059,11 @@
  *         It is implementation-dependent whether a failure to initialize
  *         results in this error code.
  */
-psa_status_t psa_get_key_policy(psa_key_slot_t key,
+psa_status_t psa_get_key_policy(psa_key_handle_t handle,
                                 psa_key_policy_t *policy);
 
 /**@}*/
 
-/** \defgroup persistence Key lifetime
- * @{
- */
-
-/** Encoding of key lifetimes.
- */
-typedef uint32_t psa_key_lifetime_t;
-
-/** A volatile key slot retains its content as long as the application is
- * running. It is guaranteed to be erased on a power reset.
- */
-#define PSA_KEY_LIFETIME_VOLATILE               ((psa_key_lifetime_t)0x00000000)
-
-/** A persistent key slot retains its content as long as it is not explicitly
- * destroyed.
- */
-#define PSA_KEY_LIFETIME_PERSISTENT             ((psa_key_lifetime_t)0x00000001)
-
-/** A write-once key slot may not be modified once a key has been set.
- * It will retain its content as long as the device remains operational.
- */
-#define PSA_KEY_LIFETIME_WRITE_ONCE             ((psa_key_lifetime_t)0x7fffffff)
-
-/** \brief Retrieve the lifetime of a key slot.
- *
- * The assignment of lifetimes to slots is implementation-dependent.
- *
- * \param key           Slot to query.
- * \param[out] lifetime On success, the lifetime value.
- *
- * \retval #PSA_SUCCESS
- *         Success.
- * \retval #PSA_ERROR_INVALID_ARGUMENT
- *         The key slot is invalid.
- * \retval #PSA_ERROR_COMMUNICATION_FAILURE
- * \retval #PSA_ERROR_HARDWARE_FAILURE
- * \retval #PSA_ERROR_TAMPERING_DETECTED
- * \retval #PSA_ERROR_BAD_STATE
- *         The library has not been previously initialized by psa_crypto_init().
- *         It is implementation-dependent whether a failure to initialize
- *         results in this error code.
- */
-psa_status_t psa_get_key_lifetime(psa_key_slot_t key,
-                                  psa_key_lifetime_t *lifetime);
-
-/** \brief Change the lifetime of a key slot.
- *
- * Whether the lifetime of a key slot can be changed at all, and if so
- * whether the lifetime of an occupied key slot can be changed, is
- * implementation-dependent.
- *
- * When creating a persistent key, you must call this function before creating
- * the key material with psa_import_key(), psa_generate_key() or
- * psa_generator_import_key(). To open an existing persistent key, you must
- * call this function with the correct lifetime value before using the slot
- * for a cryptographic operation. Once a slot's lifetime has been set,
- * the lifetime remains associated with the slot until a subsequent call to
- * psa_set_key_lifetime(), until the key is wiped with psa_destroy_key or
- * until the application terminates (or disconnects from the cryptography
- * service, if the implementation offers such a possibility).
- *
- * \param key           Slot whose lifetime is to be changed.
- * \param lifetime      The lifetime value to set for the given key slot.
- *
- * \retval #PSA_SUCCESS
- *         Success.
- * \retval #PSA_ERROR_INVALID_ARGUMENT
- *         The key slot is invalid,
- *         or the lifetime value is invalid.
- * \retval #PSA_ERROR_NOT_SUPPORTED
- *         The implementation does not support the specified lifetime value,
- *         at least for the specified key slot.
- * \retval #PSA_ERROR_OCCUPIED_SLOT
- *         The slot contains a key, and the implementation does not support
- *         changing the lifetime of an occupied slot.
- * \retval #PSA_ERROR_COMMUNICATION_FAILURE
- * \retval #PSA_ERROR_HARDWARE_FAILURE
- * \retval #PSA_ERROR_TAMPERING_DETECTED
- * \retval #PSA_ERROR_BAD_STATE
- *         The library has not been previously initialized by psa_crypto_init().
- *         It is implementation-dependent whether a failure to initialize
- *         results in this error code.
- */
-psa_status_t psa_set_key_lifetime(psa_key_slot_t key,
-                                  psa_key_lifetime_t lifetime);
-
-/**@}*/
-
 /** \defgroup hash Message digests
  * @{
  */
@@ -2212,12 +2316,13 @@
  * - A call to psa_mac_sign_finish() or psa_mac_abort().
  *
  * \param[out] operation    The operation object to use.
- * \param key               Slot containing the key to use for the operation.
+ * \param handle            Handle to the key to use for the operation.
  * \param alg               The MAC algorithm to compute (\c PSA_ALG_XXX value
  *                          such that #PSA_ALG_IS_MAC(alg) is true).
  *
  * \retval #PSA_SUCCESS
  *         Success.
+ * \retval #PSA_ERROR_INVALID_HANDLE
  * \retval #PSA_ERROR_EMPTY_SLOT
  * \retval #PSA_ERROR_NOT_PERMITTED
  * \retval #PSA_ERROR_INVALID_ARGUMENT
@@ -2234,7 +2339,7 @@
  *         results in this error code.
  */
 psa_status_t psa_mac_sign_setup(psa_mac_operation_t *operation,
-                                psa_key_slot_t key,
+                                psa_key_handle_t handle,
                                 psa_algorithm_t alg);
 
 /** Start a multipart MAC verification operation.
@@ -2264,12 +2369,13 @@
  * - A call to psa_mac_verify_finish() or psa_mac_abort().
  *
  * \param[out] operation    The operation object to use.
- * \param key               Slot containing the key to use for the operation.
+ * \param handle            Handle to the key to use for the operation.
  * \param alg               The MAC algorithm to compute (\c PSA_ALG_XXX value
  *                          such that #PSA_ALG_IS_MAC(\p alg) is true).
  *
  * \retval #PSA_SUCCESS
  *         Success.
+ * \retval #PSA_ERROR_INVALID_HANDLE
  * \retval #PSA_ERROR_EMPTY_SLOT
  * \retval #PSA_ERROR_NOT_PERMITTED
  * \retval #PSA_ERROR_INVALID_ARGUMENT
@@ -2286,7 +2392,7 @@
  *         results in this error code.
  */
 psa_status_t psa_mac_verify_setup(psa_mac_operation_t *operation,
-                                  psa_key_slot_t key,
+                                  psa_key_handle_t handle,
                                   psa_algorithm_t alg);
 
 /** Add a message fragment to a multipart MAC operation.
@@ -2463,13 +2569,14 @@
  * - A call to psa_cipher_finish() or psa_cipher_abort().
  *
  * \param[out] operation        The operation object to use.
- * \param key                   Slot containing the key to use for the operation.
+ * \param handle                Handle to the key to use for the operation.
  * \param alg                   The cipher algorithm to compute
  *                              (\c PSA_ALG_XXX value such that
  *                              #PSA_ALG_IS_CIPHER(\p alg) is true).
  *
  * \retval #PSA_SUCCESS
  *         Success.
+ * \retval #PSA_ERROR_INVALID_HANDLE
  * \retval #PSA_ERROR_EMPTY_SLOT
  * \retval #PSA_ERROR_NOT_PERMITTED
  * \retval #PSA_ERROR_INVALID_ARGUMENT
@@ -2486,7 +2593,7 @@
  *         results in this error code.
  */
 psa_status_t psa_cipher_encrypt_setup(psa_cipher_operation_t *operation,
-                                      psa_key_slot_t key,
+                                      psa_key_handle_t handle,
                                       psa_algorithm_t alg);
 
 /** Set the key for a multipart symmetric decryption operation.
@@ -2516,13 +2623,14 @@
  * - A call to psa_cipher_finish() or psa_cipher_abort().
  *
  * \param[out] operation        The operation object to use.
- * \param key                   Slot containing the key to use for the operation.
+ * \param handle                Handle to the key to use for the operation.
  * \param alg                   The cipher algorithm to compute
  *                              (\c PSA_ALG_XXX value such that
  *                              #PSA_ALG_IS_CIPHER(\p alg) is true).
  *
  * \retval #PSA_SUCCESS
  *         Success.
+ * \retval #PSA_ERROR_INVALID_HANDLE
  * \retval #PSA_ERROR_EMPTY_SLOT
  * \retval #PSA_ERROR_NOT_PERMITTED
  * \retval #PSA_ERROR_INVALID_ARGUMENT
@@ -2539,7 +2647,7 @@
  *         results in this error code.
  */
 psa_status_t psa_cipher_decrypt_setup(psa_cipher_operation_t *operation,
-                                      psa_key_slot_t key,
+                                      psa_key_handle_t handle,
                                       psa_algorithm_t alg);
 
 /** Generate an IV for a symmetric encryption operation.
@@ -2742,7 +2850,7 @@
 
 /** Process an authenticated encryption operation.
  *
- * \param key                     Slot containing the key to use.
+ * \param handle                  Handle to the key to use for the operation.
  * \param alg                     The AEAD algorithm to compute
  *                                (\c PSA_ALG_XXX value such that
  *                                #PSA_ALG_IS_AEAD(\p alg) is true).
@@ -2770,6 +2878,7 @@
  *
  * \retval #PSA_SUCCESS
  *         Success.
+ * \retval #PSA_ERROR_INVALID_HANDLE
  * \retval #PSA_ERROR_EMPTY_SLOT
  * \retval #PSA_ERROR_NOT_PERMITTED
  * \retval #PSA_ERROR_INVALID_ARGUMENT
@@ -2785,7 +2894,7 @@
  *         It is implementation-dependent whether a failure to initialize
  *         results in this error code.
  */
-psa_status_t psa_aead_encrypt(psa_key_slot_t key,
+psa_status_t psa_aead_encrypt(psa_key_handle_t handle,
                               psa_algorithm_t alg,
                               const uint8_t *nonce,
                               size_t nonce_length,
@@ -2799,7 +2908,7 @@
 
 /** Process an authenticated decryption operation.
  *
- * \param key                     Slot containing the key to use.
+ * \param handle                  Handle to the key to use for the operation.
  * \param alg                     The AEAD algorithm to compute
  *                                (\c PSA_ALG_XXX value such that
  *                                #PSA_ALG_IS_AEAD(\p alg) is true).
@@ -2825,6 +2934,7 @@
  *
  * \retval #PSA_SUCCESS
  *         Success.
+ * \retval #PSA_ERROR_INVALID_HANDLE
  * \retval #PSA_ERROR_EMPTY_SLOT
  * \retval #PSA_ERROR_INVALID_SIGNATURE
  *         The ciphertext is not authentic.
@@ -2842,7 +2952,7 @@
  *         It is implementation-dependent whether a failure to initialize
  *         results in this error code.
  */
-psa_status_t psa_aead_decrypt(psa_key_slot_t key,
+psa_status_t psa_aead_decrypt(psa_key_handle_t handle,
                               psa_algorithm_t alg,
                               const uint8_t *nonce,
                               size_t nonce_length,
@@ -2880,7 +2990,8 @@
  * parameter to this function. You can use #PSA_ALG_SIGN_GET_HASH(\p alg)
  * to determine the hash algorithm to use.
  *
- * \param key                   Key slot containing an asymmetric key pair.
+ * \param handle                Handle to the key to use for the operation.
+ *                              It must be an asymmetric key pair.
  * \param alg                   A signature algorithm that is compatible with
  *                              the type of \p key.
  * \param[in] hash              The hash or message to sign.
@@ -2909,7 +3020,7 @@
  *         It is implementation-dependent whether a failure to initialize
  *         results in this error code.
  */
-psa_status_t psa_asymmetric_sign(psa_key_slot_t key,
+psa_status_t psa_asymmetric_sign(psa_key_handle_t handle,
                                  psa_algorithm_t alg,
                                  const uint8_t *hash,
                                  size_t hash_length,
@@ -2926,8 +3037,8 @@
  * parameter to this function. You can use #PSA_ALG_SIGN_GET_HASH(\p alg)
  * to determine the hash algorithm to use.
  *
- * \param key               Key slot containing a public key or an
- *                          asymmetric key pair.
+ * \param handle            Handle to the key to use for the operation.
+ *                          It must be a public key or an asymmetric key pair.
  * \param alg               A signature algorithm that is compatible with
  *                          the type of \p key.
  * \param[in] hash          The hash or message whose signature is to be
@@ -2952,7 +3063,7 @@
  *         It is implementation-dependent whether a failure to initialize
  *         results in this error code.
  */
-psa_status_t psa_asymmetric_verify(psa_key_slot_t key,
+psa_status_t psa_asymmetric_verify(psa_key_handle_t handle,
                                    psa_algorithm_t alg,
                                    const uint8_t *hash,
                                    size_t hash_length,
@@ -2967,8 +3078,9 @@
 /**
  * \brief Encrypt a short message with a public key.
  *
- * \param key                   Key slot containing a public key or an
- *                              asymmetric key pair.
+ * \param handle                Handle to the key to use for the operation.
+ *                              It must be a public key or an asymmetric
+ *                              key pair.
  * \param alg                   An asymmetric encryption algorithm that is
  *                              compatible with the type of \p key.
  * \param[in] input             The message to encrypt.
@@ -3010,7 +3122,7 @@
  *         It is implementation-dependent whether a failure to initialize
  *         results in this error code.
  */
-psa_status_t psa_asymmetric_encrypt(psa_key_slot_t key,
+psa_status_t psa_asymmetric_encrypt(psa_key_handle_t handle,
                                     psa_algorithm_t alg,
                                     const uint8_t *input,
                                     size_t input_length,
@@ -3023,7 +3135,8 @@
 /**
  * \brief Decrypt a short message with a private key.
  *
- * \param key                   Key slot containing an asymmetric key pair.
+ * \param handle                Handle to the key to use for the operation.
+ *                              It must be an asymmetric key pair.
  * \param alg                   An asymmetric encryption algorithm that is
  *                              compatible with the type of \p key.
  * \param[in] input             The message to decrypt.
@@ -3066,7 +3179,7 @@
  *         It is implementation-dependent whether a failure to initialize
  *         results in this error code.
  */
-psa_status_t psa_asymmetric_decrypt(psa_key_slot_t key,
+psa_status_t psa_asymmetric_decrypt(psa_key_handle_t handle,
                                     psa_algorithm_t alg,
                                     const uint8_t *input,
                                     size_t input_length,
@@ -3137,9 +3250,9 @@
  * \param[in] generator     The generator to query.
  * \param[out] capacity     On success, the capacity of the generator.
  *
- * \retval PSA_SUCCESS
- * \retval PSA_ERROR_BAD_STATE
- * \retval PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval #PSA_SUCCESS
+ * \retval #PSA_ERROR_BAD_STATE
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE
  */
 psa_status_t psa_get_generator_capacity(const psa_crypto_generator_t *generator,
                                         size_t *capacity);
@@ -3155,19 +3268,19 @@
  *                          written.
  * \param output_length     Number of bytes to output.
  *
- * \retval PSA_SUCCESS
- * \retval PSA_ERROR_INSUFFICIENT_CAPACITY
+ * \retval #PSA_SUCCESS
+ * \retval #PSA_ERROR_INSUFFICIENT_CAPACITY
  *                          There were fewer than \p output_length bytes
  *                          in the generator. Note that in this case, no
  *                          output is written to the output buffer.
  *                          The generator's capacity is set to 0, thus
  *                          subsequent calls to this function will not
  *                          succeed, even with a smaller output buffer.
- * \retval PSA_ERROR_BAD_STATE
- * \retval PSA_ERROR_INSUFFICIENT_MEMORY
- * \retval PSA_ERROR_COMMUNICATION_FAILURE
- * \retval PSA_ERROR_HARDWARE_FAILURE
- * \retval PSA_ERROR_TAMPERING_DETECTED
+ * \retval #PSA_ERROR_BAD_STATE
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval #PSA_ERROR_HARDWARE_FAILURE
+ * \retval #PSA_ERROR_TAMPERING_DETECTED
  */
 psa_status_t psa_generator_read(psa_crypto_generator_t *generator,
                                 uint8_t *output,
@@ -3185,42 +3298,47 @@
  * if the implementation provides an isolation boundary then
  * the key material is not exposed outside the isolation boundary.
  *
- * \param key               Slot where the key will be stored. This must be a
- *                          valid slot for a key of the chosen type. It must
- *                          be unoccupied.
+ * \param handle            Handle to the slot where the key will be stored.
+ *                          This must be a valid slot for a key of the chosen
+ *                          type: it must have been obtained by calling
+ *                          psa_allocate_key() or psa_create_key() with the
+ *                          correct \p type and with a maximum size that is
+ *                          compatible with \p bits.
+ *                          It must not contain any key material yet.
  * \param type              Key type (a \c PSA_KEY_TYPE_XXX value).
  *                          This must be a symmetric key type.
  * \param bits              Key size in bits.
  * \param[in,out] generator The generator object to read from.
  *
- * \retval PSA_SUCCESS
+ * \retval #PSA_SUCCESS
  *         Success.
- * \retval PSA_ERROR_INSUFFICIENT_CAPACITY
+ *         If the key is persistent, the key material and the key's metadata
+ *         have been saved to persistent storage.
+ * \retval #PSA_ERROR_INSUFFICIENT_CAPACITY
  *                          There were fewer than \p output_length bytes
  *                          in the generator. Note that in this case, no
  *                          output is written to the output buffer.
  *                          The generator's capacity is set to 0, thus
  *                          subsequent calls to this function will not
  *                          succeed, even with a smaller output buffer.
- * \retval PSA_ERROR_NOT_SUPPORTED
+ * \retval #PSA_ERROR_NOT_SUPPORTED
  *         The key type or key size is not supported, either by the
  *         implementation in general or in this particular slot.
- * \retval PSA_ERROR_BAD_STATE
- * \retval PSA_ERROR_INVALID_ARGUMENT
- *         The key slot is invalid.
- * \retval PSA_ERROR_OCCUPIED_SLOT
+ * \retval #PSA_ERROR_BAD_STATE
+ * \retval #PSA_ERROR_INVALID_HANDLE
+ * \retval #PSA_ERROR_OCCUPIED_SLOT
  *         There is already a key in the specified slot.
- * \retval PSA_ERROR_INSUFFICIENT_MEMORY
- * \retval PSA_ERROR_INSUFFICIENT_STORAGE
- * \retval PSA_ERROR_COMMUNICATION_FAILURE
- * \retval PSA_ERROR_HARDWARE_FAILURE
- * \retval PSA_ERROR_TAMPERING_DETECTED
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_INSUFFICIENT_STORAGE
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval #PSA_ERROR_HARDWARE_FAILURE
+ * \retval #PSA_ERROR_TAMPERING_DETECTED
  * \retval #PSA_ERROR_BAD_STATE
  *         The library has not been previously initialized by psa_crypto_init().
  *         It is implementation-dependent whether a failure to initialize
  *         results in this error code.
  */
-psa_status_t psa_generator_import_key(psa_key_slot_t key,
+psa_status_t psa_generator_import_key(psa_key_handle_t handle,
                                       psa_key_type_t type,
                                       size_t bits,
                                       psa_crypto_generator_t *generator);
@@ -3241,11 +3359,11 @@
  *
  * \param[in,out] generator    The generator to abort.
  *
- * \retval PSA_SUCCESS
- * \retval PSA_ERROR_BAD_STATE
- * \retval PSA_ERROR_COMMUNICATION_FAILURE
- * \retval PSA_ERROR_HARDWARE_FAILURE
- * \retval PSA_ERROR_TAMPERING_DETECTED
+ * \retval #PSA_SUCCESS
+ * \retval #PSA_ERROR_BAD_STATE
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval #PSA_ERROR_HARDWARE_FAILURE
+ * \retval #PSA_ERROR_TAMPERING_DETECTED
  */
 psa_status_t psa_generator_abort(psa_crypto_generator_t *generator);
 
@@ -3280,7 +3398,7 @@
  *                                a logical zero (`{0}`),
  *                                \c PSA_CRYPTO_GENERATOR_INIT or
  *                                psa_crypto_generator_init().
- * \param key                     Slot containing the secret key to use.
+ * \param handle                  Handle to the secret key.
  * \param alg                     The key derivation algorithm to compute
  *                                (\c PSA_ALG_XXX value such that
  *                                #PSA_ALG_IS_KEY_DERIVATION(\p alg) is true).
@@ -3293,6 +3411,7 @@
  *
  * \retval #PSA_SUCCESS
  *         Success.
+ * \retval #PSA_ERROR_INVALID_HANDLE
  * \retval #PSA_ERROR_EMPTY_SLOT
  * \retval #PSA_ERROR_NOT_PERMITTED
  * \retval #PSA_ERROR_INVALID_ARGUMENT
@@ -3310,7 +3429,7 @@
  *         results in this error code.
  */
 psa_status_t psa_key_derivation(psa_crypto_generator_t *generator,
-                                psa_key_slot_t key,
+                                psa_key_handle_t handle,
                                 psa_algorithm_t alg,
                                 const uint8_t *salt,
                                 size_t salt_length,
@@ -3333,7 +3452,7 @@
  *                                a logical zero (`{0}`),
  *                                \c PSA_CRYPTO_GENERATOR_INIT or
  *                                psa_crypto_generator_init().
- * \param private_key             Slot containing the private key to use.
+ * \param private_key             Handle to the private key to use.
  * \param[in] peer_key            Public key of the peer. It must be
  *                                in the same format that psa_import_key()
  *                                accepts. The standard formats for public
@@ -3346,6 +3465,7 @@
  *
  * \retval #PSA_SUCCESS
  *         Success.
+ * \retval #PSA_ERROR_INVALID_HANDLE
  * \retval #PSA_ERROR_EMPTY_SLOT
  * \retval #PSA_ERROR_NOT_PERMITTED
  * \retval #PSA_ERROR_INVALID_ARGUMENT
@@ -3360,7 +3480,7 @@
  * \retval #PSA_ERROR_TAMPERING_DETECTED
  */
 psa_status_t psa_key_agreement(psa_crypto_generator_t *generator,
-                               psa_key_slot_t private_key,
+                               psa_key_handle_t private_key,
                                const uint8_t *peer_key,
                                size_t peer_key_length,
                                psa_algorithm_t alg);
@@ -3409,9 +3529,13 @@
 /**
  * \brief Generate a key or key pair.
  *
- * \param key               Slot where the key will be stored. This must be a
- *                          valid slot for a key of the chosen type. It must
- *                          be unoccupied.
+ * \param handle            Handle to the slot where the key will be stored.
+ *                          This must be a valid slot for a key of the chosen
+ *                          type: it must have been obtained by calling
+ *                          psa_allocate_key() or psa_create_key() with the
+ *                          correct \p type and with a maximum size that is
+ *                          compatible with \p bits.
+ *                          It must not contain any key material yet.
  * \param type              Key type (a \c PSA_KEY_TYPE_XXX value).
  * \param bits              Key size in bits.
  * \param[in] extra         Extra parameters for key generation. The
@@ -3440,6 +3564,12 @@
  *                          \c NULL then \p extra_size must be zero.
  *
  * \retval #PSA_SUCCESS
+ *         Success.
+ *         If the key is persistent, the key material and the key's metadata
+ *         have been saved to persistent storage.
+ * \retval #PSA_ERROR_INVALID_HANDLE
+ * \retval #PSA_ERROR_OCCUPIED_SLOT
+ *         There is already a key in the specified slot.
  * \retval #PSA_ERROR_NOT_SUPPORTED
  * \retval #PSA_ERROR_INVALID_ARGUMENT
  * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
@@ -3452,7 +3582,7 @@
  *         It is implementation-dependent whether a failure to initialize
  *         results in this error code.
  */
-psa_status_t psa_generate_key(psa_key_slot_t key,
+psa_status_t psa_generate_key(psa_key_handle_t handle,
                               psa_key_type_t type,
                               size_t bits,
                               const void *extra,
diff --git a/include/psa/crypto_platform.h b/include/psa/crypto_platform.h
index 9af320d..50ca546 100644
--- a/include/psa/crypto_platform.h
+++ b/include/psa/crypto_platform.h
@@ -46,7 +46,7 @@
 /* PSA requires several types which C99 provides in stdint.h. */
 #include <stdint.h>
 
-/* Integral type representing a key slot number. */
-typedef uint16_t psa_key_slot_t;
+/* Integral type representing a key handle. */
+typedef uint16_t psa_key_handle_t;
 
 #endif /* PSA_CRYPTO_PLATFORM_H */
diff --git a/library/CMakeLists.txt b/library/CMakeLists.txt
index c8070bb..3a3f61b 100644
--- a/library/CMakeLists.txt
+++ b/library/CMakeLists.txt
@@ -54,6 +54,7 @@
     platform_util.c
     poly1305.c
     psa_crypto.c
+    psa_crypto_slot_management.c
     psa_crypto_storage.c
     psa_crypto_storage_file.c
     psa_crypto_storage_its.c
diff --git a/library/Makefile b/library/Makefile
index 95faaae..1822a24 100644
--- a/library/Makefile
+++ b/library/Makefile
@@ -83,6 +83,7 @@
 		pkcs5.o		pkparse.o	pkwrite.o	\
 		platform.o	platform_util.o	poly1305.o	\
 		psa_crypto.o					\
+		psa_crypto_slot_management.o			\
 		psa_crypto_storage.o				\
 		psa_crypto_storage_file.o			\
 		psa_crypto_storage_its.o			\
diff --git a/library/psa_crypto.c b/library/psa_crypto.c
index 8e70c41..0a47fae 100644
--- a/library/psa_crypto.c
+++ b/library/psa_crypto.c
@@ -43,7 +43,9 @@
 
 #include "psa/crypto.h"
 
+#include "psa_crypto_core.h"
 #include "psa_crypto_invasive.h"
+#include "psa_crypto_slot_management.h"
 /* Include internal declarations that are useful for implementing persistently
  * stored keys. */
 #include "psa_crypto_storage.h"
@@ -80,6 +82,7 @@
 #include "mbedtls/md_internal.h"
 #include "mbedtls/pk.h"
 #include "mbedtls/pk_internal.h"
+#include "mbedtls/platform_util.h"
 #include "mbedtls/ripemd160.h"
 #include "mbedtls/rsa.h"
 #include "mbedtls/sha1.h"
@@ -93,12 +96,6 @@
 
 #define ARRAY_LENGTH( array ) ( sizeof( array ) / sizeof( *( array ) ) )
 
-/* Implementation that should never be optimized out by the compiler */
-static void mbedtls_zeroize( void *v, size_t n )
-{
-    volatile unsigned char *p = v; while( n-- ) *p++ = 0;
-}
-
 /* constant-time buffer comparison */
 static inline int safer_memcmp( const uint8_t *a, const uint8_t *b, size_t n )
 {
@@ -117,31 +114,6 @@
 /* Global data, support functions and library management */
 /****************************************************************/
 
-/* 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
-
-typedef struct
-{
-    psa_key_type_t type;
-    psa_key_policy_t policy;
-    psa_key_lifetime_t lifetime;
-    union
-    {
-        struct raw_data
-        {
-            uint8_t *data;
-            size_t bytes;
-        } raw;
-#if defined(MBEDTLS_RSA_C)
-        mbedtls_rsa_context *rsa;
-#endif /* MBEDTLS_RSA_C */
-#if defined(MBEDTLS_ECP_C)
-        mbedtls_ecp_keypair *ecp;
-#endif /* MBEDTLS_ECP_C */
-    } data;
-} key_slot_t;
-
 static int key_type_is_raw_bytes( psa_key_type_t type )
 {
     return( PSA_KEY_TYPE_IS_UNSTRUCTURED( type ) );
@@ -158,10 +130,8 @@
     void (* entropy_free )( mbedtls_entropy_context *ctx );
     mbedtls_entropy_context entropy;
     mbedtls_ctr_drbg_context ctr_drbg;
-    key_slot_t key_slots[PSA_KEY_SLOT_COUNT];
     unsigned initialized : 1;
     unsigned rng_state : 2;
-    unsigned key_slots_initialized : 1;
 } psa_global_data_t;
 
 static psa_global_data_t global_data;
@@ -638,9 +608,12 @@
 }
 #endif /* defined(MBEDTLS_ECP_C) */
 
-static psa_status_t psa_import_key_into_slot( key_slot_t *slot,
-                                              const uint8_t *data,
-                                              size_t data_length )
+/** Import key data into a slot. `slot->type` must have been set
+ * previously. This function assumes that the slot does not contain
+ * any key material yet. On failure, the slot content is unchanged. */
+psa_status_t psa_import_key_into_slot( psa_key_slot_t *slot,
+                                       const uint8_t *data,
+                                       size_t data_length )
 {
     psa_status_t status = PSA_SUCCESS;
 
@@ -719,71 +692,17 @@
     return( PSA_SUCCESS );
 }
 
-#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C)
-static psa_status_t psa_load_persistent_key_into_slot( psa_key_slot_t key,
-                                                       key_slot_t *p_slot )
-{
-    psa_status_t status = PSA_SUCCESS;
-    uint8_t *key_data = NULL;
-    size_t key_data_length = 0;
-
-    status = psa_load_persistent_key( key, &( p_slot )->type,
-                                      &( p_slot )->policy, &key_data,
-                                      &key_data_length );
-    if( status != PSA_SUCCESS )
-        goto exit;
-    status = psa_import_key_into_slot( p_slot,
-                                       key_data, key_data_length );
-exit:
-    psa_free_persistent_key_data( key_data, key_data_length );
-    return( status );
-}
-#endif /* defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) */
-
-/* Retrieve a key slot, occupied or not. */
-static psa_status_t psa_get_key_slot( psa_key_slot_t key,
-                                      key_slot_t **p_slot )
-{
-    GUARD_MODULE_INITIALIZED;
-
-    /* 0 is not a valid slot number under any circumstance. This
-     * implementation provides slots number 1 to N where N is the
-     * number of available slots. */
-    if( key == 0 || key > ARRAY_LENGTH( global_data.key_slots ) )
-        return( PSA_ERROR_INVALID_ARGUMENT );
-
-    *p_slot = &global_data.key_slots[key - 1];
-
-#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C)
-    if( ( *p_slot )->lifetime == PSA_KEY_LIFETIME_PERSISTENT )
-    {
-        /* There are two circumstances this can occur: the key material has
-         * not yet been created, or the key exists in storage but has not yet
-         * been loaded into memory. */
-        if( ( *p_slot )->type == PSA_KEY_TYPE_NONE )
-        {
-            psa_status_t status = PSA_SUCCESS;
-            status = psa_load_persistent_key_into_slot( key, *p_slot );
-            if( status != PSA_ERROR_EMPTY_SLOT )
-                return( status );
-        }
-    }
-#endif /* defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) */
-
-    return( PSA_SUCCESS );
-}
-
 /* Retrieve an empty key slot (slot with no key data, but possibly
  * with some metadata such as a policy). */
-static psa_status_t psa_get_empty_key_slot( psa_key_slot_t key,
-                                            key_slot_t **p_slot )
+static psa_status_t psa_get_empty_key_slot( psa_key_handle_t handle,
+                                            psa_key_slot_t **p_slot )
 {
     psa_status_t status;
-    key_slot_t *slot = NULL;
+    psa_key_slot_t *slot = NULL;
 
     *p_slot = NULL;
 
-    status = psa_get_key_slot( key, &slot );
+    status = psa_get_key_slot( handle, &slot );
     if( status != PSA_SUCCESS )
         return( status );
 
@@ -797,17 +716,17 @@
 /** Retrieve a slot which must contain a key. The key must have allow all the
  * usage flags set in \p usage. If \p alg is nonzero, the key must allow
  * operations with this algorithm. */
-static psa_status_t psa_get_key_from_slot( psa_key_slot_t key,
-                                           key_slot_t **p_slot,
+static psa_status_t psa_get_key_from_slot( psa_key_handle_t handle,
+                                           psa_key_slot_t **p_slot,
                                            psa_key_usage_t usage,
                                            psa_algorithm_t alg )
 {
     psa_status_t status;
-    key_slot_t *slot = NULL;
+    psa_key_slot_t *slot = NULL;
 
     *p_slot = NULL;
 
-    status = psa_get_key_slot( key, &slot );
+    status = psa_get_key_slot( handle, &slot );
     if( status != PSA_SUCCESS )
         return( status );
     if( slot->type == PSA_KEY_TYPE_NONE )
@@ -828,7 +747,8 @@
     return( PSA_SUCCESS );
 }
 
-static psa_status_t psa_remove_key_data_from_memory( key_slot_t *slot )
+/** Wipe key data from a slot. Preserve metadata such as the policy. */
+static psa_status_t psa_remove_key_data_from_memory( psa_key_slot_t *slot )
 {
     if( slot->type == PSA_KEY_TYPE_NONE )
     {
@@ -864,15 +784,27 @@
     return( PSA_SUCCESS );
 }
 
-psa_status_t psa_import_key( psa_key_slot_t key,
+/** Completely wipe a slot in memory, including its policy.
+ * Persistent storage is not affected. */
+psa_status_t psa_wipe_key_slot( psa_key_slot_t *slot )
+{
+    psa_status_t status = psa_remove_key_data_from_memory( slot );
+    /* At this point, key material and other type-specific content has
+     * been wiped. Clear remaining metadata. We can call memset and not
+     * zeroize because the metadata is not particularly sensitive. */
+    memset( slot, 0, sizeof( *slot ) );
+    return( status );
+}
+
+psa_status_t psa_import_key( psa_key_handle_t handle,
                              psa_key_type_t type,
                              const uint8_t *data,
                              size_t data_length )
 {
-    key_slot_t *slot;
+    psa_key_slot_t *slot;
     psa_status_t status;
 
-    status = psa_get_empty_key_slot( key, &slot );
+    status = psa_get_empty_key_slot( handle, &slot );
     if( status != PSA_SUCCESS )
         return( status );
 
@@ -889,7 +821,8 @@
     if( slot->lifetime == PSA_KEY_LIFETIME_PERSISTENT )
     {
         /* Store in file location */
-        status = psa_save_persistent_key( key, slot->type, &slot->policy, data,
+        status = psa_save_persistent_key( slot->persistent_storage_id,
+                                          slot->type, &slot->policy, data,
                                           data_length );
         if( status != PSA_SUCCESS )
         {
@@ -902,31 +835,30 @@
     return( status );
 }
 
-psa_status_t psa_destroy_key( psa_key_slot_t key )
+psa_status_t psa_destroy_key( psa_key_handle_t handle )
 {
-    key_slot_t *slot;
+    psa_key_slot_t *slot;
     psa_status_t status = PSA_SUCCESS;
     psa_status_t storage_status = PSA_SUCCESS;
 
-    status = psa_get_key_slot( key, &slot );
+    status = psa_get_key_slot( handle, &slot );
     if( status != PSA_SUCCESS )
         return( status );
 #if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C)
     if( slot->lifetime == PSA_KEY_LIFETIME_PERSISTENT )
     {
-        storage_status = psa_destroy_persistent_key( key );
+        storage_status =
+            psa_destroy_persistent_key( slot->persistent_storage_id );
     }
 #endif /* defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) */
-    status = psa_remove_key_data_from_memory( slot );
-    /* Zeroize the slot to wipe metadata such as policies. */
-    mbedtls_zeroize( slot, sizeof( *slot ) );
+    status = psa_wipe_key_slot( slot );
     if( status != PSA_SUCCESS )
         return( status );
     return( storage_status );
 }
 
 /* Return the size of the key in the given slot, in bits. */
-static size_t psa_get_key_bits( const key_slot_t *slot )
+static size_t psa_get_key_bits( const psa_key_slot_t *slot )
 {
     if( key_type_is_raw_bytes( slot->type ) )
         return( slot->data.raw.bytes * 8 );
@@ -942,18 +874,18 @@
     return( 0 );
 }
 
-psa_status_t psa_get_key_information( psa_key_slot_t key,
+psa_status_t psa_get_key_information( psa_key_handle_t handle,
                                       psa_key_type_t *type,
                                       size_t *bits )
 {
-    key_slot_t *slot;
+    psa_key_slot_t *slot;
     psa_status_t status;
 
     if( type != NULL )
         *type = 0;
     if( bits != NULL )
         *bits = 0;
-    status = psa_get_key_slot( key, &slot );
+    status = psa_get_key_slot( handle, &slot );
     if( status != PSA_SUCCESS )
         return( status );
 
@@ -966,7 +898,7 @@
     return( PSA_SUCCESS );
 }
 
-static  psa_status_t psa_internal_export_key( key_slot_t *slot,
+static  psa_status_t psa_internal_export_key( psa_key_slot_t *slot,
                                               uint8_t *data,
                                               size_t data_size,
                                               size_t *data_length,
@@ -1074,12 +1006,12 @@
     }
 }
 
-psa_status_t psa_export_key( psa_key_slot_t key,
+psa_status_t psa_export_key( psa_key_handle_t handle,
                              uint8_t *data,
                              size_t data_size,
                              size_t *data_length )
 {
-    key_slot_t *slot;
+    psa_key_slot_t *slot;
     psa_status_t status;
 
     /* Set the key to empty now, so that even when there are errors, we always
@@ -1091,19 +1023,19 @@
     /* Export requires the EXPORT flag. There is an exception for public keys,
      * which don't require any flag, but psa_get_key_from_slot takes
      * care of this. */
-    status = psa_get_key_from_slot( key, &slot, PSA_KEY_USAGE_EXPORT, 0 );
+    status = psa_get_key_from_slot( handle, &slot, PSA_KEY_USAGE_EXPORT, 0 );
     if( status != PSA_SUCCESS )
         return( status );
     return( psa_internal_export_key( slot, data, data_size,
                                      data_length, 0 ) );
 }
 
-psa_status_t psa_export_public_key( psa_key_slot_t key,
+psa_status_t psa_export_public_key( psa_key_handle_t handle,
                                     uint8_t *data,
                                     size_t data_size,
                                     size_t *data_length )
 {
-    key_slot_t *slot;
+    psa_key_slot_t *slot;
     psa_status_t status;
 
     /* Set the key to empty now, so that even when there are errors, we always
@@ -1113,7 +1045,7 @@
     *data_length = 0;
 
     /* Exporting a public key doesn't require a usage flag. */
-    status = psa_get_key_from_slot( key, &slot, 0, 0 );
+    status = psa_get_key_from_slot( handle, &slot, 0, 0 );
     if( status != PSA_SUCCESS )
         return( status );
     return( psa_internal_export_key( slot, data, data_size,
@@ -1121,8 +1053,7 @@
 }
 
 #if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C)
-static psa_status_t psa_save_generated_persistent_key( psa_key_slot_t key,
-                                                       key_slot_t *slot,
+static psa_status_t psa_save_generated_persistent_key( psa_key_slot_t *slot,
                                                        size_t bits )
 {
     psa_status_t status;
@@ -1140,14 +1071,15 @@
         goto exit;
     }
     /* Store in file location */
-    status = psa_save_persistent_key( key, slot->type, &slot->policy,
+    status = psa_save_persistent_key( slot->persistent_storage_id,
+                                      slot->type, &slot->policy,
                                       data, key_length );
     if( status != PSA_SUCCESS )
     {
         slot->type = PSA_KEY_TYPE_NONE;
     }
 exit:
-    mbedtls_zeroize( data, key_length );
+    mbedtls_platform_zeroize( data, key_length );
     mbedtls_free( data );
     return( status );
 }
@@ -1654,7 +1586,7 @@
 #if defined(MBEDTLS_MD_C)
 static psa_status_t psa_hmac_abort_internal( psa_hmac_internal_data *hmac )
 {
-    mbedtls_zeroize( hmac->opad, sizeof( hmac->opad ) );
+    mbedtls_platform_zeroize( hmac->opad, sizeof( hmac->opad ) );
     return( psa_hash_abort( &hmac->hash_ctx ) );
 }
 
@@ -1716,7 +1648,7 @@
 #if defined(MBEDTLS_CMAC_C)
 static int psa_cmac_setup( psa_mac_operation_t *operation,
                            size_t key_bits,
-                           key_slot_t *slot,
+                           psa_key_slot_t *slot,
                            const mbedtls_cipher_info_t *cipher_info )
 {
     int ret;
@@ -1798,19 +1730,19 @@
     status = psa_hash_update( &hmac->hash_ctx, ipad, block_size );
 
 cleanup:
-    mbedtls_zeroize( ipad, key_length );
+    mbedtls_platform_zeroize( ipad, key_length );
 
     return( status );
 }
 #endif /* MBEDTLS_MD_C */
 
 static psa_status_t psa_mac_setup( psa_mac_operation_t *operation,
-                                   psa_key_slot_t key,
+                                   psa_key_handle_t handle,
                                    psa_algorithm_t alg,
                                    int is_sign )
 {
     psa_status_t status;
-    key_slot_t *slot;
+    psa_key_slot_t *slot;
     size_t key_bits;
     psa_key_usage_t usage =
         is_sign ? PSA_KEY_USAGE_SIGN : PSA_KEY_USAGE_VERIFY;
@@ -1823,7 +1755,7 @@
     if( is_sign )
         operation->is_sign = 1;
 
-    status = psa_get_key_from_slot( key, &slot, usage, alg );
+    status = psa_get_key_from_slot( handle, &slot, usage, alg );
     if( status != PSA_SUCCESS )
         goto exit;
     key_bits = psa_get_key_bits( slot );
@@ -1916,17 +1848,17 @@
 }
 
 psa_status_t psa_mac_sign_setup( psa_mac_operation_t *operation,
-                                 psa_key_slot_t key,
+                                 psa_key_handle_t handle,
                                  psa_algorithm_t alg )
 {
-    return( psa_mac_setup( operation, key, alg, 1 ) );
+    return( psa_mac_setup( operation, handle, alg, 1 ) );
 }
 
 psa_status_t psa_mac_verify_setup( psa_mac_operation_t *operation,
-                                   psa_key_slot_t key,
+                                   psa_key_handle_t handle,
                                    psa_algorithm_t alg )
 {
-    return( psa_mac_setup( operation, key, alg, 0 ) );
+    return( psa_mac_setup( operation, handle, alg, 0 ) );
 }
 
 psa_status_t psa_mac_update( psa_mac_operation_t *operation,
@@ -2004,7 +1936,7 @@
     memcpy( mac, tmp, mac_size );
 
 exit:
-    mbedtls_zeroize( tmp, hash_size );
+    mbedtls_platform_zeroize( tmp, hash_size );
     return( status );
 }
 #endif /* MBEDTLS_MD_C */
@@ -2028,7 +1960,7 @@
         int ret = mbedtls_cipher_cmac_finish( &operation->ctx.cmac, tmp );
         if( ret == 0 )
             memcpy( mac, tmp, operation->mac_size );
-        mbedtls_zeroize( tmp, sizeof( tmp ) );
+        mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
         return( mbedtls_to_psa_error( ret ) );
     }
     else
@@ -2116,7 +2048,7 @@
     else
         psa_mac_abort( operation );
 
-    mbedtls_zeroize( actual_mac, sizeof( actual_mac ) );
+    mbedtls_platform_zeroize( actual_mac, sizeof( actual_mac ) );
 
     return( status );
 }
@@ -2383,7 +2315,7 @@
 }
 #endif /* MBEDTLS_ECDSA_C */
 
-psa_status_t psa_asymmetric_sign( psa_key_slot_t key,
+psa_status_t psa_asymmetric_sign( psa_key_handle_t handle,
                                   psa_algorithm_t alg,
                                   const uint8_t *hash,
                                   size_t hash_length,
@@ -2391,12 +2323,12 @@
                                   size_t signature_size,
                                   size_t *signature_length )
 {
-    key_slot_t *slot;
+    psa_key_slot_t *slot;
     psa_status_t status;
 
     *signature_length = signature_size;
 
-    status = psa_get_key_from_slot( key, &slot, PSA_KEY_USAGE_SIGN, alg );
+    status = psa_get_key_from_slot( handle, &slot, PSA_KEY_USAGE_SIGN, alg );
     if( status != PSA_SUCCESS )
         goto exit;
     if( ! PSA_KEY_TYPE_IS_KEYPAIR( slot->type ) )
@@ -2459,17 +2391,17 @@
     return( status );
 }
 
-psa_status_t psa_asymmetric_verify( psa_key_slot_t key,
+psa_status_t psa_asymmetric_verify( psa_key_handle_t handle,
                                     psa_algorithm_t alg,
                                     const uint8_t *hash,
                                     size_t hash_length,
                                     const uint8_t *signature,
                                     size_t signature_length )
 {
-    key_slot_t *slot;
+    psa_key_slot_t *slot;
     psa_status_t status;
 
-    status = psa_get_key_from_slot( key, &slot, PSA_KEY_USAGE_VERIFY, alg );
+    status = psa_get_key_from_slot( handle, &slot, PSA_KEY_USAGE_VERIFY, alg );
     if( status != PSA_SUCCESS )
         return( status );
 
@@ -2515,7 +2447,7 @@
 }
 #endif /* defined(MBEDTLS_RSA_C) && defined(MBEDTLS_PKCS1_V21) */
 
-psa_status_t psa_asymmetric_encrypt( psa_key_slot_t key,
+psa_status_t psa_asymmetric_encrypt( psa_key_handle_t handle,
                                      psa_algorithm_t alg,
                                      const uint8_t *input,
                                      size_t input_length,
@@ -2525,7 +2457,7 @@
                                      size_t output_size,
                                      size_t *output_length )
 {
-    key_slot_t *slot;
+    psa_key_slot_t *slot;
     psa_status_t status;
 
     (void) input;
@@ -2539,7 +2471,7 @@
     if( ! PSA_ALG_IS_RSA_OAEP( alg ) && salt_length != 0 )
         return( PSA_ERROR_INVALID_ARGUMENT );
 
-    status = psa_get_key_from_slot( key, &slot, PSA_KEY_USAGE_ENCRYPT, alg );
+    status = psa_get_key_from_slot( handle, &slot, PSA_KEY_USAGE_ENCRYPT, alg );
     if( status != PSA_SUCCESS )
         return( status );
     if( ! ( PSA_KEY_TYPE_IS_PUBLIC_KEY( slot->type ) ||
@@ -2595,7 +2527,7 @@
     }
 }
 
-psa_status_t psa_asymmetric_decrypt( psa_key_slot_t key,
+psa_status_t psa_asymmetric_decrypt( psa_key_handle_t handle,
                                      psa_algorithm_t alg,
                                      const uint8_t *input,
                                      size_t input_length,
@@ -2605,7 +2537,7 @@
                                      size_t output_size,
                                      size_t *output_length )
 {
-    key_slot_t *slot;
+    psa_key_slot_t *slot;
     psa_status_t status;
 
     (void) input;
@@ -2619,7 +2551,7 @@
     if( ! PSA_ALG_IS_RSA_OAEP( alg ) && salt_length != 0 )
         return( PSA_ERROR_INVALID_ARGUMENT );
 
-    status = psa_get_key_from_slot( key, &slot, PSA_KEY_USAGE_DECRYPT, alg );
+    status = psa_get_key_from_slot( handle, &slot, PSA_KEY_USAGE_DECRYPT, alg );
     if( status != PSA_SUCCESS )
         return( status );
     if( ! PSA_KEY_TYPE_IS_KEYPAIR( slot->type ) )
@@ -2705,13 +2637,13 @@
 }
 
 static psa_status_t psa_cipher_setup( psa_cipher_operation_t *operation,
-                                      psa_key_slot_t key,
+                                      psa_key_handle_t handle,
                                       psa_algorithm_t alg,
                                       mbedtls_operation_t cipher_operation )
 {
     int ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
     psa_status_t status;
-    key_slot_t *slot;
+    psa_key_slot_t *slot;
     size_t key_bits;
     const mbedtls_cipher_info_t *cipher_info = NULL;
     psa_key_usage_t usage = ( cipher_operation == MBEDTLS_ENCRYPT ?
@@ -2722,7 +2654,7 @@
     if( status != PSA_SUCCESS )
         return( status );
 
-    status = psa_get_key_from_slot( key, &slot, usage, alg);
+    status = psa_get_key_from_slot( handle, &slot, usage, alg);
     if( status != PSA_SUCCESS )
         return( status );
     key_bits = psa_get_key_bits( slot );
@@ -2797,17 +2729,17 @@
 }
 
 psa_status_t psa_cipher_encrypt_setup( psa_cipher_operation_t *operation,
-                                       psa_key_slot_t key,
+                                       psa_key_handle_t handle,
                                        psa_algorithm_t alg )
 {
-    return( psa_cipher_setup( operation, key, alg, MBEDTLS_ENCRYPT ) );
+    return( psa_cipher_setup( operation, handle, alg, MBEDTLS_ENCRYPT ) );
 }
 
 psa_status_t psa_cipher_decrypt_setup( psa_cipher_operation_t *operation,
-                                       psa_key_slot_t key,
+                                       psa_key_handle_t handle,
                                        psa_algorithm_t alg )
 {
-    return( psa_cipher_setup( operation, key, alg, MBEDTLS_DECRYPT ) );
+    return( psa_cipher_setup( operation, handle, alg, MBEDTLS_DECRYPT ) );
 }
 
 psa_status_t psa_cipher_generate_iv( psa_cipher_operation_t *operation,
@@ -2957,7 +2889,7 @@
         goto error;
     }
 
-    mbedtls_zeroize( temp_output_buffer, sizeof( temp_output_buffer ) );
+    mbedtls_platform_zeroize( temp_output_buffer, sizeof( temp_output_buffer ) );
     status = psa_cipher_abort( operation );
 
     return( status );
@@ -2966,7 +2898,7 @@
 
     *output_length = 0;
 
-    mbedtls_zeroize( temp_output_buffer, sizeof( temp_output_buffer ) );
+    mbedtls_platform_zeroize( temp_output_buffer, sizeof( temp_output_buffer ) );
     (void) psa_cipher_abort( operation );
 
     return( status );
@@ -3030,16 +2962,16 @@
 }
 #endif /* !defined(MBEDTLS_PSA_CRYPTO_SPM) */
 
-psa_status_t psa_set_key_policy( psa_key_slot_t key,
+psa_status_t psa_set_key_policy( psa_key_handle_t handle,
                                  const psa_key_policy_t *policy )
 {
-    key_slot_t *slot;
+    psa_key_slot_t *slot;
     psa_status_t status;
 
     if( policy == NULL )
         return( PSA_ERROR_INVALID_ARGUMENT );
 
-    status = psa_get_empty_key_slot( key, &slot );
+    status = psa_get_empty_key_slot( handle, &slot );
     if( status != PSA_SUCCESS )
         return( status );
 
@@ -3056,16 +2988,16 @@
     return( PSA_SUCCESS );
 }
 
-psa_status_t psa_get_key_policy( psa_key_slot_t key,
+psa_status_t psa_get_key_policy( psa_key_handle_t handle,
                                  psa_key_policy_t *policy )
 {
-    key_slot_t *slot;
+    psa_key_slot_t *slot;
     psa_status_t status;
 
     if( policy == NULL )
         return( PSA_ERROR_INVALID_ARGUMENT );
 
-    status = psa_get_key_slot( key, &slot );
+    status = psa_get_key_slot( handle, &slot );
     if( status != PSA_SUCCESS )
         return( status );
 
@@ -3080,13 +3012,13 @@
 /* Key Lifetime */
 /****************************************************************/
 
-psa_status_t psa_get_key_lifetime( psa_key_slot_t key,
+psa_status_t psa_get_key_lifetime( psa_key_handle_t handle,
                                    psa_key_lifetime_t *lifetime )
 {
-    key_slot_t *slot;
+    psa_key_slot_t *slot;
     psa_status_t status;
 
-    status = psa_get_key_slot( key, &slot );
+    status = psa_get_key_slot( handle, &slot );
     if( status != PSA_SUCCESS )
         return( status );
 
@@ -3095,34 +3027,6 @@
     return( PSA_SUCCESS );
 }
 
-psa_status_t psa_set_key_lifetime( psa_key_slot_t key,
-                                   psa_key_lifetime_t lifetime )
-{
-    key_slot_t *slot;
-    psa_status_t status;
-
-    if( lifetime != PSA_KEY_LIFETIME_VOLATILE &&
-        lifetime != PSA_KEY_LIFETIME_PERSISTENT &&
-        lifetime != PSA_KEY_LIFETIME_WRITE_ONCE )
-        return( PSA_ERROR_INVALID_ARGUMENT );
-
-    status = psa_get_empty_key_slot( key, &slot );
-    if( status != PSA_SUCCESS )
-        return( status );
-
-    if( lifetime == PSA_KEY_LIFETIME_WRITE_ONCE )
-        return( PSA_ERROR_NOT_SUPPORTED );
-
-#if !defined(MBEDTLS_PSA_CRYPTO_STORAGE_C)
-    if( lifetime == PSA_KEY_LIFETIME_PERSISTENT )
-        return( PSA_ERROR_NOT_SUPPORTED );
-#endif
-
-    slot->lifetime = lifetime;
-
-    return( PSA_SUCCESS );
-}
-
 
 
 /****************************************************************/
@@ -3131,7 +3035,7 @@
 
 typedef struct
 {
-    key_slot_t *slot;
+    psa_key_slot_t *slot;
     const mbedtls_cipher_info_t *cipher_info;
     union
     {
@@ -3165,7 +3069,7 @@
 }
 
 static psa_status_t psa_aead_setup( aead_operation_t *operation,
-                                    psa_key_slot_t key,
+                                    psa_key_handle_t handle,
                                     psa_key_usage_t usage,
                                     psa_algorithm_t alg )
 {
@@ -3173,7 +3077,7 @@
     size_t key_bits;
     mbedtls_cipher_id_t cipher_id;
 
-    status = psa_get_key_from_slot( key, &operation->slot, usage, alg );
+    status = psa_get_key_from_slot( handle, &operation->slot, usage, alg );
     if( status != PSA_SUCCESS )
         return( status );
 
@@ -3238,7 +3142,7 @@
     return( status );
 }
 
-psa_status_t psa_aead_encrypt( psa_key_slot_t key,
+psa_status_t psa_aead_encrypt( psa_key_handle_t handle,
                                psa_algorithm_t alg,
                                const uint8_t *nonce,
                                size_t nonce_length,
@@ -3256,7 +3160,7 @@
 
     *ciphertext_length = 0;
 
-    status = psa_aead_setup( &operation, key, PSA_KEY_USAGE_ENCRYPT, alg );
+    status = psa_aead_setup( &operation, handle, PSA_KEY_USAGE_ENCRYPT, alg );
     if( status != PSA_SUCCESS )
         return( status );
 
@@ -3332,7 +3236,7 @@
     return( PSA_SUCCESS );
 }
 
-psa_status_t psa_aead_decrypt( psa_key_slot_t key,
+psa_status_t psa_aead_decrypt( psa_key_handle_t handle,
                                psa_algorithm_t alg,
                                const uint8_t *nonce,
                                size_t nonce_length,
@@ -3350,7 +3254,7 @@
 
     *plaintext_length = 0;
 
-    status = psa_aead_setup( &operation, key, PSA_KEY_USAGE_DECRYPT, alg );
+    status = psa_aead_setup( &operation, handle, PSA_KEY_USAGE_DECRYPT, alg );
     if( status != PSA_SUCCESS )
         return( status );
 
@@ -3428,7 +3332,7 @@
     {
         if( generator->ctx.buffer.data != NULL )
         {
-            mbedtls_zeroize( generator->ctx.buffer.data,
+            mbedtls_platform_zeroize( generator->ctx.buffer.data,
                              generator->ctx.buffer.size );
             mbedtls_free( generator->ctx.buffer.data );
         }
@@ -3446,14 +3350,14 @@
     {
         if( generator->ctx.tls12_prf.key != NULL )
         {
-            mbedtls_zeroize( generator->ctx.tls12_prf.key,
+            mbedtls_platform_zeroize( generator->ctx.tls12_prf.key,
                              generator->ctx.tls12_prf.key_len );
             mbedtls_free( generator->ctx.tls12_prf.key );
         }
 
         if( generator->ctx.tls12_prf.Ai_with_seed != NULL )
         {
-            mbedtls_zeroize( generator->ctx.tls12_prf.Ai_with_seed,
+            mbedtls_platform_zeroize( generator->ctx.tls12_prf.Ai_with_seed,
                              generator->ctx.tls12_prf.Ai_with_seed_len );
             mbedtls_free( generator->ctx.tls12_prf.Ai_with_seed );
         }
@@ -3779,7 +3683,7 @@
 }
 #endif /* MBEDTLS_DES_C */
 
-psa_status_t psa_generator_import_key( psa_key_slot_t key,
+psa_status_t psa_generator_import_key( psa_key_handle_t handle,
                                        psa_key_type_t type,
                                        size_t bits,
                                        psa_crypto_generator_t *generator )
@@ -3803,7 +3707,7 @@
     if( type == PSA_KEY_TYPE_DES )
         psa_des_set_key_parity( data, bytes );
 #endif /* MBEDTLS_DES_C */
-    status = psa_import_key( key, type, data, bytes );
+    status = psa_import_key( handle, type, data, bytes );
 
 exit:
     mbedtls_free( data );
@@ -3955,7 +3859,7 @@
                                             salt, salt_length,
                                             label, label_length );
 
-    mbedtls_zeroize( pms, sizeof( pms ) );
+    mbedtls_platform_zeroize( pms, sizeof( pms ) );
     return( status );
 }
 #endif /* MBEDTLS_MD_C */
@@ -4060,7 +3964,7 @@
 }
 
 psa_status_t psa_key_derivation( psa_crypto_generator_t *generator,
-                                 psa_key_slot_t key,
+                                 psa_key_handle_t handle,
                                  psa_algorithm_t alg,
                                  const uint8_t *salt,
                                  size_t salt_length,
@@ -4068,7 +3972,7 @@
                                  size_t label_length,
                                  size_t capacity )
 {
-    key_slot_t *slot;
+    psa_key_slot_t *slot;
     psa_status_t status;
 
     if( generator->alg != 0 )
@@ -4080,7 +3984,7 @@
     if( ! PSA_ALG_IS_KEY_DERIVATION( alg ) )
         return( PSA_ERROR_INVALID_ARGUMENT );
 
-    status = psa_get_key_from_slot( key, &slot, PSA_KEY_USAGE_DERIVE, alg );
+    status = psa_get_key_from_slot( handle, &slot, PSA_KEY_USAGE_DERIVE, alg );
     if( status != PSA_SUCCESS )
         return( status );
 
@@ -4165,7 +4069,7 @@
  * to potentially free embedded data structures and wipe confidential data.
  */
 static psa_status_t psa_key_agreement_internal( psa_crypto_generator_t *generator,
-                                                key_slot_t *private_key,
+                                                psa_key_slot_t *private_key,
                                                 const uint8_t *peer_key,
                                                 size_t peer_key_length,
                                                 psa_algorithm_t alg )
@@ -4206,17 +4110,17 @@
                                           NULL, 0, NULL, 0,
                                           PSA_GENERATOR_UNBRIDLED_CAPACITY );
 exit:
-    mbedtls_zeroize( shared_secret, shared_secret_length );
+    mbedtls_platform_zeroize( shared_secret, shared_secret_length );
     return( status );
 }
 
 psa_status_t psa_key_agreement( psa_crypto_generator_t *generator,
-                                psa_key_slot_t private_key,
+                                psa_key_handle_t private_key,
                                 const uint8_t *peer_key,
                                 size_t peer_key_length,
                                 psa_algorithm_t alg )
 {
-    key_slot_t *slot;
+    psa_key_slot_t *slot;
     psa_status_t status;
     if( ! PSA_ALG_IS_KEY_AGREEMENT( alg ) )
         return( PSA_ERROR_INVALID_ARGUMENT );
@@ -4316,19 +4220,19 @@
 }
 #endif
 
-psa_status_t psa_generate_key( psa_key_slot_t key,
+psa_status_t psa_generate_key( psa_key_handle_t handle,
                                psa_key_type_t type,
                                size_t bits,
                                const void *extra,
                                size_t extra_size )
 {
-    key_slot_t *slot;
+    psa_key_slot_t *slot;
     psa_status_t status;
 
     if( extra == NULL && extra_size != 0 )
         return( PSA_ERROR_INVALID_ARGUMENT );
 
-    status = psa_get_empty_key_slot( key, &slot );
+    status = psa_get_empty_key_slot( handle, &slot );
     if( status != PSA_SUCCESS )
         return( status );
 
@@ -4437,7 +4341,7 @@
 #if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C)
     if( slot->lifetime == PSA_KEY_LIFETIME_PERSISTENT )
     {
-        return( psa_save_generated_persistent_key( key, slot, bits ) );
+        return( psa_save_generated_persistent_key( slot, bits ) );
     }
 #endif /* defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) */
 
@@ -4462,21 +4366,7 @@
 
 void mbedtls_psa_crypto_free( void )
 {
-    psa_key_slot_t key;
-    key_slot_t *slot;
-    psa_status_t status;
-    if( global_data.key_slots_initialized )
-    {
-        for( key = 1; key <= PSA_KEY_SLOT_COUNT; key++ )
-        {
-            status = psa_get_key_slot( key, &slot );
-            if( status != PSA_SUCCESS )
-                continue;
-            psa_remove_key_data_from_memory( slot );
-            /* Zeroize the slot to wipe metadata such as policies. */
-            mbedtls_zeroize( slot, sizeof( *slot ) );
-        }
-    }
+    psa_wipe_all_key_slots( );
     if( global_data.rng_state != RNG_NOT_INITIALIZED )
     {
         mbedtls_ctr_drbg_free( &global_data.ctr_drbg );
@@ -4485,12 +4375,12 @@
     /* Wipe all remaining data, including configuration.
      * In particular, this sets all state indicator to the value
      * indicating "uninitialized". */
-    mbedtls_zeroize( &global_data, sizeof( global_data ) );
+    mbedtls_platform_zeroize( &global_data, sizeof( global_data ) );
 }
 
 psa_status_t psa_crypto_init( void )
 {
-    int ret;
+    psa_status_t status;
     const unsigned char drbg_seed[] = "PSA";
 
     /* Double initialization is explicitly allowed. */
@@ -4508,26 +4398,26 @@
     global_data.entropy_init( &global_data.entropy );
     mbedtls_ctr_drbg_init( &global_data.ctr_drbg );
     global_data.rng_state = RNG_INITIALIZED;
-    ret = mbedtls_ctr_drbg_seed( &global_data.ctr_drbg,
-                                 mbedtls_entropy_func,
-                                 &global_data.entropy,
-                                 drbg_seed, sizeof( drbg_seed ) - 1 );
-    if( ret != 0 )
+    status = mbedtls_to_psa_error(
+        mbedtls_ctr_drbg_seed( &global_data.ctr_drbg,
+                               mbedtls_entropy_func,
+                               &global_data.entropy,
+                               drbg_seed, sizeof( drbg_seed ) - 1 ) );
+    if( status != PSA_SUCCESS )
         goto exit;
     global_data.rng_state = RNG_SEEDED;
 
-    /* Initialize the key slots. Zero-initialization has made all key
-     * slots empty, so there is nothing to do. In a future version we will
-     * load data from storage. */
-    global_data.key_slots_initialized = 1;
+    status = psa_initialize_key_slots( );
+    if( status != PSA_SUCCESS )
+        goto exit;
 
     /* All done. */
     global_data.initialized = 1;
 
 exit:
-    if( ret != 0 )
+    if( status != PSA_SUCCESS )
         mbedtls_psa_crypto_free( );
-    return( mbedtls_to_psa_error( ret ) );
+    return( status );
 }
 
 #endif /* MBEDTLS_PSA_CRYPTO_C */
diff --git a/library/psa_crypto_core.h b/library/psa_crypto_core.h
new file mode 100644
index 0000000..c289681
--- /dev/null
+++ b/library/psa_crypto_core.h
@@ -0,0 +1,99 @@
+/*
+ *  PSA crypto core internal interfaces
+ */
+/*  Copyright (C) 2018, ARM Limited, All Rights Reserved
+ *  SPDX-License-Identifier: Apache-2.0
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ */
+
+#ifndef PSA_CRYPTO_CORE_H
+#define PSA_CRYPTO_CORE_H
+
+#if !defined(MBEDTLS_CONFIG_FILE)
+#include "mbedtls/config.h"
+#else
+#include MBEDTLS_CONFIG_FILE
+#endif
+
+#include "psa/crypto.h"
+
+#include "mbedtls/ecp.h"
+#include "mbedtls/rsa.h"
+
+/** The data structure representing a key slot, containing key material
+ * and metadata for one key.
+ */
+typedef struct
+{
+    psa_key_type_t type;
+    psa_key_policy_t policy;
+    psa_key_lifetime_t lifetime;
+    psa_key_id_t persistent_storage_id;
+    unsigned allocated : 1;
+    union
+    {
+        struct raw_data
+        {
+            uint8_t *data;
+            size_t bytes;
+        } raw;
+#if defined(MBEDTLS_RSA_C)
+        mbedtls_rsa_context *rsa;
+#endif /* MBEDTLS_RSA_C */
+#if defined(MBEDTLS_ECP_C)
+        mbedtls_ecp_keypair *ecp;
+#endif /* MBEDTLS_ECP_C */
+    } data;
+} psa_key_slot_t;
+
+/** Completely wipe a slot in memory, including its policy.
+ *
+ * Persistent storage is not affected.
+ *
+ * \param[in,out] slot  The key slot to wipe.
+ *
+ * \retval PSA_SUCCESS
+ *         Success. This includes the case of a key slot that was
+ *         already fully wiped.
+ * \retval PSA_ERROR_TAMPERING_DETECTED
+ */
+psa_status_t psa_wipe_key_slot( psa_key_slot_t *slot );
+
+/** Import key data into a slot.
+ *
+ * `slot->type` must have been set previously.
+ * This function assumes that the slot does not contain any key material yet.
+ * On failure, the slot content is unchanged.
+ *
+ * Persistent storage is not affected.
+ *
+ * \param[in,out] slot  The key slot to import data into.
+ *                      Its `type` field must have previously been set to
+ *                      the desired key type.
+ *                      It must not contain any key material yet.
+ * \param[in] data      Buffer containing the key material to parse and import.
+ * \param data_length   Size of \p data in bytes.
+ *
+ * \retval PSA_SUCCESS
+ * \retval PSA_ERROR_INVALID_ARGUMENT
+ * \retval PSA_ERROR_NOT_SUPPORTED
+ * \retval PSA_ERROR_INSUFFICIENT_MEMORY
+ */
+psa_status_t psa_import_key_into_slot( psa_key_slot_t *slot,
+                                       const uint8_t *data,
+                                       size_t data_length );
+
+#endif /* PSA_CRYPTO_CORE_H */
diff --git a/library/psa_crypto_slot_management.c b/library/psa_crypto_slot_management.c
new file mode 100644
index 0000000..0b4399f
--- /dev/null
+++ b/library/psa_crypto_slot_management.c
@@ -0,0 +1,287 @@
+/*
+ *  PSA crypto layer on top of Mbed TLS crypto
+ */
+/*  Copyright (C) 2018, ARM Limited, All Rights Reserved
+ *  SPDX-License-Identifier: Apache-2.0
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ */
+
+#if !defined(MBEDTLS_CONFIG_FILE)
+#include "mbedtls/config.h"
+#else
+#include MBEDTLS_CONFIG_FILE
+#endif
+
+#if defined(MBEDTLS_PSA_CRYPTO_C)
+
+#include "psa/crypto.h"
+
+#include "psa_crypto_core.h"
+#include "psa_crypto_slot_management.h"
+#include "psa_crypto_storage.h"
+
+#include <stdlib.h>
+#include <string.h>
+#if defined(MBEDTLS_PLATFORM_C)
+#include "mbedtls/platform.h"
+#else
+#define mbedtls_calloc calloc
+#define mbedtls_free   free
+#endif
+
+#define ARRAY_LENGTH( array ) ( sizeof( array ) / sizeof( *( array ) ) )
+
+typedef struct
+{
+    psa_key_slot_t key_slots[PSA_KEY_SLOT_COUNT];
+    unsigned key_slots_initialized : 1;
+} psa_global_data_t;
+
+static psa_global_data_t global_data;
+
+/* Access a key slot at the given handle. The handle of a key slot is
+ * the index of the slot in the global slot array, plus one so that handles
+ * start at 1 and not 0. */
+psa_status_t psa_get_key_slot( psa_key_handle_t handle,
+                               psa_key_slot_t **p_slot )
+{
+    psa_key_slot_t *slot = NULL;
+
+    if( ! global_data.key_slots_initialized )
+        return( PSA_ERROR_BAD_STATE );
+
+    /* 0 is not a valid handle under any circumstance. This
+     * implementation provides slots number 1 to N where N is the
+     * number of available slots. */
+    if( handle == 0 || handle > ARRAY_LENGTH( global_data.key_slots ) )
+        return( PSA_ERROR_INVALID_HANDLE );
+    slot = &global_data.key_slots[handle - 1];
+
+    /* If the slot hasn't been allocated, the handle is invalid. */
+    if( ! slot->allocated )
+        return( PSA_ERROR_INVALID_HANDLE );
+
+    *p_slot = slot;
+    return( PSA_SUCCESS );
+}
+
+psa_status_t psa_initialize_key_slots( void )
+{
+    /* Nothing to do: program startup and psa_wipe_all_key_slots() both
+     * guarantee that the key slots are initialized to all-zero, which
+     * means that all the key slots are in a valid, empty state. */
+    global_data.key_slots_initialized = 1;
+    return( PSA_SUCCESS );
+}
+
+void psa_wipe_all_key_slots( void )
+{
+    psa_key_handle_t key;
+    for( key = 1; key <= PSA_KEY_SLOT_COUNT; key++ )
+    {
+        psa_key_slot_t *slot = &global_data.key_slots[key - 1];
+        (void) psa_wipe_key_slot( slot );
+    }
+    global_data.key_slots_initialized = 0;
+}
+
+/** Find a free key slot and mark it as in use.
+ *
+ * \param[out] handle   On success, a slot number that is not in use. This
+ *                      value can be used as a handle to the slot.
+ *
+ * \retval #PSA_SUCCESS
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ */
+static psa_status_t psa_internal_allocate_key_slot( psa_key_handle_t *handle )
+{
+    for( *handle = PSA_KEY_SLOT_COUNT; *handle != 0; --( *handle ) )
+    {
+        psa_key_slot_t *slot = &global_data.key_slots[*handle - 1];
+        if( ! slot->allocated )
+        {
+            slot->allocated = 1;
+            return( PSA_SUCCESS );
+        }
+    }
+    return( PSA_ERROR_INSUFFICIENT_MEMORY );
+}
+
+/** Wipe a key slot and mark it as available.
+ *
+ * This does not affect persistent storage.
+ *
+ * \param handle        The handle to the key slot to release.
+ *
+ * \retval #PSA_SUCCESS
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ * \retval #PSA_ERROR_TAMPERING_DETECTED
+ */
+static psa_status_t psa_internal_release_key_slot( psa_key_handle_t handle )
+{
+    psa_key_slot_t *slot;
+    psa_status_t status;
+
+    status = psa_get_key_slot( handle, &slot );
+    if( status != PSA_SUCCESS )
+        return( status );
+
+    return( psa_wipe_key_slot( slot ) );
+}
+
+psa_status_t psa_allocate_key( psa_key_type_t type,
+                               size_t max_bits,
+                               psa_key_handle_t *handle )
+{
+    /* This implementation doesn't reserve memory for the keys. */
+    (void) type;
+    (void) max_bits;
+    *handle = 0;
+    return( psa_internal_allocate_key_slot( handle ) );
+}
+
+#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C)
+static psa_status_t psa_load_persistent_key_into_slot( psa_key_slot_t *p_slot )
+{
+    psa_status_t status = PSA_SUCCESS;
+    uint8_t *key_data = NULL;
+    size_t key_data_length = 0;
+
+    status = psa_load_persistent_key( p_slot->persistent_storage_id,
+                                      &( p_slot )->type,
+                                      &( p_slot )->policy, &key_data,
+                                      &key_data_length );
+    if( status != PSA_SUCCESS )
+        goto exit;
+    status = psa_import_key_into_slot( p_slot,
+                                       key_data, key_data_length );
+exit:
+    psa_free_persistent_key_data( key_data, key_data_length );
+    return( status );
+}
+#endif /* defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) */
+
+/** Declare a slot as persistent and load it from storage.
+ *
+ * This function may only be called immediately after a successful call
+ * to psa_internal_allocate_key_slot().
+ *
+ * \param handle        A handle to a key slot freshly allocated with
+ *                      psa_internal_allocate_key_slot().
+ *
+ * \retval #PSA_SUCCESS
+ *         The slot content was loaded successfully.
+ * \retval #PSA_ERROR_EMPTY_SLOT
+ *         There is no content for this slot in persistent storage.
+ * \retval #PSA_ERROR_INVALID_HANDLE
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ *         \p id is not acceptable.
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_STORAGE_FAILURE
+ */
+static psa_status_t psa_internal_make_key_persistent( psa_key_handle_t handle,
+                                                      psa_key_id_t id )
+{
+#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C)
+    psa_key_slot_t *slot;
+    psa_status_t status;
+
+    /* Reject id=0 because by general library conventions, 0 is an invalid
+     * value wherever possible. */
+    if( id == 0 )
+        return( PSA_ERROR_INVALID_ARGUMENT );
+    /* Reject high values because the file names are reserved for the
+     * library's internal use. */
+    if( id >= PSA_MAX_PERSISTENT_KEY_IDENTIFIER )
+        return( PSA_ERROR_INVALID_ARGUMENT );
+
+    status = psa_get_key_slot( handle, &slot );
+    if( status != PSA_SUCCESS )
+        return( status );
+
+    slot->lifetime = PSA_KEY_LIFETIME_PERSISTENT;
+    slot->persistent_storage_id = id;
+    status = psa_load_persistent_key_into_slot( slot );
+
+    return( status );
+
+#else /* MBEDTLS_PSA_CRYPTO_STORAGE_C */
+    (void) handle;
+    (void) id;
+    return( PSA_ERROR_NOT_SUPPORTED );
+#endif /* !MBEDTLS_PSA_CRYPTO_STORAGE_C */
+}
+
+static psa_status_t persistent_key_setup( psa_key_lifetime_t lifetime,
+                                          psa_key_id_t id,
+                                          psa_key_handle_t *handle,
+                                          psa_status_t wanted_load_status )
+{
+    psa_status_t status;
+
+    *handle = 0;
+
+    if( lifetime != PSA_KEY_LIFETIME_PERSISTENT )
+        return( PSA_ERROR_INVALID_ARGUMENT );
+
+    status = psa_internal_allocate_key_slot( handle );
+    if( status != PSA_SUCCESS )
+        return( status );
+
+    status = psa_internal_make_key_persistent( *handle, id );
+    if( status != wanted_load_status )
+    {
+        psa_internal_release_key_slot( *handle );
+        *handle = 0;
+    }
+    return( status );
+}
+
+psa_status_t psa_open_key( psa_key_lifetime_t lifetime,
+                           psa_key_id_t id,
+                           psa_key_handle_t *handle )
+{
+    return( persistent_key_setup( lifetime, id, handle, PSA_SUCCESS ) );
+}
+
+psa_status_t psa_create_key( psa_key_lifetime_t lifetime,
+                             psa_key_id_t id,
+                             psa_key_type_t type,
+                             size_t max_bits,
+                             psa_key_handle_t *handle )
+{
+    psa_status_t status;
+
+    /* This implementation doesn't reserve memory for the keys. */
+    (void) type;
+    (void) max_bits;
+
+    status = persistent_key_setup( lifetime, id, handle,
+                                   PSA_ERROR_EMPTY_SLOT );
+    switch( status )
+    {
+        case PSA_SUCCESS: return( PSA_ERROR_OCCUPIED_SLOT );
+        case PSA_ERROR_EMPTY_SLOT: return( PSA_SUCCESS );
+        default: return( status );
+    }
+}
+
+psa_status_t psa_close_key( psa_key_handle_t handle )
+{
+    return( psa_internal_release_key_slot( handle ) );
+}
+
+#endif /* MBEDTLS_PSA_CRYPTO_C */
diff --git a/library/psa_crypto_slot_management.h b/library/psa_crypto_slot_management.h
new file mode 100644
index 0000000..6746bad
--- /dev/null
+++ b/library/psa_crypto_slot_management.h
@@ -0,0 +1,58 @@
+/*
+ *  PSA crypto layer on top of Mbed TLS crypto
+ */
+/*  Copyright (C) 2018, ARM Limited, All Rights Reserved
+ *  SPDX-License-Identifier: Apache-2.0
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ */
+
+#ifndef PSA_CRYPTO_SLOT_MANAGEMENT_H
+#define PSA_CRYPTO_SLOT_MANAGEMENT_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
+
+/** Access a key slot at the given handle.
+ *
+ * \param handle        Key handle to query.
+ * \param[out] p_slot   On success, `*p_slot` contains a pointer to the
+ *                      key slot in memory designated by \p handle.
+ *
+ * \retval PSA_SUCCESS
+ *         Success: \p handle is a handle to `*p_slot`. Note that `*p_slot`
+ *         may be empty or occupied.
+ * \retval PSA_ERROR_INVALID_HANDLE
+ *         \p handle is out of range or is not in use.
+ * \retval PSA_ERROR_BAD_STATE
+ *         The library has not been initialized.
+ */
+psa_status_t psa_get_key_slot( psa_key_handle_t handle,
+                               psa_key_slot_t **p_slot );
+
+/** Initialize the key slot structures.
+ *
+ * \retval PSA_SUCCESS
+ *         Currently this function always succeeds.
+ */
+psa_status_t psa_initialize_key_slots( void );
+
+/** Delete all data from key slots in memory.
+ *
+ * This does not affect persistent storage. */
+void psa_wipe_all_key_slots( void );
+
+#endif /* PSA_CRYPTO_SLOT_MANAGEMENT_H */
diff --git a/library/psa_crypto_storage.c b/library/psa_crypto_storage.c
index 0a5805b..687269b 100644
--- a/library/psa_crypto_storage.c
+++ b/library/psa_crypto_storage.c
@@ -147,7 +147,7 @@
     return( PSA_SUCCESS );
 }
 
-psa_status_t psa_save_persistent_key( const psa_key_slot_t key,
+psa_status_t psa_save_persistent_key( const psa_key_id_t key,
                                       const psa_key_type_t type,
                                       const psa_key_policy_t *policy,
                                       const uint8_t *data,
@@ -185,7 +185,7 @@
     mbedtls_free( key_data );
 }
 
-psa_status_t psa_load_persistent_key( psa_key_slot_t key,
+psa_status_t psa_load_persistent_key( psa_key_id_t key,
                                       psa_key_type_t *type,
                                       psa_key_policy_t *policy,
                                       uint8_t **data,
diff --git a/library/psa_crypto_storage.h b/library/psa_crypto_storage.h
index 167b0db..85881c1 100644
--- a/library/psa_crypto_storage.h
+++ b/library/psa_crypto_storage.h
@@ -44,6 +44,23 @@
  * inadvertently store an obscene amount of data) */
 #define PSA_CRYPTO_MAX_STORAGE_SIZE ( 30 * 1024 )
 
+/** The maximum permitted persistent slot number.
+ *
+ * In Mbed Crypto 0.1.0b:
+ * - Using the file backend, all key ids are ok except 0.
+ * - Using the ITS backend, all key ids are ok except 0xFFFFFF52
+ *   (#PSA_CRYPTO_ITS_RANDOM_SEED_UID) for which the file contains the
+ *   device's random seed (if this feature is enabled).
+ * - Only key ids from 1 to #PSA_KEY_SLOT_COUNT are actually used.
+ *
+ * Since we need to preserve the random seed, avoid using that key slot.
+ * Reserve a whole range of key slots just in case something else comes up.
+ *
+ * This limitation will probably become moot when we implement client
+ * separation for key storage.
+ */
+#define PSA_MAX_PERSISTENT_KEY_IDENTIFIER 0xffff0000
+
 /**
  * \brief Format key data and metadata and save to a location for given key
  *        slot.
@@ -56,20 +73,20 @@
  * already occupied non-persistent key, as well as validating the key data.
  *
  *
- * \param key           Slot number of the key to be stored. This must be a
- *                      valid slot for a key of the chosen type. This should be
- *                      an occupied key slot with an unoccupied corresponding
- *                      storage location.
+ * \param key           Persistent identifier of the key to be stored. This
+ *                      should be an unoccupied storage location.
  * \param type          Key type (a \c PSA_KEY_TYPE_XXX value).
  * \param[in] policy    The key policy to save.
  * \param[in] data      Buffer containing the key data.
  * \param data_length   The number of bytes that make up the key data.
  *
  * \retval PSA_SUCCESS
+ * \retval PSA_ERROR_INSUFFICIENT_MEMORY
  * \retval PSA_ERROR_INSUFFICIENT_STORAGE
  * \retval PSA_ERROR_STORAGE_FAILURE
+ * \retval PSA_ERROR_OCCUPIED_SLOT
  */
-psa_status_t psa_save_persistent_key( const psa_key_slot_t key,
+psa_status_t psa_save_persistent_key( const psa_key_id_t key,
                                       const psa_key_type_t type,
                                       const psa_key_policy_t *policy,
                                       const uint8_t *data,
@@ -87,10 +104,8 @@
  * this function to zeroize and free this buffer, regardless of whether this
  * function succeeds or fails.
  *
- * \param key               Slot number whose content is to be loaded. This
- *                          must be an unoccupied key slot with an occupied
- *                          corresponding storage location. The key slot
- *                          lifetime must be set to persistent.
+ * \param key               Persistent identifier of the key to be loaded. This
+ *                          should be an occupied storage location.
  * \param[out] type         On success, the key type (a \c PSA_KEY_TYPE_XXX
  *                          value).
  * \param[out] policy       On success, the key's policy.
@@ -100,8 +115,9 @@
  * \retval PSA_SUCCESS
  * \retval PSA_ERROR_INSUFFICIENT_MEMORY
  * \retval PSA_ERROR_STORAGE_FAILURE
+ * \retval PSA_ERROR_EMPTY_SLOT
  */
-psa_status_t psa_load_persistent_key( psa_key_slot_t key,
+psa_status_t psa_load_persistent_key( psa_key_id_t key,
                                       psa_key_type_t *type,
                                       psa_key_policy_t *policy,
                                       uint8_t **data,
@@ -110,16 +126,18 @@
 /**
  * \brief Remove persistent data for the given key slot number.
  *
- * \param key           Slot number whose content is to be removed
+ * \param key           Persistent identifier of the key to remove
  *                      from persistent storage.
  *
  * \retval PSA_SUCCESS
+ *         The key was successfully removed,
+ *         or the key did not exist.
  * \retval PSA_ERROR_STORAGE_FAILURE
  */
-psa_status_t psa_destroy_persistent_key( const psa_key_slot_t key );
+psa_status_t psa_destroy_persistent_key( const psa_key_id_t key );
 
 /**
- * \brief Zeroizes and frees the given buffer.
+ * \brief Free the temporary buffer allocated by psa_load_persistent_key().
  *
  * This function must be called at some point after psa_load_persistent_key()
  * to zeroize and free the memory allocated to the buffer in that function.
diff --git a/library/psa_crypto_storage_backend.h b/library/psa_crypto_storage_backend.h
index 3ca9a1d..47896b8 100644
--- a/library/psa_crypto_storage_backend.h
+++ b/library/psa_crypto_storage_backend.h
@@ -47,15 +47,16 @@
  * This function reads data from a storage backend and returns the data in a
  * buffer.
  *
- * \param key              Slot number whose content is to be loaded. This must
- *                         be a key slot whose lifetime is set to persistent.
- * \param[out] data        Buffer where the data is to be written.
- * \param data_size        Size of the \c data buffer in bytes.
+ * \param key               Persistent identifier of the key to be loaded. This
+ *                          should be an occupied storage location.
+ * \param[out] data         Buffer where the data is to be written.
+ * \param data_size         Size of the \c data buffer in bytes.
  *
  * \retval PSA_SUCCESS
  * \retval PSA_ERROR_STORAGE_FAILURE
+ * \retval PSA_ERROR_EMPTY_SLOT
  */
-psa_status_t psa_crypto_storage_load( const psa_key_slot_t key, uint8_t *data,
+psa_status_t psa_crypto_storage_load( const psa_key_id_t key, uint8_t *data,
                                       size_t data_size );
 
 /**
@@ -63,7 +64,8 @@
  *
  * This function stores the given data buffer to a persistent storage.
  *
- * \param key           Slot number whose content is to be stored.
+ * \param key           Persistent identifier of the key to be stored. This
+ *                      should be an unoccupied storage location.
  * \param[in] data      Buffer containing the data to be stored.
  * \param data_length   The number of bytes
  *                      that make up the data.
@@ -71,8 +73,9 @@
  * \retval PSA_SUCCESS
  * \retval PSA_ERROR_INSUFFICIENT_STORAGE
  * \retval PSA_ERROR_STORAGE_FAILURE
+ * \retval PSA_ERROR_OCCUPIED_SLOT
  */
-psa_status_t psa_crypto_storage_store( const psa_key_slot_t key,
+psa_status_t psa_crypto_storage_store( const psa_key_id_t key,
                                        const uint8_t *data,
                                        size_t data_length );
 
@@ -82,26 +85,26 @@
  * This function checks if any key data or metadata exists for the key slot in
  * the persistent storage.
  *
- * \param key           Slot number whose content is to be checked.
+ * \param key           Persistent identifier to check.
  *
  * \retval 0
  *         No persistent data present for slot number
  * \retval 1
  *         Persistent data present for slot number
  */
-int psa_is_key_present_in_storage( const psa_key_slot_t key );
+int psa_is_key_present_in_storage( const psa_key_id_t key );
 
 /**
  * \brief Get data length for given key slot number.
  *
- * \param key              Slot number whose stored data length is to be obtained.
- * \param[out] data_length The number of bytes
- *                         that make up the data.
+ * \param key               Persistent identifier whose stored data length
+ *                          is to be obtained.
+ * \param[out] data_length  The number of bytes that make up the data.
  *
  * \retval PSA_SUCCESS
  * \retval PSA_ERROR_STORAGE_FAILURE
  */
-psa_status_t psa_crypto_storage_get_data_length( const psa_key_slot_t key,
+psa_status_t psa_crypto_storage_get_data_length( const psa_key_id_t key,
                                                  size_t *data_length );
 
 
diff --git a/library/psa_crypto_storage_file.c b/library/psa_crypto_storage_file.c
index 03c711a..87420be 100644
--- a/library/psa_crypto_storage_file.c
+++ b/library/psa_crypto_storage_file.c
@@ -48,15 +48,16 @@
 
 enum { MAX_LOCATION_LEN = sizeof(CRYPTO_STORAGE_FILE_LOCATION) + 40 };
 
-static void key_slot_to_location( const psa_key_slot_t key,
-                                  char *location,
-                                  size_t location_size )
+static void key_id_to_location( const psa_key_id_t key,
+                                char *location,
+                                size_t location_size )
 {
     mbedtls_snprintf( location, location_size,
-                      CRYPTO_STORAGE_FILE_LOCATION "psa_key_slot_%d", key );
+                      CRYPTO_STORAGE_FILE_LOCATION "psa_key_slot_%lu",
+                      (unsigned long) key );
 }
 
-psa_status_t psa_crypto_storage_load( const psa_key_slot_t key, uint8_t *data,
+psa_status_t psa_crypto_storage_load( const psa_key_id_t key, uint8_t *data,
                                       size_t data_size )
 {
     psa_status_t status = PSA_SUCCESS;
@@ -64,7 +65,7 @@
     size_t num_read;
     char slot_location[MAX_LOCATION_LEN];
 
-    key_slot_to_location( key, slot_location, MAX_LOCATION_LEN );
+    key_id_to_location( key, slot_location, MAX_LOCATION_LEN );
     file = fopen( slot_location, "rb" );
     if( file == NULL )
     {
@@ -81,12 +82,12 @@
     return( status );
 }
 
-int psa_is_key_present_in_storage( const psa_key_slot_t key )
+int psa_is_key_present_in_storage( const psa_key_id_t key )
 {
     char slot_location[MAX_LOCATION_LEN];
     FILE *file;
 
-    key_slot_to_location( key, slot_location, MAX_LOCATION_LEN );
+    key_id_to_location( key, slot_location, MAX_LOCATION_LEN );
 
     file = fopen( slot_location, "r" );
     if( file == NULL )
@@ -99,7 +100,7 @@
     return( 1 );
 }
 
-psa_status_t psa_crypto_storage_store( const psa_key_slot_t key,
+psa_status_t psa_crypto_storage_store( const psa_key_id_t key,
                                        const uint8_t *data,
                                        size_t data_length )
 {
@@ -114,7 +115,7 @@
      * affect actual keys. */
     const char *temp_location = CRYPTO_STORAGE_FILE_LOCATION "psa_key_slot_0";
 
-    key_slot_to_location( key, slot_location, MAX_LOCATION_LEN );
+    key_id_to_location( key, slot_location, MAX_LOCATION_LEN );
 
     if( psa_is_key_present_in_storage( key ) == 1 )
         return( PSA_ERROR_OCCUPIED_SLOT );
@@ -154,12 +155,12 @@
     return( status );
 }
 
-psa_status_t psa_destroy_persistent_key( const psa_key_slot_t key )
+psa_status_t psa_destroy_persistent_key( const psa_key_id_t key )
 {
     FILE *file;
     char slot_location[MAX_LOCATION_LEN];
 
-    key_slot_to_location( key, slot_location, MAX_LOCATION_LEN );
+    key_id_to_location( key, slot_location, MAX_LOCATION_LEN );
 
     /* Only try remove the file if it exists */
     file = fopen( slot_location, "rb" );
@@ -173,7 +174,7 @@
     return( PSA_SUCCESS );
 }
 
-psa_status_t psa_crypto_storage_get_data_length( const psa_key_slot_t key,
+psa_status_t psa_crypto_storage_get_data_length( const psa_key_id_t key,
                                                  size_t *data_length )
 {
     psa_status_t status = PSA_SUCCESS;
@@ -181,7 +182,7 @@
     long file_size;
     char slot_location[MAX_LOCATION_LEN];
 
-    key_slot_to_location( key, slot_location, MAX_LOCATION_LEN );
+    key_id_to_location( key, slot_location, MAX_LOCATION_LEN );
 
     file = fopen( slot_location, "rb" );
     if( file == NULL )
diff --git a/library/psa_crypto_storage_its.c b/library/psa_crypto_storage_its.c
index 35caa39..d53467a 100644
--- a/library/psa_crypto_storage_its.c
+++ b/library/psa_crypto_storage_its.c
@@ -68,12 +68,12 @@
     }
 }
 
-static uint32_t psa_its_identifier_of_slot( psa_key_slot_t key )
+static uint32_t psa_its_identifier_of_slot( psa_key_id_t key )
 {
     return( key );
 }
 
-psa_status_t psa_crypto_storage_load( const psa_key_slot_t key, uint8_t *data,
+psa_status_t psa_crypto_storage_load( const psa_key_id_t key, uint8_t *data,
                                       size_t data_size )
 {
     psa_its_status_t ret;
@@ -92,7 +92,7 @@
     return( status );
 }
 
-int psa_is_key_present_in_storage( const psa_key_slot_t key )
+int psa_is_key_present_in_storage( const psa_key_id_t key )
 {
     psa_its_status_t ret;
     uint32_t data_identifier = psa_its_identifier_of_slot( key );
@@ -105,7 +105,7 @@
     return( 1 );
 }
 
-psa_status_t psa_crypto_storage_store( const psa_key_slot_t key,
+psa_status_t psa_crypto_storage_store( const psa_key_id_t key,
                                        const uint8_t *data,
                                        size_t data_length )
 {
@@ -143,7 +143,7 @@
     return( status );
 }
 
-psa_status_t psa_destroy_persistent_key( const psa_key_slot_t key )
+psa_status_t psa_destroy_persistent_key( const psa_key_id_t key )
 {
     psa_its_status_t ret;
     uint32_t data_identifier = psa_its_identifier_of_slot( key );
@@ -163,7 +163,7 @@
     return( PSA_SUCCESS );
 }
 
-psa_status_t psa_crypto_storage_get_data_length( const psa_key_slot_t key,
+psa_status_t psa_crypto_storage_get_data_length( const psa_key_id_t key,
                                                  size_t *data_length )
 {
     psa_its_status_t ret;
diff --git a/programs/psa/crypto_examples.c b/programs/psa/crypto_examples.c
index 72c41fa..53b6b2a 100644
--- a/programs/psa/crypto_examples.c
+++ b/programs/psa/crypto_examples.c
@@ -44,10 +44,7 @@
 }
 #else
 
-/* Use key slot 1 for our cipher key. Key slot 0 is reserved as unused. */
-static const psa_key_slot_t key_slot_cipher = 1;
-
-static psa_status_t set_key_policy( psa_key_slot_t key_slot,
+static psa_status_t set_key_policy( psa_key_handle_t key_handle,
                                     psa_key_usage_t key_usage,
                                     psa_algorithm_t alg )
 {
@@ -56,7 +53,7 @@
 
     psa_key_policy_init( &policy );
     psa_key_policy_set_usage( &policy, key_usage, alg );
-    status = psa_set_key_policy( key_slot, &policy );
+    status = psa_set_key_policy( key_handle, &policy );
     ASSERT_STATUS( status, PSA_SUCCESS );
 exit:
     return( status );
@@ -98,7 +95,7 @@
     return( status );
 }
 
-static psa_status_t cipher_encrypt( psa_key_slot_t key_slot,
+static psa_status_t cipher_encrypt( psa_key_handle_t key_handle,
                                     psa_algorithm_t alg,
                                     uint8_t * iv,
                                     size_t iv_size,
@@ -114,7 +111,7 @@
     size_t iv_len = 0;
 
     memset( &operation, 0, sizeof( operation ) );
-    status = psa_cipher_encrypt_setup( &operation, key_slot, alg );
+    status = psa_cipher_encrypt_setup( &operation, key_handle, alg );
     ASSERT_STATUS( status, PSA_SUCCESS );
 
     status = psa_cipher_generate_iv( &operation, iv, iv_size, &iv_len );
@@ -129,7 +126,7 @@
     return( status );
 }
 
-static psa_status_t cipher_decrypt( psa_key_slot_t key_slot,
+static psa_status_t cipher_decrypt( psa_key_handle_t key_handle,
                                     psa_algorithm_t alg,
                                     const uint8_t * iv,
                                     size_t iv_size,
@@ -144,7 +141,7 @@
     psa_cipher_operation_t operation;
 
     memset( &operation, 0, sizeof( operation ) );
-    status = psa_cipher_decrypt_setup( &operation, key_slot, alg );
+    status = psa_cipher_decrypt_setup( &operation, key_handle, alg );
     ASSERT_STATUS( status, PSA_SUCCESS );
 
     status = psa_cipher_set_iv( &operation, iv, iv_size );
@@ -170,6 +167,7 @@
     const psa_algorithm_t alg = PSA_ALG_CBC_NO_PADDING;
 
     psa_status_t status;
+    psa_key_handle_t key_handle = 0;
     size_t output_len = 0;
     uint8_t iv[block_size];
     uint8_t input[block_size];
@@ -179,21 +177,24 @@
     status = psa_generate_random( input, sizeof( input ) );
     ASSERT_STATUS( status, PSA_SUCCESS );
 
-    status = set_key_policy( key_slot_cipher,
+    status = psa_allocate_key( PSA_KEY_TYPE_AES, key_bits, &key_handle );
+    ASSERT_STATUS( status, PSA_SUCCESS );
+
+    status = set_key_policy( key_handle,
                              PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT,
                              alg );
     ASSERT_STATUS( status, PSA_SUCCESS );
 
-    status = psa_generate_key( key_slot_cipher, PSA_KEY_TYPE_AES, key_bits,
+    status = psa_generate_key( key_handle, PSA_KEY_TYPE_AES, key_bits,
                                NULL, 0 );
     ASSERT_STATUS( status, PSA_SUCCESS );
 
-    status = cipher_encrypt( key_slot_cipher, alg, iv, sizeof( iv ),
+    status = cipher_encrypt( key_handle, alg, iv, sizeof( iv ),
                              input, sizeof( input ), part_size,
                              encrypt, sizeof( encrypt ), &output_len );
     ASSERT_STATUS( status, PSA_SUCCESS );
 
-    status = cipher_decrypt( key_slot_cipher, alg, iv, sizeof( iv ),
+    status = cipher_decrypt( key_handle, alg, iv, sizeof( iv ),
                              encrypt, output_len, part_size,
                              decrypt, sizeof( decrypt ), &output_len );
     ASSERT_STATUS( status, PSA_SUCCESS );
@@ -202,7 +203,7 @@
     ASSERT_STATUS( status, PSA_SUCCESS );
 
 exit:
-    psa_destroy_key( key_slot_cipher );
+    psa_destroy_key( key_handle );
     return( status );
 }
 
@@ -218,6 +219,7 @@
     const psa_algorithm_t alg = PSA_ALG_CBC_PKCS7;
 
     psa_status_t status;
+    psa_key_handle_t key_handle = 0;
     size_t output_len = 0;
     uint8_t iv[block_size], input[input_size],
             encrypt[input_size + block_size], decrypt[input_size + block_size];
@@ -225,21 +227,24 @@
     status = psa_generate_random( input, sizeof( input ) );
     ASSERT_STATUS( status, PSA_SUCCESS );
 
-    status = set_key_policy( key_slot_cipher,
+    status = psa_allocate_key( PSA_KEY_TYPE_AES, key_bits, &key_handle );
+    ASSERT_STATUS( status, PSA_SUCCESS );
+
+    status = set_key_policy( key_handle,
                              PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT,
                              alg );
     ASSERT_STATUS( status, PSA_SUCCESS );
 
-    status = psa_generate_key( key_slot_cipher, PSA_KEY_TYPE_AES, key_bits,
+    status = psa_generate_key( key_handle, PSA_KEY_TYPE_AES, key_bits,
                                NULL, 0 );
     ASSERT_STATUS( status, PSA_SUCCESS );
 
-    status = cipher_encrypt( key_slot_cipher, alg, iv, sizeof( iv ),
+    status = cipher_encrypt( key_handle, alg, iv, sizeof( iv ),
                              input, sizeof( input ), part_size,
                              encrypt, sizeof( encrypt ), &output_len );
     ASSERT_STATUS( status, PSA_SUCCESS );
 
-    status = cipher_decrypt( key_slot_cipher, alg, iv, sizeof( iv ),
+    status = cipher_decrypt( key_handle, alg, iv, sizeof( iv ),
                              encrypt, output_len, part_size,
                              decrypt, sizeof( decrypt ), &output_len );
     ASSERT_STATUS( status, PSA_SUCCESS );
@@ -248,7 +253,7 @@
     ASSERT_STATUS( status, PSA_SUCCESS );
 
 exit:
-    psa_destroy_key( key_slot_cipher );
+    psa_destroy_key( key_handle );
     return( status );
 }
 
@@ -263,6 +268,7 @@
     const psa_algorithm_t alg = PSA_ALG_CTR;
 
     psa_status_t status;
+    psa_key_handle_t key_handle = 0;
     size_t output_len = 0;
     uint8_t iv[block_size], input[input_size], encrypt[input_size],
             decrypt[input_size];
@@ -270,21 +276,23 @@
     status = psa_generate_random( input, sizeof( input ) );
     ASSERT_STATUS( status, PSA_SUCCESS );
 
-    status = set_key_policy( key_slot_cipher,
+    status = psa_allocate_key( PSA_KEY_TYPE_AES, key_bits, &key_handle );
+    ASSERT_STATUS( status, PSA_SUCCESS );
+    status = set_key_policy( key_handle,
                              PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT,
                              alg );
     ASSERT_STATUS( status, PSA_SUCCESS );
 
-    status = psa_generate_key( key_slot_cipher, PSA_KEY_TYPE_AES, key_bits,
+    status = psa_generate_key( key_handle, PSA_KEY_TYPE_AES, key_bits,
                                NULL, 0 );
     ASSERT_STATUS( status, PSA_SUCCESS );
 
-    status = cipher_encrypt( key_slot_cipher, alg, iv, sizeof( iv ),
+    status = cipher_encrypt( key_handle, alg, iv, sizeof( iv ),
                              input, sizeof( input ), part_size,
                              encrypt, sizeof( encrypt ), &output_len );
     ASSERT_STATUS( status, PSA_SUCCESS );
 
-    status = cipher_decrypt( key_slot_cipher, alg, iv, sizeof( iv ),
+    status = cipher_decrypt( key_handle, alg, iv, sizeof( iv ),
                              encrypt, output_len, part_size,
                              decrypt, sizeof( decrypt ), &output_len );
     ASSERT_STATUS( status, PSA_SUCCESS );
@@ -293,7 +301,7 @@
     ASSERT_STATUS( status, PSA_SUCCESS );
 
 exit:
-    psa_destroy_key( key_slot_cipher );
+    psa_destroy_key( key_handle );
     return( status );
 }
 
diff --git a/programs/psa/key_ladder_demo.c b/programs/psa/key_ladder_demo.c
index 2c75ca4..470b1fc 100644
--- a/programs/psa/key_ladder_demo.c
+++ b/programs/psa/key_ladder_demo.c
@@ -167,15 +167,6 @@
     uint8_t iv[WRAPPING_IV_SIZE];
 } wrapped_data_header_t;
 
-/* This program uses three key slots: one for the master key, one to
- * derive intermediate keys, and one for the wrapping key. We use a
- * single slot for all the intermediate keys because they are only
- * needed successively, so each time we derive an intermediate key,
- * we destroy the previous one. */
-static const psa_key_slot_t master_key_slot = 1;
-static const psa_key_slot_t derived_key_slot = 2;
-static const psa_key_slot_t wrapping_key_slot = 3;
-
 /* The modes that this program can operate in (see usage). */
 enum program_mode
 {
@@ -187,7 +178,7 @@
 
 /* Save a key to a file. In the real world, you may want to export a derived
  * key sometimes, to share it with another party. */
-static psa_status_t save_key( psa_key_slot_t key_slot,
+static psa_status_t save_key( psa_key_handle_t key_handle,
                               const char *output_file_name )
 {
     psa_status_t status = PSA_SUCCESS;
@@ -195,7 +186,7 @@
     size_t key_size;
     FILE *key_file = NULL;
 
-    PSA_CHECK( psa_export_key( key_slot,
+    PSA_CHECK( psa_export_key( key_handle,
                                key_data, sizeof( key_data ),
                                &key_size ) );
     SYS_CHECK( ( key_file = fopen( output_file_name, "wb" ) ) != NULL );
@@ -217,22 +208,27 @@
 static psa_status_t generate( const char *key_file_name )
 {
     psa_status_t status = PSA_SUCCESS;
+    psa_key_handle_t key_handle = 0;
     psa_key_policy_t policy;
 
+    PSA_CHECK( psa_allocate_key( PSA_KEY_TYPE_DERIVE,
+                                 PSA_BYTES_TO_BITS( KEY_SIZE_BYTES ),
+                                 &key_handle ) );
     psa_key_policy_init( &policy );
     psa_key_policy_set_usage( &policy,
                               PSA_KEY_USAGE_DERIVE | PSA_KEY_USAGE_EXPORT,
                               KDF_ALG );
-    PSA_CHECK( psa_set_key_policy( master_key_slot, &policy ) );
+    PSA_CHECK( psa_set_key_policy( key_handle, &policy ) );
 
-    PSA_CHECK( psa_generate_key( master_key_slot,
+    PSA_CHECK( psa_generate_key( key_handle,
                                  PSA_KEY_TYPE_DERIVE,
                                  PSA_BYTES_TO_BITS( KEY_SIZE_BYTES ),
                                  NULL, 0 ) );
 
-    PSA_CHECK( save_key( master_key_slot, key_file_name ) );
+    PSA_CHECK( save_key( key_handle, key_file_name ) );
 
 exit:
+    (void) psa_destroy_key( key_handle );
     return( status );
 }
 
@@ -241,10 +237,10 @@
  * In the real world, this master key would be stored in an internal memory
  * and the storage would be managed by the keystore capability of the PSA
  * crypto library. */
-static psa_status_t import_key_from_file( psa_key_slot_t key_slot,
-                                          psa_key_usage_t usage,
+static psa_status_t import_key_from_file( psa_key_usage_t usage,
                                           psa_algorithm_t alg,
-                                          const char *key_file_name )
+                                          const char *key_file_name,
+                                          psa_key_handle_t *master_key_handle )
 {
     psa_status_t status = PSA_SUCCESS;
     psa_key_policy_t policy;
@@ -253,6 +249,8 @@
     FILE *key_file = NULL;
     unsigned char extra_byte;
 
+    *master_key_handle = 0;
+
     SYS_CHECK( ( key_file = fopen( key_file_name, "rb" ) ) != NULL );
     SYS_CHECK( ( key_size = fread( key_data, 1, sizeof( key_data ),
                                    key_file ) ) != 0 );
@@ -266,30 +264,41 @@
     SYS_CHECK( fclose( key_file ) == 0 );
     key_file = NULL;
 
+    PSA_CHECK( psa_allocate_key( PSA_KEY_TYPE_DERIVE,
+                                 PSA_BYTES_TO_BITS( key_size ),
+                                 master_key_handle ) );
     psa_key_policy_init( &policy );
     psa_key_policy_set_usage( &policy, usage, alg );
-    PSA_CHECK( psa_set_key_policy( key_slot, &policy ) );
-    PSA_CHECK( psa_import_key( key_slot,
+    PSA_CHECK( psa_set_key_policy( *master_key_handle, &policy ) );
+    PSA_CHECK( psa_import_key( *master_key_handle,
                                PSA_KEY_TYPE_DERIVE,
                                key_data, key_size ) );
 exit:
     if( key_file != NULL )
         fclose( key_file );
     mbedtls_platform_zeroize( key_data, sizeof( key_data ) );
+    if( status != PSA_SUCCESS )
+    {
+        /* If psa_allocate_key hasn't been called yet or has failed,
+         * *master_key_handle is 0. psa_destroy_key(0) is guaranteed to do
+         * nothing and return PSA_ERROR_INVALID_HANDLE. */
+        (void) psa_destroy_key( *master_key_handle );
+        *master_key_handle = 0;
+    }
     return( status );
 }
 
 /* Derive the intermediate keys, using the list of labels provided on
- * the command line. */
+ * the command line. On input, *key_handle is a handle to the master key.
+ * This function closes the master key. On successful output, *key_handle
+ * is a handle to the final derived key. */
 static psa_status_t derive_key_ladder( const char *ladder[],
-                                       size_t ladder_depth )
+                                       size_t ladder_depth,
+                                       psa_key_handle_t *key_handle )
 {
     psa_status_t status = PSA_SUCCESS;
     psa_key_policy_t policy;
     psa_crypto_generator_t generator = PSA_CRYPTO_GENERATOR_INIT;
-    /* We'll derive the first intermediate key from the master key, then
-     * each subsequent intemediate key from the previous intemediate key. */
-    psa_key_slot_t parent_key_slot = master_key_slot;
     size_t i;
     psa_key_policy_init( &policy );
     psa_key_policy_set_usage( &policy,
@@ -303,63 +312,81 @@
          * the current intermediate key (if i>0). */
         PSA_CHECK( psa_key_derivation(
                        &generator,
-                       parent_key_slot,
+                       *key_handle,
                        KDF_ALG,
                        DERIVE_KEY_SALT, DERIVE_KEY_SALT_LENGTH,
                        (uint8_t*) ladder[i], strlen( ladder[i] ),
                        KEY_SIZE_BYTES ) );
         /* When the parent key is not the master key, destroy it,
          * since it is no longer needed. */
-        if( i != 0 )
-            PSA_CHECK( psa_destroy_key( derived_key_slot ) );
-        PSA_CHECK( psa_set_key_policy( derived_key_slot, &policy ) );
+        PSA_CHECK( psa_close_key( *key_handle ) );
+        *key_handle = 0;
+        PSA_CHECK( psa_allocate_key( PSA_KEY_TYPE_DERIVE,
+                                     PSA_BYTES_TO_BITS( KEY_SIZE_BYTES ),
+                                     key_handle ) );
+        PSA_CHECK( psa_set_key_policy( *key_handle, &policy ) );
         /* Use the generator obtained from the parent key to create
          * the next intermediate key. */
         PSA_CHECK( psa_generator_import_key(
-                       derived_key_slot,
+                       *key_handle,
                        PSA_KEY_TYPE_DERIVE,
                        PSA_BYTES_TO_BITS( KEY_SIZE_BYTES ),
                        &generator ) );
         PSA_CHECK( psa_generator_abort( &generator ) );
-        parent_key_slot = derived_key_slot;
     }
 
 exit:
     psa_generator_abort( &generator );
+    if( status != PSA_SUCCESS )
+    {
+        psa_close_key( *key_handle );
+        *key_handle = 0;
+    }
     return( status );
 }
 
 /* Derive a wrapping key from the last intermediate key. */
-static psa_status_t derive_wrapping_key( psa_key_usage_t usage )
+static psa_status_t derive_wrapping_key( psa_key_usage_t usage,
+                                         psa_key_handle_t derived_key_handle,
+                                         psa_key_handle_t *wrapping_key_handle )
 {
     psa_status_t status = PSA_SUCCESS;
     psa_key_policy_t policy;
     psa_crypto_generator_t generator = PSA_CRYPTO_GENERATOR_INIT;
 
+    *wrapping_key_handle = 0;
+    PSA_CHECK( psa_allocate_key( PSA_KEY_TYPE_AES, WRAPPING_KEY_BITS,
+                                 wrapping_key_handle ) );
     psa_key_policy_init( &policy );
     psa_key_policy_set_usage( &policy, usage, WRAPPING_ALG );
-    PSA_CHECK( psa_set_key_policy( wrapping_key_slot, &policy ) );
+    PSA_CHECK( psa_set_key_policy( *wrapping_key_handle, &policy ) );
 
     PSA_CHECK( psa_key_derivation(
                    &generator,
-                   derived_key_slot,
+                   derived_key_handle,
                    KDF_ALG,
                    WRAPPING_KEY_SALT, WRAPPING_KEY_SALT_LENGTH,
                    NULL, 0,
                    PSA_BITS_TO_BYTES( WRAPPING_KEY_BITS ) ) );
     PSA_CHECK( psa_generator_import_key(
-                   wrapping_key_slot,
+                   *wrapping_key_handle,
                    PSA_KEY_TYPE_AES,
                    WRAPPING_KEY_BITS,
                    &generator ) );
 
 exit:
     psa_generator_abort( &generator );
+    if( status != PSA_SUCCESS )
+    {
+        psa_close_key( *wrapping_key_handle );
+        *wrapping_key_handle = 0;
+    }
     return( status );
 }
 
 static psa_status_t wrap_data( const char *input_file_name,
-                               const char *output_file_name )
+                               const char *output_file_name,
+                               psa_key_handle_t wrapping_key_handle )
 {
     psa_status_t status;
     FILE *input_file = NULL;
@@ -407,7 +434,7 @@
 
     /* Wrap the data. */
     PSA_CHECK( psa_generate_random( header.iv, WRAPPING_IV_SIZE ) );
-    PSA_CHECK( psa_aead_encrypt( wrapping_key_slot, WRAPPING_ALG,
+    PSA_CHECK( psa_aead_encrypt( wrapping_key_handle, WRAPPING_ALG,
                                  header.iv, WRAPPING_IV_SIZE,
                                  (uint8_t *) &header, sizeof( header ),
                                  buffer, input_size,
@@ -435,7 +462,8 @@
 }
 
 static psa_status_t unwrap_data( const char *input_file_name,
-                                 const char *output_file_name )
+                                 const char *output_file_name,
+                                 psa_key_handle_t wrapping_key_handle )
 {
     psa_status_t status;
     FILE *input_file = NULL;
@@ -487,7 +515,7 @@
     input_file = NULL;
 
     /* Unwrap the data. */
-    PSA_CHECK( psa_aead_decrypt( wrapping_key_slot, WRAPPING_ALG,
+    PSA_CHECK( psa_aead_decrypt( wrapping_key_handle, WRAPPING_ALG,
                                  header.iv, WRAPPING_IV_SIZE,
                                  (uint8_t *) &header, sizeof( header ),
                                  buffer, ciphertext_size,
@@ -525,6 +553,8 @@
                          const char *output_file_name )
 {
     psa_status_t status = PSA_SUCCESS;
+    psa_key_handle_t derivation_key_handle = 0;
+    psa_key_handle_t wrapping_key_handle = 0;
 
     /* Initialize the PSA crypto library. */
     PSA_CHECK( psa_crypto_init( ) );
@@ -534,26 +564,33 @@
         return( generate( key_file_name ) );
 
     /* Read the master key. */
-    PSA_CHECK( import_key_from_file( master_key_slot,
-                                     PSA_KEY_USAGE_DERIVE | PSA_KEY_USAGE_EXPORT,
+    PSA_CHECK( import_key_from_file( PSA_KEY_USAGE_DERIVE | PSA_KEY_USAGE_EXPORT,
                                      KDF_ALG,
-                                     key_file_name ) );
+                                     key_file_name,
+                                     &derivation_key_handle ) );
 
     /* Calculate the derived key for this session. */
-    PSA_CHECK( derive_key_ladder( ladder, ladder_depth ) );
+    PSA_CHECK( derive_key_ladder( ladder, ladder_depth,
+                                  &derivation_key_handle ) );
 
     switch( mode )
     {
         case MODE_SAVE:
-            PSA_CHECK( save_key( derived_key_slot, output_file_name ) );
+            PSA_CHECK( save_key( derivation_key_handle, output_file_name ) );
             break;
         case MODE_UNWRAP:
-            PSA_CHECK( derive_wrapping_key( PSA_KEY_USAGE_DECRYPT ) );
-            PSA_CHECK( unwrap_data( input_file_name, output_file_name ) );
+            PSA_CHECK( derive_wrapping_key( PSA_KEY_USAGE_DECRYPT,
+                                            derivation_key_handle,
+                                            &wrapping_key_handle ) );
+            PSA_CHECK( unwrap_data( input_file_name, output_file_name,
+                                    wrapping_key_handle ) );
             break;
         case MODE_WRAP:
-            PSA_CHECK( derive_wrapping_key( PSA_KEY_USAGE_ENCRYPT ) );
-            PSA_CHECK( wrap_data( input_file_name, output_file_name ) );
+            PSA_CHECK( derive_wrapping_key( PSA_KEY_USAGE_ENCRYPT,
+                                            derivation_key_handle,
+                                            &wrapping_key_handle ) );
+            PSA_CHECK( wrap_data( input_file_name, output_file_name,
+                                  wrapping_key_handle ) );
             break;
         default:
             /* Unreachable but some compilers don't realize it. */
@@ -561,6 +598,11 @@
     }
 
 exit:
+    /* Close any remaining key. Deinitializing the crypto library would do
+     * this anyway, but explicitly closing handles makes the code easier
+     * to reuse. */
+    (void) psa_close_key( derivation_key_handle );
+    (void) psa_close_key( wrapping_key_handle );
     /* Deinitialize the PSA crypto library. */
     mbedtls_psa_crypto_free( );
     return( status );
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 56ce933..21cdfab 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -116,6 +116,7 @@
 add_test_suite(psa_crypto_init)
 add_test_suite(psa_crypto_metadata)
 add_test_suite(psa_crypto_persistent_key)
+add_test_suite(psa_crypto_slot_management)
 add_test_suite(psa_crypto_storage_file)
 add_test_suite(shax)
 add_test_suite(ssl)
diff --git a/tests/suites/helpers.function b/tests/suites/helpers.function
index f416b30..cbe3fa0 100644
--- a/tests/suites/helpers.function
+++ b/tests/suites/helpers.function
@@ -95,7 +95,7 @@
  * You must set \p pointer to \c NULL before calling this macro and
  * put `mbedtls_free( pointer )` in the test's cleanup code.
  *
- * If \p size is zero, the resulting \p pointer will be \c NULL.
+ * If \p length is zero, the resulting \p pointer will be \c NULL.
  * This is usually what we want in tests since API functions are
  * supposed to accept null pointers when a buffer size is zero.
  *
@@ -105,20 +105,21 @@
  * \param pointer   An lvalue where the address of the allocated buffer
  *                  will be stored.
  *                  This expression may be evaluated multiple times.
- * \param size      Buffer size to allocate in bytes.
+ * \param length    Number of elements to allocate.
  *                  This expression may be evaluated multiple times.
  *
  */
-#define ASSERT_ALLOC( pointer, size )                           \
-    do                                                          \
-    {                                                           \
-        TEST_ASSERT( ( pointer ) == NULL );                     \
-        if( ( size ) != 0 )                                     \
-        {                                                       \
-            ( pointer ) = mbedtls_calloc( 1, ( size ) );        \
-            TEST_ASSERT( ( pointer ) != NULL );                 \
-        }                                                       \
-    }                                                           \
+#define ASSERT_ALLOC( pointer, length )                           \
+    do                                                            \
+    {                                                             \
+        TEST_ASSERT( ( pointer ) == NULL );                       \
+        if( ( length ) != 0 )                                     \
+        {                                                         \
+            ( pointer ) = mbedtls_calloc( sizeof( *( pointer ) ), \
+                                          ( length ) );           \
+            TEST_ASSERT( ( pointer ) != NULL );                   \
+        }                                                         \
+    }                                                             \
     while( 0 )
 
 /** Compare two buffers and fail the test case if they differ.
diff --git a/tests/suites/test_suite_psa_crypto.data b/tests/suites/test_suite_psa_crypto.data
index 91739f5..848e8ed 100644
--- a/tests/suites/test_suite_psa_crypto.data
+++ b/tests/suites/test_suite_psa_crypto.data
@@ -1,9 +1,6 @@
 PSA compile-time sanity checks
 static_checks:
 
-PSA fill 250 slots
-fill_slots:250
-
 PSA import/export raw: 0 bytes
 import_export:"":PSA_KEY_TYPE_RAW_DATA:0:PSA_KEY_USAGE_EXPORT:0:0:PSA_SUCCESS:1
 
@@ -32,14 +29,14 @@
 depends_on:MBEDTLS_AES_C
 import_key_nonempty_slot
 
-PSA export empty key slot
-export_invalid_slot:1:PSA_ERROR_EMPTY_SLOT
+PSA export invalid handle (0)
+export_invalid_handle:0:PSA_ERROR_INVALID_HANDLE
 
-PSA export out of range key slot - lower bound
-export_invalid_slot:0:PSA_ERROR_INVALID_ARGUMENT
+PSA export invalid handle (smallest plausible handle)
+export_invalid_handle:1:PSA_ERROR_INVALID_HANDLE
 
-PSA export out of range key slot - upper bound
-export_invalid_slot:(psa_key_slot_t)(-1):PSA_ERROR_INVALID_ARGUMENT
+PSA export invalid handle (largest plausible handle)
+export_invalid_handle:-1:PSA_ERROR_INVALID_HANDLE
 
 PSA export a slot where there was some activity but no key material creation
 export_with_no_key_activity
@@ -320,6 +317,10 @@
 depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_BP512R1_ENABLED:MBEDTLS_RSA_C
 import:"3082013b020100024100ee2b131d6b1818a94ca8e91c42387eb15a7c271f57b89e7336b144d4535b16c83097ecdefbbb92d1b5313b5a37214d0e8f25922dca778b424b25295fc8a1a7070203010001024100978ac8eadb0dc6035347d6aba8671215ff21283385396f7897c04baf5e2a835f3b53ef80a82ed36ae687a925380b55a0c73eb85656e989dcf0ed7fb4887024e1022100fdad8e1c6853563f8b921d2d112462ae7d6b176082d2ba43e87e1a37fc1a8b33022100f0592cf4c55ba44307b18981bcdbda376c51e590ffa5345ba866f6962dca94dd02201995f1a967d44ff4a4cd1de837bc65bf97a2bf7eda730a9a62cea53254591105022027f96cf4b8ee68ff8d04062ec1ce7f18c0b74e4b3379b29f9bfea3fc8e592731022100cefa6d220496b43feb83194255d8fb930afcf46f36606e3aa0eb7a93ad88c10c":PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_BRAINPOOL_P512R1):PSA_ERROR_INVALID_ARGUMENT
 
+PSA import failure preserves policy
+depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15
+import_twice:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_USAGE_VERIFY:PSA_KEY_TYPE_RSA_PUBLIC_KEY:"":PSA_ERROR_INVALID_ARGUMENT:PSA_KEY_TYPE_RSA_PUBLIC_KEY:"30819f300d06092a864886f70d010101050003818d0030818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_SUCCESS
+
 PSA import RSA key pair: maximum size exceeded
 depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C
 import_rsa_made_up:PSA_VENDOR_RSA_MAX_KEY_BITS+8:1:PSA_ERROR_NOT_SUPPORTED
@@ -467,18 +468,6 @@
 depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECDH_C
 agreement_key_policy:PSA_KEY_USAGE_DERIVE:PSA_ALG_ECDH(PSA_ALG_SELECT_RAW):PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_SECP256R1):"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":PSA_ALG_FFDH(PSA_ALG_SELECT_RAW)
 
-PSA key lifetime: set and get volatile
-key_lifetime:PSA_KEY_LIFETIME_VOLATILE
-
-PSA key lifetime set: invalid key slot
-key_lifetime_set_fail:0:PSA_KEY_LIFETIME_VOLATILE:PSA_ERROR_INVALID_ARGUMENT
-
-PSA key lifetime set: cannot change write_once lifetime
-key_lifetime_set_fail:1:PSA_KEY_LIFETIME_WRITE_ONCE:PSA_ERROR_NOT_SUPPORTED
-
-PSA key lifetime set: invalid key lifetime value
-key_lifetime_set_fail:1:PSA_KEY_LIFETIME_PERSISTENT+1:PSA_ERROR_INVALID_ARGUMENT
-
 PSA hash setup: good, SHA-1
 depends_on:MBEDTLS_SHA1_C
 hash_setup:PSA_ALG_SHA_1:PSA_SUCCESS
diff --git a/tests/suites/test_suite_psa_crypto.function b/tests/suites/test_suite_psa_crypto.function
index 2fa060b..c40ac5f 100644
--- a/tests/suites/test_suite_psa_crypto.function
+++ b/tests/suites/test_suite_psa_crypto.function
@@ -130,7 +130,7 @@
     return( len );
 }
 
-static int exercise_mac_key( psa_key_slot_t key,
+static int exercise_mac_key( psa_key_handle_t handle,
                              psa_key_usage_t usage,
                              psa_algorithm_t alg )
 {
@@ -142,7 +142,7 @@
     if( usage & PSA_KEY_USAGE_SIGN )
     {
         TEST_ASSERT( psa_mac_sign_setup( &operation,
-                                         key, alg ) == PSA_SUCCESS );
+                                         handle, alg ) == PSA_SUCCESS );
         TEST_ASSERT( psa_mac_update( &operation,
                                      input, sizeof( input ) ) == PSA_SUCCESS );
         TEST_ASSERT( psa_mac_sign_finish( &operation,
@@ -157,7 +157,7 @@
               PSA_SUCCESS :
               PSA_ERROR_INVALID_SIGNATURE );
         TEST_ASSERT( psa_mac_verify_setup( &operation,
-                                           key, alg ) == PSA_SUCCESS );
+                                           handle, alg ) == PSA_SUCCESS );
         TEST_ASSERT( psa_mac_update( &operation,
                                      input, sizeof( input ) ) == PSA_SUCCESS );
         TEST_ASSERT( psa_mac_verify_finish( &operation,
@@ -172,7 +172,7 @@
     return( 0 );
 }
 
-static int exercise_cipher_key( psa_key_slot_t key,
+static int exercise_cipher_key( psa_key_handle_t handle,
                                 psa_key_usage_t usage,
                                 psa_algorithm_t alg )
 {
@@ -188,7 +188,7 @@
     if( usage & PSA_KEY_USAGE_ENCRYPT )
     {
         TEST_ASSERT( psa_cipher_encrypt_setup( &operation,
-                                               key, alg ) == PSA_SUCCESS );
+                                               handle, alg ) == PSA_SUCCESS );
         TEST_ASSERT( psa_cipher_generate_iv( &operation,
                                              iv, sizeof( iv ),
                                              &iv_length ) == PSA_SUCCESS );
@@ -210,11 +210,11 @@
         if( ! ( usage & PSA_KEY_USAGE_ENCRYPT ) )
         {
             size_t bits;
-            TEST_ASSERT( psa_get_key_information( key, &type, &bits ) );
+            TEST_ASSERT( psa_get_key_information( handle, &type, &bits ) );
             iv_length = PSA_BLOCK_CIPHER_BLOCK_SIZE( type );
         }
         TEST_ASSERT( psa_cipher_decrypt_setup( &operation,
-                                               key, alg ) == PSA_SUCCESS );
+                                               handle, alg ) == PSA_SUCCESS );
         TEST_ASSERT( psa_cipher_set_iv( &operation,
                                         iv, iv_length ) == PSA_SUCCESS );
         TEST_ASSERT( psa_cipher_update( &operation,
@@ -243,7 +243,7 @@
     return( 0 );
 }
 
-static int exercise_aead_key( psa_key_slot_t key,
+static int exercise_aead_key( psa_key_handle_t handle,
                               psa_key_usage_t usage,
                               psa_algorithm_t alg )
 {
@@ -256,7 +256,7 @@
 
     if( usage & PSA_KEY_USAGE_ENCRYPT )
     {
-        TEST_ASSERT( psa_aead_encrypt( key, alg,
+        TEST_ASSERT( psa_aead_encrypt( handle, alg,
                                        nonce, nonce_length,
                                        NULL, 0,
                                        plaintext, sizeof( plaintext ),
@@ -270,7 +270,7 @@
             ( usage & PSA_KEY_USAGE_ENCRYPT ?
               PSA_SUCCESS :
               PSA_ERROR_INVALID_SIGNATURE );
-        TEST_ASSERT( psa_aead_decrypt( key, alg,
+        TEST_ASSERT( psa_aead_decrypt( handle, alg,
                                        nonce, nonce_length,
                                        NULL, 0,
                                        ciphertext, ciphertext_length,
@@ -284,7 +284,7 @@
     return( 0 );
 }
 
-static int exercise_signature_key( psa_key_slot_t key,
+static int exercise_signature_key( psa_key_handle_t handle,
                                    psa_key_usage_t usage,
                                    psa_algorithm_t alg )
 {
@@ -301,7 +301,7 @@
         psa_algorithm_t hash_alg = PSA_ALG_SIGN_GET_HASH( alg );
         if( hash_alg != 0 )
             payload_length = PSA_HASH_SIZE( hash_alg );
-        TEST_ASSERT( psa_asymmetric_sign( key, alg,
+        TEST_ASSERT( psa_asymmetric_sign( handle, alg,
                                           payload, payload_length,
                                           signature, sizeof( signature ),
                                           &signature_length ) == PSA_SUCCESS );
@@ -313,7 +313,7 @@
             ( usage & PSA_KEY_USAGE_SIGN ?
               PSA_SUCCESS :
               PSA_ERROR_INVALID_SIGNATURE );
-        TEST_ASSERT( psa_asymmetric_verify( key, alg,
+        TEST_ASSERT( psa_asymmetric_verify( handle, alg,
                                             payload, payload_length,
                                             signature, signature_length ) ==
                      verify_status );
@@ -325,7 +325,7 @@
     return( 0 );
 }
 
-static int exercise_asymmetric_encryption_key( psa_key_slot_t key,
+static int exercise_asymmetric_encryption_key( psa_key_handle_t handle,
                                                psa_key_usage_t usage,
                                                psa_algorithm_t alg )
 {
@@ -337,7 +337,7 @@
     if( usage & PSA_KEY_USAGE_ENCRYPT )
     {
         TEST_ASSERT(
-            psa_asymmetric_encrypt( key, alg,
+            psa_asymmetric_encrypt( handle, alg,
                                     plaintext, plaintext_length,
                                     NULL, 0,
                                     ciphertext, sizeof( ciphertext ),
@@ -347,7 +347,7 @@
     if( usage & PSA_KEY_USAGE_DECRYPT )
     {
         psa_status_t status =
-            psa_asymmetric_decrypt( key, alg,
+            psa_asymmetric_decrypt( handle, alg,
                                     ciphertext, ciphertext_length,
                                     NULL, 0,
                                     plaintext, sizeof( plaintext ),
@@ -364,7 +364,7 @@
     return( 0 );
 }
 
-static int exercise_key_derivation_key( psa_key_slot_t key,
+static int exercise_key_derivation_key( psa_key_handle_t handle,
                                         psa_key_usage_t usage,
                                         psa_algorithm_t alg )
 {
@@ -378,7 +378,7 @@
     if( usage & PSA_KEY_USAGE_DERIVE )
     {
         TEST_ASSERT( psa_key_derivation( &generator,
-                                         key, alg,
+                                         handle, alg,
                                          label, label_length,
                                          seed, seed_length,
                                          sizeof( output ) ) == PSA_SUCCESS );
@@ -397,7 +397,7 @@
 /* We need two keys to exercise key agreement. Exercise the
  * private key against its own public key. */
 static psa_status_t key_agreement_with_self( psa_crypto_generator_t *generator,
-                                             psa_key_type_t key_slot,
+                                             psa_key_handle_t handle,
                                              psa_algorithm_t alg )
 {
     psa_key_type_t private_key_type;
@@ -410,18 +410,18 @@
      * good enough: callers will report it as a failed test anyway. */
     psa_status_t status = PSA_ERROR_UNKNOWN_ERROR;
 
-    TEST_ASSERT( psa_get_key_information( key_slot,
+    TEST_ASSERT( psa_get_key_information( handle,
                                           &private_key_type,
                                           &key_bits ) == PSA_SUCCESS );
     public_key_type = PSA_KEY_TYPE_PUBLIC_KEY_OF_KEYPAIR( private_key_type );
     public_key_length = PSA_KEY_EXPORT_MAX_SIZE( public_key_type, key_bits );
     ASSERT_ALLOC( public_key, public_key_length );
     TEST_ASSERT( public_key != NULL );
-    TEST_ASSERT( psa_export_public_key( key_slot,
+    TEST_ASSERT( psa_export_public_key( handle,
                                         public_key, public_key_length,
                                         &public_key_length ) == PSA_SUCCESS );
 
-    status = psa_key_agreement( generator, key_slot,
+    status = psa_key_agreement( generator, handle,
                                 public_key, public_key_length,
                                 alg );
 exit:
@@ -429,7 +429,7 @@
     return( status );
 }
 
-static int exercise_key_agreement_key( psa_key_slot_t key,
+static int exercise_key_agreement_key( psa_key_handle_t handle,
                                        psa_key_usage_t usage,
                                        psa_algorithm_t alg )
 {
@@ -441,7 +441,7 @@
     {
         /* We need two keys to exercise key agreement. Exercise the
          * private key against its own public key. */
-        TEST_ASSERT( key_agreement_with_self( &generator, key, alg ) ==
+        TEST_ASSERT( key_agreement_with_self( &generator, handle, alg ) ==
                      PSA_SUCCESS );
         TEST_ASSERT( psa_generator_read( &generator,
                                          output,
@@ -713,7 +713,7 @@
     return( 0 );
 }
 
-static int exercise_export_key( psa_key_slot_t slot,
+static int exercise_export_key( psa_key_handle_t handle,
                                 psa_key_usage_t usage )
 {
     psa_key_type_t type;
@@ -723,12 +723,12 @@
     size_t exported_length = 0;
     int ok = 0;
 
-    TEST_ASSERT( psa_get_key_information( slot, &type, &bits ) == PSA_SUCCESS );
+    TEST_ASSERT( psa_get_key_information( handle, &type, &bits ) == PSA_SUCCESS );
 
     if( ( usage & PSA_KEY_USAGE_EXPORT ) == 0 &&
         ! PSA_KEY_TYPE_IS_PUBLIC_KEY( type ) )
     {
-        TEST_ASSERT( psa_export_key( slot, NULL, 0, &exported_length ) ==
+        TEST_ASSERT( psa_export_key( handle, NULL, 0, &exported_length ) ==
                      PSA_ERROR_NOT_PERMITTED );
         return( 1 );
     }
@@ -736,7 +736,7 @@
     exported_size = PSA_KEY_EXPORT_MAX_SIZE( type, bits );
     ASSERT_ALLOC( exported, exported_size );
 
-    TEST_ASSERT( psa_export_key( slot,
+    TEST_ASSERT( psa_export_key( handle,
                                  exported, exported_size,
                                  &exported_length ) == PSA_SUCCESS );
     ok = exported_key_sanity_check( type, bits, exported, exported_length );
@@ -746,7 +746,7 @@
     return( ok );
 }
 
-static int exercise_export_public_key( psa_key_slot_t slot )
+static int exercise_export_public_key( psa_key_handle_t handle )
 {
     psa_key_type_t type;
     psa_key_type_t public_type;
@@ -756,10 +756,10 @@
     size_t exported_length = 0;
     int ok = 0;
 
-    TEST_ASSERT( psa_get_key_information( slot, &type, &bits ) == PSA_SUCCESS );
+    TEST_ASSERT( psa_get_key_information( handle, &type, &bits ) == PSA_SUCCESS );
     if( ! PSA_KEY_TYPE_IS_ASYMMETRIC( type ) )
     {
-        TEST_ASSERT( psa_export_public_key( slot,
+        TEST_ASSERT( psa_export_public_key( handle,
                                             NULL, 0, &exported_length ) ==
                      PSA_ERROR_INVALID_ARGUMENT );
         return( 1 );
@@ -769,7 +769,7 @@
     exported_size = PSA_KEY_EXPORT_MAX_SIZE( public_type, bits );
     ASSERT_ALLOC( exported, exported_size );
 
-    TEST_ASSERT( psa_export_public_key( slot,
+    TEST_ASSERT( psa_export_public_key( handle,
                                         exported, exported_size,
                                         &exported_length ) == PSA_SUCCESS );
     ok = exported_key_sanity_check( public_type, bits,
@@ -780,7 +780,7 @@
     return( ok );
 }
 
-static int exercise_key( psa_key_slot_t slot,
+static int exercise_key( psa_key_handle_t handle,
                          psa_key_usage_t usage,
                          psa_algorithm_t alg )
 {
@@ -788,19 +788,19 @@
     if( alg == 0 )
         ok = 1; /* If no algorihm, do nothing (used for raw data "keys"). */
     else if( PSA_ALG_IS_MAC( alg ) )
-        ok = exercise_mac_key( slot, usage, alg );
+        ok = exercise_mac_key( handle, usage, alg );
     else if( PSA_ALG_IS_CIPHER( alg ) )
-        ok = exercise_cipher_key( slot, usage, alg );
+        ok = exercise_cipher_key( handle, usage, alg );
     else if( PSA_ALG_IS_AEAD( alg ) )
-        ok = exercise_aead_key( slot, usage, alg );
+        ok = exercise_aead_key( handle, usage, alg );
     else if( PSA_ALG_IS_SIGN( alg ) )
-        ok = exercise_signature_key( slot, usage, alg );
+        ok = exercise_signature_key( handle, usage, alg );
     else if( PSA_ALG_IS_ASYMMETRIC_ENCRYPTION( alg ) )
-        ok = exercise_asymmetric_encryption_key( slot, usage, alg );
+        ok = exercise_asymmetric_encryption_key( handle, usage, alg );
     else if( PSA_ALG_IS_KEY_DERIVATION( alg ) )
-        ok = exercise_key_derivation_key( slot, usage, alg );
+        ok = exercise_key_derivation_key( handle, usage, alg );
     else if( PSA_ALG_IS_KEY_AGREEMENT( alg ) )
-        ok = exercise_key_agreement_key( slot, usage, alg );
+        ok = exercise_key_agreement_key( handle, usage, alg );
     else
     {
         char message[40];
@@ -811,8 +811,8 @@
         ok = 0;
     }
 
-    ok = ok && exercise_export_key( slot, usage );
-    ok = ok && exercise_export_public_key( slot );
+    ok = ok && exercise_export_key( handle, usage );
+    ok = ok && exercise_export_public_key( handle );
 
     return( ok );
 }
@@ -845,6 +845,13 @@
 
 }
 
+/* An overapproximation of the amount of storage needed for a key of the
+ * given type and with the given content. The API doesn't make it easy
+ * to find a good value for the size. The current implementation doesn't
+ * care about the value anyway. */
+#define KEY_BITS_FROM_DATA( type, data )        \
+    ( data )->len
+
 typedef enum {
     IMPORT_KEY = 0,
     GENERATE_KEY = 1,
@@ -872,65 +879,9 @@
 /* END_CASE */
 
 /* BEGIN_CASE */
-void fill_slots( int max_arg )
-{
-    /* Fill all the slots until we run out of memory or out of slots,
-     * or until some limit specified in the test data for the sake of
-     * implementations with an essentially unlimited number of slots.
-     * This test assumes that available slots are numbered from 1. */
-
-    psa_key_slot_t slot;
-    psa_key_slot_t max = 0;
-    psa_key_policy_t policy;
-    uint8_t exported[sizeof( max )];
-    size_t exported_size;
-    psa_status_t status;
-
-    TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS );
-
-    psa_key_policy_init( &policy );
-    psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_EXPORT, 0 );
-
-    for( max = 1; max <= (size_t) max_arg; max++ )
-    {
-        status = psa_set_key_policy( max, &policy );
-        /* Stop filling slots if we run out of memory or out of
-         * available slots. */
-        TEST_ASSERT( status == PSA_SUCCESS ||
-                     status == PSA_ERROR_INSUFFICIENT_MEMORY ||
-                     status == PSA_ERROR_INVALID_ARGUMENT );
-        if( status != PSA_SUCCESS )
-            break;
-        status = psa_import_key( max, PSA_KEY_TYPE_RAW_DATA,
-                                 (uint8_t*) &max, sizeof( max ) );
-        /* Since psa_set_key_policy succeeded, we know that the slot
-         * number is valid. But we may legitimately run out of memory. */
-        TEST_ASSERT( status == PSA_SUCCESS ||
-                     status == PSA_ERROR_INSUFFICIENT_MEMORY );
-        if( status != PSA_SUCCESS )
-            break;
-    }
-    /* `max` is now the first slot number that wasn't filled. */
-    max -= 1;
-
-    for( slot = 1; slot <= max; slot++ )
-    {
-        TEST_ASSERT( psa_export_key( slot,
-                                     exported, sizeof( exported ),
-                                     &exported_size ) == PSA_SUCCESS );
-        ASSERT_COMPARE( &slot, sizeof( slot ), exported, exported_size );
-    }
-
-exit:
-    /* Do not destroy the keys. mbedtls_psa_crypto_free() should do it. */
-    mbedtls_psa_crypto_free( );
-}
-/* END_CASE */
-
-/* BEGIN_CASE */
 void import( data_t *data, int type, int expected_status_arg )
 {
-    int slot = 1;
+    psa_key_handle_t handle = 0;
     psa_status_t expected_status = expected_status_arg;
     psa_status_t status;
 
@@ -938,10 +889,55 @@
     TEST_ASSERT( PSA_CRYPTO_TEST_SIZE_T_RANGE( data->len ) );
     TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS );
 
-    status = psa_import_key( slot, type, data->x, data->len );
+    TEST_ASSERT( psa_allocate_key( type, KEY_BITS_FROM_DATA( type, data ),
+                                   &handle ) == PSA_SUCCESS );
+    status = psa_import_key( handle, type, data->x, data->len );
     TEST_ASSERT( status == expected_status );
     if( status == PSA_SUCCESS )
-        TEST_ASSERT( psa_destroy_key( slot ) == PSA_SUCCESS );
+        TEST_ASSERT( psa_destroy_key( handle ) == PSA_SUCCESS );
+
+exit:
+    mbedtls_psa_crypto_free( );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void import_twice( int alg_arg, int usage_arg,
+                   int type1_arg, data_t *data1,
+                   int expected_import1_status_arg,
+                   int type2_arg, data_t *data2,
+                   int expected_import2_status_arg )
+{
+    psa_key_handle_t handle = 0;
+    psa_algorithm_t alg = alg_arg;
+    psa_key_usage_t usage = usage_arg;
+    psa_key_type_t type1 = type1_arg;
+    psa_status_t expected_import1_status = expected_import1_status_arg;
+    psa_key_type_t type2 = type2_arg;
+    psa_status_t expected_import2_status = expected_import2_status_arg;
+    psa_key_policy_t policy;
+    psa_status_t status;
+
+    TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS );
+
+    TEST_ASSERT( psa_allocate_key( type1,
+                                   MAX( KEY_BITS_FROM_DATA( type1, data1 ),
+                                        KEY_BITS_FROM_DATA( type2, data2 ) ),
+                                   &handle ) == PSA_SUCCESS );
+    psa_key_policy_init( &policy );
+    psa_key_policy_set_usage( &policy, usage, alg );
+    TEST_ASSERT( psa_set_key_policy( handle, &policy ) == PSA_SUCCESS );
+
+    status = psa_import_key( handle, type1, data1->x, data1->len );
+    TEST_ASSERT( status == expected_import1_status );
+    status = psa_import_key( handle, type2, data2->x, data2->len );
+    TEST_ASSERT( status == expected_import2_status );
+
+    if( expected_import1_status == PSA_SUCCESS ||
+        expected_import2_status == PSA_SUCCESS )
+    {
+        TEST_ASSERT( exercise_key( handle, usage, alg ) );
+    }
 
 exit:
     mbedtls_psa_crypto_free( );
@@ -951,7 +947,7 @@
 /* BEGIN_CASE */
 void import_rsa_made_up( int bits_arg, int keypair, int expected_status_arg )
 {
-    int slot = 1;
+    psa_key_handle_t handle = 0;
     size_t bits = bits_arg;
     psa_status_t expected_status = expected_status_arg;
     psa_status_t status;
@@ -972,10 +968,11 @@
     length = ret;
 
     /* Try importing the key */
-    status = psa_import_key( slot, type, p, length );
+    TEST_ASSERT( psa_allocate_key( type, bits, &handle ) == PSA_SUCCESS );
+    status = psa_import_key( handle, type, p, length );
     TEST_ASSERT( status == expected_status );
     if( status == PSA_SUCCESS )
-        TEST_ASSERT( psa_destroy_key( slot ) == PSA_SUCCESS );
+        TEST_ASSERT( psa_destroy_key( handle ) == PSA_SUCCESS );
 
 exit:
     mbedtls_free( buffer );
@@ -993,8 +990,7 @@
                     int expected_export_status_arg,
                     int canonical_input )
 {
-    int slot = 1;
-    int slot2 = slot + 1;
+    psa_key_handle_t handle = 0;
     psa_key_type_t type = type_arg;
     psa_algorithm_t alg = alg_arg;
     psa_status_t expected_export_status = expected_export_status_arg;
@@ -1016,23 +1012,28 @@
         ASSERT_ALLOC( reexported, export_size );
     TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS );
 
+    TEST_ASSERT( psa_allocate_key( type, expected_bits, &handle ) ==
+                 PSA_SUCCESS );
     psa_key_policy_init( &policy );
     psa_key_policy_set_usage( &policy, usage_arg, alg );
-    TEST_ASSERT( psa_set_key_policy( slot, &policy ) == PSA_SUCCESS );
+    TEST_ASSERT( psa_set_key_policy( handle, &policy ) == PSA_SUCCESS );
+
+    TEST_ASSERT( psa_get_key_information(
+                     handle, NULL, NULL ) == PSA_ERROR_EMPTY_SLOT );
 
     /* Import the key */
-    TEST_ASSERT( psa_import_key( slot, type,
+    TEST_ASSERT( psa_import_key( handle, type,
                                  data->x, data->len ) == PSA_SUCCESS );
 
     /* Test the key information */
-    TEST_ASSERT( psa_get_key_information( slot,
+    TEST_ASSERT( psa_get_key_information( handle,
                                           &got_type,
                                           &got_bits ) == PSA_SUCCESS );
     TEST_ASSERT( got_type == type );
     TEST_ASSERT( got_bits == (size_t) expected_bits );
 
     /* Export the key */
-    status = psa_export_key( slot,
+    status = psa_export_key( handle,
                              exported, export_size,
                              &exported_length );
     TEST_ASSERT( status == expected_export_status );
@@ -1051,32 +1052,36 @@
         goto destroy;
     }
 
-    if( ! exercise_export_key( slot, usage_arg ) )
+    if( ! exercise_export_key( handle, usage_arg ) )
         goto exit;
 
     if( canonical_input )
         ASSERT_COMPARE( data->x, data->len, exported, exported_length );
     else
     {
-        TEST_ASSERT( psa_set_key_policy( slot2, &policy ) == PSA_SUCCESS );
+        psa_key_handle_t handle2;
+        TEST_ASSERT( psa_allocate_key( type, expected_bits, &handle2 ) ==
+                     PSA_SUCCESS );
+        TEST_ASSERT( psa_set_key_policy( handle2, &policy ) == PSA_SUCCESS );
 
-        TEST_ASSERT( psa_import_key( slot2, type,
+        TEST_ASSERT( psa_import_key( handle2, type,
                                      exported,
                                      exported_length ) == PSA_SUCCESS );
-        TEST_ASSERT( psa_export_key( slot2,
+        TEST_ASSERT( psa_export_key( handle2,
                                      reexported,
                                      export_size,
                                      &reexported_length ) == PSA_SUCCESS );
         ASSERT_COMPARE( exported, exported_length,
                         reexported, reexported_length );
+        TEST_ASSERT( psa_close_key( handle2 ) == PSA_SUCCESS );
     }
     TEST_ASSERT( exported_length <= PSA_KEY_EXPORT_MAX_SIZE( type, got_bits ) );
 
 destroy:
     /* Destroy the key */
-    TEST_ASSERT( psa_destroy_key( slot ) == PSA_SUCCESS );
+    TEST_ASSERT( psa_destroy_key( handle ) == PSA_SUCCESS );
     TEST_ASSERT( psa_get_key_information(
-                     slot, NULL, NULL ) == PSA_ERROR_EMPTY_SLOT );
+                     handle, NULL, NULL ) == PSA_ERROR_INVALID_HANDLE );
 
 exit:
     mbedtls_free( exported );
@@ -1088,18 +1093,21 @@
 /* BEGIN_CASE */
 void import_key_nonempty_slot( )
 {
-    int slot = 1;
+    psa_key_handle_t handle = 0;
     psa_key_type_t type = PSA_KEY_TYPE_RAW_DATA;
     psa_status_t status;
     const uint8_t data[] = { 0x1, 0x2, 0x3, 0x4, 0x5 };
     TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS );
 
+    TEST_ASSERT( psa_allocate_key( type, PSA_BYTES_TO_BITS( sizeof( data ) ),
+                                   &handle ) == PSA_SUCCESS );
+
     /* Import the key */
-    TEST_ASSERT( psa_import_key( slot, type,
+    TEST_ASSERT( psa_import_key( handle, type,
                                  data, sizeof( data ) ) == PSA_SUCCESS );
 
     /* Import the key again */
-    status = psa_import_key( slot, type, data, sizeof( data ) );
+    status = psa_import_key( handle, type, data, sizeof( data ) );
     TEST_ASSERT( status == PSA_ERROR_OCCUPIED_SLOT );
 
 exit:
@@ -1108,7 +1116,7 @@
 /* END_CASE */
 
 /* BEGIN_CASE */
-void export_invalid_slot( int slot, int expected_export_status_arg )
+void export_invalid_handle( int handle, int expected_export_status_arg )
 {
     psa_status_t status;
     unsigned char *exported = NULL;
@@ -1119,7 +1127,7 @@
     TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS );
 
     /* Export the key */
-    status = psa_export_key( slot,
+    status = psa_export_key( (psa_key_handle_t) handle,
                              exported, export_size,
                              &exported_length );
     TEST_ASSERT( status == expected_export_status );
@@ -1132,7 +1140,7 @@
 /* BEGIN_CASE */
 void export_with_no_key_activity( )
 {
-    int slot = 1;
+    psa_key_handle_t handle = 0;
     psa_algorithm_t alg = PSA_ALG_CTR;
     psa_status_t status;
     psa_key_policy_t policy;
@@ -1142,12 +1150,14 @@
 
     TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS );
 
+    TEST_ASSERT( psa_allocate_key( PSA_KEY_TYPE_RAW_DATA, 0,
+                                   &handle ) == PSA_SUCCESS );
     psa_key_policy_init( &policy );
     psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_EXPORT, alg );
-    TEST_ASSERT( psa_set_key_policy( slot, &policy ) == PSA_SUCCESS );
+    TEST_ASSERT( psa_set_key_policy( handle, &policy ) == PSA_SUCCESS );
 
     /* Export the key */
-    status = psa_export_key( slot,
+    status = psa_export_key( handle,
                              exported, export_size,
                              &exported_length );
     TEST_ASSERT( status == PSA_ERROR_EMPTY_SLOT );
@@ -1160,7 +1170,7 @@
 /* BEGIN_CASE */
 void cipher_with_no_key_activity( )
 {
-    int slot = 1;
+    psa_key_handle_t handle = 0;
     psa_status_t status;
     psa_key_policy_t policy;
     psa_cipher_operation_t operation;
@@ -1168,11 +1178,13 @@
 
     TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS );
 
+    TEST_ASSERT( psa_allocate_key( PSA_KEY_TYPE_RAW_DATA, 0,
+                                   &handle ) == PSA_SUCCESS );
     psa_key_policy_init( &policy );
     psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_ENCRYPT, exercise_alg );
-    TEST_ASSERT( psa_set_key_policy( slot, &policy ) == PSA_SUCCESS );
+    TEST_ASSERT( psa_set_key_policy( handle, &policy ) == PSA_SUCCESS );
 
-    status = psa_cipher_encrypt_setup( &operation, slot, exercise_alg );
+    status = psa_cipher_encrypt_setup( &operation, handle, exercise_alg );
     TEST_ASSERT( status == PSA_ERROR_EMPTY_SLOT );
 
 exit:
@@ -1185,7 +1197,7 @@
 void export_after_import_failure( data_t *data, int type_arg,
                                   int expected_import_status_arg )
 {
-    int slot = 1;
+    psa_key_handle_t handle = 0;
     psa_key_type_t type = type_arg;
     psa_status_t status;
     unsigned char *exported = NULL;
@@ -1195,13 +1207,16 @@
 
     TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS );
 
+    TEST_ASSERT( psa_allocate_key( type, KEY_BITS_FROM_DATA( type, data ),
+                                   &handle ) == PSA_SUCCESS );
+
     /* Import the key - expect failure */
-    status = psa_import_key( slot, type,
+    status = psa_import_key( handle, type,
                                  data->x, data->len );
     TEST_ASSERT( status == expected_import_status );
 
     /* Export the key */
-    status = psa_export_key( slot,
+    status = psa_export_key( handle,
                              exported, export_size,
                              &exported_length );
     TEST_ASSERT( status == PSA_ERROR_EMPTY_SLOT );
@@ -1215,7 +1230,7 @@
 void cipher_after_import_failure( data_t *data, int type_arg,
                                   int expected_import_status_arg )
 {
-    int slot = 1;
+    psa_key_handle_t handle = 0;
     psa_cipher_operation_t operation;
     psa_key_type_t type = type_arg;
     psa_status_t status;
@@ -1224,12 +1239,15 @@
 
     TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS );
 
+    TEST_ASSERT( psa_allocate_key( type, KEY_BITS_FROM_DATA( type, data ),
+                                   &handle ) == PSA_SUCCESS );
+
     /* Import the key - expect failure */
-    status = psa_import_key( slot, type,
+    status = psa_import_key( handle, type,
                                  data->x, data->len );
     TEST_ASSERT( status == expected_import_status );
 
-    status = psa_cipher_encrypt_setup( &operation, slot, exercise_alg );
+    status = psa_cipher_encrypt_setup( &operation, handle, exercise_alg );
     TEST_ASSERT( status == PSA_ERROR_EMPTY_SLOT );
 
 exit:
@@ -1241,7 +1259,7 @@
 /* BEGIN_CASE */
 void export_after_destroy_key( data_t *data, int type_arg )
 {
-    int slot = 1;
+    psa_key_handle_t handle = 0;
     psa_key_type_t type = type_arg;
     psa_status_t status;
     psa_key_policy_t policy;
@@ -1252,26 +1270,28 @@
 
     TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS );
 
+    TEST_ASSERT( psa_allocate_key( type, KEY_BITS_FROM_DATA( type, data ),
+                                   &handle ) == PSA_SUCCESS );
     psa_key_policy_init( &policy );
     psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_EXPORT, alg );
-    TEST_ASSERT( psa_set_key_policy( slot, &policy ) == PSA_SUCCESS );
+    TEST_ASSERT( psa_set_key_policy( handle, &policy ) == PSA_SUCCESS );
     export_size = (ptrdiff_t) data->len;
     ASSERT_ALLOC( exported, export_size );
 
     /* Import the key */
-    TEST_ASSERT( psa_import_key( slot, type,
+    TEST_ASSERT( psa_import_key( handle, type,
                                  data->x, data->len ) == PSA_SUCCESS );
 
-    TEST_ASSERT( psa_export_key( slot, exported, export_size,
+    TEST_ASSERT( psa_export_key( handle, exported, export_size,
                                  &exported_length ) == PSA_SUCCESS );
 
     /* Destroy the key */
-    TEST_ASSERT( psa_destroy_key( slot ) == PSA_SUCCESS );
+    TEST_ASSERT( psa_destroy_key( handle ) == PSA_SUCCESS );
 
     /* Export the key */
-    status = psa_export_key( slot, exported, export_size,
+    status = psa_export_key( handle, exported, export_size,
                              &exported_length );
-    TEST_ASSERT( status == PSA_ERROR_EMPTY_SLOT );
+    TEST_ASSERT( status == PSA_ERROR_INVALID_HANDLE );
 
 exit:
     mbedtls_free( exported );
@@ -1287,7 +1307,7 @@
                                int expected_export_status_arg,
                                data_t *expected_public_key )
 {
-    int slot = 1;
+    psa_key_handle_t handle = 0;
     psa_key_type_t type = type_arg;
     psa_algorithm_t alg = alg_arg;
     psa_status_t expected_export_status = expected_export_status_arg;
@@ -1299,17 +1319,19 @@
 
     TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS );
 
+    TEST_ASSERT( psa_allocate_key( type, KEY_BITS_FROM_DATA( type, data ),
+                                   &handle ) == PSA_SUCCESS );
     psa_key_policy_init( &policy );
     psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_EXPORT, alg );
-    TEST_ASSERT( psa_set_key_policy( slot, &policy ) == PSA_SUCCESS );
+    TEST_ASSERT( psa_set_key_policy( handle, &policy ) == PSA_SUCCESS );
 
     /* Import the key */
-    TEST_ASSERT( psa_import_key( slot, type,
+    TEST_ASSERT( psa_import_key( handle, type,
                                  data->x, data->len ) == PSA_SUCCESS );
 
     /* Export the public key */
     ASSERT_ALLOC( exported, export_size );
-    status = psa_export_public_key( slot,
+    status = psa_export_public_key( handle,
                                     exported, export_size,
                                     &exported_length );
     TEST_ASSERT( status == expected_export_status );
@@ -1317,7 +1339,7 @@
     {
         psa_key_type_t public_type = PSA_KEY_TYPE_PUBLIC_KEY_OF_KEYPAIR( type );
         size_t bits;
-        TEST_ASSERT( psa_get_key_information( slot, NULL, &bits ) ==
+        TEST_ASSERT( psa_get_key_information( handle, NULL, &bits ) ==
                      PSA_SUCCESS );
         TEST_ASSERT( expected_public_key->len <=
                      PSA_KEY_EXPORT_MAX_SIZE( public_type, bits ) );
@@ -1327,7 +1349,7 @@
 
 exit:
     mbedtls_free( exported );
-    psa_destroy_key( slot );
+    psa_destroy_key( handle );
     mbedtls_psa_crypto_free( );
 }
 /* END_CASE */
@@ -1338,7 +1360,7 @@
                               int bits_arg,
                               int alg_arg )
 {
-    int slot = 1;
+    psa_key_handle_t handle = 0;
     psa_key_type_t type = type_arg;
     size_t bits = bits_arg;
     psa_algorithm_t alg = alg_arg;
@@ -1350,27 +1372,29 @@
 
     TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS );
 
+    TEST_ASSERT( psa_allocate_key( type, KEY_BITS_FROM_DATA( type, data ),
+                                   &handle ) == PSA_SUCCESS );
     psa_key_policy_init( &policy );
     psa_key_policy_set_usage( &policy, usage, alg );
-    TEST_ASSERT( psa_set_key_policy( slot, &policy ) == PSA_SUCCESS );
+    TEST_ASSERT( psa_set_key_policy( handle, &policy ) == PSA_SUCCESS );
 
     /* Import the key */
-    status = psa_import_key( slot, type, data->x, data->len );
+    status = psa_import_key( handle, type, data->x, data->len );
     TEST_ASSERT( status == PSA_SUCCESS );
 
     /* Test the key information */
-    TEST_ASSERT( psa_get_key_information( slot,
+    TEST_ASSERT( psa_get_key_information( handle,
                                           &got_type,
                                           &got_bits ) == PSA_SUCCESS );
     TEST_ASSERT( got_type == type );
     TEST_ASSERT( got_bits == bits );
 
     /* Do something with the key according to its type and permitted usage. */
-    if( ! exercise_key( slot, usage, alg ) )
+    if( ! exercise_key( handle, usage, alg ) )
         goto exit;
 
 exit:
-    psa_destroy_key( slot );
+    psa_destroy_key( handle );
     mbedtls_psa_crypto_free( );
 }
 /* END_CASE */
@@ -1378,7 +1402,7 @@
 /* BEGIN_CASE */
 void key_policy( int usage_arg, int alg_arg )
 {
-    int key_slot = 1;
+    psa_key_handle_t handle = 0;
     psa_algorithm_t alg = alg_arg;
     psa_key_usage_t usage = usage_arg;
     psa_key_type_t key_type = PSA_KEY_TYPE_AES;
@@ -1390,25 +1414,26 @@
 
     TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS );
 
+    TEST_ASSERT( psa_allocate_key( key_type, PSA_BYTES_TO_BITS( sizeof( key ) ),
+                                   &handle ) == PSA_SUCCESS );
     psa_key_policy_init( &policy_set );
     psa_key_policy_init( &policy_get );
-
     psa_key_policy_set_usage( &policy_set, usage, alg );
 
     TEST_ASSERT( psa_key_policy_get_usage( &policy_set ) == usage );
     TEST_ASSERT( psa_key_policy_get_algorithm( &policy_set ) == alg );
-    TEST_ASSERT( psa_set_key_policy( key_slot, &policy_set ) == PSA_SUCCESS );
+    TEST_ASSERT( psa_set_key_policy( handle, &policy_set ) == PSA_SUCCESS );
 
-    TEST_ASSERT( psa_import_key( key_slot, key_type,
+    TEST_ASSERT( psa_import_key( handle, key_type,
                                  key, sizeof( key ) ) == PSA_SUCCESS );
 
-    TEST_ASSERT( psa_get_key_policy( key_slot, &policy_get ) == PSA_SUCCESS );
+    TEST_ASSERT( psa_get_key_policy( handle, &policy_get ) == PSA_SUCCESS );
 
     TEST_ASSERT( policy_get.usage == policy_set.usage );
     TEST_ASSERT( policy_get.alg == policy_set.alg );
 
 exit:
-    psa_destroy_key( key_slot );
+    psa_destroy_key( handle );
     mbedtls_psa_crypto_free( );
 }
 /* END_CASE */
@@ -1420,7 +1445,7 @@
                      data_t *key_data,
                      int exercise_alg )
 {
-    int key_slot = 1;
+    psa_key_handle_t handle = 0;
     psa_key_policy_t policy;
     psa_mac_operation_t operation;
     psa_status_t status;
@@ -1428,14 +1453,17 @@
 
     TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS );
 
+    TEST_ASSERT( psa_allocate_key( key_type,
+                                   KEY_BITS_FROM_DATA( key_type, key_data ),
+                                   &handle ) == PSA_SUCCESS );
     psa_key_policy_init( &policy );
     psa_key_policy_set_usage( &policy, policy_usage, policy_alg );
-    TEST_ASSERT( psa_set_key_policy( key_slot, &policy ) == PSA_SUCCESS );
+    TEST_ASSERT( psa_set_key_policy( handle, &policy ) == PSA_SUCCESS );
 
-    TEST_ASSERT( psa_import_key( key_slot, key_type,
+    TEST_ASSERT( psa_import_key( handle, key_type,
                                  key_data->x, key_data->len ) == PSA_SUCCESS );
 
-    status = psa_mac_sign_setup( &operation, key_slot, exercise_alg );
+    status = psa_mac_sign_setup( &operation, handle, exercise_alg );
     if( policy_alg == exercise_alg &&
         ( policy_usage & PSA_KEY_USAGE_SIGN ) != 0 )
         TEST_ASSERT( status == PSA_SUCCESS );
@@ -1444,7 +1472,7 @@
     psa_mac_abort( &operation );
 
     memset( mac, 0, sizeof( mac ) );
-    status = psa_mac_verify_setup( &operation, key_slot, exercise_alg );
+    status = psa_mac_verify_setup( &operation, handle, exercise_alg );
     if( policy_alg == exercise_alg &&
         ( policy_usage & PSA_KEY_USAGE_VERIFY ) != 0 )
         TEST_ASSERT( status == PSA_SUCCESS );
@@ -1453,7 +1481,7 @@
 
 exit:
     psa_mac_abort( &operation );
-    psa_destroy_key( key_slot );
+    psa_destroy_key( handle );
     mbedtls_psa_crypto_free( );
 }
 /* END_CASE */
@@ -1465,21 +1493,24 @@
                         data_t *key_data,
                         int exercise_alg )
 {
-    int key_slot = 1;
+    psa_key_handle_t handle = 0;
     psa_key_policy_t policy;
     psa_cipher_operation_t operation;
     psa_status_t status;
 
     TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS );
 
+    TEST_ASSERT( psa_allocate_key( key_type,
+                                   KEY_BITS_FROM_DATA( key_type, key_data ),
+                                   &handle ) == PSA_SUCCESS );
     psa_key_policy_init( &policy );
     psa_key_policy_set_usage( &policy, policy_usage, policy_alg );
-    TEST_ASSERT( psa_set_key_policy( key_slot, &policy ) == PSA_SUCCESS );
+    TEST_ASSERT( psa_set_key_policy( handle, &policy ) == PSA_SUCCESS );
 
-    TEST_ASSERT( psa_import_key( key_slot, key_type,
+    TEST_ASSERT( psa_import_key( handle, key_type,
                                  key_data->x, key_data->len ) == PSA_SUCCESS );
 
-    status = psa_cipher_encrypt_setup( &operation, key_slot, exercise_alg );
+    status = psa_cipher_encrypt_setup( &operation, handle, exercise_alg );
     if( policy_alg == exercise_alg &&
         ( policy_usage & PSA_KEY_USAGE_ENCRYPT ) != 0 )
         TEST_ASSERT( status == PSA_SUCCESS );
@@ -1487,7 +1518,7 @@
         TEST_ASSERT( status == PSA_ERROR_NOT_PERMITTED );
     psa_cipher_abort( &operation );
 
-    status = psa_cipher_decrypt_setup( &operation, key_slot, exercise_alg );
+    status = psa_cipher_decrypt_setup( &operation, handle, exercise_alg );
     if( policy_alg == exercise_alg &&
         ( policy_usage & PSA_KEY_USAGE_DECRYPT ) != 0 )
         TEST_ASSERT( status == PSA_SUCCESS );
@@ -1496,7 +1527,7 @@
 
 exit:
     psa_cipher_abort( &operation );
-    psa_destroy_key( key_slot );
+    psa_destroy_key( handle );
     mbedtls_psa_crypto_free( );
 }
 /* END_CASE */
@@ -1510,7 +1541,7 @@
                       int tag_length_arg,
                       int exercise_alg )
 {
-    int key_slot = 1;
+    psa_key_handle_t handle = 0;
     psa_key_policy_t policy;
     psa_status_t status;
     unsigned char nonce[16] = {0};
@@ -1524,14 +1555,17 @@
 
     TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS );
 
+    TEST_ASSERT( psa_allocate_key( key_type,
+                                   KEY_BITS_FROM_DATA( key_type, key_data ),
+                                   &handle ) == PSA_SUCCESS );
     psa_key_policy_init( &policy );
     psa_key_policy_set_usage( &policy, policy_usage, policy_alg );
-    TEST_ASSERT( psa_set_key_policy( key_slot, &policy ) == PSA_SUCCESS );
+    TEST_ASSERT( psa_set_key_policy( handle, &policy ) == PSA_SUCCESS );
 
-    TEST_ASSERT( psa_import_key( key_slot, key_type,
+    TEST_ASSERT( psa_import_key( handle, key_type,
                                  key_data->x, key_data->len ) == PSA_SUCCESS );
 
-    status = psa_aead_encrypt( key_slot, exercise_alg,
+    status = psa_aead_encrypt( handle, exercise_alg,
                                nonce, nonce_length,
                                NULL, 0,
                                NULL, 0,
@@ -1544,7 +1578,7 @@
         TEST_ASSERT( status == PSA_ERROR_NOT_PERMITTED );
 
     memset( tag, 0, sizeof( tag ) );
-    status = psa_aead_decrypt( key_slot, exercise_alg,
+    status = psa_aead_decrypt( handle, exercise_alg,
                                nonce, nonce_length,
                                NULL, 0,
                                tag, tag_length,
@@ -1557,7 +1591,7 @@
         TEST_ASSERT( status == PSA_ERROR_NOT_PERMITTED );
 
 exit:
-    psa_destroy_key( key_slot );
+    psa_destroy_key( handle );
     mbedtls_psa_crypto_free( );
 }
 /* END_CASE */
@@ -1569,7 +1603,7 @@
                                        data_t *key_data,
                                        int exercise_alg )
 {
-    int key_slot = 1;
+    psa_key_handle_t handle = 0;
     psa_key_policy_t policy;
     psa_status_t status;
     size_t key_bits;
@@ -1579,21 +1613,24 @@
 
     TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS );
 
+    TEST_ASSERT( psa_allocate_key( key_type,
+                                   KEY_BITS_FROM_DATA( key_type, key_data ),
+                                   &handle ) == PSA_SUCCESS );
     psa_key_policy_init( &policy );
     psa_key_policy_set_usage( &policy, policy_usage, policy_alg );
-    TEST_ASSERT( psa_set_key_policy( key_slot, &policy ) == PSA_SUCCESS );
+    TEST_ASSERT( psa_set_key_policy( handle, &policy ) == PSA_SUCCESS );
 
-    TEST_ASSERT( psa_import_key( key_slot, key_type,
+    TEST_ASSERT( psa_import_key( handle, key_type,
                                  key_data->x, key_data->len ) == PSA_SUCCESS );
 
-    TEST_ASSERT( psa_get_key_information( key_slot,
+    TEST_ASSERT( psa_get_key_information( handle,
                                           NULL,
                                           &key_bits ) == PSA_SUCCESS );
     buffer_length = PSA_ASYMMETRIC_ENCRYPT_OUTPUT_SIZE( key_type, key_bits,
                                                         exercise_alg );
     ASSERT_ALLOC( buffer, buffer_length );
 
-    status = psa_asymmetric_encrypt( key_slot, exercise_alg,
+    status = psa_asymmetric_encrypt( handle, exercise_alg,
                                      NULL, 0,
                                      NULL, 0,
                                      buffer, buffer_length,
@@ -1606,7 +1643,7 @@
 
     if( buffer_length != 0 )
         memset( buffer, 0, buffer_length );
-    status = psa_asymmetric_decrypt( key_slot, exercise_alg,
+    status = psa_asymmetric_decrypt( handle, exercise_alg,
                                      buffer, buffer_length,
                                      NULL, 0,
                                      buffer, buffer_length,
@@ -1618,7 +1655,7 @@
         TEST_ASSERT( status == PSA_ERROR_NOT_PERMITTED );
 
 exit:
-    psa_destroy_key( key_slot );
+    psa_destroy_key( handle );
     mbedtls_psa_crypto_free( );
     mbedtls_free( buffer );
 }
@@ -1631,7 +1668,7 @@
                                       data_t *key_data,
                                       int exercise_alg )
 {
-    int key_slot = 1;
+    psa_key_handle_t handle = 0;
     psa_key_policy_t policy;
     psa_status_t status;
     unsigned char payload[16] = {1};
@@ -1641,14 +1678,17 @@
 
     TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS );
 
+    TEST_ASSERT( psa_allocate_key( key_type,
+                                   KEY_BITS_FROM_DATA( key_type, key_data ),
+                                   &handle ) == PSA_SUCCESS );
     psa_key_policy_init( &policy );
     psa_key_policy_set_usage( &policy, policy_usage, policy_alg );
-    TEST_ASSERT( psa_set_key_policy( key_slot, &policy ) == PSA_SUCCESS );
+    TEST_ASSERT( psa_set_key_policy( handle, &policy ) == PSA_SUCCESS );
 
-    TEST_ASSERT( psa_import_key( key_slot, key_type,
+    TEST_ASSERT( psa_import_key( handle, key_type,
                                  key_data->x, key_data->len ) == PSA_SUCCESS );
 
-    status = psa_asymmetric_sign( key_slot, exercise_alg,
+    status = psa_asymmetric_sign( handle, exercise_alg,
                                   payload, payload_length,
                                   signature, sizeof( signature ),
                                   &signature_length );
@@ -1659,7 +1699,7 @@
         TEST_ASSERT( status == PSA_ERROR_NOT_PERMITTED );
 
     memset( signature, 0, sizeof( signature ) );
-    status = psa_asymmetric_verify( key_slot, exercise_alg,
+    status = psa_asymmetric_verify( handle, exercise_alg,
                                     payload, payload_length,
                                     signature, sizeof( signature ) );
     if( policy_alg == exercise_alg &&
@@ -1669,7 +1709,7 @@
         TEST_ASSERT( status == PSA_ERROR_NOT_PERMITTED );
 
 exit:
-    psa_destroy_key( key_slot );
+    psa_destroy_key( handle );
     mbedtls_psa_crypto_free( );
 }
 /* END_CASE */
@@ -1681,21 +1721,24 @@
                         data_t *key_data,
                         int exercise_alg )
 {
-    int key_slot = 1;
+    psa_key_handle_t handle = 0;
     psa_key_policy_t policy;
     psa_crypto_generator_t generator = PSA_CRYPTO_GENERATOR_INIT;
     psa_status_t status;
 
     TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS );
 
+    TEST_ASSERT( psa_allocate_key( key_type,
+                                   KEY_BITS_FROM_DATA( key_type, key_data ),
+                                   &handle ) == PSA_SUCCESS );
     psa_key_policy_init( &policy );
     psa_key_policy_set_usage( &policy, policy_usage, policy_alg );
-    TEST_ASSERT( psa_set_key_policy( key_slot, &policy ) == PSA_SUCCESS );
+    TEST_ASSERT( psa_set_key_policy( handle, &policy ) == PSA_SUCCESS );
 
-    TEST_ASSERT( psa_import_key( key_slot, key_type,
+    TEST_ASSERT( psa_import_key( handle, key_type,
                                  key_data->x, key_data->len ) == PSA_SUCCESS );
 
-    status = psa_key_derivation( &generator, key_slot,
+    status = psa_key_derivation( &generator, handle,
                                  exercise_alg,
                                  NULL, 0,
                                  NULL, 0,
@@ -1708,7 +1751,7 @@
 
 exit:
     psa_generator_abort( &generator );
-    psa_destroy_key( key_slot );
+    psa_destroy_key( handle );
     mbedtls_psa_crypto_free( );
 }
 /* END_CASE */
@@ -1720,7 +1763,7 @@
                            data_t *key_data,
                            int exercise_alg )
 {
-    int key_slot = 1;
+    psa_key_handle_t handle = 0;
     psa_key_policy_t policy;
     psa_key_type_t key_type = key_type_arg;
     psa_crypto_generator_t generator = PSA_CRYPTO_GENERATOR_INIT;
@@ -1728,14 +1771,17 @@
 
     TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS );
 
+    TEST_ASSERT( psa_allocate_key( key_type,
+                                   KEY_BITS_FROM_DATA( key_type, key_data ),
+                                   &handle ) == PSA_SUCCESS );
     psa_key_policy_init( &policy );
     psa_key_policy_set_usage( &policy, policy_usage, policy_alg );
-    TEST_ASSERT( psa_set_key_policy( key_slot, &policy ) == PSA_SUCCESS );
+    TEST_ASSERT( psa_set_key_policy( handle, &policy ) == PSA_SUCCESS );
 
-    TEST_ASSERT( psa_import_key( key_slot, key_type,
+    TEST_ASSERT( psa_import_key( handle, key_type,
                                  key_data->x, key_data->len ) == PSA_SUCCESS );
 
-    status = key_agreement_with_self( &generator, key_slot, exercise_alg );
+    status = key_agreement_with_self( &generator, handle, exercise_alg );
 
     if( policy_alg == exercise_alg &&
         ( policy_usage & PSA_KEY_USAGE_DERIVE ) != 0 )
@@ -1745,62 +1791,7 @@
 
 exit:
     psa_generator_abort( &generator );
-    psa_destroy_key( key_slot );
-    mbedtls_psa_crypto_free( );
-}
-/* END_CASE */
-
-/* BEGIN_CASE */
-void key_lifetime( int lifetime_arg )
-{
-    int key_slot = 1;
-    psa_key_type_t key_type = PSA_KEY_TYPE_RAW_DATA;
-    unsigned char key[32] = {0};
-    psa_key_lifetime_t lifetime_set = lifetime_arg;
-    psa_key_lifetime_t lifetime_get;
-
-    memset( key, 0x2a, sizeof( key ) );
-
-    TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS );
-
-    TEST_ASSERT( psa_set_key_lifetime( key_slot,
-                                       lifetime_set ) == PSA_SUCCESS );
-
-    TEST_ASSERT( psa_import_key( key_slot, key_type,
-                                 key, sizeof( key ) ) == PSA_SUCCESS );
-
-    TEST_ASSERT( psa_get_key_lifetime( key_slot,
-                                       &lifetime_get ) == PSA_SUCCESS );
-
-    TEST_ASSERT( lifetime_get == lifetime_set );
-
-exit:
-    psa_destroy_key( key_slot );
-    mbedtls_psa_crypto_free( );
-}
-/* END_CASE */
-
-/* BEGIN_CASE */
-void key_lifetime_set_fail( int key_slot_arg,
-                            int lifetime_arg,
-                            int expected_status_arg )
-{
-    psa_key_slot_t key_slot = key_slot_arg;
-    psa_key_lifetime_t lifetime_set = lifetime_arg;
-    psa_status_t actual_status;
-    psa_status_t expected_status = expected_status_arg;
-
-    TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS );
-
-    actual_status = psa_set_key_lifetime( key_slot, lifetime_set );
-
-    if( actual_status == PSA_SUCCESS )
-        actual_status = psa_set_key_lifetime( key_slot, lifetime_set );
-
-    TEST_ASSERT( expected_status == actual_status );
-
-exit:
-    psa_destroy_key( key_slot );
+    psa_destroy_key( handle );
     mbedtls_psa_crypto_free( );
 }
 /* END_CASE */
@@ -1928,7 +1919,7 @@
                 int alg_arg,
                 int expected_status_arg )
 {
-    int key_slot = 1;
+    psa_key_handle_t handle = 0;
     psa_key_type_t key_type = key_type_arg;
     psa_algorithm_t alg = alg_arg;
     psa_status_t expected_status = expected_status_arg;
@@ -1938,21 +1929,23 @@
 
     TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS );
 
+    TEST_ASSERT( psa_allocate_key( key_type, PSA_BYTES_TO_BITS( key->len ),
+                                   &handle ) == PSA_SUCCESS );
     psa_key_policy_init( &policy );
     psa_key_policy_set_usage( &policy,
                               PSA_KEY_USAGE_SIGN | PSA_KEY_USAGE_VERIFY,
                               alg );
-    TEST_ASSERT( psa_set_key_policy( key_slot, &policy ) == PSA_SUCCESS );
+    TEST_ASSERT( psa_set_key_policy( handle, &policy ) == PSA_SUCCESS );
 
-    TEST_ASSERT( psa_import_key( key_slot, key_type,
+    TEST_ASSERT( psa_import_key( handle, key_type,
                                  key->x, key->len ) == PSA_SUCCESS );
 
-    status = psa_mac_sign_setup( &operation, key_slot, alg );
+    status = psa_mac_sign_setup( &operation, handle, alg );
     psa_mac_abort( &operation );
     TEST_ASSERT( status == expected_status );
 
 exit:
-    psa_destroy_key( key_slot );
+    psa_destroy_key( handle );
     mbedtls_psa_crypto_free( );
 }
 /* END_CASE */
@@ -1964,7 +1957,7 @@
                data_t *input,
                data_t *expected_mac )
 {
-    int key_slot = 1;
+    psa_key_handle_t handle = 0;
     psa_key_type_t key_type = key_type_arg;
     psa_algorithm_t alg = alg_arg;
     psa_mac_operation_t operation;
@@ -1983,16 +1976,18 @@
 
     TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS );
 
+    TEST_ASSERT( psa_allocate_key( key_type, PSA_BYTES_TO_BITS( key->len ),
+                                   &handle ) == PSA_SUCCESS );
     psa_key_policy_init( &policy );
     psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_SIGN, alg );
-    TEST_ASSERT( psa_set_key_policy( key_slot, &policy ) == PSA_SUCCESS );
+    TEST_ASSERT( psa_set_key_policy( handle, &policy ) == PSA_SUCCESS );
 
-    TEST_ASSERT( psa_import_key( key_slot, key_type,
+    TEST_ASSERT( psa_import_key( handle, key_type,
                                  key->x, key->len ) == PSA_SUCCESS );
 
     /* Calculate the MAC. */
     TEST_ASSERT( psa_mac_sign_setup( &operation,
-                                     key_slot, alg ) == PSA_SUCCESS );
+                                     handle, alg ) == PSA_SUCCESS );
     TEST_ASSERT( psa_mac_update( &operation,
                                  input->x, input->len ) == PSA_SUCCESS );
     TEST_ASSERT( psa_mac_sign_finish( &operation,
@@ -2008,7 +2003,7 @@
                               sizeof( actual_mac ) - mac_length ) );
 
 exit:
-    psa_destroy_key( key_slot );
+    psa_destroy_key( handle );
     mbedtls_psa_crypto_free( );
 }
 /* END_CASE */
@@ -2020,7 +2015,7 @@
                  data_t *input,
                  data_t *expected_mac )
 {
-    int key_slot = 1;
+    psa_key_handle_t handle = 0;
     psa_key_type_t key_type = key_type_arg;
     psa_algorithm_t alg = alg_arg;
     psa_mac_operation_t operation;
@@ -2037,16 +2032,18 @@
 
     TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS );
 
+    TEST_ASSERT( psa_allocate_key( key_type, PSA_BYTES_TO_BITS( key->len ),
+                                   &handle ) == PSA_SUCCESS );
     psa_key_policy_init( &policy );
     psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_VERIFY, alg );
-    TEST_ASSERT( psa_set_key_policy( key_slot, &policy ) == PSA_SUCCESS );
+    TEST_ASSERT( psa_set_key_policy( handle, &policy ) == PSA_SUCCESS );
 
-    TEST_ASSERT( psa_import_key( key_slot, key_type,
+    TEST_ASSERT( psa_import_key( handle, key_type,
                                  key->x, key->len ) == PSA_SUCCESS );
 
     TEST_ASSERT( psa_mac_verify_setup( &operation,
-                                       key_slot, alg ) == PSA_SUCCESS );
-    TEST_ASSERT( psa_destroy_key( key_slot ) == PSA_SUCCESS );
+                                       handle, alg ) == PSA_SUCCESS );
+    TEST_ASSERT( psa_destroy_key( handle ) == PSA_SUCCESS );
     TEST_ASSERT( psa_mac_update( &operation,
                                  input->x, input->len ) == PSA_SUCCESS );
     TEST_ASSERT( psa_mac_verify_finish( &operation,
@@ -2054,7 +2051,7 @@
                                         expected_mac->len ) == PSA_SUCCESS );
 
 exit:
-    psa_destroy_key( key_slot );
+    psa_destroy_key( handle );
     mbedtls_psa_crypto_free( );
 }
 /* END_CASE */
@@ -2065,7 +2062,7 @@
                    int alg_arg,
                    int expected_status_arg )
 {
-    int key_slot = 1;
+    psa_key_handle_t handle = 0;
     psa_key_type_t key_type = key_type_arg;
     psa_algorithm_t alg = alg_arg;
     psa_status_t expected_status = expected_status_arg;
@@ -2075,19 +2072,21 @@
 
     TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS );
 
+    TEST_ASSERT( psa_allocate_key( key_type, PSA_BYTES_TO_BITS( key->len ),
+                                   &handle ) == PSA_SUCCESS );
     psa_key_policy_init( &policy );
     psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_ENCRYPT, alg );
-    TEST_ASSERT( psa_set_key_policy( key_slot, &policy ) == PSA_SUCCESS );
+    TEST_ASSERT( psa_set_key_policy( handle, &policy ) == PSA_SUCCESS );
 
-    TEST_ASSERT( psa_import_key( key_slot, key_type,
+    TEST_ASSERT( psa_import_key( handle, key_type,
                                  key->x, key->len ) == PSA_SUCCESS );
 
-    status = psa_cipher_encrypt_setup( &operation, key_slot, alg );
+    status = psa_cipher_encrypt_setup( &operation, handle, alg );
     psa_cipher_abort( &operation );
     TEST_ASSERT( status == expected_status );
 
 exit:
-    psa_destroy_key( key_slot );
+    psa_destroy_key( handle );
     mbedtls_psa_crypto_free( );
 }
 /* END_CASE */
@@ -2098,7 +2097,7 @@
                      data_t *input, data_t *expected_output,
                      int expected_status_arg )
 {
-    int key_slot = 1;
+    psa_key_handle_t handle = 0;
     psa_status_t status;
     psa_key_type_t key_type = key_type_arg;
     psa_algorithm_t alg = alg_arg;
@@ -2124,15 +2123,17 @@
 
     TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS );
 
+    TEST_ASSERT( psa_allocate_key( key_type, PSA_BYTES_TO_BITS( key->len ),
+                                   &handle ) == PSA_SUCCESS );
     psa_key_policy_init( &policy );
     psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_ENCRYPT, alg );
-    TEST_ASSERT( psa_set_key_policy( key_slot, &policy ) == PSA_SUCCESS );
+    TEST_ASSERT( psa_set_key_policy( handle, &policy ) == PSA_SUCCESS );
 
-    TEST_ASSERT( psa_import_key( key_slot, key_type,
+    TEST_ASSERT( psa_import_key( handle, key_type,
                                  key->x, key->len ) == PSA_SUCCESS );
 
     TEST_ASSERT( psa_cipher_encrypt_setup( &operation,
-                                           key_slot, alg ) == PSA_SUCCESS );
+                                           handle, alg ) == PSA_SUCCESS );
 
     TEST_ASSERT( psa_cipher_set_iv( &operation,
                                     iv, iv_size ) == PSA_SUCCESS );
@@ -2161,7 +2162,7 @@
 
 exit:
     mbedtls_free( output );
-    psa_destroy_key( key_slot );
+    psa_destroy_key( handle );
     mbedtls_psa_crypto_free( );
 }
 /* END_CASE */
@@ -2173,7 +2174,7 @@
                                int first_part_size,
                                data_t *expected_output )
 {
-    int key_slot = 1;
+    psa_key_handle_t handle = 0;
     psa_key_type_t key_type = key_type_arg;
     psa_algorithm_t alg = alg_arg;
     unsigned char iv[16] = {0};
@@ -2197,15 +2198,17 @@
 
     TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS );
 
+    TEST_ASSERT( psa_allocate_key( key_type, PSA_BYTES_TO_BITS( key->len ),
+                                   &handle ) == PSA_SUCCESS );
     psa_key_policy_init( &policy );
     psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_ENCRYPT, alg );
-    TEST_ASSERT( psa_set_key_policy( key_slot, &policy ) == PSA_SUCCESS );
+    TEST_ASSERT( psa_set_key_policy( handle, &policy ) == PSA_SUCCESS );
 
-    TEST_ASSERT( psa_import_key( key_slot, key_type,
+    TEST_ASSERT( psa_import_key( handle, key_type,
                                  key->x, key->len ) == PSA_SUCCESS );
 
     TEST_ASSERT( psa_cipher_encrypt_setup( &operation,
-                                           key_slot, alg ) == PSA_SUCCESS );
+                                           handle, alg ) == PSA_SUCCESS );
 
     TEST_ASSERT( psa_cipher_set_iv( &operation,
                                     iv, sizeof( iv ) ) == PSA_SUCCESS );
@@ -2236,7 +2239,7 @@
 
 exit:
     mbedtls_free( output );
-    psa_destroy_key( key_slot );
+    psa_destroy_key( handle );
     mbedtls_psa_crypto_free( );
 }
 /* END_CASE */
@@ -2248,7 +2251,7 @@
                                int first_part_size,
                                data_t *expected_output )
 {
-    int key_slot = 1;
+    psa_key_handle_t handle = 0;
 
     psa_key_type_t key_type = key_type_arg;
     psa_algorithm_t alg = alg_arg;
@@ -2273,15 +2276,17 @@
 
     TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS );
 
+    TEST_ASSERT( psa_allocate_key( key_type, PSA_BYTES_TO_BITS( key->len ),
+                                   &handle ) == PSA_SUCCESS );
     psa_key_policy_init( &policy );
     psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_DECRYPT, alg );
-    TEST_ASSERT( psa_set_key_policy( key_slot, &policy ) == PSA_SUCCESS );
+    TEST_ASSERT( psa_set_key_policy( handle, &policy ) == PSA_SUCCESS );
 
-    TEST_ASSERT( psa_import_key( key_slot, key_type,
+    TEST_ASSERT( psa_import_key( handle, key_type,
                                  key->x, key->len ) == PSA_SUCCESS );
 
     TEST_ASSERT( psa_cipher_decrypt_setup( &operation,
-                                           key_slot, alg ) == PSA_SUCCESS );
+                                           handle, alg ) == PSA_SUCCESS );
 
     TEST_ASSERT( psa_cipher_set_iv( &operation,
                                     iv, sizeof( iv ) ) == PSA_SUCCESS );
@@ -2314,7 +2319,7 @@
 
 exit:
     mbedtls_free( output );
-    psa_destroy_key( key_slot );
+    psa_destroy_key( handle );
     mbedtls_psa_crypto_free( );
 }
 /* END_CASE */
@@ -2325,7 +2330,7 @@
                      data_t *input, data_t *expected_output,
                      int expected_status_arg )
 {
-    int key_slot = 1;
+    psa_key_handle_t handle = 0;
     psa_status_t status;
     psa_key_type_t key_type = key_type_arg;
     psa_algorithm_t alg = alg_arg;
@@ -2351,15 +2356,17 @@
 
     TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS );
 
+    TEST_ASSERT( psa_allocate_key( key_type, PSA_BYTES_TO_BITS( key->len ),
+                                   &handle ) == PSA_SUCCESS );
     psa_key_policy_init( &policy );
     psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_DECRYPT, alg );
-    TEST_ASSERT( psa_set_key_policy( key_slot, &policy ) == PSA_SUCCESS );
+    TEST_ASSERT( psa_set_key_policy( handle, &policy ) == PSA_SUCCESS );
 
-    TEST_ASSERT( psa_import_key( key_slot, key_type,
+    TEST_ASSERT( psa_import_key( handle, key_type,
                                  key->x, key->len ) == PSA_SUCCESS );
 
     TEST_ASSERT( psa_cipher_decrypt_setup( &operation,
-                                           key_slot, alg ) == PSA_SUCCESS );
+                                           handle, alg ) == PSA_SUCCESS );
 
     TEST_ASSERT( psa_cipher_set_iv( &operation,
                                     iv, iv_size ) == PSA_SUCCESS );
@@ -2389,7 +2396,7 @@
 
 exit:
     mbedtls_free( output );
-    psa_destroy_key( key_slot );
+    psa_destroy_key( handle );
     mbedtls_psa_crypto_free( );
 }
 /* END_CASE */
@@ -2399,7 +2406,7 @@
                            data_t *key,
                            data_t *input )
 {
-    int key_slot = 1;
+    psa_key_handle_t handle = 0;
     psa_key_type_t key_type = key_type_arg;
     psa_algorithm_t alg = alg_arg;
     unsigned char iv[16] = {0};
@@ -2423,17 +2430,19 @@
 
     TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS );
 
+    TEST_ASSERT( psa_allocate_key( key_type, PSA_BYTES_TO_BITS( key->len ),
+                                   &handle ) == PSA_SUCCESS );
     psa_key_policy_init( &policy );
     psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT, alg );
-    TEST_ASSERT( psa_set_key_policy( key_slot, &policy ) == PSA_SUCCESS );
+    TEST_ASSERT( psa_set_key_policy( handle, &policy ) == PSA_SUCCESS );
 
-    TEST_ASSERT( psa_import_key( key_slot, key_type,
+    TEST_ASSERT( psa_import_key( handle, key_type,
                                  key->x, key->len ) == PSA_SUCCESS );
 
     TEST_ASSERT( psa_cipher_encrypt_setup( &operation1,
-                                           key_slot, alg ) == PSA_SUCCESS );
+                                           handle, alg ) == PSA_SUCCESS );
     TEST_ASSERT( psa_cipher_decrypt_setup( &operation2,
-                                           key_slot, alg ) == PSA_SUCCESS );
+                                           handle, alg ) == PSA_SUCCESS );
 
     TEST_ASSERT( psa_cipher_generate_iv( &operation1,
                                          iv, iv_size,
@@ -2476,7 +2485,7 @@
 exit:
     mbedtls_free( output1 );
     mbedtls_free( output2 );
-    psa_destroy_key( key_slot );
+    psa_destroy_key( handle );
     mbedtls_psa_crypto_free( );
 }
 /* END_CASE */
@@ -2488,7 +2497,7 @@
                                      data_t *input,
                                      int first_part_size )
 {
-    int key_slot = 1;
+    psa_key_handle_t handle = 0;
     psa_key_type_t key_type = key_type_arg;
     psa_algorithm_t alg = alg_arg;
     unsigned char iv[16] = {0};
@@ -2512,17 +2521,19 @@
 
     TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS );
 
+    TEST_ASSERT( psa_allocate_key( key_type, PSA_BYTES_TO_BITS( key->len ),
+                                   &handle ) == PSA_SUCCESS );
     psa_key_policy_init( &policy );
     psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT, alg );
-    TEST_ASSERT( psa_set_key_policy( key_slot, &policy ) == PSA_SUCCESS );
+    TEST_ASSERT( psa_set_key_policy( handle, &policy ) == PSA_SUCCESS );
 
-    TEST_ASSERT( psa_import_key( key_slot, key_type,
+    TEST_ASSERT( psa_import_key( handle, key_type,
                                  key->x, key->len ) == PSA_SUCCESS );
 
     TEST_ASSERT( psa_cipher_encrypt_setup( &operation1,
-                                           key_slot, alg ) == PSA_SUCCESS );
+                                           handle, alg ) == PSA_SUCCESS );
     TEST_ASSERT( psa_cipher_decrypt_setup( &operation2,
-                                           key_slot, alg ) == PSA_SUCCESS );
+                                           handle, alg ) == PSA_SUCCESS );
 
     TEST_ASSERT( psa_cipher_generate_iv( &operation1,
                                          iv, iv_size,
@@ -2584,7 +2595,7 @@
 exit:
     mbedtls_free( output1 );
     mbedtls_free( output2 );
-    psa_destroy_key( key_slot );
+    psa_destroy_key( handle );
     mbedtls_psa_crypto_free( );
 }
 /* END_CASE */
@@ -2597,7 +2608,7 @@
                            data_t *input_data,
                            int expected_result_arg )
 {
-    int slot = 1;
+    psa_key_handle_t handle = 0;
     psa_key_type_t key_type = key_type_arg;
     psa_algorithm_t alg = alg_arg;
     unsigned char *output_data = NULL;
@@ -2623,16 +2634,18 @@
 
     TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS );
 
+    TEST_ASSERT( psa_allocate_key( key_type, PSA_BYTES_TO_BITS( key_data->len ),
+                                   &handle ) == PSA_SUCCESS );
     psa_key_policy_init( &policy );
     psa_key_policy_set_usage( &policy,
                               PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT,
                               alg );
-    TEST_ASSERT( psa_set_key_policy( slot, &policy ) == PSA_SUCCESS );
+    TEST_ASSERT( psa_set_key_policy( handle, &policy ) == PSA_SUCCESS );
 
-    TEST_ASSERT( psa_import_key( slot, key_type,
+    TEST_ASSERT( psa_import_key( handle, key_type,
                                  key_data->x, key_data->len ) == PSA_SUCCESS );
 
-    TEST_ASSERT( psa_aead_encrypt( slot, alg,
+    TEST_ASSERT( psa_aead_encrypt( handle, alg,
                                    nonce->x, nonce->len,
                                    additional_data->x,
                                    additional_data->len,
@@ -2644,7 +2657,7 @@
     {
         ASSERT_ALLOC( output_data2, output_length );
 
-        TEST_ASSERT( psa_aead_decrypt( slot, alg,
+        TEST_ASSERT( psa_aead_decrypt( handle, alg,
                                        nonce->x, nonce->len,
                                        additional_data->x,
                                        additional_data->len,
@@ -2657,7 +2670,7 @@
     }
 
 exit:
-    psa_destroy_key( slot );
+    psa_destroy_key( handle );
     mbedtls_free( output_data );
     mbedtls_free( output_data2 );
     mbedtls_psa_crypto_free( );
@@ -2672,7 +2685,7 @@
                    data_t *input_data,
                    data_t *expected_result )
 {
-    int slot = 1;
+    psa_key_handle_t handle = 0;
     psa_key_type_t key_type = key_type_arg;
     psa_algorithm_t alg = alg_arg;
     unsigned char *output_data = NULL;
@@ -2697,15 +2710,17 @@
 
     TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS );
 
+    TEST_ASSERT( psa_allocate_key( key_type, PSA_BYTES_TO_BITS( key_data->len ),
+                                   &handle ) == PSA_SUCCESS );
     psa_key_policy_init( &policy );
     psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_ENCRYPT , alg );
-    TEST_ASSERT( psa_set_key_policy( slot, &policy ) == PSA_SUCCESS );
+    TEST_ASSERT( psa_set_key_policy( handle, &policy ) == PSA_SUCCESS );
 
-    TEST_ASSERT( psa_import_key( slot, key_type,
+    TEST_ASSERT( psa_import_key( handle, key_type,
                                  key_data->x,
                                  key_data->len ) == PSA_SUCCESS );
 
-    TEST_ASSERT( psa_aead_encrypt( slot, alg,
+    TEST_ASSERT( psa_aead_encrypt( handle, alg,
                                    nonce->x, nonce->len,
                                    additional_data->x, additional_data->len,
                                    input_data->x, input_data->len,
@@ -2716,7 +2731,7 @@
                     output_data, output_length );
 
 exit:
-    psa_destroy_key( slot );
+    psa_destroy_key( handle );
     mbedtls_free( output_data );
     mbedtls_psa_crypto_free( );
 }
@@ -2731,7 +2746,7 @@
                    data_t *expected_data,
                    int expected_result_arg )
 {
-    int slot = 1;
+    psa_key_handle_t handle = 0;
     psa_key_type_t key_type = key_type_arg;
     psa_algorithm_t alg = alg_arg;
     unsigned char *output_data = NULL;
@@ -2757,15 +2772,17 @@
 
     TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS );
 
+    TEST_ASSERT( psa_allocate_key( key_type, PSA_BYTES_TO_BITS( key_data->len ),
+                                   &handle ) == PSA_SUCCESS );
     psa_key_policy_init( &policy );
     psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_DECRYPT , alg );
-    TEST_ASSERT( psa_set_key_policy( slot, &policy ) == PSA_SUCCESS );
+    TEST_ASSERT( psa_set_key_policy( handle, &policy ) == PSA_SUCCESS );
 
-    TEST_ASSERT( psa_import_key( slot, key_type,
+    TEST_ASSERT( psa_import_key( handle, key_type,
                                  key_data->x,
                                  key_data->len ) == PSA_SUCCESS );
 
-    TEST_ASSERT( psa_aead_decrypt( slot, alg,
+    TEST_ASSERT( psa_aead_decrypt( handle, alg,
                                    nonce->x, nonce->len,
                                    additional_data->x,
                                    additional_data->len,
@@ -2778,7 +2795,7 @@
                         output_data, output_length );
 
 exit:
-    psa_destroy_key( slot );
+    psa_destroy_key( handle );
     mbedtls_free( output_data );
     mbedtls_psa_crypto_free( );
 }
@@ -2804,7 +2821,7 @@
                          int alg_arg, data_t *input_data,
                          data_t *output_data )
 {
-    int slot = 1;
+    psa_key_handle_t handle = 0;
     psa_key_type_t key_type = key_type_arg;
     psa_algorithm_t alg = alg_arg;
     size_t key_bits;
@@ -2822,14 +2839,17 @@
 
     TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS );
 
+    TEST_ASSERT( psa_allocate_key( key_type,
+                                   KEY_BITS_FROM_DATA( key_type, key_data ),
+                                   &handle ) == PSA_SUCCESS );
     psa_key_policy_init( &policy );
     psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_SIGN, alg );
-    TEST_ASSERT( psa_set_key_policy( slot, &policy ) == PSA_SUCCESS );
+    TEST_ASSERT( psa_set_key_policy( handle, &policy ) == PSA_SUCCESS );
 
-    TEST_ASSERT( psa_import_key( slot, key_type,
+    TEST_ASSERT( psa_import_key( handle, key_type,
                                  key_data->x,
                                  key_data->len ) == PSA_SUCCESS );
-    TEST_ASSERT( psa_get_key_information( slot,
+    TEST_ASSERT( psa_get_key_information( handle,
                                           NULL,
                                           &key_bits ) == PSA_SUCCESS );
 
@@ -2842,7 +2862,7 @@
     ASSERT_ALLOC( signature, signature_size );
 
     /* Perform the signature. */
-    TEST_ASSERT( psa_asymmetric_sign( slot, alg,
+    TEST_ASSERT( psa_asymmetric_sign( handle, alg,
                                       input_data->x, input_data->len,
                                       signature, signature_size,
                                       &signature_length ) == PSA_SUCCESS );
@@ -2851,7 +2871,7 @@
                     signature, signature_length );
 
 exit:
-    psa_destroy_key( slot );
+    psa_destroy_key( handle );
     mbedtls_free( signature );
     mbedtls_psa_crypto_free( );
 }
@@ -2862,7 +2882,7 @@
                 int alg_arg, data_t *input_data,
                 int signature_size_arg, int expected_status_arg )
 {
-    int slot = 1;
+    psa_key_handle_t handle = 0;
     psa_key_type_t key_type = key_type_arg;
     psa_algorithm_t alg = alg_arg;
     size_t signature_size = signature_size_arg;
@@ -2881,15 +2901,18 @@
 
     TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS );
 
+    TEST_ASSERT( psa_allocate_key( key_type,
+                                   KEY_BITS_FROM_DATA( key_type, key_data ),
+                                   &handle ) == PSA_SUCCESS );
     psa_key_policy_init( &policy );
     psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_SIGN, alg );
-    TEST_ASSERT( psa_set_key_policy( slot, &policy ) == PSA_SUCCESS );
+    TEST_ASSERT( psa_set_key_policy( handle, &policy ) == PSA_SUCCESS );
 
-    TEST_ASSERT( psa_import_key( slot, key_type,
+    TEST_ASSERT( psa_import_key( handle, key_type,
                                  key_data->x,
                                  key_data->len ) == PSA_SUCCESS );
 
-    actual_status = psa_asymmetric_sign( slot, alg,
+    actual_status = psa_asymmetric_sign( handle, alg,
                                          input_data->x, input_data->len,
                                          signature, signature_size,
                                          &signature_length );
@@ -2901,7 +2924,7 @@
     TEST_ASSERT( signature_length <= signature_size );
 
 exit:
-    psa_destroy_key( slot );
+    psa_destroy_key( handle );
     mbedtls_free( signature );
     mbedtls_psa_crypto_free( );
 }
@@ -2911,7 +2934,7 @@
 void sign_verify( int key_type_arg, data_t *key_data,
                   int alg_arg, data_t *input_data )
 {
-    int slot = 1;
+    psa_key_handle_t handle = 0;
     psa_key_type_t key_type = key_type_arg;
     psa_algorithm_t alg = alg_arg;
     size_t key_bits;
@@ -2922,16 +2945,19 @@
 
     TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS );
 
+    TEST_ASSERT( psa_allocate_key( key_type,
+                                   KEY_BITS_FROM_DATA( key_type, key_data ),
+                                   &handle ) == PSA_SUCCESS );
     psa_key_policy_init( &policy );
     psa_key_policy_set_usage( &policy,
                               PSA_KEY_USAGE_SIGN | PSA_KEY_USAGE_VERIFY,
                               alg );
-    TEST_ASSERT( psa_set_key_policy( slot, &policy ) == PSA_SUCCESS );
+    TEST_ASSERT( psa_set_key_policy( handle, &policy ) == PSA_SUCCESS );
 
-    TEST_ASSERT( psa_import_key( slot, key_type,
+    TEST_ASSERT( psa_import_key( handle, key_type,
                                  key_data->x,
                                  key_data->len ) == PSA_SUCCESS );
-    TEST_ASSERT( psa_get_key_information( slot,
+    TEST_ASSERT( psa_get_key_information( handle,
                                           NULL,
                                           &key_bits ) == PSA_SUCCESS );
 
@@ -2944,7 +2970,7 @@
     ASSERT_ALLOC( signature, signature_size );
 
     /* Perform the signature. */
-    TEST_ASSERT( psa_asymmetric_sign( slot, alg,
+    TEST_ASSERT( psa_asymmetric_sign( handle, alg,
                                       input_data->x, input_data->len,
                                       signature, signature_size,
                                       &signature_length ) == PSA_SUCCESS );
@@ -2954,7 +2980,7 @@
 
     /* Use the library to verify that the signature is correct. */
     TEST_ASSERT( psa_asymmetric_verify(
-                     slot, alg,
+                     handle, alg,
                      input_data->x, input_data->len,
                      signature, signature_length ) == PSA_SUCCESS );
 
@@ -2965,14 +2991,14 @@
          * because ECDSA may ignore the last few bits of the input. */
         input_data->x[0] ^= 1;
         TEST_ASSERT( psa_asymmetric_verify(
-                         slot, alg,
+                         handle, alg,
                          input_data->x, input_data->len,
                          signature,
                          signature_length ) == PSA_ERROR_INVALID_SIGNATURE );
     }
 
 exit:
-    psa_destroy_key( slot );
+    psa_destroy_key( handle );
     mbedtls_free( signature );
     mbedtls_psa_crypto_free( );
 }
@@ -2983,7 +3009,7 @@
                         int alg_arg, data_t *hash_data,
                         data_t *signature_data )
 {
-    int slot = 1;
+    psa_key_handle_t handle = 0;
     psa_key_type_t key_type = key_type_arg;
     psa_algorithm_t alg = alg_arg;
     psa_key_policy_t policy;
@@ -2999,20 +3025,23 @@
 
     TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS );
 
+    TEST_ASSERT( psa_allocate_key( key_type,
+                                   KEY_BITS_FROM_DATA( key_type, key_data ),
+                                   &handle ) == PSA_SUCCESS );
     psa_key_policy_init( &policy );
     psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_VERIFY, alg );
-    TEST_ASSERT( psa_set_key_policy( slot, &policy ) == PSA_SUCCESS );
+    TEST_ASSERT( psa_set_key_policy( handle, &policy ) == PSA_SUCCESS );
 
-    TEST_ASSERT( psa_import_key( slot, key_type,
+    TEST_ASSERT( psa_import_key( handle, key_type,
                                  key_data->x,
                                  key_data->len ) == PSA_SUCCESS );
 
-    TEST_ASSERT( psa_asymmetric_verify( slot, alg,
+    TEST_ASSERT( psa_asymmetric_verify( handle, alg,
                                         hash_data->x, hash_data->len,
                                         signature_data->x,
                                         signature_data->len ) == PSA_SUCCESS );
 exit:
-    psa_destroy_key( slot );
+    psa_destroy_key( handle );
     mbedtls_psa_crypto_free( );
 }
 /* END_CASE */
@@ -3023,7 +3052,7 @@
                              data_t *signature_data,
                              int expected_status_arg )
 {
-    int slot = 1;
+    psa_key_handle_t handle = 0;
     psa_key_type_t key_type = key_type_arg;
     psa_algorithm_t alg = alg_arg;
     psa_status_t actual_status;
@@ -3039,15 +3068,18 @@
 
     TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS );
 
+    TEST_ASSERT( psa_allocate_key( key_type,
+                                   KEY_BITS_FROM_DATA( key_type, key_data ),
+                                   &handle ) == PSA_SUCCESS );
     psa_key_policy_init( &policy );
     psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_VERIFY, alg );
-    TEST_ASSERT( psa_set_key_policy( slot, &policy ) == PSA_SUCCESS );
+    TEST_ASSERT( psa_set_key_policy( handle, &policy ) == PSA_SUCCESS );
 
-    TEST_ASSERT( psa_import_key( slot, key_type,
+    TEST_ASSERT( psa_import_key( handle, key_type,
                                  key_data->x,
                                  key_data->len ) == PSA_SUCCESS );
 
-    actual_status = psa_asymmetric_verify( slot, alg,
+    actual_status = psa_asymmetric_verify( handle, alg,
                                            hash_data->x, hash_data->len,
                                            signature_data->x,
                                            signature_data->len );
@@ -3055,7 +3087,7 @@
     TEST_ASSERT( actual_status == expected_status );
 
 exit:
-    psa_destroy_key( slot );
+    psa_destroy_key( handle );
     mbedtls_psa_crypto_free( );
 }
 /* END_CASE */
@@ -3069,7 +3101,7 @@
                          int expected_output_length_arg,
                          int expected_status_arg )
 {
-    int slot = 1;
+    psa_key_handle_t handle = 0;
     psa_key_type_t key_type = key_type_arg;
     psa_algorithm_t alg = alg_arg;
     size_t expected_output_length = expected_output_length_arg;
@@ -3083,23 +3115,27 @@
 
     TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS );
 
+
     /* Import the key */
+    TEST_ASSERT( psa_allocate_key( key_type,
+                                   KEY_BITS_FROM_DATA( key_type, key_data ),
+                                   &handle ) == PSA_SUCCESS );
     psa_key_policy_init( &policy );
     psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_ENCRYPT, alg );
-    TEST_ASSERT( psa_set_key_policy( slot, &policy ) == PSA_SUCCESS );
-    TEST_ASSERT( psa_import_key( slot, key_type,
+    TEST_ASSERT( psa_set_key_policy( handle, &policy ) == PSA_SUCCESS );
+    TEST_ASSERT( psa_import_key( handle, key_type,
                                  key_data->x,
                                  key_data->len ) == PSA_SUCCESS );
 
     /* Determine the maximum output length */
-    TEST_ASSERT( psa_get_key_information( slot,
+    TEST_ASSERT( psa_get_key_information( handle,
                                           NULL,
                                           &key_bits ) == PSA_SUCCESS );
     output_size = PSA_ASYMMETRIC_ENCRYPT_OUTPUT_SIZE( key_type, key_bits, alg );
     ASSERT_ALLOC( output, output_size );
 
     /* Encrypt the input */
-    actual_status = psa_asymmetric_encrypt( slot, alg,
+    actual_status = psa_asymmetric_encrypt( handle, alg,
                                             input_data->x, input_data->len,
                                             label->x, label->len,
                                             output, output_size,
@@ -3114,7 +3150,7 @@
         output_length = ~0;
         if( output_size != 0 )
             memset( output, 0, output_size );
-        actual_status = psa_asymmetric_encrypt( slot, alg,
+        actual_status = psa_asymmetric_encrypt( handle, alg,
                                                 input_data->x, input_data->len,
                                                 NULL, label->len,
                                                 output, output_size,
@@ -3124,7 +3160,7 @@
     }
 
 exit:
-    psa_destroy_key( slot );
+    psa_destroy_key( handle );
     mbedtls_free( output );
     mbedtls_psa_crypto_free( );
 }
@@ -3137,7 +3173,7 @@
                                  data_t *input_data,
                                  data_t *label )
 {
-    int slot = 1;
+    psa_key_handle_t handle = 0;
     psa_key_type_t key_type = key_type_arg;
     psa_algorithm_t alg = alg_arg;
     size_t key_bits;
@@ -3156,19 +3192,22 @@
 
     TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS );
 
+    TEST_ASSERT( psa_allocate_key( key_type,
+                                   KEY_BITS_FROM_DATA( key_type, key_data ),
+                                   &handle ) == PSA_SUCCESS );
     psa_key_policy_init( &policy );
     psa_key_policy_set_usage( &policy,
                               PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT,
                               alg );
-    TEST_ASSERT( psa_set_key_policy( slot, &policy ) == PSA_SUCCESS );
+    TEST_ASSERT( psa_set_key_policy( handle, &policy ) == PSA_SUCCESS );
 
-    TEST_ASSERT( psa_import_key( slot, key_type,
+    TEST_ASSERT( psa_import_key( handle, key_type,
                                  key_data->x,
                                  key_data->len ) == PSA_SUCCESS );
 
 
     /* Determine the maximum ciphertext length */
-    TEST_ASSERT( psa_get_key_information( slot,
+    TEST_ASSERT( psa_get_key_information( handle,
                                           NULL,
                                           &key_bits ) == PSA_SUCCESS );
     output_size = PSA_ASYMMETRIC_ENCRYPT_OUTPUT_SIZE( key_type, key_bits, alg );
@@ -3179,7 +3218,7 @@
     /* We test encryption by checking that encrypt-then-decrypt gives back
      * the original plaintext because of the non-optional random
      * part of encryption process which prevents using fixed vectors. */
-    TEST_ASSERT( psa_asymmetric_encrypt( slot, alg,
+    TEST_ASSERT( psa_asymmetric_encrypt( handle, alg,
                                          input_data->x, input_data->len,
                                          label->x, label->len,
                                          output, output_size,
@@ -3188,7 +3227,7 @@
      * it looks sensible. */
     TEST_ASSERT( output_length <= output_size );
 
-    TEST_ASSERT( psa_asymmetric_decrypt( slot, alg,
+    TEST_ASSERT( psa_asymmetric_decrypt( handle, alg,
                                          output, output_length,
                                          label->x, label->len,
                                          output2, output2_size,
@@ -3197,7 +3236,7 @@
                     output2, output2_length );
 
 exit:
-    psa_destroy_key( slot );
+    psa_destroy_key( handle );
     mbedtls_free( output );
     mbedtls_free( output2 );
     mbedtls_psa_crypto_free( );
@@ -3212,7 +3251,7 @@
                          data_t *label,
                          data_t *expected_data )
 {
-    int slot = 1;
+    psa_key_handle_t handle = 0;
     psa_key_type_t key_type = key_type_arg;
     psa_algorithm_t alg = alg_arg;
     unsigned char *output = NULL;
@@ -3232,15 +3271,18 @@
 
     TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS );
 
+    TEST_ASSERT( psa_allocate_key( key_type,
+                                   KEY_BITS_FROM_DATA( key_type, key_data ),
+                                   &handle ) == PSA_SUCCESS );
     psa_key_policy_init( &policy );
     psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_DECRYPT, alg );
-    TEST_ASSERT( psa_set_key_policy( slot, &policy ) == PSA_SUCCESS );
+    TEST_ASSERT( psa_set_key_policy( handle, &policy ) == PSA_SUCCESS );
 
-    TEST_ASSERT( psa_import_key( slot, key_type,
+    TEST_ASSERT( psa_import_key( handle, key_type,
                                  key_data->x,
                                  key_data->len ) == PSA_SUCCESS );
 
-    TEST_ASSERT( psa_asymmetric_decrypt( slot, alg,
+    TEST_ASSERT( psa_asymmetric_decrypt( handle, alg,
                                          input_data->x, input_data->len,
                                          label->x, label->len,
                                          output,
@@ -3256,7 +3298,7 @@
         output_length = ~0;
         if( output_size != 0 )
             memset( output, 0, output_size );
-        TEST_ASSERT( psa_asymmetric_decrypt( slot, alg,
+        TEST_ASSERT( psa_asymmetric_decrypt( handle, alg,
                                              input_data->x, input_data->len,
                                              NULL, label->len,
                                              output,
@@ -3267,7 +3309,7 @@
     }
 
 exit:
-    psa_destroy_key( slot );
+    psa_destroy_key( handle );
     mbedtls_free( output );
     mbedtls_psa_crypto_free( );
 }
@@ -3281,7 +3323,7 @@
                               data_t *label,
                               int expected_status_arg  )
 {
-    int slot = 1;
+    psa_key_handle_t handle = 0;
     psa_key_type_t key_type = key_type_arg;
     psa_algorithm_t alg = alg_arg;
     unsigned char *output = NULL;
@@ -3301,15 +3343,18 @@
 
     TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS );
 
+    TEST_ASSERT( psa_allocate_key( key_type,
+                                   KEY_BITS_FROM_DATA( key_type, key_data ),
+                                   &handle ) == PSA_SUCCESS );
     psa_key_policy_init( &policy );
     psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_DECRYPT, alg );
-    TEST_ASSERT( psa_set_key_policy( slot, &policy ) == PSA_SUCCESS );
+    TEST_ASSERT( psa_set_key_policy( handle, &policy ) == PSA_SUCCESS );
 
-    TEST_ASSERT( psa_import_key( slot, key_type,
+    TEST_ASSERT( psa_import_key( handle, key_type,
                                  key_data->x,
                                  key_data->len ) == PSA_SUCCESS );
 
-    actual_status = psa_asymmetric_decrypt( slot, alg,
+    actual_status = psa_asymmetric_decrypt( handle, alg,
                                             input_data->x, input_data->len,
                                             label->x, label->len,
                                             output, output_size,
@@ -3324,7 +3369,7 @@
         output_length = ~0;
         if( output_size != 0 )
             memset( output, 0, output_size );
-        actual_status = psa_asymmetric_decrypt( slot, alg,
+        actual_status = psa_asymmetric_decrypt( handle, alg,
                                                 input_data->x, input_data->len,
                                                 NULL, label->len,
                                                 output, output_size,
@@ -3334,7 +3379,7 @@
     }
 
 exit:
-    psa_destroy_key( slot );
+    psa_destroy_key( handle );
     mbedtls_free( output );
     mbedtls_psa_crypto_free( );
 }
@@ -3349,7 +3394,7 @@
                    int requested_capacity_arg,
                    int expected_status_arg )
 {
-    psa_key_slot_t slot = 1;
+    psa_key_handle_t handle = 0;
     size_t key_type = key_type_arg;
     psa_algorithm_t alg = alg_arg;
     size_t requested_capacity = requested_capacity_arg;
@@ -3359,22 +3404,24 @@
 
     TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS );
 
+    TEST_ASSERT( psa_allocate_key( key_type, PSA_BYTES_TO_BITS( key_data->len ),
+                                   &handle ) == PSA_SUCCESS );
     psa_key_policy_init( &policy );
     psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_DERIVE, alg );
-    TEST_ASSERT( psa_set_key_policy( slot, &policy ) == PSA_SUCCESS );
+    TEST_ASSERT( psa_set_key_policy( handle, &policy ) == PSA_SUCCESS );
 
-    TEST_ASSERT( psa_import_key( slot, key_type,
+    TEST_ASSERT( psa_import_key( handle, key_type,
                                  key_data->x,
                                  key_data->len ) == PSA_SUCCESS );
 
-    TEST_ASSERT( psa_key_derivation( &generator, slot, alg,
+    TEST_ASSERT( psa_key_derivation( &generator, handle, alg,
                                      salt->x, salt->len,
                                      label->x, label->len,
                                      requested_capacity ) == expected_status );
 
 exit:
     psa_generator_abort( &generator );
-    psa_destroy_key( slot );
+    psa_destroy_key( handle );
     mbedtls_psa_crypto_free( );
 }
 /* END_CASE */
@@ -3382,7 +3429,7 @@
 /* BEGIN_CASE */
 void test_derive_invalid_generator_state( )
 {
-    psa_key_slot_t base_key = 1;
+    psa_key_handle_t handle = 0;
     size_t key_type = PSA_KEY_TYPE_DERIVE;
     psa_crypto_generator_t generator = PSA_CRYPTO_GENERATOR_INIT;
     psa_algorithm_t alg = PSA_ALG_HKDF( PSA_ALG_SHA_256 );
@@ -3395,22 +3442,25 @@
 
     TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS );
 
+    TEST_ASSERT( psa_allocate_key( key_type,
+                                   PSA_BYTES_TO_BITS( sizeof( key_data ) ),
+                                   &handle ) == PSA_SUCCESS );
     psa_key_policy_init( &policy );
     psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_DERIVE, alg );
-    TEST_ASSERT( psa_set_key_policy( base_key, &policy ) == PSA_SUCCESS );
+    TEST_ASSERT( psa_set_key_policy( handle, &policy ) == PSA_SUCCESS );
 
-    TEST_ASSERT( psa_import_key( base_key, key_type,
+    TEST_ASSERT( psa_import_key( handle, key_type,
                                  key_data,
                                  sizeof( key_data ) ) == PSA_SUCCESS );
 
     /* valid key derivation */
-    TEST_ASSERT(  psa_key_derivation( &generator, base_key, alg,
+    TEST_ASSERT(  psa_key_derivation( &generator, handle, alg,
                                       NULL, 0,
                                       NULL, 0,
                                       capacity ) == PSA_SUCCESS );
 
     /* state of generator shouldn't allow additional generation */
-    TEST_ASSERT(  psa_key_derivation( &generator, base_key, alg,
+    TEST_ASSERT(  psa_key_derivation( &generator, handle, alg,
                                       NULL, 0,
                                       NULL, 0,
                                       capacity ) == PSA_ERROR_BAD_STATE );
@@ -3424,7 +3474,7 @@
 
 exit:
     psa_generator_abort( &generator );
-    psa_destroy_key( base_key );
+    psa_destroy_key( handle );
     mbedtls_psa_crypto_free( );
 }
 /* END_CASE */
@@ -3466,7 +3516,7 @@
                     data_t *expected_output1,
                     data_t *expected_output2 )
 {
-    psa_key_slot_t slot = 1;
+    psa_key_handle_t handle = 0;
     psa_algorithm_t alg = alg_arg;
     size_t requested_capacity = requested_capacity_arg;
     psa_crypto_generator_t generator = PSA_CRYPTO_GENERATOR_INIT;
@@ -3492,16 +3542,19 @@
     ASSERT_ALLOC( output_buffer, output_buffer_size );
     TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS );
 
+    TEST_ASSERT( psa_allocate_key( PSA_KEY_TYPE_DERIVE,
+                                   PSA_BYTES_TO_BITS( key_data->len ),
+                                   &handle ) == PSA_SUCCESS );
     psa_key_policy_init( &policy );
     psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_DERIVE, alg );
-    TEST_ASSERT( psa_set_key_policy( slot, &policy ) == PSA_SUCCESS );
+    TEST_ASSERT( psa_set_key_policy( handle, &policy ) == PSA_SUCCESS );
 
-    TEST_ASSERT( psa_import_key( slot, PSA_KEY_TYPE_DERIVE,
+    TEST_ASSERT( psa_import_key( handle, PSA_KEY_TYPE_DERIVE,
                                  key_data->x,
                                  key_data->len ) == PSA_SUCCESS );
 
     /* Extraction phase. */
-    TEST_ASSERT( psa_key_derivation( &generator, slot, alg,
+    TEST_ASSERT( psa_key_derivation( &generator, handle, alg,
                                      salt->x, salt->len,
                                      label->x, label->len,
                                      requested_capacity ) == PSA_SUCCESS );
@@ -3549,7 +3602,7 @@
 exit:
     mbedtls_free( output_buffer );
     psa_generator_abort( &generator );
-    psa_destroy_key( slot );
+    psa_destroy_key( handle );
     mbedtls_psa_crypto_free( );
 }
 /* END_CASE */
@@ -3561,7 +3614,7 @@
                   data_t *label,
                   int requested_capacity_arg )
 {
-    psa_key_slot_t slot = 1;
+    psa_key_handle_t handle = 0;
     psa_algorithm_t alg = alg_arg;
     size_t requested_capacity = requested_capacity_arg;
     psa_crypto_generator_t generator = PSA_CRYPTO_GENERATOR_INIT;
@@ -3572,16 +3625,19 @@
 
     TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS );
 
+    TEST_ASSERT( psa_allocate_key( PSA_KEY_TYPE_DERIVE,
+                                   PSA_BYTES_TO_BITS( key_data->len ),
+                                   &handle ) == PSA_SUCCESS );
     psa_key_policy_init( &policy );
     psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_DERIVE, alg );
-    TEST_ASSERT( psa_set_key_policy( slot, &policy ) == PSA_SUCCESS );
+    TEST_ASSERT( psa_set_key_policy( handle, &policy ) == PSA_SUCCESS );
 
-    TEST_ASSERT( psa_import_key( slot, PSA_KEY_TYPE_DERIVE,
+    TEST_ASSERT( psa_import_key( handle, PSA_KEY_TYPE_DERIVE,
                                  key_data->x,
                                  key_data->len ) == PSA_SUCCESS );
 
     /* Extraction phase. */
-    TEST_ASSERT( psa_key_derivation( &generator, slot, alg,
+    TEST_ASSERT( psa_key_derivation( &generator, handle, alg,
                                      salt->x, salt->len,
                                      label->x, label->len,
                                      requested_capacity ) == PSA_SUCCESS );
@@ -3615,7 +3671,7 @@
 
 exit:
     psa_generator_abort( &generator );
-    psa_destroy_key( slot );
+    psa_destroy_key( handle );
     mbedtls_psa_crypto_free( );
 }
 /* END_CASE */
@@ -3630,8 +3686,8 @@
                           int derived_usage_arg,
                           int derived_alg_arg )
 {
-    psa_key_slot_t base_key = 1;
-    psa_key_slot_t derived_key = 2;
+    psa_key_handle_t base_handle = 0;
+    psa_key_handle_t derived_handle = 0;
     psa_algorithm_t alg = alg_arg;
     psa_key_type_t derived_type = derived_type_arg;
     size_t derived_bits = derived_bits_arg;
@@ -3645,40 +3701,45 @@
 
     TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS );
 
+    TEST_ASSERT( psa_allocate_key( PSA_KEY_TYPE_DERIVE,
+                                   PSA_BYTES_TO_BITS( key_data->len ),
+                                   &base_handle ) == PSA_SUCCESS );
     psa_key_policy_init( &policy );
     psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_DERIVE, alg );
-    TEST_ASSERT( psa_set_key_policy( base_key, &policy ) == PSA_SUCCESS );
-    TEST_ASSERT( psa_import_key( base_key, PSA_KEY_TYPE_DERIVE,
+    TEST_ASSERT( psa_set_key_policy( base_handle, &policy ) == PSA_SUCCESS );
+    TEST_ASSERT( psa_import_key( base_handle, PSA_KEY_TYPE_DERIVE,
                                  key_data->x,
                                  key_data->len ) == PSA_SUCCESS );
 
     /* Derive a key. */
-    TEST_ASSERT( psa_key_derivation( &generator, base_key, alg,
+    TEST_ASSERT( psa_key_derivation( &generator, base_handle, alg,
                                      salt->x, salt->len,
                                      label->x, label->len,
                                      capacity ) == PSA_SUCCESS );
+    TEST_ASSERT( psa_allocate_key( derived_type, derived_bits,
+                                   &derived_handle ) == PSA_SUCCESS );
     psa_key_policy_set_usage( &policy, derived_usage, derived_alg );
-    TEST_ASSERT( psa_set_key_policy( derived_key, &policy ) == PSA_SUCCESS );
-    TEST_ASSERT( psa_generator_import_key( derived_key,
+    TEST_ASSERT( psa_set_key_policy( derived_handle, &policy ) == PSA_SUCCESS );
+    TEST_ASSERT( psa_generator_import_key( derived_handle,
                                            derived_type,
                                            derived_bits,
                                            &generator ) == PSA_SUCCESS );
 
     /* Test the key information */
-    TEST_ASSERT( psa_get_key_information( derived_key,
+    TEST_ASSERT( psa_get_key_information( derived_handle,
                                           &got_type,
                                           &got_bits ) == PSA_SUCCESS );
     TEST_ASSERT( got_type == derived_type );
     TEST_ASSERT( got_bits == derived_bits );
 
     /* Exercise the derived key. */
-    if( ! exercise_key( derived_key, derived_usage, derived_alg ) )
+    if( ! exercise_key( derived_handle, derived_usage, derived_alg ) )
         goto exit;
 
 exit:
     psa_generator_abort( &generator );
-    psa_destroy_key( base_key );
-    psa_destroy_key( derived_key );
+    psa_destroy_key( base_handle );
+    psa_destroy_key( derived_handle );
     mbedtls_psa_crypto_free( );
 }
 /* END_CASE */
@@ -3691,10 +3752,11 @@
                         int bytes1_arg,
                         int bytes2_arg )
 {
-    psa_key_slot_t base_key = 1;
-    psa_key_slot_t derived_key = 2;
+    psa_key_handle_t base_handle = 0;
+    psa_key_handle_t derived_handle = 0;
     psa_algorithm_t alg = alg_arg;
     size_t bytes1 = bytes1_arg;
+    size_t derived_bits = PSA_BYTES_TO_BITS( bytes1 );
     size_t bytes2 = bytes2_arg;
     size_t capacity = bytes1 + bytes2;
     psa_crypto_generator_t generator = PSA_CRYPTO_GENERATOR_INIT;
@@ -3707,15 +3769,18 @@
     ASSERT_ALLOC( export_buffer, capacity );
     TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS );
 
+    TEST_ASSERT( psa_allocate_key( PSA_KEY_TYPE_DERIVE,
+                                   PSA_BYTES_TO_BITS( key_data->len ),
+                                   &base_handle ) == PSA_SUCCESS );
     psa_key_policy_init( &policy );
     psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_DERIVE, alg );
-    TEST_ASSERT( psa_set_key_policy( base_key, &policy ) == PSA_SUCCESS );
-    TEST_ASSERT( psa_import_key( base_key, PSA_KEY_TYPE_DERIVE,
+    TEST_ASSERT( psa_set_key_policy( base_handle, &policy ) == PSA_SUCCESS );
+    TEST_ASSERT( psa_import_key( base_handle, PSA_KEY_TYPE_DERIVE,
                                  key_data->x,
                                  key_data->len ) == PSA_SUCCESS );
 
     /* Derive some material and output it. */
-    TEST_ASSERT( psa_key_derivation( &generator, base_key, alg,
+    TEST_ASSERT( psa_key_derivation( &generator, base_handle, alg,
                                      salt->x, salt->len,
                                      label->x, label->len,
                                      capacity ) == PSA_SUCCESS );
@@ -3725,27 +3790,32 @@
     TEST_ASSERT( psa_generator_abort( &generator ) == PSA_SUCCESS );
 
     /* Derive the same output again, but this time store it in key objects. */
-    TEST_ASSERT( psa_key_derivation( &generator, base_key, alg,
+    TEST_ASSERT( psa_key_derivation( &generator, base_handle, alg,
                                      salt->x, salt->len,
                                      label->x, label->len,
                                      capacity ) == PSA_SUCCESS );
+    TEST_ASSERT( psa_allocate_key( PSA_KEY_TYPE_RAW_DATA, derived_bits,
+                                   &derived_handle ) == PSA_SUCCESS );
     psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_EXPORT, 0 );
-    TEST_ASSERT( psa_set_key_policy( derived_key, &policy ) == PSA_SUCCESS );
-    TEST_ASSERT( psa_generator_import_key( derived_key,
+    TEST_ASSERT( psa_set_key_policy( derived_handle, &policy ) == PSA_SUCCESS );
+    TEST_ASSERT( psa_generator_import_key( derived_handle,
                                            PSA_KEY_TYPE_RAW_DATA,
-                                           PSA_BYTES_TO_BITS( bytes1 ),
+                                           derived_bits,
                                            &generator ) == PSA_SUCCESS );
-    TEST_ASSERT( psa_export_key( derived_key,
+    TEST_ASSERT( psa_export_key( derived_handle,
                                  export_buffer, bytes1,
                                  &length ) == PSA_SUCCESS );
     TEST_ASSERT( length == bytes1 );
-    TEST_ASSERT( psa_destroy_key( derived_key ) == PSA_SUCCESS );
-    TEST_ASSERT( psa_set_key_policy( derived_key, &policy ) == PSA_SUCCESS );
-    TEST_ASSERT( psa_generator_import_key( derived_key,
+    TEST_ASSERT( psa_destroy_key( derived_handle ) == PSA_SUCCESS );
+    TEST_ASSERT( psa_allocate_key( PSA_KEY_TYPE_RAW_DATA,
+                                   PSA_BYTES_TO_BITS( bytes2 ),
+                                   &derived_handle ) == PSA_SUCCESS );
+    TEST_ASSERT( psa_set_key_policy( derived_handle, &policy ) == PSA_SUCCESS );
+    TEST_ASSERT( psa_generator_import_key( derived_handle,
                                            PSA_KEY_TYPE_RAW_DATA,
                                            PSA_BYTES_TO_BITS( bytes2 ),
                                            &generator ) == PSA_SUCCESS );
-    TEST_ASSERT( psa_export_key( derived_key,
+    TEST_ASSERT( psa_export_key( derived_handle,
                                  export_buffer + bytes1, bytes2,
                                  &length ) == PSA_SUCCESS );
     TEST_ASSERT( length == bytes2 );
@@ -3757,8 +3827,8 @@
     mbedtls_free( output_buffer );
     mbedtls_free( export_buffer );
     psa_generator_abort( &generator );
-    psa_destroy_key( base_key );
-    psa_destroy_key( derived_key );
+    psa_destroy_key( base_handle );
+    psa_destroy_key( derived_handle );
     mbedtls_psa_crypto_free( );
 }
 /* END_CASE */
@@ -3769,7 +3839,7 @@
                           data_t *peer_key_data,
                           int expected_status_arg )
 {
-    psa_key_slot_t our_key = 1;
+    psa_key_handle_t our_key = 0;
     psa_algorithm_t alg = alg_arg;
     psa_key_type_t our_key_type = our_key_type_arg;
     psa_crypto_generator_t generator = PSA_CRYPTO_GENERATOR_INIT;
@@ -3777,6 +3847,10 @@
 
     TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS );
 
+    TEST_ASSERT( psa_allocate_key( our_key_type,
+                                   KEY_BITS_FROM_DATA( our_key_type,
+                                                       our_key_data ),
+                                   &our_key ) == PSA_SUCCESS );
     psa_key_policy_init( &policy );
     psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_DERIVE, alg );
     TEST_ASSERT( psa_set_key_policy( our_key, &policy ) == PSA_SUCCESS );
@@ -3802,7 +3876,7 @@
                              data_t *peer_key_data,
                              int expected_capacity_arg )
 {
-    psa_key_slot_t our_key = 1;
+    psa_key_handle_t our_key = 0;
     psa_algorithm_t alg = alg_arg;
     psa_key_type_t our_key_type = our_key_type_arg;
     psa_crypto_generator_t generator = PSA_CRYPTO_GENERATOR_INIT;
@@ -3812,6 +3886,10 @@
 
     TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS );
 
+    TEST_ASSERT( psa_allocate_key( our_key_type,
+                                   KEY_BITS_FROM_DATA( our_key_type,
+                                                       our_key_data ),
+                                   &our_key ) == PSA_SUCCESS );
     psa_key_policy_init( &policy );
     psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_DERIVE, alg );
     TEST_ASSERT( psa_set_key_policy( our_key, &policy ) == PSA_SUCCESS );
@@ -3856,7 +3934,7 @@
                            data_t *peer_key_data,
                            data_t *expected_output1, data_t *expected_output2 )
 {
-    psa_key_slot_t our_key = 1;
+    psa_key_handle_t our_key = 0;
     psa_algorithm_t alg = alg_arg;
     psa_key_type_t our_key_type = our_key_type_arg;
     psa_crypto_generator_t generator = PSA_CRYPTO_GENERATOR_INIT;
@@ -3868,6 +3946,10 @@
 
     TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS );
 
+    TEST_ASSERT( psa_allocate_key( our_key_type,
+                                   KEY_BITS_FROM_DATA( our_key_type,
+                                                       our_key_data ),
+                                   &our_key ) == PSA_SUCCESS );
     psa_key_policy_init( &policy );
     psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_DERIVE, alg );
     TEST_ASSERT( psa_set_key_policy( our_key, &policy ) == PSA_SUCCESS );
@@ -3961,7 +4043,7 @@
                    int alg_arg,
                    int expected_status_arg )
 {
-    int slot = 1;
+    psa_key_handle_t handle = 0;
     psa_key_type_t type = type_arg;
     psa_key_usage_t usage = usage_arg;
     size_t bits = bits_arg;
@@ -3975,16 +4057,17 @@
 
     TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS );
 
+    TEST_ASSERT( psa_allocate_key( type, bits, &handle ) == PSA_SUCCESS );
     psa_key_policy_init( &policy );
     psa_key_policy_set_usage( &policy, usage, alg );
-    TEST_ASSERT( psa_set_key_policy( slot, &policy ) == PSA_SUCCESS );
+    TEST_ASSERT( psa_set_key_policy( handle, &policy ) == PSA_SUCCESS );
 
     /* Generate a key */
-    TEST_ASSERT( psa_generate_key( slot, type, bits,
+    TEST_ASSERT( psa_generate_key( handle, type, bits,
                                    NULL, 0 ) == expected_status );
 
     /* Test the key information */
-    TEST_ASSERT( psa_get_key_information( slot,
+    TEST_ASSERT( psa_get_key_information( handle,
                                           &got_type,
                                           &got_bits ) == expected_info_status );
     if( expected_info_status != PSA_SUCCESS )
@@ -3993,11 +4076,11 @@
     TEST_ASSERT( got_bits == bits );
 
     /* Do something with the key according to its type and permitted usage. */
-    if( ! exercise_key( slot, usage, alg ) )
+    if( ! exercise_key( handle, usage, alg ) )
         goto exit;
 
 exit:
-    psa_destroy_key( slot );
+    psa_destroy_key( handle );
     mbedtls_psa_crypto_free( );
 }
 /* END_CASE */
@@ -4008,8 +4091,8 @@
                                            int alg_arg, int generation_method,
                                            int export_status )
 {
-    psa_key_slot_t slot = 1;
-    psa_key_slot_t base_key = 2;
+    psa_key_handle_t handle = 0;
+    psa_key_handle_t base_key;
     psa_key_type_t type = (psa_key_type_t) type_arg;
     psa_key_type_t type_get;
     size_t bits_get;
@@ -4031,33 +4114,34 @@
 
     TEST_ASSERT( psa_crypto_init() == PSA_SUCCESS );
 
-    TEST_ASSERT( psa_set_key_lifetime(
-        slot, PSA_KEY_LIFETIME_PERSISTENT ) == PSA_SUCCESS );
-
+    TEST_ASSERT( psa_create_key( PSA_KEY_LIFETIME_PERSISTENT, 1,
+                                 type, bits,
+                                 &handle ) == PSA_SUCCESS );
     psa_key_policy_init( &policy_set );
-
     psa_key_policy_set_usage( &policy_set, policy_usage,
                               policy_alg );
+    TEST_ASSERT( psa_set_key_policy( handle, &policy_set ) == PSA_SUCCESS );
 
-    TEST_ASSERT( psa_set_key_policy( slot, &policy_set ) == PSA_SUCCESS );
     switch( generation_method )
     {
         case IMPORT_KEY:
             /* Import the key */
-            TEST_ASSERT( psa_import_key( slot, type,
+            TEST_ASSERT( psa_import_key( handle, type,
                                          data->x, data->len ) == PSA_SUCCESS );
             break;
 
         case GENERATE_KEY:
             /* Generate a key */
-            TEST_ASSERT( psa_generate_key( slot, type, bits,
+            TEST_ASSERT( psa_generate_key( handle, type, bits,
                                            NULL, 0 ) == PSA_SUCCESS );
             break;
 
         case DERIVE_KEY:
             /* Create base key */
+            TEST_ASSERT( psa_allocate_key( PSA_KEY_TYPE_DERIVE,
+                                           PSA_BYTES_TO_BITS( data->len ),
+                                           &base_key ) == PSA_SUCCESS );
             psa_key_policy_init( &base_policy_set );
-
             psa_key_policy_set_usage( &base_policy_set, PSA_KEY_USAGE_DERIVE,
                                       base_policy_alg );
             TEST_ASSERT( psa_set_key_policy(
@@ -4070,38 +4154,35 @@
                                              NULL, 0, NULL, 0,
                                              export_size ) == PSA_SUCCESS );
             TEST_ASSERT( psa_generator_import_key(
-                slot, PSA_KEY_TYPE_RAW_DATA,
+                handle, PSA_KEY_TYPE_RAW_DATA,
                 bits, &generator ) == PSA_SUCCESS );
             break;
     }
 
     /* Export the key */
-    TEST_ASSERT( psa_export_key( slot, first_export, export_size,
+    TEST_ASSERT( psa_export_key( handle, first_export, export_size,
                                  &first_exported_length ) == export_status );
 
     /* Shutdown and restart */
     mbedtls_psa_crypto_free();
-
     TEST_ASSERT( psa_crypto_init() == PSA_SUCCESS );
 
-    /* Mark slot as persistent again */
-    TEST_ASSERT( psa_set_key_lifetime(
-        slot, PSA_KEY_LIFETIME_PERSISTENT ) == PSA_SUCCESS );
-
     /* Check key slot still contains key data */
+    TEST_ASSERT( psa_open_key( PSA_KEY_LIFETIME_PERSISTENT, 1,
+                               &handle ) == PSA_SUCCESS );
     TEST_ASSERT( psa_get_key_information(
-        slot, &type_get, &bits_get ) == PSA_SUCCESS );
+        handle, &type_get, &bits_get ) == PSA_SUCCESS );
     TEST_ASSERT( type_get == type );
     TEST_ASSERT( bits_get == (size_t) bits );
 
-    TEST_ASSERT( psa_get_key_policy( slot, &policy_get ) == PSA_SUCCESS );
+    TEST_ASSERT( psa_get_key_policy( handle, &policy_get ) == PSA_SUCCESS );
     TEST_ASSERT( psa_key_policy_get_usage(
         &policy_get ) == policy_usage );
     TEST_ASSERT( psa_key_policy_get_algorithm(
         &policy_get ) == policy_alg );
 
     /* Export the key again */
-    TEST_ASSERT( psa_export_key( slot, second_export, export_size,
+    TEST_ASSERT( psa_export_key( handle, second_export, export_size,
                                  &second_exported_length ) == export_status );
 
     if( export_status == PSA_SUCCESS )
@@ -4121,13 +4202,13 @@
     }
 
     /* Do something with the key according to its type and permitted usage. */
-    if( ! exercise_key( slot, policy_usage, policy_alg ) )
+    if( ! exercise_key( handle, policy_usage, policy_alg ) )
         goto exit;
 
 exit:
     mbedtls_free( first_export );
     mbedtls_free( second_export );
-    psa_destroy_key( slot );
+    psa_destroy_key( handle );
     mbedtls_psa_crypto_free();
 }
 /* END_CASE */
diff --git a/tests/suites/test_suite_psa_crypto_persistent_key.data b/tests/suites/test_suite_psa_crypto_persistent_key.data
index 46e547c..c9eb8e1 100644
--- a/tests/suites/test_suite_psa_crypto_persistent_key.data
+++ b/tests/suites/test_suite_psa_crypto_persistent_key.data
@@ -24,10 +24,6 @@
 Save larger than maximum size persistent raw key, should fail
 save_large_persistent_key:1:PSA_ERROR_INSUFFICIENT_STORAGE
 
-Persistent key is configurable
-depends_on:MBEDTLS_PK_C:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C
-persistent_key_is_configurable:1:PSA_KEY_TYPE_RSA_KEYPAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24"
-
 Persistent key destroy
 depends_on:MBEDTLS_PK_C:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C
 persistent_key_destroy:1:1:PSA_KEY_TYPE_RSA_KEYPAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_KEY_TYPE_RAW_DATA:"deadbeef"
@@ -36,10 +32,6 @@
 depends_on:MBEDTLS_PK_C:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C
 persistent_key_destroy:1:0:PSA_KEY_TYPE_RSA_KEYPAIR:"":PSA_KEY_TYPE_RAW_DATA:"deadbeef"
 
-Key lifetime defaults to volatile
-depends_on:MBEDTLS_PK_C:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C
-default_volatile_lifetime:1:PSA_KEY_TYPE_RSA_KEYPAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24"
-
 Persistent key import
 depends_on:MBEDTLS_PK_C:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C
 persistent_key_import:1:PSA_KEY_TYPE_RSA_KEYPAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_SUCCESS
diff --git a/tests/suites/test_suite_psa_crypto_persistent_key.function b/tests/suites/test_suite_psa_crypto_persistent_key.function
index 0ede6e6..08c7ca0 100644
--- a/tests/suites/test_suite_psa_crypto_persistent_key.function
+++ b/tests/suites/test_suite_psa_crypto_persistent_key.function
@@ -85,7 +85,8 @@
 /* BEGIN_CASE */
 void save_large_persistent_key( int data_too_large, int expected_status )
 {
-    psa_key_slot_t slot = 1;
+    psa_key_id_t key_id = 42;
+    psa_key_handle_t handle = 0;
     uint8_t *data = NULL;
     size_t data_length = PSA_CRYPTO_MAX_STORAGE_SIZE;
 
@@ -96,180 +97,107 @@
 
     TEST_ASSERT( psa_crypto_init() == PSA_SUCCESS );
 
-    TEST_ASSERT( psa_set_key_lifetime(
-        slot, PSA_KEY_LIFETIME_PERSISTENT ) == PSA_SUCCESS );
+    TEST_ASSERT( psa_create_key( PSA_KEY_LIFETIME_PERSISTENT, key_id,
+                                 PSA_KEY_TYPE_RAW_DATA,
+                                 PSA_BYTES_TO_BITS( data_length ),
+                                 &handle ) == PSA_SUCCESS );
 
-    TEST_ASSERT( psa_import_key( slot, PSA_KEY_TYPE_RAW_DATA,
+    TEST_ASSERT( psa_import_key( handle, PSA_KEY_TYPE_RAW_DATA,
         data, data_length ) == expected_status );
 
 exit:
     mbedtls_free( data );
-    psa_destroy_persistent_key( slot );
     mbedtls_psa_crypto_free();
-}
-/* END_CASE */
-
-
-/* BEGIN_CASE */
-void persistent_key_is_configurable( int slot_arg, int type_arg,
-                                     data_t *data )
-{
-    psa_key_policy_t policy;
-    psa_key_lifetime_t lifetime;
-    psa_key_slot_t slot = (psa_key_slot_t) slot_arg;
-    psa_key_type_t type = (psa_key_type_t) type_arg;
-
-    TEST_ASSERT( psa_crypto_init() == PSA_SUCCESS );
-
-    TEST_ASSERT( psa_set_key_lifetime(
-        slot, PSA_KEY_LIFETIME_PERSISTENT ) == PSA_SUCCESS );
-
-    psa_key_policy_init( &policy );
-
-    TEST_ASSERT( psa_set_key_policy( slot, &policy ) == PSA_SUCCESS );
-
-    TEST_ASSERT( psa_import_key( slot, type,
-                                 data->x, data->len ) == PSA_SUCCESS );
-
-    TEST_ASSERT( psa_get_key_lifetime( slot, &lifetime ) == PSA_SUCCESS );
-
-    TEST_ASSERT( lifetime == PSA_KEY_LIFETIME_PERSISTENT );
-
-exit:
-    psa_destroy_persistent_key( slot );
-    mbedtls_psa_crypto_free();
+    psa_destroy_persistent_key( key_id );
 }
 /* END_CASE */
 
 /* BEGIN_CASE */
-void persistent_key_destroy( int slot_arg, int should_store,
+void persistent_key_destroy( int key_id_arg, int should_store,
                              int first_type_arg, data_t *first_data,
                              int second_type_arg, data_t *second_data )
 {
     psa_key_policy_t policy;
-    psa_key_slot_t slot = (psa_key_slot_t) slot_arg;
+    psa_key_id_t key_id = key_id_arg;
+    psa_key_handle_t handle = 0;
     psa_key_type_t first_type = (psa_key_type_t) first_type_arg;
     psa_key_type_t second_type = (psa_key_type_t) second_type_arg;
 
     TEST_ASSERT( psa_crypto_init() == PSA_SUCCESS );
 
-    TEST_ASSERT( psa_set_key_lifetime(
-        slot, PSA_KEY_LIFETIME_PERSISTENT ) == PSA_SUCCESS );
-
     psa_key_policy_init( &policy );
 
+    TEST_ASSERT( psa_create_key( PSA_KEY_LIFETIME_PERSISTENT, key_id,
+                                 first_type,
+                                 PSA_BYTES_TO_BITS( first_data->len ),
+                                 &handle ) == PSA_SUCCESS );
+
     if( should_store == 1 )
     {
         TEST_ASSERT( psa_import_key(
-            slot, first_type,
+            handle, first_type,
             first_data->x, first_data->len ) == PSA_SUCCESS );
     }
 
     /* Destroy the key */
-    TEST_ASSERT( psa_destroy_key( slot ) == PSA_SUCCESS );
-
-    TEST_ASSERT( psa_get_key_information(
-        slot, NULL, NULL ) == PSA_ERROR_EMPTY_SLOT );
+    TEST_ASSERT( psa_destroy_key( handle ) == PSA_SUCCESS );
 
     /* Check key slot storage is removed */
-    TEST_ASSERT( psa_is_key_present_in_storage( slot ) == 0 );
-
-    /* Check destroying the key again doesn't report failure */
-    TEST_ASSERT( psa_destroy_key( slot ) == PSA_SUCCESS );
-    TEST_ASSERT( psa_get_key_information(
-        slot, NULL, NULL ) == PSA_ERROR_EMPTY_SLOT );
+    TEST_ASSERT( psa_is_key_present_in_storage( key_id ) == 0 );
+    TEST_ASSERT( psa_open_key( PSA_KEY_LIFETIME_PERSISTENT, key_id,
+                               &handle ) == PSA_ERROR_EMPTY_SLOT );
+    TEST_ASSERT( handle == 0 );
 
     /* Shutdown and restart */
     mbedtls_psa_crypto_free();
-
     TEST_ASSERT( psa_crypto_init() == PSA_SUCCESS );
 
-    /* Mark slot as persistent again */
-    TEST_ASSERT( psa_set_key_lifetime(
-        slot, PSA_KEY_LIFETIME_PERSISTENT ) == PSA_SUCCESS );
-
-    /* Check key slot is empty */
-    TEST_ASSERT( psa_get_key_information(
-        slot, NULL, NULL ) == PSA_ERROR_EMPTY_SLOT );
-
-    /* Import different key data to ensure slot really was empty */
-    psa_key_policy_init( &policy );
-
-    psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_EXPORT,
-                              PSA_ALG_VENDOR_FLAG );
-
-    TEST_ASSERT( psa_set_key_policy( slot, &policy ) == PSA_SUCCESS );
-
+    /* Create another key in the same slot */
+    TEST_ASSERT( psa_create_key( PSA_KEY_LIFETIME_PERSISTENT, key_id,
+                                 second_type,
+                                 PSA_BYTES_TO_BITS( second_data->len ),
+                                 &handle ) == PSA_SUCCESS );
     TEST_ASSERT( psa_import_key(
-        slot, second_type,
+        handle, second_type,
         second_data->x, second_data->len ) == PSA_SUCCESS );
 
 exit:
-    psa_destroy_persistent_key( slot );
     mbedtls_psa_crypto_free();
+    psa_destroy_persistent_key( key_id );
 }
 /* END_CASE */
 
 /* BEGIN_CASE */
-void default_volatile_lifetime( int slot_arg, int type_arg, data_t *data )
-{
-    psa_key_policy_t policy;
-    psa_key_slot_t slot = (psa_key_slot_t) slot_arg;
-    psa_key_type_t type = (psa_key_type_t) type_arg;
-
-    TEST_ASSERT( psa_crypto_init() == PSA_SUCCESS );
-
-    psa_key_policy_init( &policy );
-
-    TEST_ASSERT( psa_import_key( slot, type,
-                                 data->x, data->len ) == PSA_SUCCESS );
-
-    /* Shutdown and restart */
-    mbedtls_psa_crypto_free();
-
-    TEST_ASSERT( psa_crypto_init() == PSA_SUCCESS );
-
-    /* Check key slot is empty */
-    TEST_ASSERT( psa_get_key_information(
-        slot, NULL, NULL ) == PSA_ERROR_EMPTY_SLOT );
-
-exit:
-    psa_destroy_persistent_key( slot );
-    mbedtls_psa_crypto_free();
-}
-/* END_CASE */
-
-/* BEGIN_CASE */
-void persistent_key_import( int slot_arg, int type_arg, data_t *data,
+void persistent_key_import( int key_id_arg, int type_arg, data_t *data,
                             int expected_status )
 {
     psa_key_policy_t policy;
     psa_key_lifetime_t lifetime;
-    psa_key_slot_t slot = (psa_key_slot_t) slot_arg;
+    psa_key_id_t key_id = (psa_key_id_t) key_id_arg;
     psa_key_type_t type = (psa_key_type_t) type_arg;
+    psa_key_handle_t handle = 0;
 
     TEST_ASSERT( psa_crypto_init() == PSA_SUCCESS );
 
-    TEST_ASSERT( psa_set_key_lifetime(
-        slot, PSA_KEY_LIFETIME_PERSISTENT ) == PSA_SUCCESS );
-
+    TEST_ASSERT( psa_create_key( PSA_KEY_LIFETIME_PERSISTENT, key_id,
+                                 type,
+                                 PSA_BYTES_TO_BITS( data->len ),
+                                 &handle ) == PSA_SUCCESS );
     psa_key_policy_init( &policy );
-
-    TEST_ASSERT( psa_import_key( slot, type,
+    TEST_ASSERT( psa_import_key( handle, type,
                                  data->x, data->len ) == expected_status );
 
     if( expected_status != PSA_SUCCESS )
     {
-        TEST_ASSERT( psa_is_key_present_in_storage( slot ) == 0 );
+        TEST_ASSERT( psa_is_key_present_in_storage( key_id ) == 0 );
         goto exit;
     }
 
-    TEST_ASSERT( psa_get_key_lifetime( slot, &lifetime ) == PSA_SUCCESS );
-
+    TEST_ASSERT( psa_get_key_lifetime( handle, &lifetime ) == PSA_SUCCESS );
     TEST_ASSERT( lifetime == PSA_KEY_LIFETIME_PERSISTENT );
 
 exit:
-    psa_destroy_persistent_key( slot );
+    psa_destroy_persistent_key( key_id );
     mbedtls_psa_crypto_free();
 }
 /* END_CASE */
@@ -278,8 +206,9 @@
 void import_export_persistent_key( data_t *data, int type_arg,
                                    int expected_bits, int key_not_exist )
 {
-    psa_key_slot_t slot = 1;
+    psa_key_id_t key_id = 42;
     psa_key_type_t type = (psa_key_type_t) type_arg;
+    psa_key_handle_t handle = 0;
     unsigned char *exported = NULL;
     size_t export_size = data->len;
     size_t exported_length;
@@ -292,51 +221,48 @@
 
     TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS );
 
-    TEST_ASSERT( psa_set_key_lifetime(
-        slot, PSA_KEY_LIFETIME_PERSISTENT ) == PSA_SUCCESS );
+    TEST_ASSERT( psa_create_key( PSA_KEY_LIFETIME_PERSISTENT, key_id,
+                                 type,
+                                 PSA_BYTES_TO_BITS( data->len ),
+                                 &handle ) == PSA_SUCCESS );
 
     psa_key_policy_init( &policy );
-
     psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_EXPORT,
                               PSA_ALG_VENDOR_FLAG );
-
-    TEST_ASSERT( psa_set_key_policy( slot, &policy ) == PSA_SUCCESS );
+    TEST_ASSERT( psa_set_key_policy( handle, &policy ) == PSA_SUCCESS );
 
     /* Import the key */
-    TEST_ASSERT( psa_import_key( slot, type,
+    TEST_ASSERT( psa_import_key( handle, type,
                                  data->x, data->len ) == PSA_SUCCESS );
 
-    TEST_ASSERT( psa_get_key_lifetime(
-        slot, &lifetime_get ) == PSA_SUCCESS );
+    TEST_ASSERT( psa_get_key_lifetime( handle, &lifetime_get ) == PSA_SUCCESS );
     TEST_ASSERT( lifetime_get == PSA_KEY_LIFETIME_PERSISTENT );
 
     /* Test the key information */
     TEST_ASSERT( psa_get_key_information(
-        slot, &got_type, &got_bits ) == PSA_SUCCESS );
+        handle, &got_type, &got_bits ) == PSA_SUCCESS );
     TEST_ASSERT( got_type == type );
     TEST_ASSERT( got_bits == (size_t) expected_bits );
 
-    TEST_ASSERT( psa_is_key_present_in_storage( slot ) == 1 );
+    TEST_ASSERT( psa_is_key_present_in_storage( key_id ) == 1 );
 
     if( key_not_exist )
     {
-        psa_destroy_persistent_key( slot );
+        psa_destroy_persistent_key( key_id );
     }
     /* Export the key */
-    TEST_ASSERT( psa_export_key( slot, exported, export_size,
+    TEST_ASSERT( psa_export_key( handle, exported, export_size,
                                  &exported_length ) == PSA_SUCCESS );
 
     ASSERT_COMPARE( data->x, data->len, exported, exported_length );
 
     /* Destroy the key */
-    TEST_ASSERT( psa_destroy_key( slot ) == PSA_SUCCESS );
-    TEST_ASSERT( psa_get_key_information(
-                     slot, NULL, NULL ) == PSA_ERROR_EMPTY_SLOT );
-    TEST_ASSERT( psa_is_key_present_in_storage( slot ) == 0 );
+    TEST_ASSERT( psa_destroy_key( handle ) == PSA_SUCCESS );
+    TEST_ASSERT( psa_is_key_present_in_storage( key_id ) == 0 );
 
 exit:
     mbedtls_free( exported );
-    psa_destroy_persistent_key( slot );
     mbedtls_psa_crypto_free( );
+    psa_destroy_persistent_key( key_id );
 }
 /* END_CASE */
diff --git a/tests/suites/test_suite_psa_crypto_slot_management.data b/tests/suites/test_suite_psa_crypto_slot_management.data
new file mode 100644
index 0000000..39661b9
--- /dev/null
+++ b/tests/suites/test_suite_psa_crypto_slot_management.data
@@ -0,0 +1,84 @@
+Transient slot, check after closing
+transient_slot_lifecycle:PSA_KEY_TYPE_RAW_DATA:128:0:0:"0123456789abcdef0123456789abcdef":CLOSE_BY_CLOSE
+
+Transient slot, check after destroying
+transient_slot_lifecycle:PSA_KEY_TYPE_RAW_DATA:128:0:0:"0123456789abcdef0123456789abcdef":CLOSE_BY_DESTROY
+
+Transient slot, check after restart
+transient_slot_lifecycle:PSA_KEY_TYPE_RAW_DATA:128:0:0:"0123456789abcdef0123456789abcdef":CLOSE_BY_SHUTDOWN
+
+Persistent slot, check after closing
+persistent_slot_lifecycle:PSA_KEY_LIFETIME_PERSISTENT:1:PSA_KEY_TYPE_RAW_DATA:128:0:0:"0123456789abcdef0123456789abcdef":CLOSE_BY_CLOSE
+
+Persistent slot, check after destroying
+persistent_slot_lifecycle:PSA_KEY_LIFETIME_PERSISTENT:1:PSA_KEY_TYPE_RAW_DATA:128:0:0:"0123456789abcdef0123456789abcdef":CLOSE_BY_DESTROY
+
+Persistent slot, check after restart
+persistent_slot_lifecycle:PSA_KEY_LIFETIME_PERSISTENT:1:PSA_KEY_TYPE_RAW_DATA:128:0:0:"0123456789abcdef0123456789abcdef":CLOSE_BY_SHUTDOWN
+
+Attempt to overwrite: close before, same type
+create_existent:PSA_KEY_LIFETIME_PERSISTENT:1:PSA_KEY_TYPE_RAW_DATA:CLOSE_BEFORE
+
+Attempt to overwrite: close before, different type
+depends_on:MBEDTLS_AES_C
+create_existent:PSA_KEY_LIFETIME_PERSISTENT:1:PSA_KEY_TYPE_AES:CLOSE_BEFORE
+
+Attempt to overwrite: close after, same type
+create_existent:PSA_KEY_LIFETIME_PERSISTENT:1:PSA_KEY_TYPE_RAW_DATA:CLOSE_AFTER
+
+Attempt to overwrite: close after, different type
+depends_on:MBEDTLS_AES_C
+create_existent:PSA_KEY_LIFETIME_PERSISTENT:1:PSA_KEY_TYPE_AES:CLOSE_AFTER
+
+Attempt to overwrite: keep open, same type
+create_existent:PSA_KEY_LIFETIME_PERSISTENT:1:PSA_KEY_TYPE_RAW_DATA:KEEP_OPEN
+
+Attempt to overwrite: keep open, different type
+depends_on:MBEDTLS_AES_C
+create_existent:PSA_KEY_LIFETIME_PERSISTENT:1:PSA_KEY_TYPE_AES:KEEP_OPEN
+
+Open failure: invalid identifier (0)
+depends_on:MBEDTLS_PSA_CRYPTO_STORAGE_C
+open_fail:PSA_KEY_LIFETIME_PERSISTENT:0:PSA_ERROR_INVALID_ARGUMENT
+
+Open failure: invalid identifier (random seed UID)
+depends_on:MBEDTLS_PSA_CRYPTO_STORAGE_C
+open_fail:PSA_KEY_LIFETIME_PERSISTENT:PSA_CRYPTO_ITS_RANDOM_SEED_UID:PSA_ERROR_INVALID_ARGUMENT
+
+Open failure: non-existent identifier
+depends_on:MBEDTLS_PSA_CRYPTO_STORAGE_C
+open_fail:PSA_KEY_LIFETIME_PERSISTENT:1:PSA_ERROR_EMPTY_SLOT
+
+Open failure: volatile lifetime
+open_fail:PSA_KEY_LIFETIME_VOLATILE:1:PSA_ERROR_INVALID_ARGUMENT
+
+Open failure: invalid lifetime
+open_fail:0x7fffffff:0:PSA_ERROR_INVALID_ARGUMENT
+
+Create failure: volatile lifetime
+create_fail:PSA_KEY_LIFETIME_VOLATILE:1:PSA_KEY_TYPE_RAW_DATA:8:PSA_ERROR_INVALID_ARGUMENT
+
+Create failure: invalid lifetime
+create_fail:0x7fffffff:0:PSA_KEY_TYPE_RAW_DATA:8:PSA_ERROR_INVALID_ARGUMENT
+
+Create failure: invalid key id (0)
+depends_on:MBEDTLS_PSA_CRYPTO_STORAGE_C
+create_fail:PSA_KEY_LIFETIME_PERSISTENT:0:PSA_KEY_TYPE_RAW_DATA:8:PSA_ERROR_INVALID_ARGUMENT
+
+Create failure: invalid key id (random seed UID)
+depends_on:MBEDTLS_PSA_CRYPTO_STORAGE_C
+create_fail:PSA_KEY_LIFETIME_PERSISTENT:PSA_CRYPTO_ITS_RANDOM_SEED_UID:PSA_KEY_TYPE_RAW_DATA:8:PSA_ERROR_INVALID_ARGUMENT
+
+Open not supported
+depends_on:!MBEDTLS_PSA_CRYPTO_STORAGE_C
+open_fail:PSA_KEY_LIFETIME_PERSISTENT:1:PSA_ERROR_NOT_SUPPORTED
+
+Create not supported
+depends_on:!MBEDTLS_PSA_CRYPTO_STORAGE_C
+create_fail:PSA_KEY_LIFETIME_PERSISTENT:1:PSA_KEY_TYPE_RAW_DATA:8:PSA_ERROR_NOT_SUPPORTED
+
+Close/destroy invalid handle
+invalid_handle:
+
+Open many transient handles
+many_transient_handles:42
diff --git a/tests/suites/test_suite_psa_crypto_slot_management.function b/tests/suites/test_suite_psa_crypto_slot_management.function
new file mode 100644
index 0000000..fdcb5a9
--- /dev/null
+++ b/tests/suites/test_suite_psa_crypto_slot_management.function
@@ -0,0 +1,398 @@
+/* BEGIN_HEADER */
+#include <stdint.h>
+
+#if defined(MBEDTLS_PSA_CRYPTO_SPM)
+#include "spm/psa_defs.h"
+#endif
+#include "psa/crypto.h"
+
+#include "psa_crypto_storage.h"
+
+#define PSA_ASSERT( expr ) TEST_ASSERT( ( expr ) == PSA_SUCCESS )
+
+typedef enum
+{
+    CLOSE_BY_CLOSE,
+    CLOSE_BY_DESTROY,
+    CLOSE_BY_SHUTDOWN,
+} close_method_t;
+
+typedef enum
+{
+    KEEP_OPEN,
+    CLOSE_BEFORE,
+    CLOSE_AFTER,
+} reopen_policy_t;
+
+/* All test functions that create persistent keys must call
+ * `TEST_MAX_KEY_ID( key_id )` before creating a persistent key with this
+ * identifier, and must call psa_purge_key_storage() in their cleanup
+ * code. */
+
+#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C)
+/* There is no API to purge all keys. For this test suite, require that
+ * all key IDs be less than a certain maximum, or a well-known value
+ * which corresponds to a file that does not contain a key. */
+#define MAX_KEY_ID_FOR_TEST 32
+#define KEY_ID_IS_WELL_KNOWN( key_id )                  \
+    ( ( key_id ) == PSA_CRYPTO_ITS_RANDOM_SEED_UID )
+#define TEST_MAX_KEY_ID( key_id )                       \
+    TEST_ASSERT( ( key_id ) <= MAX_KEY_ID_FOR_TEST ||   \
+                 KEY_ID_IS_WELL_KNOWN( key_id ) )
+void psa_purge_key_storage( void )
+{
+    psa_key_id_t i;
+    /* The tests may have potentially created key ids from 1 to
+     * MAX_KEY_ID_FOR_TEST. In addition, run the destroy function on key id
+     * 0, which file-based storage uses as a temporary file. */
+    for( i = 0; i <= MAX_KEY_ID_FOR_TEST; i++ )
+        psa_destroy_persistent_key( i );
+}
+#else
+#define TEST_MAX_KEY_ID( key_id ) ( (void) ( key_id ) )
+#endif /* MBEDTLS_PSA_CRYPTO_STORAGE_C */
+
+static int psa_key_policy_equal( psa_key_policy_t *p1,
+                                 psa_key_policy_t *p2 )
+{
+    return( psa_key_policy_get_usage( p1 ) == psa_key_policy_get_usage( p2 ) &&
+            psa_key_policy_get_algorithm( p1 ) == psa_key_policy_get_algorithm( p2 ) );
+}
+
+/* END_HEADER */
+
+/* BEGIN_DEPENDENCIES
+ * depends_on:MBEDTLS_PSA_CRYPTO_C
+ * END_DEPENDENCIES
+ */
+
+/* BEGIN_CASE */
+void transient_slot_lifecycle( int type_arg, int max_bits_arg,
+                               int alg_arg, int usage_arg,
+                               data_t *key_data,
+                               int close_method_arg )
+{
+    psa_key_type_t type = type_arg;
+    size_t max_bits = max_bits_arg;
+    psa_algorithm_t alg = alg_arg;
+    psa_key_usage_t usage_flags = usage_arg;
+    close_method_t close_method = close_method_arg;
+    psa_key_type_t read_type;
+    psa_key_handle_t handle = 0;
+    psa_key_policy_t policy;
+
+    PSA_ASSERT( psa_crypto_init( ) );
+
+    /* Get a handle and import a key. */
+    PSA_ASSERT( psa_allocate_key( type, max_bits, &handle ) );
+    TEST_ASSERT( handle != 0 );
+    psa_key_policy_init( &policy );
+    psa_key_policy_set_usage( &policy, usage_flags, alg );
+    PSA_ASSERT( psa_set_key_policy( handle, &policy ) );
+    PSA_ASSERT( psa_import_key( handle, type, key_data->x, key_data->len ) );
+    PSA_ASSERT( psa_get_key_information( handle, &read_type, NULL ) );
+    TEST_ASSERT( read_type == type );
+
+    /* Do something that invalidates the handle. */
+    switch( close_method )
+    {
+        case CLOSE_BY_CLOSE:
+            PSA_ASSERT( psa_close_key( handle ) );
+            break;
+        case CLOSE_BY_DESTROY:
+            PSA_ASSERT( psa_destroy_key( handle ) );
+            break;
+        case CLOSE_BY_SHUTDOWN:
+            mbedtls_psa_crypto_free( );
+            PSA_ASSERT( psa_crypto_init( ) );
+            break;
+    }
+    /* Test that the handle is now invalid. */
+    TEST_ASSERT( psa_get_key_information( handle, &read_type, NULL ) ==
+                 PSA_ERROR_INVALID_HANDLE );
+    TEST_ASSERT( psa_close_key( handle ) == PSA_ERROR_INVALID_HANDLE );
+
+exit:
+    mbedtls_psa_crypto_free( );
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:MBEDTLS_PSA_CRYPTO_STORAGE_C */
+void persistent_slot_lifecycle( int lifetime_arg, int id_arg,
+                                int type_arg, int max_bits_arg,
+                                int alg_arg, int usage_arg,
+                                data_t *key_data,
+                                int close_method_arg )
+{
+    psa_key_lifetime_t lifetime = lifetime_arg;
+    psa_key_id_t id = id_arg;
+    psa_key_type_t type = type_arg;
+    size_t max_bits = max_bits_arg;
+    psa_algorithm_t alg = alg_arg;
+    psa_key_usage_t usage_flags = usage_arg;
+    close_method_t close_method = close_method_arg;
+    psa_key_type_t read_type;
+    psa_key_handle_t handle = 0;
+    psa_key_policy_t policy;
+
+    TEST_MAX_KEY_ID( id );
+
+    PSA_ASSERT( psa_crypto_init( ) );
+
+    /* Get a handle and import a key. */
+    PSA_ASSERT( psa_create_key( lifetime, id, type, max_bits, &handle ) );
+    TEST_ASSERT( handle != 0 );
+    psa_key_policy_init( &policy );
+    psa_key_policy_set_usage( &policy, usage_flags, alg );
+    PSA_ASSERT( psa_set_key_policy( handle, &policy ) );
+    PSA_ASSERT( psa_import_key( handle, type, key_data->x, key_data->len ) );
+    PSA_ASSERT( psa_get_key_information( handle, &read_type, NULL ) );
+    TEST_ASSERT( read_type == type );
+
+    /* Close the key and reopen it. */
+    PSA_ASSERT( psa_close_key( handle ) );
+    PSA_ASSERT( psa_open_key( lifetime, id, &handle ) );
+    PSA_ASSERT( psa_get_key_information( handle, &read_type, NULL ) );
+    TEST_ASSERT( read_type == type );
+
+    /* Do something that invalidates the handle. */
+    switch( close_method )
+    {
+        case CLOSE_BY_CLOSE:
+            PSA_ASSERT( psa_close_key( handle ) );
+            break;
+        case CLOSE_BY_DESTROY:
+            PSA_ASSERT( psa_destroy_key( handle ) );
+            break;
+        case CLOSE_BY_SHUTDOWN:
+            mbedtls_psa_crypto_free( );
+            PSA_ASSERT( psa_crypto_init( ) );
+            break;
+    }
+    /* Test that the handle is now invalid. */
+    TEST_ASSERT( psa_get_key_information( handle, &read_type, NULL ) ==
+                 PSA_ERROR_INVALID_HANDLE );
+    TEST_ASSERT( psa_close_key( handle ) == PSA_ERROR_INVALID_HANDLE );
+
+    /* Try to reopen the key. If we destroyed it, check that it doesn't
+     * exist, otherwise check that it still exists. */
+    switch( close_method )
+    {
+        case CLOSE_BY_CLOSE:
+        case CLOSE_BY_SHUTDOWN:
+            PSA_ASSERT( psa_open_key( lifetime, id, &handle ) );
+            PSA_ASSERT( psa_get_key_information( handle, &read_type, NULL ) );
+            TEST_ASSERT( read_type == type );
+            break;
+        case CLOSE_BY_DESTROY:
+            TEST_ASSERT( psa_open_key( lifetime, id, &handle ) ==
+                         PSA_ERROR_EMPTY_SLOT );
+            break;
+    }
+
+exit:
+    mbedtls_psa_crypto_free( );
+    psa_purge_key_storage( );
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:MBEDTLS_PSA_CRYPTO_STORAGE_C */
+void create_existent( int lifetime_arg, int id_arg,
+                      int new_type_arg,
+                      int reopen_policy_arg )
+{
+    psa_key_lifetime_t lifetime = lifetime_arg;
+    psa_key_id_t id = id_arg;
+    psa_key_handle_t handle1 = 0, handle2 = 0;
+    psa_key_policy_t policy1, read_policy;
+    psa_key_type_t type1 = PSA_KEY_TYPE_RAW_DATA;
+    psa_key_type_t type2 = new_type_arg;
+    psa_key_type_t read_type;
+    const uint8_t material1[16] = "test material #1";
+    size_t bits1 = PSA_BYTES_TO_BITS( sizeof( material1 ) );
+    size_t read_bits;
+    uint8_t reexported[sizeof( material1 )];
+    size_t reexported_length;
+    reopen_policy_t reopen_policy = reopen_policy_arg;
+
+    TEST_MAX_KEY_ID( id );
+
+    PSA_ASSERT( psa_crypto_init( ) );
+
+    /* Create a key. */
+    PSA_ASSERT( psa_create_key( lifetime, id, type1, bits1, &handle1 ) );
+    TEST_ASSERT( handle1 != 0 );
+    psa_key_policy_init( &policy1 );
+    psa_key_policy_set_usage( &policy1, PSA_KEY_USAGE_EXPORT, 0 );
+    PSA_ASSERT( psa_set_key_policy( handle1, &policy1 ) );
+    PSA_ASSERT( psa_import_key( handle1, type1,
+                                material1, sizeof( material1 ) ) );
+
+    if( reopen_policy == CLOSE_BEFORE )
+        PSA_ASSERT( psa_close_key( handle1 ) );
+
+    /* Attempt to create a new key in the same slot. */
+    TEST_ASSERT( psa_create_key( lifetime, id, type2, bits1, &handle2 ) ==
+                 PSA_ERROR_OCCUPIED_SLOT );
+    TEST_ASSERT( handle2 == 0 );
+
+    if( reopen_policy == CLOSE_AFTER )
+        PSA_ASSERT( psa_close_key( handle1 ) );
+    if( reopen_policy == CLOSE_BEFORE || reopen_policy == CLOSE_AFTER )
+        PSA_ASSERT( psa_open_key( lifetime, id, &handle1 ) );
+
+    /* Check that the original key hasn't changed. */
+    PSA_ASSERT( psa_get_key_policy( handle1, &read_policy ) );
+    TEST_ASSERT( psa_key_policy_equal( &read_policy, &policy1 ) );
+    PSA_ASSERT( psa_get_key_information( handle1, &read_type, &read_bits ) );
+    TEST_ASSERT( read_type == type1 );
+    TEST_ASSERT( read_bits == bits1 );
+    PSA_ASSERT( psa_export_key( handle1,
+                                reexported, sizeof( reexported ),
+                                &reexported_length ) );
+    ASSERT_COMPARE( material1, sizeof( material1 ),
+                    reexported, reexported_length );
+
+exit:
+    mbedtls_psa_crypto_free( );
+    psa_purge_key_storage( );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void open_fail( int lifetime_arg, int id_arg,
+                int expected_status_arg )
+{
+    psa_key_lifetime_t lifetime = lifetime_arg;
+    psa_key_id_t id = id_arg;
+    psa_status_t expected_status = expected_status_arg;
+    psa_key_handle_t handle = 0xdead;
+
+    PSA_ASSERT( psa_crypto_init( ) );
+
+    TEST_ASSERT( psa_open_key( lifetime, id, &handle ) == expected_status );
+    TEST_ASSERT( handle == 0 );
+
+exit:
+    mbedtls_psa_crypto_free( );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void create_fail( int lifetime_arg, int id_arg,
+                  int type_arg, int max_bits_arg,
+                  int expected_status_arg )
+{
+    psa_key_lifetime_t lifetime = lifetime_arg;
+    psa_key_id_t id = id_arg;
+    psa_key_type_t type = type_arg;
+    size_t max_bits = max_bits_arg;
+    psa_status_t expected_status = expected_status_arg;
+    psa_key_handle_t handle = 0xdead;
+
+    TEST_MAX_KEY_ID( id );
+
+    PSA_ASSERT( psa_crypto_init( ) );
+
+    TEST_ASSERT( psa_create_key( lifetime, id,
+                                 type, max_bits,
+                                 &handle ) == expected_status );
+    TEST_ASSERT( handle == 0 );
+
+exit:
+    mbedtls_psa_crypto_free( );
+#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C)
+    psa_purge_key_storage( );
+#endif
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void invalid_handle( )
+{
+    psa_key_handle_t handle1 = 0;
+    psa_key_policy_t policy;
+    psa_key_type_t read_type;
+    size_t read_bits;
+    uint8_t material[1] = "a";
+
+    PSA_ASSERT( psa_crypto_init( ) );
+
+    /* Allocate a handle and store a key in it. */
+    PSA_ASSERT( psa_allocate_key( PSA_KEY_TYPE_RAW_DATA, 1, &handle1 ) );
+    TEST_ASSERT( handle1 != 0 );
+    psa_key_policy_init( &policy );
+    psa_key_policy_set_usage( &policy, 0, 0 );
+    PSA_ASSERT( psa_set_key_policy( handle1, &policy ) );
+    PSA_ASSERT( psa_import_key( handle1, PSA_KEY_TYPE_RAW_DATA,
+                                material, sizeof( material ) ) );
+
+    /* Attempt to close and destroy some invalid handles. */
+    TEST_ASSERT( psa_close_key( 0 ) == PSA_ERROR_INVALID_HANDLE );
+    TEST_ASSERT( psa_close_key( handle1 - 1 ) == PSA_ERROR_INVALID_HANDLE );
+    TEST_ASSERT( psa_close_key( handle1 + 1 ) == PSA_ERROR_INVALID_HANDLE );
+    TEST_ASSERT( psa_destroy_key( 0 ) == PSA_ERROR_INVALID_HANDLE );
+    TEST_ASSERT( psa_destroy_key( handle1 - 1 ) == PSA_ERROR_INVALID_HANDLE );
+    TEST_ASSERT( psa_destroy_key( handle1 + 1 ) == PSA_ERROR_INVALID_HANDLE );
+
+    /* After all this, check that the original handle is intact. */
+    PSA_ASSERT( psa_get_key_information( handle1, &read_type, &read_bits ) );
+    TEST_ASSERT( read_type == PSA_KEY_TYPE_RAW_DATA );
+    TEST_ASSERT( read_bits == PSA_BYTES_TO_BITS( sizeof( material ) ) );
+    PSA_ASSERT( psa_close_key( handle1 ) );
+
+exit:
+    mbedtls_psa_crypto_free( );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void many_transient_handles( int max_handles_arg )
+{
+    psa_key_handle_t *handles = NULL;
+    size_t max_handles = max_handles_arg;
+    size_t i, j;
+    psa_status_t status;
+    psa_key_policy_t policy;
+    uint8_t exported[sizeof( size_t )];
+    size_t exported_length;
+    size_t max_bits = PSA_BITS_TO_BYTES( sizeof( exported ) );
+
+    ASSERT_ALLOC( handles, max_handles );
+    PSA_ASSERT( psa_crypto_init( ) );
+    psa_key_policy_init( &policy );
+    psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_EXPORT, 0 );
+
+    for( i = 0; i < max_handles; i++ )
+    {
+        status = psa_allocate_key( PSA_KEY_TYPE_RAW_DATA, max_bits,
+                                   &handles[i] );
+        if( status == PSA_ERROR_INSUFFICIENT_MEMORY )
+            break;
+        TEST_ASSERT( status == PSA_SUCCESS );
+        TEST_ASSERT( handles[i] != 0 );
+        for( j = 0; j < i; j++ )
+            TEST_ASSERT( handles[i] != handles[j] );
+        PSA_ASSERT( psa_set_key_policy( handles[i], &policy ) );
+        PSA_ASSERT( psa_import_key( handles[i], PSA_KEY_TYPE_RAW_DATA,
+                                    (uint8_t *) &i, sizeof( i ) ) );
+    }
+    max_handles = i;
+
+    for( i = 1; i < max_handles; i++ )
+    {
+        PSA_ASSERT( psa_close_key( handles[i - 1] ) );
+        PSA_ASSERT( psa_export_key( handles[i],
+                                    exported, sizeof( exported ),
+                                    &exported_length ) );
+        ASSERT_COMPARE( exported, exported_length,
+                        (uint8_t *) &i, sizeof( i ) );
+    }
+    PSA_ASSERT( psa_close_key( handles[i - 1] ) );
+
+exit:
+    mbedtls_psa_crypto_free( );
+    mbedtls_free( handles );
+}
+/* END_CASE */
+
diff --git a/tests/suites/test_suite_psa_crypto_storage_file.function b/tests/suites/test_suite_psa_crypto_storage_file.function
index b6dcad7..e753d78 100644
--- a/tests/suites/test_suite_psa_crypto_storage_file.function
+++ b/tests/suites/test_suite_psa_crypto_storage_file.function
@@ -11,9 +11,11 @@
  */
 
 /* BEGIN_CASE */
-void load_data_from_file( int slot_to_load, data_t *data, int should_make_file,
+void load_data_from_file( int id_to_load_arg,
+                          data_t *data, int should_make_file,
                           int capacity_arg, int expected_status )
 {
+    psa_key_id_t id_to_load = id_to_load_arg;
     char slot_location[] = "psa_key_slot_1";
     psa_status_t status;
     int ret;
@@ -36,8 +38,7 @@
     /* Read from the file with psa_crypto_storage_load. */
     loaded_data = mbedtls_calloc( 1, capacity );
     TEST_ASSERT( loaded_data != NULL );
-    status = psa_crypto_storage_load( (psa_key_slot_t) slot_to_load, loaded_data,
-                                   file_size );
+    status = psa_crypto_storage_load( id_to_load, loaded_data, file_size );
 
     /* Check we get the expected status. */
     TEST_ASSERT( status == expected_status );
diff --git a/visualc/VS2010/mbedTLS.vcxproj b/visualc/VS2010/mbedTLS.vcxproj
index d305c45..366b97e 100644
--- a/visualc/VS2010/mbedTLS.vcxproj
+++ b/visualc/VS2010/mbedTLS.vcxproj
@@ -231,7 +231,9 @@
     <ClInclude Include="..\..\include\psa\crypto_platform.h" />

     <ClInclude Include="..\..\include\psa\crypto_sizes.h" />

     <ClInclude Include="..\..\include\psa\crypto_struct.h" />

+    <ClInclude Include="..\..\library/psa_crypto_core.h" />

     <ClInclude Include="..\..\library/psa_crypto_invasive.h" />

+    <ClInclude Include="..\..\library/psa_crypto_slot_management.h" />

     <ClInclude Include="..\..\library/psa_crypto_storage.h" />

     <ClInclude Include="..\..\library/psa_crypto_storage_backend.h" />

   </ItemGroup>

@@ -291,6 +293,7 @@
     <ClCompile Include="..\..\library\platform_util.c" />

     <ClCompile Include="..\..\library\poly1305.c" />

     <ClCompile Include="..\..\library\psa_crypto.c" />

+    <ClCompile Include="..\..\library\psa_crypto_slot_management.c" />

     <ClCompile Include="..\..\library\psa_crypto_storage.c" />

     <ClCompile Include="..\..\library\psa_crypto_storage_file.c" />

     <ClCompile Include="..\..\library\psa_crypto_storage_its.c" />