Merge pull request #263 from ARMmbed/psa-key_attributes-prototype

PSA key creation with attributes
diff --git a/docs/getting_started.md b/docs/getting_started.md
index 3008a19..84ed891 100644
--- a/docs/getting_started.md
+++ b/docs/getting_started.md
@@ -510,7 +510,7 @@
     psa_set_key_policy(slot, &policy);
 
     /* Generate a key */
-    psa_generate_key(slot, PSA_KEY_TYPE_AES, bits, NULL, 0);
+    psa_generate_key(slot, PSA_KEY_TYPE_AES, bits);
 
     psa_export_key(slot, exported, exported_size, &exported_length)
 
diff --git a/include/psa/crypto.h b/include/psa/crypto.h
index 6a7bce8..fff144c 100644
--- a/include/psa/crypto.h
+++ b/include/psa/crypto.h
@@ -93,137 +93,414 @@
 
 /**@}*/
 
-/** \defgroup policy Key policies
+/** \defgroup attributes Key attributes
  * @{
  */
 
-/** The type of the key policy data structure.
+/** The type of a structure containing key attributes.
  *
- * Before calling any function on a key policy, the application must initialize
- * it by any of the following means:
+ * This is an opaque structure that can represent the metadata of a key
+ * object. Metadata that can be stored in attributes includes:
+ * - The location of the key in storage, indicated by its key identifier
+ *   and its lifetime.
+ * - The key's policy, comprising usage flags and a specification of
+ *   the permitted algorithm(s).
+ * - Information about the key itself: the key type, the key size, and
+ *   for some key type additional domain parameters.
+ * - Implementations may define additional attributes.
+ *
+ * The actual key material is not considered an attribute of a key.
+ * Key attributes do not contain information that is generally considered
+ * highly confidential.
+ *
+ * An attribute structure can be a simple data structure where each function
+ * `psa_set_key_xxx` sets a field and the corresponding function
+ * `psa_get_key_xxx` retrieves the value of the corresponding field.
+ * However, implementations may report values that are equivalent to the
+ * original one, but have a different encoding. For example, an
+ * implementation may use a more compact representation for types where
+ * many bit-patterns are invalid or not supported, and store all values
+ * that it does not support as a special marker value. In such an
+ * implementation, after setting an invalid value, the corresponding
+ * get function returns an invalid value which may not be the one that
+ * was originally stored.
+ *
+ * An attribute structure may contain references to auxiliary resources,
+ * for example pointers to allocated memory or indirect references to
+ * pre-calculated values. In order to free such resources, the application
+ * must call psa_reset_key_attributes(). As an exception, calling
+ * psa_reset_key_attributes() on an attribute structure is optional if
+ * the structure has only been modified by the following functions
+ * since it was initialized or last reset with psa_reset_key_attributes():
+ * - psa_make_key_persistent()
+ * - psa_set_key_type()
+ * - psa_set_key_bits()
+ * - psa_set_key_usage_flags()
+ * - psa_set_key_algorithm()
+ *
+ * Before calling any function on a key attribute structure, the application
+ * must initialize it by any of the following means:
  * - Set the structure to all-bits-zero, for example:
  *   \code
- *   psa_key_policy_t policy;
- *   memset(&policy, 0, sizeof(policy));
+ *   psa_key_attributes_t attributes;
+ *   memset(&attributes, 0, sizeof(attributes));
  *   \endcode
  * - Initialize the structure to logical zero values, for example:
  *   \code
- *   psa_key_policy_t policy = {0};
+ *   psa_key_attributes_t attributes = {0};
  *   \endcode
- * - Initialize the structure to the initializer #PSA_KEY_POLICY_INIT,
+ * - Initialize the structure to the initializer #PSA_KEY_ATTRIBUTES_INIT,
  *   for example:
  *   \code
- *   psa_key_policy_t policy = PSA_KEY_POLICY_INIT;
+ *   psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
  *   \endcode
- * - Assign the result of the function psa_key_policy_init()
+ * - Assign the result of the function psa_key_attributes_init()
  *   to the structure, for example:
  *   \code
- *   psa_key_policy_t policy;
- *   policy = psa_key_policy_init();
+ *   psa_key_attributes_t attributes;
+ *   attributes = psa_key_attributes_init();
  *   \endcode
  *
- * This is an implementation-defined \c struct. Applications should not
- * make any assumptions about the content of this structure except
- * as directed by the documentation of a specific implementation. */
-typedef struct psa_key_policy_s psa_key_policy_t;
-
-/** \def PSA_KEY_POLICY_INIT
+ * A freshly initialized attribute structure contains the following
+ * values:
  *
- * This macro returns a suitable initializer for a key policy object of type
- * #psa_key_policy_t.
+ * - lifetime: #PSA_KEY_LIFETIME_VOLATILE.
+ * - key identifier: unspecified.
+ * - type: \c 0, with no domain parameters.
+ * - key size: \c 0.
+ * - usage flags: \c 0.
+ * - algorithm: \c 0.
+ *
+ * A typical sequence to create a key is as follows:
+ * -# Create and initialize an attribute structure.
+ * -# If the key is persistent, call psa_make_key_persistent().
+ * -# Set the key policy with psa_set_key_usage_flags() and
+ *    psa_set_key_algorithm().
+ * -# Set the key type with psa_set_key_type(). If the key type requires
+ *    domain parameters, call psa_set_key_domain_parameters() instead.
+ *    Skip this step if copying an existing key with psa_copy_key().
+ * -# When generating a random key with psa_generate_key() or deriving a key
+ *    with psa_generator_import_key(), set the desired key size with
+ *    psa_set_key_bits().
+ * -# Call a key creation function: psa_import_key(), psa_generate_key(),
+ *    psa_generator_import_key() or psa_copy_key(). This function reads
+ *    the attribute structure, creates a key with these attributes, and
+ *    outputs a handle to the newly created key.
+ * -# The attribute structure is now no longer necessary. If you called
+ *    psa_set_key_domain_parameters() earlier, you must call
+ *    psa_reset_key_attributes() to free any resources used by the
+ *    domain parameters. Otherwise calling psa_reset_key_attributes()
+ *    is optional.
+ *
+ * A typical sequence to query a key's attributes is as follows:
+ * -# Call psa_get_key_attributes().
+ * -# Call `psa_get_key_xxx` functions to retrieve the attribute(s) that
+ *    you are interested in.
+ * -# Call psa_reset_key_attributes() to free any resources that may be
+ *    used by the attribute structure.
+ *
+ * Once a key has been created, it is impossible to change its attributes.
  */
-#ifdef __DOXYGEN_ONLY__
-/* This is an example definition for documentation purposes.
- * Implementations should define a suitable value in `crypto_struct.h`.
- */
-#define PSA_KEY_POLICY_INIT {0}
-#endif
+typedef struct psa_key_attributes_s psa_key_attributes_t;
 
-/** Return an initial value for a key policy that forbids all usage of the key.
+/** Declare a key as persistent.
+ *
+ * This function does not access storage, it merely fills the attribute
+ * structure with given values. The persistent key will be written to
+ * storage when the attribute structure is passed to a key creation
+ * function such as psa_import_key(), psa_generate_key(),
+ * psa_generator_import_key() or psa_copy_key().
+ *
+ * This function overwrites any identifier and lifetime values
+ * previously set in \p attributes.
+ *
+ * This function may be declared as `static` (i.e. without external
+ * linkage). This function may be provided as a function-like macro,
+ * but in this case it must evaluate each of its arguments exactly once.
+ *
+ * \param[out] attributes       The attribute structure to write to.
+ * \param id                    The persistent identifier for the key.
+ * \param lifetime              The lifetime for the key.
+ *                              If this is #PSA_KEY_LIFETIME_VOLATILE, the
+ *                              key will be volatile, and \p id is ignored.
  */
-static psa_key_policy_t psa_key_policy_init(void);
+static void psa_make_key_persistent(psa_key_attributes_t *attributes,
+                                    psa_key_id_t id,
+                                    psa_key_lifetime_t lifetime);
 
-/** \brief Set the standard fields of a policy structure.
+/** Retrieve the key identifier from key attributes.
  *
- * Note that this function does not make any consistency check of the
- * parameters. The values are only checked when applying the policy to
- * a key slot with psa_set_key_policy().
+ * This function may be declared as `static` (i.e. without external
+ * linkage). This function may be provided as a function-like macro,
+ * but in this case it must evaluate its argument exactly once.
  *
- * \param[in,out] policy The key policy to modify. It must have been
- *                       initialized as per the documentation for
- *                       #psa_key_policy_t.
- * \param usage          The permitted uses for the key.
- * \param alg            The algorithm that the key may be used for.
+ * \param[in] attributes        The key attribute structure to query.
+ *
+ * \return The persistent identifier stored in the attribute structure.
+ *         This value is unspecified if the attribute structure declares
+ *         the key as volatile.
  */
-void psa_key_policy_set_usage(psa_key_policy_t *policy,
-                              psa_key_usage_t usage,
-                              psa_algorithm_t alg);
+static psa_key_id_t psa_get_key_id(const psa_key_attributes_t *attributes);
 
-/** \brief Retrieve the usage field of a policy structure.
+/** Retrieve the lifetime from key attributes.
  *
- * \param[in] policy    The policy object to query.
+ * This function may be declared as `static` (i.e. without external
+ * linkage). This function may be provided as a function-like macro,
+ * but in this case it must evaluate its argument exactly once.
  *
- * \return The permitted uses for a key with this policy.
+ * \param[in] attributes        The key attribute structure to query.
+ *
+ * \return The lifetime value stored in the attribute structure.
  */
-psa_key_usage_t psa_key_policy_get_usage(const psa_key_policy_t *policy);
+static psa_key_lifetime_t psa_get_key_lifetime(
+    const psa_key_attributes_t *attributes);
 
-/** \brief Retrieve the algorithm field of a policy structure.
+/** Declare usage flags for a key.
  *
- * \param[in] policy    The policy object to query.
+ * Usage flags are part of a key's usage policy. They encode what
+ * kind of operations are permitted on the key. For more details,
+ * refer to the documentation of the type #psa_key_usage_t.
  *
- * \return The permitted algorithm for a key with this policy.
+ * This function overwrites any usage flags
+ * previously set in \p attributes.
+ *
+ * This function may be declared as `static` (i.e. without external
+ * linkage). This function may be provided as a function-like macro,
+ * but in this case it must evaluate each of its arguments exactly once.
+ *
+ * \param[out] attributes       The attribute structure to write to.
+ * \param usage_flags           The usage flags to write.
  */
-psa_algorithm_t psa_key_policy_get_algorithm(const psa_key_policy_t *policy);
+static void psa_set_key_usage_flags(psa_key_attributes_t *attributes,
+                                    psa_key_usage_t usage_flags);
 
-/** \brief Set the usage policy on a key slot.
+/** Retrieve the usage flags from key attributes.
  *
- * This function must be called on an empty key slot, before importing,
- * generating or creating a key in the slot. Changing the policy of an
- * existing key is not permitted.
+ * This function may be declared as `static` (i.e. without external
+ * linkage). This function may be provided as a function-like macro,
+ * but in this case it must evaluate its argument exactly once.
  *
- * Implementations may set restrictions on supported key policies
- * depending on the key type and the key slot.
+ * \param[in] attributes        The key attribute structure to query.
  *
- * \param handle        Handle to the key whose policy is to be changed.
- * \param[in] policy    The policy object to query.
+ * \return The usage flags stored in the attribute structure.
+ */
+static psa_key_usage_t psa_get_key_usage_flags(
+    const psa_key_attributes_t *attributes);
+
+/** Declare the permitted algorithm policy for a key.
+ *
+ * The permitted algorithm policy of a key encodes which algorithm or
+ * algorithms are permitted to be used with this key.
+ *
+ * This function overwrites any algorithm policy
+ * previously set in \p attributes.
+ *
+ * This function may be declared as `static` (i.e. without external
+ * linkage). This function may be provided as a function-like macro,
+ * but in this case it must evaluate each of its arguments exactly once.
+ *
+ * \param[out] attributes       The attribute structure to write to.
+ * \param alg                   The permitted algorithm policy to write.
+ */
+static void psa_set_key_algorithm(psa_key_attributes_t *attributes,
+                                  psa_algorithm_t alg);
+
+/** Retrieve the algorithm policy from key attributes.
+ *
+ * This function may be declared as `static` (i.e. without external
+ * linkage). This function may be provided as a function-like macro,
+ * but in this case it must evaluate its argument exactly once.
+ *
+ * \param[in] attributes        The key attribute structure to query.
+ *
+ * \return The algorithm stored in the attribute structure.
+ */
+static psa_algorithm_t psa_get_key_algorithm(
+    const psa_key_attributes_t *attributes);
+
+/** Declare the type of a key.
+ *
+ * If a type requires domain parameters, you must call
+ * psa_set_key_domain_parameters() instead of this function.
+ *
+ * This function overwrites any key type and domain parameters
+ * previously set in \p attributes.
+ *
+ * This function may be declared as `static` (i.e. without external
+ * linkage). This function may be provided as a function-like macro,
+ * but in this case it must evaluate each of its arguments exactly once.
+ *
+ * \param[out] attributes       The attribute structure to write to.
+ * \param type                  The key type to write.
+ */
+static void psa_set_key_type(psa_key_attributes_t *attributes,
+                             psa_key_type_t type);
+
+/** Declare the size of a key.
+ *
+ * This function overwrites any key size previously set in \p attributes.
+ *
+ * This function may be declared as `static` (i.e. without external
+ * linkage). This function may be provided as a function-like macro,
+ * but in this case it must evaluate each of its arguments exactly once.
+ *
+ * \param[out] attributes       The attribute structure to write to.
+ * \param bits                  The key size in bits.
+ */
+static void psa_set_key_bits(psa_key_attributes_t *attributes,
+                             size_t bits);
+
+/** Retrieve the key type from key attributes.
+ *
+ * This function may be declared as `static` (i.e. without external
+ * linkage). This function may be provided as a function-like macro,
+ * but in this case it must evaluate its argument exactly once.
+ *
+ * \param[in] attributes        The key attribute structure to query.
+ *
+ * \return The key type stored in the attribute structure.
+ */
+static psa_key_type_t psa_get_key_type(const psa_key_attributes_t *attributes);
+
+/** Retrieve the key size from key attributes.
+ *
+ * This function may be declared as `static` (i.e. without external
+ * linkage). This function may be provided as a function-like macro,
+ * but in this case it must evaluate its argument exactly once.
+ *
+ * \param[in] attributes        The key attribute structure to query.
+ *
+ * \return The key size stored in the attribute structure, in bits.
+ */
+static size_t psa_get_key_bits(const psa_key_attributes_t *attributes);
+
+/**
+ * \brief Set domain parameters for a key.
+ *
+ * Some key types require additional domain parameters in addition to
+ * the key type identifier and the key size.
+ * The format for the required domain parameters varies by the key type.
+ *
+ * - For RSA keys (#PSA_KEY_TYPE_RSA_PUBLIC_KEY or #PSA_KEY_TYPE_RSA_KEYPAIR),
+ *   the domain parameter data consists of the public exponent,
+ *   represented as a big-endian integer with no leading zeros.
+ *   This information is used when generating an RSA key pair.
+ *   When importing a key, the public exponent is read from the imported
+ *   key data and the exponent recorded in the attribute structure is ignored.
+ *   As an exception, the public exponent 65537 is represented by an empty
+ *   byte string.
+ * - For DSA keys (#PSA_KEY_TYPE_DSA_PUBLIC_KEY or #PSA_KEY_TYPE_DSA_KEYPAIR),
+ *   the `Dss-Parms` format as defined by RFC 3279 §2.3.2.
+ *   ```
+ *   Dss-Parms ::= SEQUENCE  {
+ *      p       INTEGER,
+ *      q       INTEGER,
+ *      g       INTEGER
+ *   }
+ *   ```
+ * - For Diffie-Hellman key exchange keys (#PSA_KEY_TYPE_DH_PUBLIC_KEY or
+ *   #PSA_KEY_TYPE_DH_KEYPAIR), the
+ *   `DomainParameters` format as defined by RFC 3279 §2.3.3.
+ *   ```
+ *   DomainParameters ::= SEQUENCE {
+ *      p               INTEGER,                    -- odd prime, p=jq +1
+ *      g               INTEGER,                    -- generator, g
+ *      q               INTEGER,                    -- factor of p-1
+ *      j               INTEGER OPTIONAL,           -- subgroup factor
+ *      validationParms ValidationParms OPTIONAL
+ *   }
+ *   ValidationParms ::= SEQUENCE {
+ *      seed            BIT STRING,
+ *      pgenCounter     INTEGER
+ *   }
+ *   ```
+ *
+ * \note This function may allocate memory or other resources.
+ *       Once you have called this function on an attribute structure,
+ *       you must call psa_reset_key_attributes() to free these resources.
+ *
+ * \param[in,out] attributes    Attribute structure where the specified domain
+ *                              parameters will be stored.
+ *                              If this function fails, the content of
+ *                              \p attributes is not modified.
+ * \param type                  Key type (a \c PSA_KEY_TYPE_XXX value).
+ * \param[in] data              Buffer containing the key domain parameters.
+ *                              The content of this buffer is interpreted
+ *                              according to \p type as described above.
+ * \param data_length           Size of the \p data buffer in bytes.
  *
  * \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_ALREADY_EXISTS
- * \retval #PSA_ERROR_NOT_SUPPORTED
  * \retval #PSA_ERROR_INVALID_ARGUMENT
- * \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.
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
  */
-psa_status_t psa_set_key_policy(psa_key_handle_t handle,
-                                const psa_key_policy_t *policy);
+psa_status_t psa_set_key_domain_parameters(psa_key_attributes_t *attributes,
+                                           psa_key_type_t type,
+                                           const uint8_t *data,
+                                           size_t data_length);
 
-/** \brief Get the usage policy for a key slot.
+/**
+ * \brief Get domain parameters for a key.
  *
- * \param handle        Handle to the key slot whose policy is being queried.
- * \param[out] policy   On success, the key's policy.
+ * Get the domain parameters for a key with this function, if any. The format
+ * of the domain parameters written to \p data is specified in the
+ * documentation for psa_set_key_domain_parameters().
+ *
+ * \param[in] attributes        The key attribute structure to query.
+ * \param[out] data             On success, the key domain parameters.
+ * \param data_size             Size of the \p data buffer in bytes.
+ *                              The buffer is guaranteed to be large
+ *                              enough if its size in bytes is at least
+ *                              the value given by
+ *                              PSA_KEY_DOMAIN_PARAMETERS_SIZE().
+ * \param[out] data_length      On success, the number of bytes
+ *                              that make up the key domain parameters data.
+ *
+ * \retval #PSA_SUCCESS
+ * \retval #PSA_ERROR_BUFFER_TOO_SMALL
+ */
+psa_status_t psa_get_key_domain_parameters(
+    const psa_key_attributes_t *attributes,
+    uint8_t *data,
+    size_t data_size,
+    size_t *data_length);
+
+/** Retrieve the attributes of a key.
+ *
+ * This function first resets the attribute structure as with
+ * psa_reset_key_attributes(). It then copies the attributes of
+ * the given key into the given attribute structure.
+ *
+ * \note This function may allocate memory or other resources.
+ *       Once you have called this function on an attribute structure,
+ *       you must call psa_reset_key_attributes() to free these resources.
+ *
+ * \param[in] handle            Handle to the key to query.
+ * \param[in,out] attributes    On success, the attributes of the key.
+ *                              On failure, equivalent to a
+ *                              freshly-initialized structure.
  *
  * \retval #PSA_SUCCESS
  * \retval #PSA_ERROR_INVALID_HANDLE
+ * \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
- *         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_policy(psa_key_handle_t handle,
-                                psa_key_policy_t *policy);
+psa_status_t psa_get_key_attributes(psa_key_handle_t handle,
+                                    psa_key_attributes_t *attributes);
+
+/** Reset a key attribute structure to a freshly initialized state.
+ *
+ * You must initialize the attribute structure as described in the
+ * documentation of the type #psa_key_attributes_t before calling this
+ * function. Once the structure has been initialized, you may call this
+ * function at any time.
+ *
+ * This function frees any auxiliary resources that the structure
+ * may contain.
+ *
+ * \param[in,out] attributes    The attribute structure to reset.
+ */
+void psa_reset_key_attributes(psa_key_attributes_t *attributes);
 
 /**@}*/
 
@@ -231,44 +508,6 @@
  * @{
  */
 
-/** \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.
- *
- * \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.
- */
-psa_status_t psa_allocate_key(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().
@@ -302,43 +541,6 @@
                           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[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_ALREADY_EXISTS
- *         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_handle_t *handle);
-
 /** Close a key handle.
  *
  * If the handle designates a volatile key, destroy the key material and
@@ -380,32 +582,38 @@
  * minimize the risk that an invalid input is accidentally interpreted
  * according to a different format.
  *
- * \param handle      Handle to the slot where the key will be stored.
- *                    It must have been obtained by calling
- *                    psa_allocate_key() or psa_create_key() and must
- *                    not contain key material yet.
- * \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] attributes    The attributes for the new key.
+ *                          The key size field in \p attributes is
+ *                          ignored; the actual key size is determined
+ *                          from the \p data buffer.
+ * \param[out] handle       On success, a handle to the newly created key.
+ *                          \c 0 on failure.
  * \param[in] data    Buffer containing the key data. The content of this
- *                    buffer is interpreted according to \p type. It must
- *                    contain the format described in the documentation
+ *                    buffer is interpreted according to the type and,
+ *                    if applicable, domain parameters declared in
+ *                    \p attributes.
+ *                    All implementations must support at least the format
+ *                    described in the documentation
  *                    of psa_export_key() or psa_export_public_key() for
- *                    the chosen type.
+ *                    the chosen type. Implementations may allow other
+ *                    formats, but should be conservative: implementations
+ *                    should err on the side of rejecting content if it
+ *                    may be erroneous (e.g. wrong type or truncated data).
  * \param data_length Size of the \p data buffer in bytes.
  *
  * \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_ALREADY_EXISTS
+ *         This is an attempt to create a persistent key, and there is
+ *         already a persistent key with the given identifier.
  * \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.
+ *         implementation in general or in this particular persistent location.
  * \retval #PSA_ERROR_INVALID_ARGUMENT
- *         The key slot is invalid,
+ *         The key attributes, as a whole, are invalid,
  *         or the key data is not correctly formatted.
- * \retval #PSA_ERROR_ALREADY_EXISTS
- *         There is already a key in the specified slot.
  * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
  * \retval #PSA_ERROR_INSUFFICIENT_STORAGE
  * \retval #PSA_ERROR_COMMUNICATION_FAILURE
@@ -417,8 +625,8 @@
  *         It is implementation-dependent whether a failure to initialize
  *         results in this error code.
  */
-psa_status_t psa_import_key(psa_key_handle_t handle,
-                            psa_key_type_t type,
+psa_status_t psa_import_key(const psa_key_attributes_t *attributes,
+                            psa_key_handle_t *handle,
                             const uint8_t *data,
                             size_t data_length);
 
@@ -464,133 +672,6 @@
 psa_status_t psa_destroy_key(psa_key_handle_t handle);
 
 /**
- * \brief Get basic metadata about a key.
- *
- * \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.
- * \param[out] bits     On success, the key size in bits.
- *                      This may be a null pointer, in which case the key size
- *                      is not written.
- *
- * \retval #PSA_SUCCESS
- * \retval #PSA_ERROR_INVALID_HANDLE
- * \retval #PSA_ERROR_DOES_NOT_EXIST
- *         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
- * \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_information(psa_key_handle_t handle,
-                                     psa_key_type_t *type,
-                                     size_t *bits);
-
-/**
- * \brief Set domain parameters for a key.
- *
- * Some key types require additional domain parameters to be set before import
- * or generation of the key. The domain parameters can be set with this
- * function or, for key generation, through the \c extra parameter of
- * psa_generate_key().
- *
- * The format for the required domain parameters varies by the key type.
- * - For DSA public keys (#PSA_KEY_TYPE_DSA_PUBLIC_KEY),
- *   the `Dss-Parms` format as defined by RFC 3279 §2.3.2.
- *   ```
- *   Dss-Parms ::= SEQUENCE  {
- *      p       INTEGER,
- *      q       INTEGER,
- *      g       INTEGER
- *   }
- *   ```
- * - For Diffie-Hellman key exchange keys (#PSA_KEY_TYPE_DH_PUBLIC_KEY), the
- *   `DomainParameters` format as defined by RFC 3279 §2.3.3.
- *   ```
- *   DomainParameters ::= SEQUENCE {
- *      p               INTEGER,                    -- odd prime, p=jq +1
- *      g               INTEGER,                    -- generator, g
- *      q               INTEGER,                    -- factor of p-1
- *      j               INTEGER OPTIONAL,           -- subgroup factor
- *      validationParms ValidationParms OPTIONAL
- *   }
- *   ValidationParms ::= SEQUENCE {
- *      seed            BIT STRING,
- *      pgenCounter     INTEGER
- *   }
- *   ```
- *
- * \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. It must not contain
- *                    key material yet.
- * \param type        Key type (a \c PSA_KEY_TYPE_XXX value). When
- *                    subsequently creating key material into \p handle,
- *                    the type must be compatible.
- * \param[in] data    Buffer containing the key domain parameters. The content
- *                    of this buffer is interpreted according to \p type. of
- *                    psa_export_key() or psa_export_public_key() for the
- *                    chosen type.
- * \param data_length Size of the \p data buffer in bytes.
- *
- * \retval #PSA_SUCCESS
- * \retval #PSA_ERROR_INVALID_HANDLE
- * \retval #PSA_ERROR_OCCUPIED_SLOT
- *         There is already a key in the specified slot.
- * \retval #PSA_ERROR_INVALID_ARGUMENT
- * \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_domain_parameters(psa_key_handle_t handle,
-                                           psa_key_type_t type,
-                                           const uint8_t *data,
-                                           size_t data_length);
-
-/**
- * \brief Get domain parameters for a key.
- *
- * Get the domain parameters for a key with this function, if any. The format
- * of the domain parameters written to \p data is specified in the
- * documentation for psa_set_key_domain_parameters().
- *
- * \param handle            Handle to the key to get domain parameters from.
- * \param[out] data         On success, the key domain parameters.
- * \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 domain parameters data.
- *
- * \retval #PSA_SUCCESS
- * \retval #PSA_ERROR_INVALID_HANDLE
- * \retval #PSA_ERROR_EMPTY_SLOT
- *         There is no key in the specified slot.
- * \retval #PSA_ERROR_INVALID_ARGUMENT
- * \retval #PSA_ERROR_NOT_SUPPORTED
- * \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_domain_parameters(psa_key_handle_t handle,
-                                           uint8_t *data,
-                                           size_t data_size,
-                                           size_t *data_length);
-
-/**
  * \brief Export a key in binary format.
  *
  * The output of this function can be passed to psa_import_key() to
@@ -757,48 +838,52 @@
  * In an implementation where slots have different ownerships,
  * this function may be used to share a key with a different party,
  * subject to implementation-defined restrictions on key sharing.
- * In this case \p constraint would typically prevent the recipient
- * from exporting the key.
  *
- * The resulting key may only be used in a way that conforms to all
- * three of: the policy of the source key, the policy previously set
- * on the target, and the \p constraint parameter passed when calling
- * this function.
+ * The resulting key may only be used in a way that conforms to
+ * both the policy of the original key and the policy specified in
+ * the \p attributes parameter:
  * - The usage flags on the resulting key are the bitwise-and of the
- *   usage flags on the source policy, the previously-set target policy
- *   and the policy constraint.
- * - If all three policies allow the same algorithm or wildcard-based
+ *   usage flags on the source policy and the usage flags in \p attributes.
+ * - If both allow the same algorithm or wildcard-based
  *   algorithm policy, the resulting key has the same algorithm policy.
- * - If one of the policies allows an algorithm and all the other policies
- *   either allow the same algorithm or a wildcard-based algorithm policy
- *   that includes this algorithm, the resulting key allows the same
- *   algorithm.
+ * - If either of the policies allows an algorithm and the other policy
+ *   allows a wildcard-based algorithm policy that includes this algorithm,
+ *   the resulting key allows the same algorithm.
+ * - If the policies do not allow any algorithm in common, this function
+ *   fails with the status #PSA_ERROR_INVALID_ARGUMENT.
  *
- * The effect of this function on implementation-defined metadata is
+ * The effect of this function on implementation-defined attributes is
  * implementation-defined.
  *
  * \param source_handle     The key to copy. It must be a handle to an
  *                          occupied slot.
- * \param target_handle     A handle to the target slot. It must not contain
- *                          key material yet.
- * \param[in] constraint    An optional policy constraint. If this parameter
- *                          is non-null then the resulting key will conform
- *                          to this policy in addition to the source policy
- *                          and the policy already present on the target
- *                          slot. If this parameter is null then the
- *                          function behaves in the same way as if it was
- *                          the target policy, i.e. only the source and
- *                          target policies apply.
+ * \param[in] attributes    The attributes for the new key.
+ *                          They are used as follows:
+ *                          - The key type, key size and domain parameters
+ *                            are ignored. This information is copied
+ *                            from the source key.
+ *                          - The key location (the lifetime and, for
+ *                            persistent keys, the key identifier) is
+ *                            used directly.
+ *                          - The policy constraints (usage flags and
+ *                            algorithm policy) are combined from
+ *                            the source key and \p attributes so that
+ *                            both sets of restrictions apply, as
+ *                            described in the documentation of this function.
+ * \param[out] target_handle On success, a handle to the newly created key.
+ *                          \c 0 on failure.
  *
  * \retval #PSA_SUCCESS
  * \retval #PSA_ERROR_INVALID_HANDLE
+ *         \p source_handle is invalid.
  * \retval #PSA_ERROR_ALREADY_EXISTS
- *         \p target_handle already contains key material.
- * \retval #PSA_ERROR_DOES_NOT_EXIST
- *         \p source_handle does not contain key material.
+ *         This is an attempt to create a persistent key, and there is
+ *         already a persistent key with the given identifier.
  * \retval #PSA_ERROR_INVALID_ARGUMENT
- *         The policy constraints on the source, on the target and
- *         \p constraint are incompatible.
+ *         The lifetime or identifier in \p attributes are invalid.
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ *         The policy constraints on the source and specified in
+ *         \p attributes are incompatible.
  * \retval #PSA_ERROR_NOT_PERMITTED
  *         The source key is not exportable and its lifetime does not
  *         allow copying it to the target's lifetime.
@@ -809,8 +894,8 @@
  * \retval #PSA_ERROR_TAMPERING_DETECTED
  */
 psa_status_t psa_copy_key(psa_key_handle_t source_handle,
-                          psa_key_handle_t target_handle,
-                          const psa_key_policy_t *constraint);
+                          const psa_key_attributes_t *attributes,
+                          psa_key_handle_t *target_handle);
 
 /**@}*/
 
@@ -2971,19 +3056,18 @@
  * In all cases, the data that is read is discarded from the generator.
  * The generator's capacity is decreased by the number of bytes read.
  *
- * \param handle            Handle to the slot where the key will be stored.
- *                          It must have been obtained by calling
- *                          psa_allocate_key() or psa_create_key() and must
- *                          not contain key material yet.
- * \param type              Key type (a \c PSA_KEY_TYPE_XXX value).
- *                          This must be a secret key type or a key pair type.
- * \param bits              Key size in bits.
+ * \param[in] attributes    The attributes for the new key.
+ * \param[out] handle       On success, a handle to the newly created key.
+ *                          \c 0 on failure.
  * \param[in,out] generator The generator object to read from.
  *
  * \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_ALREADY_EXISTS
+ *         This is an attempt to create a persistent key, and there is
+ *         already a persistent key with the given identifier.
  * \retval #PSA_ERROR_INSUFFICIENT_DATA
  *         There was not enough data to create the desired key.
  *         Note that in this case, no output is written to the output buffer.
@@ -2993,9 +3077,6 @@
  *         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_HANDLE
- * \retval #PSA_ERROR_ALREADY_EXISTS
- *         There is already a key in the specified slot.
  * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
  * \retval #PSA_ERROR_INSUFFICIENT_STORAGE
  * \retval #PSA_ERROR_COMMUNICATION_FAILURE
@@ -3006,9 +3087,8 @@
  *         It is implementation-dependent whether a failure to initialize
  *         results in this error code.
  */
-psa_status_t psa_generator_import_key(psa_key_handle_t handle,
-                                      psa_key_type_t type,
-                                      size_t bits,
+psa_status_t psa_generator_import_key(const psa_key_attributes_t *attributes,
+                                      psa_key_handle_t *handle,
                                       psa_crypto_generator_t *generator);
 
 /** Abort a generator.
@@ -3324,68 +3404,37 @@
 psa_status_t psa_generate_random(uint8_t *output,
                                  size_t output_size);
 
-/** Extra parameters for RSA key generation.
- *
- * You may pass a pointer to a structure of this type as the \c extra
- * parameter to psa_generate_key().
- */
-typedef struct {
-    uint32_t e; /**< Public exponent value. Default: 65537. */
-} psa_generate_key_extra_rsa;
-
 /**
  * \brief Generate a key or key pair.
  *
- * \param handle            Handle to the slot where the key will be stored.
- *                          It must have been obtained by calling
- *                          psa_allocate_key() or psa_create_key() and must
- *                          not contain 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
- *                          interpretation of this parameter depends on
- *                          \p type. All types support \c NULL to use
- *                          default parameters. Implementation that support
- *                          the generation of vendor-specific key types
- *                          that allow extra parameters shall document
- *                          the format of these extra parameters and
- *                          the default values. For standard parameters,
- *                          the meaning of \p extra is as follows:
- *                          - For a symmetric key type (a type such
- *                            that #PSA_KEY_TYPE_IS_ASYMMETRIC(\p type) is
- *                            false), \p extra must be \c NULL.
- *                          - For an elliptic curve key type (a type
- *                            such that #PSA_KEY_TYPE_IS_ECC(\p type) is
- *                            false), \p extra must be \c NULL.
- *                          - For an RSA key (\p type is
- *                            #PSA_KEY_TYPE_RSA_KEYPAIR), \p extra is an
- *                            optional #psa_generate_key_extra_rsa structure
- *                            specifying the public exponent. The
- *                            default public exponent used when \p extra
- *                            is \c NULL is 65537.
- *                          - For an DSA key (\p type is
- *                            #PSA_KEY_TYPE_DSA_KEYPAIR), \p extra is an
- *                            optional structure specifying the key domain
- *                            parameters. The key domain parameters can also be
- *                            provided by psa_set_key_domain_parameters(),
- *                            which documents the format of the structure.
- *                          - For a DH key (\p type is
- *                            #PSA_KEY_TYPE_DH_KEYPAIR), the \p extra is an
- *                            optional structure specifying the key domain
- *                            parameters. The key domain parameters can also be
- *                            provided by psa_set_key_domain_parameters(),
- *                            which documents the format of the structure.
- * \param extra_size        Size of the buffer that \p extra
- *                          points to, in bytes. Note that if \p extra is
- *                          \c NULL then \p extra_size must be zero.
+ * The key is generated randomly.
+ * Its location, policy, type and size are taken from \p attributes.
+ *
+ * If the type requires additional domain parameters, these are taken
+ * from \p attributes as well. The following types use domain parameters:
+ * - When generating an RSA key (#PSA_KEY_TYPE_RSA_KEYPAIR),
+ *   the default public exponent is 65537. This value is used if
+ *   \p attributes was set with psa_set_key_type() or by passing an empty
+ *   byte string as domain parameters to psa_set_key_domain_parameters().
+ *   If psa_set_key_domain_parameters() was used to set a non-empty
+ *   domain parameter string in \p attributes, this string is read as
+ *   a big-endian integer which is used as the public exponent.
+ * - When generating a DSA key (#PSA_KEY_TYPE_DSA_KEYPAIR) or a
+ *   Diffie-Hellman key (#PSA_KEY_TYPE_DH_KEYPAIR), the domain parameters
+ *   from \p attributes are interpreted as described for
+ *   psa_set_key_domain_parameters().
+ *
+ * \param[in] attributes    The attributes for the new key.
+ * \param[out] handle       On success, a handle to the newly created key.
+ *                          \c 0 on failure.
  *
  * \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_ALREADY_EXISTS
- *         There is already a key in the specified slot.
+ *         This is an attempt to create a persistent key, and there is
+ *         already a persistent key with the given identifier.
  * \retval #PSA_ERROR_NOT_SUPPORTED
  * \retval #PSA_ERROR_INVALID_ARGUMENT
  * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
@@ -3398,11 +3447,8 @@
  *         It is implementation-dependent whether a failure to initialize
  *         results in this error code.
  */
-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);
+psa_status_t psa_generate_key(const psa_key_attributes_t *attributes,
+                              psa_key_handle_t *handle);
 
 /**@}*/
 
diff --git a/include/psa/crypto_extra.h b/include/psa/crypto_extra.h
index 093355d..f2cf051 100644
--- a/include/psa/crypto_extra.h
+++ b/include/psa/crypto_extra.h
@@ -202,6 +202,247 @@
 /* FIXME Deprecated. Remove this as soon as all the tests are updated. */
 #define PSA_ALG_SELECT_RAW                      ((psa_algorithm_t)0x31000001)
 
+/** \defgroup policy Key policies
+ * @{
+ *
+ * The functions in this section are legacy interfaces where the properties
+ * of a key object are set after allocating a handle, in constrast with the
+ * preferred interface where key objects are created atomically from
+ * a structure that represents the properties.
+ */
+
+/** \def PSA_KEY_POLICY_INIT
+ *
+ * This macro returns a suitable initializer for a key policy object of type
+ * #psa_key_policy_t.
+ */
+#ifdef __DOXYGEN_ONLY__
+/* This is an example definition for documentation purposes.
+ * Implementations should define a suitable value in `crypto_struct.h`.
+ */
+#define PSA_KEY_POLICY_INIT {0}
+#endif
+
+/** Return an initial value for a key policy that forbids all usage of the key.
+ */
+static psa_key_policy_t psa_key_policy_init(void);
+
+/** \brief Set the standard fields of a policy structure.
+ *
+ * Note that this function does not make any consistency check of the
+ * parameters. The values are only checked when applying the policy to
+ * a key slot with psa_set_key_policy().
+ *
+ * \param[in,out] policy The key policy to modify. It must have been
+ *                       initialized as per the documentation for
+ *                       #psa_key_policy_t.
+ * \param usage          The permitted uses for the key.
+ * \param alg            The algorithm that the key may be used for.
+ */
+void psa_key_policy_set_usage(psa_key_policy_t *policy,
+                              psa_key_usage_t usage,
+                              psa_algorithm_t alg);
+
+/** \brief Retrieve the usage field of a policy structure.
+ *
+ * \param[in] policy    The policy object to query.
+ *
+ * \return The permitted uses for a key with this policy.
+ */
+psa_key_usage_t psa_key_policy_get_usage(const psa_key_policy_t *policy);
+
+/** \brief Retrieve the algorithm field of a policy structure.
+ *
+ * \param[in] policy    The policy object to query.
+ *
+ * \return The permitted algorithm for a key with this policy.
+ */
+psa_algorithm_t psa_key_policy_get_algorithm(const psa_key_policy_t *policy);
+
+/** \brief Set the usage policy on a key slot.
+ *
+ * This function must be called on an empty key slot, before importing,
+ * generating or creating a key in the slot. Changing the policy of an
+ * existing key is not permitted.
+ *
+ * Implementations may set restrictions on supported key policies
+ * depending on the key type and the key slot.
+ *
+ * \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_ALREADY_EXISTS
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ * \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_policy(psa_key_handle_t handle,
+                                const psa_key_policy_t *policy);
+
+/** \brief Get the usage policy for a key slot.
+ *
+ * \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
+ * \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_policy(psa_key_handle_t handle,
+                                psa_key_policy_t *policy);
+
+/**@}*/
+
+/** \defgroup to_handle Key creation to allocated handle
+ * @{
+ *
+ * The functions in this section are legacy interfaces where the properties
+ * of a key object are set after allocating a handle, in constrast with the
+ * preferred interface where key objects are created atomically from
+ * a structure that represents the properties.
+ */
+
+/** 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[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_ALREADY_EXISTS
+ *         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_handle_t *handle);
+
+/** 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.
+ *
+ * \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.
+ */
+psa_status_t psa_allocate_key(psa_key_handle_t *handle);
+
+/**
+ * \brief Get basic metadata about a key.
+ *
+ * \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.
+ * \param[out] bits     On success, the key size in bits.
+ *                      This may be a null pointer, in which case the key size
+ *                      is not written.
+ *
+ * \retval #PSA_SUCCESS
+ * \retval #PSA_ERROR_INVALID_HANDLE
+ * \retval #PSA_ERROR_DOES_NOT_EXIST
+ *         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
+ * \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_information(psa_key_handle_t handle,
+                                     psa_key_type_t *type,
+                                     size_t *bits);
+
+/** \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_from_handle(psa_key_handle_t handle,
+                                  psa_key_lifetime_t *lifetime);
+
+psa_status_t psa_import_key_to_handle(psa_key_handle_t handle,
+                            psa_key_type_t type,
+                            const uint8_t *data,
+                            size_t data_length);
+
+psa_status_t psa_copy_key_to_handle(psa_key_handle_t source_handle,
+                          psa_key_handle_t target_handle,
+                          const psa_key_policy_t *constraint);
+
+psa_status_t psa_generator_import_key_to_handle(psa_key_handle_t handle,
+                                      psa_key_type_t type,
+                                      size_t bits,
+                                      psa_crypto_generator_t *generator);
+
+psa_status_t psa_generate_key_to_handle(psa_key_handle_t handle,
+                              psa_key_type_t type,
+                              size_t bits,
+                              const void *extra,
+                              size_t extra_size);
+
+/**@}*/
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/include/psa/crypto_sizes.h b/include/psa/crypto_sizes.h
index 3c879e8..5f6282c 100644
--- a/include/psa/crypto_sizes.h
+++ b/include/psa/crypto_sizes.h
@@ -598,4 +598,36 @@
      PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY(key_type) ? PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(key_bits) : \
      0)
 
+/** Safe output buffer size for psa_get_key_domain_parameters().
+ *
+ * This macro returns a compile-time constant if its arguments are
+ * compile-time constants.
+ *
+ * \warning This function may call its arguments multiple times or
+ *          zero times, so you should not pass arguments that contain
+ *          side effects.
+ *
+ * \param key_type  A supported key type.
+ * \param key_bits  The size of the key in bits.
+ *
+ * \return If the parameters are valid and supported, return
+ *         a buffer size in bytes that guarantees that
+ *         psa_get_key_domain_parameters() will not fail with
+ *         #PSA_ERROR_BUFFER_TOO_SMALL.
+ *         If the parameters are a valid combination that is not supported
+ *         by the implementation, this macro either shall return either a
+ *         sensible size or 0.
+ *         If the parameters are not valid, the
+ *         return value is unspecified.
+ */
+#define PSA_KEY_DOMAIN_PARAMETERS_SIZE(key_type, key_bits)              \
+    (PSA_KEY_TYPE_IS_RSA(key_type) ? sizeof(int) :                      \
+     PSA_KEY_TYPE_IS_DH(key_type) ? PSA_DH_KEY_DOMAIN_PARAMETERS_SIZE(key_bits) : \
+     PSA_KEY_TYPE_IS_DSA(key_type) ? PSA_DSA_KEY_DOMAIN_PARAMETERS_SIZE(key_bits) : \
+     0)
+#define PSA_DH_KEY_DOMAIN_PARAMETERS_SIZE(key_bits)     \
+    (4 + (PSA_BITS_TO_BYTES(key_bits) + 5) * 3 /*without optional parts*/)
+#define PSA_DSA_KEY_DOMAIN_PARAMETERS_SIZE(key_bits)    \
+    (4 + (PSA_BITS_TO_BYTES(key_bits) + 5) * 2 /*p, g*/ + 34 /*q*/)
+
 #endif /* PSA_CRYPTO_SIZES_H */
diff --git a/include/psa/crypto_struct.h b/include/psa/crypto_struct.h
index 6eed259..f6bec2c 100644
--- a/include/psa/crypto_struct.h
+++ b/include/psa/crypto_struct.h
@@ -252,6 +252,7 @@
     psa_key_usage_t usage;
     psa_algorithm_t alg;
 };
+typedef struct psa_key_policy_s psa_key_policy_t;
 
 #define PSA_KEY_POLICY_INIT {0, 0}
 static inline struct psa_key_policy_s psa_key_policy_init( void )
@@ -260,4 +261,102 @@
     return( v );
 }
 
+struct psa_key_attributes_s
+{
+    psa_key_id_t id;
+    psa_key_lifetime_t lifetime;
+    psa_key_policy_t policy;
+    psa_key_type_t type;
+    size_t bits;
+    void *domain_parameters;
+    size_t domain_parameters_size;
+};
+
+#define PSA_KEY_ATTRIBUTES_INIT {0, 0, {0, 0}, 0, 0, NULL, 0}
+static inline struct psa_key_attributes_s psa_key_attributes_init( void )
+{
+    const struct psa_key_attributes_s v = PSA_KEY_ATTRIBUTES_INIT;
+    return( v );
+}
+
+static inline void psa_make_key_persistent(psa_key_attributes_t *attributes,
+                                           psa_key_id_t id,
+                                           psa_key_lifetime_t lifetime)
+{
+    attributes->id = id;
+    attributes->lifetime = lifetime;
+}
+
+static inline psa_key_id_t psa_get_key_id(
+    const psa_key_attributes_t *attributes)
+{
+    return( attributes->id );
+}
+
+static inline psa_key_lifetime_t psa_get_key_lifetime(
+    const psa_key_attributes_t *attributes)
+{
+    return( attributes->lifetime );
+}
+
+static inline void psa_set_key_usage_flags(psa_key_attributes_t *attributes,
+                                           psa_key_usage_t usage_flags)
+{
+    attributes->policy.usage = usage_flags;
+}
+
+static inline psa_key_usage_t psa_get_key_usage_flags(
+    const psa_key_attributes_t *attributes)
+{
+    return( attributes->policy.usage );
+}
+
+static inline void psa_set_key_algorithm(psa_key_attributes_t *attributes,
+                                         psa_algorithm_t alg)
+{
+    attributes->policy.alg = alg;
+}
+
+static inline psa_algorithm_t psa_get_key_algorithm(
+    const psa_key_attributes_t *attributes)
+{
+    return( attributes->policy.alg );
+}
+
+static inline void psa_set_key_type(psa_key_attributes_t *attributes,
+                                    psa_key_type_t type)
+{
+    if( attributes->domain_parameters == NULL )
+    {
+        /* Common case: quick path */
+        attributes->type = type;
+    }
+    else
+    {
+        /* Call the bigger function to free the old domain paramteres.
+         * Ignore any errors which may arise due to type requiring
+         * non-default domain parameters, since this function can't
+         * report errors. */
+        (void) psa_set_key_domain_parameters( attributes, type, NULL, 0 );
+    }
+}
+
+static inline psa_key_type_t psa_get_key_type(
+    const psa_key_attributes_t *attributes)
+{
+    return( attributes->type );
+}
+
+static inline void psa_set_key_bits(psa_key_attributes_t *attributes,
+                                    size_t bits)
+{
+    attributes->bits = bits;
+}
+
+static inline size_t psa_get_key_bits(
+    const psa_key_attributes_t *attributes)
+{
+    return( attributes->bits );
+}
+
 #endif /* PSA_CRYPTO_STRUCT_H */
diff --git a/library/cipher.c b/library/cipher.c
index e854cf6..11f6f8e 100644
--- a/library/cipher.c
+++ b/library/cipher.c
@@ -338,7 +338,7 @@
             return( MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED );
 
         /* Populate new key slot. */
-        status = psa_import_key( cipher_psa->slot,
+        status = psa_import_key_to_handle( cipher_psa->slot,
                                  key_type, key, key_bytelen );
         if( status != PSA_SUCCESS )
             return( MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED );
diff --git a/library/pk.c b/library/pk.c
index a1e278e..6bbfdd1 100644
--- a/library/pk.c
+++ b/library/pk.c
@@ -629,7 +629,7 @@
         return( MBEDTLS_ERR_PK_HW_ACCEL_FAILED );
 
     /* import private key in slot */
-    if( PSA_SUCCESS != psa_import_key( key, key_type, d, d_len ) )
+    if( PSA_SUCCESS != psa_import_key_to_handle( key, key_type, d, d_len ) )
         return( MBEDTLS_ERR_PK_HW_ACCEL_FAILED );
 
     /* remember slot number to be destroyed later by caller */
diff --git a/library/pk_wrap.c b/library/pk_wrap.c
index c7f879a..0c74825 100644
--- a/library/pk_wrap.c
+++ b/library/pk_wrap.c
@@ -589,7 +589,7 @@
         goto cleanup;
     }
 
-    if( psa_import_key( key_slot, psa_type, buf + sizeof( buf ) - key_len, key_len )
+    if( psa_import_key_to_handle( key_slot, psa_type, buf + sizeof( buf ) - key_len, key_len )
          != PSA_SUCCESS )
     {
         ret = MBEDTLS_ERR_PK_BAD_INPUT_DATA;
diff --git a/library/psa_crypto.c b/library/psa_crypto.c
index 3ecab01..6e01997 100644
--- a/library/psa_crypto.c
+++ b/library/psa_crypto.c
@@ -903,7 +903,7 @@
     return( status );
 }
 
-psa_status_t psa_import_key( psa_key_handle_t handle,
+psa_status_t psa_import_key_to_handle( psa_key_handle_t handle,
                              psa_key_type_t type,
                              const uint8_t *data,
                              size_t data_length )
@@ -965,7 +965,7 @@
 }
 
 /* Return the size of the key in the given slot, in bits. */
-static size_t psa_get_key_bits( const psa_key_slot_t *slot )
+static size_t psa_get_key_slot_bits( const psa_key_slot_t *slot )
 {
     if( key_type_is_raw_bytes( slot->type ) )
         return( slot->data.raw.bytes * 8 );
@@ -981,6 +981,133 @@
     return( 0 );
 }
 
+void psa_reset_key_attributes( psa_key_attributes_t *attributes )
+{
+    mbedtls_free( attributes->domain_parameters );
+    memset( attributes, 0, sizeof( *attributes ) );
+}
+
+psa_status_t psa_set_key_domain_parameters( psa_key_attributes_t *attributes,
+                                            psa_key_type_t type,
+                                            const uint8_t *data,
+                                            size_t data_length )
+{
+    uint8_t *copy = NULL;
+
+    if( data_length != 0 )
+    {
+        copy = mbedtls_calloc( 1, data_length );
+        if( copy == NULL )
+            return( PSA_ERROR_INSUFFICIENT_MEMORY );
+        memcpy( copy, data, data_length );
+    }
+    /* After this point, this function is guaranteed to succeed, so it
+     * can start modifying `*attributes`. */
+
+    if( attributes->domain_parameters != NULL )
+    {
+        mbedtls_free( attributes->domain_parameters );
+        attributes->domain_parameters = NULL;
+        attributes->domain_parameters_size = 0;
+    }
+
+    attributes->domain_parameters = copy;
+    attributes->domain_parameters_size = data_length;
+    attributes->type = type;
+    return( PSA_SUCCESS );
+}
+
+psa_status_t psa_get_key_domain_parameters(
+    const psa_key_attributes_t *attributes,
+    uint8_t *data, size_t data_size, size_t *data_length )
+{
+    if( attributes->domain_parameters_size > data_size )
+        return( PSA_ERROR_BUFFER_TOO_SMALL );
+    *data_length = attributes->domain_parameters_size;
+    if( attributes->domain_parameters_size != 0 )
+        memcpy( data, attributes->domain_parameters,
+                attributes->domain_parameters_size );
+    return( PSA_SUCCESS );
+}
+
+#if defined(MBEDTLS_RSA_C)
+static psa_status_t psa_get_rsa_public_exponent(
+    const mbedtls_rsa_context *rsa,
+    psa_key_attributes_t *attributes )
+{
+    mbedtls_mpi mpi;
+    int ret;
+    uint8_t *buffer = NULL;
+    size_t buflen;
+    mbedtls_mpi_init( &mpi );
+
+    ret = mbedtls_rsa_export( rsa, NULL, NULL, NULL, NULL, &mpi );
+    if( ret != 0 )
+        goto exit;
+    if( mbedtls_mpi_cmp_int( &mpi, 65537 ) == 0 )
+    {
+        /* It's the default value, which is reported as an empty string,
+         * so there's nothing to do. */
+        goto exit;
+    }
+
+    buflen = mbedtls_mpi_size( &mpi );
+    buffer = mbedtls_calloc( 1, buflen );
+    if( buffer == NULL )
+    {
+        ret = MBEDTLS_ERR_MPI_ALLOC_FAILED;
+        goto exit;
+    }
+    ret = mbedtls_mpi_write_binary( &mpi, buffer, buflen );
+    if( ret != 0 )
+        goto exit;
+    attributes->domain_parameters = buffer;
+    attributes->domain_parameters_size = buflen;
+
+exit:
+    mbedtls_mpi_free( &mpi );
+    if( ret != 0 )
+        mbedtls_free( buffer );
+    return( mbedtls_to_psa_error( ret ) );
+}
+#endif /* MBEDTLS_RSA_C */
+
+psa_status_t psa_get_key_attributes( psa_key_handle_t handle,
+                                     psa_key_attributes_t *attributes )
+{
+    psa_key_slot_t *slot;
+    psa_status_t status;
+
+    psa_reset_key_attributes( attributes );
+
+    status = psa_get_key_slot( handle, &slot );
+    if( status != PSA_SUCCESS )
+        return( status );
+
+    attributes->id = slot->persistent_storage_id;
+    attributes->lifetime = slot->lifetime;
+    attributes->policy = slot->policy;
+    attributes->type = slot->type;
+    attributes->bits = psa_get_key_slot_bits( slot );
+
+    switch( slot->type )
+    {
+#if defined(MBEDTLS_RSA_C)
+        case PSA_KEY_TYPE_RSA_KEYPAIR:
+        case PSA_KEY_TYPE_RSA_PUBLIC_KEY:
+            status = psa_get_rsa_public_exponent( slot->data.rsa, attributes );
+            break;
+#endif
+        default:
+            /* Nothing else to do. */
+            break;
+    }
+
+    if( status != PSA_SUCCESS )
+        psa_reset_key_attributes( attributes );
+    return( status );
+}
+
 psa_status_t psa_get_key_information( psa_key_handle_t handle,
                                       psa_key_type_t *type,
                                       size_t *bits )
@@ -1001,7 +1128,7 @@
     if( type != NULL )
         *type = slot->type;
     if( bits != NULL )
-        *bits = psa_get_key_bits( slot );
+        *bits = psa_get_key_slot_bits( slot );
     return( PSA_SUCCESS );
 }
 
@@ -1050,7 +1177,7 @@
     {
         psa_status_t status;
 
-        size_t bytes = PSA_BITS_TO_BYTES( psa_get_key_bits( slot ) );
+        size_t bytes = PSA_BITS_TO_BYTES( psa_get_key_slot_bits( slot ) );
         if( bytes > data_size )
             return( PSA_ERROR_BUFFER_TOO_SMALL );
         status = mbedtls_to_psa_error(
@@ -1212,8 +1339,171 @@
 }
 #endif /* defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) */
 
+static psa_status_t psa_set_key_policy_internal(
+    psa_key_slot_t *slot,
+    const psa_key_policy_t *policy )
+{
+    if( ( policy->usage & ~( PSA_KEY_USAGE_EXPORT |
+                             PSA_KEY_USAGE_ENCRYPT |
+                             PSA_KEY_USAGE_DECRYPT |
+                             PSA_KEY_USAGE_SIGN |
+                             PSA_KEY_USAGE_VERIFY |
+                             PSA_KEY_USAGE_DERIVE ) ) != 0 )
+        return( PSA_ERROR_INVALID_ARGUMENT );
+
+    slot->policy = *policy;
+    return( PSA_SUCCESS );
+}
+
+/** Prepare a key slot to receive key material.
+ *
+ * This function allocates a key slot and sets its metadata.
+ *
+ * If this function fails, call psa_fail_key_creation().
+ *
+ * This function is intended to be used as follows:
+ * -# Call psa_start_key_creation() to allocate a key slot, prepare
+ *    it with the specified attributes, and assign it a handle.
+ * -# Populate the slot with the key material.
+ * -# Call psa_finish_key_creation() to finalize the creation of the slot.
+ * In case of failure at any step, stop the sequence and call
+ * psa_fail_key_creation().
+ *
+ * \param attributes    Key attributes for the new key.
+ * \param handle        On success, a handle for the allocated slot.
+ * \param p_slot        On success, a pointer to the prepared slot.
+ *
+ * \retval #PSA_SUCCESS
+ *         The key slot is ready to receive key material.
+ * \return If this function fails, the key slot is an invalid state.
+ *         You must call psa_fail_key_creation() to wipe and free the slot.
+ */
+static psa_status_t psa_start_key_creation(
+    const psa_key_attributes_t *attributes,
+    psa_key_handle_t *handle,
+    psa_key_slot_t **p_slot )
+{
+    psa_status_t status;
+    psa_key_slot_t *slot;
+
+    status = psa_allocate_key( handle );
+    if( status != PSA_SUCCESS )
+        return( status );
+    status = psa_get_key_slot( *handle, p_slot );
+    if( status != PSA_SUCCESS )
+        return( status );
+    slot = *p_slot;
+
+    status = psa_set_key_policy_internal( slot, &attributes->policy );
+    if( status != PSA_SUCCESS )
+        return( status );
+    slot->lifetime = attributes->lifetime;
+    if( attributes->lifetime != PSA_KEY_LIFETIME_VOLATILE )
+    {
+        status = psa_validate_persistent_key_parameters( attributes->lifetime,
+                                                         attributes->id );
+        if( status != PSA_SUCCESS )
+            return( status );
+        slot->persistent_storage_id = attributes->id;
+    }
+    slot->type = attributes->type;
+
+    return( status );
+}
+
+/** Finalize the creation of a key once its key material has been set.
+ *
+ * This entails writing the key to persistent storage.
+ *
+ * If this function fails, call psa_fail_key_creation().
+ * See the documentation of psa_start_key_creation() for the intended use
+ * of this function.
+ *
+ * \param slot          Pointer to the slot with key material.
+ *
+ * \retval #PSA_SUCCESS
+ *         The key was successfully created. The handle is now valid.
+ * \return If this function fails, the key slot is an invalid state.
+ *         You must call psa_fail_key_creation() to wipe and free the slot.
+ */
+static psa_status_t psa_finish_key_creation( psa_key_slot_t *slot )
+{
+    psa_status_t status = PSA_SUCCESS;
+    (void) slot;
+
+#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C)
+    if( slot->lifetime == PSA_KEY_LIFETIME_PERSISTENT )
+    {
+        uint8_t *buffer = NULL;
+        size_t buffer_size = 0;
+        size_t length;
+
+        buffer_size = PSA_KEY_EXPORT_MAX_SIZE( slot->type,
+                                               psa_get_key_slot_bits( slot ) );
+        buffer = mbedtls_calloc( 1, buffer_size );
+        if( buffer == NULL && buffer_size != 0 )
+            return( PSA_ERROR_INSUFFICIENT_MEMORY );
+        status = psa_internal_export_key( slot,
+                                          buffer, buffer_size, &length,
+                                          0 );
+
+        if( status == PSA_SUCCESS )
+        {
+            status = psa_save_persistent_key( slot->persistent_storage_id,
+                                              slot->type, &slot->policy,
+                                              buffer, length );
+        }
+
+        if( buffer_size != 0 )
+            mbedtls_platform_zeroize( buffer, buffer_size );
+        mbedtls_free( buffer );
+    }
+#endif /* defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) */
+
+    return( status );
+}
+
+/** Abort the creation of a key.
+ *
+ * You may call this function after calling psa_start_key_creation(),
+ * or after psa_finish_key_creation() fails. In other circumstances, this
+ * function may not clean up persistent storage.
+ * See the documentation of psa_start_key_creation() for the intended use
+ * of this function.
+ *
+ * \param slot          Pointer to the slot with key material.
+ */
+static void psa_fail_key_creation( psa_key_slot_t *slot )
+{
+    if( slot == NULL )
+        return;
+    psa_wipe_key_slot( slot );
+}
+
+psa_status_t psa_import_key( const psa_key_attributes_t *attributes,
+                             psa_key_handle_t *handle,
+                             const uint8_t *data,
+                             size_t data_length )
+{
+    psa_status_t status;
+    psa_key_slot_t *slot = NULL;
+    status = psa_start_key_creation( attributes, handle, &slot );
+    if( status == PSA_SUCCESS )
+    {
+        status = psa_import_key_into_slot( slot, data, data_length );
+    }
+    if( status == PSA_SUCCESS )
+        status = psa_finish_key_creation( slot );
+    if( status != PSA_SUCCESS )
+    {
+        psa_fail_key_creation( slot );
+        *handle = 0;
+    }
+    return( status );
+}
+
 static psa_status_t psa_copy_key_material( const psa_key_slot_t *source,
-                                           psa_key_handle_t target )
+                                           psa_key_slot_t *target )
 {
     psa_status_t status;
     uint8_t *buffer = NULL;
@@ -1221,14 +1511,15 @@
     size_t length;
 
     buffer_size = PSA_KEY_EXPORT_MAX_SIZE( source->type,
-                                           psa_get_key_bits( source ) );
+                                           psa_get_key_slot_bits( source ) );
     buffer = mbedtls_calloc( 1, buffer_size );
     if( buffer == NULL && buffer_size != 0 )
         return( PSA_ERROR_INSUFFICIENT_MEMORY );
     status = psa_internal_export_key( source, buffer, buffer_size, &length, 0 );
     if( status != PSA_SUCCESS )
         goto exit;
-    status = psa_import_key( target, source->type, buffer, length );
+    target->type = source->type;
+    status = psa_import_key_into_slot( target, buffer, length );
 
 exit:
     if( buffer_size != 0 )
@@ -1237,7 +1528,7 @@
     return( status );
 }
 
-psa_status_t psa_copy_key(psa_key_handle_t source_handle,
+psa_status_t psa_copy_key_to_handle(psa_key_handle_t source_handle,
                           psa_key_handle_t target_handle,
                           const psa_key_policy_t *constraint)
 {
@@ -1263,7 +1554,7 @@
             return( status );
     }
 
-    status = psa_copy_key_material( source_slot, target_handle );
+    status = psa_copy_key_material( source_slot, target_slot );
     if( status != PSA_SUCCESS )
         return( status );
 
@@ -1271,6 +1562,42 @@
     return( PSA_SUCCESS );
 }
 
+psa_status_t psa_copy_key( psa_key_handle_t source_handle,
+                           const psa_key_attributes_t *specified_attributes,
+                           psa_key_handle_t *target_handle )
+{
+    psa_status_t status;
+    psa_key_slot_t *source_slot = NULL;
+    psa_key_slot_t *target_slot = NULL;
+    psa_key_attributes_t actual_attributes = *specified_attributes;
+
+    status = psa_get_key_from_slot( source_handle, &source_slot, 0, 0 );
+    if( status != PSA_SUCCESS )
+        goto exit;
+
+    status = psa_restrict_key_policy( &actual_attributes.policy,
+                                      &source_slot->policy );
+    if( status != PSA_SUCCESS )
+        goto exit;
+
+    status = psa_start_key_creation( &actual_attributes,
+                                     target_handle, &target_slot );
+    if( status != PSA_SUCCESS )
+        goto exit;
+
+    status = psa_copy_key_material( source_slot, target_slot );
+
+exit:
+    if( status == PSA_SUCCESS )
+        status = psa_finish_key_creation( target_slot );
+    if( status != PSA_SUCCESS )
+    {
+        psa_fail_key_creation( target_slot );
+        *target_handle = 0;
+    }
+    return( status );
+}
+
 
 
 /****************************************************************/
@@ -2015,7 +2342,7 @@
     status = psa_get_key_from_slot( handle, &slot, usage, alg );
     if( status != PSA_SUCCESS )
         goto exit;
-    key_bits = psa_get_key_bits( slot );
+    key_bits = psa_get_key_slot_bits( slot );
 
 #if defined(MBEDTLS_CMAC_C)
     if( full_length_alg == PSA_ALG_CMAC )
@@ -2926,7 +3253,7 @@
     status = psa_get_key_from_slot( handle, &slot, usage, alg);
     if( status != PSA_SUCCESS )
         goto exit;
-    key_bits = psa_get_key_bits( slot );
+    key_bits = psa_get_key_slot_bits( slot );
 
     cipher_info = mbedtls_cipher_info_from_psa( alg, slot->type, key_bits, NULL );
     if( cipher_info == NULL )
@@ -3240,17 +3567,7 @@
     if( status != PSA_SUCCESS )
         return( status );
 
-    if( ( policy->usage & ~( PSA_KEY_USAGE_EXPORT |
-                             PSA_KEY_USAGE_ENCRYPT |
-                             PSA_KEY_USAGE_DECRYPT |
-                             PSA_KEY_USAGE_SIGN |
-                             PSA_KEY_USAGE_VERIFY |
-                             PSA_KEY_USAGE_DERIVE ) ) != 0 )
-        return( PSA_ERROR_INVALID_ARGUMENT );
-
-    slot->policy = *policy;
-
-    return( PSA_SUCCESS );
+    return( psa_set_key_policy_internal( slot, policy ) );
 }
 
 psa_status_t psa_get_key_policy( psa_key_handle_t handle,
@@ -3277,7 +3594,7 @@
 /* Key Lifetime */
 /****************************************************************/
 
-psa_status_t psa_get_key_lifetime( psa_key_handle_t handle,
+psa_status_t psa_get_key_lifetime_from_handle( psa_key_handle_t handle,
                                    psa_key_lifetime_t *lifetime )
 {
     psa_key_slot_t *slot;
@@ -3346,7 +3663,7 @@
     if( status != PSA_SUCCESS )
         return( status );
 
-    key_bits = psa_get_key_bits( operation->slot );
+    key_bits = psa_get_key_slot_bits( operation->slot );
 
     operation->cipher_info =
         mbedtls_cipher_info_from_psa( alg, operation->slot->type, key_bits,
@@ -3996,7 +4313,61 @@
 }
 #endif /* MBEDTLS_DES_C */
 
-psa_status_t psa_generator_import_key( psa_key_handle_t handle,
+static psa_status_t psa_generator_import_key_internal(
+    psa_key_slot_t *slot,
+    size_t bits,
+    psa_crypto_generator_t *generator )
+{
+    uint8_t *data = NULL;
+    size_t bytes = PSA_BITS_TO_BYTES( bits );
+    psa_status_t status;
+
+    if( ! key_type_is_raw_bytes( slot->type ) )
+        return( PSA_ERROR_INVALID_ARGUMENT );
+    if( bits % 8 != 0 )
+        return( PSA_ERROR_INVALID_ARGUMENT );
+    data = mbedtls_calloc( 1, bytes );
+    if( data == NULL )
+        return( PSA_ERROR_INSUFFICIENT_MEMORY );
+
+    status = psa_generator_read( generator, data, bytes );
+    if( status != PSA_SUCCESS )
+        goto exit;
+#if defined(MBEDTLS_DES_C)
+    if( slot->type == PSA_KEY_TYPE_DES )
+        psa_des_set_key_parity( data, bytes );
+#endif /* MBEDTLS_DES_C */
+    status = psa_import_key_into_slot( slot, data, bytes );
+
+exit:
+    mbedtls_free( data );
+    return( status );
+}
+
+psa_status_t psa_generator_import_key( const psa_key_attributes_t *attributes,
+                                       psa_key_handle_t *handle,
+                                       psa_crypto_generator_t *generator )
+{
+    psa_status_t status;
+    psa_key_slot_t *slot = NULL;
+    status = psa_start_key_creation( attributes, handle, &slot );
+    if( status == PSA_SUCCESS )
+    {
+        status = psa_generator_import_key_internal( slot,
+                                                    attributes->bits,
+                                                    generator );
+    }
+    if( status == PSA_SUCCESS )
+        status = psa_finish_key_creation( slot );
+    if( status != PSA_SUCCESS )
+    {
+        psa_fail_key_creation( slot );
+        *handle = 0;
+    }
+    return( status );
+}
+
+psa_status_t psa_generator_import_key_to_handle( psa_key_handle_t handle,
                                        psa_key_type_t type,
                                        size_t bits,
                                        psa_crypto_generator_t *generator )
@@ -4020,7 +4391,7 @@
     if( type == PSA_KEY_TYPE_DES )
         psa_des_set_key_parity( data, bytes );
 #endif /* MBEDTLS_DES_C */
-    status = psa_import_key( handle, type, data, bytes );
+    status = psa_import_key_to_handle( handle, type, data, bytes );
 
 exit:
     mbedtls_free( data );
@@ -4749,24 +5120,46 @@
 }
 #endif /* MBEDTLS_PSA_INJECT_ENTROPY */
 
-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 )
+#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_GENPRIME)
+static psa_status_t psa_read_rsa_exponent( const uint8_t *domain_parameters,
+                                           size_t domain_parameters_size,
+                                           int *exponent )
 {
-    psa_key_slot_t *slot;
-    psa_status_t status;
+    size_t i;
+    uint32_t acc = 0;
 
-    if( extra == NULL && extra_size != 0 )
+    if( domain_parameters_size == 0 )
+    {
+        *exponent = 65537;
+        return( PSA_SUCCESS );
+    }
+
+    /* Mbed TLS encodes the public exponent as an int. For simplicity, only
+     * support values that fit in a 32-bit integer, which is larger than
+     * int on just about every platform anyway. */
+    if( domain_parameters_size > sizeof( acc ) )
+        return( PSA_ERROR_NOT_SUPPORTED );
+    for( i = 0; i < domain_parameters_size; i++ )
+        acc = ( acc << 8 ) | domain_parameters[i];
+    if( acc > INT_MAX )
+        return( PSA_ERROR_NOT_SUPPORTED );
+    *exponent = acc;
+    return( PSA_SUCCESS );
+}
+#endif /* MBEDTLS_RSA_C && MBEDTLS_GENPRIME */
+
+static psa_status_t psa_generate_key_internal(
+    psa_key_slot_t *slot, size_t bits,
+    const uint8_t *domain_parameters, size_t domain_parameters_size )
+{
+    psa_key_type_t type = slot->type;
+
+    if( domain_parameters == NULL && domain_parameters_size != 0 )
         return( PSA_ERROR_INVALID_ARGUMENT );
 
-    status = psa_get_empty_key_slot( handle, &slot );
-    if( status != PSA_SUCCESS )
-        return( status );
-
     if( key_type_is_raw_bytes( type ) )
     {
+        psa_status_t status;
         status = prepare_raw_data_slot( type, bits, &slot->data.raw );
         if( status != PSA_SUCCESS )
             return( status );
@@ -4790,26 +5183,19 @@
     {
         mbedtls_rsa_context *rsa;
         int ret;
-        int exponent = 65537;
+        int exponent;
+        psa_status_t status;
         if( bits > PSA_VENDOR_RSA_MAX_KEY_BITS )
             return( PSA_ERROR_NOT_SUPPORTED );
         /* Accept only byte-aligned keys, for the same reasons as
          * in psa_import_rsa_key(). */
         if( bits % 8 != 0 )
             return( PSA_ERROR_NOT_SUPPORTED );
-        if( extra != NULL )
-        {
-            const psa_generate_key_extra_rsa *p = extra;
-            if( extra_size != sizeof( *p ) )
-                return( PSA_ERROR_INVALID_ARGUMENT );
-#if INT_MAX < 0xffffffff
-            /* Check that the uint32_t value passed by the caller fits
-             * in the range supported by this implementation. */
-            if( p->e > INT_MAX )
-                return( PSA_ERROR_NOT_SUPPORTED );
-#endif
-            exponent = p->e;
-        }
+        status = psa_read_rsa_exponent( domain_parameters,
+                                        domain_parameters_size,
+                                        &exponent );
+        if( status != PSA_SUCCESS )
+            return( status );
         rsa = mbedtls_calloc( 1, sizeof( *rsa ) );
         if( rsa == NULL )
             return( PSA_ERROR_INSUFFICIENT_MEMORY );
@@ -4839,7 +5225,7 @@
             mbedtls_ecp_curve_info_from_grp_id( grp_id );
         mbedtls_ecp_keypair *ecp;
         int ret;
-        if( extra != NULL )
+        if( domain_parameters_size != 0 )
             return( PSA_ERROR_NOT_SUPPORTED );
         if( grp_id == MBEDTLS_ECP_DP_NONE || curve_info == NULL )
             return( PSA_ERROR_NOT_SUPPORTED );
@@ -4865,7 +5251,32 @@
 
         return( PSA_ERROR_NOT_SUPPORTED );
 
+    return( PSA_SUCCESS );
+}
+
+psa_status_t psa_generate_key_to_handle( psa_key_handle_t handle,
+                               psa_key_type_t type,
+                               size_t bits,
+                               const void *extra,
+                               size_t extra_size )
+{
+    psa_key_slot_t *slot;
+    psa_status_t status;
+
+#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_GENPRIME)
+    /* The old public exponent encoding is no longer supported. */
+    if( extra_size != 0 )
+        return( PSA_ERROR_NOT_SUPPORTED );
+#endif
+
+    status = psa_get_empty_key_slot( handle, &slot );
+    if( status != PSA_SUCCESS )
+        return( status );
+
     slot->type = type;
+    status = psa_generate_key_internal( slot, bits, extra, extra_size );
+    if( status != PSA_SUCCESS )
+        slot->type = 0;
 
 #if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C)
     if( slot->lifetime == PSA_KEY_LIFETIME_PERSISTENT )
@@ -4877,6 +5288,29 @@
     return( status );
 }
 
+psa_status_t psa_generate_key( const psa_key_attributes_t *attributes,
+                               psa_key_handle_t *handle )
+{
+    psa_status_t status;
+    psa_key_slot_t *slot = NULL;
+    status = psa_start_key_creation( attributes, handle, &slot );
+    if( status == PSA_SUCCESS )
+    {
+        status = psa_generate_key_internal(
+            slot, attributes->bits,
+            attributes->domain_parameters, attributes->domain_parameters_size );
+    }
+    if( status == PSA_SUCCESS )
+        status = psa_finish_key_creation( slot );
+    if( status != PSA_SUCCESS )
+    {
+        psa_fail_key_creation( slot );
+        *handle = 0;
+    }
+    return( status );
+}
+
+
 
 /****************************************************************/
 /* Module setup */
diff --git a/library/psa_crypto_slot_management.c b/library/psa_crypto_slot_management.c
index 33c03a7..8ee5615 100644
--- a/library/psa_crypto_slot_management.c
+++ b/library/psa_crypto_slot_management.c
@@ -192,7 +192,6 @@
         return( 0 );
     return( 1 );
 }
-#endif /* defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) */
 
 /** Declare a slot as persistent and load it from storage.
  *
@@ -215,13 +214,9 @@
 static psa_status_t psa_internal_make_key_persistent( psa_key_handle_t handle,
                                                       psa_key_file_id_t id )
 {
-#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C)
     psa_key_slot_t *slot;
     psa_status_t status;
 
-    if( ! psa_is_key_id_valid( id ) )
-        return( PSA_ERROR_INVALID_ARGUMENT );
-
     status = psa_get_key_slot( handle, &slot );
     if( status != PSA_SUCCESS )
         return( status );
@@ -231,9 +226,22 @@
     status = psa_load_persistent_key_into_slot( slot );
 
     return( status );
+}
+#endif /* defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) */
+
+psa_status_t psa_validate_persistent_key_parameters(
+    psa_key_lifetime_t lifetime,
+    psa_key_file_id_t id )
+{
+    if( lifetime != PSA_KEY_LIFETIME_PERSISTENT )
+        return( PSA_ERROR_INVALID_ARGUMENT );
+
+#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C)
+    if( ! psa_is_key_id_valid( id ) )
+        return( PSA_ERROR_INVALID_ARGUMENT );
+    return( PSA_SUCCESS );
 
 #else /* MBEDTLS_PSA_CRYPTO_STORAGE_C */
-    (void) handle;
     (void) id;
     return( PSA_ERROR_NOT_SUPPORTED );
 #endif /* !MBEDTLS_PSA_CRYPTO_STORAGE_C */
@@ -248,9 +256,11 @@
 
     *handle = 0;
 
-    if( lifetime != PSA_KEY_LIFETIME_PERSISTENT )
-        return( PSA_ERROR_INVALID_ARGUMENT );
+    status = psa_validate_persistent_key_parameters( lifetime, id );
+    if( status != PSA_SUCCESS )
+        return( status );
 
+#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C)
     status = psa_internal_allocate_key_slot( handle );
     if( status != PSA_SUCCESS )
         return( status );
@@ -262,6 +272,10 @@
         *handle = 0;
     }
     return( status );
+#else /* defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) */
+    (void) wanted_load_status;
+    return( PSA_ERROR_NOT_SUPPORTED );
+#endif /* !defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) */
 }
 
 psa_status_t psa_open_key( psa_key_lifetime_t lifetime,
diff --git a/library/psa_crypto_slot_management.h b/library/psa_crypto_slot_management.h
index 6746bad..914e2d5 100644
--- a/library/psa_crypto_slot_management.h
+++ b/library/psa_crypto_slot_management.h
@@ -55,4 +55,26 @@
  * This does not affect persistent storage. */
 void psa_wipe_all_key_slots( void );
 
+/** Test whether the given parameters are acceptable for a persistent key.
+ *
+ * This function does not access the storage in any way. It only tests
+ * whether the parameters are meaningful and permitted by general policy.
+ * It does not test whether the a file by the given id exists or could be
+ * created.
+ *
+ * \param lifetime      The lifetime to test.
+ * \param id            The key id to test.
+ *
+ * \retval PSA_SUCCESS
+ *         The given parameters are valid.
+ * \retval PSA_ERROR_INVALID_ARGUMENT
+ *         \p lifetime is volatile or is invalid.
+ * \retval PSA_ERROR_INVALID_ARGUMENT
+ *         \p id is invalid.
+ */
+psa_status_t psa_validate_persistent_key_parameters(
+    psa_key_lifetime_t lifetime,
+    psa_key_file_id_t id );
+
+
 #endif /* PSA_CRYPTO_SLOT_MANAGEMENT_H */
diff --git a/library/psa_crypto_storage.c b/library/psa_crypto_storage.c
index 840f418..1e3ce08 100644
--- a/library/psa_crypto_storage.c
+++ b/library/psa_crypto_storage.c
@@ -309,16 +309,22 @@
         *key_data_length > PSA_CRYPTO_MAX_STORAGE_SIZE )
         return( PSA_ERROR_STORAGE_FAILURE );
 
-    *key_data = mbedtls_calloc( 1, *key_data_length );
-    if( *key_data == NULL )
-        return( PSA_ERROR_INSUFFICIENT_MEMORY );
+    if( *key_data_length == 0 )
+    {
+        *key_data = NULL;
+    }
+    else
+    {
+        *key_data = mbedtls_calloc( 1, *key_data_length );
+        if( *key_data == NULL )
+            return( PSA_ERROR_INSUFFICIENT_MEMORY );
+        memcpy( *key_data, storage_format->key_data, *key_data_length );
+    }
 
     GET_UINT32_LE(*type, storage_format->type, 0);
     GET_UINT32_LE(policy->usage, storage_format->policy, 0);
     GET_UINT32_LE(policy->alg, storage_format->policy, sizeof( uint32_t ));
 
-    memcpy( *key_data, storage_format->key_data, *key_data_length );
-
     return( PSA_SUCCESS );
 }
 
diff --git a/library/ssl_cli.c b/library/ssl_cli.c
index 4e5b3a6..65bc64c 100644
--- a/library/ssl_cli.c
+++ b/library/ssl_cli.c
@@ -3148,7 +3148,7 @@
             return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED );
 
         /* Generate ECDH private key. */
-        status = psa_generate_key( handshake->ecdh_psa_privkey,
+        status = psa_generate_key_to_handle( handshake->ecdh_psa_privkey,
                           PSA_KEY_TYPE_ECC_KEYPAIR( handshake->ecdh_psa_curve ),
                           MBEDTLS_PSA_ECC_KEY_BITS_OF_CURVE( handshake->ecdh_psa_curve ),
                           NULL, 0 );
diff --git a/library/ssl_tls.c b/library/ssl_tls.c
index 660d548..2681442 100644
--- a/library/ssl_tls.c
+++ b/library/ssl_tls.c
@@ -544,7 +544,7 @@
     if( status != PSA_SUCCESS )
         return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED );
 
-    status = psa_import_key( master_slot, PSA_KEY_TYPE_DERIVE, secret, slen );
+    status = psa_import_key_to_handle( master_slot, PSA_KEY_TYPE_DERIVE, secret, slen );
     if( status != PSA_SUCCESS )
         return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED );
 
diff --git a/programs/psa/crypto_examples.c b/programs/psa/crypto_examples.c
index 2f7c445..1a81f45 100644
--- a/programs/psa/crypto_examples.c
+++ b/programs/psa/crypto_examples.c
@@ -39,20 +39,6 @@
 }
 #else
 
-static psa_status_t set_key_policy( psa_key_handle_t key_handle,
-                                    psa_key_usage_t key_usage,
-                                    psa_algorithm_t alg )
-{
-    psa_status_t status;
-    psa_key_policy_t policy = PSA_KEY_POLICY_INIT;
-
-    psa_key_policy_set_usage( &policy, key_usage, alg );
-    status = psa_set_key_policy( key_handle, &policy );
-    ASSERT_STATUS( status, PSA_SUCCESS );
-exit:
-    return( status );
-}
-
 static psa_status_t cipher_operation( psa_cipher_operation_t *operation,
                                       const uint8_t * input,
                                       size_t input_size,
@@ -161,6 +147,7 @@
     const psa_algorithm_t alg = PSA_ALG_CBC_NO_PADDING;
 
     psa_status_t status;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
     psa_key_handle_t key_handle = 0;
     size_t output_len = 0;
     uint8_t iv[block_size];
@@ -171,16 +158,13 @@
     status = psa_generate_random( input, sizeof( input ) );
     ASSERT_STATUS( status, PSA_SUCCESS );
 
-    status = psa_allocate_key( &key_handle );
-    ASSERT_STATUS( status, PSA_SUCCESS );
+    psa_set_key_usage_flags( &attributes,
+                             PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT );
+    psa_set_key_algorithm( &attributes, alg );
+    psa_set_key_type( &attributes, PSA_KEY_TYPE_AES );
+    psa_set_key_bits( &attributes, key_bits );
 
-    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_handle, PSA_KEY_TYPE_AES, key_bits,
-                               NULL, 0 );
+    status = psa_generate_key( &attributes, &key_handle );
     ASSERT_STATUS( status, PSA_SUCCESS );
 
     status = cipher_encrypt( key_handle, alg, iv, sizeof( iv ),
@@ -213,6 +197,7 @@
     const psa_algorithm_t alg = PSA_ALG_CBC_PKCS7;
 
     psa_status_t status;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
     psa_key_handle_t key_handle = 0;
     size_t output_len = 0;
     uint8_t iv[block_size], input[input_size],
@@ -224,13 +209,13 @@
     status = psa_allocate_key( &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 );
+    psa_set_key_usage_flags( &attributes,
+                             PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT );
+    psa_set_key_algorithm( &attributes, alg );
+    psa_set_key_type( &attributes, PSA_KEY_TYPE_AES );
+    psa_set_key_bits( &attributes, key_bits );
 
-    status = psa_generate_key( key_handle, PSA_KEY_TYPE_AES, key_bits,
-                               NULL, 0 );
+    status = psa_generate_key( &attributes, &key_handle );
     ASSERT_STATUS( status, PSA_SUCCESS );
 
     status = cipher_encrypt( key_handle, alg, iv, sizeof( iv ),
@@ -262,6 +247,7 @@
     const psa_algorithm_t alg = PSA_ALG_CTR;
 
     psa_status_t status;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
     psa_key_handle_t key_handle = 0;
     size_t output_len = 0;
     uint8_t iv[block_size], input[input_size], encrypt[input_size],
@@ -270,15 +256,13 @@
     status = psa_generate_random( input, sizeof( input ) );
     ASSERT_STATUS( status, PSA_SUCCESS );
 
-    status = psa_allocate_key( &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 );
+    psa_set_key_usage_flags( &attributes,
+                             PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT );
+    psa_set_key_algorithm( &attributes, alg );
+    psa_set_key_type( &attributes, PSA_KEY_TYPE_AES );
+    psa_set_key_bits( &attributes, key_bits );
 
-    status = psa_generate_key( key_handle, PSA_KEY_TYPE_AES, key_bits,
-                               NULL, 0 );
+    status = psa_generate_key( &attributes, &key_handle );
     ASSERT_STATUS( status, PSA_SUCCESS );
 
     status = cipher_encrypt( key_handle, alg, iv, sizeof( iv ),
diff --git a/programs/psa/key_ladder_demo.c b/programs/psa/key_ladder_demo.c
index 23c2347..6d4c707 100644
--- a/programs/psa/key_ladder_demo.c
+++ b/programs/psa/key_ladder_demo.c
@@ -200,18 +200,15 @@
 {
     psa_status_t status = PSA_SUCCESS;
     psa_key_handle_t key_handle = 0;
-    psa_key_policy_t policy = PSA_KEY_POLICY_INIT;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
 
-    PSA_CHECK( psa_allocate_key( &key_handle ) );
-    psa_key_policy_set_usage( &policy,
-                              PSA_KEY_USAGE_DERIVE | PSA_KEY_USAGE_EXPORT,
-                              KDF_ALG );
-    PSA_CHECK( psa_set_key_policy( key_handle, &policy ) );
+    psa_set_key_usage_flags( &attributes,
+                             PSA_KEY_USAGE_DERIVE | PSA_KEY_USAGE_EXPORT );
+    psa_set_key_algorithm( &attributes, KDF_ALG );
+    psa_set_key_type( &attributes, PSA_KEY_TYPE_DERIVE );
+    psa_set_key_bits( &attributes, PSA_BYTES_TO_BITS( KEY_SIZE_BYTES ) );
 
-    PSA_CHECK( psa_generate_key( key_handle,
-                                 PSA_KEY_TYPE_DERIVE,
-                                 PSA_BYTES_TO_BITS( KEY_SIZE_BYTES ),
-                                 NULL, 0 ) );
+    PSA_CHECK( psa_generate_key( &attributes, &key_handle ) );
 
     PSA_CHECK( save_key( key_handle, key_file_name ) );
 
@@ -231,7 +228,7 @@
                                           psa_key_handle_t *master_key_handle )
 {
     psa_status_t status = PSA_SUCCESS;
-    psa_key_policy_t policy = PSA_KEY_POLICY_INIT;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
     uint8_t key_data[KEY_SIZE_BYTES];
     size_t key_size;
     FILE *key_file = NULL;
@@ -252,11 +249,10 @@
     SYS_CHECK( fclose( key_file ) == 0 );
     key_file = NULL;
 
-    PSA_CHECK( psa_allocate_key( master_key_handle ) );
-    psa_key_policy_set_usage( &policy, usage, alg );
-    PSA_CHECK( psa_set_key_policy( *master_key_handle, &policy ) );
-    PSA_CHECK( psa_import_key( *master_key_handle,
-                               PSA_KEY_TYPE_DERIVE,
+    psa_set_key_usage_flags( &attributes, usage );
+    psa_set_key_algorithm( &attributes, alg );
+    psa_set_key_type( &attributes, PSA_KEY_TYPE_DERIVE );
+    PSA_CHECK( psa_import_key( &attributes, master_key_handle,
                                key_data, key_size ) );
 exit:
     if( key_file != NULL )
@@ -282,12 +278,15 @@
                                        psa_key_handle_t *key_handle )
 {
     psa_status_t status = PSA_SUCCESS;
-    psa_key_policy_t policy = PSA_KEY_POLICY_INIT;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
     psa_crypto_generator_t generator = PSA_CRYPTO_GENERATOR_INIT;
     size_t i;
-    psa_key_policy_set_usage( &policy,
-                              PSA_KEY_USAGE_DERIVE | PSA_KEY_USAGE_EXPORT,
-                              KDF_ALG );
+
+    psa_set_key_usage_flags( &attributes,
+                             PSA_KEY_USAGE_DERIVE | PSA_KEY_USAGE_EXPORT );
+    psa_set_key_algorithm( &attributes, KDF_ALG );
+    psa_set_key_type( &attributes, PSA_KEY_TYPE_DERIVE );
+    psa_set_key_bits( &attributes, PSA_BYTES_TO_BITS( KEY_SIZE_BYTES ) );
 
     /* For each label in turn, ... */
     for( i = 0; i < ladder_depth; i++ )
@@ -305,15 +304,10 @@
          * since it is no longer needed. */
         PSA_CHECK( psa_close_key( *key_handle ) );
         *key_handle = 0;
-        PSA_CHECK( psa_allocate_key( 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(
-                       *key_handle,
-                       PSA_KEY_TYPE_DERIVE,
-                       PSA_BYTES_TO_BITS( KEY_SIZE_BYTES ),
-                       &generator ) );
+        PSA_CHECK( psa_generator_import_key( &attributes, key_handle,
+                                             &generator ) );
         PSA_CHECK( psa_generator_abort( &generator ) );
     }
 
@@ -333,13 +327,14 @@
                                          psa_key_handle_t *wrapping_key_handle )
 {
     psa_status_t status = PSA_SUCCESS;
-    psa_key_policy_t policy = PSA_KEY_POLICY_INIT;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
     psa_crypto_generator_t generator = PSA_CRYPTO_GENERATOR_INIT;
 
     *wrapping_key_handle = 0;
-    PSA_CHECK( psa_allocate_key( wrapping_key_handle ) );
-    psa_key_policy_set_usage( &policy, usage, WRAPPING_ALG );
-    PSA_CHECK( psa_set_key_policy( *wrapping_key_handle, &policy ) );
+    psa_set_key_usage_flags( &attributes, usage );
+    psa_set_key_algorithm( &attributes, WRAPPING_ALG );
+    psa_set_key_type( &attributes, PSA_KEY_TYPE_AES );
+    psa_set_key_bits( &attributes, WRAPPING_KEY_BITS );
 
     PSA_CHECK( psa_key_derivation(
                    &generator,
@@ -348,11 +343,8 @@
                    WRAPPING_KEY_SALT, WRAPPING_KEY_SALT_LENGTH,
                    NULL, 0,
                    PSA_BITS_TO_BYTES( WRAPPING_KEY_BITS ) ) );
-    PSA_CHECK( psa_generator_import_key(
-                   *wrapping_key_handle,
-                   PSA_KEY_TYPE_AES,
-                   WRAPPING_KEY_BITS,
-                   &generator ) );
+    PSA_CHECK( psa_generator_import_key( &attributes, wrapping_key_handle,
+                                         &generator ) );
 
 exit:
     psa_generator_abort( &generator );
diff --git a/tests/suites/test_suite_pk.function b/tests/suites/test_suite_pk.function
index d85d9ed..7415b63 100644
--- a/tests/suites/test_suite_pk.function
+++ b/tests/suites/test_suite_pk.function
@@ -97,7 +97,7 @@
         return( PK_PSA_INVALID_SLOT );
 
     /* generate key */
-    if( PSA_SUCCESS != psa_generate_key( key, type, bits, NULL, 0 ) )
+    if( PSA_SUCCESS != psa_generate_key_to_handle( key, type, bits, NULL, 0 ) )
         return( PK_PSA_INVALID_SLOT );
 
     return( key );
diff --git a/tests/suites/test_suite_psa_crypto.data b/tests/suites/test_suite_psa_crypto.data
index 9629d43..e29cbf7 100644
--- a/tests/suites/test_suite_psa_crypto.data
+++ b/tests/suites/test_suite_psa_crypto.data
@@ -1,6 +1,9 @@
 PSA compile-time sanity checks
 static_checks:
 
+PSA key attributes structure
+attributes_set_get:0x6963:PSA_KEY_LIFETIME_PERSISTENT:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_CCM:PSA_KEY_TYPE_AES:128
+
 PSA import/export raw: 0 bytes
 import_export:"":PSA_KEY_TYPE_RAW_DATA:0:PSA_KEY_USAGE_EXPORT:0:0:PSA_SUCCESS:1
 
@@ -25,52 +28,14 @@
 depends_on:MBEDTLS_AES_C
 import_export:"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef":PSA_KEY_TYPE_AES:PSA_ALG_CTR:PSA_KEY_USAGE_EXPORT:256:0:PSA_SUCCESS:1
 
-PSA import to non empty key slot
-depends_on:MBEDTLS_AES_C
-import_key_nonempty_slot
+PSA invalid handle (0)
+invalid_handle:0
 
-PSA export invalid handle (0)
-export_invalid_handle:0:PSA_ERROR_INVALID_HANDLE
+PSA invalid handle (smallest plausible handle)
+invalid_handle:1
 
-PSA export invalid handle (smallest plausible handle)
-export_invalid_handle:1:PSA_ERROR_INVALID_HANDLE
-
-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
-
-PSA setup cipher where there was some activity on key but no key material creation
-cipher_with_no_key_activity
-
-PSA export a slot after a failed import of a AES key
-depends_on:MBEDTLS_AES_C
-export_after_import_failure:"0123456789abcdef":PSA_KEY_TYPE_AES:PSA_ERROR_INVALID_ARGUMENT
-
-PSA export a slot after a failed import of a RSA key
-depends_on:MBEDTLS_RSA_C:MBEDTLS_PK_PARSE_C
-export_after_import_failure:"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_KEY_TYPE_RSA_KEYPAIR:PSA_ERROR_INVALID_ARGUMENT
-
-PSA export a slot after a failed import of an EC keypair
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED
-export_after_import_failure:"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff":PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_SECP256R1):PSA_ERROR_INVALID_ARGUMENT
-
-PSA setup cipher after a failed import of a AES key
-depends_on:MBEDTLS_AES_C
-cipher_after_import_failure:"0123456789abcdef":PSA_KEY_TYPE_AES:PSA_ERROR_INVALID_ARGUMENT
-
-PSA export RSA public key from a slot where there was an import followed by destroy.
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C
-export_after_destroy_key:"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_KEY_TYPE_RSA_PUBLIC_KEY
-
-PSA export AES key from a slot where there was an import followed by destroy.
-depends_on:MBEDTLS_AES_C
-export_after_destroy_key:"0123456789abcdef0123456789abcdef":PSA_KEY_TYPE_AES
-
-PSA export EC key from a slot where there was an import followed by destroy.
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP384R1_ENABLED
-export_after_destroy_key:"3f5d8d9be280b5696cc5cc9f94cf8af7e6b61dd6592b2ab2b3a4c607450417ec327dcdcaed7c10053d719a0574f0a76a":PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_SECP384R1)
+PSA invalid handle (largest plausible handle)
+invalid_handle:-1
 
 PSA import AES: bad key size
 depends_on:MBEDTLS_AES_C
@@ -310,10 +275,6 @@
 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:"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":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
@@ -325,8 +286,8 @@
 PSA key policy set and get
 key_policy:PSA_KEY_USAGE_ENCRYPT:PSA_ALG_CBC_NO_PADDING
 
-Key policy initializers zero properly
-key_policy_init:
+Key attributes initializers zero properly
+key_attributes_init:
 
 PSA key policy: MAC, sign | verify
 depends_on:MBEDTLS_MD_C:MBEDTLS_SHA256_C
@@ -517,115 +478,79 @@
 raw_agreement_key_policy:PSA_KEY_USAGE_DERIVE:PSA_ALG_ECDH:PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_SECP256R1):"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_HKDF(PSA_ALG_SHA_256))
 
 Copy key: raw, 0 bytes
-copy_key_policy:0:0:PSA_KEY_TYPE_RAW_DATA:"":0:0:-1:-1:0:0
+copy_key:0:0:PSA_KEY_TYPE_RAW_DATA:"":1:-1:-1:PSA_SUCCESS:0:0
+
+Copy key: AES, copy attributes
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
+copy_key:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_EXPORT:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"404142434445464748494a4b4c4d4e4f":1:-1:-1:PSA_SUCCESS:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_EXPORT:PSA_ALG_CTR
 
 Copy key: AES, same usage flags
 depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
-copy_key_policy:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_EXPORT:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"404142434445464748494a4b4c4d4e4f":PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_EXPORT:PSA_ALG_CTR:-1:-1:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_EXPORT:PSA_ALG_CTR
+copy_key:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_EXPORT:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"404142434445464748494a4b4c4d4e4f":0:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_EXPORT:PSA_ALG_CTR:PSA_SUCCESS:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_EXPORT:PSA_ALG_CTR
 
 Copy key: AES, fewer usage flags
 depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
-copy_key_policy:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_EXPORT:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"404142434445464748494a4b4c4d4e4f":PSA_KEY_USAGE_ENCRYPT:PSA_ALG_CTR:-1:-1:PSA_KEY_USAGE_ENCRYPT:PSA_ALG_CTR
+copy_key:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_EXPORT:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"404142434445464748494a4b4c4d4e4f":0:PSA_KEY_USAGE_ENCRYPT:PSA_ALG_CTR:PSA_SUCCESS:PSA_KEY_USAGE_ENCRYPT:PSA_ALG_CTR
 
 Copy key: AES, 1 more usage flag
 depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
-copy_key_policy:PSA_KEY_USAGE_ENCRYPT:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"404142434445464748494a4b4c4d4e4f":PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_CTR:-1:-1:PSA_KEY_USAGE_ENCRYPT:PSA_ALG_CTR
+copy_key:PSA_KEY_USAGE_ENCRYPT:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"404142434445464748494a4b4c4d4e4f":0:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_CTR:PSA_SUCCESS:PSA_KEY_USAGE_ENCRYPT:PSA_ALG_CTR
 
 Copy key: AES, 2 more usage flags
 depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
-copy_key_policy:PSA_KEY_USAGE_ENCRYPT:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"404142434445464748494a4b4c4d4e4f":PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_EXPORT:PSA_ALG_CTR:-1:-1:PSA_KEY_USAGE_ENCRYPT:PSA_ALG_CTR
+copy_key:PSA_KEY_USAGE_ENCRYPT:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"404142434445464748494a4b4c4d4e4f":0:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_EXPORT:PSA_ALG_CTR:PSA_SUCCESS:PSA_KEY_USAGE_ENCRYPT:PSA_ALG_CTR
 
 Copy key: AES, intersect usage flags
 depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
-copy_key_policy:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_EXPORT:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"404142434445464748494a4b4c4d4e4f":PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_CTR:-1:-1:PSA_KEY_USAGE_ENCRYPT:PSA_ALG_CTR
-
-Copy key: AES, source=target, constraint with same usage flags
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
-copy_key_policy:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_EXPORT:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"404142434445464748494a4b4c4d4e4f":PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_EXPORT:PSA_ALG_CTR:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_EXPORT:PSA_ALG_CTR:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_EXPORT:PSA_ALG_CTR
-
-Copy key: AES, source=target, constraint with fewer usage flags
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
-copy_key_policy:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_EXPORT:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"404142434445464748494a4b4c4d4e4f":PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_EXPORT:PSA_ALG_CTR:PSA_KEY_USAGE_ENCRYPT:PSA_ALG_CTR:PSA_KEY_USAGE_ENCRYPT:PSA_ALG_CTR
-
-Copy key: AES, source=target, constraint with 1 more usage flag
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
-copy_key_policy:PSA_KEY_USAGE_ENCRYPT:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"404142434445464748494a4b4c4d4e4f":PSA_KEY_USAGE_ENCRYPT:PSA_ALG_CTR:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_CTR:PSA_KEY_USAGE_ENCRYPT:PSA_ALG_CTR
-
-Copy key: AES, source=target, constraint with 2 more usage flags
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
-copy_key_policy:PSA_KEY_USAGE_ENCRYPT:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"404142434445464748494a4b4c4d4e4f":PSA_KEY_USAGE_ENCRYPT:PSA_ALG_CTR:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_EXPORT:PSA_ALG_CTR:PSA_KEY_USAGE_ENCRYPT:PSA_ALG_CTR
-
-Copy key: AES, source=target, constraint with different usage flags
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
-copy_key_policy:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_EXPORT:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"404142434445464748494a4b4c4d4e4f":PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_EXPORT:PSA_ALG_CTR:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_CTR:PSA_KEY_USAGE_ENCRYPT:PSA_ALG_CTR
-
-Copy key: AES, permissive target, restrictive constraint
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
-copy_key_policy:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_EXPORT:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"404142434445464748494a4b4c4d4e4f":PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_EXPORT:PSA_ALG_CTR:PSA_KEY_USAGE_ENCRYPT:PSA_ALG_CTR:PSA_KEY_USAGE_ENCRYPT:PSA_ALG_CTR
+copy_key:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_EXPORT:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"404142434445464748494a4b4c4d4e4f":0:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_CTR:PSA_SUCCESS:PSA_KEY_USAGE_ENCRYPT:PSA_ALG_CTR
 
 Copy key: RSA key pair, same usage flags
 depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_SHA256_C
-copy_key_policy:PSA_KEY_USAGE_SIGN | PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):PSA_KEY_TYPE_RSA_KEYPAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_KEY_USAGE_SIGN | PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):-1:-1:PSA_KEY_USAGE_SIGN | PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256)
+copy_key:PSA_KEY_USAGE_SIGN | PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):PSA_KEY_TYPE_RSA_KEYPAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":0:PSA_KEY_USAGE_SIGN | PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):PSA_SUCCESS:PSA_KEY_USAGE_SIGN | PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256)
 
 Copy key: RSA key pair, fewer usage flags
 depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_SHA256_C
-copy_key_policy:PSA_KEY_USAGE_SIGN | PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):PSA_KEY_TYPE_RSA_KEYPAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_KEY_USAGE_SIGN:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):-1:-1:PSA_KEY_USAGE_SIGN:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256)
+copy_key:PSA_KEY_USAGE_SIGN | PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):PSA_KEY_TYPE_RSA_KEYPAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":0:PSA_KEY_USAGE_SIGN:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):PSA_SUCCESS:PSA_KEY_USAGE_SIGN:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256)
 
 Copy key: RSA key pair, more usage flags
 depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_SHA256_C
-copy_key_policy:PSA_KEY_USAGE_SIGN:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):PSA_KEY_TYPE_RSA_KEYPAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_KEY_USAGE_SIGN | PSA_KEY_USAGE_VERIFY:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):-1:-1:PSA_KEY_USAGE_SIGN:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256)
+copy_key:PSA_KEY_USAGE_SIGN:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):PSA_KEY_TYPE_RSA_KEYPAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":0:PSA_KEY_USAGE_SIGN | PSA_KEY_USAGE_VERIFY:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):PSA_SUCCESS:PSA_KEY_USAGE_SIGN:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256)
 
 Copy key: RSA key pair, intersect usage flags
 depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_SHA256_C
-copy_key_policy:PSA_KEY_USAGE_SIGN | PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):PSA_KEY_TYPE_RSA_KEYPAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_KEY_USAGE_SIGN | PSA_KEY_USAGE_VERIFY:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):-1:-1:PSA_KEY_USAGE_SIGN:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256)
+copy_key:PSA_KEY_USAGE_SIGN | PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):PSA_KEY_TYPE_RSA_KEYPAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":0:PSA_KEY_USAGE_SIGN | PSA_KEY_USAGE_VERIFY:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):PSA_SUCCESS:PSA_KEY_USAGE_SIGN:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256)
 
 Copy key: RSA key pair, wildcard algorithm in source
 depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_SHA256_C
-copy_key_policy:PSA_KEY_USAGE_SIGN | PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH):PSA_KEY_TYPE_RSA_KEYPAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_KEY_USAGE_SIGN | PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):-1:-1:PSA_KEY_USAGE_SIGN | PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256)
+copy_key:PSA_KEY_USAGE_SIGN | PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH):PSA_KEY_TYPE_RSA_KEYPAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":0:PSA_KEY_USAGE_SIGN | PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):PSA_SUCCESS:PSA_KEY_USAGE_SIGN | PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256)
 
 Copy key: RSA key pair, wildcard algorithm in target
 depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_SHA256_C
-copy_key_policy:PSA_KEY_USAGE_SIGN | PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):PSA_KEY_TYPE_RSA_KEYPAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_KEY_USAGE_SIGN | PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH):-1:-1:PSA_KEY_USAGE_SIGN | PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256)
+copy_key:PSA_KEY_USAGE_SIGN | PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):PSA_KEY_TYPE_RSA_KEYPAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":0:PSA_KEY_USAGE_SIGN | PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH):PSA_SUCCESS:PSA_KEY_USAGE_SIGN | PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256)
 
 Copy key: RSA key pair, wildcard algorithm in source and target
 depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_SHA256_C
-copy_key_policy:PSA_KEY_USAGE_SIGN | PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH):PSA_KEY_TYPE_RSA_KEYPAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_KEY_USAGE_SIGN | PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH):-1:-1:PSA_KEY_USAGE_SIGN | PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH)
-
-Copy key: RSA key pair, wildcard in constraint
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_SHA256_C
-copy_key_policy:PSA_KEY_USAGE_SIGN | PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH):PSA_KEY_TYPE_RSA_KEYPAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_KEY_USAGE_SIGN | PSA_KEY_USAGE_VERIFY | PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH):PSA_KEY_USAGE_SIGN:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH):PSA_KEY_USAGE_SIGN:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH)
-
-Copy key: RSA key pair, wildcard, restrictive constraint
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_SHA256_C
-copy_key_policy:PSA_KEY_USAGE_SIGN | PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH):PSA_KEY_TYPE_RSA_KEYPAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_KEY_USAGE_SIGN | PSA_KEY_USAGE_VERIFY | PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH):PSA_KEY_USAGE_SIGN:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):PSA_KEY_USAGE_SIGN:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256)
+copy_key:PSA_KEY_USAGE_SIGN | PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH):PSA_KEY_TYPE_RSA_KEYPAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":0:PSA_KEY_USAGE_SIGN | PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH):PSA_SUCCESS:PSA_KEY_USAGE_SIGN | PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH)
 
 Copy fail: AES, incompatible target policy
 depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR:MBEDTLS_CIPHER_MODE_CBC
-copy_fail:PSA_KEY_USAGE_EXPORT:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"404142434445464748494a4b4c4d4e4f":PSA_KEY_USAGE_EXPORT:PSA_ALG_CBC_NO_PADDING:-1:-1:PSA_ERROR_INVALID_ARGUMENT
+copy_key:PSA_KEY_USAGE_EXPORT:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"404142434445464748494a4b4c4d4e4f":0:PSA_KEY_USAGE_EXPORT:PSA_ALG_CBC_NO_PADDING:PSA_ERROR_INVALID_ARGUMENT:-1:-1
 
 Copy fail: RSA, incompatible target policy (source wildcard)
 depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_RSA_C:MBEDTLS_SHA256_C
-copy_fail:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH):PSA_KEY_TYPE_RSA_KEYPAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):-1:-1:PSA_ERROR_INVALID_ARGUMENT
+copy_key:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH):PSA_KEY_TYPE_RSA_KEYPAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":0:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):PSA_ERROR_INVALID_ARGUMENT:-1:-1
 
 Copy fail: RSA, incompatible target policy (target wildcard)
 depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_RSA_C:MBEDTLS_SHA256_C
-copy_fail:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):PSA_KEY_TYPE_RSA_KEYPAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PSS(PSA_ALG_ANY_HASH):-1:-1:PSA_ERROR_INVALID_ARGUMENT
+copy_key:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):PSA_KEY_TYPE_RSA_KEYPAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":0:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PSS(PSA_ALG_ANY_HASH):PSA_ERROR_INVALID_ARGUMENT:-1:-1
 
 Copy fail: RSA, incompatible target policy (source and target wildcard)
 depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_RSA_C:MBEDTLS_SHA256_C
-copy_fail:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH):PSA_KEY_TYPE_RSA_KEYPAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PSS(PSA_ALG_ANY_HASH):-1:-1:PSA_ERROR_INVALID_ARGUMENT
-
-Copy fail: RSA, incompatible constraint (wildcard on different base)
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_RSA_C:MBEDTLS_SHA256_C
-copy_fail:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):PSA_KEY_TYPE_RSA_KEYPAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PSS(PSA_ALG_ANY_HASH):PSA_ERROR_INVALID_ARGUMENT
-
-Copy fail: RSA, incompatible constraint
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_RSA_C:MBEDTLS_SHA256_C
-copy_fail:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH):PSA_KEY_TYPE_RSA_KEYPAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH):PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PSS(PSA_ALG_ANY_HASH):PSA_ERROR_INVALID_ARGUMENT
+copy_key:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH):PSA_KEY_TYPE_RSA_KEYPAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":0:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_PSS(PSA_ALG_ANY_HASH):PSA_ERROR_INVALID_ARGUMENT:-1:-1
 
 Copy fail: RSA, ANY_HASH is not meaningful with OAEP
 depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_RSA_C:MBEDTLS_SHA256_C
-copy_fail:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_OAEP(PSA_ALG_ANY_HASH):PSA_KEY_TYPE_RSA_KEYPAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_OAEP(PSA_ALG_SHA_256):-1:-1:PSA_ERROR_INVALID_ARGUMENT
+copy_key:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_OAEP(PSA_ALG_ANY_HASH):PSA_KEY_TYPE_RSA_KEYPAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":0:PSA_KEY_USAGE_EXPORT:PSA_ALG_RSA_OAEP(PSA_ALG_SHA_256):PSA_ERROR_INVALID_ARGUMENT:-1:-1
 
 Hash operation object initializers zero properly
 hash_operation_init:
@@ -2111,34 +2036,60 @@
 depends_on:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECDSA_C
 generate_key:PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_SECP256R1):128:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN | PSA_KEY_USAGE_VERIFY:PSA_ALG_ECDSA_ANY:PSA_ERROR_INVALID_ARGUMENT
 
-persistent key can be accessed after in-memory deletion: AES, 128 bits, CTR
+PSA generate key: RSA, default e
+generate_key_rsa:512:"":PSA_SUCCESS
+
+PSA generate key: RSA, e=3
+generate_key_rsa:512:"03":PSA_SUCCESS
+
+PSA generate key: RSA, e=65537
+generate_key_rsa:512:"010001":PSA_SUCCESS
+
+PSA generate key: RSA, e=513
+generate_key_rsa:512:"0201":PSA_SUCCESS
+
+PSA generate key: RSA, e=1
+generate_key_rsa:512:"01":PSA_ERROR_INVALID_ARGUMENT
+
+PSA generate key: RSA, e=2
+generate_key_rsa:512:"01":PSA_ERROR_INVALID_ARGUMENT
+
+PSA import persistent key: raw data, 0 bits
 depends_on:MBEDTLS_PK_C:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_PSA_CRYPTO_STORAGE_C
-persistent_key_load_key_from_storage:"2b7e151628aed2a6abf7158809cf4f3c":PSA_KEY_TYPE_AES:128:PSA_KEY_USAGE_EXPORT:PSA_ALG_CTR:IMPORT_KEY:PSA_SUCCESS
+persistent_key_load_key_from_storage:"":PSA_KEY_TYPE_RAW_DATA:0:PSA_KEY_USAGE_EXPORT:0:IMPORT_KEY
 
-PSA generate persistent key: raw data, 8 bits
+PSA import persistent key: AES, 128 bits, exportable
+depends_on:MBEDTLS_PK_C:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_PSA_CRYPTO_STORAGE_C
+persistent_key_load_key_from_storage:"2b7e151628aed2a6abf7158809cf4f3c":PSA_KEY_TYPE_AES:128:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_EXPORT:PSA_ALG_CTR:IMPORT_KEY
+
+PSA import persistent key: AES, 128 bits, non-exportable
+depends_on:MBEDTLS_PK_C:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_PSA_CRYPTO_STORAGE_C
+persistent_key_load_key_from_storage:"2b7e151628aed2a6abf7158809cf4f3c":PSA_KEY_TYPE_AES:128:PSA_KEY_USAGE_ENCRYPT:PSA_ALG_CTR:IMPORT_KEY
+
+PSA generate persistent key: raw data, 8 bits, exportable
 depends_on:MBEDTLS_PSA_CRYPTO_STORAGE_C
-persistent_key_load_key_from_storage:"":PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0:GENERATE_KEY:PSA_SUCCESS
+persistent_key_load_key_from_storage:"":PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0:GENERATE_KEY
 
-PSA generate persistent key: AES, 128 bits, CTR
+PSA generate persistent key: AES, 128 bits, exportable
 depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR:MBEDTLS_PSA_CRYPTO_STORAGE_C
-persistent_key_load_key_from_storage:"":PSA_KEY_TYPE_AES:128:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_CTR:GENERATE_KEY:PSA_SUCCESS
+persistent_key_load_key_from_storage:"":PSA_KEY_TYPE_AES:128:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_CTR:GENERATE_KEY
 
-PSA generate persistent key: DES, 64 bits, CBC-nopad
+PSA generate persistent key: AES, 128 bits, non-exportable
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR:MBEDTLS_PSA_CRYPTO_STORAGE_C
+persistent_key_load_key_from_storage:"":PSA_KEY_TYPE_AES:128:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_CTR:GENERATE_KEY
+
+PSA generate persistent key: DES, 64 bits, exportable
 depends_on:MBEDTLS_DES_C:MBEDTLS_PSA_CRYPTO_STORAGE_C
-persistent_key_load_key_from_storage:"":PSA_KEY_TYPE_DES:64:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_CBC_NO_PADDING:GENERATE_KEY:PSA_SUCCESS
+persistent_key_load_key_from_storage:"":PSA_KEY_TYPE_DES:64:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_CBC_NO_PADDING:GENERATE_KEY
 
-PSA generate persistent key: RSA, 1024 bits, good, sign (PSS SHA-256)
+PSA generate persistent key: RSA, 1024 bits, exportable
 depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME:MBEDTLS_PKCS1_V21:MBEDTLS_SHA256_C:MBEDTLS_PSA_CRYPTO_STORAGE_C
-persistent_key_load_key_from_storage:"":PSA_KEY_TYPE_RSA_KEYPAIR:1024:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN | PSA_KEY_USAGE_VERIFY:PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):GENERATE_KEY:PSA_SUCCESS
+persistent_key_load_key_from_storage:"":PSA_KEY_TYPE_RSA_KEYPAIR:1024:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN | PSA_KEY_USAGE_VERIFY:PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):GENERATE_KEY
 
-PSA generate persistent key: ECC, SECP256R1, good
+PSA generate persistent key: ECC, SECP256R1, exportable
 depends_on:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECDSA_C:MBEDTLS_PSA_CRYPTO_STORAGE_C
-persistent_key_load_key_from_storage:"":PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_SECP256R1):256:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN | PSA_KEY_USAGE_VERIFY:PSA_ALG_ECDSA_ANY:GENERATE_KEY:PSA_SUCCESS
+persistent_key_load_key_from_storage:"":PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_SECP256R1):256:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN | PSA_KEY_USAGE_VERIFY:PSA_ALG_ECDSA_ANY:GENERATE_KEY
 
-PSA derive persistent key: HKDF SHA-256
+PSA derive persistent key: HKDF SHA-256, exportable
 depends_on:MBEDTLS_MD_C:MBEDTLS_SHA256_C:MBEDTLS_PSA_CRYPTO_STORAGE_C
-persistent_key_load_key_from_storage:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_KEY_TYPE_RAW_DATA:1024:PSA_KEY_USAGE_EXPORT:0:DERIVE_KEY:PSA_SUCCESS
-
-PSA generate persistent key: AES, 128 bits, CTR
-depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR:MBEDTLS_PSA_CRYPTO_STORAGE_C
-persistent_key_load_key_from_storage:"":PSA_KEY_TYPE_AES:128:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_CTR:GENERATE_KEY:PSA_ERROR_NOT_PERMITTED
+persistent_key_load_key_from_storage:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_KEY_TYPE_RAW_DATA:1024:PSA_KEY_USAGE_EXPORT:0:DERIVE_KEY
diff --git a/tests/suites/test_suite_psa_crypto.function b/tests/suites/test_suite_psa_crypto.function
index e017364..c194396 100644
--- a/tests/suites/test_suite_psa_crypto.function
+++ b/tests/suites/test_suite_psa_crypto.function
@@ -211,12 +211,12 @@
                         psa_status_t *status )
 {
     psa_key_handle_t handle = 0;
-    psa_key_policy_t policy = PSA_KEY_POLICY_INIT;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
 
-    PSA_ASSERT( psa_allocate_key( &handle ) );
-    psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_SIGN, alg );
-    PSA_ASSERT( psa_set_key_policy( handle, &policy ) );
-    PSA_ASSERT( psa_import_key( handle, key_type, key_bytes, key_length ) );
+    psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_SIGN );
+    psa_set_key_algorithm( &attributes, alg );
+    psa_set_key_type( &attributes, key_type );
+    PSA_ASSERT( psa_import_key( &attributes, &handle, key_bytes, key_length ) );
 
     *status = psa_mac_sign_setup( operation, handle, alg );
     /* Whether setup succeeded or failed, abort must succeed. */
@@ -245,12 +245,12 @@
                            psa_status_t *status )
 {
     psa_key_handle_t handle = 0;
-    psa_key_policy_t policy = PSA_KEY_POLICY_INIT;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
 
-    PSA_ASSERT( psa_allocate_key( &handle ) );
-    psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_ENCRYPT, alg );
-    PSA_ASSERT( psa_set_key_policy( handle, &policy ) );
-    PSA_ASSERT( psa_import_key( handle, key_type, key_bytes, key_length ) );
+    psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_ENCRYPT );
+    psa_set_key_algorithm( &attributes, alg );
+    psa_set_key_type( &attributes, key_type );
+    PSA_ASSERT( psa_import_key( &attributes, &handle, key_bytes, key_length ) );
 
     *status = psa_cipher_encrypt_setup( operation, handle, alg );
     /* Whether setup succeeded or failed, abort must succeed. */
@@ -346,12 +346,16 @@
     if( usage & PSA_KEY_USAGE_DECRYPT )
     {
         psa_status_t status;
-        psa_key_type_t type = PSA_KEY_TYPE_NONE;
+        int maybe_invalid_padding = 0;
         if( ! ( usage & PSA_KEY_USAGE_ENCRYPT ) )
         {
-            size_t bits;
-            TEST_ASSERT( psa_get_key_information( handle, &type, &bits ) );
-            iv_length = PSA_BLOCK_CIPHER_BLOCK_SIZE( type );
+            psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+            PSA_ASSERT( psa_get_key_attributes( handle, &attributes ) );
+            /* This should be PSA_CIPHER_GET_IV_SIZE but the API doesn't
+             * have this macro yet. */
+            iv_length = PSA_BLOCK_CIPHER_BLOCK_SIZE(
+                psa_get_key_type( &attributes ) );
+            maybe_invalid_padding = ! PSA_ALG_IS_STREAM_CIPHER( alg );
         }
         PSA_ASSERT( psa_cipher_decrypt_setup( &operation,
                                               handle, alg ) );
@@ -368,12 +372,11 @@
         /* For a stream cipher, all inputs are valid. For a block cipher,
          * if the input is some aribtrary data rather than an actual
          ciphertext, a padding error is likely.  */
-        if( ( usage & PSA_KEY_USAGE_ENCRYPT ) ||
-            PSA_BLOCK_CIPHER_BLOCK_SIZE( type ) == 1 )
-            PSA_ASSERT( status );
-        else
+        if( maybe_invalid_padding )
             TEST_ASSERT( status == PSA_SUCCESS ||
                          status == PSA_ERROR_INVALID_PADDING );
+        else
+            PSA_ASSERT( status );
     }
 
     return( 1 );
@@ -579,10 +582,11 @@
      * psa_key_agreement fails. This isn't fully satisfactory, but it's
      * good enough: callers will report it as a failed test anyway. */
     psa_status_t status = PSA_ERROR_GENERIC_ERROR;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
 
-    PSA_ASSERT( psa_get_key_information( handle,
-                                         &private_key_type,
-                                         &key_bits ) );
+    PSA_ASSERT( psa_get_key_attributes( handle, &attributes ) );
+    private_key_type = psa_get_key_type( &attributes );
+    key_bits = psa_get_key_bits( &attributes );
     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 );
@@ -594,6 +598,7 @@
                                 public_key, public_key_length );
 exit:
     mbedtls_free( public_key );
+    psa_reset_key_attributes( &attributes );
     return( status );
 }
 
@@ -613,10 +618,11 @@
      * psa_key_agreement fails. This isn't fully satisfactory, but it's
      * good enough: callers will report it as a failed test anyway. */
     psa_status_t status = PSA_ERROR_GENERIC_ERROR;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
 
-    PSA_ASSERT( psa_get_key_information( handle,
-                                         &private_key_type,
-                                         &key_bits ) );
+    PSA_ASSERT( psa_get_key_attributes( handle, &attributes ) );
+    private_key_type = psa_get_key_type( &attributes );
+    key_bits = psa_get_key_bits( &attributes );
     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 );
@@ -630,6 +636,7 @@
         output, sizeof( output ), &output_length );
 exit:
     mbedtls_free( public_key );
+    psa_reset_key_attributes( &attributes );
     return( status );
 }
 
@@ -918,66 +925,73 @@
 static int exercise_export_key( psa_key_handle_t handle,
                                 psa_key_usage_t usage )
 {
-    psa_key_type_t type;
-    size_t bits;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
     uint8_t *exported = NULL;
     size_t exported_size = 0;
     size_t exported_length = 0;
     int ok = 0;
 
-    PSA_ASSERT( psa_get_key_information( handle, &type, &bits ) );
+    PSA_ASSERT( psa_get_key_attributes( handle, &attributes ) );
 
     if( ( usage & PSA_KEY_USAGE_EXPORT ) == 0 &&
-        ! PSA_KEY_TYPE_IS_PUBLIC_KEY( type ) )
+        ! PSA_KEY_TYPE_IS_PUBLIC_KEY( psa_get_key_type( &attributes ) ) )
     {
         TEST_EQUAL( psa_export_key( handle, NULL, 0, &exported_length ),
                     PSA_ERROR_NOT_PERMITTED );
-        return( 1 );
+        ok = 1;
+        goto exit;
     }
 
-    exported_size = PSA_KEY_EXPORT_MAX_SIZE( type, bits );
+    exported_size = PSA_KEY_EXPORT_MAX_SIZE( psa_get_key_type( &attributes ),
+                                             psa_get_key_bits( &attributes ) );
     ASSERT_ALLOC( exported, exported_size );
 
     PSA_ASSERT( psa_export_key( handle,
                                 exported, exported_size,
                                 &exported_length ) );
-    ok = exported_key_sanity_check( type, bits, exported, exported_length );
+    ok = exported_key_sanity_check( psa_get_key_type( &attributes ),
+                                    psa_get_key_bits( &attributes ),
+                                    exported, exported_length );
 
 exit:
     mbedtls_free( exported );
+    psa_reset_key_attributes( &attributes );
     return( ok );
 }
 
 static int exercise_export_public_key( psa_key_handle_t handle )
 {
-    psa_key_type_t type;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
     psa_key_type_t public_type;
-    size_t bits;
     uint8_t *exported = NULL;
     size_t exported_size = 0;
     size_t exported_length = 0;
     int ok = 0;
 
-    PSA_ASSERT( psa_get_key_information( handle, &type, &bits ) );
-    if( ! PSA_KEY_TYPE_IS_ASYMMETRIC( type ) )
+    PSA_ASSERT( psa_get_key_attributes( handle, &attributes ) );
+    if( ! PSA_KEY_TYPE_IS_ASYMMETRIC( psa_get_key_type( &attributes ) ) )
     {
         TEST_EQUAL( psa_export_public_key( handle, NULL, 0, &exported_length ),
                     PSA_ERROR_INVALID_ARGUMENT );
         return( 1 );
     }
 
-    public_type = PSA_KEY_TYPE_PUBLIC_KEY_OF_KEYPAIR( type );
-    exported_size = PSA_KEY_EXPORT_MAX_SIZE( public_type, bits );
+    public_type = PSA_KEY_TYPE_PUBLIC_KEY_OF_KEYPAIR(
+        psa_get_key_type( &attributes ) );
+    exported_size = PSA_KEY_EXPORT_MAX_SIZE( public_type,
+                                             psa_get_key_bits( &attributes ) );
     ASSERT_ALLOC( exported, exported_size );
 
     PSA_ASSERT( psa_export_public_key( handle,
                                        exported, exported_size,
                                        &exported_length ) );
-    ok = exported_key_sanity_check( public_type, bits,
+    ok = exported_key_sanity_check( public_type,
+                                    psa_get_key_bits( &attributes ),
                                     exported, exported_length );
 
 exit:
     mbedtls_free( exported );
+    psa_reset_key_attributes( &attributes );
     return( ok );
 }
 
@@ -1075,6 +1089,43 @@
 
 }
 
+static int test_operations_on_invalid_handle( psa_key_handle_t handle )
+{
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    uint8_t buffer[1];
+    size_t length;
+    int ok = 0;
+
+    psa_make_key_persistent( &attributes, 0x6964, PSA_KEY_LIFETIME_PERSISTENT );
+    psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_ENCRYPT );
+    psa_set_key_algorithm( &attributes, PSA_ALG_CTR );
+    psa_set_key_type( &attributes, PSA_KEY_TYPE_AES );
+    TEST_EQUAL( psa_get_key_attributes( handle, &attributes ),
+                PSA_ERROR_INVALID_HANDLE );
+    TEST_EQUAL( psa_get_key_id( &attributes ), 0 );
+    TEST_EQUAL( psa_get_key_lifetime( &attributes ), 0 );
+    TEST_EQUAL( psa_get_key_usage_flags( &attributes ), 0 );
+    TEST_EQUAL( psa_get_key_algorithm( &attributes ), 0 );
+    TEST_EQUAL( psa_get_key_type( &attributes ), 0 );
+    TEST_EQUAL( psa_get_key_bits( &attributes ), 0 );
+
+    TEST_EQUAL( psa_export_key( handle,
+                                buffer, sizeof( buffer ), &length ),
+                PSA_ERROR_INVALID_HANDLE );
+    TEST_EQUAL( psa_export_public_key( handle,
+                                       buffer, sizeof( buffer ), &length ),
+                PSA_ERROR_INVALID_HANDLE );
+
+    TEST_EQUAL( psa_close_key( handle ), PSA_ERROR_INVALID_HANDLE );
+    TEST_EQUAL( psa_destroy_key( handle ), PSA_ERROR_INVALID_HANDLE );
+
+    ok = 1;
+
+exit:
+    psa_reset_key_attributes( &attributes );
+    return( ok );
+}
+
 /* 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
@@ -1109,61 +1160,76 @@
 /* END_CASE */
 
 /* BEGIN_CASE */
-void import( data_t *data, int type, int expected_status_arg )
+void attributes_set_get( int id_arg, int lifetime_arg,
+                         int usage_flags_arg, int alg_arg,
+                         int type_arg, int bits_arg )
 {
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    psa_key_id_t id = id_arg;
+    psa_key_lifetime_t lifetime = lifetime_arg;
+    psa_key_usage_t usage_flags = usage_flags_arg;
+    psa_algorithm_t alg = alg_arg;
+    psa_key_type_t type = type_arg;
+    size_t bits = bits_arg;
+
+    TEST_EQUAL( psa_get_key_id( &attributes ), 0 );
+    TEST_EQUAL( psa_get_key_lifetime( &attributes ), 0 );
+    TEST_EQUAL( psa_get_key_usage_flags( &attributes ), 0 );
+    TEST_EQUAL( psa_get_key_algorithm( &attributes ), 0 );
+    TEST_EQUAL( psa_get_key_type( &attributes ), 0 );
+    TEST_EQUAL( psa_get_key_bits( &attributes ), 0 );
+
+    psa_make_key_persistent( &attributes, id, lifetime );
+    psa_set_key_usage_flags( &attributes, usage_flags );
+    psa_set_key_algorithm( &attributes, alg );
+    psa_set_key_type( &attributes, type );
+    psa_set_key_bits( &attributes, bits );
+
+    TEST_EQUAL( psa_get_key_id( &attributes ), id );
+    TEST_EQUAL( psa_get_key_lifetime( &attributes ), lifetime );
+    TEST_EQUAL( psa_get_key_usage_flags( &attributes ), usage_flags );
+    TEST_EQUAL( psa_get_key_algorithm( &attributes ), alg );
+    TEST_EQUAL( psa_get_key_type( &attributes ), type );
+    TEST_EQUAL( psa_get_key_bits( &attributes ), bits );
+
+    psa_reset_key_attributes( &attributes );
+
+    TEST_EQUAL( psa_get_key_id( &attributes ), 0 );
+    TEST_EQUAL( psa_get_key_lifetime( &attributes ), 0 );
+    TEST_EQUAL( psa_get_key_usage_flags( &attributes ), 0 );
+    TEST_EQUAL( psa_get_key_algorithm( &attributes ), 0 );
+    TEST_EQUAL( psa_get_key_type( &attributes ), 0 );
+    TEST_EQUAL( psa_get_key_bits( &attributes ), 0 );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void import( data_t *data, int type_arg, int expected_status_arg )
+{
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    psa_key_attributes_t got_attributes = PSA_KEY_ATTRIBUTES_INIT;
     psa_key_handle_t handle = 0;
+    psa_key_type_t type = type_arg;
     psa_status_t expected_status = expected_status_arg;
     psa_status_t status;
 
     PSA_ASSERT( psa_crypto_init( ) );
 
-    PSA_ASSERT( psa_allocate_key( &handle ) );
-    status = psa_import_key( handle, type, data->x, data->len );
+    psa_set_key_type( &attributes, type );
+    status = psa_import_key( &attributes, &handle, data->x, data->len );
     TEST_EQUAL( status, expected_status );
-    if( status == PSA_SUCCESS )
-        PSA_ASSERT( psa_destroy_key( handle ) );
+    if( status != PSA_SUCCESS )
+        goto exit;
+
+    PSA_ASSERT( psa_get_key_attributes( handle, &got_attributes ) );
+    TEST_EQUAL( psa_get_key_type( &got_attributes ), type );
+
+    PSA_ASSERT( psa_destroy_key( handle ) );
+    test_operations_on_invalid_handle( handle );
 
 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_KEY_POLICY_INIT;
-    psa_status_t status;
-
-    PSA_ASSERT( psa_crypto_init( ) );
-
-    PSA_ASSERT( psa_allocate_key( &handle ) );
-    psa_key_policy_set_usage( &policy, usage, alg );
-    PSA_ASSERT( psa_set_key_policy( handle, &policy ) );
-
-    status = psa_import_key( handle, type1, data1->x, data1->len );
-    TEST_EQUAL( status, expected_import1_status );
-    status = psa_import_key( handle, type2, data2->x, data2->len );
-    TEST_EQUAL( status, expected_import2_status );
-
-    if( expected_import1_status == PSA_SUCCESS ||
-        expected_import2_status == PSA_SUCCESS )
-    {
-        if( ! exercise_key( handle, usage, alg ) )
-            goto exit;
-    }
-
-exit:
+    psa_destroy_key( handle );
+    psa_reset_key_attributes( &got_attributes );
     mbedtls_psa_crypto_free( );
 }
 /* END_CASE */
@@ -1183,6 +1249,7 @@
     unsigned char *p;
     int ret;
     size_t length;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
 
     PSA_ASSERT( psa_crypto_init( ) );
     ASSERT_ALLOC( buffer, buffer_size );
@@ -1192,8 +1259,8 @@
     length = ret;
 
     /* Try importing the key */
-    PSA_ASSERT( psa_allocate_key( &handle ) );
-    status = psa_import_key( handle, type, p, length );
+    psa_set_key_type( &attributes, type );
+    status = psa_import_key( &attributes, &handle, p, length );
     TEST_EQUAL( status, expected_status );
     if( status == PSA_SUCCESS )
         PSA_ASSERT( psa_destroy_key( handle ) );
@@ -1224,9 +1291,8 @@
     size_t export_size;
     size_t exported_length = INVALID_EXPORT_LENGTH;
     size_t reexported_length;
-    psa_key_type_t got_type;
-    size_t got_bits;
-    psa_key_policy_t policy = PSA_KEY_POLICY_INIT;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    psa_key_attributes_t got_attributes = PSA_KEY_ATTRIBUTES_INIT;
 
     export_size = (ptrdiff_t) data->len + export_size_delta;
     ASSERT_ALLOC( exported, export_size );
@@ -1234,23 +1300,17 @@
         ASSERT_ALLOC( reexported, export_size );
     PSA_ASSERT( psa_crypto_init( ) );
 
-    PSA_ASSERT( psa_allocate_key( &handle ) );
-    psa_key_policy_set_usage( &policy, usage_arg, alg );
-    PSA_ASSERT( psa_set_key_policy( handle, &policy ) );
-
-    TEST_EQUAL( psa_get_key_information( handle, NULL, NULL ),
-                PSA_ERROR_DOES_NOT_EXIST );
+    psa_set_key_usage_flags( &attributes, usage_arg );
+    psa_set_key_algorithm( &attributes, alg );
+    psa_set_key_type( &attributes, type );
 
     /* Import the key */
-    PSA_ASSERT( psa_import_key( handle, type,
-                                data->x, data->len ) );
+    PSA_ASSERT( psa_import_key( &attributes, &handle, data->x, data->len ) );
 
     /* Test the key information */
-    PSA_ASSERT( psa_get_key_information( handle,
-                                         &got_type,
-                                         &got_bits ) );
-    TEST_EQUAL( got_type, type );
-    TEST_EQUAL( got_bits, (size_t) expected_bits );
+    PSA_ASSERT( psa_get_key_attributes( handle, &got_attributes ) );
+    TEST_EQUAL( psa_get_key_type( &got_attributes ), type );
+    TEST_EQUAL( psa_get_key_bits( &got_attributes ), (size_t) expected_bits );
 
     /* Export the key */
     status = psa_export_key( handle,
@@ -1280,12 +1340,8 @@
     else
     {
         psa_key_handle_t handle2;
-        PSA_ASSERT( psa_allocate_key( &handle2 ) );
-        PSA_ASSERT( psa_set_key_policy( handle2, &policy ) );
-
-        PSA_ASSERT( psa_import_key( handle2, type,
-                                    exported,
-                                    exported_length ) );
+        PSA_ASSERT( psa_import_key( &attributes, &handle2,
+                                    exported, exported_length ) );
         PSA_ASSERT( psa_export_key( handle2,
                                     reexported,
                                     export_size,
@@ -1294,39 +1350,26 @@
                         reexported, reexported_length );
         PSA_ASSERT( psa_close_key( handle2 ) );
     }
-    TEST_ASSERT( exported_length <= PSA_KEY_EXPORT_MAX_SIZE( type, got_bits ) );
+    TEST_ASSERT( exported_length <= PSA_KEY_EXPORT_MAX_SIZE( type, psa_get_key_bits( &got_attributes ) ) );
 
 destroy:
     /* Destroy the key */
     PSA_ASSERT( psa_destroy_key( handle ) );
-    TEST_EQUAL( psa_get_key_information( handle, NULL, NULL ),
-                PSA_ERROR_INVALID_HANDLE );
+    test_operations_on_invalid_handle( handle );
 
 exit:
     mbedtls_free( exported );
     mbedtls_free( reexported );
+    psa_reset_key_attributes( &got_attributes );
     mbedtls_psa_crypto_free( );
 }
 /* END_CASE */
 
 /* BEGIN_CASE */
-void import_key_nonempty_slot( )
+void invalid_handle( int handle )
 {
-    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 };
     PSA_ASSERT( psa_crypto_init( ) );
-
-    PSA_ASSERT( psa_allocate_key( &handle ) );
-
-    /* Import the key */
-    PSA_ASSERT( psa_import_key( handle, type,
-                                data, sizeof( data ) ) );
-
-    /* Import the key again */
-    status = psa_import_key( handle, type, data, sizeof( data ) );
-    TEST_EQUAL( status, PSA_ERROR_ALREADY_EXISTS );
+    test_operations_on_invalid_handle( handle );
 
 exit:
     mbedtls_psa_crypto_free( );
@@ -1334,182 +1377,6 @@
 /* END_CASE */
 
 /* BEGIN_CASE */
-void export_invalid_handle( int handle, int expected_export_status_arg )
-{
-    psa_status_t status;
-    unsigned char *exported = NULL;
-    size_t export_size = 0;
-    size_t exported_length = INVALID_EXPORT_LENGTH;
-    psa_status_t expected_export_status = expected_export_status_arg;
-
-    PSA_ASSERT( psa_crypto_init( ) );
-
-    /* Export the key */
-    status = psa_export_key( (psa_key_handle_t) handle,
-                             exported, export_size,
-                             &exported_length );
-    TEST_EQUAL( status, expected_export_status );
-
-exit:
-    mbedtls_psa_crypto_free( );
-}
-/* END_CASE */
-
-/* BEGIN_CASE */
-void export_with_no_key_activity( )
-{
-    psa_key_handle_t handle = 0;
-    psa_algorithm_t alg = PSA_ALG_CTR;
-    psa_status_t status;
-    psa_key_policy_t policy = PSA_KEY_POLICY_INIT;
-    unsigned char *exported = NULL;
-    size_t export_size = 0;
-    size_t exported_length = INVALID_EXPORT_LENGTH;
-
-    PSA_ASSERT( psa_crypto_init( ) );
-
-    PSA_ASSERT( psa_allocate_key( &handle ) );
-    psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_EXPORT, alg );
-    PSA_ASSERT( psa_set_key_policy( handle, &policy ) );
-
-    /* Export the key */
-    status = psa_export_key( handle,
-                             exported, export_size,
-                             &exported_length );
-    TEST_EQUAL( status, PSA_ERROR_DOES_NOT_EXIST );
-
-exit:
-    mbedtls_psa_crypto_free( );
-}
-/* END_CASE */
-
-/* BEGIN_CASE */
-void cipher_with_no_key_activity( )
-{
-    psa_key_handle_t handle = 0;
-    psa_status_t status;
-    psa_key_policy_t policy = PSA_KEY_POLICY_INIT;
-    psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT;
-    int exercise_alg = PSA_ALG_CTR;
-
-    PSA_ASSERT( psa_crypto_init( ) );
-
-    PSA_ASSERT( psa_allocate_key( &handle ) );
-    psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_ENCRYPT, exercise_alg );
-    PSA_ASSERT( psa_set_key_policy( handle, &policy ) );
-
-    status = psa_cipher_encrypt_setup( &operation, handle, exercise_alg );
-    TEST_EQUAL( status, PSA_ERROR_DOES_NOT_EXIST );
-
-exit:
-    psa_cipher_abort( &operation );
-    mbedtls_psa_crypto_free( );
-}
-/* END_CASE */
-
-/* BEGIN_CASE */
-void export_after_import_failure( data_t *data, int type_arg,
-                                  int expected_import_status_arg )
-{
-    psa_key_handle_t handle = 0;
-    psa_key_type_t type = type_arg;
-    psa_status_t status;
-    unsigned char *exported = NULL;
-    size_t export_size = 0;
-    psa_status_t expected_import_status = expected_import_status_arg;
-    size_t exported_length = INVALID_EXPORT_LENGTH;
-
-    PSA_ASSERT( psa_crypto_init( ) );
-
-    PSA_ASSERT( psa_allocate_key( &handle ) );
-
-    /* Import the key - expect failure */
-    status = psa_import_key( handle, type,
-                             data->x, data->len );
-    TEST_EQUAL( status, expected_import_status );
-
-    /* Export the key */
-    status = psa_export_key( handle,
-                             exported, export_size,
-                             &exported_length );
-    TEST_EQUAL( status, PSA_ERROR_DOES_NOT_EXIST );
-
-exit:
-    mbedtls_psa_crypto_free( );
-}
-/* END_CASE */
-
-/* BEGIN_CASE */
-void cipher_after_import_failure( data_t *data, int type_arg,
-                                  int expected_import_status_arg )
-{
-    psa_key_handle_t handle = 0;
-    psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT;
-    psa_key_type_t type = type_arg;
-    psa_status_t status;
-    psa_status_t expected_import_status = expected_import_status_arg;
-    int exercise_alg = PSA_ALG_CTR;
-
-    PSA_ASSERT( psa_crypto_init( ) );
-
-    PSA_ASSERT( psa_allocate_key( &handle ) );
-
-    /* Import the key - expect failure */
-    status = psa_import_key( handle, type,
-                             data->x, data->len );
-    TEST_EQUAL( status, expected_import_status );
-
-    status = psa_cipher_encrypt_setup( &operation, handle, exercise_alg );
-    TEST_EQUAL( status, PSA_ERROR_DOES_NOT_EXIST );
-
-exit:
-    psa_cipher_abort( &operation );
-    mbedtls_psa_crypto_free( );
-}
-/* END_CASE */
-
-/* BEGIN_CASE */
-void export_after_destroy_key( data_t *data, int type_arg )
-{
-    psa_key_handle_t handle = 0;
-    psa_key_type_t type = type_arg;
-    psa_status_t status;
-    psa_key_policy_t policy = PSA_KEY_POLICY_INIT;
-    psa_algorithm_t alg = PSA_ALG_CTR;
-    unsigned char *exported = NULL;
-    size_t export_size = 0;
-    size_t exported_length = INVALID_EXPORT_LENGTH;
-
-    PSA_ASSERT( psa_crypto_init( ) );
-
-    PSA_ASSERT( psa_allocate_key( &handle ) );
-    psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_EXPORT, alg );
-    PSA_ASSERT( psa_set_key_policy( handle, &policy ) );
-    export_size = (ptrdiff_t) data->len;
-    ASSERT_ALLOC( exported, export_size );
-
-    /* Import the key */
-    PSA_ASSERT( psa_import_key( handle, type,
-                                data->x, data->len ) );
-
-    PSA_ASSERT( psa_export_key( handle, exported, export_size,
-                                &exported_length ) );
-
-    /* Destroy the key */
-    PSA_ASSERT( psa_destroy_key( handle ) );
-
-    /* Export the key */
-    status = psa_export_key( handle, exported, export_size,
-                             &exported_length );
-    TEST_EQUAL( status, PSA_ERROR_INVALID_HANDLE );
-
-exit:
-    mbedtls_free( exported );
-    mbedtls_psa_crypto_free( );
-}
-/* END_CASE */
-
-/* BEGIN_CASE */
 void import_export_public_key( data_t *data,
                                int type_arg,
                                int alg_arg,
@@ -1525,17 +1392,16 @@
     unsigned char *exported = NULL;
     size_t export_size = expected_public_key->len + export_size_delta;
     size_t exported_length = INVALID_EXPORT_LENGTH;
-    psa_key_policy_t policy = PSA_KEY_POLICY_INIT;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
 
     PSA_ASSERT( psa_crypto_init( ) );
 
-    PSA_ASSERT( psa_allocate_key( &handle ) );
-    psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_EXPORT, alg );
-    PSA_ASSERT( psa_set_key_policy( handle, &policy ) );
+    psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_EXPORT );
+    psa_set_key_algorithm( &attributes, alg );
+    psa_set_key_type( &attributes, type );
 
     /* Import the key */
-    PSA_ASSERT( psa_import_key( handle, type,
-                                data->x, data->len ) );
+    PSA_ASSERT( psa_import_key( &attributes, &handle, data->x, data->len ) );
 
     /* Export the public key */
     ASSERT_ALLOC( exported, export_size );
@@ -1547,7 +1413,8 @@
     {
         psa_key_type_t public_type = PSA_KEY_TYPE_PUBLIC_KEY_OF_KEYPAIR( type );
         size_t bits;
-        PSA_ASSERT( psa_get_key_information( handle, NULL, &bits ) );
+        PSA_ASSERT( psa_get_key_attributes( handle, &attributes ) );
+        bits = psa_get_key_bits( &attributes );
         TEST_ASSERT( expected_public_key->len <=
                      PSA_KEY_EXPORT_MAX_SIZE( public_type, bits ) );
         ASSERT_COMPARE( expected_public_key->x, expected_public_key->len,
@@ -1557,6 +1424,7 @@
 exit:
     mbedtls_free( exported );
     psa_destroy_key( handle );
+    psa_reset_key_attributes( &attributes );
     mbedtls_psa_crypto_free( );
 }
 /* END_CASE */
@@ -1572,34 +1440,33 @@
     size_t bits = bits_arg;
     psa_algorithm_t alg = alg_arg;
     psa_key_usage_t usage = usage_to_exercise( type, alg );
-    psa_key_policy_t policy = PSA_KEY_POLICY_INIT;
-    psa_key_type_t got_type;
-    size_t got_bits;
-    psa_status_t status;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    psa_key_attributes_t got_attributes = PSA_KEY_ATTRIBUTES_INIT;
 
     PSA_ASSERT( psa_crypto_init( ) );
 
-    PSA_ASSERT( psa_allocate_key( &handle ) );
-    psa_key_policy_set_usage( &policy, usage, alg );
-    PSA_ASSERT( psa_set_key_policy( handle, &policy ) );
+    psa_set_key_usage_flags( &attributes, usage );
+    psa_set_key_algorithm( &attributes, alg );
+    psa_set_key_type( &attributes, type );
 
     /* Import the key */
-    status = psa_import_key( handle, type, data->x, data->len );
-    PSA_ASSERT( status );
+    PSA_ASSERT( psa_import_key( &attributes, &handle, data->x, data->len ) );
 
     /* Test the key information */
-    PSA_ASSERT( psa_get_key_information( handle,
-                                         &got_type,
-                                         &got_bits ) );
-    TEST_EQUAL( got_type, type );
-    TEST_EQUAL( got_bits, bits );
+    PSA_ASSERT( psa_get_key_attributes( handle, &got_attributes ) );
+    TEST_EQUAL( psa_get_key_type( &got_attributes ), type );
+    TEST_EQUAL( psa_get_key_bits( &got_attributes ), bits );
 
     /* Do something with the key according to its type and permitted usage. */
     if( ! exercise_key( handle, usage, alg ) )
         goto exit;
 
+    PSA_ASSERT( psa_destroy_key( handle ) );
+    test_operations_on_invalid_handle( handle );
+
 exit:
     psa_destroy_key( handle );
+    psa_reset_key_attributes( &got_attributes );
     mbedtls_psa_crypto_free( );
 }
 /* END_CASE */
@@ -1612,56 +1479,62 @@
     psa_key_usage_t usage = usage_arg;
     psa_key_type_t key_type = PSA_KEY_TYPE_AES;
     unsigned char key[32] = {0};
-    psa_key_policy_t policy_set = PSA_KEY_POLICY_INIT;
-    psa_key_policy_t policy_get = PSA_KEY_POLICY_INIT;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
 
     memset( key, 0x2a, sizeof( key ) );
 
     PSA_ASSERT( psa_crypto_init( ) );
 
-    PSA_ASSERT( psa_allocate_key( &handle ) );
-    psa_key_policy_set_usage( &policy_set, usage, alg );
+    psa_set_key_usage_flags( &attributes, usage );
+    psa_set_key_algorithm( &attributes, alg );
+    psa_set_key_type( &attributes, key_type );
 
-    TEST_EQUAL( psa_key_policy_get_usage( &policy_set ), usage );
-    TEST_EQUAL( psa_key_policy_get_algorithm( &policy_set ), alg );
-    PSA_ASSERT( psa_set_key_policy( handle, &policy_set ) );
+    PSA_ASSERT( psa_import_key( &attributes, &handle, key, sizeof( key ) ) );
 
-    PSA_ASSERT( psa_import_key( handle, key_type,
-                                key, sizeof( key ) ) );
-
-    PSA_ASSERT( psa_get_key_policy( handle, &policy_get ) );
-
-    TEST_EQUAL( policy_get.usage, policy_set.usage );
-    TEST_EQUAL( policy_get.alg, policy_set.alg );
+    PSA_ASSERT( psa_get_key_attributes( handle, &attributes ) );
+    TEST_EQUAL( psa_get_key_type( &attributes ), key_type );
+    TEST_EQUAL( psa_get_key_usage_flags( &attributes ), usage );
+    TEST_EQUAL( psa_get_key_algorithm( &attributes ), alg );
 
 exit:
     psa_destroy_key( handle );
+    psa_reset_key_attributes( &attributes );
     mbedtls_psa_crypto_free( );
 }
 /* END_CASE */
 
 /* BEGIN_CASE */
-void key_policy_init( )
+void key_attributes_init( )
 {
     /* Test each valid way of initializing the object, except for `= {0}`, as
      * Clang 5 complains when `-Wmissing-field-initializers` is used, even
      * though it's OK by the C standard. We could test for this, but we'd need
      * to supress the Clang warning for the test. */
-    psa_key_policy_t func = psa_key_policy_init( );
-    psa_key_policy_t init = PSA_KEY_POLICY_INIT;
-    psa_key_policy_t zero;
+    psa_key_attributes_t func = psa_key_attributes_init( );
+    psa_key_attributes_t init = PSA_KEY_ATTRIBUTES_INIT;
+    psa_key_attributes_t zero;
 
     memset( &zero, 0, sizeof( zero ) );
 
-    /* A default key policy should not permit any usage. */
-    TEST_EQUAL( psa_key_policy_get_usage( &func ), 0 );
-    TEST_EQUAL( psa_key_policy_get_usage( &init ), 0 );
-    TEST_EQUAL( psa_key_policy_get_usage( &zero ), 0 );
+    TEST_EQUAL( psa_get_key_lifetime( &func ), PSA_KEY_LIFETIME_VOLATILE );
+    TEST_EQUAL( psa_get_key_lifetime( &init ), PSA_KEY_LIFETIME_VOLATILE );
+    TEST_EQUAL( psa_get_key_lifetime( &zero ), PSA_KEY_LIFETIME_VOLATILE );
 
-    /* A default key policy should not permit any algorithm. */
-    TEST_EQUAL( psa_key_policy_get_algorithm( &func ), 0 );
-    TEST_EQUAL( psa_key_policy_get_algorithm( &init ), 0 );
-    TEST_EQUAL( psa_key_policy_get_algorithm( &zero ), 0 );
+    TEST_EQUAL( psa_get_key_type( &func ), 0 );
+    TEST_EQUAL( psa_get_key_type( &init ), 0 );
+    TEST_EQUAL( psa_get_key_type( &zero ), 0 );
+
+    TEST_EQUAL( psa_get_key_bits( &func ), 0 );
+    TEST_EQUAL( psa_get_key_bits( &init ), 0 );
+    TEST_EQUAL( psa_get_key_bits( &zero ), 0 );
+
+    TEST_EQUAL( psa_get_key_usage_flags( &func ), 0 );
+    TEST_EQUAL( psa_get_key_usage_flags( &init ), 0 );
+    TEST_EQUAL( psa_get_key_usage_flags( &zero ), 0 );
+
+    TEST_EQUAL( psa_get_key_algorithm( &func ), 0 );
+    TEST_EQUAL( psa_get_key_algorithm( &init ), 0 );
+    TEST_EQUAL( psa_get_key_algorithm( &zero ), 0 );
 }
 /* END_CASE */
 
@@ -1673,18 +1546,18 @@
                      int exercise_alg )
 {
     psa_key_handle_t handle = 0;
-    psa_key_policy_t policy = PSA_KEY_POLICY_INIT;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
     psa_mac_operation_t operation = PSA_MAC_OPERATION_INIT;
     psa_status_t status;
     unsigned char mac[PSA_MAC_MAX_SIZE];
 
     PSA_ASSERT( psa_crypto_init( ) );
 
-    PSA_ASSERT( psa_allocate_key( &handle ) );
-    psa_key_policy_set_usage( &policy, policy_usage, policy_alg );
-    PSA_ASSERT( psa_set_key_policy( handle, &policy ) );
+    psa_set_key_usage_flags( &attributes, policy_usage );
+    psa_set_key_algorithm( &attributes, policy_alg );
+    psa_set_key_type( &attributes, key_type );
 
-    PSA_ASSERT( psa_import_key( handle, key_type,
+    PSA_ASSERT( psa_import_key( &attributes, &handle,
                                 key_data->x, key_data->len ) );
 
     status = psa_mac_sign_setup( &operation, handle, exercise_alg );
@@ -1718,17 +1591,17 @@
                         int exercise_alg )
 {
     psa_key_handle_t handle = 0;
-    psa_key_policy_t policy = PSA_KEY_POLICY_INIT;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
     psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT;
     psa_status_t status;
 
     PSA_ASSERT( psa_crypto_init( ) );
 
-    PSA_ASSERT( psa_allocate_key( &handle ) );
-    psa_key_policy_set_usage( &policy, policy_usage, policy_alg );
-    PSA_ASSERT( psa_set_key_policy( handle, &policy ) );
+    psa_set_key_usage_flags( &attributes, policy_usage );
+    psa_set_key_algorithm( &attributes, policy_alg );
+    psa_set_key_type( &attributes, key_type );
 
-    PSA_ASSERT( psa_import_key( handle, key_type,
+    PSA_ASSERT( psa_import_key( &attributes, &handle,
                                 key_data->x, key_data->len ) );
 
     status = psa_cipher_encrypt_setup( &operation, handle, exercise_alg );
@@ -1763,7 +1636,7 @@
                       int exercise_alg )
 {
     psa_key_handle_t handle = 0;
-    psa_key_policy_t policy = PSA_KEY_POLICY_INIT;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
     psa_status_t status;
     unsigned char nonce[16] = {0};
     size_t nonce_length = nonce_length_arg;
@@ -1776,11 +1649,11 @@
 
     PSA_ASSERT( psa_crypto_init( ) );
 
-    PSA_ASSERT( psa_allocate_key( &handle ) );
-    psa_key_policy_set_usage( &policy, policy_usage, policy_alg );
-    PSA_ASSERT( psa_set_key_policy( handle, &policy ) );
+    psa_set_key_usage_flags( &attributes, policy_usage );
+    psa_set_key_algorithm( &attributes, policy_alg );
+    psa_set_key_type( &attributes, key_type );
 
-    PSA_ASSERT( psa_import_key( handle, key_type,
+    PSA_ASSERT( psa_import_key( &attributes, &handle,
                                 key_data->x, key_data->len ) );
 
     status = psa_aead_encrypt( handle, exercise_alg,
@@ -1822,7 +1695,7 @@
                                        int exercise_alg )
 {
     psa_key_handle_t handle = 0;
-    psa_key_policy_t policy = PSA_KEY_POLICY_INIT;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
     psa_status_t status;
     size_t key_bits;
     size_t buffer_length;
@@ -1831,16 +1704,15 @@
 
     PSA_ASSERT( psa_crypto_init( ) );
 
-    PSA_ASSERT( psa_allocate_key( &handle ) );
-    psa_key_policy_set_usage( &policy, policy_usage, policy_alg );
-    PSA_ASSERT( psa_set_key_policy( handle, &policy ) );
+    psa_set_key_usage_flags( &attributes, policy_usage );
+    psa_set_key_algorithm( &attributes, policy_alg );
+    psa_set_key_type( &attributes, key_type );
 
-    PSA_ASSERT( psa_import_key( handle, key_type,
+    PSA_ASSERT( psa_import_key( &attributes, &handle,
                                 key_data->x, key_data->len ) );
 
-    PSA_ASSERT( psa_get_key_information( handle,
-                                         NULL,
-                                         &key_bits ) );
+    PSA_ASSERT( psa_get_key_attributes( handle, &attributes ) );
+    key_bits = psa_get_key_bits( &attributes );
     buffer_length = PSA_ASYMMETRIC_ENCRYPT_OUTPUT_SIZE( key_type, key_bits,
                                                         exercise_alg );
     ASSERT_ALLOC( buffer, buffer_length );
@@ -1871,6 +1743,7 @@
 
 exit:
     psa_destroy_key( handle );
+    psa_reset_key_attributes( &attributes );
     mbedtls_psa_crypto_free( );
     mbedtls_free( buffer );
 }
@@ -1885,7 +1758,7 @@
                                       int payload_length_arg )
 {
     psa_key_handle_t handle = 0;
-    psa_key_policy_t policy = PSA_KEY_POLICY_INIT;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
     psa_status_t status;
     unsigned char payload[PSA_HASH_MAX_SIZE] = {1};
     /* If `payload_length_arg > 0`, `exercise_alg` is supposed to be
@@ -1899,11 +1772,11 @@
 
     PSA_ASSERT( psa_crypto_init( ) );
 
-    PSA_ASSERT( psa_allocate_key( &handle ) );
-    psa_key_policy_set_usage( &policy, policy_usage, policy_alg );
-    PSA_ASSERT( psa_set_key_policy( handle, &policy ) );
+    psa_set_key_usage_flags( &attributes, policy_usage );
+    psa_set_key_algorithm( &attributes, policy_alg );
+    psa_set_key_type( &attributes, key_type );
 
-    PSA_ASSERT( psa_import_key( handle, key_type,
+    PSA_ASSERT( psa_import_key( &attributes, &handle,
                                 key_data->x, key_data->len ) );
 
     status = psa_asymmetric_sign( handle, exercise_alg,
@@ -1938,17 +1811,17 @@
                         int exercise_alg )
 {
     psa_key_handle_t handle = 0;
-    psa_key_policy_t policy = PSA_KEY_POLICY_INIT;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
     psa_crypto_generator_t generator = PSA_CRYPTO_GENERATOR_INIT;
     psa_status_t status;
 
     PSA_ASSERT( psa_crypto_init( ) );
 
-    PSA_ASSERT( psa_allocate_key( &handle ) );
-    psa_key_policy_set_usage( &policy, policy_usage, policy_alg );
-    PSA_ASSERT( psa_set_key_policy( handle, &policy ) );
+    psa_set_key_usage_flags( &attributes, policy_usage );
+    psa_set_key_algorithm( &attributes, policy_alg );
+    psa_set_key_type( &attributes, key_type );
 
-    PSA_ASSERT( psa_import_key( handle, key_type,
+    PSA_ASSERT( psa_import_key( &attributes, &handle,
                                 key_data->x, key_data->len ) );
 
     status = psa_key_derivation( &generator, handle,
@@ -1977,18 +1850,18 @@
                            int exercise_alg )
 {
     psa_key_handle_t handle = 0;
-    psa_key_policy_t policy = PSA_KEY_POLICY_INIT;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
     psa_key_type_t key_type = key_type_arg;
     psa_crypto_generator_t generator = PSA_CRYPTO_GENERATOR_INIT;
     psa_status_t status;
 
     PSA_ASSERT( psa_crypto_init( ) );
 
-    PSA_ASSERT( psa_allocate_key( &handle ) );
-    psa_key_policy_set_usage( &policy, policy_usage, policy_alg );
-    PSA_ASSERT( psa_set_key_policy( handle, &policy ) );
+    psa_set_key_usage_flags( &attributes, policy_usage );
+    psa_set_key_algorithm( &attributes, policy_alg );
+    psa_set_key_type( &attributes, key_type );
 
-    PSA_ASSERT( psa_import_key( handle, key_type,
+    PSA_ASSERT( psa_import_key( &attributes, &handle,
                                 key_data->x, key_data->len ) );
 
     PSA_ASSERT( psa_key_derivation_setup( &generator, exercise_alg ) );
@@ -2015,18 +1888,18 @@
                                int exercise_alg )
 {
     psa_key_handle_t handle = 0;
-    psa_key_policy_t policy = PSA_KEY_POLICY_INIT;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
     psa_key_type_t key_type = key_type_arg;
     psa_crypto_generator_t generator = PSA_CRYPTO_GENERATOR_INIT;
     psa_status_t status;
 
     PSA_ASSERT( psa_crypto_init( ) );
 
-    PSA_ASSERT( psa_allocate_key( &handle ) );
-    psa_key_policy_set_usage( &policy, policy_usage, policy_alg );
-    PSA_ASSERT( psa_set_key_policy( handle, &policy ) );
+    psa_set_key_usage_flags( &attributes, policy_usage );
+    psa_set_key_algorithm( &attributes, policy_alg );
+    psa_set_key_type( &attributes, key_type );
 
-    PSA_ASSERT( psa_import_key( handle, key_type,
+    PSA_ASSERT( psa_import_key( &attributes, &handle,
                                 key_data->x, key_data->len ) );
 
     status = raw_key_agreement_with_self( exercise_alg, handle );
@@ -2045,69 +1918,61 @@
 /* END_CASE */
 
 /* BEGIN_CASE */
-void copy_key_policy( int source_usage_arg, int source_alg_arg,
-                      int type_arg, data_t *material,
-                      int target_usage_arg, int target_alg_arg,
-                      int constraint_usage_arg, int constraint_alg_arg,
-                      int expected_usage_arg, int expected_alg_arg )
+void copy_key( int source_usage_arg, int source_alg_arg,
+               int type_arg, data_t *material,
+               int copy_attributes,
+               int target_usage_arg, int target_alg_arg,
+               int expected_status_arg,
+               int expected_usage_arg, int expected_alg_arg )
 {
-    psa_key_usage_t source_usage = source_usage_arg;
-    psa_algorithm_t source_alg = source_alg_arg;
-    psa_key_handle_t source_handle = 0;
-    psa_key_policy_t source_policy = PSA_KEY_POLICY_INIT;
-    psa_key_type_t source_type = type_arg;
-    size_t source_bits;
-    psa_key_usage_t target_usage = target_usage_arg;
-    psa_algorithm_t target_alg = target_alg_arg;
-    psa_key_handle_t target_handle = 0;
-    psa_key_policy_t target_policy = PSA_KEY_POLICY_INIT;
-    psa_key_type_t target_type;
-    size_t target_bits;
-    psa_key_usage_t constraint_usage = constraint_usage_arg;
-    psa_algorithm_t constraint_alg = constraint_alg_arg;
-    psa_key_policy_t constraint = PSA_KEY_POLICY_INIT;
-    psa_key_policy_t *p_constraint = NULL;
+    psa_key_attributes_t source_attributes = PSA_KEY_ATTRIBUTES_INIT;
+    psa_key_attributes_t target_attributes = PSA_KEY_ATTRIBUTES_INIT;
     psa_key_usage_t expected_usage = expected_usage_arg;
     psa_algorithm_t expected_alg = expected_alg_arg;
+    psa_key_handle_t source_handle = 0;
+    psa_key_handle_t target_handle = 0;
     uint8_t *export_buffer = NULL;
 
-    if( constraint_usage_arg != -1 )
-    {
-        p_constraint = &constraint;
-        psa_key_policy_set_usage( p_constraint,
-                                  constraint_usage, constraint_alg );
-    }
-
     PSA_ASSERT( psa_crypto_init( ) );
 
-    /* Populate the source slot. */
-    PSA_ASSERT( psa_allocate_key( &source_handle ) );
-    psa_key_policy_set_usage( &source_policy, source_usage, source_alg );
-    PSA_ASSERT( psa_set_key_policy( source_handle, &source_policy ) );
-    PSA_ASSERT( psa_import_key( source_handle, source_type,
+    /* Prepare the source key. */
+    psa_set_key_usage_flags( &source_attributes, source_usage_arg );
+    psa_set_key_algorithm( &source_attributes, source_alg_arg );
+    psa_set_key_type( &source_attributes, type_arg );
+    PSA_ASSERT( psa_import_key( &source_attributes, &source_handle,
                                 material->x, material->len ) );
-    PSA_ASSERT( psa_get_key_information( source_handle, NULL, &source_bits ) );
+    /* Retrieve the key size. */
+    PSA_ASSERT( psa_get_key_attributes( source_handle, &source_attributes ) );
 
-    /* Prepare the target slot. */
-    PSA_ASSERT( psa_allocate_key( &target_handle ) );
-    psa_key_policy_set_usage( &target_policy, target_usage, target_alg );
-    PSA_ASSERT( psa_set_key_policy( target_handle, &target_policy ) );
-    target_policy = psa_key_policy_init();
+    /* Prepare the target attributes. */
+    if( copy_attributes )
+        target_attributes = source_attributes;
+    if( target_usage_arg != -1 )
+        psa_set_key_usage_flags( &target_attributes, target_usage_arg );
+    if( target_alg_arg != -1 )
+        psa_set_key_algorithm( &target_attributes, target_alg_arg );
 
     /* Copy the key. */
-    PSA_ASSERT( psa_copy_key( source_handle, target_handle, p_constraint ) );
+    TEST_EQUAL( psa_copy_key( source_handle,
+                              &target_attributes, &target_handle ),
+                expected_status_arg );
+    if( expected_status_arg != PSA_SUCCESS )
+    {
+        TEST_EQUAL( target_handle, 0 );
+        goto exit;
+    }
 
     /* Destroy the source to ensure that this doesn't affect the target. */
     PSA_ASSERT( psa_destroy_key( source_handle ) );
 
     /* Test that the target slot has the expected content and policy. */
-    PSA_ASSERT( psa_get_key_information( target_handle,
-                                         &target_type, &target_bits ) );
-    TEST_EQUAL( source_type, target_type );
-    TEST_EQUAL( source_bits, target_bits );
-    PSA_ASSERT( psa_get_key_policy( target_handle, &target_policy ) );
-    TEST_EQUAL( expected_usage, psa_key_policy_get_usage( &target_policy ) );
-    TEST_EQUAL( expected_alg, psa_key_policy_get_algorithm( &target_policy ) );
+    PSA_ASSERT( psa_get_key_attributes( target_handle, &target_attributes ) );
+    TEST_EQUAL( psa_get_key_type( &source_attributes ),
+                psa_get_key_type( &target_attributes ) );
+    TEST_EQUAL( psa_get_key_bits( &source_attributes ),
+                psa_get_key_bits( &target_attributes ) );
+    TEST_EQUAL( expected_usage, psa_get_key_usage_flags( &target_attributes ) );
+    TEST_EQUAL( expected_alg, psa_get_key_algorithm( &target_attributes ) );
     if( expected_usage & PSA_KEY_USAGE_EXPORT )
     {
         size_t length;
@@ -2123,81 +1988,14 @@
     PSA_ASSERT( psa_close_key( target_handle ) );
 
 exit:
+    psa_reset_key_attributes( &source_attributes );
+    psa_reset_key_attributes( &target_attributes );
     mbedtls_psa_crypto_free( );
     mbedtls_free( export_buffer );
 }
 /* END_CASE */
 
 /* BEGIN_CASE */
-void copy_fail( int source_usage_arg, int source_alg_arg,
-                int type_arg, data_t *material,
-                int target_usage_arg, int target_alg_arg,
-                int constraint_usage_arg, int constraint_alg_arg,
-                int expected_status_arg )
-{
-    /* Test copy failure into an empty slot. There is a test for copy failure
-     * into an occupied slot in
-     * test_suite_psa_crypto_slot_management.function. */
-
-    psa_key_usage_t source_usage = source_usage_arg;
-    psa_algorithm_t source_alg = source_alg_arg;
-    psa_key_handle_t source_handle = 0;
-    psa_key_policy_t source_policy = PSA_KEY_POLICY_INIT;
-    psa_key_type_t source_type = type_arg;
-    size_t source_bits;
-    psa_key_usage_t target_usage = target_usage_arg;
-    psa_algorithm_t target_alg = target_alg_arg;
-    psa_key_handle_t target_handle = 0;
-    psa_key_policy_t target_policy = PSA_KEY_POLICY_INIT;
-    psa_key_type_t target_type;
-    size_t target_bits;
-    psa_key_usage_t constraint_usage = constraint_usage_arg;
-    psa_algorithm_t constraint_alg = constraint_alg_arg;
-    psa_key_policy_t constraint = PSA_KEY_POLICY_INIT;
-    psa_key_policy_t *p_constraint = NULL;
-    psa_status_t expected_status = expected_status_arg;
-
-    if( constraint_usage_arg != -1 )
-    {
-        p_constraint = &constraint;
-        psa_key_policy_set_usage( p_constraint,
-                                  constraint_usage, constraint_alg );
-    }
-
-    PSA_ASSERT( psa_crypto_init( ) );
-
-    /* Populate the source slot. */
-    PSA_ASSERT( psa_allocate_key( &source_handle ) );
-    psa_key_policy_set_usage( &source_policy, source_usage, source_alg );
-    PSA_ASSERT( psa_set_key_policy( source_handle, &source_policy ) );
-    PSA_ASSERT( psa_import_key( source_handle, source_type,
-                                material->x, material->len ) );
-    PSA_ASSERT( psa_get_key_information( source_handle, NULL, &source_bits ) );
-
-    /* Prepare the target slot. */
-    PSA_ASSERT( psa_allocate_key( &target_handle ) );
-    psa_key_policy_set_usage( &target_policy, target_usage, target_alg );
-    PSA_ASSERT( psa_set_key_policy( target_handle, &target_policy ) );
-    target_policy = psa_key_policy_init();
-
-    /* Copy the key. */
-    TEST_EQUAL( psa_copy_key( source_handle, target_handle, p_constraint ),
-                expected_status );
-
-    /* Test that the target slot is unaffected. */
-    TEST_EQUAL( psa_get_key_information( target_handle,
-                                         &target_type, &target_bits ),
-                PSA_ERROR_DOES_NOT_EXIST );
-    PSA_ASSERT( psa_get_key_policy( target_handle, &target_policy ) );
-    TEST_EQUAL( target_usage, psa_key_policy_get_usage( &target_policy ) );
-    TEST_EQUAL( target_alg, psa_key_policy_get_algorithm( &target_policy ) );
-
-exit:
-    mbedtls_psa_crypto_free( );
-}
-/* END_CASE */
-
-/* BEGIN_CASE */
 void hash_operation_init( )
 {
     const uint8_t input[1] = { 0 };
@@ -2571,7 +2369,7 @@
         0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
         0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
         0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa };
-    psa_key_policy_t policy = PSA_KEY_POLICY_INIT;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
     psa_mac_operation_t operation = PSA_MAC_OPERATION_INIT;
     uint8_t sign_mac[PSA_MAC_MAX_SIZE + 10] = { 0 };
     size_t sign_mac_length = 0;
@@ -2582,13 +2380,11 @@
         0x2c, 0xf9, 0x18, 0xca, 0x59, 0x7e, 0x5d, 0xf6 };
 
     PSA_ASSERT( psa_crypto_init( ) );
-    PSA_ASSERT( psa_allocate_key( &handle ) );
-    psa_key_policy_set_usage( &policy,
-                              PSA_KEY_USAGE_SIGN | PSA_KEY_USAGE_VERIFY,
-                              alg );
-    PSA_ASSERT( psa_set_key_policy( handle, &policy ) );
+    psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_SIGN | PSA_KEY_USAGE_VERIFY );
+    psa_set_key_algorithm( &attributes, alg );
+    psa_set_key_type( &attributes, key_type );
 
-    PSA_ASSERT( psa_import_key( handle, key_type,
+    PSA_ASSERT( psa_import_key( &attributes, &handle,
                                 key, sizeof(key) ) );
 
     /* Call update without calling setup beforehand. */
@@ -2696,7 +2492,7 @@
     psa_key_type_t key_type = key_type_arg;
     psa_algorithm_t alg = alg_arg;
     psa_mac_operation_t operation = PSA_MAC_OPERATION_INIT;
-    psa_key_policy_t policy = PSA_KEY_POLICY_INIT;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
     /* Leave a little extra room in the output buffer. At the end of the
      * test, we'll check that the implementation didn't overwrite onto
      * this extra room. */
@@ -2711,11 +2507,11 @@
 
     PSA_ASSERT( psa_crypto_init( ) );
 
-    PSA_ASSERT( psa_allocate_key( &handle ) );
-    psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_SIGN, alg );
-    PSA_ASSERT( psa_set_key_policy( handle, &policy ) );
+    psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_SIGN );
+    psa_set_key_algorithm( &attributes, alg );
+    psa_set_key_type( &attributes, key_type );
 
-    PSA_ASSERT( psa_import_key( handle, key_type,
+    PSA_ASSERT( psa_import_key( &attributes, &handle,
                                 key->x, key->len ) );
 
     /* Calculate the MAC. */
@@ -2752,17 +2548,17 @@
     psa_key_type_t key_type = key_type_arg;
     psa_algorithm_t alg = alg_arg;
     psa_mac_operation_t operation = PSA_MAC_OPERATION_INIT;
-    psa_key_policy_t policy = PSA_KEY_POLICY_INIT;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
 
     TEST_ASSERT( expected_mac->len <= PSA_MAC_MAX_SIZE );
 
     PSA_ASSERT( psa_crypto_init( ) );
 
-    PSA_ASSERT( psa_allocate_key( &handle ) );
-    psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_VERIFY, alg );
-    PSA_ASSERT( psa_set_key_policy( handle, &policy ) );
+    psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_VERIFY );
+    psa_set_key_algorithm( &attributes, alg );
+    psa_set_key_type( &attributes, key_type );
 
-    PSA_ASSERT( psa_import_key( handle, key_type,
+    PSA_ASSERT( psa_import_key( &attributes, &handle,
                                 key->x, key->len ) );
 
     PSA_ASSERT( psa_mac_verify_setup( &operation,
@@ -2864,7 +2660,7 @@
     psa_key_handle_t handle = 0;
     psa_key_type_t key_type = PSA_KEY_TYPE_AES;
     psa_algorithm_t alg = PSA_ALG_CBC_PKCS7;
-    psa_key_policy_t policy = PSA_KEY_POLICY_INIT;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
     psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT;
     unsigned char iv[PSA_BLOCK_CIPHER_BLOCK_SIZE(PSA_KEY_TYPE_AES)] = { 0 };
     const uint8_t key[] = {
@@ -2877,12 +2673,10 @@
     size_t length = 0;
 
     PSA_ASSERT( psa_crypto_init( ) );
-    PSA_ASSERT( psa_allocate_key( &handle ) );
-    psa_key_policy_set_usage( &policy,
-                              PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT,
-                              alg );
-    PSA_ASSERT( psa_set_key_policy( handle, &policy ) );
-    PSA_ASSERT( psa_import_key( handle, key_type,
+    psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT );
+    psa_set_key_algorithm( &attributes, alg );
+    psa_set_key_type( &attributes, key_type );
+    PSA_ASSERT( psa_import_key( &attributes, &handle,
                                 key, sizeof(key) ) );
 
 
@@ -3029,18 +2823,18 @@
     size_t function_output_length = 0;
     size_t total_output_length = 0;
     psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT;
-    psa_key_policy_t policy = PSA_KEY_POLICY_INIT;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
 
     iv_size = PSA_BLOCK_CIPHER_BLOCK_SIZE( key_type );
     memset( iv, 0x2a, iv_size );
 
     PSA_ASSERT( psa_crypto_init( ) );
 
-    PSA_ASSERT( psa_allocate_key( &handle ) );
-    psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_ENCRYPT, alg );
-    PSA_ASSERT( psa_set_key_policy( handle, &policy ) );
+    psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_ENCRYPT );
+    psa_set_key_algorithm( &attributes, alg );
+    psa_set_key_type( &attributes, key_type );
 
-    PSA_ASSERT( psa_import_key( handle, key_type,
+    PSA_ASSERT( psa_import_key( &attributes, &handle,
                                 key->x, key->len ) );
 
     PSA_ASSERT( psa_cipher_encrypt_setup( &operation,
@@ -3099,18 +2893,18 @@
     size_t function_output_length = 0;
     size_t total_output_length = 0;
     psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT;
-    psa_key_policy_t policy = PSA_KEY_POLICY_INIT;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
 
     iv_size = PSA_BLOCK_CIPHER_BLOCK_SIZE( key_type );
     memset( iv, 0x2a, iv_size );
 
     PSA_ASSERT( psa_crypto_init( ) );
 
-    PSA_ASSERT( psa_allocate_key( &handle ) );
-    psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_ENCRYPT, alg );
-    PSA_ASSERT( psa_set_key_policy( handle, &policy ) );
+    psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_ENCRYPT );
+    psa_set_key_algorithm( &attributes, alg );
+    psa_set_key_type( &attributes, key_type );
 
-    PSA_ASSERT( psa_import_key( handle, key_type,
+    PSA_ASSERT( psa_import_key( &attributes, &handle,
                                 key->x, key->len ) );
 
     PSA_ASSERT( psa_cipher_encrypt_setup( &operation,
@@ -3175,18 +2969,18 @@
     size_t function_output_length = 0;
     size_t total_output_length = 0;
     psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT;
-    psa_key_policy_t policy = PSA_KEY_POLICY_INIT;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
 
     iv_size = PSA_BLOCK_CIPHER_BLOCK_SIZE( key_type );
     memset( iv, 0x2a, iv_size );
 
     PSA_ASSERT( psa_crypto_init( ) );
 
-    PSA_ASSERT( psa_allocate_key( &handle ) );
-    psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_DECRYPT, alg );
-    PSA_ASSERT( psa_set_key_policy( handle, &policy ) );
+    psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_DECRYPT );
+    psa_set_key_algorithm( &attributes, alg );
+    psa_set_key_type( &attributes, key_type );
 
-    PSA_ASSERT( psa_import_key( handle, key_type,
+    PSA_ASSERT( psa_import_key( &attributes, &handle,
                                 key->x, key->len ) );
 
     PSA_ASSERT( psa_cipher_decrypt_setup( &operation,
@@ -3249,18 +3043,18 @@
     size_t function_output_length = 0;
     size_t total_output_length = 0;
     psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT;
-    psa_key_policy_t policy = PSA_KEY_POLICY_INIT;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
 
     iv_size = PSA_BLOCK_CIPHER_BLOCK_SIZE( key_type );
     memset( iv, 0x2a, iv_size );
 
     PSA_ASSERT( psa_crypto_init( ) );
 
-    PSA_ASSERT( psa_allocate_key( &handle ) );
-    psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_DECRYPT, alg );
-    PSA_ASSERT( psa_set_key_policy( handle, &policy ) );
+    psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_DECRYPT );
+    psa_set_key_algorithm( &attributes, alg );
+    psa_set_key_type( &attributes, key_type );
 
-    PSA_ASSERT( psa_import_key( handle, key_type,
+    PSA_ASSERT( psa_import_key( &attributes, &handle,
                                 key->x, key->len ) );
 
     PSA_ASSERT( psa_cipher_decrypt_setup( &operation,
@@ -3319,15 +3113,15 @@
     size_t function_output_length = 0;
     psa_cipher_operation_t operation1 = PSA_CIPHER_OPERATION_INIT;
     psa_cipher_operation_t operation2 = PSA_CIPHER_OPERATION_INIT;
-    psa_key_policy_t policy = PSA_KEY_POLICY_INIT;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
 
     PSA_ASSERT( psa_crypto_init( ) );
 
-    PSA_ASSERT( psa_allocate_key( &handle ) );
-    psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT, alg );
-    PSA_ASSERT( psa_set_key_policy( handle, &policy ) );
+    psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT );
+    psa_set_key_algorithm( &attributes, alg );
+    psa_set_key_type( &attributes, key_type );
 
-    PSA_ASSERT( psa_import_key( handle, key_type,
+    PSA_ASSERT( psa_import_key( &attributes, &handle,
                                 key->x, key->len ) );
 
     PSA_ASSERT( psa_cipher_encrypt_setup( &operation1,
@@ -3405,15 +3199,15 @@
     size_t function_output_length;
     psa_cipher_operation_t operation1 = PSA_CIPHER_OPERATION_INIT;
     psa_cipher_operation_t operation2 = PSA_CIPHER_OPERATION_INIT;
-    psa_key_policy_t policy = PSA_KEY_POLICY_INIT;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
 
     PSA_ASSERT( psa_crypto_init( ) );
 
-    PSA_ASSERT( psa_allocate_key( &handle ) );
-    psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT, alg );
-    PSA_ASSERT( psa_set_key_policy( handle, &policy ) );
+    psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT );
+    psa_set_key_algorithm( &attributes, alg );
+    psa_set_key_type( &attributes, key_type );
 
-    PSA_ASSERT( psa_import_key( handle, key_type,
+    PSA_ASSERT( psa_import_key( &attributes, &handle,
                                 key->x, key->len ) );
 
     PSA_ASSERT( psa_cipher_encrypt_setup( &operation1,
@@ -3504,20 +3298,18 @@
     size_t output_length2 = 0;
     size_t tag_length = 16;
     psa_status_t expected_result = expected_result_arg;
-    psa_key_policy_t policy = PSA_KEY_POLICY_INIT;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
 
     output_size = input_data->len + tag_length;
     ASSERT_ALLOC( output_data, output_size );
 
     PSA_ASSERT( psa_crypto_init( ) );
 
-    PSA_ASSERT( psa_allocate_key( &handle ) );
-    psa_key_policy_set_usage( &policy,
-                              PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT,
-                              alg );
-    PSA_ASSERT( psa_set_key_policy( handle, &policy ) );
+    psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT );
+    psa_set_key_algorithm( &attributes, alg );
+    psa_set_key_type( &attributes, key_type );
 
-    PSA_ASSERT( psa_import_key( handle, key_type,
+    PSA_ASSERT( psa_import_key( &attributes, &handle,
                                 key_data->x, key_data->len ) );
 
     TEST_EQUAL( psa_aead_encrypt( handle, alg,
@@ -3569,20 +3361,19 @@
     size_t output_size = 0;
     size_t output_length = 0;
     size_t tag_length = 16;
-    psa_key_policy_t policy = PSA_KEY_POLICY_INIT;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
 
     output_size = input_data->len + tag_length;
     ASSERT_ALLOC( output_data, output_size );
 
     PSA_ASSERT( psa_crypto_init( ) );
 
-    PSA_ASSERT( psa_allocate_key( &handle ) );
-    psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_ENCRYPT , alg );
-    PSA_ASSERT( psa_set_key_policy( handle, &policy ) );
+    psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_ENCRYPT  );
+    psa_set_key_algorithm( &attributes, alg );
+    psa_set_key_type( &attributes, key_type );
 
-    PSA_ASSERT( psa_import_key( handle, key_type,
-                                key_data->x,
-                                key_data->len ) );
+    PSA_ASSERT( psa_import_key( &attributes, &handle,
+                                key_data->x, key_data->len ) );
 
     PSA_ASSERT( psa_aead_encrypt( handle, alg,
                                   nonce->x, nonce->len,
@@ -3617,7 +3408,7 @@
     size_t output_size = 0;
     size_t output_length = 0;
     size_t tag_length = 16;
-    psa_key_policy_t policy = PSA_KEY_POLICY_INIT;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
     psa_status_t expected_result = expected_result_arg;
 
     output_size = input_data->len + tag_length;
@@ -3625,13 +3416,12 @@
 
     PSA_ASSERT( psa_crypto_init( ) );
 
-    PSA_ASSERT( psa_allocate_key( &handle ) );
-    psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_DECRYPT , alg );
-    PSA_ASSERT( psa_set_key_policy( handle, &policy ) );
+    psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_DECRYPT  );
+    psa_set_key_algorithm( &attributes, alg );
+    psa_set_key_type( &attributes, key_type );
 
-    PSA_ASSERT( psa_import_key( handle, key_type,
-                                key_data->x,
-                                key_data->len ) );
+    PSA_ASSERT( psa_import_key( &attributes, &handle,
+                                key_data->x, key_data->len ) );
 
     TEST_EQUAL( psa_aead_decrypt( handle, alg,
                                   nonce->x, nonce->len,
@@ -3680,20 +3470,18 @@
     unsigned char *signature = NULL;
     size_t signature_size;
     size_t signature_length = 0xdeadbeef;
-    psa_key_policy_t policy = PSA_KEY_POLICY_INIT;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
 
     PSA_ASSERT( psa_crypto_init( ) );
 
-    PSA_ASSERT( psa_allocate_key( &handle ) );
-    psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_SIGN, alg );
-    PSA_ASSERT( psa_set_key_policy( handle, &policy ) );
+    psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_SIGN );
+    psa_set_key_algorithm( &attributes, alg );
+    psa_set_key_type( &attributes, key_type );
 
-    PSA_ASSERT( psa_import_key( handle, key_type,
-                                key_data->x,
-                                key_data->len ) );
-    PSA_ASSERT( psa_get_key_information( handle,
-                                         NULL,
-                                         &key_bits ) );
+    PSA_ASSERT( psa_import_key( &attributes, &handle,
+                                key_data->x, key_data->len ) );
+    PSA_ASSERT( psa_get_key_attributes( handle, &attributes ) );
+    key_bits = psa_get_key_bits( &attributes );
 
     /* Allocate a buffer which has the size advertized by the
      * library. */
@@ -3713,6 +3501,7 @@
                     signature, signature_length );
 
 exit:
+    psa_reset_key_attributes( &attributes );
     psa_destroy_key( handle );
     mbedtls_free( signature );
     mbedtls_psa_crypto_free( );
@@ -3732,19 +3521,18 @@
     psa_status_t expected_status = expected_status_arg;
     unsigned char *signature = NULL;
     size_t signature_length = 0xdeadbeef;
-    psa_key_policy_t policy = PSA_KEY_POLICY_INIT;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
 
     ASSERT_ALLOC( signature, signature_size );
 
     PSA_ASSERT( psa_crypto_init( ) );
 
-    PSA_ASSERT( psa_allocate_key( &handle ) );
-    psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_SIGN, alg );
-    PSA_ASSERT( psa_set_key_policy( handle, &policy ) );
+    psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_SIGN );
+    psa_set_key_algorithm( &attributes, alg );
+    psa_set_key_type( &attributes, key_type );
 
-    PSA_ASSERT( psa_import_key( handle, key_type,
-                                key_data->x,
-                                key_data->len ) );
+    PSA_ASSERT( psa_import_key( &attributes, &handle,
+                                key_data->x, key_data->len ) );
 
     actual_status = psa_asymmetric_sign( handle, alg,
                                          input_data->x, input_data->len,
@@ -3758,6 +3546,7 @@
     TEST_ASSERT( signature_length <= signature_size );
 
 exit:
+    psa_reset_key_attributes( &attributes );
     psa_destroy_key( handle );
     mbedtls_free( signature );
     mbedtls_psa_crypto_free( );
@@ -3775,22 +3564,18 @@
     unsigned char *signature = NULL;
     size_t signature_size;
     size_t signature_length = 0xdeadbeef;
-    psa_key_policy_t policy = PSA_KEY_POLICY_INIT;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
 
     PSA_ASSERT( psa_crypto_init( ) );
 
-    PSA_ASSERT( psa_allocate_key( &handle ) );
-    psa_key_policy_set_usage( &policy,
-                              PSA_KEY_USAGE_SIGN | PSA_KEY_USAGE_VERIFY,
-                              alg );
-    PSA_ASSERT( psa_set_key_policy( handle, &policy ) );
+    psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_SIGN | PSA_KEY_USAGE_VERIFY );
+    psa_set_key_algorithm( &attributes, alg );
+    psa_set_key_type( &attributes, key_type );
 
-    PSA_ASSERT( psa_import_key( handle, key_type,
-                                key_data->x,
-                                key_data->len ) );
-    PSA_ASSERT( psa_get_key_information( handle,
-                                         NULL,
-                                         &key_bits ) );
+    PSA_ASSERT( psa_import_key( &attributes, &handle,
+                                key_data->x, key_data->len ) );
+    PSA_ASSERT( psa_get_key_attributes( handle, &attributes ) );
+    key_bits = psa_get_key_bits( &attributes );
 
     /* Allocate a buffer which has the size advertized by the
      * library. */
@@ -3828,6 +3613,7 @@
     }
 
 exit:
+    psa_reset_key_attributes( &attributes );
     psa_destroy_key( handle );
     mbedtls_free( signature );
     mbedtls_psa_crypto_free( );
@@ -3842,25 +3628,25 @@
     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 = PSA_KEY_POLICY_INIT;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
 
     TEST_ASSERT( signature_data->len <= PSA_ASYMMETRIC_SIGNATURE_MAX_SIZE );
 
     PSA_ASSERT( psa_crypto_init( ) );
 
-    PSA_ASSERT( psa_allocate_key( &handle ) );
-    psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_VERIFY, alg );
-    PSA_ASSERT( psa_set_key_policy( handle, &policy ) );
+    psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_VERIFY );
+    psa_set_key_algorithm( &attributes, alg );
+    psa_set_key_type( &attributes, key_type );
 
-    PSA_ASSERT( psa_import_key( handle, key_type,
-                                key_data->x,
-                                key_data->len ) );
+    PSA_ASSERT( psa_import_key( &attributes, &handle,
+                                key_data->x, key_data->len ) );
 
     PSA_ASSERT( psa_asymmetric_verify( handle, alg,
                                        hash_data->x, hash_data->len,
                                        signature_data->x,
                                        signature_data->len ) );
 exit:
+    psa_reset_key_attributes( &attributes );
     psa_destroy_key( handle );
     mbedtls_psa_crypto_free( );
 }
@@ -3877,17 +3663,16 @@
     psa_algorithm_t alg = alg_arg;
     psa_status_t actual_status;
     psa_status_t expected_status = expected_status_arg;
-    psa_key_policy_t policy = PSA_KEY_POLICY_INIT;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
 
     PSA_ASSERT( psa_crypto_init( ) );
 
-    PSA_ASSERT( psa_allocate_key( &handle ) );
-    psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_VERIFY, alg );
-    PSA_ASSERT( psa_set_key_policy( handle, &policy ) );
+    psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_VERIFY );
+    psa_set_key_algorithm( &attributes, alg );
+    psa_set_key_type( &attributes, key_type );
 
-    PSA_ASSERT( psa_import_key( handle, key_type,
-                                key_data->x,
-                                key_data->len ) );
+    PSA_ASSERT( psa_import_key( &attributes, &handle,
+                                key_data->x, key_data->len ) );
 
     actual_status = psa_asymmetric_verify( handle, alg,
                                            hash_data->x, hash_data->len,
@@ -3897,6 +3682,7 @@
     TEST_EQUAL( actual_status, expected_status );
 
 exit:
+    psa_reset_key_attributes( &attributes );
     psa_destroy_key( handle );
     mbedtls_psa_crypto_free( );
 }
@@ -3921,22 +3707,20 @@
     size_t output_length = ~0;
     psa_status_t actual_status;
     psa_status_t expected_status = expected_status_arg;
-    psa_key_policy_t policy = PSA_KEY_POLICY_INIT;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
 
     PSA_ASSERT( psa_crypto_init( ) );
 
     /* Import the key */
-    PSA_ASSERT( psa_allocate_key( &handle ) );
-    psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_ENCRYPT, alg );
-    PSA_ASSERT( psa_set_key_policy( handle, &policy ) );
-    PSA_ASSERT( psa_import_key( handle, key_type,
-                                key_data->x,
-                                key_data->len ) );
+    psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_ENCRYPT );
+    psa_set_key_algorithm( &attributes, alg );
+    psa_set_key_type( &attributes, key_type );
+    PSA_ASSERT( psa_import_key( &attributes, &handle,
+                                key_data->x, key_data->len ) );
 
     /* Determine the maximum output length */
-    PSA_ASSERT( psa_get_key_information( handle,
-                                         NULL,
-                                         &key_bits ) );
+    PSA_ASSERT( psa_get_key_attributes( handle, &attributes ) );
+    key_bits = psa_get_key_bits( &attributes );
     output_size = PSA_ASYMMETRIC_ENCRYPT_OUTPUT_SIZE( key_type, key_bits, alg );
     ASSERT_ALLOC( output, output_size );
 
@@ -3966,6 +3750,7 @@
     }
 
 exit:
+    psa_reset_key_attributes( &attributes );
     psa_destroy_key( handle );
     mbedtls_free( output );
     mbedtls_psa_crypto_free( );
@@ -3989,24 +3774,20 @@
     unsigned char *output2 = NULL;
     size_t output2_size;
     size_t output2_length = ~0;
-    psa_key_policy_t policy = PSA_KEY_POLICY_INIT;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
 
     PSA_ASSERT( psa_crypto_init( ) );
 
-    PSA_ASSERT( psa_allocate_key( &handle ) );
-    psa_key_policy_set_usage( &policy,
-                              PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT,
-                              alg );
-    PSA_ASSERT( psa_set_key_policy( handle, &policy ) );
+    psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT );
+    psa_set_key_algorithm( &attributes, alg );
+    psa_set_key_type( &attributes, key_type );
 
-    PSA_ASSERT( psa_import_key( handle, key_type,
-                                key_data->x,
-                                key_data->len ) );
+    PSA_ASSERT( psa_import_key( &attributes, &handle,
+                                key_data->x, key_data->len ) );
 
     /* Determine the maximum ciphertext length */
-    PSA_ASSERT( psa_get_key_information( handle,
-                                         NULL,
-                                         &key_bits ) );
+    PSA_ASSERT( psa_get_key_attributes( handle, &attributes ) );
+    key_bits = psa_get_key_bits( &attributes );
     output_size = PSA_ASYMMETRIC_ENCRYPT_OUTPUT_SIZE( key_type, key_bits, alg );
     ASSERT_ALLOC( output, output_size );
     output2_size = input_data->len;
@@ -4033,6 +3814,7 @@
                     output2, output2_length );
 
 exit:
+    psa_reset_key_attributes( &attributes );
     psa_destroy_key( handle );
     mbedtls_free( output );
     mbedtls_free( output2 );
@@ -4054,20 +3836,19 @@
     unsigned char *output = NULL;
     size_t output_size = 0;
     size_t output_length = ~0;
-    psa_key_policy_t policy = PSA_KEY_POLICY_INIT;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
 
     output_size = expected_data->len;
     ASSERT_ALLOC( output, output_size );
 
     PSA_ASSERT( psa_crypto_init( ) );
 
-    PSA_ASSERT( psa_allocate_key( &handle ) );
-    psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_DECRYPT, alg );
-    PSA_ASSERT( psa_set_key_policy( handle, &policy ) );
+    psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_DECRYPT );
+    psa_set_key_algorithm( &attributes, alg );
+    psa_set_key_type( &attributes, key_type );
 
-    PSA_ASSERT( psa_import_key( handle, key_type,
-                                key_data->x,
-                                key_data->len ) );
+    PSA_ASSERT( psa_import_key( &attributes, &handle,
+                                key_data->x, key_data->len ) );
 
     PSA_ASSERT( psa_asymmetric_decrypt( handle, alg,
                                         input_data->x, input_data->len,
@@ -4096,6 +3877,7 @@
     }
 
 exit:
+    psa_reset_key_attributes( &attributes );
     psa_destroy_key( handle );
     mbedtls_free( output );
     mbedtls_psa_crypto_free( );
@@ -4119,19 +3901,18 @@
     size_t output_length = ~0;
     psa_status_t actual_status;
     psa_status_t expected_status = expected_status_arg;
-    psa_key_policy_t policy = PSA_KEY_POLICY_INIT;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
 
     ASSERT_ALLOC( output, output_size );
 
     PSA_ASSERT( psa_crypto_init( ) );
 
-    PSA_ASSERT( psa_allocate_key( &handle ) );
-    psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_DECRYPT, alg );
-    PSA_ASSERT( psa_set_key_policy( handle, &policy ) );
+    psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_DECRYPT );
+    psa_set_key_algorithm( &attributes, alg );
+    psa_set_key_type( &attributes, key_type );
 
-    PSA_ASSERT( psa_import_key( handle, key_type,
-                                key_data->x,
-                                key_data->len ) );
+    PSA_ASSERT( psa_import_key( &attributes, &handle,
+                                key_data->x, key_data->len ) );
 
     actual_status = psa_asymmetric_decrypt( handle, alg,
                                             input_data->x, input_data->len,
@@ -4158,6 +3939,7 @@
     }
 
 exit:
+    psa_reset_key_attributes( &attributes );
     psa_destroy_key( handle );
     mbedtls_free( output );
     mbedtls_psa_crypto_free( );
@@ -4208,17 +3990,16 @@
     size_t requested_capacity = requested_capacity_arg;
     psa_status_t expected_status = expected_status_arg;
     psa_crypto_generator_t generator = PSA_CRYPTO_GENERATOR_INIT;
-    psa_key_policy_t policy = PSA_KEY_POLICY_INIT;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
 
     PSA_ASSERT( psa_crypto_init( ) );
 
-    PSA_ASSERT( psa_allocate_key( &handle ) );
-    psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_DERIVE, alg );
-    PSA_ASSERT( psa_set_key_policy( handle, &policy ) );
+    psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_DERIVE );
+    psa_set_key_algorithm( &attributes, alg );
+    psa_set_key_type( &attributes, key_type );
 
-    PSA_ASSERT( psa_import_key( handle, key_type,
-                                key_data->x,
-                                key_data->len ) );
+    PSA_ASSERT( psa_import_key( &attributes, &handle,
+                                key_data->x, key_data->len ) );
 
     TEST_EQUAL( psa_key_derivation( &generator, handle, alg,
                                     salt->x, salt->len,
@@ -4245,17 +4026,16 @@
     const uint8_t key_data[22] = { 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
                                    0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
                                    0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b};
-    psa_key_policy_t policy = PSA_KEY_POLICY_INIT;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
 
     PSA_ASSERT( psa_crypto_init( ) );
 
-    PSA_ASSERT( psa_allocate_key( &handle ) );
-    psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_DERIVE, alg );
-    PSA_ASSERT( psa_set_key_policy( handle, &policy ) );
+    psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_DERIVE );
+    psa_set_key_algorithm( &attributes, alg );
+    psa_set_key_type( &attributes, key_type );
 
-    PSA_ASSERT( psa_import_key( handle, key_type,
-                                key_data,
-                                sizeof( key_data ) ) );
+    PSA_ASSERT( psa_import_key( &attributes, &handle,
+                                key_data, sizeof( key_data ) ) );
 
     /* valid key derivation */
     PSA_ASSERT(  psa_key_derivation( &generator, handle, alg,
@@ -4330,7 +4110,7 @@
     uint8_t *output_buffer = NULL;
     size_t expected_capacity;
     size_t current_capacity;
-    psa_key_policy_t policy = PSA_KEY_POLICY_INIT;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
     psa_status_t status;
     unsigned i;
 
@@ -4344,13 +4124,12 @@
     ASSERT_ALLOC( output_buffer, output_buffer_size );
     PSA_ASSERT( psa_crypto_init( ) );
 
-    PSA_ASSERT( psa_allocate_key( &handle ) );
-    psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_DERIVE, alg );
-    PSA_ASSERT( psa_set_key_policy( handle, &policy ) );
+    psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_DERIVE );
+    psa_set_key_algorithm( &attributes, alg );
+    psa_set_key_type( &attributes, PSA_KEY_TYPE_DERIVE );
 
-    PSA_ASSERT( psa_import_key( handle, PSA_KEY_TYPE_DERIVE,
-                                key_data->x,
-                                key_data->len ) );
+    PSA_ASSERT( psa_import_key( &attributes, &handle,
+                                key_data->x, key_data->len ) );
 
     /* Extraction phase. */
     if( PSA_ALG_IS_HKDF( alg ) )
@@ -4437,17 +4216,16 @@
     unsigned char output_buffer[16];
     size_t expected_capacity = requested_capacity;
     size_t current_capacity;
-    psa_key_policy_t policy = PSA_KEY_POLICY_INIT;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
 
     PSA_ASSERT( psa_crypto_init( ) );
 
-    PSA_ASSERT( psa_allocate_key( &handle ) );
-    psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_DERIVE, alg );
-    PSA_ASSERT( psa_set_key_policy( handle, &policy ) );
+    psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_DERIVE );
+    psa_set_key_algorithm( &attributes, alg );
+    psa_set_key_type( &attributes, PSA_KEY_TYPE_DERIVE );
 
-    PSA_ASSERT( psa_import_key( handle, PSA_KEY_TYPE_DERIVE,
-                                key_data->x,
-                                key_data->len ) );
+    PSA_ASSERT( psa_import_key( &attributes, &handle,
+                                key_data->x, key_data->len ) );
 
     /* Extraction phase. */
     if( PSA_ALG_IS_HKDF( alg ) )
@@ -4524,38 +4302,33 @@
     psa_algorithm_t derived_alg = derived_alg_arg;
     size_t capacity = PSA_BITS_TO_BYTES( derived_bits );
     psa_crypto_generator_t generator = PSA_CRYPTO_GENERATOR_INIT;
-    psa_key_policy_t policy = PSA_KEY_POLICY_INIT;
-    psa_key_type_t got_type;
-    size_t got_bits;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    psa_key_attributes_t got_attributes = PSA_KEY_ATTRIBUTES_INIT;
 
     PSA_ASSERT( psa_crypto_init( ) );
 
-    PSA_ASSERT( psa_allocate_key( &base_handle ) );
-    psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_DERIVE, alg );
-    PSA_ASSERT( psa_set_key_policy( base_handle, &policy ) );
-    PSA_ASSERT( psa_import_key( base_handle, PSA_KEY_TYPE_DERIVE,
-                                key_data->x,
-                                key_data->len ) );
+    psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_DERIVE );
+    psa_set_key_algorithm( &attributes, alg );
+    psa_set_key_type( &attributes, PSA_KEY_TYPE_DERIVE );
+    PSA_ASSERT( psa_import_key( &attributes, &base_handle,
+                                key_data->x, key_data->len ) );
 
     /* Derive a key. */
     PSA_ASSERT( psa_key_derivation( &generator, base_handle, alg,
                                     salt->x, salt->len,
                                     label->x, label->len,
                                     capacity ) );
-    PSA_ASSERT( psa_allocate_key( &derived_handle ) );
-    psa_key_policy_set_usage( &policy, derived_usage, derived_alg );
-    PSA_ASSERT( psa_set_key_policy( derived_handle, &policy ) );
-    PSA_ASSERT( psa_generator_import_key( derived_handle,
-                                          derived_type,
-                                          derived_bits,
+    psa_set_key_usage_flags( &attributes, derived_usage );
+    psa_set_key_algorithm( &attributes, derived_alg );
+    psa_set_key_type( &attributes, derived_type );
+    psa_set_key_bits( &attributes, derived_bits );
+    PSA_ASSERT( psa_generator_import_key( &attributes, &derived_handle,
                                           &generator ) );
 
     /* Test the key information */
-    PSA_ASSERT( psa_get_key_information( derived_handle,
-                                         &got_type,
-                                         &got_bits ) );
-    TEST_EQUAL( got_type, derived_type );
-    TEST_EQUAL( got_bits, derived_bits );
+    PSA_ASSERT( psa_get_key_attributes( derived_handle, &got_attributes ) );
+    TEST_EQUAL( psa_get_key_type( &got_attributes ), derived_type );
+    TEST_EQUAL( psa_get_key_bits( &got_attributes ), derived_bits );
 
     /* Exercise the derived key. */
     if( ! exercise_key( derived_handle, derived_usage, derived_alg ) )
@@ -4563,6 +4336,7 @@
 
 exit:
     psa_generator_abort( &generator );
+    psa_reset_key_attributes( &got_attributes );
     psa_destroy_key( base_handle );
     psa_destroy_key( derived_handle );
     mbedtls_psa_crypto_free( );
@@ -4581,25 +4355,24 @@
     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;
     uint8_t *output_buffer = NULL;
     uint8_t *export_buffer = NULL;
-    psa_key_policy_t policy = PSA_KEY_POLICY_INIT;
+    psa_key_attributes_t base_attributes = PSA_KEY_ATTRIBUTES_INIT;
+    psa_key_attributes_t derived_attributes = PSA_KEY_ATTRIBUTES_INIT;
     size_t length;
 
     ASSERT_ALLOC( output_buffer, capacity );
     ASSERT_ALLOC( export_buffer, capacity );
     PSA_ASSERT( psa_crypto_init( ) );
 
-    PSA_ASSERT( psa_allocate_key( &base_handle ) );
-    psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_DERIVE, alg );
-    PSA_ASSERT( psa_set_key_policy( base_handle, &policy ) );
-    PSA_ASSERT( psa_import_key( base_handle, PSA_KEY_TYPE_DERIVE,
-                                key_data->x,
-                                key_data->len ) );
+    psa_set_key_usage_flags( &base_attributes, PSA_KEY_USAGE_DERIVE );
+    psa_set_key_algorithm( &base_attributes, alg );
+    psa_set_key_type( &base_attributes, PSA_KEY_TYPE_DERIVE );
+    PSA_ASSERT( psa_import_key( &base_attributes, &base_handle,
+                                key_data->x, key_data->len ) );
 
     /* Derive some material and output it. */
     PSA_ASSERT( psa_key_derivation( &generator, base_handle, alg,
@@ -4616,23 +4389,19 @@
                                     salt->x, salt->len,
                                     label->x, label->len,
                                     capacity ) );
-    PSA_ASSERT( psa_allocate_key( &derived_handle ) );
-    psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_EXPORT, 0 );
-    PSA_ASSERT( psa_set_key_policy( derived_handle, &policy ) );
-    PSA_ASSERT( psa_generator_import_key( derived_handle,
-                                          PSA_KEY_TYPE_RAW_DATA,
-                                          derived_bits,
+    psa_set_key_usage_flags( &derived_attributes, PSA_KEY_USAGE_EXPORT );
+    psa_set_key_algorithm( &derived_attributes, 0 );
+    psa_set_key_type( &derived_attributes, PSA_KEY_TYPE_RAW_DATA );
+    psa_set_key_bits( &derived_attributes, PSA_BYTES_TO_BITS( bytes1 ) );
+    PSA_ASSERT( psa_generator_import_key( &derived_attributes, &derived_handle,
                                           &generator ) );
     PSA_ASSERT( psa_export_key( derived_handle,
                                 export_buffer, bytes1,
                                 &length ) );
     TEST_EQUAL( length, bytes1 );
     PSA_ASSERT( psa_destroy_key( derived_handle ) );
-    PSA_ASSERT( psa_allocate_key( &derived_handle ) );
-    PSA_ASSERT( psa_set_key_policy( derived_handle, &policy ) );
-    PSA_ASSERT( psa_generator_import_key( derived_handle,
-                                          PSA_KEY_TYPE_RAW_DATA,
-                                          PSA_BYTES_TO_BITS( bytes2 ),
+    psa_set_key_bits( &derived_attributes, PSA_BYTES_TO_BITS( bytes2 ) );
+    PSA_ASSERT( psa_generator_import_key( &derived_attributes, &derived_handle,
                                           &generator ) );
     PSA_ASSERT( psa_export_key( derived_handle,
                                 export_buffer + bytes1, bytes2,
@@ -4663,18 +4432,17 @@
     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;
-    psa_key_policy_t policy = PSA_KEY_POLICY_INIT;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
     psa_status_t expected_status = expected_status_arg;
     psa_status_t status;
 
     PSA_ASSERT( psa_crypto_init( ) );
 
-    PSA_ASSERT( psa_allocate_key( &our_key ) );
-    psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_DERIVE, alg );
-    PSA_ASSERT( psa_set_key_policy( our_key, &policy ) );
-    PSA_ASSERT( psa_import_key( our_key, our_key_type,
-                                our_key_data->x,
-                                our_key_data->len ) );
+    psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_DERIVE );
+    psa_set_key_algorithm( &attributes, alg );
+    psa_set_key_type( &attributes, our_key_type );
+    PSA_ASSERT( psa_import_key( &attributes, &our_key,
+                                our_key_data->x, our_key_data->len ) );
 
     /* The tests currently include inputs that should fail at either step.
      * Test cases that fail at the setup step should be changed to call
@@ -4709,19 +4477,18 @@
     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_key_policy_t policy = PSA_KEY_POLICY_INIT;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
     unsigned char *output = NULL;
     size_t output_length = ~0;
 
     ASSERT_ALLOC( output, expected_output->len );
     PSA_ASSERT( psa_crypto_init( ) );
 
-    PSA_ASSERT( psa_allocate_key( &our_key ) );
-    psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_DERIVE, alg );
-    PSA_ASSERT( psa_set_key_policy( our_key, &policy ) );
-    PSA_ASSERT( psa_import_key( our_key, our_key_type,
-                                our_key_data->x,
-                                our_key_data->len ) );
+    psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_DERIVE );
+    psa_set_key_algorithm( &attributes, alg );
+    psa_set_key_type( &attributes, our_key_type );
+    PSA_ASSERT( psa_import_key( &attributes, &our_key,
+                                our_key_data->x, our_key_data->len ) );
 
     PSA_ASSERT( psa_key_agreement_raw_shared_secret(
                     alg, our_key,
@@ -4747,18 +4514,17 @@
     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;
-    psa_key_policy_t policy = PSA_KEY_POLICY_INIT;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
     size_t actual_capacity;
     unsigned char output[16];
 
     PSA_ASSERT( psa_crypto_init( ) );
 
-    PSA_ASSERT( psa_allocate_key( &our_key ) );
-    psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_DERIVE, alg );
-    PSA_ASSERT( psa_set_key_policy( our_key, &policy ) );
-    PSA_ASSERT( psa_import_key( our_key, our_key_type,
-                                our_key_data->x,
-                                our_key_data->len ) );
+    psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_DERIVE );
+    psa_set_key_algorithm( &attributes, alg );
+    psa_set_key_type( &attributes, our_key_type );
+    PSA_ASSERT( psa_import_key( &attributes, &our_key,
+                                our_key_data->x, our_key_data->len ) );
 
     PSA_ASSERT( psa_key_derivation_setup( &generator, alg ) );
     PSA_ASSERT( psa_key_agreement( &generator, PSA_KDF_STEP_SECRET,
@@ -4806,7 +4572,7 @@
     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;
-    psa_key_policy_t policy = PSA_KEY_POLICY_INIT;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
     uint8_t *actual_output = NULL;
 
     ASSERT_ALLOC( actual_output, MAX( expected_output1->len,
@@ -4814,12 +4580,11 @@
 
     PSA_ASSERT( psa_crypto_init( ) );
 
-    PSA_ASSERT( psa_allocate_key( &our_key ) );
-    psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_DERIVE, alg );
-    PSA_ASSERT( psa_set_key_policy( our_key, &policy ) );
-    PSA_ASSERT( psa_import_key( our_key, our_key_type,
-                                our_key_data->x,
-                                our_key_data->len ) );
+    psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_DERIVE );
+    psa_set_key_algorithm( &attributes, alg );
+    psa_set_key_type( &attributes, our_key_type );
+    PSA_ASSERT( psa_import_key( &attributes, &our_key,
+                                our_key_data->x, our_key_data->len ) );
 
     PSA_ASSERT( psa_key_derivation_setup( &generator, alg ) );
     PSA_ASSERT( psa_key_agreement( &generator, PSA_KDF_STEP_SECRET,
@@ -4919,57 +4684,154 @@
     size_t bits = bits_arg;
     psa_algorithm_t alg = alg_arg;
     psa_status_t expected_status = expected_status_arg;
-    psa_key_type_t got_type;
-    size_t got_bits;
-    psa_status_t expected_info_status =
-        expected_status == PSA_SUCCESS ? PSA_SUCCESS : PSA_ERROR_DOES_NOT_EXIST;
-    psa_key_policy_t policy = PSA_KEY_POLICY_INIT;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    psa_key_attributes_t got_attributes = PSA_KEY_ATTRIBUTES_INIT;
 
     PSA_ASSERT( psa_crypto_init( ) );
 
-    PSA_ASSERT( psa_allocate_key( &handle ) );
-    psa_key_policy_set_usage( &policy, usage, alg );
-    PSA_ASSERT( psa_set_key_policy( handle, &policy ) );
+    psa_set_key_usage_flags( &attributes, usage );
+    psa_set_key_algorithm( &attributes, alg );
+    psa_set_key_type( &attributes, type );
+    psa_set_key_bits( &attributes, bits );
 
     /* Generate a key */
-    TEST_EQUAL( psa_generate_key( handle, type, bits, NULL, 0 ),
-                expected_status );
+    TEST_EQUAL( psa_generate_key( &attributes, &handle ), expected_status );
+    if( expected_status != PSA_SUCCESS )
+        goto exit;
 
     /* Test the key information */
-    TEST_EQUAL( psa_get_key_information( handle, &got_type, &got_bits ),
-                expected_info_status );
-    if( expected_info_status != PSA_SUCCESS )
-        goto exit;
-    TEST_EQUAL( got_type, type );
-    TEST_EQUAL( got_bits, bits );
+    PSA_ASSERT( psa_get_key_attributes( handle, &got_attributes ) );
+    TEST_EQUAL( psa_get_key_type( &got_attributes ), type );
+    TEST_EQUAL( psa_get_key_bits( &got_attributes ), bits );
 
     /* Do something with the key according to its type and permitted usage. */
     if( ! exercise_key( handle, usage, alg ) )
         goto exit;
 
 exit:
+    psa_reset_key_attributes( &got_attributes );
     psa_destroy_key( handle );
     mbedtls_psa_crypto_free( );
 }
 /* END_CASE */
 
-/* BEGIN_CASE depends_on:MBEDTLS_PSA_CRYPTO_STORAGE_C */
-void persistent_key_load_key_from_storage( data_t *data, int type_arg,
-                                           int bits, int usage_arg,
-                                           int alg_arg, int generation_method,
-                                           int export_status )
+/* BEGIN_CASE depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME:MBEDTLS_PKCS1_V15 */
+void generate_key_rsa( int bits_arg,
+                       data_t *e_arg,
+                       int expected_status_arg )
 {
     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;
-    psa_key_policy_t policy_set = PSA_KEY_POLICY_INIT;
-    psa_key_policy_t policy_get = PSA_KEY_POLICY_INIT;
-    psa_key_usage_t policy_usage = (psa_key_usage_t) usage_arg;
-    psa_algorithm_t policy_alg = (psa_algorithm_t) alg_arg;
-    psa_key_policy_t base_policy_set = PSA_KEY_POLICY_INIT;
-    psa_algorithm_t base_policy_alg = PSA_ALG_HKDF(PSA_ALG_SHA_256);
+    psa_key_type_t type = PSA_KEY_TYPE_RSA_KEYPAIR;
+    size_t bits = bits_arg;
+    psa_key_usage_t usage = PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT;
+    psa_algorithm_t alg = PSA_ALG_RSA_PKCS1V15_SIGN_RAW;
+    psa_status_t expected_status = expected_status_arg;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    uint8_t *exported = NULL;
+    size_t exported_size =
+        PSA_KEY_EXPORT_MAX_SIZE( PSA_KEY_TYPE_RSA_PUBLIC_KEY, bits );
+    size_t exported_length = SIZE_MAX;
+    uint8_t *e_read_buffer = NULL;
+    int is_default_public_exponent = 0;
+    size_t e_read_size = PSA_KEY_DOMAIN_PARAMETERS_SIZE( type, bits );
+    size_t e_read_length = SIZE_MAX;
+
+    if( e_arg->len == 0 ||
+        ( e_arg->len == 3 &&
+          e_arg->x[0] == 1 && e_arg->x[1] == 0 && e_arg->x[2] == 1 ) )
+    {
+        is_default_public_exponent = 1;
+        e_read_size = 0;
+    }
+    ASSERT_ALLOC( e_read_buffer, e_read_size );
+    ASSERT_ALLOC( exported, exported_size );
+
+    PSA_ASSERT( psa_crypto_init( ) );
+
+    psa_set_key_usage_flags( &attributes, usage );
+    psa_set_key_algorithm( &attributes, alg );
+    PSA_ASSERT( psa_set_key_domain_parameters( &attributes, type,
+                                               e_arg->x, e_arg->len ) );
+    psa_set_key_bits( &attributes, bits );
+
+    /* Generate a key */
+    TEST_EQUAL( psa_generate_key( &attributes, &handle ), expected_status );
+    if( expected_status != PSA_SUCCESS )
+        goto exit;
+
+    /* Test the key information */
+    PSA_ASSERT( psa_get_key_attributes( handle, &attributes ) );
+    TEST_EQUAL( psa_get_key_type( &attributes ), type );
+    TEST_EQUAL( psa_get_key_bits( &attributes ), bits );
+    PSA_ASSERT( psa_get_key_domain_parameters( &attributes,
+                                               e_read_buffer, e_read_size,
+                                               &e_read_length ) );
+    if( is_default_public_exponent )
+        TEST_EQUAL( e_read_length, 0 );
+    else
+        ASSERT_COMPARE( e_read_buffer, e_read_length, e_arg->x, e_arg->len );
+
+    /* Do something with the key according to its type and permitted usage. */
+    if( ! exercise_key( handle, usage, alg ) )
+        goto exit;
+
+    /* Export the key and check the public exponent. */
+    PSA_ASSERT( psa_export_public_key( handle,
+                                       exported, exported_size,
+                                       &exported_length ) );
+    {
+        uint8_t *p = exported;
+        uint8_t *end = exported + exported_length;
+        size_t len;
+        /*   RSAPublicKey ::= SEQUENCE {
+         *      modulus            INTEGER,    -- n
+         *      publicExponent     INTEGER  }  -- e
+         */
+        TEST_EQUAL( 0, mbedtls_asn1_get_tag( &p, end, &len,
+                                          MBEDTLS_ASN1_SEQUENCE |
+                                          MBEDTLS_ASN1_CONSTRUCTED ) );
+        TEST_ASSERT( asn1_skip_integer( &p, end, bits, bits, 1 ) );
+        TEST_EQUAL( 0, mbedtls_asn1_get_tag( &p, end, &len,
+                                             MBEDTLS_ASN1_INTEGER ) );
+        if( len >= 1 && p[0] == 0 )
+        {
+            ++p;
+            --len;
+        }
+        if( e_arg->len == 0 )
+        {
+            TEST_EQUAL( len, 3 );
+            TEST_EQUAL( p[0], 1 );
+            TEST_EQUAL( p[1], 0 );
+            TEST_EQUAL( p[2], 1 );
+        }
+        else
+            ASSERT_COMPARE( p, len, e_arg->x, e_arg->len );
+    }
+
+exit:
+    psa_reset_key_attributes( &attributes );
+    psa_destroy_key( handle );
+    mbedtls_psa_crypto_free( );
+    mbedtls_free( e_read_buffer );
+    mbedtls_free( exported );
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:MBEDTLS_PSA_CRYPTO_STORAGE_C */
+void persistent_key_load_key_from_storage( data_t *data,
+                                           int type_arg, int bits_arg,
+                                           int usage_flags_arg, int alg_arg,
+                                           int generation_method )
+{
+    psa_key_id_t key_id = 1;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    psa_key_handle_t handle = 0;
+    psa_key_handle_t base_key = 0;
+    psa_key_type_t type = type_arg;
+    size_t bits = bits_arg;
+    psa_key_usage_t usage_flags = usage_flags_arg;
+    psa_algorithm_t alg = alg_arg;
     psa_crypto_generator_t generator = PSA_CRYPTO_GENERATOR_INIT;
     unsigned char *first_export = NULL;
     unsigned char *second_export = NULL;
@@ -4977,102 +4839,116 @@
     size_t first_exported_length;
     size_t second_exported_length;
 
-    ASSERT_ALLOC( first_export, export_size );
-    ASSERT_ALLOC( second_export, export_size );
+    if( usage_flags & PSA_KEY_USAGE_EXPORT )
+    {
+        ASSERT_ALLOC( first_export, export_size );
+        ASSERT_ALLOC( second_export, export_size );
+    }
 
     PSA_ASSERT( psa_crypto_init() );
 
-    PSA_ASSERT( psa_create_key( PSA_KEY_LIFETIME_PERSISTENT, 1,
-                                &handle ) );
-    psa_key_policy_set_usage( &policy_set, policy_usage,
-                              policy_alg );
-    PSA_ASSERT( psa_set_key_policy( handle, &policy_set ) );
+    psa_make_key_persistent( &attributes, key_id, PSA_KEY_LIFETIME_PERSISTENT );
+    psa_set_key_usage_flags( &attributes, usage_flags );
+    psa_set_key_algorithm( &attributes, alg );
+    psa_set_key_type( &attributes, type );
+    psa_set_key_bits( &attributes, bits );
 
     switch( generation_method )
     {
         case IMPORT_KEY:
             /* Import the key */
-            PSA_ASSERT( psa_import_key( handle, type,
+            PSA_ASSERT( psa_import_key( &attributes, &handle,
                                         data->x, data->len ) );
             break;
 
         case GENERATE_KEY:
             /* Generate a key */
-            PSA_ASSERT( psa_generate_key( handle, type, bits,
-                                          NULL, 0 ) );
+            PSA_ASSERT( psa_generate_key( &attributes, &handle ) );
             break;
 
         case DERIVE_KEY:
-            /* Create base key */
-            PSA_ASSERT( psa_allocate_key( &base_key ) );
-            psa_key_policy_set_usage( &base_policy_set, PSA_KEY_USAGE_DERIVE,
-                                      base_policy_alg );
-            PSA_ASSERT( psa_set_key_policy(
-                            base_key, &base_policy_set ) );
-            PSA_ASSERT( psa_import_key( base_key, PSA_KEY_TYPE_DERIVE,
-                                        data->x, data->len ) );
-            /* Derive a key. */
-            PSA_ASSERT( psa_key_derivation( &generator, base_key,
-                                            base_policy_alg,
-                                            NULL, 0, NULL, 0,
-                                            export_size ) );
-            PSA_ASSERT( psa_generator_import_key(
-                            handle, PSA_KEY_TYPE_RAW_DATA,
-                            bits, &generator ) );
+            {
+                /* Create base key */
+                psa_algorithm_t derive_alg = PSA_ALG_HKDF( PSA_ALG_SHA_256 );
+                psa_key_attributes_t base_attributes = PSA_KEY_ATTRIBUTES_INIT;
+                psa_set_key_usage_flags( &base_attributes,
+                                         PSA_KEY_USAGE_DERIVE );
+                psa_set_key_algorithm( &base_attributes, derive_alg );
+                psa_set_key_type( &base_attributes, PSA_KEY_TYPE_DERIVE );
+                PSA_ASSERT( psa_import_key( &base_attributes, &base_key,
+                                            data->x, data->len ) );
+                /* Derive a key. */
+                PSA_ASSERT( psa_key_derivation_setup( &generator, derive_alg ) );
+                PSA_ASSERT( psa_key_derivation_input_key( &generator,
+                                                          PSA_KDF_STEP_SECRET,
+                                                          base_key ) );
+                PSA_ASSERT( psa_key_derivation_input_bytes(
+                                &generator, PSA_KDF_STEP_INFO,
+                                NULL, 0 ) );
+                PSA_ASSERT( psa_generator_import_key( &attributes, &handle,
+                                                      &generator ) );
+                PSA_ASSERT( psa_generator_abort( &generator ) );
+                PSA_ASSERT( psa_destroy_key( base_key ) );
+                base_key = 0;
+            }
             break;
     }
+    psa_reset_key_attributes( &attributes );
 
-    /* Export the key */
-    TEST_EQUAL( psa_export_key( handle,
-                                first_export, export_size,
-                                &first_exported_length ),
-                export_status );
+    /* Export the key if permitted by the key policy. */
+    if( usage_flags & PSA_KEY_USAGE_EXPORT )
+    {
+        PSA_ASSERT( psa_export_key( handle,
+                                    first_export, export_size,
+                                    &first_exported_length ) );
+        if( generation_method == IMPORT_KEY )
+            ASSERT_COMPARE( data->x, data->len,
+                            first_export, first_exported_length );
+    }
 
     /* Shutdown and restart */
     mbedtls_psa_crypto_free();
     PSA_ASSERT( psa_crypto_init() );
 
     /* Check key slot still contains key data */
-    PSA_ASSERT( psa_open_key( PSA_KEY_LIFETIME_PERSISTENT, 1,
+    PSA_ASSERT( psa_open_key( PSA_KEY_LIFETIME_PERSISTENT, key_id,
                               &handle ) );
-    PSA_ASSERT( psa_get_key_information(
-                    handle, &type_get, &bits_get ) );
-    TEST_EQUAL( type_get, type );
-    TEST_EQUAL( bits_get, (size_t) bits );
+    PSA_ASSERT( psa_get_key_attributes( handle, &attributes ) );
+    TEST_EQUAL( psa_get_key_id( &attributes ), key_id );
+    TEST_EQUAL( psa_get_key_lifetime( &attributes ),
+                PSA_KEY_LIFETIME_PERSISTENT );
+    TEST_EQUAL( psa_get_key_type( &attributes ), type );
+    TEST_EQUAL( psa_get_key_bits( &attributes ), bits );
+    TEST_EQUAL( psa_get_key_usage_flags( &attributes ), usage_flags );
+    TEST_EQUAL( psa_get_key_algorithm( &attributes ), alg );
 
-    PSA_ASSERT( psa_get_key_policy( handle, &policy_get ) );
-    TEST_EQUAL( psa_key_policy_get_usage( &policy_get ), policy_usage );
-    TEST_EQUAL( psa_key_policy_get_algorithm( &policy_get ), policy_alg );
-
-    /* Export the key again */
-    TEST_EQUAL( psa_export_key( handle,
-                                second_export, export_size,
-                                &second_exported_length ),
-                export_status );
-
-    if( export_status == PSA_SUCCESS )
+    /* Export the key again if permitted by the key policy. */
+    if( usage_flags & PSA_KEY_USAGE_EXPORT )
     {
+        PSA_ASSERT( psa_export_key( handle,
+                                    second_export, export_size,
+                                    &second_exported_length ) );
         ASSERT_COMPARE( first_export, first_exported_length,
                         second_export, second_exported_length );
-
-        switch( generation_method )
-        {
-            case IMPORT_KEY:
-                ASSERT_COMPARE( data->x, data->len,
-                                first_export, first_exported_length );
-                break;
-            default:
-                break;
-        }
     }
 
     /* Do something with the key according to its type and permitted usage. */
-    if( ! exercise_key( handle, policy_usage, policy_alg ) )
+    if( ! exercise_key( handle, usage_flags, alg ) )
         goto exit;
 
 exit:
+    psa_reset_key_attributes( &attributes );
     mbedtls_free( first_export );
     mbedtls_free( second_export );
+    psa_generator_abort( &generator );
+    psa_destroy_key( base_key );
+    if( handle == 0 )
+    {
+        /* In case there was a test failure after creating the persistent key
+         * but while it was not open, try to re-open the persistent key
+         * to delete it. */
+        psa_open_key( PSA_KEY_LIFETIME_PERSISTENT, key_id, &handle );
+    }
     psa_destroy_key( handle );
     mbedtls_psa_crypto_free();
 }
diff --git a/tests/suites/test_suite_psa_crypto_init.function b/tests/suites/test_suite_psa_crypto_init.function
index c8f6e1b..9551e1a 100644
--- a/tests/suites/test_suite_psa_crypto_init.function
+++ b/tests/suites/test_suite_psa_crypto_init.function
@@ -182,15 +182,20 @@
 {
     psa_status_t status;
     uint8_t data[10] = { 0 };
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    psa_key_handle_t handle = 0xdead;
     int i;
+
     for( i = 0; i < count; i++ )
     {
         status = psa_crypto_init( );
         PSA_ASSERT( status );
         mbedtls_psa_crypto_free( );
     }
-    status = psa_import_key( 1, PSA_KEY_TYPE_RAW_DATA, data, sizeof( data ) );
+    psa_set_key_type( &attributes, PSA_KEY_TYPE_RAW_DATA );
+    status = psa_import_key( &attributes, &handle, data, sizeof( data ) );
     TEST_EQUAL( status, PSA_ERROR_BAD_STATE );
+    TEST_EQUAL( handle, 0 );
 }
 /* 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 f97a5e0..c16f871 100644
--- a/tests/suites/test_suite_psa_crypto_persistent_key.data
+++ b/tests/suites/test_suite_psa_crypto_persistent_key.data
@@ -26,45 +26,78 @@
 
 Persistent key destroy
 depends_on:MBEDTLS_PK_C:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C
+persistent_key_destroy:1:0:PSA_KEY_TYPE_RSA_KEYPAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_KEY_TYPE_RAW_DATA:"deadbeef"
+
+Persistent key destroy after restart
+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"
 
-Persistent key destroy missing key
+Persistent key import (RSA)
 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"
+persistent_key_import:1:PSA_KEY_TYPE_RSA_KEYPAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":0:PSA_SUCCESS
 
-Persistent key import
+Persistent key import with restart (RSA)
 depends_on:MBEDTLS_PK_C:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C
-persistent_key_import:1:PSA_KEY_TYPE_RSA_KEYPAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_SUCCESS
+persistent_key_import:1:PSA_KEY_TYPE_RSA_KEYPAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":1:PSA_SUCCESS
 
 Persistent key import garbage data, should fail
 depends_on:MBEDTLS_PK_C:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C
-persistent_key_import:1:PSA_KEY_TYPE_RSA_KEYPAIR:"11111111":PSA_ERROR_INVALID_ARGUMENT
+persistent_key_import:1:PSA_KEY_TYPE_RSA_KEYPAIR:"11111111":0:PSA_ERROR_INVALID_ARGUMENT
 
 import/export persistent raw key: 0 byte
-import_export_persistent_key:"":PSA_KEY_TYPE_RAW_DATA:0:0
+import_export_persistent_key:"":PSA_KEY_TYPE_RAW_DATA:0:0:0
 
 import/export persistent raw key: 1 byte
-import_export_persistent_key:"2a":PSA_KEY_TYPE_RAW_DATA:8:0
+import_export_persistent_key:"2a":PSA_KEY_TYPE_RAW_DATA:8:0:0
 
 import/export persistent key RSA public key: good, 1024-bit
 depends_on:MBEDTLS_PK_C:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C
-import_export_persistent_key:"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_KEY_TYPE_RSA_PUBLIC_KEY:1024:0
+import_export_persistent_key:"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_KEY_TYPE_RSA_PUBLIC_KEY:1024:0:0
 
 import/export persistent key RSA keypair: good, 1024-bit
 depends_on:MBEDTLS_PK_C:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C
-import_export_persistent_key:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_KEY_TYPE_RSA_KEYPAIR:1024:0
+import_export_persistent_key:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_KEY_TYPE_RSA_KEYPAIR:1024:0:0
 
 import/export persistent raw key file not exist: 1 byte
-import_export_persistent_key:"2a":PSA_KEY_TYPE_RAW_DATA:8:1
+import_export_persistent_key:"2a":PSA_KEY_TYPE_RAW_DATA:8:0:1
 
 import/export persistent key RSA public key file not exist: 1024-bit
 depends_on:MBEDTLS_PK_C:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C
-import_export_persistent_key:"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_KEY_TYPE_RSA_PUBLIC_KEY:1024:1
+import_export_persistent_key:"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_KEY_TYPE_RSA_PUBLIC_KEY:1024:0:1
 
 import/export persistent key RSA keypair file not exist: 1024-bit
 depends_on:MBEDTLS_PK_C:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C
-import_export_persistent_key:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_KEY_TYPE_RSA_KEYPAIR:1024:1
+import_export_persistent_key:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_KEY_TYPE_RSA_KEYPAIR:1024:0:1
 
 PSA import/export-persistent symmetric key: 16 bytes
 depends_on:MBEDTLS_PK_C:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C
-import_export_persistent_key:"2b7e151628aed2a6abf7158809cf4f3c":PSA_KEY_TYPE_AES:128:0
+import_export_persistent_key:"2b7e151628aed2a6abf7158809cf4f3c":PSA_KEY_TYPE_AES:128:0:0
+
+import/export persistent raw key with restart: 0 byte
+import_export_persistent_key:"":PSA_KEY_TYPE_RAW_DATA:0:1:0
+
+import/export persistent raw key with restart: 1 byte
+import_export_persistent_key:"2a":PSA_KEY_TYPE_RAW_DATA:8:1:0
+
+import/export persistent key RSA public key with restart: good, 1024-bit
+depends_on:MBEDTLS_PK_C:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C
+import_export_persistent_key:"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_KEY_TYPE_RSA_PUBLIC_KEY:1024:1:0
+
+import/export persistent key RSA keypair with restart: good, 1024-bit
+depends_on:MBEDTLS_PK_C:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C
+import_export_persistent_key:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_KEY_TYPE_RSA_KEYPAIR:1024:1:0
+
+import/export persistent raw key file not exist with restart: 1 byte
+import_export_persistent_key:"2a":PSA_KEY_TYPE_RAW_DATA:8:1:1
+
+import/export persistent key RSA public key file not exist with restart: 1024-bit
+depends_on:MBEDTLS_PK_C:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C
+import_export_persistent_key:"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_KEY_TYPE_RSA_PUBLIC_KEY:1024:1:1
+
+import/export persistent key RSA keypair file not exist with restart: 1024-bit
+depends_on:MBEDTLS_PK_C:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C
+import_export_persistent_key:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_KEY_TYPE_RSA_KEYPAIR:1024:1:1
+
+PSA import/export-persistent symmetric key: 16 bytes
+depends_on:MBEDTLS_PK_C:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C
+import_export_persistent_key:"2b7e151628aed2a6abf7158809cf4f3c":PSA_KEY_TYPE_AES:128:1:0
diff --git a/tests/suites/test_suite_psa_crypto_persistent_key.function b/tests/suites/test_suite_psa_crypto_persistent_key.function
index 90e10f6..a2f4f77 100644
--- a/tests/suites/test_suite_psa_crypto_persistent_key.function
+++ b/tests/suites/test_suite_psa_crypto_persistent_key.function
@@ -87,6 +87,7 @@
     psa_key_handle_t handle = 0;
     uint8_t *data = NULL;
     size_t data_length = PSA_CRYPTO_MAX_STORAGE_SIZE;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
 
     if( data_too_large )
         data_length += 1;
@@ -95,10 +96,10 @@
 
     PSA_ASSERT( psa_crypto_init() );
 
-    PSA_ASSERT( psa_create_key( PSA_KEY_LIFETIME_PERSISTENT, key_id,
-                                &handle ) );
+    psa_make_key_persistent( &attributes, key_id, PSA_KEY_LIFETIME_PERSISTENT );
+    psa_set_key_type( &attributes, PSA_KEY_TYPE_RAW_DATA );
 
-    TEST_EQUAL( psa_import_key( handle, PSA_KEY_TYPE_RAW_DATA,
+    TEST_EQUAL( psa_import_key( &attributes, &handle,
                                 data, data_length ),
                 expected_status );
 
@@ -110,7 +111,7 @@
 /* END_CASE */
 
 /* BEGIN_CASE */
-void persistent_key_destroy( int key_id_arg, int should_store,
+void persistent_key_destroy( int key_id_arg, int restart,
                              int first_type_arg, data_t *first_data,
                              int second_type_arg, data_t *second_data )
 {
@@ -118,18 +119,25 @@
     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;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
 
     PSA_ASSERT( psa_crypto_init() );
 
-    PSA_ASSERT( psa_create_key( PSA_KEY_LIFETIME_PERSISTENT, key_id,
-                                &handle ) );
+    psa_make_key_persistent( &attributes, key_id, PSA_KEY_LIFETIME_PERSISTENT );
+    psa_set_key_type( &attributes, first_type );
 
-    if( should_store == 1 )
+    PSA_ASSERT( psa_import_key( &attributes, &handle,
+                                first_data->x, first_data->len ) );
+
+    if( restart )
     {
-        PSA_ASSERT( psa_import_key(
-                        handle, first_type,
-                        first_data->x, first_data->len ) );
+        psa_close_key( handle );
+        mbedtls_psa_crypto_free();
+        PSA_ASSERT( psa_crypto_init() );
+        PSA_ASSERT( psa_open_key( PSA_KEY_LIFETIME_PERSISTENT, key_id,
+                                  &handle ) );
     }
+    TEST_EQUAL( psa_is_key_present_in_storage( key_id ), 1 );
 
     /* Destroy the key */
     PSA_ASSERT( psa_destroy_key( handle ) );
@@ -145,11 +153,10 @@
     PSA_ASSERT( psa_crypto_init() );
 
     /* Create another key in the same slot */
-    PSA_ASSERT( psa_create_key( PSA_KEY_LIFETIME_PERSISTENT, key_id,
-                                &handle ) );
-    PSA_ASSERT( psa_import_key(
-                    handle, second_type,
-                    second_data->x, second_data->len ) );
+    psa_make_key_persistent( &attributes, key_id, PSA_KEY_LIFETIME_PERSISTENT );
+    psa_set_key_type( &attributes, second_type );
+    PSA_ASSERT( psa_import_key( &attributes, &handle,
+                                second_data->x, second_data->len ) );
 
 exit:
     mbedtls_psa_crypto_free();
@@ -159,18 +166,18 @@
 
 /* BEGIN_CASE */
 void persistent_key_import( int key_id_arg, int type_arg, data_t *data,
-                            int expected_status )
+                            int restart, int expected_status )
 {
-    psa_key_lifetime_t lifetime;
     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;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
 
     PSA_ASSERT( psa_crypto_init() );
 
-    PSA_ASSERT( psa_create_key( PSA_KEY_LIFETIME_PERSISTENT, key_id,
-                                &handle ) );
-    TEST_EQUAL( psa_import_key( handle, type, data->x, data->len ),
+    psa_make_key_persistent( &attributes, key_id, PSA_KEY_LIFETIME_PERSISTENT );
+    psa_set_key_type( &attributes, type );
+    TEST_EQUAL( psa_import_key( &attributes, &handle, data->x, data->len ),
                 expected_status );
 
     if( expected_status != PSA_SUCCESS )
@@ -179,10 +186,26 @@
         goto exit;
     }
 
-    PSA_ASSERT( psa_get_key_lifetime( handle, &lifetime ) );
-    TEST_EQUAL( lifetime, PSA_KEY_LIFETIME_PERSISTENT );
+    if( restart )
+    {
+        psa_close_key( handle );
+        mbedtls_psa_crypto_free();
+        PSA_ASSERT( psa_crypto_init() );
+        PSA_ASSERT( psa_open_key( PSA_KEY_LIFETIME_PERSISTENT, key_id,
+                                  &handle ) );
+    }
+
+    psa_reset_key_attributes( &attributes );
+    PSA_ASSERT( psa_get_key_attributes( handle, &attributes ) );
+    TEST_EQUAL( psa_get_key_id( &attributes ), key_id );
+    TEST_EQUAL( psa_get_key_lifetime( &attributes ),
+                PSA_KEY_LIFETIME_PERSISTENT );
+    TEST_EQUAL( psa_get_key_type( &attributes ), type );
+    TEST_EQUAL( psa_get_key_usage_flags( &attributes ), 0 );
+    TEST_EQUAL( psa_get_key_algorithm( &attributes ), 0 );
 
 exit:
+    psa_reset_key_attributes( &attributes );
     psa_destroy_persistent_key( key_id );
     mbedtls_psa_crypto_free();
 }
@@ -190,7 +213,8 @@
 
 /* BEGIN_CASE */
 void import_export_persistent_key( data_t *data, int type_arg,
-                                   int expected_bits, int key_not_exist )
+                                   int expected_bits,
+                                   int restart, int key_not_exist )
 {
     psa_key_id_t key_id = 42;
     psa_key_type_t type = (psa_key_type_t) type_arg;
@@ -198,34 +222,40 @@
     unsigned char *exported = NULL;
     size_t export_size = data->len;
     size_t exported_length;
-    psa_key_type_t got_type;
-    size_t got_bits;
-    psa_key_policy_t policy = PSA_KEY_POLICY_INIT;
-    psa_key_lifetime_t lifetime_get;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
 
     ASSERT_ALLOC( exported, export_size );
 
     PSA_ASSERT( psa_crypto_init( ) );
 
-    PSA_ASSERT( psa_create_key( PSA_KEY_LIFETIME_PERSISTENT, key_id,
-                                &handle ) );
-
-    psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_EXPORT,
-                              PSA_ALG_VENDOR_FLAG );
-    PSA_ASSERT( psa_set_key_policy( handle, &policy ) );
+    psa_make_key_persistent( &attributes, key_id, PSA_KEY_LIFETIME_PERSISTENT );
+    psa_set_key_type( &attributes, type );
+    psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_EXPORT );
 
     /* Import the key */
-    PSA_ASSERT( psa_import_key( handle, type,
+    PSA_ASSERT( psa_import_key( &attributes, &handle,
                                 data->x, data->len ) );
 
-    PSA_ASSERT( psa_get_key_lifetime( handle, &lifetime_get ) );
-    TEST_EQUAL( lifetime_get, PSA_KEY_LIFETIME_PERSISTENT );
+
+    if( restart )
+    {
+        psa_close_key( handle );
+        mbedtls_psa_crypto_free();
+        PSA_ASSERT( psa_crypto_init() );
+        PSA_ASSERT( psa_open_key( PSA_KEY_LIFETIME_PERSISTENT, key_id,
+                                  &handle ) );
+    }
 
     /* Test the key information */
-    PSA_ASSERT( psa_get_key_information(
-                    handle, &got_type, &got_bits ) );
-    TEST_EQUAL( got_type, type );
-    TEST_EQUAL( got_bits, (size_t) expected_bits );
+    psa_reset_key_attributes( &attributes );
+    PSA_ASSERT( psa_get_key_attributes( handle, &attributes ) );
+    TEST_EQUAL( psa_get_key_id( &attributes ), key_id );
+    TEST_EQUAL( psa_get_key_lifetime( &attributes ),
+                PSA_KEY_LIFETIME_PERSISTENT );
+    TEST_EQUAL( psa_get_key_type( &attributes ), type );
+    TEST_EQUAL( psa_get_key_bits( &attributes ), (size_t) expected_bits );
+    TEST_EQUAL( psa_get_key_usage_flags( &attributes ), PSA_KEY_USAGE_EXPORT );
+    TEST_EQUAL( psa_get_key_algorithm( &attributes ), 0 );
 
     TEST_EQUAL( psa_is_key_present_in_storage( key_id ), 1 );
 
@@ -244,6 +274,7 @@
     TEST_EQUAL( psa_is_key_present_in_storage( key_id ), 0 );
 
 exit:
+    psa_reset_key_attributes( &attributes );
     mbedtls_free( exported );
     mbedtls_psa_crypto_free( );
     psa_destroy_persistent_key( key_id );
diff --git a/tests/suites/test_suite_psa_crypto_slot_management.data b/tests/suites/test_suite_psa_crypto_slot_management.data
index e937465..5dc2b67 100644
--- a/tests/suites/test_suite_psa_crypto_slot_management.data
+++ b/tests/suites/test_suite_psa_crypto_slot_management.data
@@ -43,9 +43,6 @@
 Open failure: invalid lifetime
 open_fail:0x7fffffff:0:PSA_ERROR_INVALID_ARGUMENT
 
-Create failure: volatile lifetime
-create_fail:PSA_KEY_LIFETIME_VOLATILE:1:PSA_ERROR_INVALID_ARGUMENT
-
 Create failure: invalid lifetime
 create_fail:0x7fffffff:0:PSA_ERROR_INVALID_ARGUMENT
 
@@ -80,42 +77,17 @@
 depends_on:MBEDTLS_PSA_CRYPTO_STORAGE_C
 copy_across_lifetimes:PSA_KEY_LIFETIME_PERSISTENT:1:PSA_KEY_USAGE_EXPORT:0:PSA_KEY_TYPE_RAW_DATA:"4142434445":PSA_KEY_LIFETIME_PERSISTENT:2:PSA_KEY_USAGE_EXPORT:0:PSA_KEY_USAGE_EXPORT:0
 
-Copy empty volatile to volatile
-copy_from_empty:PSA_KEY_LIFETIME_VOLATILE:0:PSA_KEY_USAGE_EXPORT:0:PSA_KEY_LIFETIME_VOLATILE:0:PSA_KEY_USAGE_EXPORT:0
-
-Copy empty volatile to persistent
-depends_on:MBEDTLS_PSA_CRYPTO_STORAGE_C
-copy_from_empty:PSA_KEY_LIFETIME_VOLATILE:0:PSA_KEY_USAGE_EXPORT:0:PSA_KEY_LIFETIME_PERSISTENT:1:PSA_KEY_USAGE_EXPORT:0
-
-Copy empty persistent to volatile
-depends_on:MBEDTLS_PSA_CRYPTO_STORAGE_C
-copy_from_empty:PSA_KEY_LIFETIME_PERSISTENT:1:PSA_KEY_USAGE_EXPORT:0:PSA_KEY_LIFETIME_VOLATILE:0:PSA_KEY_USAGE_EXPORT:0
-
-Copy empty persistent to persistent
-depends_on:MBEDTLS_PSA_CRYPTO_STORAGE_C
-copy_from_empty:PSA_KEY_LIFETIME_PERSISTENT:1:PSA_KEY_USAGE_EXPORT:0:PSA_KEY_LIFETIME_PERSISTENT:2:PSA_KEY_USAGE_EXPORT:0
-
-Copy volatile to occupied volatile
-copy_to_occupied:PSA_KEY_LIFETIME_VOLATILE:0:PSA_KEY_USAGE_EXPORT:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"404142434445464748494a4b4c4d4e4f":PSA_KEY_LIFETIME_VOLATILE:0:PSA_KEY_USAGE_EXPORT:PSA_ALG_CBC_NO_PADDING:PSA_KEY_TYPE_AES:"606162636465666768696a6b6c6d6e6f"
-
-Copy volatile to occupied persistent
+Copy volatile to occupied
 depends_on:MBEDTLS_PSA_CRYPTO_STORAGE_C
 copy_to_occupied:PSA_KEY_LIFETIME_VOLATILE:0:PSA_KEY_USAGE_EXPORT:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"404142434445464748494a4b4c4d4e4f":PSA_KEY_LIFETIME_PERSISTENT:2:PSA_KEY_USAGE_EXPORT:PSA_ALG_CBC_NO_PADDING:PSA_KEY_TYPE_AES:"606162636465666768696a6b6c6d6e6f"
 
-Copy persistent to occupied volatile
-depends_on:MBEDTLS_PSA_CRYPTO_STORAGE_C
-copy_to_occupied:PSA_KEY_LIFETIME_PERSISTENT:1:PSA_KEY_USAGE_EXPORT:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"404142434445464748494a4b4c4d4e4f":PSA_KEY_LIFETIME_VOLATILE:0:PSA_KEY_USAGE_EXPORT:PSA_ALG_CBC_NO_PADDING:PSA_KEY_TYPE_AES:"606162636465666768696a6b6c6d6e6f"
-
-Copy persistent to occupied persistent
+Copy persistent to occupied
 depends_on:MBEDTLS_PSA_CRYPTO_STORAGE_C
 copy_to_occupied:PSA_KEY_LIFETIME_PERSISTENT:1:PSA_KEY_USAGE_EXPORT:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"404142434445464748494a4b4c4d4e4f":PSA_KEY_LIFETIME_PERSISTENT:2:PSA_KEY_USAGE_EXPORT:PSA_ALG_CBC_NO_PADDING:PSA_KEY_TYPE_AES:"606162636465666768696a6b6c6d6e6f"
 
-Copy volatile to itself
-copy_to_same:PSA_KEY_LIFETIME_VOLATILE:0:PSA_KEY_USAGE_EXPORT:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"404142434445464748494a4b4c4d4e4f"
-
-Copy persistent to itself
+Copy persistent to same
 depends_on:MBEDTLS_PSA_CRYPTO_STORAGE_C
-copy_to_same:PSA_KEY_LIFETIME_VOLATILE:0:PSA_KEY_USAGE_EXPORT:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"404142434445464748494a4b4c4d4e4f"
+copy_to_occupied:PSA_KEY_LIFETIME_PERSISTENT:1:PSA_KEY_USAGE_EXPORT:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"404142434445464748494a4b4c4d4e4f":PSA_KEY_LIFETIME_PERSISTENT:1:PSA_KEY_USAGE_EXPORT:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"404142434445464748494a4b4c4d4e4f"
 
 Close/destroy invalid handle
 invalid_handle:
diff --git a/tests/suites/test_suite_psa_crypto_slot_management.function b/tests/suites/test_suite_psa_crypto_slot_management.function
index 0278b88..03b7197 100644
--- a/tests/suites/test_suite_psa_crypto_slot_management.function
+++ b/tests/suites/test_suite_psa_crypto_slot_management.function
@@ -50,13 +50,6 @@
 #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
@@ -73,20 +66,20 @@
     psa_key_usage_t usage_flags = usage_arg;
     psa_key_type_t type = type_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_KEY_POLICY_INIT;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
 
     PSA_ASSERT( psa_crypto_init( ) );
 
-    /* Get a handle and import a key. */
-    PSA_ASSERT( psa_allocate_key( &handle ) );
+    /* Import a key. */
+    psa_set_key_usage_flags( &attributes, usage_flags );
+    psa_set_key_algorithm( &attributes, alg );
+    psa_set_key_type( &attributes, type );
+    PSA_ASSERT( psa_import_key( &attributes, &handle,
+                                key_data->x, key_data->len ) );
     TEST_ASSERT( handle != 0 );
-    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_EQUAL( read_type, type );
+    PSA_ASSERT( psa_get_key_attributes( handle, &attributes ) );
+    TEST_EQUAL( psa_get_key_type( &attributes ), type );
 
     /* Do something that invalidates the handle. */
     switch( close_method )
@@ -102,8 +95,9 @@
             PSA_ASSERT( psa_crypto_init( ) );
             break;
     }
+
     /* Test that the handle is now invalid. */
-    TEST_EQUAL( psa_get_key_information( handle, &read_type, NULL ),
+    TEST_EQUAL( psa_get_key_attributes( handle, &attributes ),
                 PSA_ERROR_INVALID_HANDLE );
     TEST_EQUAL( psa_close_key( handle ), PSA_ERROR_INVALID_HANDLE );
 
@@ -126,18 +120,20 @@
     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_KEY_POLICY_INIT;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
 
     TEST_MAX_KEY_ID( id );
 
     PSA_ASSERT( psa_crypto_init( ) );
 
     /* Get a handle and import a key. */
-    PSA_ASSERT( psa_create_key( lifetime, id, &handle ) );
+    psa_make_key_persistent( &attributes, id, lifetime );
+    psa_set_key_type( &attributes, type );
+    psa_set_key_usage_flags( &attributes, usage_flags );
+    psa_set_key_algorithm( &attributes, alg );
+    PSA_ASSERT( psa_import_key( &attributes, &handle,
+                                key_data->x, key_data->len ) );
     TEST_ASSERT( handle != 0 );
-    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_EQUAL( read_type, type );
 
@@ -195,13 +191,11 @@
     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 = PSA_KEY_POLICY_INIT;
-    psa_key_policy_t read_policy = PSA_KEY_POLICY_INIT;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
     psa_key_type_t type1 = PSA_KEY_TYPE_RAW_DATA;
-    psa_key_type_t read_type;
-    const uint8_t material1[16] = "test material #1";
+    const uint8_t material1[5] = "a key";
+    const uint8_t material2[5] = "b key";
     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;
@@ -211,18 +205,20 @@
     PSA_ASSERT( psa_crypto_init( ) );
 
     /* Create a key. */
-    PSA_ASSERT( psa_create_key( lifetime, id, &handle1 ) );
-    TEST_ASSERT( handle1 != 0 );
-    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,
+    psa_make_key_persistent( &attributes, id, lifetime );
+    psa_set_key_type( &attributes, type1 );
+    psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_EXPORT );
+    psa_set_key_algorithm( &attributes, 0 );
+    PSA_ASSERT( psa_import_key( &attributes, &handle1,
                                 material1, sizeof( material1 ) ) );
+    TEST_ASSERT( handle1 != 0 );
 
     if( reopen_policy == CLOSE_BEFORE )
         PSA_ASSERT( psa_close_key( handle1 ) );
 
     /* Attempt to create a new key in the same slot. */
-    TEST_EQUAL( psa_create_key( lifetime, id, &handle2 ),
+    TEST_EQUAL( psa_import_key( &attributes, &handle2,
+                                material2, sizeof( material2 ) ),
                 PSA_ERROR_ALREADY_EXISTS );
     TEST_EQUAL( handle2, 0 );
 
@@ -232,11 +228,15 @@
         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_EQUAL( read_type, type1 );
-    TEST_EQUAL( read_bits, bits1 );
+    psa_reset_key_attributes( &attributes );
+    PSA_ASSERT( psa_get_key_attributes( handle1, &attributes ) );
+    TEST_EQUAL( psa_get_key_id( &attributes ), id );
+    TEST_EQUAL( psa_get_key_lifetime( &attributes ), lifetime );
+    TEST_EQUAL( psa_get_key_type( &attributes ), type1 );
+    TEST_EQUAL( psa_get_key_bits( &attributes ), bits1 );
+    TEST_EQUAL( psa_get_key_usage_flags( &attributes ), PSA_KEY_USAGE_EXPORT );
+    TEST_EQUAL( psa_get_key_algorithm( &attributes ), 0 );
+
     PSA_ASSERT( psa_export_key( handle1,
                                 reexported, sizeof( reexported ),
                                 &reexported_length ) );
@@ -274,14 +274,19 @@
 {
     psa_key_lifetime_t lifetime = lifetime_arg;
     psa_key_id_t id = id_arg;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
     psa_status_t expected_status = expected_status_arg;
     psa_key_handle_t handle = 0xdead;
+    uint8_t material[1] = {'k'};
 
     TEST_MAX_KEY_ID( id );
 
     PSA_ASSERT( psa_crypto_init( ) );
 
-    TEST_EQUAL( psa_create_key( lifetime, id, &handle ),
+    psa_make_key_persistent( &attributes, id, lifetime );
+    psa_set_key_type( &attributes, PSA_KEY_TYPE_RAW_DATA );
+    TEST_EQUAL( psa_import_key( &attributes, &handle,
+                                material, sizeof( material ) ),
                 expected_status );
     TEST_EQUAL( handle, 0 );
 
@@ -306,17 +311,14 @@
     psa_key_usage_t source_usage = source_usage_arg;
     psa_algorithm_t source_alg = source_alg_arg;
     psa_key_handle_t source_handle = 0;
-    psa_key_policy_t source_policy = PSA_KEY_POLICY_INIT;
+    psa_key_attributes_t source_attributes = PSA_KEY_ATTRIBUTES_INIT;
     psa_key_type_t source_type = type_arg;
-    size_t source_bits;
     psa_key_lifetime_t target_lifetime = target_lifetime_arg;
     psa_key_id_t target_id = target_id_arg;
     psa_key_usage_t target_usage = target_usage_arg;
     psa_algorithm_t target_alg = target_alg_arg;
     psa_key_handle_t target_handle = 0;
-    psa_key_policy_t target_policy = PSA_KEY_POLICY_INIT;
-    psa_key_type_t target_type;
-    size_t target_bits;
+    psa_key_attributes_t target_attributes = PSA_KEY_ATTRIBUTES_INIT;
     psa_key_usage_t expected_usage = expected_usage_arg;
     psa_algorithm_t expected_alg = expected_alg_arg;
     uint8_t *export_buffer = NULL;
@@ -327,29 +329,27 @@
     PSA_ASSERT( psa_crypto_init( ) );
 
     /* Populate the source slot. */
-    if( source_lifetime == PSA_KEY_LIFETIME_VOLATILE )
-        PSA_ASSERT( psa_allocate_key( &source_handle ) );
-    else
-        PSA_ASSERT( psa_create_key( source_lifetime, source_id,
-                                    &source_handle ) );
-    psa_key_policy_set_usage( &source_policy, source_usage, source_alg );
-    PSA_ASSERT( psa_set_key_policy( source_handle, &source_policy ) );
-    PSA_ASSERT( psa_import_key( source_handle, source_type,
+    if( source_lifetime != PSA_KEY_LIFETIME_VOLATILE )
+        psa_make_key_persistent( &source_attributes,
+                                 source_id, source_lifetime );
+    psa_set_key_type( &source_attributes, source_type );
+    psa_set_key_usage_flags( &source_attributes, source_usage );
+    psa_set_key_algorithm( &source_attributes, source_alg );
+    PSA_ASSERT( psa_import_key( &source_attributes, &source_handle,
                                 material->x, material->len ) );
-    PSA_ASSERT( psa_get_key_information( source_handle, NULL, &source_bits ) );
+    /* Update the attributes with the bit size. */
+    PSA_ASSERT( psa_get_key_attributes( source_handle, &source_attributes ) );
 
     /* Prepare the target slot. */
-    if( target_lifetime == PSA_KEY_LIFETIME_VOLATILE )
-        PSA_ASSERT( psa_allocate_key( &target_handle ) );
-    else
-        PSA_ASSERT( psa_create_key( target_lifetime, target_id,
-                                    &target_handle ) );
-    psa_key_policy_set_usage( &target_policy, target_usage, target_alg );
-    PSA_ASSERT( psa_set_key_policy( target_handle, &target_policy ) );
-    target_policy = psa_key_policy_init();
+    if( target_lifetime != PSA_KEY_LIFETIME_VOLATILE )
+        psa_make_key_persistent( &target_attributes,
+                                 target_id, target_lifetime );
+    psa_set_key_usage_flags( &target_attributes, target_usage );
+    psa_set_key_algorithm( &target_attributes, target_alg );
 
     /* Copy the key. */
-    PSA_ASSERT( psa_copy_key( source_handle, target_handle, NULL ) );
+    PSA_ASSERT( psa_copy_key( source_handle,
+                              &target_attributes, &target_handle ) );
 
     /* Destroy the source to ensure that this doesn't affect the target. */
     PSA_ASSERT( psa_destroy_key( source_handle ) );
@@ -365,13 +365,15 @@
     }
 
     /* Test that the target slot has the expected content. */
-    PSA_ASSERT( psa_get_key_information( target_handle,
-                                         &target_type, &target_bits ) );
-    TEST_EQUAL( source_type, target_type );
-    TEST_EQUAL( source_bits, target_bits );
-    PSA_ASSERT( psa_get_key_policy( target_handle, &target_policy ) );
-    TEST_EQUAL( expected_usage, psa_key_policy_get_usage( &target_policy ) );
-    TEST_EQUAL( expected_alg, psa_key_policy_get_algorithm( &target_policy ) );
+    psa_reset_key_attributes( &target_attributes );
+    PSA_ASSERT( psa_get_key_attributes( target_handle, &target_attributes ) );
+    TEST_EQUAL( target_id, psa_get_key_id( &target_attributes ) );
+    TEST_EQUAL( target_lifetime, psa_get_key_lifetime( &target_attributes ) );
+    TEST_EQUAL( source_type, psa_get_key_type( &target_attributes ) );
+    TEST_EQUAL( psa_get_key_bits( &source_attributes ),
+                psa_get_key_bits( &target_attributes ) );
+    TEST_EQUAL( expected_usage, psa_get_key_usage_flags( &target_attributes ) );
+    TEST_EQUAL( expected_alg, psa_get_key_algorithm( &target_attributes ) );
     if( expected_usage & PSA_KEY_USAGE_EXPORT )
     {
         size_t length;
@@ -381,6 +383,14 @@
         ASSERT_COMPARE( material->x, material->len,
                         export_buffer, length );
     }
+    else
+    {
+        size_t length;
+        /* Check that the key is actually non-exportable. */
+        TEST_EQUAL( psa_export_key( target_handle, export_buffer,
+                                    material->len, &length ),
+                    PSA_ERROR_NOT_PERMITTED );
+    }
 
 exit:
     mbedtls_psa_crypto_free( );
@@ -392,69 +402,6 @@
 /* END_CASE */
 
 /* BEGIN_CASE */
-void copy_from_empty( int source_lifetime_arg, int source_id_arg,
-                       int source_usage_arg, int source_alg_arg,
-                       int target_lifetime_arg, int target_id_arg,
-                       int target_usage_arg, int target_alg_arg )
-{
-    psa_key_lifetime_t source_lifetime = source_lifetime_arg;
-    psa_key_id_t source_id = source_id_arg;
-    psa_key_usage_t source_usage = source_usage_arg;
-    psa_algorithm_t source_alg = source_alg_arg;
-    psa_key_handle_t source_handle = 0;
-    psa_key_policy_t source_policy = PSA_KEY_POLICY_INIT;
-    psa_key_lifetime_t target_lifetime = target_lifetime_arg;
-    psa_key_id_t target_id = target_id_arg;
-    psa_key_usage_t target_usage = target_usage_arg;
-    psa_algorithm_t target_alg = target_alg_arg;
-    psa_key_handle_t target_handle = 0;
-    psa_key_policy_t target_policy = PSA_KEY_POLICY_INIT;
-    psa_key_policy_t got_policy;
-
-    TEST_MAX_KEY_ID( source_id );
-    TEST_MAX_KEY_ID( target_id );
-
-    PSA_ASSERT( psa_crypto_init( ) );
-
-    /* Prepare the source slot. */
-    if( source_lifetime == PSA_KEY_LIFETIME_VOLATILE )
-        PSA_ASSERT( psa_allocate_key( &source_handle ) );
-    else
-        PSA_ASSERT( psa_create_key( source_lifetime, source_id,
-                                    &source_handle ) );
-    psa_key_policy_set_usage( &source_policy, source_usage, source_alg );
-    PSA_ASSERT( psa_set_key_policy( source_handle, &source_policy ) );
-
-    /* Prepare the target slot. */
-    if( target_lifetime == PSA_KEY_LIFETIME_VOLATILE )
-        PSA_ASSERT( psa_allocate_key( &target_handle ) );
-    else
-        PSA_ASSERT( psa_create_key( target_lifetime, target_id,
-                                    &target_handle ) );
-    psa_key_policy_set_usage( &target_policy, target_usage, target_alg );
-    PSA_ASSERT( psa_set_key_policy( target_handle, &target_policy ) );
-
-    /* Copy the key. */
-    TEST_EQUAL( psa_copy_key( source_handle, target_handle, NULL ),
-                PSA_ERROR_DOES_NOT_EXIST );
-
-    /* Test that the slots are unaffected. */
-    PSA_ASSERT( psa_get_key_policy( source_handle, &got_policy ) );
-    TEST_EQUAL( source_usage, psa_key_policy_get_usage( &got_policy ) );
-    TEST_EQUAL( source_alg, psa_key_policy_get_algorithm( &got_policy ) );
-    PSA_ASSERT( psa_get_key_policy( target_handle, &got_policy ) );
-    TEST_EQUAL( target_usage, psa_key_policy_get_usage( &got_policy ) );
-    TEST_EQUAL( target_alg, psa_key_policy_get_algorithm( &got_policy ) );
-
-exit:
-    mbedtls_psa_crypto_free( );
-#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C)
-    psa_purge_key_storage( );
-#endif
-}
-/* END_CASE */
-
-/* BEGIN_CASE */
 void copy_to_occupied( int source_lifetime_arg, int source_id_arg,
                        int source_usage_arg, int source_alg_arg,
                        int source_type_arg, data_t *source_material,
@@ -467,21 +414,18 @@
     psa_key_usage_t source_usage = source_usage_arg;
     psa_algorithm_t source_alg = source_alg_arg;
     psa_key_handle_t source_handle = 0;
-    psa_key_policy_t source_policy = PSA_KEY_POLICY_INIT;
     psa_key_type_t source_type = source_type_arg;
-    size_t source_bits;
     psa_key_lifetime_t target_lifetime = target_lifetime_arg;
     psa_key_id_t target_id = target_id_arg;
     psa_key_usage_t target_usage = target_usage_arg;
     psa_algorithm_t target_alg = target_alg_arg;
     psa_key_handle_t target_handle = 0;
-    psa_key_policy_t target_policy = PSA_KEY_POLICY_INIT;
     psa_key_type_t target_type = target_type_arg;
-    size_t target_bits;
-    psa_key_policy_t got_policy;
-    psa_key_type_t got_type;
-    size_t got_bits;
+    psa_key_handle_t new_handle = 0xdead;
     uint8_t *export_buffer = NULL;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    psa_key_attributes_t attributes1 = PSA_KEY_ATTRIBUTES_INIT;
+    psa_key_attributes_t attributes2 = PSA_KEY_ATTRIBUTES_INIT;
 
     TEST_MAX_KEY_ID( source_id );
     TEST_MAX_KEY_ID( target_id );
@@ -489,41 +433,52 @@
     PSA_ASSERT( psa_crypto_init( ) );
 
     /* Populate the source slot. */
-    if( source_lifetime == PSA_KEY_LIFETIME_VOLATILE )
-        PSA_ASSERT( psa_allocate_key( &source_handle ) );
-    else
-        PSA_ASSERT( psa_create_key( source_lifetime, source_id,
-                                    &source_handle ) );
-    psa_key_policy_set_usage( &source_policy, source_usage, source_alg );
-    PSA_ASSERT( psa_set_key_policy( source_handle, &source_policy ) );
-    PSA_ASSERT( psa_import_key( source_handle, source_type,
+    if( source_lifetime != PSA_KEY_LIFETIME_VOLATILE )
+        psa_make_key_persistent( &attributes,
+                                 source_id, source_lifetime );
+    psa_set_key_type( &attributes, source_type );
+    psa_set_key_usage_flags( &attributes, source_usage );
+    psa_set_key_algorithm( &attributes, source_alg );
+    PSA_ASSERT( psa_import_key( &attributes, &source_handle,
                                 source_material->x, source_material->len ) );
-    PSA_ASSERT( psa_get_key_information( source_handle, NULL, &source_bits ) );
 
     /* Populate the target slot. */
-    if( target_lifetime == PSA_KEY_LIFETIME_VOLATILE )
-        PSA_ASSERT( psa_allocate_key( &target_handle ) );
+    if( target_id == source_id )
+    {
+        target_handle = source_handle;
+    }
     else
-        PSA_ASSERT( psa_create_key( target_lifetime, target_id,
-                                    &target_handle ) );
-    psa_key_policy_set_usage( &target_policy, target_usage, target_alg );
-    PSA_ASSERT( psa_set_key_policy( target_handle, &target_policy ) );
-    PSA_ASSERT( psa_import_key( target_handle, target_type,
-                                target_material->x, target_material->len ) );
-    PSA_ASSERT( psa_get_key_information( target_handle, NULL, &target_bits ) );
+    {
+        psa_make_key_persistent( &attributes1, target_id, target_lifetime );
+        psa_set_key_type( &attributes1, target_type );
+        psa_set_key_usage_flags( &attributes1, target_usage );
+        psa_set_key_algorithm( &attributes1, target_alg );
+        PSA_ASSERT( psa_import_key( &attributes1, &target_handle,
+                                    target_material->x, target_material->len ) );
+    }
+    PSA_ASSERT( psa_get_key_attributes( target_handle, &attributes1 ) );
 
-    /* Copy the key. */
-    TEST_EQUAL( psa_copy_key( source_handle, target_handle, NULL ),
+    /* Make a copy attempt. */
+    psa_make_key_persistent( &attributes, target_id, target_lifetime );
+    TEST_EQUAL( psa_copy_key( source_handle,
+                              &attributes, &new_handle ),
                 PSA_ERROR_ALREADY_EXISTS );
+    TEST_EQUAL( new_handle , 0 );
 
     /* Test that the target slot is unaffected. */
-    PSA_ASSERT( psa_get_key_information( target_handle,
-                                         &got_type, &got_bits ) );
-    TEST_EQUAL( target_type, got_type );
-    TEST_EQUAL( target_bits, got_bits );
-    PSA_ASSERT( psa_get_key_policy( target_handle, &got_policy ) );
-    TEST_EQUAL( target_usage, psa_key_policy_get_usage( &got_policy ) );
-    TEST_EQUAL( target_alg, psa_key_policy_get_algorithm( &got_policy ) );
+    PSA_ASSERT( psa_get_key_attributes( target_handle, &attributes2 ) );
+    TEST_EQUAL( psa_get_key_id( &attributes1 ),
+                psa_get_key_id( &attributes2 ) );
+    TEST_EQUAL( psa_get_key_lifetime( &attributes1 ),
+                psa_get_key_lifetime( &attributes2 ) );
+    TEST_EQUAL( psa_get_key_type( &attributes1 ),
+                psa_get_key_type( &attributes2 ) );
+    TEST_EQUAL( psa_get_key_bits( &attributes1 ),
+                psa_get_key_bits( &attributes2 ) );
+    TEST_EQUAL( psa_get_key_usage_flags( &attributes1 ),
+                psa_get_key_usage_flags( &attributes2 ) );
+    TEST_EQUAL( psa_get_key_algorithm( &attributes1 ),
+                psa_get_key_algorithm( &attributes2 ) );
     if( target_usage & PSA_KEY_USAGE_EXPORT )
     {
         size_t length;
@@ -544,75 +499,10 @@
 /* END_CASE */
 
 /* BEGIN_CASE */
-void copy_to_same( int lifetime_arg, int id_arg,
-                   int usage_arg, int alg_arg,
-                   int type_arg, data_t *material )
-{
-    psa_key_lifetime_t lifetime = lifetime_arg;
-    psa_key_id_t id = id_arg;
-    psa_key_usage_t usage = usage_arg;
-    psa_algorithm_t alg = alg_arg;
-    psa_key_handle_t handle = 0;
-    psa_key_policy_t policy = PSA_KEY_POLICY_INIT;
-    psa_key_type_t type = type_arg;
-    size_t bits;
-    psa_key_policy_t got_policy;
-    psa_key_type_t got_type;
-    size_t got_bits;
-    uint8_t *export_buffer = NULL;
-
-    TEST_MAX_KEY_ID( id );
-
-    PSA_ASSERT( psa_crypto_init( ) );
-
-    /* Populate the slot. */
-    if( lifetime == PSA_KEY_LIFETIME_VOLATILE )
-        PSA_ASSERT( psa_allocate_key( &handle ) );
-    else
-        PSA_ASSERT( psa_create_key( lifetime, id,
-                                    &handle ) );
-    psa_key_policy_set_usage( &policy, usage, alg );
-    PSA_ASSERT( psa_set_key_policy( handle, &policy ) );
-    PSA_ASSERT( psa_import_key( handle, type,
-                                material->x, material->len ) );
-    PSA_ASSERT( psa_get_key_information( handle, NULL, &bits ) );
-
-    /* Copy the key. */
-    TEST_EQUAL( psa_copy_key( handle, handle, NULL ),
-                PSA_ERROR_ALREADY_EXISTS );
-
-    /* Test that the slot is unaffected. */
-    PSA_ASSERT( psa_get_key_information( handle,
-                                         &got_type, &got_bits ) );
-    TEST_EQUAL( type, got_type );
-    TEST_EQUAL( bits, got_bits );
-    PSA_ASSERT( psa_get_key_policy( handle, &got_policy ) );
-    TEST_EQUAL( usage, psa_key_policy_get_usage( &got_policy ) );
-    TEST_EQUAL( alg, psa_key_policy_get_algorithm( &got_policy ) );
-    if( usage & PSA_KEY_USAGE_EXPORT )
-    {
-        size_t length;
-        ASSERT_ALLOC( export_buffer, material->len );
-        PSA_ASSERT( psa_export_key( handle, export_buffer,
-                                    material->len, &length ) );
-        ASSERT_COMPARE( material->x, material->len,
-                        export_buffer, length );
-    }
-
-exit:
-    mbedtls_psa_crypto_free( );
-    mbedtls_free( export_buffer );
-#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_POLICY_INIT;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
     psa_key_type_t read_type;
     size_t read_bits;
     uint8_t material[1] = "a";
@@ -620,12 +510,12 @@
     PSA_ASSERT( psa_crypto_init( ) );
 
     /* Allocate a handle and store a key in it. */
-    PSA_ASSERT( psa_allocate_key( &handle1 ) );
-    TEST_ASSERT( handle1 != 0 );
-    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,
+    psa_set_key_type( &attributes, PSA_KEY_TYPE_RAW_DATA );
+    psa_set_key_usage_flags( &attributes, 0 );
+    psa_set_key_algorithm( &attributes, 0 );
+    PSA_ASSERT( psa_import_key( &attributes, &handle1,
                                 material, sizeof( material ) ) );
+    TEST_ASSERT( handle1 != 0 );
 
     /* Attempt to close and destroy some invalid handles. */
     TEST_EQUAL( psa_close_key( 0 ), PSA_ERROR_INVALID_HANDLE );
@@ -653,26 +543,27 @@
     size_t max_handles = max_handles_arg;
     size_t i, j;
     psa_status_t status;
-    psa_key_policy_t policy = PSA_KEY_POLICY_INIT;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
     uint8_t exported[sizeof( size_t )];
     size_t exported_length;
 
     ASSERT_ALLOC( handles, max_handles );
     PSA_ASSERT( psa_crypto_init( ) );
-    psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_EXPORT, 0 );
+
+    psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_EXPORT );
+    psa_set_key_algorithm( &attributes, 0 );
+    psa_set_key_type( &attributes, PSA_KEY_TYPE_RAW_DATA );
 
     for( i = 0; i < max_handles; i++ )
     {
-        status = psa_allocate_key( &handles[i] );
+        status = psa_import_key( &attributes, &handles[i],
+                                 (uint8_t *) &i, sizeof( i ) );
         if( status == PSA_ERROR_INSUFFICIENT_MEMORY )
             break;
         PSA_ASSERT( status );
         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;