Support mbedtls_psa_get_random() in SSL test programs

The SSL test programs can now use mbedtls_psa_get_random() rather than
entropy+DRBG as a random generator. This happens if
the configuration option MBEDTLS_USE_PSA_CRYPTO is enabled, or if
MBEDTLS_TEST_USE_PSA_CRYPTO_RNG is set at build time.

Signed-off-by: Gilles Peskine <Gilles.Peskine@arm.com>
diff --git a/programs/ssl/ssl_test_lib.c b/programs/ssl/ssl_test_lib.c
index 56e9431..6636e9e 100644
--- a/programs/ssl/ssl_test_lib.c
+++ b/programs/ssl/ssl_test_lib.c
@@ -46,6 +46,7 @@
     return 0x5af2a056;
 }
 
+#if !defined(MBEDTLS_TEST_USE_PSA_CRYPTO_RNG)
 static int dummy_entropy( void *data, unsigned char *output, size_t len )
 {
     size_t i;
@@ -60,9 +61,15 @@
     }
     return( ret );
 }
+#endif
 
 void rng_init( rng_context_t *rng )
 {
+#if defined(MBEDTLS_TEST_USE_PSA_CRYPTO_RNG)
+    (void) rng;
+    psa_crypto_init( );
+#else /* !MBEDTLS_TEST_USE_PSA_CRYPTO_RNG */
+
 #if defined(MBEDTLS_CTR_DRBG_C)
     mbedtls_ctr_drbg_init( &rng->drbg );
 #elif defined(MBEDTLS_HMAC_DRBG_C)
@@ -72,6 +79,7 @@
 #endif
 
     mbedtls_entropy_init( &rng->entropy );
+#endif /* !MBEDTLS_TEST_USE_PSA_CRYPTO_RNG */
 }
 
 int rng_seed( rng_context_t *rng, int reproducible, const char *pers )
@@ -84,6 +92,18 @@
         return( -1 );
     }
 #endif
+#if defined(MBEDTLS_TEST_USE_PSA_CRYPTO_RNG)
+    /* The PSA crypto RNG does its own seeding. */
+    (void) rng;
+    (void) pers;
+    if( reproducible )
+    {
+        mbedtls_fprintf( stderr,
+                         "The PSA RNG does not support reproducible mode.\n" );
+        return( -1 );
+    }
+    return( 0 );
+#else /* !MBEDTLS_TEST_USE_PSA_CRYPTO_RNG */
     int ( *f_entropy )( void *, unsigned char *, size_t ) =
         ( reproducible ? dummy_entropy : mbedtls_entropy_func );
 
@@ -108,9 +128,9 @@
                                       f_entropy, &rng->entropy,
                                       (const unsigned char *) pers,
                                       strlen( pers ) );
-#else
+#else /* !defined(MBEDTLS_CTR_DRBG_C) && !defined(MBEDTLS_HMAC_DRBG_C) */
 #error "No DRBG available"
-#endif
+#endif /* !defined(MBEDTLS_CTR_DRBG_C) && !defined(MBEDTLS_HMAC_DRBG_C) */
 
     if( ret != 0 )
     {
@@ -118,12 +138,21 @@
                         (unsigned int) -ret );
         return( ret );
     }
+#endif /* !MBEDTLS_TEST_USE_PSA_CRYPTO_RNG */
 
     return( 0 );
 }
 
 void rng_free( rng_context_t *rng )
 {
+#if defined(MBEDTLS_TEST_USE_PSA_CRYPTO_RNG)
+    (void) rng;
+    /* Deinitialize the PSA crypto subsystem. This deactivates all PSA APIs.
+     * This is ok because none of our applications try to do any crypto after
+     * deinitializing the RNG. */
+    mbedtls_psa_crypto_free( );
+#else /* !MBEDTLS_TEST_USE_PSA_CRYPTO_RNG */
+
 #if defined(MBEDTLS_CTR_DRBG_C)
     mbedtls_ctr_drbg_free( &rng->drbg );
 #elif defined(MBEDTLS_HMAC_DRBG_C)
@@ -133,11 +162,18 @@
 #endif
 
     mbedtls_entropy_free( &rng->entropy );
+#endif /* !MBEDTLS_TEST_USE_PSA_CRYPTO_RNG */
 }
 
 int rng_get( void *p_rng, unsigned char *output, size_t output_len )
 {
+#if defined(MBEDTLS_TEST_USE_PSA_CRYPTO_RNG)
+    (void) p_rng;
+    return( mbedtls_psa_get_random( MBEDTLS_PSA_RANDOM_STATE,
+                                    output, output_len ) );
+#else /* !MBEDTLS_TEST_USE_PSA_CRYPTO_RNG */
     rng_context_t *rng = p_rng;
+
 #if defined(MBEDTLS_CTR_DRBG_C)
     return( mbedtls_ctr_drbg_random( &rng->drbg, output, output_len ) );
 #elif defined(MBEDTLS_HMAC_DRBG_C)
@@ -145,6 +181,8 @@
 #else
 #error "No DRBG available"
 #endif
+
+#endif /* !MBEDTLS_TEST_USE_PSA_CRYPTO_RNG */
 }
 
 #if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK)
diff --git a/programs/ssl/ssl_test_lib.h b/programs/ssl/ssl_test_lib.h
index 861e82a..d605a94 100644
--- a/programs/ssl/ssl_test_lib.h
+++ b/programs/ssl/ssl_test_lib.h
@@ -130,10 +130,38 @@
 
 mbedtls_time_t dummy_constant_time( mbedtls_time_t* time );
 
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+/* If MBEDTLS_TEST_USE_PSA_CRYPTO_RNG is defined, the SSL test programs will use
+ * mbedtls_psa_get_random() rather than entropy+DRBG as a random generator.
+ *
+ * The constraints are:
+ * - Without the entropy module, the PSA RNG is the only option.
+ * - Without at least one of the DRBG modules, the PSA RNG is the only option.
+ * - The PSA RNG does not support explicit seeding, so it is incompatible with
+ *   the reproducible mode used by test programs.
+ * - For good overall test coverage, there should be at least one configuration
+ *   where the test programs use the PSA RNG while the PSA RNG is itself based
+ *   on entropy+DRBG, and at least one configuration where the test programs
+ *   do not use the PSA RNG even though it's there.
+ *
+ * A simple choice that meets the constraints is to use the PSA RNG whenever
+ * MBEDTLS_USE_PSA_CRYPTO is enabled. There's no real technical reason the
+ * choice to use the PSA RNG in the test programs and the choice to use
+ * PSA crypto when TLS code needs crypto have to be tied together, but it
+ * happens to be a good match. It's also a good match from an application
+ * perspective: either PSA is preferred for TLS (both for crypto and for
+ * random generation) or it isn't.
+ */
+#define MBEDTLS_TEST_USE_PSA_CRYPTO_RNG
+#endif
+
 /** A context for random number generation (RNG).
  */
 typedef struct
 {
+#if defined(MBEDTLS_TEST_USE_PSA_CRYPTO_RNG)
+    unsigned char dummy;
+#else /* MBEDTLS_TEST_USE_PSA_CRYPTO_RNG */
     mbedtls_entropy_context entropy;
 #if defined(MBEDTLS_CTR_DRBG_C)
     mbedtls_ctr_drbg_context drbg;
@@ -142,6 +170,7 @@
 #else
 #error "No DRBG available"
 #endif
+#endif /* MBEDTLS_TEST_USE_PSA_CRYPTO_RNG */
 } rng_context_t;
 
 /** Initialize the RNG.
diff --git a/tests/scripts/all.sh b/tests/scripts/all.sh
index d1366e8..91d457a 100755
--- a/tests/scripts/all.sh
+++ b/tests/scripts/all.sh
@@ -1018,12 +1018,16 @@
     scripts/config.py unset MBEDTLS_HMAC_DRBG_C
     scripts/config.py unset MBEDTLS_ECDSA_DETERMINISTIC # requires HMAC_DRBG
     scripts/config.py set MBEDTLS_ECP_NO_INTERNAL_RNG
-    make CFLAGS="$ASAN_CFLAGS -O2" LDFLAGS="$ASAN_CFLAGS"
+    # When MBEDTLS_USE_PSA_CRYPTO is disabled and there is no DRBG,
+    # the SSL test programs don't have an RNG and can't work. Explicitly
+    # make them use the PSA RNG with -DMBEDTLS_TEST_USE_PSA_CRYPTO_RNG.
+    make CFLAGS="$ASAN_CFLAGS -O2 -DMBEDTLS_TEST_USE_PSA_CRYPTO_RNG" LDFLAGS="$ASAN_CFLAGS"
 
     msg "test: PSA_CRYPTO_EXTERNAL_RNG minus *_DRBG, classic crypto - main suites"
     make test
 
-    # no SSL tests as they all depend on having a DRBG
+    msg "test: PSA_CRYPTO_EXTERNAL_RNG minus *_DRBG, classic crypto - ssl-opt.sh (subset)"
+    if_build_succeeded tests/ssl-opt.sh -f 'Default'
 }
 
 component_test_psa_external_rng_no_drbg_use_psa () {
@@ -1038,6 +1042,9 @@
 
     msg "test: PSA_CRYPTO_EXTERNAL_RNG minus *_DRBG, PSA crypto - main suites"
     make test
+
+    msg "test: PSA_CRYPTO_EXTERNAL_RNG minus *_DRBG, PSA crypto - ssl-opt.sh (subset)"
+    if_build_succeeded tests/ssl-opt.sh -f 'Default\|opaque'
 }
 
 component_test_psa_external_rng_use_psa_crypto () {