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: