Merge pull request #198 from gilles-peskine-arm/psa-api-1.0-beta-merge_development_20190801

Merge mbed-crypto/development into psa-api-1.0-beta
diff --git a/include/psa/crypto_extra.h b/include/psa/crypto_extra.h
index b2d4633..6dfaa13 100644
--- a/include/psa/crypto_extra.h
+++ b/include/psa/crypto_extra.h
@@ -89,7 +89,7 @@
     psa_key_attributes_t *attributes,
     psa_algorithm_t alg2)
 {
-    attributes->policy.alg2 = alg2;
+    attributes->core.policy.alg2 = alg2;
 }
 
 /** Retrieve the enrollment algorithm policy from key attributes.
@@ -101,7 +101,7 @@
 static inline psa_algorithm_t psa_get_key_enrollment_algorithm(
     const psa_key_attributes_t *attributes)
 {
-    return( attributes->policy.alg2 );
+    return( attributes->core.policy.alg2 );
 }
 
 /**@}*/
diff --git a/include/psa/crypto_se_driver.h b/include/psa/crypto_se_driver.h
index 9aebc45..f95eaeb 100644
--- a/include/psa/crypto_se_driver.h
+++ b/include/psa/crypto_se_driver.h
@@ -833,14 +833,18 @@
  *
  * \param[in,out] drv_context   The driver context structure.
  * \param[in] key_slot          Slot where the key will be stored
- *                              This must be a valid slot for a key of the chosen
- *                              type. It must be unoccupied.
+ *                              This must be a valid slot for a key of the
+ *                              chosen type. It must be unoccupied.
  * \param[in] lifetime          The required lifetime of the key storage
  * \param[in] type              Key type (a \c PSA_KEY_TYPE_XXX value)
  * \param[in] algorithm         Key algorithm (a \c PSA_ALG_XXX value)
  * \param[in] usage             The allowed uses of the key
  * \param[in] p_data            Buffer containing the key data
  * \param[in] data_length       Size of the `data` buffer in bytes
+ * \param[out] bits             On success, the key size in bits. The driver
+ *                              must determine this value after parsing the
+ *                              key according to the key type.
+ *                              This value is not used if the function fails.
  *
  * \retval #PSA_SUCCESS
  *         Success.
@@ -852,7 +856,8 @@
                                                 psa_algorithm_t algorithm,
                                                 psa_key_usage_t usage,
                                                 const uint8_t *p_data,
-                                                size_t data_length);
+                                                size_t data_length,
+                                                size_t *bits);
 
 /**
  * \brief A function that destroys a secure element key and restore the slot to
diff --git a/include/psa/crypto_struct.h b/include/psa/crypto_struct.h
index c02511d..9e38e53 100644
--- a/include/psa/crypto_struct.h
+++ b/include/psa/crypto_struct.h
@@ -309,18 +309,39 @@
     return( v );
 }
 
+/* The type used internally for key sizes.
+ * Public interfaces use size_t, but internally we use a smaller type. */
+typedef uint16_t psa_key_bits_t;
+/* The maximum value of the type used to represent bit-sizes.
+ * This is used to mark an invalid key size. */
+#define PSA_KEY_BITS_TOO_LARGE ( (psa_key_bits_t) ( -1 ) )
+/* The maximum size of a key in bits.
+ * Currently defined as the maximum that can be represented, rounded down
+ * to a whole number of bytes.
+ * This is an uncast value so that it can be used in preprocessor
+ * conditionals. */
+#define PSA_MAX_KEY_BITS 0xfff8
+
+typedef struct
+{
+    psa_key_type_t type;
+    psa_key_lifetime_t lifetime;
+    psa_key_id_t id;
+    psa_key_policy_t policy;
+    psa_key_bits_t bits;
+    uint16_t flags;
+} psa_core_key_attributes_t;
+
+#define PSA_CORE_KEY_ATTRIBUTES_INIT {0, 0, 0, {0, 0, 0}, 0, 0}
+
 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;
+    psa_core_key_attributes_t core;
     void *domain_parameters;
     size_t domain_parameters_size;
 };
 
-#define PSA_KEY_ATTRIBUTES_INIT {0, 0, {0, 0, 0}, 0, 0, NULL, 0}
+#define PSA_KEY_ATTRIBUTES_INIT {PSA_CORE_KEY_ATTRIBUTES_INIT, 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;
@@ -330,53 +351,53 @@
 static inline void psa_set_key_id(psa_key_attributes_t *attributes,
                                   psa_key_id_t id)
 {
-    attributes->id = id;
-    if( attributes->lifetime == PSA_KEY_LIFETIME_VOLATILE )
-        attributes->lifetime = PSA_KEY_LIFETIME_PERSISTENT;
+    attributes->core.id = id;
+    if( attributes->core.lifetime == PSA_KEY_LIFETIME_VOLATILE )
+        attributes->core.lifetime = PSA_KEY_LIFETIME_PERSISTENT;
 }
 
 static inline psa_key_id_t psa_get_key_id(
     const psa_key_attributes_t *attributes)
 {
-    return( attributes->id );
+    return( attributes->core.id );
 }
 
 static inline void psa_set_key_lifetime(psa_key_attributes_t *attributes,
                                         psa_key_lifetime_t lifetime)
 {
-    attributes->lifetime = lifetime;
+    attributes->core.lifetime = lifetime;
     if( lifetime == PSA_KEY_LIFETIME_VOLATILE )
-        attributes->id = 0;
+        attributes->core.id = 0;
 }
 
 static inline psa_key_lifetime_t psa_get_key_lifetime(
     const psa_key_attributes_t *attributes)
 {
-    return( attributes->lifetime );
+    return( attributes->core.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;
+    attributes->core.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 );
+    return( attributes->core.policy.usage );
 }
 
 static inline void psa_set_key_algorithm(psa_key_attributes_t *attributes,
                                          psa_algorithm_t alg)
 {
-    attributes->policy.alg = alg;
+    attributes->core.policy.alg = alg;
 }
 
 static inline psa_algorithm_t psa_get_key_algorithm(
     const psa_key_attributes_t *attributes)
 {
-    return( attributes->policy.alg );
+    return( attributes->core.policy.alg );
 }
 
 /* This function is declared in crypto_extra.h, which comes after this
@@ -392,7 +413,7 @@
     if( attributes->domain_parameters == NULL )
     {
         /* Common case: quick path */
-        attributes->type = type;
+        attributes->core.type = type;
     }
     else
     {
@@ -407,19 +428,22 @@
 static inline psa_key_type_t psa_get_key_type(
     const psa_key_attributes_t *attributes)
 {
-    return( attributes->type );
+    return( attributes->core.type );
 }
 
 static inline void psa_set_key_bits(psa_key_attributes_t *attributes,
                                     size_t bits)
 {
-    attributes->bits = bits;
+    if( bits > PSA_MAX_KEY_BITS )
+        attributes->core.bits = PSA_KEY_BITS_TOO_LARGE;
+    else
+        attributes->core.bits = (psa_key_bits_t) bits;
 }
 
 static inline size_t psa_get_key_bits(
     const psa_key_attributes_t *attributes)
 {
-    return( attributes->bits );
+    return( attributes->core.bits );
 }
 
 #endif /* PSA_CRYPTO_STRUCT_H */
diff --git a/library/psa_crypto.c b/library/psa_crypto.c
index 2eb0e52..41289c6 100644
--- a/library/psa_crypto.c
+++ b/library/psa_crypto.c
@@ -40,6 +40,7 @@
  * stored keys. */
 #include "psa_crypto_storage.h"
 
+#include <assert.h>
 #include <stdlib.h>
 #include <string.h>
 #include "mbedtls/platform.h"
@@ -366,7 +367,7 @@
 #if defined(MBEDTLS_PSA_CRYPTO_SE_C)
 static inline int psa_key_slot_is_external( const psa_key_slot_t *slot )
 {
-    return( psa_key_lifetime_is_external( slot->lifetime ) );
+    return( psa_key_lifetime_is_external( slot->attr.lifetime ) );
 }
 #endif /* MBEDTLS_PSA_CRYPTO_SE_C */
 
@@ -695,7 +696,45 @@
 }
 #endif /* defined(MBEDTLS_ECP_C) */
 
-/** Import key data into a slot. `slot->type` must have been set
+
+/** Return the size of the key in the given slot, in bits.
+ *
+ * \param[in] slot      A key slot.
+ *
+ * \return The key size in bits, read from the metadata in the slot.
+ */
+static inline size_t psa_get_key_slot_bits( const psa_key_slot_t *slot )
+{
+    return( slot->attr.bits );
+}
+
+/** Calculate the size of the key in the given slot, in bits.
+ *
+ * \param[in] slot      A key slot containing a transparent key.
+ *
+ * \return The key size in bits, calculated from the key data.
+ */
+static psa_key_bits_t psa_calculate_key_bits( const psa_key_slot_t *slot )
+{
+    size_t bits = 0; /* return 0 on an empty slot */
+
+    if( key_type_is_raw_bytes( slot->attr.type ) )
+        bits = PSA_BYTES_TO_BITS( slot->data.raw.bytes );
+#if defined(MBEDTLS_RSA_C)
+    else if( PSA_KEY_TYPE_IS_RSA( slot->attr.type ) )
+        bits = PSA_BYTES_TO_BITS( mbedtls_rsa_get_len( slot->data.rsa ) );
+#endif /* defined(MBEDTLS_RSA_C) */
+#if defined(MBEDTLS_ECP_C)
+    else if( PSA_KEY_TYPE_IS_ECC( slot->attr.type ) )
+        bits = slot->data.ecp->grp.pbits;
+#endif /* defined(MBEDTLS_ECP_C) */
+
+    /* We know that the size fits in psa_key_bits_t thanks to checks
+     * when the key was created. */
+    return( (psa_key_bits_t) bits );
+}
+
+/** Import key data into a slot. `slot->attr.type` must have been set
  * previously. This function assumes that the slot does not contain
  * any key material yet. On failure, the slot content is unchanged. */
 psa_status_t psa_import_key_into_slot( psa_key_slot_t *slot,
@@ -704,13 +743,17 @@
 {
     psa_status_t status = PSA_SUCCESS;
 
-    if( key_type_is_raw_bytes( slot->type ) )
+    if( key_type_is_raw_bytes( slot->attr.type ) )
     {
-        /* Ensure that a bytes-to-bit conversion won't overflow. */
+        size_t bit_size = PSA_BYTES_TO_BITS( data_length );
+        /* Ensure that the bytes-to-bit conversion didn't overflow. */
         if( data_length > SIZE_MAX / 8 )
             return( PSA_ERROR_NOT_SUPPORTED );
-        status = prepare_raw_data_slot( slot->type,
-                                        PSA_BYTES_TO_BITS( data_length ),
+        /* Enforce a size limit, and in particular ensure that the bit
+         * size fits in its representation type. */
+        if( bit_size > PSA_MAX_KEY_BITS )
+            return( PSA_ERROR_NOT_SUPPORTED );
+        status = prepare_raw_data_slot( slot->attr.type, bit_size,
                                         &slot->data.raw );
         if( status != PSA_SUCCESS )
             return( status );
@@ -719,25 +762,25 @@
     }
     else
 #if defined(MBEDTLS_ECP_C)
-    if( PSA_KEY_TYPE_IS_ECC_KEY_PAIR( slot->type ) )
+    if( PSA_KEY_TYPE_IS_ECC_KEY_PAIR( slot->attr.type ) )
     {
-        status = psa_import_ec_private_key( PSA_KEY_TYPE_GET_CURVE( slot->type ),
+        status = psa_import_ec_private_key( PSA_KEY_TYPE_GET_CURVE( slot->attr.type ),
                                             data, data_length,
                                             &slot->data.ecp );
     }
-    else if( PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY( slot->type ) )
+    else if( PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY( slot->attr.type ) )
     {
         status = psa_import_ec_public_key(
-            PSA_KEY_TYPE_GET_CURVE( slot->type ),
+            PSA_KEY_TYPE_GET_CURVE( slot->attr.type ),
             data, data_length,
             &slot->data.ecp );
     }
     else
 #endif /* MBEDTLS_ECP_C */
 #if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_PK_PARSE_C)
-    if( PSA_KEY_TYPE_IS_RSA( slot->type ) )
+    if( PSA_KEY_TYPE_IS_RSA( slot->attr.type ) )
     {
-        status = psa_import_rsa_key( slot->type,
+        status = psa_import_rsa_key( slot->attr.type,
             data, data_length,
             &slot->data.rsa );
     }
@@ -746,6 +789,14 @@
     {
         return( PSA_ERROR_NOT_SUPPORTED );
     }
+
+    if( status == PSA_SUCCESS )
+    {
+        /* Write the actual key size to the slot.
+         * psa_start_key_creation() wrote the size declared by the
+         * caller, which may be 0 (meaning unspecified) or wrong. */
+        slot->attr.bits = psa_calculate_key_bits( slot );
+    }
     return( status );
 }
 
@@ -851,20 +902,18 @@
     status = psa_get_key_slot( handle, &slot );
     if( status != PSA_SUCCESS )
         return( status );
-    if( slot->type == PSA_KEY_TYPE_NONE )
-        return( PSA_ERROR_DOES_NOT_EXIST );
 
     /* Enforce that usage policy for the key slot contains all the flags
      * required by the usage parameter. There is one exception: public
      * keys can always be exported, so we treat public key objects as
      * if they had the export flag. */
-    if( PSA_KEY_TYPE_IS_PUBLIC_KEY( slot->type ) )
+    if( PSA_KEY_TYPE_IS_PUBLIC_KEY( slot->attr.type ) )
         usage &= ~PSA_KEY_USAGE_EXPORT;
-    if( ( slot->policy.usage & usage ) != usage )
+    if( ( slot->attr.policy.usage & usage ) != usage )
         return( PSA_ERROR_NOT_PERMITTED );
 
     /* Enforce that the usage policy permits the requested algortihm. */
-    if( alg != 0 && ! psa_key_policy_permits( &slot->policy, alg ) )
+    if( alg != 0 && ! psa_key_policy_permits( &slot->attr.policy, alg ) )
         return( PSA_ERROR_NOT_PERMITTED );
 
     *p_slot = slot;
@@ -911,17 +960,17 @@
     }
     else
 #endif /* MBEDTLS_PSA_CRYPTO_SE_C */
-    if( slot->type == PSA_KEY_TYPE_NONE )
+    if( slot->attr.type == PSA_KEY_TYPE_NONE )
     {
         /* No key material to clean. */
     }
-    else if( key_type_is_raw_bytes( slot->type ) )
+    else if( key_type_is_raw_bytes( slot->attr.type ) )
     {
         mbedtls_free( slot->data.raw.data );
     }
     else
 #if defined(MBEDTLS_RSA_C)
-    if( PSA_KEY_TYPE_IS_RSA( slot->type ) )
+    if( PSA_KEY_TYPE_IS_RSA( slot->attr.type ) )
     {
         mbedtls_rsa_free( slot->data.rsa );
         mbedtls_free( slot->data.rsa );
@@ -929,7 +978,7 @@
     else
 #endif /* defined(MBEDTLS_RSA_C) */
 #if defined(MBEDTLS_ECP_C)
-    if( PSA_KEY_TYPE_IS_ECC( slot->type ) )
+    if( PSA_KEY_TYPE_IS_ECC( slot->attr.type ) )
     {
         mbedtls_ecp_keypair_free( slot->data.ecp );
         mbedtls_free( slot->data.ecp );
@@ -978,7 +1027,7 @@
         return( status );
 
 #if defined(MBEDTLS_PSA_CRYPTO_SE_C)
-    driver = psa_get_se_driver_entry( slot->lifetime );
+    driver = psa_get_se_driver_entry( slot->attr.lifetime );
     if( driver != NULL )
     {
         /* For a key in a secure element, we need to do three things:
@@ -987,9 +1036,9 @@
          * persistent data. Start a transaction that will encompass these
          * three actions. */
         psa_crypto_prepare_transaction( PSA_CRYPTO_TRANSACTION_DESTROY_KEY );
-        psa_crypto_transaction.key.lifetime = slot->lifetime;
+        psa_crypto_transaction.key.lifetime = slot->attr.lifetime;
         psa_crypto_transaction.key.slot = slot->data.se.slot_number;
-        psa_crypto_transaction.key.id = slot->persistent_storage_id;
+        psa_crypto_transaction.key.id = slot->attr.id;
         status = psa_crypto_save_transaction( );
         if( status != PSA_SUCCESS )
         {
@@ -1003,10 +1052,10 @@
 #endif /* MBEDTLS_PSA_CRYPTO_SE_C */
 
 #if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C)
-    if( slot->lifetime == PSA_KEY_LIFETIME_PERSISTENT )
+    if( slot->attr.lifetime == PSA_KEY_LIFETIME_PERSISTENT )
     {
         storage_status =
-            psa_destroy_persistent_key( slot->persistent_storage_id );
+            psa_destroy_persistent_key( slot->attr.id );
     }
 #endif /* defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) */
 
@@ -1032,23 +1081,6 @@
     return( storage_status );
 }
 
-/* Return the size of the key in the given slot, in bits. */
-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 );
-#if defined(MBEDTLS_RSA_C)
-    if( PSA_KEY_TYPE_IS_RSA( slot->type ) )
-        return( PSA_BYTES_TO_BITS( mbedtls_rsa_get_len( slot->data.rsa ) ) );
-#endif /* defined(MBEDTLS_RSA_C) */
-#if defined(MBEDTLS_ECP_C)
-    if( PSA_KEY_TYPE_IS_ECC( slot->type ) )
-        return( slot->data.ecp->grp.pbits );
-#endif /* defined(MBEDTLS_ECP_C) */
-    /* Shouldn't happen except on an empty slot. */
-    return( 0 );
-}
-
 void psa_reset_key_attributes( psa_key_attributes_t *attributes )
 {
     mbedtls_free( attributes->domain_parameters );
@@ -1081,7 +1113,7 @@
 
     attributes->domain_parameters = copy;
     attributes->domain_parameters_size = data_length;
-    attributes->type = type;
+    attributes->core.type = type;
     return( PSA_SUCCESS );
 }
 
@@ -1140,20 +1172,6 @@
 }
 #endif /* MBEDTLS_RSA_C */
 
-/** Retrieve the readily-accessible attributes of a key in a slot.
- *
- * This function does not compute attributes that are not directly
- * stored in the slot, such as the bit size of a transparent key.
- */
-static void psa_get_key_slot_attributes( psa_key_slot_t *slot,
-                                         psa_key_attributes_t *attributes )
-{
-    attributes->id = slot->persistent_storage_id;
-    attributes->lifetime = slot->lifetime;
-    attributes->policy = slot->policy;
-    attributes->type = slot->type;
-}
-
 /** Retrieve all the publicly-accessible attributes of a key.
  */
 psa_status_t psa_get_key_attributes( psa_key_handle_t handle,
@@ -1164,21 +1182,26 @@
 
     psa_reset_key_attributes( attributes );
 
-    status = psa_get_transparent_key( handle, &slot, 0, 0 );
+    status = psa_get_key_from_slot( handle, &slot, 0, 0 );
     if( status != PSA_SUCCESS )
         return( status );
 
-    psa_get_key_slot_attributes( slot, attributes );
-    attributes->bits = psa_get_key_slot_bits( slot );
+    attributes->core = slot->attr;
 
-    switch( slot->type )
+    switch( slot->attr.type )
     {
 #if defined(MBEDTLS_RSA_C)
         case PSA_KEY_TYPE_RSA_KEY_PAIR:
         case PSA_KEY_TYPE_RSA_PUBLIC_KEY:
+#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
+            /* TOnogrepDO: reporting the public exponent for opaque keys
+             * is not yet implemented. */
+            if( psa_get_se_driver( slot->attr.lifetime, NULL, NULL ) )
+                break;
+#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
             status = psa_get_rsa_public_exponent( slot->data.rsa, attributes );
             break;
-#endif
+#endif /* MBEDTLS_RSA_C */
         default:
             /* Nothing else to do. */
             break;
@@ -1218,11 +1241,11 @@
 
     *data_length = 0;
 
-    if( export_public_key && ! PSA_KEY_TYPE_IS_ASYMMETRIC( slot->type ) )
+    if( export_public_key && ! PSA_KEY_TYPE_IS_ASYMMETRIC( slot->attr.type ) )
         return( PSA_ERROR_INVALID_ARGUMENT );
 
 #if defined(MBEDTLS_PSA_CRYPTO_SE_C)
-    if( psa_get_se_driver( slot->lifetime, &drv, &drv_context ) )
+    if( psa_get_se_driver( slot->attr.lifetime, &drv, &drv_context ) )
     {
         psa_drv_se_export_key_t method;
         if( drv->key_management == NULL )
@@ -1238,7 +1261,7 @@
     }
 #endif /* MBEDTLS_PSA_CRYPTO_SE_C */
 
-    if( key_type_is_raw_bytes( slot->type ) )
+    if( key_type_is_raw_bytes( slot->attr.type ) )
     {
         if( slot->data.raw.bytes > data_size )
             return( PSA_ERROR_BUFFER_TOO_SMALL );
@@ -1252,11 +1275,11 @@
         return( PSA_SUCCESS );
     }
 #if defined(MBEDTLS_ECP_C)
-    if( PSA_KEY_TYPE_IS_ECC_KEY_PAIR( slot->type ) && !export_public_key )
+    if( PSA_KEY_TYPE_IS_ECC_KEY_PAIR( slot->attr.type ) && !export_public_key )
     {
         psa_status_t status;
 
-        size_t bytes = PSA_BITS_TO_BYTES( psa_get_key_slot_bits( slot ) );
+        size_t bytes = PSA_BITS_TO_BYTES( slot->attr.bits );
         if( bytes > data_size )
             return( PSA_ERROR_BUFFER_TOO_SMALL );
         status = mbedtls_to_psa_error(
@@ -1271,12 +1294,12 @@
     else
     {
 #if defined(MBEDTLS_PK_WRITE_C)
-        if( PSA_KEY_TYPE_IS_RSA( slot->type ) ||
-            PSA_KEY_TYPE_IS_ECC( slot->type ) )
+        if( PSA_KEY_TYPE_IS_RSA( slot->attr.type ) ||
+            PSA_KEY_TYPE_IS_ECC( slot->attr.type ) )
         {
             mbedtls_pk_context pk;
             int ret;
-            if( PSA_KEY_TYPE_IS_RSA( slot->type ) )
+            if( PSA_KEY_TYPE_IS_RSA( slot->attr.type ) )
             {
 #if defined(MBEDTLS_RSA_C)
                 mbedtls_pk_init( &pk );
@@ -1296,7 +1319,7 @@
                 return( PSA_ERROR_NOT_SUPPORTED );
 #endif
             }
-            if( export_public_key || PSA_KEY_TYPE_IS_PUBLIC_KEY( slot->type ) )
+            if( export_public_key || PSA_KEY_TYPE_IS_PUBLIC_KEY( slot->attr.type ) )
             {
                 ret = pk_write_pubkey_simple( &pk, data, data_size );
             }
@@ -1385,9 +1408,13 @@
                                      data_length, 1 ) );
 }
 
-static psa_status_t psa_set_key_policy_internal(
-    psa_key_slot_t *slot,
-    const psa_key_policy_t *policy )
+/** Validate that a key policy is internally well-formed.
+ *
+ * This function only rejects invalid policies. It does not validate the
+ * consistency of the policy with respect to other attributes of the key
+ * such as the key type.
+ */
+static psa_status_t psa_validate_key_policy( const psa_key_policy_t *policy )
 {
     if( ( policy->usage & ~( PSA_KEY_USAGE_EXPORT |
                              PSA_KEY_USAGE_COPY |
@@ -1398,7 +1425,48 @@
                              PSA_KEY_USAGE_DERIVE ) ) != 0 )
         return( PSA_ERROR_INVALID_ARGUMENT );
 
-    slot->policy = *policy;
+    return( PSA_SUCCESS );
+}
+
+/** Validate the internal consistency of key attributes.
+ *
+ * This function only rejects invalid attribute values. If does not
+ * validate the consistency of the attributes with any key data that may
+ * be involved in the creation of the key.
+ *
+ * Call this function early in the key creation process.
+ *
+ * \param[in] attributes    Key attributes for the new key.
+ * \param[out] p_drv        On any return, the driver for the key, if any.
+ *                          NULL for a transparent key.
+ *
+ */
+static psa_status_t psa_validate_key_attributes(
+    const psa_key_attributes_t *attributes,
+    psa_se_drv_table_entry_t **p_drv )
+{
+    psa_status_t status;
+
+    if( attributes->core.lifetime != PSA_KEY_LIFETIME_VOLATILE )
+    {
+        status = psa_validate_persistent_key_parameters(
+            attributes->core.lifetime, attributes->core.id,
+            p_drv, 1 );
+        if( status != PSA_SUCCESS )
+            return( status );
+    }
+
+    status = psa_validate_key_policy( &attributes->core.policy );
+    if( status != PSA_SUCCESS )
+        return( status );
+
+    /* Refuse to create overly large keys.
+     * Note that this doesn't trigger on import if the attributes don't
+     * explicitly specify a size (so psa_get_key_bits returns 0), so
+     * psa_import_key() needs its own checks. */
+    if( psa_get_key_bits( attributes ) > PSA_MAX_KEY_BITS )
+        return( PSA_ERROR_NOT_SUPPORTED );
+
     return( PSA_SUCCESS );
 }
 
@@ -1438,26 +1506,22 @@
 
     *p_drv = NULL;
 
+    status = psa_validate_key_attributes( attributes, p_drv );
+    if( status != PSA_SUCCESS )
+        return( status );
+
     status = psa_internal_allocate_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;
+    /* We're storing the declared bit-size of the key. It's up to each
+     * creation mechanism to verify that this information is correct.
+     * It's automatically correct for mechanisms that use the bit-size as
+     * an input (generate, device) but not for those where the bit-size
+     * is optional (import, copy). */
 
-    if( attributes->lifetime != PSA_KEY_LIFETIME_VOLATILE )
-    {
-        status = psa_validate_persistent_key_parameters( attributes->lifetime,
-                                                         attributes->id,
-                                                         p_drv, 1 );
-        if( status != PSA_SUCCESS )
-            return( status );
-        slot->persistent_storage_id = attributes->id;
-    }
-    slot->type = attributes->type;
+    slot->attr = attributes->core;
 
 #if defined(MBEDTLS_PSA_CRYPTO_SE_C)
     /* For a key in a secure element, we need to do three things:
@@ -1480,9 +1544,9 @@
         if( status != PSA_SUCCESS )
             return( status );
         psa_crypto_prepare_transaction( PSA_CRYPTO_TRANSACTION_CREATE_KEY );
-        psa_crypto_transaction.key.lifetime = slot->lifetime;
+        psa_crypto_transaction.key.lifetime = slot->attr.lifetime;
         psa_crypto_transaction.key.slot = slot->data.se.slot_number;
-        psa_crypto_transaction.key.id = slot->persistent_storage_id;
+        psa_crypto_transaction.key.id = slot->attr.id;
         status = psa_crypto_save_transaction( );
         if( status != PSA_SUCCESS )
         {
@@ -1521,42 +1585,44 @@
     (void) driver;
 
 #if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C)
-    if( slot->lifetime != PSA_KEY_LIFETIME_VOLATILE )
+    if( slot->attr.lifetime != PSA_KEY_LIFETIME_VOLATILE )
     {
-        uint8_t *buffer = NULL;
-        size_t buffer_size = 0;
-        size_t length = 0;
-
 #if defined(MBEDTLS_PSA_CRYPTO_SE_C)
         if( driver != NULL )
         {
-            buffer = (uint8_t*) &slot->data.se.slot_number;
-            length = sizeof( slot->data.se.slot_number );
+            psa_se_key_data_storage_t data;
+#if defined(static_assert)
+            static_assert( sizeof( slot->data.se.slot_number ) ==
+                           sizeof( data.slot_number ),
+                           "Slot number size does not match psa_se_key_data_storage_t" );
+            static_assert( sizeof( slot->attr.bits ) == sizeof( data.bits ),
+                           "Bit-size size does not match psa_se_key_data_storage_t" );
+#endif
+            memcpy( &data.slot_number, &slot->data.se.slot_number,
+                    sizeof( slot->data.se.slot_number ) );
+            memcpy( &data.bits, &slot->attr.bits,
+                    sizeof( slot->attr.bits ) );
+            status = psa_save_persistent_key( &slot->attr,
+                                              (uint8_t*) &data,
+                                              sizeof( data ) );
         }
         else
 #endif /* MBEDTLS_PSA_CRYPTO_SE_C */
         {
-            buffer_size = PSA_KEY_EXPORT_MAX_SIZE( slot->type,
-                                                   psa_get_key_slot_bits( slot ) );
-            buffer = mbedtls_calloc( 1, buffer_size );
+            size_t buffer_size =
+                PSA_KEY_EXPORT_MAX_SIZE( slot->attr.type,
+                                         slot->attr.bits );
+            uint8_t *buffer = mbedtls_calloc( 1, buffer_size );
+            size_t length = 0;
             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->attr,
+                                                  buffer, length );
 
-        if( status == PSA_SUCCESS )
-        {
-            psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
-            psa_get_key_slot_attributes( slot, &attributes );
-            status = psa_save_persistent_key( &attributes, buffer, length );
-        }
-
-#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
-        if( driver == NULL )
-#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
-        {
             if( buffer_size != 0 )
                 mbedtls_platform_zeroize( buffer, buffer_size );
             mbedtls_free( buffer );
@@ -1570,7 +1636,7 @@
         status = psa_save_se_persistent_data( driver );
         if( status != PSA_SUCCESS )
         {
-            psa_destroy_persistent_key( slot->persistent_storage_id );
+            psa_destroy_persistent_key( slot->attr.id );
             return( status );
         }
         status = psa_crypto_stop_transaction( );
@@ -1617,20 +1683,29 @@
     psa_wipe_key_slot( slot );
 }
 
-static psa_status_t psa_check_key_slot_attributes(
+/** Validate optional attributes during key creation.
+ *
+ * Some key attributes are optional during key creation. If they are
+ * specified in the attributes structure, check that they are consistent
+ * with the data in the slot.
+ *
+ * This function should be called near the end of key creation, after
+ * the slot in memory is fully populated but before saving persistent data.
+ */
+static psa_status_t psa_validate_optional_attributes(
     const psa_key_slot_t *slot,
     const psa_key_attributes_t *attributes )
 {
-    if( attributes->type != 0 )
+    if( attributes->core.type != 0 )
     {
-        if( attributes->type != slot->type )
+        if( attributes->core.type != slot->attr.type )
             return( PSA_ERROR_INVALID_ARGUMENT );
     }
 
     if( attributes->domain_parameters_size != 0 )
     {
 #if defined(MBEDTLS_RSA_C)
-        if( PSA_KEY_TYPE_IS_RSA( slot->type ) )
+        if( PSA_KEY_TYPE_IS_RSA( slot->attr.type ) )
         {
             mbedtls_mpi actual, required;
             int ret;
@@ -1660,9 +1735,9 @@
         }
     }
 
-    if( attributes->bits != 0 )
+    if( attributes->core.bits != 0 )
     {
-        if( attributes->bits != psa_get_key_slot_bits( slot ) )
+        if( attributes->core.bits != slot->attr.bits )
             return( PSA_ERROR_INVALID_ARGUMENT );
     }
 
@@ -1686,6 +1761,7 @@
     if( driver != NULL )
     {
         const psa_drv_se_t *drv = psa_get_se_driver_methods( driver );
+        size_t bits;
         if( drv->key_management == NULL ||
             drv->key_management->p_import == NULL )
         {
@@ -1695,9 +1771,18 @@
         status = drv->key_management->p_import(
             psa_get_se_driver_context( driver ),
             slot->data.se.slot_number,
-            slot->lifetime, slot->type, slot->policy.alg, slot->policy.usage,
-            data, data_length );
-        /* TOnogrepDO: psa_check_key_slot_attributes? */
+            slot->attr.lifetime, slot->attr.type,
+            slot->attr.policy.alg, slot->attr.policy.usage,
+            data, data_length,
+            &bits );
+        if( status != PSA_SUCCESS )
+            goto exit;
+        if( bits > PSA_MAX_KEY_BITS )
+        {
+            status = PSA_ERROR_NOT_SUPPORTED;
+            goto exit;
+        }
+        slot->attr.bits = (psa_key_bits_t) bits;
     }
     else
 #endif /* MBEDTLS_PSA_CRYPTO_SE_C */
@@ -1705,10 +1790,10 @@
         status = psa_import_key_into_slot( slot, data, data_length );
         if( status != PSA_SUCCESS )
             goto exit;
-        status = psa_check_key_slot_attributes( slot, attributes );
-        if( status != PSA_SUCCESS )
-            goto exit;
     }
+    status = psa_validate_optional_attributes( slot, attributes );
+    if( status != PSA_SUCCESS )
+        goto exit;
 
     status = psa_finish_key_creation( slot, driver );
 exit:
@@ -1728,7 +1813,7 @@
     size_t buffer_size = 0;
     size_t length;
 
-    buffer_size = PSA_KEY_EXPORT_MAX_SIZE( source->type,
+    buffer_size = PSA_KEY_EXPORT_MAX_SIZE( source->attr.type,
                                            psa_get_key_slot_bits( source ) );
     buffer = mbedtls_calloc( 1, buffer_size );
     if( buffer == NULL && buffer_size != 0 )
@@ -1736,7 +1821,7 @@
     status = psa_internal_export_key( source, buffer, buffer_size, &length, 0 );
     if( status != PSA_SUCCESS )
         goto exit;
-    target->type = source->type;
+    target->attr.type = source->attr.type;
     status = psa_import_key_into_slot( target, buffer, length );
 
 exit:
@@ -1761,12 +1846,13 @@
     if( status != PSA_SUCCESS )
         goto exit;
 
-    status = psa_check_key_slot_attributes( source_slot, specified_attributes );
+    status = psa_validate_optional_attributes( source_slot,
+                                               specified_attributes );
     if( status != PSA_SUCCESS )
         goto exit;
 
-    status = psa_restrict_key_policy( &actual_attributes.policy,
-                                      &source_slot->policy );
+    status = psa_restrict_key_policy( &actual_attributes.core.policy,
+                                      &source_slot->attr.policy );
     if( status != PSA_SUCCESS )
         goto exit;
 
@@ -2556,7 +2642,7 @@
     {
         const mbedtls_cipher_info_t *cipher_info =
             mbedtls_cipher_info_from_psa( full_length_alg,
-                                          slot->type, key_bits, NULL );
+                                          slot->attr.type, key_bits, NULL );
         int ret;
         if( cipher_info == NULL )
         {
@@ -2588,7 +2674,7 @@
             goto exit;
         }
 
-        if( slot->type != PSA_KEY_TYPE_HMAC )
+        if( slot->attr.type != PSA_KEY_TYPE_HMAC )
         {
             status = PSA_ERROR_INVALID_ARGUMENT;
             goto exit;
@@ -3128,14 +3214,14 @@
     status = psa_get_transparent_key( handle, &slot, PSA_KEY_USAGE_SIGN, alg );
     if( status != PSA_SUCCESS )
         goto exit;
-    if( ! PSA_KEY_TYPE_IS_KEY_PAIR( slot->type ) )
+    if( ! PSA_KEY_TYPE_IS_KEY_PAIR( slot->attr.type ) )
     {
         status = PSA_ERROR_INVALID_ARGUMENT;
         goto exit;
     }
 
 #if defined(MBEDTLS_RSA_C)
-    if( slot->type == PSA_KEY_TYPE_RSA_KEY_PAIR )
+    if( slot->attr.type == PSA_KEY_TYPE_RSA_KEY_PAIR )
     {
         status = psa_rsa_sign( slot->data.rsa,
                                alg,
@@ -3146,7 +3232,7 @@
     else
 #endif /* defined(MBEDTLS_RSA_C) */
 #if defined(MBEDTLS_ECP_C)
-    if( PSA_KEY_TYPE_IS_ECC( slot->type ) )
+    if( PSA_KEY_TYPE_IS_ECC( slot->attr.type ) )
     {
 #if defined(MBEDTLS_ECDSA_C)
         if(
@@ -3203,7 +3289,7 @@
         return( status );
 
 #if defined(MBEDTLS_RSA_C)
-    if( PSA_KEY_TYPE_IS_RSA( slot->type ) )
+    if( PSA_KEY_TYPE_IS_RSA( slot->attr.type ) )
     {
         return( psa_rsa_verify( slot->data.rsa,
                                 alg,
@@ -3213,7 +3299,7 @@
     else
 #endif /* defined(MBEDTLS_RSA_C) */
 #if defined(MBEDTLS_ECP_C)
-    if( PSA_KEY_TYPE_IS_ECC( slot->type ) )
+    if( PSA_KEY_TYPE_IS_ECC( slot->attr.type ) )
     {
 #if defined(MBEDTLS_ECDSA_C)
         if( PSA_ALG_IS_ECDSA( alg ) )
@@ -3271,12 +3357,12 @@
     status = psa_get_transparent_key( handle, &slot, PSA_KEY_USAGE_ENCRYPT, alg );
     if( status != PSA_SUCCESS )
         return( status );
-    if( ! ( PSA_KEY_TYPE_IS_PUBLIC_KEY( slot->type ) ||
-            PSA_KEY_TYPE_IS_KEY_PAIR( slot->type ) ) )
+    if( ! ( PSA_KEY_TYPE_IS_PUBLIC_KEY( slot->attr.type ) ||
+            PSA_KEY_TYPE_IS_KEY_PAIR( slot->attr.type ) ) )
         return( PSA_ERROR_INVALID_ARGUMENT );
 
 #if defined(MBEDTLS_RSA_C)
-    if( PSA_KEY_TYPE_IS_RSA( slot->type ) )
+    if( PSA_KEY_TYPE_IS_RSA( slot->attr.type ) )
     {
         mbedtls_rsa_context *rsa = slot->data.rsa;
         int ret;
@@ -3351,11 +3437,11 @@
     status = psa_get_transparent_key( handle, &slot, PSA_KEY_USAGE_DECRYPT, alg );
     if( status != PSA_SUCCESS )
         return( status );
-    if( ! PSA_KEY_TYPE_IS_KEY_PAIR( slot->type ) )
+    if( ! PSA_KEY_TYPE_IS_KEY_PAIR( slot->attr.type ) )
         return( PSA_ERROR_INVALID_ARGUMENT );
 
 #if defined(MBEDTLS_RSA_C)
-    if( slot->type == PSA_KEY_TYPE_RSA_KEY_PAIR )
+    if( slot->attr.type == PSA_KEY_TYPE_RSA_KEY_PAIR )
     {
         mbedtls_rsa_context *rsa = slot->data.rsa;
         int ret;
@@ -3462,7 +3548,7 @@
         goto exit;
     key_bits = psa_get_key_slot_bits( slot );
 
-    cipher_info = mbedtls_cipher_info_from_psa( alg, slot->type, key_bits, NULL );
+    cipher_info = mbedtls_cipher_info_from_psa( alg, slot->attr.type, key_bits, NULL );
     if( cipher_info == NULL )
     {
         status = PSA_ERROR_NOT_SUPPORTED;
@@ -3474,7 +3560,7 @@
         goto exit;
 
 #if defined(MBEDTLS_DES_C)
-    if( slot->type == PSA_KEY_TYPE_DES && key_bits == 128 )
+    if( slot->attr.type == PSA_KEY_TYPE_DES && key_bits == 128 )
     {
         /* Two-key Triple-DES is 3-key Triple-DES with K1=K3 */
         uint8_t keys[24];
@@ -3516,10 +3602,10 @@
 
     operation->key_set = 1;
     operation->block_size = ( PSA_ALG_IS_STREAM_CIPHER( alg ) ? 1 :
-                              PSA_BLOCK_CIPHER_BLOCK_SIZE( slot->type ) );
+                              PSA_BLOCK_CIPHER_BLOCK_SIZE( slot->attr.type ) );
     if( alg & PSA_ALG_CIPHER_FROM_BLOCK_FLAG )
     {
-        operation->iv_size = PSA_BLOCK_CIPHER_BLOCK_SIZE( slot->type );
+        operation->iv_size = PSA_BLOCK_CIPHER_BLOCK_SIZE( slot->attr.type );
     }
 #if defined(MBEDTLS_CHACHA20_C)
     else
@@ -3801,7 +3887,7 @@
     key_bits = psa_get_key_slot_bits( operation->slot );
 
     operation->cipher_info =
-        mbedtls_cipher_info_from_psa( alg, operation->slot->type, key_bits,
+        mbedtls_cipher_info_from_psa( alg, operation->slot->attr.type, key_bits,
                                       &cipher_id );
     if( operation->cipher_info == NULL )
         return( PSA_ERROR_NOT_SUPPORTED );
@@ -3815,7 +3901,7 @@
             /* CCM allows the following tag lengths: 4, 6, 8, 10, 12, 14, 16.
              * The call to mbedtls_ccm_encrypt_and_tag or
              * mbedtls_ccm_auth_decrypt will validate the tag length. */
-            if( PSA_BLOCK_CIPHER_BLOCK_SIZE( operation->slot->type ) != 16 )
+            if( PSA_BLOCK_CIPHER_BLOCK_SIZE( operation->slot->attr.type ) != 16 )
                 return( PSA_ERROR_INVALID_ARGUMENT );
             mbedtls_ccm_init( &operation->ctx.ccm );
             status = mbedtls_to_psa_error(
@@ -3834,7 +3920,7 @@
             /* GCM allows the following tag lengths: 4, 8, 12, 13, 14, 15, 16.
              * The call to mbedtls_gcm_crypt_and_tag or
              * mbedtls_gcm_auth_decrypt will validate the tag length. */
-            if( PSA_BLOCK_CIPHER_BLOCK_SIZE( operation->slot->type ) != 16 )
+            if( PSA_BLOCK_CIPHER_BLOCK_SIZE( operation->slot->attr.type ) != 16 )
                 return( PSA_ERROR_INVALID_ARGUMENT );
             mbedtls_gcm_init( &operation->ctx.gcm );
             status = mbedtls_to_psa_error(
@@ -4659,7 +4745,7 @@
     size_t bytes = PSA_BITS_TO_BYTES( bits );
     psa_status_t status;
 
-    if( ! key_type_is_raw_bytes( slot->type ) )
+    if( ! key_type_is_raw_bytes( slot->attr.type ) )
         return( PSA_ERROR_INVALID_ARGUMENT );
     if( bits % 8 != 0 )
         return( PSA_ERROR_INVALID_ARGUMENT );
@@ -4671,7 +4757,7 @@
     if( status != PSA_SUCCESS )
         goto exit;
 #if defined(MBEDTLS_DES_C)
-    if( slot->type == PSA_KEY_TYPE_DES )
+    if( slot->attr.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 );
@@ -4699,7 +4785,7 @@
     if( status == PSA_SUCCESS )
     {
         status = psa_generate_derived_key_internal( slot,
-                                                    attributes->bits,
+                                                    attributes->core.bits,
                                                     operation );
     }
     if( status == PSA_SUCCESS )
@@ -4980,7 +5066,7 @@
     if( status != PSA_SUCCESS )
         return( status );
 
-    if( slot->type != PSA_KEY_TYPE_DERIVE )
+    if( slot->attr.type != PSA_KEY_TYPE_DERIVE )
         return( PSA_ERROR_INVALID_ARGUMENT );
 
     status = psa_key_derivation_internal( operation,
@@ -5355,7 +5441,7 @@
                                       operation->alg );
     if( status != PSA_SUCCESS )
         return( status );
-    if( slot->type != PSA_KEY_TYPE_DERIVE )
+    if( slot->attr.type != PSA_KEY_TYPE_DERIVE )
         return( PSA_ERROR_INVALID_ARGUMENT );
     /* Don't allow a key to be used as an input that is usually public.
      * This is debatable. It's ok from a cryptographic perspective to
@@ -5435,7 +5521,7 @@
     {
 #if defined(MBEDTLS_ECDH_C)
         case PSA_ALG_ECDH:
-            if( ! PSA_KEY_TYPE_IS_ECC_KEY_PAIR( private_key->type ) )
+            if( ! PSA_KEY_TYPE_IS_ECC_KEY_PAIR( private_key->attr.type ) )
                 return( PSA_ERROR_INVALID_ARGUMENT );
             return( psa_key_agreement_ecdh( peer_key, peer_key_length,
                                             private_key->data.ecp,
@@ -5564,6 +5650,17 @@
     int ret;
     GUARD_MODULE_INITIALIZED;
 
+    while( output_size > MBEDTLS_CTR_DRBG_MAX_REQUEST )
+    {
+        ret = mbedtls_ctr_drbg_random( &global_data.ctr_drbg,
+                                       output,
+                                       MBEDTLS_CTR_DRBG_MAX_REQUEST );
+        if( ret != 0 )
+            return( mbedtls_to_psa_error( ret ) );
+        output += MBEDTLS_CTR_DRBG_MAX_REQUEST;
+        output_size -= MBEDTLS_CTR_DRBG_MAX_REQUEST;
+    }
+
     ret = mbedtls_ctr_drbg_random( &global_data.ctr_drbg, output, output_size );
     return( mbedtls_to_psa_error( ret ) );
 }
@@ -5618,7 +5715,7 @@
     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;
+    psa_key_type_t type = slot->attr.type;
 
     if( domain_parameters == NULL && domain_parameters_size != 0 )
         return( PSA_ERROR_INVALID_ARGUMENT );
@@ -5632,10 +5729,7 @@
         status = psa_generate_random( slot->data.raw.data,
                                       slot->data.raw.bytes );
         if( status != PSA_SUCCESS )
-        {
-            mbedtls_free( slot->data.raw.data );
             return( status );
-        }
 #if defined(MBEDTLS_DES_C)
         if( type == PSA_KEY_TYPE_DES )
             psa_des_set_key_parity( slot->data.raw.data,
@@ -5737,7 +5831,7 @@
     if( status == PSA_SUCCESS )
     {
         status = psa_generate_key_internal(
-            slot, attributes->bits,
+            slot, attributes->core.bits,
             attributes->domain_parameters, attributes->domain_parameters_size );
     }
     if( status == PSA_SUCCESS )
diff --git a/library/psa_crypto_core.h b/library/psa_crypto_core.h
index 6096810..fbfb6da 100644
--- a/library/psa_crypto_core.h
+++ b/library/psa_crypto_core.h
@@ -39,11 +39,7 @@
  */
 typedef struct
 {
-    psa_key_type_t type;
-    psa_key_policy_t policy;
-    psa_key_lifetime_t lifetime;
-    psa_key_file_id_t persistent_storage_id;
-    unsigned allocated : 1;
+    psa_core_key_attributes_t attr;
     union
     {
         /* Raw-data key (key_type_is_raw_bytes() in psa_crypto.c) */
@@ -68,6 +64,70 @@
     } data;
 } psa_key_slot_t;
 
+/** Test whether a key slot is occupied.
+ *
+ * A key slot is occupied iff the key type is nonzero. This works because
+ * no valid key can have 0 as its key type.
+ *
+ * \param[in] slot      The key slot to test.
+ *
+ * \return 1 if the slot is occupied, 0 otherwise.
+ */
+static inline int psa_is_key_slot_occupied( const psa_key_slot_t *slot )
+{
+    return( slot->attr.type != 0 );
+}
+
+/** Retrieve flags from psa_key_slot_t::attr::core::flags.
+ *
+ * \param[in] slot      The key slot to query.
+ * \param mask          The mask of bits to extract.
+ *
+ * \return The key attribute flags in the given slot,
+ *         bitwise-anded with \p mask.
+ */
+static inline uint16_t psa_key_slot_get_flags( const psa_key_slot_t *slot,
+                                               uint16_t mask )
+{
+    return( slot->attr.flags & mask );
+}
+
+/** Set flags in psa_key_slot_t::attr::core::flags.
+ *
+ * \param[in,out] slot  The key slot to modify.
+ * \param mask          The mask of bits to modify.
+ * \param value         The new value of the selected bits.
+ */
+static inline void psa_key_slot_set_flags( psa_key_slot_t *slot,
+                                           uint16_t mask,
+                                           uint16_t value )
+{
+    slot->attr.flags = ( ( ~mask & slot->attr.flags ) |
+                              ( mask & value ) );
+}
+
+/** Turn on flags in psa_key_slot_t::attr::core::flags.
+ *
+ * \param[in,out] slot  The key slot to modify.
+ * \param mask          The mask of bits to set.
+ */
+static inline void psa_key_slot_set_bits_in_flags( psa_key_slot_t *slot,
+                                                   uint16_t mask )
+{
+    slot->attr.flags |= mask;
+}
+
+/** Turn off flags in psa_key_slot_t::attr::core::flags.
+ *
+ * \param[in,out] slot  The key slot to modify.
+ * \param mask          The mask of bits to clear.
+ */
+static inline void psa_key_slot_clear_bits( psa_key_slot_t *slot,
+                                            uint16_t mask )
+{
+    slot->attr.flags &= ~mask;
+}
+
 /** Completely wipe a slot in memory, including its policy.
  *
  * Persistent storage is not affected.
diff --git a/library/psa_crypto_se.c b/library/psa_crypto_se.c
index 9451e52..bc73251 100644
--- a/library/psa_crypto_se.c
+++ b/library/psa_crypto_se.c
@@ -204,7 +204,7 @@
     psa_drv_se_allocate_key_t p_allocate = NULL;
 
     /* If the lifetime is wrong, it's a bug in the library. */
-    if( driver->lifetime != attributes->lifetime )
+    if( driver->lifetime != psa_get_key_lifetime( attributes ) )
         return( PSA_ERROR_CORRUPTION_DETECTED );
 
     /* If the driver doesn't support key creation in any way, give up now. */
diff --git a/library/psa_crypto_se.h b/library/psa_crypto_se.h
index 08e658c..378c78f 100644
--- a/library/psa_crypto_se.h
+++ b/library/psa_crypto_se.h
@@ -171,4 +171,13 @@
  */
 psa_status_t psa_destroy_se_persistent_data( psa_key_lifetime_t lifetime );
 
+
+/** The storage representation of a key whose data is in a secure element.
+ */
+typedef struct
+{
+    uint8_t slot_number[sizeof( psa_key_slot_number_t )];
+    uint8_t bits[sizeof( psa_key_bits_t )];
+} psa_se_key_data_storage_t;
+
 #endif /* PSA_CRYPTO_SE_H */
diff --git a/library/psa_crypto_slot_management.c b/library/psa_crypto_slot_management.c
index 6b87ea0..0734009 100644
--- a/library/psa_crypto_slot_management.c
+++ b/library/psa_crypto_slot_management.c
@@ -33,6 +33,9 @@
 #include "psa_crypto_core.h"
 #include "psa_crypto_slot_management.h"
 #include "psa_crypto_storage.h"
+#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
+#include "psa_crypto_se.h"
+#endif
 
 #include <stdlib.h>
 #include <string.h>
@@ -71,8 +74,8 @@
         return( PSA_ERROR_INVALID_HANDLE );
     slot = &global_data.key_slots[handle - 1];
 
-    /* If the slot hasn't been allocated, the handle is invalid. */
-    if( ! slot->allocated )
+    /* If the slot isn't occupied, the handle is invalid. */
+    if( ! psa_is_key_slot_occupied( slot ) )
         return( PSA_ERROR_INVALID_HANDLE );
 
     *p_slot = slot;
@@ -108,49 +111,44 @@
     for( *handle = PSA_KEY_SLOT_COUNT; *handle != 0; --( *handle ) )
     {
         *p_slot = &global_data.key_slots[*handle - 1];
-        if( ! ( *p_slot )->allocated )
-        {
-            ( *p_slot )->allocated = 1;
+        if( ! psa_is_key_slot_occupied( *p_slot ) )
             return( PSA_SUCCESS );
-        }
     }
     *p_slot = NULL;
     return( PSA_ERROR_INSUFFICIENT_MEMORY );
 }
 
 #if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C)
-static psa_status_t psa_load_persistent_key_into_slot( psa_key_slot_t *p_slot )
+static psa_status_t psa_load_persistent_key_into_slot( psa_key_slot_t *slot )
 {
     psa_status_t status = PSA_SUCCESS;
     uint8_t *key_data = NULL;
     size_t key_data_length = 0;
-    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
 
-    psa_set_key_id( &attributes, p_slot->persistent_storage_id );
-    status = psa_load_persistent_key( &attributes,
+    status = psa_load_persistent_key( &slot->attr,
                                       &key_data, &key_data_length );
     if( status != PSA_SUCCESS )
         goto exit;
-    p_slot->lifetime = psa_get_key_lifetime( &attributes );
-    p_slot->type = psa_get_key_type( &attributes );
-    p_slot->policy = attributes.policy;
 
 #if defined(MBEDTLS_PSA_CRYPTO_SE_C)
-    if( psa_key_lifetime_is_external( p_slot->lifetime ) )
+    if( psa_key_lifetime_is_external( slot->attr.lifetime ) )
     {
-        if( key_data_length != sizeof( p_slot->data.se.slot_number ) )
+        psa_se_key_data_storage_t *data;
+        if( key_data_length != sizeof( *data ) )
         {
             status = PSA_ERROR_STORAGE_FAILURE;
             goto exit;
         }
-        memcpy( &p_slot->data.se.slot_number, key_data,
-                sizeof( p_slot->data.se.slot_number ) );
+        data = (psa_se_key_data_storage_t *) key_data;
+        memcpy( &slot->data.se.slot_number, &data->slot_number,
+                sizeof( slot->data.se.slot_number ) );
+        memcpy( &slot->attr.bits, &data->bits,
+                sizeof( slot->attr.bits ) );
     }
     else
 #endif /* MBEDTLS_PSA_CRYPTO_SE_C */
     {
-        status = psa_import_key_into_slot( p_slot,
-                                           key_data, key_data_length );
+        status = psa_import_key_into_slot( slot, key_data, key_data_length );
     }
 
 exit:
@@ -234,8 +232,8 @@
     if( status != PSA_SUCCESS )
         return( status );
 
-    slot->lifetime = PSA_KEY_LIFETIME_PERSISTENT;
-    slot->persistent_storage_id = id;
+    slot->attr.lifetime = PSA_KEY_LIFETIME_PERSISTENT;
+    slot->attr.id = id;
 
     status = psa_load_persistent_key_into_slot( slot );
     if( status != PSA_SUCCESS )
@@ -270,28 +268,25 @@
     memset( stats, 0, sizeof( *stats ) );
     for( key = 1; key <= PSA_KEY_SLOT_COUNT; key++ )
     {
-        psa_key_slot_t *slot = &global_data.key_slots[key - 1];
-        if( slot->type == PSA_KEY_TYPE_NONE )
+        const psa_key_slot_t *slot = &global_data.key_slots[key - 1];
+        if( ! psa_is_key_slot_occupied( slot ) )
         {
-            if( slot->allocated )
-                ++stats->half_filled_slots;
-            else
-                ++stats->empty_slots;
+            ++stats->empty_slots;
             continue;
         }
-        if( slot->lifetime == PSA_KEY_LIFETIME_VOLATILE )
+        if( slot->attr.lifetime == PSA_KEY_LIFETIME_VOLATILE )
             ++stats->volatile_slots;
-        else if( slot->lifetime == PSA_KEY_LIFETIME_PERSISTENT )
+        else if( slot->attr.lifetime == PSA_KEY_LIFETIME_PERSISTENT )
         {
             ++stats->persistent_slots;
-            if( slot->persistent_storage_id > stats->max_open_internal_key_id )
-                stats->max_open_internal_key_id = slot->persistent_storage_id;
+            if( slot->attr.id > stats->max_open_internal_key_id )
+                stats->max_open_internal_key_id = slot->attr.id;
         }
         else
         {
             ++stats->external_slots;
-            if( slot->persistent_storage_id > stats->max_open_external_key_id )
-                stats->max_open_external_key_id = slot->persistent_storage_id;
+            if( slot->attr.id > stats->max_open_external_key_id )
+                stats->max_open_external_key_id = slot->attr.id;
         }
     }
 }
diff --git a/library/psa_crypto_slot_management.h b/library/psa_crypto_slot_management.h
index 049520d..cde590f 100644
--- a/library/psa_crypto_slot_management.h
+++ b/library/psa_crypto_slot_management.h
@@ -58,13 +58,13 @@
  * This does not affect persistent storage. */
 void psa_wipe_all_key_slots( void );
 
-/** Find a free key slot and mark it as in use.
+/** Find a free key slot.
+ *
+ * This function returns a key slot that is available for use and is in its
+ * ground state (all-bits-zero).
  *
  * \param[out] handle   On success, a slot number that can be used as a
- *                      handle to the slot. The selected slot was not
- *                      in use before. This function marks it as in use
- *                      and otherwise leaves it in a freshly-initialized
- *                      state.
+ *                      handle to the slot.
  * \param[out] p_slot   On success, a pointer to the slot.
  *
  * \retval #PSA_SUCCESS
diff --git a/library/psa_crypto_storage.c b/library/psa_crypto_storage.c
index 687d22a..a27442c 100644
--- a/library/psa_crypto_storage.c
+++ b/library/psa_crypto_storage.c
@@ -267,7 +267,7 @@
 
 void psa_format_key_data_for_storage( const uint8_t *data,
                                       const size_t data_length,
-                                      const psa_key_attributes_t *attributes,
+                                      const psa_core_key_attributes_t *attr,
                                       uint8_t *storage_data )
 {
     psa_persistent_key_storage_format *storage_format =
@@ -275,11 +275,11 @@
 
     memcpy( storage_format->magic, PSA_KEY_STORAGE_MAGIC_HEADER, PSA_KEY_STORAGE_MAGIC_HEADER_LENGTH );
     PUT_UINT32_LE( 0, storage_format->version, 0 );
-    PUT_UINT32_LE( psa_get_key_lifetime( attributes ), storage_format->lifetime, 0 );
-    PUT_UINT32_LE( psa_get_key_type( attributes ), storage_format->type, 0 );
-    PUT_UINT32_LE( psa_get_key_usage_flags( attributes ), storage_format->policy, 0 );
-    PUT_UINT32_LE( psa_get_key_algorithm( attributes ), storage_format->policy, sizeof( uint32_t ) );
-    PUT_UINT32_LE( psa_get_key_enrollment_algorithm( attributes ), storage_format->policy, 2 * sizeof( uint32_t ) );
+    PUT_UINT32_LE( attr->lifetime, storage_format->lifetime, 0 );
+    PUT_UINT32_LE( attr->type, storage_format->type, 0 );
+    PUT_UINT32_LE( attr->policy.usage, storage_format->policy, 0 );
+    PUT_UINT32_LE( attr->policy.alg, storage_format->policy, sizeof( uint32_t ) );
+    PUT_UINT32_LE( attr->policy.alg2, storage_format->policy, 2 * sizeof( uint32_t ) );
     PUT_UINT32_LE( data_length, storage_format->data_len, 0 );
     memcpy( storage_format->key_data, data, data_length );
 }
@@ -296,7 +296,7 @@
                                               size_t storage_data_length,
                                               uint8_t **key_data,
                                               size_t *key_data_length,
-                                              psa_key_attributes_t *attributes )
+                                              psa_core_key_attributes_t *attr )
 {
     psa_status_t status;
     const psa_persistent_key_storage_format *storage_format =
@@ -331,16 +331,16 @@
         memcpy( *key_data, storage_format->key_data, *key_data_length );
     }
 
-    GET_UINT32_LE( attributes->lifetime, storage_format->lifetime, 0 );
-    GET_UINT32_LE( attributes->type, storage_format->type, 0 );
-    GET_UINT32_LE( attributes->policy.usage, storage_format->policy, 0 );
-    GET_UINT32_LE( attributes->policy.alg, storage_format->policy, sizeof( uint32_t ) );
-    GET_UINT32_LE( attributes->policy.alg2, storage_format->policy, 2 * sizeof( uint32_t ) );
+    GET_UINT32_LE( attr->lifetime, storage_format->lifetime, 0 );
+    GET_UINT32_LE( attr->type, storage_format->type, 0 );
+    GET_UINT32_LE( attr->policy.usage, storage_format->policy, 0 );
+    GET_UINT32_LE( attr->policy.alg, storage_format->policy, sizeof( uint32_t ) );
+    GET_UINT32_LE( attr->policy.alg2, storage_format->policy, 2 * sizeof( uint32_t ) );
 
     return( PSA_SUCCESS );
 }
 
-psa_status_t psa_save_persistent_key( const psa_key_attributes_t *attributes,
+psa_status_t psa_save_persistent_key( const psa_core_key_attributes_t *attr,
                                       const uint8_t *data,
                                       const size_t data_length )
 {
@@ -356,10 +356,9 @@
     if( storage_data == NULL )
         return( PSA_ERROR_INSUFFICIENT_MEMORY );
 
-    psa_format_key_data_for_storage( data, data_length, attributes,
-                                     storage_data );
+    psa_format_key_data_for_storage( data, data_length, attr, storage_data );
 
-    status = psa_crypto_storage_store( psa_get_key_id( attributes ),
+    status = psa_crypto_storage_store( attr->id,
                                        storage_data, storage_data_length );
 
     mbedtls_free( storage_data );
@@ -376,14 +375,14 @@
     mbedtls_free( key_data );
 }
 
-psa_status_t psa_load_persistent_key( psa_key_attributes_t *attributes,
+psa_status_t psa_load_persistent_key( psa_core_key_attributes_t *attr,
                                       uint8_t **data,
                                       size_t *data_length )
 {
     psa_status_t status = PSA_SUCCESS;
     uint8_t *loaded_data;
     size_t storage_data_length = 0;
-    psa_key_id_t key = psa_get_key_id( attributes );
+    psa_key_id_t key = attr->id;
 
     status = psa_crypto_storage_get_data_length( key, &storage_data_length );
     if( status != PSA_SUCCESS )
@@ -399,7 +398,7 @@
         goto exit;
 
     status = psa_parse_key_data_from_storage( loaded_data, storage_data_length,
-                                              data, data_length, attributes );
+                                              data, data_length, attr );
 
 exit:
     mbedtls_free( loaded_data );
diff --git a/library/psa_crypto_storage.h b/library/psa_crypto_storage.h
index 8fe20ac..1b7dbd6 100644
--- a/library/psa_crypto_storage.h
+++ b/library/psa_crypto_storage.h
@@ -35,9 +35,14 @@
 #include <stdint.h>
 #include <string.h>
 
-/* Limit the maximum key size to 30kB (just in case someone tries to
- * inadvertently store an obscene amount of data) */
-#define PSA_CRYPTO_MAX_STORAGE_SIZE ( 30 * 1024 )
+/* Limit the maximum key size in storage. This should have no effect
+ * since the key size is limited in memory. */
+#define PSA_CRYPTO_MAX_STORAGE_SIZE ( PSA_BITS_TO_BYTES( PSA_MAX_KEY_BITS ) )
+/* Sanity check: a file size must fit in 32 bits. Allow a generous
+ * 64kB of metadata. */
+#if PSA_CRYPTO_MAX_STORAGE_SIZE > 0xffff0000
+#error PSA_CRYPTO_MAX_STORAGE_SIZE > 0xffff0000
+#endif
 
 /** The maximum permitted persistent slot number.
  *
@@ -83,7 +88,7 @@
  * already occupied non-persistent key, as well as validating the key data.
  *
  *
- * \param[in] attributes    The attributes of the key to save.
+ * \param[in] attr          The attributes of the key to save.
  *                          The key identifier field in the attributes
  *                          determines the key's location.
  * \param[in] data          Buffer containing the key data.
@@ -95,7 +100,7 @@
  * \retval PSA_ERROR_STORAGE_FAILURE
  * \retval PSA_ERROR_ALREADY_EXISTS
  */
-psa_status_t psa_save_persistent_key( const psa_key_attributes_t *attributes,
+psa_status_t psa_save_persistent_key( const psa_core_key_attributes_t *attr,
                                       const uint8_t *data,
                                       const size_t data_length );
 
@@ -111,8 +116,7 @@
  * this function to zeroize and free this buffer, regardless of whether this
  * function succeeds or fails.
  *
- * \param[in,out] attributes
- *                          On input, the key identifier field identifies
+ * \param[in,out] attr      On input, the key identifier field identifies
  *                          the key to load. Other fields are ignored.
  *                          On success, the attribute structure contains
  *                          the key metadata that was loaded from storage.
@@ -124,7 +128,7 @@
  * \retval PSA_ERROR_STORAGE_FAILURE
  * \retval PSA_ERROR_DOES_NOT_EXIST
  */
-psa_status_t psa_load_persistent_key( psa_key_attributes_t *attributes,
+psa_status_t psa_load_persistent_key( psa_core_key_attributes_t *attr,
                                       uint8_t **data,
                                       size_t *data_length );
 
@@ -158,13 +162,13 @@
  *
  * \param[in] data          Buffer containing the key data.
  * \param data_length       Length of the key data buffer.
- * \param[in] attributes    The attributes of the key.
+ * \param[in] attr          The core attributes of the key.
  * \param[out] storage_data Output buffer for the formatted data.
  *
  */
 void psa_format_key_data_for_storage( const uint8_t *data,
                                       const size_t data_length,
-                                      const psa_key_attributes_t *attributes,
+                                      const psa_core_key_attributes_t *attr,
                                       uint8_t *storage_data );
 
 /**
@@ -176,7 +180,7 @@
  *                             containing the key data. This must be freed
  *                             using psa_free_persistent_key_data()
  * \param[out] key_data_length Length of the key data buffer
- * \param[out] attributes      On success, the attribute structure is filled
+ * \param[out] attr            On success, the attribute structure is filled
  *                             with the loaded key metadata.
  *
  * \retval PSA_SUCCESS
@@ -188,7 +192,7 @@
                                               size_t storage_data_length,
                                               uint8_t **key_data,
                                               size_t *key_data_length,
-                                              psa_key_attributes_t *attributes );
+                                              psa_core_key_attributes_t *attr );
 
 #if defined(MBEDTLS_PSA_CRYPTO_SE_C)
 /** This symbol is defined if transaction support is required. */
diff --git a/tests/suites/test_suite_psa_crypto.data b/tests/suites/test_suite_psa_crypto.data
index 53f8422..b049840 100644
--- a/tests/suites/test_suite_psa_crypto.data
+++ b/tests/suites/test_suite_psa_crypto.data
@@ -52,9 +52,18 @@
 PSA invalid handle (largest plausible handle)
 invalid_handle:-1
 
+PSA import: bad usage flag
+import_with_policy:PSA_KEY_TYPE_RAW_DATA:0x40000000:0:PSA_ERROR_INVALID_ARGUMENT
+
+PSA import: invalid type (0)
+import_with_policy:PSA_KEY_TYPE_NONE:0:0:PSA_ERROR_NOT_SUPPORTED
+
+PSA import: invalid type (PSA_KEY_TYPE_CATEGORY_MASK)
+import_with_policy:PSA_KEY_TYPE_CATEGORY_MASK:0:0:PSA_ERROR_NOT_SUPPORTED
+
 PSA import AES: bad key size
 depends_on:MBEDTLS_AES_C
-import:"0123456789abcdef":PSA_KEY_TYPE_AES:0:PSA_ERROR_INVALID_ARGUMENT
+import_with_data:"0123456789abcdef":PSA_KEY_TYPE_AES:0:PSA_ERROR_INVALID_ARGUMENT
 
 PSA import/export RSA public key: good, 1024-bit
 depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_RSA_C
@@ -110,19 +119,19 @@
 
 PSA import RSA keypair: truncated
 depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C
-import:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b":PSA_KEY_TYPE_RSA_KEY_PAIR:0:PSA_ERROR_INVALID_ARGUMENT
+import_with_data:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b":PSA_KEY_TYPE_RSA_KEY_PAIR:0:PSA_ERROR_INVALID_ARGUMENT
 
 PSA import RSA keypair: public key
 depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C
-import:"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_KEY_TYPE_RSA_KEY_PAIR:0:PSA_ERROR_INVALID_ARGUMENT
+import_with_data:"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_KEY_TYPE_RSA_KEY_PAIR:0:PSA_ERROR_INVALID_ARGUMENT
 
 PSA import RSA public key: key pair
 depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C
-import:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b":PSA_KEY_TYPE_RSA_PUBLIC_KEY:0:PSA_ERROR_INVALID_ARGUMENT
+import_with_data:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b":PSA_KEY_TYPE_RSA_PUBLIC_KEY:0:PSA_ERROR_INVALID_ARGUMENT
 
 PSA import RSA keypair: valid key but EC
 depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C
-import:"3077020101042049c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eeea00a06082a8648ce3d030107a144034200047772656f814b399279d5e1f1781fac6f099a3c5ca1b0e35351834b08b65e0b572590cdaf8f769361bcf34acfc11e5e074e8426bdde04be6e653945449617de45":PSA_KEY_TYPE_RSA_KEY_PAIR:0:PSA_ERROR_INVALID_ARGUMENT
+import_with_data:"3077020101042049c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eeea00a06082a8648ce3d030107a144034200047772656f814b399279d5e1f1781fac6f099a3c5ca1b0e35351834b08b65e0b572590cdaf8f769361bcf34acfc11e5e074e8426bdde04be6e653945449617de45":PSA_KEY_TYPE_RSA_KEY_PAIR:0:PSA_ERROR_INVALID_ARGUMENT
 
 PSA import/export-public RSA public key: good, 1024-bit
 depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_RSA_C
@@ -150,19 +159,19 @@
 
 PSA import RSA public key: 1022-bit (not supported)
 depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_RSA_C
-import:"30818802818036e4b95f847dcd7a91b0972b7ba096e040ec04e42d59f733029fb2600b8ae9e4fd8ea76f3d7ec576288102285b612db7abc53770006046fef321172a6ad84053710d48528a8d51b6481db53c09e1524d6704b58bd30313016535eefe9bcff89eb599608daaa0a72ab7720af31486b51020421fdd3c6974cc445a78dd134450230203010001":PSA_KEY_TYPE_RSA_PUBLIC_KEY:0:PSA_ERROR_NOT_SUPPORTED
+import_with_data:"30818802818036e4b95f847dcd7a91b0972b7ba096e040ec04e42d59f733029fb2600b8ae9e4fd8ea76f3d7ec576288102285b612db7abc53770006046fef321172a6ad84053710d48528a8d51b6481db53c09e1524d6704b58bd30313016535eefe9bcff89eb599608daaa0a72ab7720af31486b51020421fdd3c6974cc445a78dd134450230203010001":PSA_KEY_TYPE_RSA_PUBLIC_KEY:0:PSA_ERROR_NOT_SUPPORTED
 
 PSA import RSA keypair: 1022-bit (not supported)
 depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_RSA_C
-import:"3082025802010002818036e4b95f847dcd7a91b0972b7ba096e040ec04e42d59f733029fb2600b8ae9e4fd8ea76f3d7ec576288102285b612db7abc53770006046fef321172a6ad84053710d48528a8d51b6481db53c09e1524d6704b58bd30313016535eefe9bcff89eb599608daaa0a72ab7720af31486b51020421fdd3c6974cc445a78dd1344502302030100010281800ad9700e01e8bf68ff4c90c4465dfa13fea0e76295d817349ccb257d382acf89b3d7b31e18606af4ac92baf3710426fe0b54225ddfa527c31218b3346e03a9cae5395a780ade880b996f4061fad65689393fc8e77f46a4c1a29b0450cdaaef0710e523cd1028abe1653d23f0d5ec805a629bdf1fc4c1c00737760e1714f6b7f102407d5e545484b546bd61972b446a04af0cf17b126a8872b977da5035ca82dd0e4fef1381a6480f60db07628348602f86ba89a271563d9a3fb613b9b39703498f9902407017641093065eed178ff848b5f8a2b502a187511db28549ea7646f3e7b3ea171f4c34c0ecf0566adc4d172c057be077a45fcf8019a36a4588c4de3b8c0a631b02407cc7fccbbae2eb2be80c9c8615b7dfbbd4469907ec13b44274cacd1f69ad38679b2021352e18106131327e54f5579893e6160714bd6fdfe60c30136e45595c51024055250f779f96f94873db82a808c24325e847b6b8212cd81e9ba118a8715ab2f8b96773b310c8477c88b76e609c11cb22569408d4afa4f836b57b85ac09e661fd02400e5fc5df9614c95d77e9bc2df63d48e7a08a0034174f0f745eef4413ee36d929f194557e6990e148b7438e949a41e92bc9d9136c3e6563904151a578a2f4fc1b":PSA_KEY_TYPE_RSA_KEY_PAIR:0:PSA_ERROR_NOT_SUPPORTED
+import_with_data:"3082025802010002818036e4b95f847dcd7a91b0972b7ba096e040ec04e42d59f733029fb2600b8ae9e4fd8ea76f3d7ec576288102285b612db7abc53770006046fef321172a6ad84053710d48528a8d51b6481db53c09e1524d6704b58bd30313016535eefe9bcff89eb599608daaa0a72ab7720af31486b51020421fdd3c6974cc445a78dd1344502302030100010281800ad9700e01e8bf68ff4c90c4465dfa13fea0e76295d817349ccb257d382acf89b3d7b31e18606af4ac92baf3710426fe0b54225ddfa527c31218b3346e03a9cae5395a780ade880b996f4061fad65689393fc8e77f46a4c1a29b0450cdaaef0710e523cd1028abe1653d23f0d5ec805a629bdf1fc4c1c00737760e1714f6b7f102407d5e545484b546bd61972b446a04af0cf17b126a8872b977da5035ca82dd0e4fef1381a6480f60db07628348602f86ba89a271563d9a3fb613b9b39703498f9902407017641093065eed178ff848b5f8a2b502a187511db28549ea7646f3e7b3ea171f4c34c0ecf0566adc4d172c057be077a45fcf8019a36a4588c4de3b8c0a631b02407cc7fccbbae2eb2be80c9c8615b7dfbbd4469907ec13b44274cacd1f69ad38679b2021352e18106131327e54f5579893e6160714bd6fdfe60c30136e45595c51024055250f779f96f94873db82a808c24325e847b6b8212cd81e9ba118a8715ab2f8b96773b310c8477c88b76e609c11cb22569408d4afa4f836b57b85ac09e661fd02400e5fc5df9614c95d77e9bc2df63d48e7a08a0034174f0f745eef4413ee36d929f194557e6990e148b7438e949a41e92bc9d9136c3e6563904151a578a2f4fc1b":PSA_KEY_TYPE_RSA_KEY_PAIR:0:PSA_ERROR_NOT_SUPPORTED
 
 PSA import RSA public key: 1023-bit (not supported)
 depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_RSA_C
-import:"3081880281806c49704e91f3df44fc99e9b3c0fee5025cc04d09529a1dd05754f2da2751d7a9aa5a79f7070132f2c47b31963e37cd74675f9c93ee7c85a143fefe303e94d1ee0e4d30898d17ab3a229e8457ef21fd179039f748305babe7f134f6d58ce5d721a1a5da98f63503d2466c6a515e53494a41180a91e535bd5b55d4dce2c17419870203010001":PSA_KEY_TYPE_RSA_PUBLIC_KEY:0:PSA_ERROR_NOT_SUPPORTED
+import_with_data:"3081880281806c49704e91f3df44fc99e9b3c0fee5025cc04d09529a1dd05754f2da2751d7a9aa5a79f7070132f2c47b31963e37cd74675f9c93ee7c85a143fefe303e94d1ee0e4d30898d17ab3a229e8457ef21fd179039f748305babe7f134f6d58ce5d721a1a5da98f63503d2466c6a515e53494a41180a91e535bd5b55d4dce2c17419870203010001":PSA_KEY_TYPE_RSA_PUBLIC_KEY:0:PSA_ERROR_NOT_SUPPORTED
 
 PSA import RSA keypair: 1023-bit (not supported)
 depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_RSA_C
-import:"3082025a0201000281806c49704e91f3df44fc99e9b3c0fee5025cc04d09529a1dd05754f2da2751d7a9aa5a79f7070132f2c47b31963e37cd74675f9c93ee7c85a143fefe303e94d1ee0e4d30898d17ab3a229e8457ef21fd179039f748305babe7f134f6d58ce5d721a1a5da98f63503d2466c6a515e53494a41180a91e535bd5b55d4dce2c17419870203010001028180491b277413fb35efe82dace68b544a9dd6aa8917d329731955ec66ec3b0178fcf5a29196e1a6c093bf6c8064b36a8f0d9840a78003d11392754a70a77788975515a1442a6c806cafa2f07fe99cac78a86fa868888d654cec4baf205352cf8255acaa47e2455f23b58c0e5ae43fa297bbffe5b970caa80f71e82084fd35425479024100ef27f3fb2df90ac4910ed95fdde4877d09b0dc4e95079f12a7e2041300a8884a39372a1c79691338cd5c3965bcf3a24f2ce9e10de19d4cb87c7546d60ca0aa0d024073e9e1283475e9ab3075da0b005ca7c7b05e76325f8deb648238831c8353041d594307f784cd527cfee9187b997713d71c0ff98f01beac4d1a85583be52e90e302402f0c801e311c2677274671933f96fee4a56c6adaf6ccaa09c4875d5fd3a8542fadf3e14ffabea62e6d90302688b6b17ebc0a42e1353a79e66d6db102d9371e5d02406731ef3c8607fbf266806590a9cfd3a79a435ee355e2d9906fc6b4236c5f3a288ed178844a7d295512f49ed15b3d82325e4f729478af3262aa9bd083f273d49502410090a32c0e8ca3bcd4c66f092cdc369cd1abb4a05b9a6f0e65e5a51da1d96d5aca8c1525b3f11322c0588062fc8592ebf25b7950f918d39018e82b8acccc8f7e7a":PSA_KEY_TYPE_RSA_KEY_PAIR:0:PSA_ERROR_NOT_SUPPORTED
+import_with_data:"3082025a0201000281806c49704e91f3df44fc99e9b3c0fee5025cc04d09529a1dd05754f2da2751d7a9aa5a79f7070132f2c47b31963e37cd74675f9c93ee7c85a143fefe303e94d1ee0e4d30898d17ab3a229e8457ef21fd179039f748305babe7f134f6d58ce5d721a1a5da98f63503d2466c6a515e53494a41180a91e535bd5b55d4dce2c17419870203010001028180491b277413fb35efe82dace68b544a9dd6aa8917d329731955ec66ec3b0178fcf5a29196e1a6c093bf6c8064b36a8f0d9840a78003d11392754a70a77788975515a1442a6c806cafa2f07fe99cac78a86fa868888d654cec4baf205352cf8255acaa47e2455f23b58c0e5ae43fa297bbffe5b970caa80f71e82084fd35425479024100ef27f3fb2df90ac4910ed95fdde4877d09b0dc4e95079f12a7e2041300a8884a39372a1c79691338cd5c3965bcf3a24f2ce9e10de19d4cb87c7546d60ca0aa0d024073e9e1283475e9ab3075da0b005ca7c7b05e76325f8deb648238831c8353041d594307f784cd527cfee9187b997713d71c0ff98f01beac4d1a85583be52e90e302402f0c801e311c2677274671933f96fee4a56c6adaf6ccaa09c4875d5fd3a8542fadf3e14ffabea62e6d90302688b6b17ebc0a42e1353a79e66d6db102d9371e5d02406731ef3c8607fbf266806590a9cfd3a79a435ee355e2d9906fc6b4236c5f3a288ed178844a7d295512f49ed15b3d82325e4f729478af3262aa9bd083f273d49502410090a32c0e8ca3bcd4c66f092cdc369cd1abb4a05b9a6f0e65e5a51da1d96d5aca8c1525b3f11322c0588062fc8592ebf25b7950f918d39018e82b8acccc8f7e7a":PSA_KEY_TYPE_RSA_KEY_PAIR:0:PSA_ERROR_NOT_SUPPORTED
 
 PSA import/export EC secp224r1 key pair: good
 depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP224R1_ENABLED
@@ -256,31 +265,31 @@
 
 PSA import EC keypair: DER format
 depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED
-import:"3077020101042049c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eeea00a06082a8648ce3d030107a144034200047772656f814b399279d5e1f1781fac6f099a3c5ca1b0e35351834b08b65e0b572590cdaf8f769361bcf34acfc11e5e074e8426bdde04be6e653945449617de45":PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_CURVE_SECP256R1):0:PSA_ERROR_INVALID_ARGUMENT
+import_with_data:"3077020101042049c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eeea00a06082a8648ce3d030107a144034200047772656f814b399279d5e1f1781fac6f099a3c5ca1b0e35351834b08b65e0b572590cdaf8f769361bcf34acfc11e5e074e8426bdde04be6e653945449617de45":PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_CURVE_SECP256R1):0:PSA_ERROR_INVALID_ARGUMENT
 
 PSA import EC keypair: too short
 depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED
-import:"0123456789abcdef0123456789abcdef":PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_CURVE_SECP256R1):0:PSA_ERROR_INVALID_ARGUMENT
+import_with_data:"0123456789abcdef0123456789abcdef":PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_CURVE_SECP256R1):0:PSA_ERROR_INVALID_ARGUMENT
 
 PSA import EC keypair: public key
 depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED
-import:"04dea5e45d0ea37fc566232a508f4ad20ea13d47e4bf5fa4d54a57a0ba012042087097496efc583fed8b24a5b9be9a51de063f5a00a8b698a16fd7f29b5485f320":PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_CURVE_SECP256R1):0:PSA_ERROR_INVALID_ARGUMENT
+import_with_data:"04dea5e45d0ea37fc566232a508f4ad20ea13d47e4bf5fa4d54a57a0ba012042087097496efc583fed8b24a5b9be9a51de063f5a00a8b698a16fd7f29b5485f320":PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_CURVE_SECP256R1):0:PSA_ERROR_INVALID_ARGUMENT
 
 PSA import EC keypair: secp256r1, all-bits-zero (bad)
 depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED
-import:"0000000000000000000000000000000000000000000000000000000000000000":PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_CURVE_SECP256R1):0:PSA_ERROR_INVALID_ARGUMENT
+import_with_data:"0000000000000000000000000000000000000000000000000000000000000000":PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_CURVE_SECP256R1):0:PSA_ERROR_INVALID_ARGUMENT
 
 PSA import EC keypair: secp256r1, d == n - 1 (good)
 depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED
-import:"ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632550":PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_CURVE_SECP256R1):0:PSA_SUCCESS
+import_with_data:"ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632550":PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_CURVE_SECP256R1):0:PSA_SUCCESS
 
 PSA import EC keypair: secp256r1, d == n (bad)
 depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED
-import:"ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551":PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_CURVE_SECP256R1):0:PSA_ERROR_INVALID_ARGUMENT
+import_with_data:"ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551":PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_CURVE_SECP256R1):0:PSA_ERROR_INVALID_ARGUMENT
 
 PSA import EC keypair: secp256r1, d > n (bad)
 depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED
-import:"ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632552":PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_CURVE_SECP256R1):0:PSA_ERROR_INVALID_ARGUMENT
+import_with_data:"ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632552":PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_CURVE_SECP256R1):0:PSA_ERROR_INVALID_ARGUMENT
 
 PSA import EC public key: key pair
 depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED
@@ -288,31 +297,39 @@
 # one would expect the status to be PSA_ERROR_INVALID_ARGUMENT. But the
 # Mbed TLS pkparse module returns MBEDTLS_ERR_PK_INVALID_ALG, I think because
 # it's looking for an OID where there is no OID.
-import:"3078020101042100ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3aa00a06082a8648ce3d030107a14403420004dea5e45d0ea37fc566232a508f4ad20ea13d47e4bf5fa4d54a57a0ba012042087097496efc583fed8b24a5b9be9a51de063f5a00a8b698a16fd7f29b5485f320":PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_CURVE_SECP256R1):0:PSA_ERROR_NOT_SUPPORTED
+import_with_data:"3078020101042100ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3aa00a06082a8648ce3d030107a14403420004dea5e45d0ea37fc566232a508f4ad20ea13d47e4bf5fa4d54a57a0ba012042087097496efc583fed8b24a5b9be9a51de063f5a00a8b698a16fd7f29b5485f320":PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_CURVE_SECP256R1):0:PSA_ERROR_NOT_SUPPORTED
 
 PSA import EC keypair: valid key but RSA
 depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_BP512R1_ENABLED:MBEDTLS_RSA_C
-import:"3082013b020100024100ee2b131d6b1818a94ca8e91c42387eb15a7c271f57b89e7336b144d4535b16c83097ecdefbbb92d1b5313b5a37214d0e8f25922dca778b424b25295fc8a1a7070203010001024100978ac8eadb0dc6035347d6aba8671215ff21283385396f7897c04baf5e2a835f3b53ef80a82ed36ae687a925380b55a0c73eb85656e989dcf0ed7fb4887024e1022100fdad8e1c6853563f8b921d2d112462ae7d6b176082d2ba43e87e1a37fc1a8b33022100f0592cf4c55ba44307b18981bcdbda376c51e590ffa5345ba866f6962dca94dd02201995f1a967d44ff4a4cd1de837bc65bf97a2bf7eda730a9a62cea53254591105022027f96cf4b8ee68ff8d04062ec1ce7f18c0b74e4b3379b29f9bfea3fc8e592731022100cefa6d220496b43feb83194255d8fb930afcf46f36606e3aa0eb7a93ad88c10c":PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_CURVE_BRAINPOOL_P512R1):0:PSA_ERROR_INVALID_ARGUMENT
+import_with_data:"3082013b020100024100ee2b131d6b1818a94ca8e91c42387eb15a7c271f57b89e7336b144d4535b16c83097ecdefbbb92d1b5313b5a37214d0e8f25922dca778b424b25295fc8a1a7070203010001024100978ac8eadb0dc6035347d6aba8671215ff21283385396f7897c04baf5e2a835f3b53ef80a82ed36ae687a925380b55a0c73eb85656e989dcf0ed7fb4887024e1022100fdad8e1c6853563f8b921d2d112462ae7d6b176082d2ba43e87e1a37fc1a8b33022100f0592cf4c55ba44307b18981bcdbda376c51e590ffa5345ba866f6962dca94dd02201995f1a967d44ff4a4cd1de837bc65bf97a2bf7eda730a9a62cea53254591105022027f96cf4b8ee68ff8d04062ec1ce7f18c0b74e4b3379b29f9bfea3fc8e592731022100cefa6d220496b43feb83194255d8fb930afcf46f36606e3aa0eb7a93ad88c10c":PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_CURVE_BRAINPOOL_P512R1):0:PSA_ERROR_INVALID_ARGUMENT
 
 PSA import AES: bits=0 ok
 depends_on:MBEDTLS_AES_C
-import:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_KEY_TYPE_AES:0:PSA_SUCCESS
+import_with_data:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_KEY_TYPE_AES:0:PSA_SUCCESS
 
 PSA import AES: bits=128 ok
 depends_on:MBEDTLS_AES_C
-import:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_KEY_TYPE_AES:128:PSA_SUCCESS
+import_with_data:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_KEY_TYPE_AES:128:PSA_SUCCESS
 
 PSA import AES: bits=256 wrong
 depends_on:MBEDTLS_AES_C
-import:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_KEY_TYPE_AES:256:PSA_ERROR_INVALID_ARGUMENT
+import_with_data:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_KEY_TYPE_AES:256:PSA_ERROR_INVALID_ARGUMENT
 
 PSA import AES: bits=256 ok
 depends_on:MBEDTLS_AES_C
-import:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_KEY_TYPE_AES:256:PSA_SUCCESS
+import_with_data:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_KEY_TYPE_AES:256:PSA_SUCCESS
 
 PSA import AES: bits=128 wrong
 depends_on:MBEDTLS_AES_C
-import:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_KEY_TYPE_AES:128:PSA_ERROR_INVALID_ARGUMENT
+import_with_data:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa":PSA_KEY_TYPE_AES:128:PSA_ERROR_INVALID_ARGUMENT
+
+PSA import large key: raw, 65528 bits (ok)
+depends_on:HAVE_RAM_AVAILABLE_128K
+import_large_key:PSA_KEY_TYPE_RAW_DATA:8191:PSA_SUCCESS
+
+PSA import large key: raw, 65536 bits (not supported)
+depends_on:HAVE_RAM_AVAILABLE_128K
+import_large_key:PSA_KEY_TYPE_RAW_DATA:8192:PSA_ERROR_NOT_SUPPORTED
 
 PSA import RSA key pair: maximum size exceeded
 depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C
@@ -2075,6 +2092,25 @@
 depends_on:MBEDTLS_MD_C:MBEDTLS_SHA256_C:!PSA_PRE_1_0_KEY_DERIVATION
 derive_key_export:PSA_ALG_TLS12_PRF(PSA_ALG_SHA_256):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":1:41
 
+PSA key derivation: invalid type (0)
+depends_on:MBEDTLS_MD_C:MBEDTLS_SHA256_C:!PSA_PRE_1_0_KEY_DERIVATION
+derive_key:PSA_ALG_HKDF(PSA_ALG_SHA_256):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":PSA_KEY_TYPE_NONE:128:PSA_ERROR_NOT_SUPPORTED
+
+PSA key derivation: invalid type (PSA_KEY_TYPE_CATEGORY_MASK)
+depends_on:MBEDTLS_MD_C:MBEDTLS_SHA256_C:!PSA_PRE_1_0_KEY_DERIVATION
+derive_key:PSA_ALG_HKDF(PSA_ALG_SHA_256):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":PSA_KEY_TYPE_CATEGORY_MASK:128:PSA_ERROR_NOT_SUPPORTED
+
+# This test assumes that PSA_MAX_KEY_BITS (currently 65536-8 bits = 8191 bytes
+# and not expected to be raised any time soon) is less than the maximum
+# output from HKDF-SHA512 (255*64 = 16320 bytes).
+PSA key derivation: largest possible key
+depends_on:MBEDTLS_MD_C:MBEDTLS_SHA512_C:!PSA_PRE_1_0_KEY_DERIVATION
+derive_key:PSA_ALG_HKDF(PSA_ALG_SHA_512):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":PSA_KEY_TYPE_RAW_DATA:PSA_MAX_KEY_BITS:PSA_SUCCESS
+
+PSA key derivation: key too large
+depends_on:MBEDTLS_MD_C:MBEDTLS_SHA512_C:!PSA_PRE_1_0_KEY_DERIVATION
+derive_key:PSA_ALG_HKDF(PSA_ALG_SHA_512):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":PSA_KEY_TYPE_RAW_DATA:PSA_MAX_KEY_BITS + 1:PSA_ERROR_NOT_SUPPORTED
+
 PSA key agreement setup: ECDH + HKDF-SHA-256: good
 depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECDH_C:MBEDTLS_MD_C:MBEDTLS_SHA256_C
 key_agreement_setup:PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_HKDF(PSA_ALG_SHA_256)):PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_CURVE_SECP256R1):"c88f01f510d9ac3f70a292daa2316de544e9aab8afe84049c62a9c57862d1433":"04d12dfb5289c8d4f81208b70270398c342296970a0bccb74c736fc7554494bf6356fbf3ca366cc23e8157854c13c58d6aac23f046ada30f8353e74f33039872ab":PSA_SUCCESS
@@ -2173,6 +2209,18 @@
 PSA generate random: 260 bytes
 generate_random:260
 
+PSA generate random: MBEDTLS_CTR_DRBG_MAX_REQUEST bytes
+generate_random:MBEDTLS_CTR_DRBG_MAX_REQUEST
+
+PSA generate random: MBEDTLS_CTR_DRBG_MAX_REQUEST+1 bytes
+generate_random:MBEDTLS_CTR_DRBG_MAX_REQUEST + 1
+
+PSA generate random: 2*MBEDTLS_CTR_DRBG_MAX_REQUEST+1 bytes
+generate_random:2 * MBEDTLS_CTR_DRBG_MAX_REQUEST + 1
+
+PSA generate key: bad type (0)
+generate_key:PSA_KEY_TYPE_NONE:128:PSA_KEY_USAGE_EXPORT:0:PSA_ERROR_NOT_SUPPORTED
+
 PSA generate key: bad type (PSA_KEY_TYPE_CATEGORY_MASK)
 generate_key:PSA_KEY_TYPE_CATEGORY_MASK:128:PSA_KEY_USAGE_EXPORT:0:PSA_ERROR_NOT_SUPPORTED
 
@@ -2188,6 +2236,19 @@
 PSA generate key: raw data, 8 bits
 generate_key:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0:PSA_SUCCESS
 
+PSA generate key: raw data, (MBEDTLS_CTR_DRBG_MAX_REQUEST + 1) * 8 bits
+generate_key:PSA_KEY_TYPE_RAW_DATA:(MBEDTLS_CTR_DRBG_MAX_REQUEST + 1) * 8:PSA_KEY_USAGE_EXPORT:0:PSA_SUCCESS
+
+PSA generate key: raw data, (2 * MBEDTLS_CTR_DRBG_MAX_REQUEST + 1) * 8 bits
+generate_key:PSA_KEY_TYPE_RAW_DATA:(2 * MBEDTLS_CTR_DRBG_MAX_REQUEST + 1) * 8:PSA_KEY_USAGE_EXPORT:0:PSA_SUCCESS
+
+PSA generate key: raw data, 65528 bits (ok)
+depends_on:HAVE_RAM_AVAILABLE_128K
+generate_key:PSA_KEY_TYPE_RAW_DATA:65528:PSA_KEY_USAGE_EXPORT:0:PSA_SUCCESS
+
+PSA generate key: raw data, 65536 bits (not supported)
+generate_key:PSA_KEY_TYPE_RAW_DATA:65536:PSA_KEY_USAGE_EXPORT:0:PSA_ERROR_NOT_SUPPORTED
+
 PSA generate key: AES, 128 bits, CTR
 depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
 generate_key:PSA_KEY_TYPE_AES:128:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_CTR:PSA_SUCCESS
diff --git a/tests/suites/test_suite_psa_crypto.function b/tests/suites/test_suite_psa_crypto.function
index d1d6c6a..0eb6172 100644
--- a/tests/suites/test_suite_psa_crypto.function
+++ b/tests/suites/test_suite_psa_crypto.function
@@ -5,8 +5,21 @@
 #include "mbedtls/asn1write.h"
 #include "mbedtls/oid.h"
 
+/* For MBEDTLS_CTR_DRBG_MAX_REQUEST, knowing that psa_generate_random()
+ * uses mbedtls_ctr_drbg internally. */
+#include "mbedtls/ctr_drbg.h"
+
 #include "psa_crypto_helpers.h"
 
+/* Tests that require more than 128kB of RAM plus change have this symbol
+ * as a dependency. Currently we always define this symbol, so the tests
+ * are always executed. In the future we should make this conditional
+ * so that tests that require a lot of memory are skipped on constrained
+ * platforms. */
+#define HAVE_RAM_AVAILABLE_128K
+
+#include "psa/crypto.h"
+
 /** An invalid export length that will never be set by psa_export_key(). */
 static const size_t INVALID_EXPORT_LENGTH = ~0U;
 
@@ -556,7 +569,8 @@
         TEST_ASSERT( ! "Key derivation algorithm not supported" );
     }
 
-    PSA_ASSERT( psa_key_derivation_set_capacity( operation, capacity ) );
+    if( capacity != SIZE_MAX )
+        PSA_ASSERT( psa_key_derivation_set_capacity( operation, capacity ) );
 
     return( 1 );
 
@@ -1201,9 +1215,52 @@
 /* END_CASE */
 
 /* BEGIN_CASE */
-void import( data_t *data, int type_arg,
-             int attr_bits_arg,
-             int expected_status_arg )
+void import_with_policy( int type_arg,
+                         int usage_arg, int alg_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_key_usage_t usage = usage_arg;
+    psa_algorithm_t alg = alg_arg;
+    psa_status_t expected_status = expected_status_arg;
+    const uint8_t key_material[16] = {0};
+    psa_status_t status;
+
+    PSA_ASSERT( psa_crypto_init( ) );
+
+    psa_set_key_type( &attributes, type );
+    psa_set_key_usage_flags( &attributes, usage );
+    psa_set_key_algorithm( &attributes, alg );
+
+    status = psa_import_key( &attributes,
+                             key_material, sizeof( key_material ),
+                             &handle );
+    TEST_EQUAL( status, expected_status );
+    if( status != PSA_SUCCESS )
+        goto exit;
+
+    PSA_ASSERT( psa_get_key_attributes( handle, &got_attributes ) );
+    TEST_EQUAL( psa_get_key_type( &got_attributes ), type );
+    TEST_EQUAL( psa_get_key_usage_flags( &got_attributes ), usage );
+    TEST_EQUAL( psa_get_key_algorithm( &got_attributes ), alg );
+
+    PSA_ASSERT( psa_destroy_key( handle ) );
+    test_operations_on_invalid_handle( handle );
+
+exit:
+    psa_destroy_key( handle );
+    psa_reset_key_attributes( &got_attributes );
+    PSA_DONE( );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void import_with_data( data_t *data, int type_arg,
+                       int attr_bits_arg,
+                       int expected_status_arg )
 {
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
     psa_key_attributes_t got_attributes = PSA_KEY_ATTRIBUTES_INIT;
@@ -1217,6 +1274,7 @@
 
     psa_set_key_type( &attributes, type );
     psa_set_key_bits( &attributes, attr_bits );
+
     status = psa_import_key( &attributes, data->x, data->len, &handle );
     TEST_EQUAL( status, expected_status );
     if( status != PSA_SUCCESS )
@@ -1225,7 +1283,7 @@
     PSA_ASSERT( psa_get_key_attributes( handle, &got_attributes ) );
     TEST_EQUAL( psa_get_key_type( &got_attributes ), type );
     if( attr_bits != 0 )
-        TEST_EQUAL( attr_bits, got_attributes.bits );
+        TEST_EQUAL( attr_bits, psa_get_key_bits( &got_attributes ) );
 
     PSA_ASSERT( psa_destroy_key( handle ) );
     test_operations_on_invalid_handle( handle );
@@ -1238,6 +1296,54 @@
 /* END_CASE */
 
 /* BEGIN_CASE */
+void import_large_key( int type_arg, int byte_size_arg,
+                       int expected_status_arg )
+{
+    psa_key_type_t type = type_arg;
+    size_t byte_size = byte_size_arg;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    psa_status_t expected_status = expected_status_arg;
+    psa_key_handle_t handle = 0;
+    psa_status_t status;
+    uint8_t *buffer = NULL;
+    size_t buffer_size = byte_size + 1;
+    size_t n;
+
+    /* It would be better to skip the test than fail it if the allocation
+     * fails, but the test framework doesn't support this yet. */
+    ASSERT_ALLOC( buffer, buffer_size );
+    memset( buffer, 'K', byte_size );
+
+    PSA_ASSERT( psa_crypto_init( ) );
+
+    /* Try importing the key */
+    psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_EXPORT );
+    psa_set_key_type( &attributes, type );
+    status = psa_import_key( &attributes, buffer, byte_size, &handle );
+    TEST_EQUAL( status, expected_status );
+
+    if( status == PSA_SUCCESS )
+    {
+        PSA_ASSERT( psa_get_key_attributes( handle, &attributes ) );
+        TEST_EQUAL( psa_get_key_type( &attributes ), type );
+        TEST_EQUAL( psa_get_key_bits( &attributes ),
+                    PSA_BYTES_TO_BITS( byte_size ) );
+        memset( buffer, 0, byte_size + 1 );
+        PSA_ASSERT( psa_export_key( handle, buffer, byte_size, &n ) );
+        for( n = 0; n < byte_size; n++ )
+            TEST_EQUAL( buffer[n], 'K' );
+        for( n = byte_size; n < buffer_size; n++ )
+            TEST_EQUAL( buffer[n], 0 );
+    }
+
+exit:
+    psa_destroy_key( handle );
+    PSA_DONE( );
+    mbedtls_free( buffer );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
 void import_rsa_made_up( int bits_arg, int keypair, int expected_status_arg )
 {
     psa_key_handle_t handle = 0;
@@ -4564,6 +4670,51 @@
 /* END_CASE */
 
 /* BEGIN_CASE */
+void derive_key( int alg_arg,
+                 data_t *key_data, data_t *input1, data_t *input2,
+                 int type_arg, int bits_arg,
+                 int expected_status_arg )
+{
+    psa_key_handle_t base_handle = 0;
+    psa_key_handle_t derived_handle = 0;
+    psa_algorithm_t alg = alg_arg;
+    psa_key_type_t type = type_arg;
+    size_t bits = bits_arg;
+    psa_status_t expected_status = expected_status_arg;
+    psa_key_derivation_operation_t operation = PSA_KEY_DERIVATION_OPERATION_INIT;
+    psa_key_attributes_t base_attributes = PSA_KEY_ATTRIBUTES_INIT;
+    psa_key_attributes_t derived_attributes = PSA_KEY_ATTRIBUTES_INIT;
+
+    PSA_ASSERT( psa_crypto_init( ) );
+
+    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, key_data->x, key_data->len,
+                                &base_handle ) );
+
+    if( !setup_key_derivation_wrap( &operation, base_handle, alg,
+                                    input1->x, input1->len,
+                                    input2->x, input2->len, SIZE_MAX ) )
+        goto exit;
+
+    psa_set_key_usage_flags( &derived_attributes, PSA_KEY_USAGE_EXPORT );
+    psa_set_key_algorithm( &derived_attributes, 0 );
+    psa_set_key_type( &derived_attributes, type );
+    psa_set_key_bits( &derived_attributes, bits );
+    TEST_EQUAL( psa_key_derivation_output_key( &derived_attributes, &operation,
+                                               &derived_handle ),
+                expected_status );
+
+exit:
+    psa_key_derivation_abort( &operation );
+    psa_destroy_key( base_handle );
+    psa_destroy_key( derived_handle );
+    PSA_DONE( );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
 void key_agreement_setup( int alg_arg,
                           int our_key_type_arg, data_t *our_key_data,
                           data_t *peer_key_data,
diff --git a/tests/suites/test_suite_psa_crypto_persistent_key.data b/tests/suites/test_suite_psa_crypto_persistent_key.data
index 925c0f5..3f40d35 100644
--- a/tests/suites/test_suite_psa_crypto_persistent_key.data
+++ b/tests/suites/test_suite_psa_crypto_persistent_key.data
@@ -19,10 +19,10 @@
 # Not specific to files, but only run this test in an environment where the maximum size could be reached.
 Save maximum size persistent raw key
 depends_on:MBEDTLS_PSA_ITS_FILE_C
-save_large_persistent_key:0:PSA_SUCCESS
+save_large_persistent_key:PSA_CRYPTO_MAX_STORAGE_SIZE:PSA_SUCCESS
 
 Save larger than maximum size persistent raw key, should fail
-save_large_persistent_key:1:PSA_ERROR_INSUFFICIENT_STORAGE
+save_large_persistent_key:PSA_CRYPTO_MAX_STORAGE_SIZE + 1:PSA_ERROR_NOT_SUPPORTED
 
 Persistent key destroy
 depends_on:MBEDTLS_PK_C:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C
diff --git a/tests/suites/test_suite_psa_crypto_persistent_key.function b/tests/suites/test_suite_psa_crypto_persistent_key.function
index b76c733..115bfea 100644
--- a/tests/suites/test_suite_psa_crypto_persistent_key.function
+++ b/tests/suites/test_suite_psa_crypto_persistent_key.function
@@ -45,7 +45,7 @@
     file_data_length = key_data->len + sizeof( psa_persistent_key_storage_format );
     file_data = mbedtls_calloc( 1, file_data_length );
     psa_format_key_data_for_storage( key_data->x, key_data->len,
-                                     &attributes,
+                                     &attributes.core,
                                      file_data );
 
     ASSERT_COMPARE( expected_file_data->x, expected_file_data->len,
@@ -71,7 +71,7 @@
 
     status = psa_parse_key_data_from_storage( file_data->x, file_data->len,
                                               &key_data, &key_data_length,
-                                              &attributes );
+                                              &attributes.core );
 
     TEST_EQUAL( status, expected_status );
     if( status != PSA_SUCCESS )
@@ -96,17 +96,14 @@
 /* END_CASE */
 
 /* BEGIN_CASE */
-void save_large_persistent_key( int data_too_large, int expected_status )
+void save_large_persistent_key( int data_length_arg, int expected_status )
 {
     psa_key_id_t key_id = 42;
     psa_key_handle_t handle = 0;
     uint8_t *data = NULL;
-    size_t data_length = PSA_CRYPTO_MAX_STORAGE_SIZE;
+    size_t data_length = data_length_arg;
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
 
-    if( data_too_large )
-        data_length += 1;
-
     ASSERT_ALLOC( data, data_length );
 
     PSA_ASSERT( psa_crypto_init() );
diff --git a/tests/suites/test_suite_psa_crypto_se_driver_hal.function b/tests/suites/test_suite_psa_crypto_se_driver_hal.function
index e0b8d29..6ac19a6 100644
--- a/tests/suites/test_suite_psa_crypto_se_driver_hal.function
+++ b/tests/suites/test_suite_psa_crypto_se_driver_hal.function
@@ -62,7 +62,8 @@
                                  psa_algorithm_t algorithm,
                                  psa_key_usage_t usage,
                                  const uint8_t *p_data,
-                                 size_t data_length )
+                                 size_t data_length,
+                                 size_t *bits )
 {
     (void) context;
     (void) slot_number;
@@ -71,7 +72,9 @@
     (void) algorithm;
     (void) usage;
     (void) p_data;
-    (void) data_length;
+    /* We're supposed to return a key size. Return one that's correct for
+     * plain data keys. */
+    *bits = PSA_BYTES_TO_BITS( data_length );
     return( PSA_SUCCESS );
 }
 
@@ -110,7 +113,8 @@
                                 psa_algorithm_t algorithm,
                                 psa_key_usage_t usage,
                                 const uint8_t *p_data,
-                                size_t data_length )
+                                size_t data_length,
+                                size_t *bits )
 {
     (void) context;
     DRIVER_ASSERT( slot_number < ARRAY_LENGTH( ram_slots ) );
@@ -119,6 +123,7 @@
     ram_slots[slot_number].lifetime = lifetime;
     ram_slots[slot_number].type = type;
     ram_slots[slot_number].bits = PSA_BYTES_TO_BITS( data_length );
+    *bits = PSA_BYTES_TO_BITS( data_length );
     (void) algorithm;
     (void) usage;
     memcpy( ram_slots[slot_number].content, p_data, data_length );
@@ -178,6 +183,41 @@
 /* Other test helper functions */
 /****************************************************************/
 
+/* Check that the attributes of a key reported by psa_get_key_attributes()
+ * are consistent with the attributes used when creating the key. */
+static int check_key_attributes(
+    psa_key_handle_t handle,
+    const psa_key_attributes_t *reference_attributes )
+{
+    int ok = 0;
+    psa_key_attributes_t actual_attributes = PSA_KEY_ATTRIBUTES_INIT;
+
+    PSA_ASSERT( psa_get_key_attributes( handle, &actual_attributes ) );
+
+    TEST_EQUAL( psa_get_key_id( &actual_attributes ),
+                psa_get_key_id( reference_attributes ) );
+    TEST_EQUAL( psa_get_key_lifetime( &actual_attributes ),
+                psa_get_key_lifetime( reference_attributes ) );
+    TEST_EQUAL( psa_get_key_type( &actual_attributes ),
+                psa_get_key_type( reference_attributes ) );
+    TEST_EQUAL( psa_get_key_usage_flags( &actual_attributes ),
+                psa_get_key_usage_flags( reference_attributes ) );
+    TEST_EQUAL( psa_get_key_algorithm( &actual_attributes ),
+                psa_get_key_algorithm( reference_attributes ) );
+    TEST_EQUAL( psa_get_key_enrollment_algorithm( &actual_attributes ),
+                psa_get_key_enrollment_algorithm( reference_attributes ) );
+    if( psa_get_key_bits( reference_attributes ) != 0 )
+    {
+        TEST_EQUAL( psa_get_key_bits( &actual_attributes ),
+                    psa_get_key_bits( reference_attributes ) );
+    }
+
+    ok = 1;
+
+exit:
+    return( ok );
+}
+
 /* Check that a function's return status is "smoke-free", i.e. that
  * it's an acceptable error code when calling an API function that operates
  * on a key with potentially bogus parameters. */
@@ -445,6 +485,11 @@
     /* Test that the key was created in the expected slot. */
     TEST_ASSERT( ram_slots[min_slot].type == PSA_KEY_TYPE_RAW_DATA );
 
+    /* Test the key attributes and the key data. */
+    psa_set_key_bits( &attributes,
+                      PSA_BYTES_TO_BITS( sizeof( key_material ) ) );
+    if( ! check_key_attributes( handle, &attributes ) )
+        goto exit;
     PSA_ASSERT( psa_export_key( handle,
                                 exported, sizeof( exported ),
                                 &exported_length ) );