Merge pull request #3744 from ronald-cron-arm/psa-generate-key-internal

Rework psa_generate_key
diff --git a/ChangeLog.d/getentropy.txt b/ChangeLog.d/getentropy.txt
new file mode 100644
index 0000000..460798f
--- /dev/null
+++ b/ChangeLog.d/getentropy.txt
@@ -0,0 +1,3 @@
+Changes
+   * On recent enough versions of FreeBSD and DragonFlyBSD, the entropy module
+     now uses the getrandom syscall instead of reading from /dev/urandom.
diff --git a/ChangeLog.d/psa_allow_tweaking_library_configuration.txt b/ChangeLog.d/psa_allow_tweaking_library_configuration.txt
new file mode 100644
index 0000000..78b082c
--- /dev/null
+++ b/ChangeLog.d/psa_allow_tweaking_library_configuration.txt
@@ -0,0 +1,5 @@
+Features
+   * The PSA crypto subsystem can now be configured to use less static RAM by
+     tweaking the setting for the maximum amount of keys simultaneously in RAM.
+     MBEDTLS_PSA_KEY_SLOT_COUNT sets the maximum number of volatile keys that
+     can exist simultaneously. It has a sensible default if not overridden.
diff --git a/include/mbedtls/config.h b/include/mbedtls/config.h
index c3132a5..d370dbf 100644
--- a/include/mbedtls/config.h
+++ b/include/mbedtls/config.h
@@ -3687,6 +3687,17 @@
  */
 //#define MBEDTLS_PSA_HMAC_DRBG_MD_TYPE MBEDTLS_MD_SHA256
 
+/** \def MBEDTLS_PSA_KEY_SLOT_COUNT
+ * Restrict the PSA library to supporting a maximum amount of simultaneously
+ * loaded keys. A loaded key is a key stored by the PSA Crypto core as a
+ * volatile key, or a persistent key which is loaded temporarily by the
+ * library as part of a crypto operation in flight.
+ *
+ * If this option is unset, the library will fall back to a default value of
+ * 32 keys.
+ */
+//#define MBEDTLS_PSA_KEY_SLOT_COUNT 32
+
 /* SSL Cache options */
 //#define MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT       86400 /**< 1 day  */
 //#define MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES      50 /**< Maximum entries in cache */
diff --git a/include/psa/crypto_extra.h b/include/psa/crypto_extra.h
index 1f3ff0d..d4a9ee4 100644
--- a/include/psa/crypto_extra.h
+++ b/include/psa/crypto_extra.h
@@ -39,6 +39,10 @@
 /* UID for secure storage seed */
 #define PSA_CRYPTO_ITS_RANDOM_SEED_UID 0xFFFFFF52
 
+/* See config.h for definition */
+#if !defined(MBEDTLS_PSA_KEY_SLOT_COUNT)
+#define MBEDTLS_PSA_KEY_SLOT_COUNT 32
+#endif
 
 /** \addtogroup attributes
  * @{
diff --git a/library/entropy_poll.c b/library/entropy_poll.c
index 5250a7b..84b70fe 100644
--- a/library/entropy_poll.c
+++ b/library/entropy_poll.c
@@ -109,6 +109,21 @@
 #endif /* SYS_getrandom */
 #endif /* __linux__ || __midipix__ */
 
+#if defined(__FreeBSD__) || defined(__DragonFly__)
+#include <sys/param.h>
+#if (defined(__FreeBSD__) && __FreeBSD_version >= 1200000) || \
+    (defined(__DragonFly__) && __DragonFly_version >= 500700)
+#include <errno.h>
+#include <sys/random.h>
+#define HAVE_GETRANDOM
+static int getrandom_wrapper( void *buf, size_t buflen, unsigned int flags )
+{
+    return getrandom( buf, buflen, flags );
+}
+#endif /* (__FreeBSD__ && __FreeBSD_version >= 1200000) ||
+          (__DragonFly__ && __DragonFly_version >= 500700) */
+#endif /* __FreeBSD__ || __DragonFly__ */
+
 /*
  * Some BSD systems provide KERN_ARND.
  * This is equivalent to reading from /dev/urandom, only it doesn't require an
diff --git a/library/psa_crypto_slot_management.c b/library/psa_crypto_slot_management.c
index 6dca0ef..dcbee31 100644
--- a/library/psa_crypto_slot_management.c
+++ b/library/psa_crypto_slot_management.c
@@ -45,7 +45,7 @@
 
 typedef struct
 {
-    psa_key_slot_t key_slots[PSA_KEY_SLOT_COUNT];
+    psa_key_slot_t key_slots[MBEDTLS_PSA_KEY_SLOT_COUNT];
     unsigned key_slots_initialized : 1;
 } psa_global_data_t;
 
@@ -128,13 +128,13 @@
         if( status != PSA_SUCCESS )
             return( status );
 
-        for( slot_idx = 0; slot_idx < PSA_KEY_SLOT_COUNT; slot_idx++ )
+        for( slot_idx = 0; slot_idx < MBEDTLS_PSA_KEY_SLOT_COUNT; slot_idx++ )
         {
             slot = &global_data.key_slots[ slot_idx ];
             if( mbedtls_svc_key_id_equal( key, slot->attr.id ) )
                 break;
         }
-        status = ( slot_idx < PSA_KEY_SLOT_COUNT ) ?
+        status = ( slot_idx < MBEDTLS_PSA_KEY_SLOT_COUNT ) ?
                  PSA_SUCCESS : PSA_ERROR_DOES_NOT_EXIST;
     }
 
@@ -161,7 +161,7 @@
 {
     size_t slot_idx;
 
-    for( slot_idx = 0; slot_idx < PSA_KEY_SLOT_COUNT; slot_idx++ )
+    for( slot_idx = 0; slot_idx < MBEDTLS_PSA_KEY_SLOT_COUNT; slot_idx++ )
     {
         psa_key_slot_t *slot = &global_data.key_slots[ slot_idx ];
         slot->lock_count = 1;
@@ -184,7 +184,7 @@
     }
 
     selected_slot = unlocked_persistent_key_slot = NULL;
-    for( slot_idx = 0; slot_idx < PSA_KEY_SLOT_COUNT; slot_idx++ )
+    for( slot_idx = 0; slot_idx < MBEDTLS_PSA_KEY_SLOT_COUNT; slot_idx++ )
     {
         psa_key_slot_t *slot = &global_data.key_slots[ slot_idx ];
         if( ! psa_is_key_slot_occupied( slot ) )
@@ -453,7 +453,7 @@
 
     memset( stats, 0, sizeof( *stats ) );
 
-    for( slot_idx = 0; slot_idx < PSA_KEY_SLOT_COUNT; slot_idx++ )
+    for( slot_idx = 0; slot_idx < MBEDTLS_PSA_KEY_SLOT_COUNT; slot_idx++ )
     {
         const psa_key_slot_t *slot = &global_data.key_slots[ slot_idx ];
         if( psa_is_key_slot_locked( slot ) )
diff --git a/library/psa_crypto_slot_management.h b/library/psa_crypto_slot_management.h
index ef0814a..3d1a852 100644
--- a/library/psa_crypto_slot_management.h
+++ b/library/psa_crypto_slot_management.h
@@ -25,14 +25,10 @@
 #include "psa_crypto_core.h"
 #include "psa_crypto_se.h"
 
-/* Number of key slots (plus one because 0 is not used).
- * The value is a compile-time constant for now, for simplicity. */
-#define PSA_KEY_SLOT_COUNT 32
-
 /** Range of volatile key identifiers.
  *
- *  The last PSA_KEY_SLOT_COUNT identifiers of the implementation range
- *  of key identifiers are reserved for volatile key identifiers.
+ *  The last #MBEDTLS_PSA_KEY_SLOT_COUNT identifiers of the implementation
+ *  range of key identifiers are reserved for volatile key identifiers.
  *  A volatile key identifier is equal to #PSA_KEY_ID_VOLATILE_MIN plus the
  *  index of the key slot containing the volatile key definition.
  */
@@ -40,7 +36,7 @@
 /** The minimum value for a volatile key identifier.
  */
 #define PSA_KEY_ID_VOLATILE_MIN  ( PSA_KEY_ID_VENDOR_MAX - \
-                                   PSA_KEY_SLOT_COUNT + 1 )
+                                   MBEDTLS_PSA_KEY_SLOT_COUNT + 1 )
 
 /** The maximum value for a volatile key identifier.
  */
diff --git a/library/psa_crypto_storage.h b/library/psa_crypto_storage.h
index 8461691..970e108 100644
--- a/library/psa_crypto_storage.h
+++ b/library/psa_crypto_storage.h
@@ -49,7 +49,7 @@
  * - Using the ITS backend, all key ids are ok except 0xFFFFFF52
  *   (#PSA_CRYPTO_ITS_RANDOM_SEED_UID) for which the file contains the
  *   device's random seed (if this feature is enabled).
- * - Only key ids from 1 to #PSA_KEY_SLOT_COUNT are actually used.
+ * - Only key ids from 1 to #MBEDTLS_PSA_KEY_SLOT_COUNT are actually used.
  *
  * Since we need to preserve the random seed, avoid using that key slot.
  * Reserve a whole range of key slots just in case something else comes up.
diff --git a/programs/test/query_config.c b/programs/test/query_config.c
index 6962adf..b9105f8 100644
--- a/programs/test/query_config.c
+++ b/programs/test/query_config.c
@@ -2642,6 +2642,14 @@
     }
 #endif /* MBEDTLS_PSA_HMAC_DRBG_MD_TYPE */
 
+#if defined(MBEDTLS_PSA_KEY_SLOT_COUNT)
+    if( strcmp( "MBEDTLS_PSA_KEY_SLOT_COUNT", config ) == 0 )
+    {
+        MACRO_EXPANSION_TO_STR( MBEDTLS_PSA_KEY_SLOT_COUNT );
+        return( 0 );
+    }
+#endif /* MBEDTLS_PSA_KEY_SLOT_COUNT */
+
 #if defined(MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT)
     if( strcmp( "MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT", config ) == 0 )
     {
diff --git a/tests/suites/test_suite_psa_crypto.function b/tests/suites/test_suite_psa_crypto.function
index 18c9dc3..93f41b5 100644
--- a/tests/suites/test_suite_psa_crypto.function
+++ b/tests/suites/test_suite_psa_crypto.function
@@ -5707,7 +5707,7 @@
             break;
 
         case DERIVE_KEY:
-#if PSA_WANT_ALG_HKDF && PSA_WANT_ALG_SHA_256
+#if defined(PSA_WANT_ALG_HKDF) && defined(PSA_WANT_ALG_SHA_256)
             {
                 /* Create base key */
                 psa_algorithm_t derive_alg = PSA_ALG_HKDF( PSA_ALG_SHA_256 );
diff --git a/tests/suites/test_suite_psa_crypto_slot_management.function b/tests/suites/test_suite_psa_crypto_slot_management.function
index d14dfbb..dbf05d2 100644
--- a/tests/suites/test_suite_psa_crypto_slot_management.function
+++ b/tests/suites/test_suite_psa_crypto_slot_management.function
@@ -933,9 +933,9 @@
     psa_set_key_type( &attributes, PSA_KEY_TYPE_RAW_DATA );
 
     /*
-     * Create PSA_KEY_SLOT_COUNT persistent keys.
+     * Create MBEDTLS_PSA_KEY_SLOT_COUNT persistent keys.
      */
-    for( i = 0; i < PSA_KEY_SLOT_COUNT; i++ )
+    for( i = 0; i < MBEDTLS_PSA_KEY_SLOT_COUNT; i++ )
     {
         key = mbedtls_svc_key_id_make( i, i + 1 );
         psa_set_key_id( &attributes, key );
@@ -951,7 +951,7 @@
      * is removed from the RAM key slots. This makes room to store its
      * description in RAM.
      */
-    i = PSA_KEY_SLOT_COUNT;
+    i = MBEDTLS_PSA_KEY_SLOT_COUNT;
     key = mbedtls_svc_key_id_make( i, i + 1 );
     psa_set_key_id( &attributes, key );
     psa_set_key_lifetime( &attributes, lifetime );
@@ -966,15 +966,15 @@
                      MBEDTLS_SVC_KEY_ID_GET_KEY_ID( returned_key_id ) ) );
 
     /*
-     * Check that we can export all ( PSA_KEY_SLOT_COUNT + 1 ) keys,
+     * Check that we can export all ( MBEDTLS_PSA_KEY_SLOT_COUNT + 1 ) keys,
      * that they have the expected value and destroy them. In that process,
      * the description of the persistent key that was evicted from the RAM
      * slots when creating the last key is restored in a RAM slot to export
      * its value.
      */
-    for( i = 0; i <= PSA_KEY_SLOT_COUNT; i++ )
+    for( i = 0; i <= MBEDTLS_PSA_KEY_SLOT_COUNT; i++ )
     {
-        if( i < PSA_KEY_SLOT_COUNT )
+        if( i < MBEDTLS_PSA_KEY_SLOT_COUNT )
             key = mbedtls_svc_key_id_make( i, i + 1 );
         else
             key = returned_key_id;
@@ -1005,9 +1005,9 @@
     mbedtls_svc_key_id_t returned_key_id = MBEDTLS_SVC_KEY_ID_INIT;
     mbedtls_svc_key_id_t *keys = NULL;
 
-    TEST_ASSERT( PSA_KEY_SLOT_COUNT >= 1 );
+    TEST_ASSERT( MBEDTLS_PSA_KEY_SLOT_COUNT >= 1 );
 
-    ASSERT_ALLOC( keys, PSA_KEY_SLOT_COUNT );
+    ASSERT_ALLOC( keys, MBEDTLS_PSA_KEY_SLOT_COUNT );
     PSA_ASSERT( psa_crypto_init( ) );
 
     psa_set_key_usage_flags( &attributes,
@@ -1027,10 +1027,10 @@
     TEST_ASSERT( mbedtls_svc_key_id_equal( returned_key_id, persistent_key ) );
 
     /*
-     * Create PSA_KEY_SLOT_COUNT volatile keys
+     * Create MBEDTLS_PSA_KEY_SLOT_COUNT volatile keys
      */
     psa_set_key_lifetime( &attributes, PSA_KEY_LIFETIME_VOLATILE );
-    for( i = 0; i < PSA_KEY_SLOT_COUNT; i++ )
+    for( i = 0; i < MBEDTLS_PSA_KEY_SLOT_COUNT; i++ )
     {
         PSA_ASSERT( psa_import_key( &attributes,
                                     (uint8_t *) &i, sizeof( i ),
@@ -1050,12 +1050,12 @@
      * Check we can export the volatile key created last and that it has the
      * expected value. Then, destroy it.
      */
-    PSA_ASSERT( psa_export_key( keys[PSA_KEY_SLOT_COUNT - 1],
+    PSA_ASSERT( psa_export_key( keys[MBEDTLS_PSA_KEY_SLOT_COUNT - 1],
                                 exported, sizeof( exported ),
                                 &exported_length ) );
-    i = PSA_KEY_SLOT_COUNT - 1;
+    i = MBEDTLS_PSA_KEY_SLOT_COUNT - 1;
     ASSERT_COMPARE( exported, exported_length, (uint8_t *) &i, sizeof( i ) );
-    PSA_ASSERT( psa_destroy_key( keys[PSA_KEY_SLOT_COUNT - 1] ) );
+    PSA_ASSERT( psa_destroy_key( keys[MBEDTLS_PSA_KEY_SLOT_COUNT - 1] ) );
 
     /*
      * Check that we can now access the persistent key again.
@@ -1078,7 +1078,7 @@
      * Check we can export the remaining volatile keys and that they have the
      * expected values.
      */
-    for( i = 0; i < ( PSA_KEY_SLOT_COUNT - 1 ); i++ )
+    for( i = 0; i < ( MBEDTLS_PSA_KEY_SLOT_COUNT - 1 ); i++ )
     {
         PSA_ASSERT( psa_export_key( keys[i],
                                     exported, sizeof( exported ),