psa: Implement persistent keys
Allow use of persistent keys, including configuring them, importing and
exporting them, and destroying them.
When getting a slot using psa_get_key_slot, there are 3 scenarios that
can occur if the keys lifetime is persistent:
1. Key type is PSA_KEY_TYPE_NONE, no persistent storage entry:
- The key slot is treated as a standard empty key slot
2. Key type is PSA_KEY_TYPE_NONE, persistent storage entry exists:
- Attempt to load the key from persistent storage
3. Key type is not PSA_KEY_TYPE_NONE:
- As checking persistent storage on every use of the key could
be expensive, the persistent key is assumed to be saved in
persistent storage, the in-memory key is continued to be used.
diff --git a/tests/suites/test_suite_psa_crypto.function b/tests/suites/test_suite_psa_crypto.function
index 674a6e9..4692dbe 100644
--- a/tests/suites/test_suite_psa_crypto.function
+++ b/tests/suites/test_suite_psa_crypto.function
@@ -4030,3 +4030,84 @@
TEST_ASSERT( status == PSA_ERROR_BAD_STATE );
}
/* END_CASE */
+
+/* BEGIN_CASE depends_on:MBEDTLS_PSA_CRYPTO_STORAGE_C */
+void persistent_key_load_key_from_storage( data_t *data, int type_arg,
+ int bits, int usage_arg,
+ int alg_arg )
+{
+ psa_key_slot_t slot = 1;
+ psa_key_type_t type = (psa_key_type_t) type_arg;
+ psa_key_type_t type_get;
+ size_t bits_get;
+ psa_key_policy_t policy_set;
+ psa_key_policy_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;
+ unsigned char *first_export = NULL;
+ unsigned char *second_export = NULL;
+ size_t export_size = PSA_KEY_EXPORT_MAX_SIZE( type, bits );
+ size_t first_exported_length;
+ size_t second_exported_length;
+
+ ASSERT_ALLOC( first_export, export_size );
+ ASSERT_ALLOC( second_export, export_size );
+
+ TEST_ASSERT( psa_crypto_init() == PSA_SUCCESS );
+
+ TEST_ASSERT( psa_set_key_lifetime(
+ slot, PSA_KEY_LIFETIME_PERSISTENT ) == PSA_SUCCESS );
+
+ psa_key_policy_init( &policy_set );
+
+ psa_key_policy_set_usage( &policy_set, policy_usage,
+ policy_alg );
+
+ TEST_ASSERT( psa_set_key_policy( slot, &policy_set ) == PSA_SUCCESS );
+
+ /* Import the key */
+ TEST_ASSERT( psa_import_key( slot, type,
+ data->x, data->len ) == PSA_SUCCESS );
+
+ /* Export the key */
+ TEST_ASSERT( psa_export_key( slot, first_export, export_size,
+ &first_exported_length ) == PSA_SUCCESS );
+
+ /* Shutdown and restart */
+ mbedtls_psa_crypto_free();
+
+ TEST_ASSERT( psa_crypto_init() == PSA_SUCCESS );
+
+ /* Mark slot as persistent again */
+ TEST_ASSERT( psa_set_key_lifetime(
+ slot, PSA_KEY_LIFETIME_PERSISTENT ) == PSA_SUCCESS );
+
+ /* Check key slot still contains key data */
+ TEST_ASSERT( psa_get_key_information(
+ slot, &type_get, &bits_get ) == PSA_SUCCESS );
+ TEST_ASSERT( type_get == type );
+ TEST_ASSERT( bits_get == (size_t) bits );
+
+ TEST_ASSERT( psa_get_key_policy( slot, &policy_get ) == PSA_SUCCESS );
+ TEST_ASSERT( psa_key_policy_get_usage(
+ &policy_get ) == policy_usage );
+ TEST_ASSERT( psa_key_policy_get_algorithm(
+ &policy_get ) == policy_alg );
+
+ /* Export the key again */
+ TEST_ASSERT( psa_export_key( slot, second_export, export_size,
+ &second_exported_length ) == 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 );
+
+exit:
+ mbedtls_free( first_export );
+ mbedtls_free( second_export );
+ psa_destroy_key( slot );
+ mbedtls_psa_crypto_free();
+}
+/* END_CASE */