Make library init and deinit more robust to errors
Allow mbedtls_psa_crypto_free to be called twice, or without a prior
call to psa_crypto_init. Keep track of the initialization state more
precisely in psa_crypto_init so that mbedtls_psa_crypto_free knows
what to do.
diff --git a/library/psa_crypto.c b/library/psa_crypto.c
index 291dcdb..4c0ac12 100644
--- a/library/psa_crypto.c
+++ b/library/psa_crypto.c
@@ -146,12 +146,21 @@
return( PSA_KEY_TYPE_IS_UNSTRUCTURED( type ) );
}
+enum rng_state
+{
+ RNG_NOT_INITIALIZED = 0,
+ RNG_INITIALIZED,
+ RNG_SEEDED,
+};
+
typedef struct
{
- int initialized;
mbedtls_entropy_context entropy;
mbedtls_ctr_drbg_context ctr_drbg;
key_slot_t key_slots[PSA_KEY_SLOT_COUNT];
+ unsigned initialized : 1;
+ enum rng_state rng_state : 2;
+ unsigned key_slots_initialized : 1;
} psa_global_data_t;
static psa_global_data_t global_data;
@@ -4433,18 +4442,26 @@
psa_key_slot_t key;
key_slot_t *slot;
psa_status_t status;
-
- for( key = 1; key <= PSA_KEY_SLOT_COUNT; key++ )
+ if( global_data.key_slots_initialized )
{
- status = psa_get_key_slot( key, &slot );
- if( status != PSA_SUCCESS )
- continue;
- psa_remove_key_data_from_memory( slot );
- /* Zeroize the slot to wipe metadata such as policies. */
- mbedtls_zeroize( slot, sizeof( *slot ) );
+ for( key = 1; key <= PSA_KEY_SLOT_COUNT; key++ )
+ {
+ status = psa_get_key_slot( key, &slot );
+ if( status != PSA_SUCCESS )
+ continue;
+ psa_remove_key_data_from_memory( slot );
+ /* Zeroize the slot to wipe metadata such as policies. */
+ mbedtls_zeroize( slot, sizeof( *slot ) );
+ }
}
- mbedtls_ctr_drbg_free( &global_data.ctr_drbg );
- mbedtls_entropy_free( &global_data.entropy );
+ if( global_data.rng_state != RNG_NOT_INITIALIZED )
+ {
+ mbedtls_ctr_drbg_free( &global_data.ctr_drbg );
+ mbedtls_entropy_free( &global_data.entropy );
+ }
+ /* Wipe all remaining data, including configuration.
+ * In particular, this sets all state indicator to the value
+ * indicating "uninitialized". */
mbedtls_zeroize( &global_data, sizeof( global_data ) );
}
@@ -4453,20 +4470,30 @@
int ret;
const unsigned char drbg_seed[] = "PSA";
+ /* Double initialization is explicitly allowed. */
if( global_data.initialized != 0 )
return( PSA_SUCCESS );
mbedtls_zeroize( &global_data, sizeof( global_data ) );
+
+ /* Initialize the random generator. */
mbedtls_entropy_init( &global_data.entropy );
mbedtls_ctr_drbg_init( &global_data.ctr_drbg );
-
+ global_data.rng_state = RNG_INITIALIZED;
ret = mbedtls_ctr_drbg_seed( &global_data.ctr_drbg,
mbedtls_entropy_func,
&global_data.entropy,
drbg_seed, sizeof( drbg_seed ) - 1 );
if( ret != 0 )
goto exit;
+ global_data.rng_state = RNG_SEEDED;
+ /* Initialize the key slots. Zero-initialization has made all key
+ * slots empty, so there is nothing to do. In a future version we will
+ * load data from storage. */
+ global_data.key_slots_initialized = 1;
+
+ /* All done. */
global_data.initialized = 1;
exit: