From 8eb294370515dfbfa02fe5f4110147dc935dc528 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Wed, 3 Feb 2021 20:07:11 +0100 Subject: [PATCH] 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 --- programs/ssl/ssl_test_lib.c | 42 +++++++++++++++++++++++++++++++++++-- programs/ssl/ssl_test_lib.h | 29 +++++++++++++++++++++++++ tests/scripts/all.sh | 11 ++++++++-- 3 files changed, 78 insertions(+), 4 deletions(-) diff --git a/programs/ssl/ssl_test_lib.c b/programs/ssl/ssl_test_lib.c index 56e94310c..6636e9e1a 100644 --- a/programs/ssl/ssl_test_lib.c +++ b/programs/ssl/ssl_test_lib.c @@ -46,6 +46,7 @@ mbedtls_time_t dummy_constant_time( mbedtls_time_t* time ) 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 @@ static int dummy_entropy( void *data, unsigned char *output, size_t len ) } 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 @@ void rng_init( rng_context_t *rng ) #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 @@ int rng_seed( rng_context_t *rng, int reproducible, const char *pers ) 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 @@ int rng_seed( rng_context_t *rng, int reproducible, const char *pers ) 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 @@ int rng_seed( rng_context_t *rng, int reproducible, const char *pers ) (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 @@ void rng_free( rng_context_t *rng ) #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 @@ int rng_get( void *p_rng, unsigned char *output, size_t output_len ) #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 861e82a00..d605a947b 100644 --- a/programs/ssl/ssl_test_lib.h +++ b/programs/ssl/ssl_test_lib.h @@ -130,10 +130,38 @@ void my_debug( void *ctx, int level, 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 @@ typedef struct #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 d1366e8ac..91d457a08 100755 --- a/tests/scripts/all.sh +++ b/tests/scripts/all.sh @@ -1018,12 +1018,16 @@ component_test_psa_external_rng_no_drbg_classic () { 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 @@ component_test_psa_external_rng_no_drbg_use_psa () { 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 () {