Use psa_core_key_attributes_t in key slots in memory

Change the type of key slots in memory to use
psa_core_key_attributes_t rather than separate fields. The goal is to
simplify some parts of the code. This commit only does the mechanical
replacement, not the substitution.

The bit-field `allocate` is now a flag `PSA_KEY_SLOT_FLAG_ALLOCATED`
in the `flags` field.

Write accessor functions for flags.

Key slots now contain a bit size field which is currently unused.
Subsequent commits will make use of it.
diff --git a/library/psa_crypto.c b/library/psa_crypto.c
index 1b2fa20..1646ae5 100644
--- a/library/psa_crypto.c
+++ b/library/psa_crypto.c
@@ -366,7 +366,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 +695,7 @@
 }
 #endif /* defined(MBEDTLS_ECP_C) */
 
-/** Import key data into a slot. `slot->type` must have been set
+/** 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,7 +704,7 @@
 {
     psa_status_t status = PSA_SUCCESS;
 
-    if( key_type_is_raw_bytes( slot->type ) )
+    if( key_type_is_raw_bytes( slot->attr.type ) )
     {
         size_t bit_size = PSA_BYTES_TO_BITS( data_length );
         /* Ensure that the bytes-to-bit conversion doesn't overflow. */
@@ -713,7 +713,7 @@
         /* 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->type, bit_size,
+        status = prepare_raw_data_slot( slot->attr.type, bit_size,
                                         &slot->data.raw );
         if( status != PSA_SUCCESS )
             return( status );
@@ -722,25 +722,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 );
     }
@@ -854,20 +854,20 @@
     status = psa_get_key_slot( handle, &slot );
     if( status != PSA_SUCCESS )
         return( status );
-    if( slot->type == PSA_KEY_TYPE_NONE )
+    if( slot->attr.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;
@@ -914,17 +914,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 );
@@ -932,7 +932,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 );
@@ -981,7 +981,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:
@@ -990,9 +990,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 )
         {
@@ -1006,10 +1006,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) */
 
@@ -1039,18 +1039,18 @@
 static size_t psa_get_key_slot_bits( const psa_key_slot_t *slot )
 {
 #if defined(MBEDTLS_PSA_CRYPTO_SE_C)
-    if( psa_get_se_driver( slot->lifetime, NULL, NULL ) )
+    if( psa_get_se_driver( slot->attr.lifetime, NULL, NULL ) )
         return( slot->data.se.bits );
 #endif /* defined(MBEDTLS_PSA_CRYPTO_SE_C) */
 
-    if( key_type_is_raw_bytes( slot->type ) )
+    if( key_type_is_raw_bytes( slot->attr.type ) )
         return( slot->data.raw.bytes * 8 );
 #if defined(MBEDTLS_RSA_C)
-    if( PSA_KEY_TYPE_IS_RSA( slot->type ) )
+    if( PSA_KEY_TYPE_IS_RSA( slot->attr.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 ) )
+    if( PSA_KEY_TYPE_IS_ECC( slot->attr.type ) )
         return( slot->data.ecp->grp.pbits );
 #endif /* defined(MBEDTLS_ECP_C) */
     /* Shouldn't happen except on an empty slot. */
@@ -1156,10 +1156,10 @@
 static void psa_get_key_slot_attributes( psa_key_slot_t *slot,
                                          psa_key_attributes_t *attributes )
 {
-    attributes->core.id = slot->persistent_storage_id;
-    attributes->core.lifetime = slot->lifetime;
-    attributes->core.policy = slot->policy;
-    attributes->core.type = slot->type;
+    attributes->core.id = slot->attr.id;
+    attributes->core.lifetime = slot->attr.lifetime;
+    attributes->core.policy = slot->attr.policy;
+    attributes->core.type = slot->attr.type;
     attributes->core.bits = psa_get_key_slot_bits( slot );
 }
 
@@ -1179,7 +1179,7 @@
 
     psa_get_key_slot_attributes( slot, attributes );
 
-    switch( slot->type )
+    switch( slot->attr.type )
     {
 #if defined(MBEDTLS_RSA_C)
         case PSA_KEY_TYPE_RSA_KEY_PAIR:
@@ -1187,7 +1187,7 @@
 #if defined(MBEDTLS_PSA_CRYPTO_SE_C)
             /* TOnogrepDO: reporting the public exponent for opaque keys
              * is not yet implemented. */
-            if( psa_get_se_driver( slot->lifetime, NULL, NULL ) )
+            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 );
@@ -1232,11 +1232,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 )
@@ -1252,7 +1252,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 );
@@ -1266,7 +1266,7 @@
         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;
 
@@ -1285,12 +1285,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 );
@@ -1310,7 +1310,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 );
             }
@@ -1412,7 +1412,7 @@
                              PSA_KEY_USAGE_DERIVE ) ) != 0 )
         return( PSA_ERROR_INVALID_ARGUMENT );
 
-    slot->policy = *policy;
+    slot->attr.policy = *policy;
     return( PSA_SUCCESS );
 }
 
@@ -1460,7 +1460,7 @@
     status = psa_set_key_policy_internal( slot, &attributes->core.policy );
     if( status != PSA_SUCCESS )
         return( status );
-    slot->lifetime = attributes->core.lifetime;
+    slot->attr.lifetime = attributes->core.lifetime;
 
     if( attributes->core.lifetime != PSA_KEY_LIFETIME_VOLATILE )
     {
@@ -1469,9 +1469,9 @@
                                                          p_drv, 1 );
         if( status != PSA_SUCCESS )
             return( status );
-        slot->persistent_storage_id = attributes->core.id;
+        slot->attr.id = attributes->core.id;
     }
-    slot->type = attributes->core.type;
+    slot->attr.type = attributes->core.type;
 
     /* Refuse to create overly large keys.
      * Note that this doesn't trigger on import if the attributes don't
@@ -1501,9 +1501,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 )
         {
@@ -1546,7 +1546,7 @@
     (void) driver;
 
 #if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C)
-    if( slot->lifetime != PSA_KEY_LIFETIME_VOLATILE )
+    if( slot->attr.lifetime != PSA_KEY_LIFETIME_VOLATILE )
     {
         psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
         psa_get_key_slot_attributes( slot, &attributes );
@@ -1562,7 +1562,7 @@
 #endif /* MBEDTLS_PSA_CRYPTO_SE_C */
         {
             size_t buffer_size =
-                PSA_KEY_EXPORT_MAX_SIZE( slot->type,
+                PSA_KEY_EXPORT_MAX_SIZE( slot->attr.type,
                                          psa_get_key_bits( &attributes ) );
             uint8_t *buffer = mbedtls_calloc( 1, buffer_size );
             size_t length = 0;
@@ -1587,7 +1587,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( );
@@ -1640,14 +1640,14 @@
 {
     if( attributes->core.type != 0 )
     {
-        if( attributes->core.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;
@@ -1712,7 +1712,8 @@
         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,
+            slot->attr.lifetime, slot->attr.type,
+            slot->attr.policy.alg, slot->attr.policy.usage,
             data, data_length,
             &slot->data.se.bits );
     }
@@ -1745,7 +1746,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 )
@@ -1753,7 +1754,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:
@@ -1783,7 +1784,7 @@
         goto exit;
 
     status = psa_restrict_key_policy( &actual_attributes.core.policy,
-                                      &source_slot->policy );
+                                      &source_slot->attr.policy );
     if( status != PSA_SUCCESS )
         goto exit;
 
@@ -2573,7 +2574,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 )
         {
@@ -2605,7 +2606,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;
@@ -3145,14 +3146,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,
@@ -3163,7 +3164,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(
@@ -3220,7 +3221,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,
@@ -3230,7 +3231,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 ) )
@@ -3288,12 +3289,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;
@@ -3368,11 +3369,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;
@@ -3479,7 +3480,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;
@@ -3491,7 +3492,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];
@@ -3533,10 +3534,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
@@ -3818,7 +3819,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 );
@@ -3832,7 +3833,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(
@@ -3851,7 +3852,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(
@@ -4676,7 +4677,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 );
@@ -4688,7 +4689,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 );
@@ -4997,7 +4998,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,
@@ -5372,7 +5373,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
@@ -5452,7 +5453,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,
@@ -5635,7 +5636,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 );
diff --git a/library/psa_crypto_core.h b/library/psa_crypto_core.h
index d335b75..88a3289 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_lifetime_t lifetime;
-    psa_key_file_id_t persistent_storage_id;
-    psa_key_policy_t policy;
-    unsigned allocated : 1;
+    psa_core_key_attributes_t attr;
     union
     {
         /* Raw-data key (key_type_is_raw_bytes() in psa_crypto.c) */
@@ -69,6 +65,60 @@
     } data;
 } psa_key_slot_t;
 
+/** Flag for psa_key_slot_t::attr::core::flags indicating that the
+ * slot is in use. */
+#define PSA_KEY_SLOT_FLAG_ALLOCATED ( (uint16_t) 0x0001 )
+
+/** 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_slot_management.c b/library/psa_crypto_slot_management.c
index 6add6b8..bfa7baa 100644
--- a/library/psa_crypto_slot_management.c
+++ b/library/psa_crypto_slot_management.c
@@ -72,7 +72,7 @@
     slot = &global_data.key_slots[handle - 1];
 
     /* If the slot hasn't been allocated, the handle is invalid. */
-    if( ! slot->allocated )
+    if( ! psa_key_slot_get_flags( slot, PSA_KEY_SLOT_FLAG_ALLOCATED ) )
         return( PSA_ERROR_INVALID_HANDLE );
 
     *p_slot = slot;
@@ -108,9 +108,10 @@
     for( *handle = PSA_KEY_SLOT_COUNT; *handle != 0; --( *handle ) )
     {
         *p_slot = &global_data.key_slots[*handle - 1];
-        if( ! ( *p_slot )->allocated )
+        if( ! psa_key_slot_get_flags( *p_slot, PSA_KEY_SLOT_FLAG_ALLOCATED ) )
         {
-            ( *p_slot )->allocated = 1;
+            psa_key_slot_set_bits_in_flags( *p_slot,
+                                            PSA_KEY_SLOT_FLAG_ALLOCATED );
             return( PSA_SUCCESS );
         }
     }
@@ -126,17 +127,17 @@
     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 );
+    psa_set_key_id( &attributes, p_slot->attr.id );
     status = psa_load_persistent_key( &attributes,
                                       &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.core.policy;
+    p_slot->attr.lifetime = psa_get_key_lifetime( &attributes );
+    p_slot->attr.type = psa_get_key_type( &attributes );
+    p_slot->attr.policy = attributes.core.policy;
 
 #if defined(MBEDTLS_PSA_CRYPTO_SE_C)
-    if( psa_key_lifetime_is_external( p_slot->lifetime ) )
+    if( psa_key_lifetime_is_external( p_slot->attr.lifetime ) )
     {
         if( key_data_length != sizeof( p_slot->data.se ) )
         {
@@ -233,8 +234,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,27 +271,27 @@
     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 )
+        if( slot->attr.type == PSA_KEY_TYPE_NONE )
         {
-            if( slot->allocated )
+            if( psa_key_slot_get_flags( slot, PSA_KEY_SLOT_FLAG_ALLOCATED ) )
                 ++stats->half_filled_slots;
             else
                 ++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;
         }
     }
 }