psa: Extend psa_generate_key to support persistent lifetimes
diff --git a/library/psa_crypto.c b/library/psa_crypto.c
index 74c3cfc..58cb738 100644
--- a/library/psa_crypto.c
+++ b/library/psa_crypto.c
@@ -1107,6 +1107,37 @@
                                      data_length, 1 ) );
 }
 
+#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C)
+static psa_status_t psa_save_generated_persistent_key( psa_key_slot_t key,
+                                                       key_slot_t *slot,
+                                                       size_t bits )
+{
+    psa_status_t status;
+    uint8_t *data;
+    size_t key_length;
+    size_t data_size = PSA_KEY_EXPORT_MAX_SIZE( slot->type, bits );
+    data = mbedtls_calloc( 1, data_size );
+    /* Get key data in export format */
+    status = psa_internal_export_key( slot, data, data_size, &key_length, 0 );
+    if( status != PSA_SUCCESS )
+    {
+        slot->type = PSA_KEY_TYPE_NONE;
+        goto exit;
+    }
+    /* Store in file location */
+    status = psa_save_persistent_key( key, slot->type, &slot->policy,
+                                      data, key_length );
+    if( status != PSA_SUCCESS )
+    {
+        slot->type = PSA_KEY_TYPE_NONE;
+    }
+exit:
+    mbedtls_zeroize( data, key_length );
+    mbedtls_free( data );
+    return( status );
+}
+#endif /* defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) */
+
 
 
 /****************************************************************/
@@ -4309,7 +4340,15 @@
         return( PSA_ERROR_NOT_SUPPORTED );
 
     slot->type = type;
-    return( PSA_SUCCESS );
+
+#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C)
+    if( slot->lifetime == PSA_KEY_LIFETIME_PERSISTENT )
+    {
+        return( psa_save_generated_persistent_key( key, slot, bits ) );
+    }
+#endif /* defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) */
+
+    return( status );
 }
 
 
diff --git a/tests/suites/test_suite_psa_crypto.data b/tests/suites/test_suite_psa_crypto.data
index 7e70de3..e1c1b05 100644
--- a/tests/suites/test_suite_psa_crypto.data
+++ b/tests/suites/test_suite_psa_crypto.data
@@ -1837,4 +1837,32 @@
 
 persistent key can be accessed after in-memory deletion: AES, 128 bits, CTR
 depends_on:MBEDTLS_PK_C:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_PSA_CRYPTO_STORAGE_C
-persistent_key_load_key_from_storage:"2b7e151628aed2a6abf7158809cf4f3c":PSA_KEY_TYPE_AES:128:PSA_KEY_USAGE_EXPORT:PSA_ALG_CTR
+persistent_key_load_key_from_storage:"2b7e151628aed2a6abf7158809cf4f3c":PSA_KEY_TYPE_AES:128:PSA_KEY_USAGE_EXPORT:PSA_ALG_CTR:IMPORT_KEY:PSA_SUCCESS
+
+PSA generate persistent key: raw data, 8 bits
+depends_on:MBEDTLS_PSA_CRYPTO_STORAGE_C
+persistent_key_load_key_from_storage:"":PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0:GENERATE_KEY:PSA_SUCCESS
+
+PSA generate persistent key: AES, 128 bits, CTR
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR:MBEDTLS_PSA_CRYPTO_STORAGE_C
+persistent_key_load_key_from_storage:"":PSA_KEY_TYPE_AES:128:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_CTR:GENERATE_KEY:PSA_SUCCESS
+
+PSA generate persistent key: DES, 64 bits, CBC-nopad
+depends_on:MBEDTLS_DES_C:MBEDTLS_PSA_CRYPTO_STORAGE_C
+persistent_key_load_key_from_storage:"":PSA_KEY_TYPE_DES:64:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_CBC_NO_PADDING:GENERATE_KEY:PSA_SUCCESS
+
+PSA generate persistent key: RSA, 1024 bits, good, sign (PSS SHA-256)
+depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME:MBEDTLS_PKCS1_V21:MBEDTLS_SHA256_C:MBEDTLS_PSA_CRYPTO_STORAGE_C
+persistent_key_load_key_from_storage:"":PSA_KEY_TYPE_RSA_KEYPAIR:1024:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN | PSA_KEY_USAGE_VERIFY:PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):GENERATE_KEY:PSA_SUCCESS
+
+PSA generate persistent key: ECC, SECP256R1, good
+depends_on:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECDSA_C:MBEDTLS_PSA_CRYPTO_STORAGE_C
+persistent_key_load_key_from_storage:"":PSA_KEY_TYPE_ECC_KEYPAIR(PSA_ECC_CURVE_SECP256R1):256:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN | PSA_KEY_USAGE_VERIFY:PSA_ALG_ECDSA_ANY:GENERATE_KEY:PSA_SUCCESS
+
+PSA derive persistent key: HKDF SHA-256
+depends_on:MBEDTLS_MD_C:MBEDTLS_SHA256_C:MBEDTLS_PSA_CRYPTO_STORAGE_C
+persistent_key_load_key_from_storage:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_KEY_TYPE_RAW_DATA:1024:PSA_KEY_USAGE_EXPORT:0:DERIVE_KEY:PSA_SUCCESS
+
+PSA generate persistent key: AES, 128 bits, CTR
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR:MBEDTLS_PSA_CRYPTO_STORAGE_C
+persistent_key_load_key_from_storage:"":PSA_KEY_TYPE_AES:128:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_CTR:GENERATE_KEY:PSA_ERROR_NOT_PERMITTED
diff --git a/tests/suites/test_suite_psa_crypto.function b/tests/suites/test_suite_psa_crypto.function
index 4692dbe..53295be 100644
--- a/tests/suites/test_suite_psa_crypto.function
+++ b/tests/suites/test_suite_psa_crypto.function
@@ -844,6 +844,13 @@
     }
 
 }
+
+typedef enum {
+    IMPORT_KEY = 0,
+    GENERATE_KEY = 1,
+    DERIVE_KEY = 2
+} generate_method;
+
 /* END_HEADER */
 
 /* BEGIN_DEPENDENCIES
@@ -4034,9 +4041,11 @@
 /* BEGIN_CASE depends_on:MBEDTLS_PSA_CRYPTO_STORAGE_C */
 void persistent_key_load_key_from_storage( data_t *data, int type_arg,
                                            int bits, int usage_arg,
-                                           int alg_arg )
+                                           int alg_arg, int generation_method,
+                                           int export_status )
 {
     psa_key_slot_t slot = 1;
+    psa_key_slot_t base_key = 2;
     psa_key_type_t type = (psa_key_type_t) type_arg;
     psa_key_type_t type_get;
     size_t bits_get;
@@ -4044,6 +4053,9 @@
     psa_key_policy_t policy_get;
     psa_key_usage_t policy_usage = (psa_key_usage_t) usage_arg;
     psa_algorithm_t policy_alg = (psa_algorithm_t) alg_arg;
+    psa_key_policy_t base_policy_set;
+    psa_algorithm_t base_policy_alg = PSA_ALG_HKDF(PSA_ALG_SHA_256);
+    psa_crypto_generator_t generator = PSA_CRYPTO_GENERATOR_INIT;
     unsigned char *first_export = NULL;
     unsigned char *second_export = NULL;
     size_t export_size = PSA_KEY_EXPORT_MAX_SIZE( type, bits );
@@ -4064,14 +4076,44 @@
                               policy_alg );
 
     TEST_ASSERT( psa_set_key_policy( slot, &policy_set ) == PSA_SUCCESS );
+    switch( generation_method )
+    {
+        case IMPORT_KEY:
+            /* Import the key */
+            TEST_ASSERT( psa_import_key( slot, type,
+                                         data->x, data->len ) == PSA_SUCCESS );
+            break;
 
-    /* Import the key */
-    TEST_ASSERT( psa_import_key( slot, type,
-                                 data->x, data->len ) == PSA_SUCCESS );
+        case GENERATE_KEY:
+            /* Generate a key */
+            TEST_ASSERT( psa_generate_key( slot, type, bits,
+                                           NULL, 0 ) == PSA_SUCCESS );
+            break;
+
+        case DERIVE_KEY:
+            /* Create base key */
+            psa_key_policy_init( &base_policy_set );
+
+            psa_key_policy_set_usage( &base_policy_set, PSA_KEY_USAGE_DERIVE,
+                                      base_policy_alg );
+            TEST_ASSERT( psa_set_key_policy(
+                base_key, &base_policy_set ) == PSA_SUCCESS );
+            TEST_ASSERT( psa_import_key( base_key, PSA_KEY_TYPE_DERIVE,
+                                         data->x, data->len ) == PSA_SUCCESS );
+            /* Derive a key. */
+            TEST_ASSERT( psa_key_derivation( &generator, base_key,
+                                             base_policy_alg,
+                                             NULL, 0, NULL, 0,
+                                             export_size ) == PSA_SUCCESS );
+            TEST_ASSERT( psa_generator_import_key(
+                slot, PSA_KEY_TYPE_RAW_DATA,
+                bits, &generator ) == PSA_SUCCESS );
+            break;
+    }
 
     /* Export the key */
     TEST_ASSERT( psa_export_key( slot, first_export, export_size,
-                                 &first_exported_length ) == PSA_SUCCESS );
+                                 &first_exported_length ) == export_status );
 
     /* Shutdown and restart */
     mbedtls_psa_crypto_free();
@@ -4096,13 +4138,27 @@
 
     /* Export the key again */
     TEST_ASSERT( psa_export_key( slot, second_export, export_size,
-                                 &second_exported_length ) == PSA_SUCCESS );
+                                 &second_exported_length ) == export_status );
 
-    ASSERT_COMPARE( first_export, first_exported_length,
-                    second_export, second_exported_length );
+    if( export_status == PSA_SUCCESS )
+    {
+        ASSERT_COMPARE( first_export, first_exported_length,
+                        second_export, second_exported_length );
 
-    ASSERT_COMPARE( data->x, data->len,
-                    first_export, first_exported_length );
+        switch( generation_method )
+        {
+            case IMPORT_KEY:
+                ASSERT_COMPARE( data->x, data->len,
+                                first_export, first_exported_length );
+                break;
+            default:
+                break;
+        }
+    }
+
+    /* Do something with the key according to its type and permitted usage. */
+    if( ! exercise_key( slot, policy_usage, policy_alg ) )
+        goto exit;
 
 exit:
     mbedtls_free( first_export );
diff --git a/tests/suites/test_suite_psa_crypto_persistent_key.function b/tests/suites/test_suite_psa_crypto_persistent_key.function
index 505f1f9..0ede6e6 100644
--- a/tests/suites/test_suite_psa_crypto_persistent_key.function
+++ b/tests/suites/test_suite_psa_crypto_persistent_key.function
@@ -16,6 +16,7 @@
     uint8_t data_len[4];
     uint8_t key_data[];
 } psa_persistent_key_storage_format;
+
 /* END_HEADER */
 
 /* BEGIN_DEPENDENCIES