From 4a23c98506658d73b04053a892b92b0266737241 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Wed, 3 Feb 2021 13:54:41 +0100 Subject: [PATCH 01/19] Fix exit status if the RNG seeding failed Signed-off-by: Gilles Peskine --- programs/ssl/ssl_client2.c | 3 ++- programs/ssl/ssl_server2.c | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c index 876555d93..706541284 100644 --- a/programs/ssl/ssl_client2.c +++ b/programs/ssl/ssl_client2.c @@ -1536,7 +1536,8 @@ int main( int argc, char *argv[] ) mbedtls_printf( "\n . Seeding the random number generator..." ); fflush( stdout ); - if( rng_seed( &rng, opt.reproducible, pers ) != 0 ) + ret = rng_seed( &rng, opt.reproducible, pers ); + if( ret != 0 ) goto exit; mbedtls_printf( " ok\n" ); diff --git a/programs/ssl/ssl_server2.c b/programs/ssl/ssl_server2.c index 57c053ce9..5d86e3bf8 100644 --- a/programs/ssl/ssl_server2.c +++ b/programs/ssl/ssl_server2.c @@ -2295,7 +2295,8 @@ int main( int argc, char *argv[] ) mbedtls_printf( "\n . Seeding the random number generator..." ); fflush( stdout ); - if( rng_seed( &rng, opt.reproducible, pers ) != 0 ) + ret = rng_seed( &rng, opt.reproducible, pers ); + if( ret != 0 ) goto exit; mbedtls_printf( " ok\n" ); From aaedbdcfd665c4ba6c63d92dd5724822108ac59a Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Wed, 3 Feb 2021 13:55:22 +0100 Subject: [PATCH 02/19] Refuse reproducible mode with MBEDTLS_USE_PSA_CRYPTO With MBEDTLS_USE_PSA_CRYPTO, some of the randomness for the TLS connection is generated inside the PSA crypto subsystem, which has no reproducible mode. Whether there is a nonzero amount of randomness coming from inside the PSA subsystem rather than from the random generator set by mbedtls_ssl_conf_rng() depends on the choice of cipher suite and other connection parameters as well as the level of support for MBEDTLS_USE_PSA_CRYPTO. Rather than give unreliable results, conservatively abort with a clear error message. Signed-off-by: Gilles Peskine --- programs/ssl/ssl_test_lib.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/programs/ssl/ssl_test_lib.c b/programs/ssl/ssl_test_lib.c index 46cea144c..56e94310c 100644 --- a/programs/ssl/ssl_test_lib.c +++ b/programs/ssl/ssl_test_lib.c @@ -76,6 +76,14 @@ void rng_init( rng_context_t *rng ) int rng_seed( rng_context_t *rng, int reproducible, const char *pers ) { +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if( reproducible ) + { + mbedtls_fprintf( stderr, + "MBEDTLS_USE_PSA_CRYPTO does not support reproducible mode.\n" ); + return( -1 ); + } +#endif int ( *f_entropy )( void *, unsigned char *, size_t ) = ( reproducible ? dummy_entropy : mbedtls_entropy_func ); From 2747d7dc609bb8ed8993e20dbf8b774104804000 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Wed, 3 Feb 2021 14:56:51 +0100 Subject: [PATCH 03/19] Duplicate no-DRBG tests: with and without MBEDTLS_USE_PSA_CRYPTO Whether MBEDTLS_USE_PSA_CRYPTO is enabled makes a significant difference with respect to how random generators are used (and, for no-HMAC_DRBG, how ECDSA signature is dispatched), so test both with and without it. Signed-off-by: Gilles Peskine --- tests/scripts/all.sh | 100 +++++++++++++++++++++++++++++++++++-------- 1 file changed, 83 insertions(+), 17 deletions(-) diff --git a/tests/scripts/all.sh b/tests/scripts/all.sh index 676c80449..d1366e8ac 100755 --- a/tests/scripts/all.sh +++ b/tests/scripts/all.sh @@ -911,37 +911,61 @@ component_test_rsa_no_crt () { if_build_succeeded tests/context-info.sh } -component_test_no_ctr_drbg () { - msg "build: Full minus CTR_DRBG" +component_test_no_ctr_drbg_classic () { + msg "build: Full minus CTR_DRBG, classic crypto in TLS" scripts/config.py full scripts/config.py unset MBEDTLS_CTR_DRBG_C + scripts/config.py unset MBEDTLS_USE_PSA_CRYPTO CC=gcc cmake -D CMAKE_BUILD_TYPE:String=Asan . make - msg "test: Full minus CTR_DRBG - main suites" + msg "test: Full minus CTR_DRBG, classic crypto - main suites" make test # In this configuration, the TLS test programs use HMAC_DRBG. # The SSL tests are slow, so run a small subset, just enough to get # confidence that the SSL code copes with HMAC_DRBG. - msg "test: Full minus CTR_DRBG - ssl-opt.sh (subset)" + msg "test: Full minus CTR_DRBG, classic crypto - ssl-opt.sh (subset)" if_build_succeeded tests/ssl-opt.sh -f 'Default\|SSL async private.*delay=\|tickets enabled on server' - msg "test: Full minus CTR_DRBG - compat.sh (subset)" + msg "test: Full minus CTR_DRBG, classic crypto - compat.sh (subset)" if_build_succeeded tests/compat.sh -m tls1_2 -t 'ECDSA PSK' -V NO -p OpenSSL } -component_test_no_hmac_drbg () { - msg "build: Full minus HMAC_DRBG" +component_test_no_ctr_drbg_use_psa () { + msg "build: Full minus CTR_DRBG, PSA crypto in TLS" scripts/config.py full - scripts/config.py unset MBEDTLS_HMAC_DRBG_C - scripts/config.py unset MBEDTLS_ECDSA_DETERMINISTIC # requires HMAC_DRBG + scripts/config.py unset MBEDTLS_CTR_DRBG_C + scripts/config.py set MBEDTLS_USE_PSA_CRYPTO CC=gcc cmake -D CMAKE_BUILD_TYPE:String=Asan . make - msg "test: Full minus HMAC_DRBG - main suites" + msg "test: Full minus CTR_DRBG, USE_PSA_CRYPTO - main suites" + make test + + # In this configuration, the TLS test programs use HMAC_DRBG. + # The SSL tests are slow, so run a small subset, just enough to get + # confidence that the SSL code copes with HMAC_DRBG. + msg "test: Full minus CTR_DRBG, USE_PSA_CRYPTO - ssl-opt.sh (subset)" + if_build_succeeded tests/ssl-opt.sh -f 'Default\|SSL async private.*delay=\|tickets enabled on server' + + msg "test: Full minus CTR_DRBG, USE_PSA_CRYPTO - compat.sh (subset)" + if_build_succeeded tests/compat.sh -m tls1_2 -t 'ECDSA PSK' -V NO -p OpenSSL +} + +component_test_no_hmac_drbg_classic () { + msg "build: Full minus HMAC_DRBG, classic crypto in TLS" + scripts/config.py full + scripts/config.py unset MBEDTLS_HMAC_DRBG_C + scripts/config.py unset MBEDTLS_ECDSA_DETERMINISTIC # requires HMAC_DRBG + scripts/config.py unset MBEDTLS_USE_PSA_CRYPTO + + CC=gcc cmake -D CMAKE_BUILD_TYPE:String=Asan . + make + + msg "test: Full minus HMAC_DRBG, classic crypto - main suites" make test # Normally our ECDSA implementation uses deterministic ECDSA. But since @@ -949,17 +973,61 @@ component_test_no_hmac_drbg () { # instead. # Test SSL with non-deterministic ECDSA. Only test features that # might be affected by how ECDSA signature is performed. - msg "test: Full minus HMAC_DRBG - ssl-opt.sh (subset)" + msg "test: Full minus HMAC_DRBG, classic crypto - ssl-opt.sh (subset)" if_build_succeeded tests/ssl-opt.sh -f 'Default\|SSL async private: sign' # To save time, only test one protocol version, since this part of # the protocol is identical in (D)TLS up to 1.2. - msg "test: Full minus HMAC_DRBG - compat.sh (ECDSA)" + msg "test: Full minus HMAC_DRBG, classic crypto - compat.sh (ECDSA)" if_build_succeeded tests/compat.sh -m tls1_2 -t 'ECDSA' } -component_test_psa_external_rng_no_drbg () { - msg "build: PSA_CRYPTO_EXTERNAL_RNG minus *_DRBG" +component_test_no_hmac_drbg_use_psa () { + msg "build: Full minus HMAC_DRBG, PSA crypto in TLS" + scripts/config.py full + scripts/config.py unset MBEDTLS_HMAC_DRBG_C + scripts/config.py unset MBEDTLS_ECDSA_DETERMINISTIC # requires HMAC_DRBG + scripts/config.py set MBEDTLS_USE_PSA_CRYPTO + + CC=gcc cmake -D CMAKE_BUILD_TYPE:String=Asan . + make + + msg "test: Full minus HMAC_DRBG, USE_PSA_CRYPTO - main suites" + make test + + # Normally our ECDSA implementation uses deterministic ECDSA. But since + # HMAC_DRBG is disabled in this configuration, randomized ECDSA is used + # instead. + # Test SSL with non-deterministic ECDSA. Only test features that + # might be affected by how ECDSA signature is performed. + msg "test: Full minus HMAC_DRBG, USE_PSA_CRYPTO - ssl-opt.sh (subset)" + if_build_succeeded tests/ssl-opt.sh -f 'Default\|SSL async private: sign' + + # To save time, only test one protocol version, since this part of + # the protocol is identical in (D)TLS up to 1.2. + msg "test: Full minus HMAC_DRBG, USE_PSA_CRYPTO - compat.sh (ECDSA)" + if_build_succeeded tests/compat.sh -m tls1_2 -t 'ECDSA' +} + +component_test_psa_external_rng_no_drbg_classic () { + msg "build: PSA_CRYPTO_EXTERNAL_RNG minus *_DRBG, classic crypto in TLS" + scripts/config.py full + scripts/config.py unset MBEDTLS_USE_PSA_CRYPTO + scripts/config.py set MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG + scripts/config.py unset MBEDTLS_CTR_DRBG_C + 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" + + 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 +} + +component_test_psa_external_rng_no_drbg_use_psa () { + msg "build: PSA_CRYPTO_EXTERNAL_RNG minus *_DRBG, PSA crypto in TLS" scripts/config.py full scripts/config.py set MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG scripts/config.py unset MBEDTLS_CTR_DRBG_C @@ -968,10 +1036,8 @@ component_test_psa_external_rng_no_drbg () { scripts/config.py set MBEDTLS_ECP_NO_INTERNAL_RNG make CFLAGS="$ASAN_CFLAGS -O2" LDFLAGS="$ASAN_CFLAGS" - msg "test: PSA_CRYPTO_EXTERNAL_RNG minus *_DRBG" + msg "test: PSA_CRYPTO_EXTERNAL_RNG minus *_DRBG, PSA crypto - main suites" make test - - # no SSL tests as they all depend on having a DRBG } component_test_psa_external_rng_use_psa_crypto () { From 077599ad85b07976e17d2f8c451d62fa8764c2a6 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Wed, 3 Feb 2021 18:55:39 +0100 Subject: [PATCH 04/19] New test suite for random generation Test random generation as a whole. This is different from test_suite_*_drbg and test_suite_entropy, which respectively test PRNG modules and entropy collection. Start with basic tests: good-case tests, and do it twice and compare the results to validate that entropy collection doesn't repeat itself. Signed-off-by: Gilles Peskine --- tests/CMakeLists.txt | 1 + tests/suites/test_suite_random.data | 17 ++++ tests/suites/test_suite_random.function | 119 ++++++++++++++++++++++++ 3 files changed, 137 insertions(+) create mode 100644 tests/suites/test_suite_random.data create mode 100644 tests/suites/test_suite_random.function diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index f8ce925df..97369b2c2 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -150,6 +150,7 @@ add_test_suite(psa_crypto_se_driver_hal) add_test_suite(psa_crypto_se_driver_hal_mocks) add_test_suite(psa_crypto_slot_management) add_test_suite(psa_its) +add_test_suite(random) add_test_suite(rsa) add_test_suite(shax) add_test_suite(ssl) diff --git a/tests/suites/test_suite_random.data b/tests/suites/test_suite_random.data new file mode 100644 index 000000000..47f2ec7eb --- /dev/null +++ b/tests/suites/test_suite_random.data @@ -0,0 +1,17 @@ +Generate random twice with CTR_DRBG +random_twice_with_ctr_drbg: + +Generate random twice with HMAC_DRBG(SHA-1) +depends_on:MBEDTLS_SHA1_C +random_twice_with_hmac_drbg:MBEDTLS_MD_SHA1 + +Generate random twice with HMAC_DRBG(SHA-256) +depends_on:MBEDTLS_SHA256_C +random_twice_with_hmac_drbg:MBEDTLS_MD_SHA256 + +Generate random twice with HMAC_DRBG(SHA-512) +depends_on:MBEDTLS_SHA512_C +random_twice_with_hmac_drbg:MBEDTLS_MD_SHA512 + +Generate random twice with PSA API +random_twice_with_psa_from_psa: diff --git a/tests/suites/test_suite_random.function b/tests/suites/test_suite_random.function new file mode 100644 index 000000000..744daf59c --- /dev/null +++ b/tests/suites/test_suite_random.function @@ -0,0 +1,119 @@ +/* BEGIN_HEADER */ + +/* Test random generation as a whole. */ + +#include "mbedtls/ctr_drbg.h" +#include "mbedtls/entropy.h" +#include "mbedtls/hmac_drbg.h" +#include "psa/crypto.h" + +/* How many bytes to generate in each test case for repeated generation. + * This must be high enough that the probability of generating the same + * output twice is infinitesimal, but low enough that random generators + * are willing to deliver that much. */ +#define OUTPUT_SIZE 32 + +/* END_HEADER */ + +/* BEGIN_CASE depends_on:MBEDTLS_ENTROPY_C:MBEDTLS_CTR_DRBG_C */ +void random_twice_with_ctr_drbg( ) +{ + mbedtls_entropy_context entropy; + mbedtls_ctr_drbg_context drbg; + unsigned char output1[OUTPUT_SIZE]; + unsigned char output2[OUTPUT_SIZE]; + + /* First round */ + mbedtls_entropy_init( &entropy ); + mbedtls_ctr_drbg_init( &drbg ); + TEST_EQUAL( 0, mbedtls_ctr_drbg_seed( &drbg, + mbedtls_entropy_func, &entropy, + NULL, 0 ) ); + TEST_EQUAL( 0, mbedtls_ctr_drbg_random( &drbg, + output1, sizeof( output1 ) ) ); + mbedtls_ctr_drbg_free( &drbg ); + mbedtls_entropy_free( &entropy ); + + /* Second round */ + mbedtls_entropy_init( &entropy ); + mbedtls_ctr_drbg_init( &drbg ); + TEST_EQUAL( 0, mbedtls_ctr_drbg_seed( &drbg, + mbedtls_entropy_func, &entropy, + NULL, 0 ) ); + TEST_EQUAL( 0, mbedtls_ctr_drbg_random( &drbg, + output2, sizeof( output2 ) ) ); + mbedtls_ctr_drbg_free( &drbg ); + mbedtls_entropy_free( &entropy ); + + /* The two rounds must generate different random data. */ + TEST_ASSERT( memcmp( output1, output2, OUTPUT_SIZE ) != 0 ); + +exit: + mbedtls_ctr_drbg_free( &drbg ); + mbedtls_entropy_free( &entropy ); +} +/* END_CASE */ + +/* BEGIN_CASE depends_on:MBEDTLS_ENTROPY_C:MBEDTLS_HMAC_DRBG_C */ +void random_twice_with_hmac_drbg( int md_type ) +{ + mbedtls_entropy_context entropy; + mbedtls_hmac_drbg_context drbg; + unsigned char output1[OUTPUT_SIZE]; + unsigned char output2[OUTPUT_SIZE]; + const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( md_type ); + + /* First round */ + mbedtls_entropy_init( &entropy ); + mbedtls_hmac_drbg_init( &drbg ); + TEST_EQUAL( 0, mbedtls_hmac_drbg_seed( &drbg, md_info, + mbedtls_entropy_func, &entropy, + NULL, 0 ) ); + TEST_EQUAL( 0, mbedtls_hmac_drbg_random( &drbg, + output1, sizeof( output1 ) ) ); + mbedtls_hmac_drbg_free( &drbg ); + mbedtls_entropy_free( &entropy ); + + /* Second round */ + mbedtls_entropy_init( &entropy ); + mbedtls_hmac_drbg_init( &drbg ); + TEST_EQUAL( 0, mbedtls_hmac_drbg_seed( &drbg, md_info, + mbedtls_entropy_func, &entropy, + NULL, 0 ) ); + TEST_EQUAL( 0, mbedtls_hmac_drbg_random( &drbg, + output2, sizeof( output2 ) ) ); + mbedtls_hmac_drbg_free( &drbg ); + mbedtls_entropy_free( &entropy ); + + /* The two rounds must generate different random data. */ + TEST_ASSERT( memcmp( output1, output2, OUTPUT_SIZE ) != 0 ); + +exit: + mbedtls_hmac_drbg_free( &drbg ); + mbedtls_entropy_free( &entropy ); +} +/* END_CASE */ + +/* BEGIN_CASE depends_on:MBEDTLS_PSA_CRYPTO_C:!MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ +void random_twice_with_psa_from_psa( ) +{ + unsigned char output1[OUTPUT_SIZE]; + unsigned char output2[OUTPUT_SIZE]; + + /* First round */ + PSA_ASSERT( psa_crypto_init( ) ); + PSA_ASSERT( psa_generate_random( output1, sizeof( output1 ) ) ); + PSA_DONE( ); + + /* Second round */ + PSA_ASSERT( psa_crypto_init( ) ); + PSA_ASSERT( psa_generate_random( output2, sizeof( output2 ) ) ); + PSA_DONE( ); + + /* The two rounds must generate different random data. */ + TEST_ASSERT( memcmp( output1, output2, OUTPUT_SIZE ) != 0 ); + +exit: + PSA_DONE( ); +} +/* END_CASE */ From e3ed802138c1616069461b5067c218a94f6d334a Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Wed, 3 Feb 2021 20:04:08 +0100 Subject: [PATCH 05/19] Expose mbedtls_psa_get_random() Expose whatever RNG the PSA subsystem uses to applications using the mbedtls_xxx API. Signed-off-by: Gilles Peskine --- ChangeLog.d/mbedtls_psa_get_random.txt | 8 +++ include/mbedtls/psa_util.h | 84 +++++++++++++++++++++++++ library/psa_crypto_random_impl.h | 3 + tests/suites/test_suite_random.data | 34 ++++++++++ tests/suites/test_suite_random.function | 83 ++++++++++++++++++++++++ 5 files changed, 212 insertions(+) create mode 100644 ChangeLog.d/mbedtls_psa_get_random.txt diff --git a/ChangeLog.d/mbedtls_psa_get_random.txt b/ChangeLog.d/mbedtls_psa_get_random.txt new file mode 100644 index 000000000..9abbfff78 --- /dev/null +++ b/ChangeLog.d/mbedtls_psa_get_random.txt @@ -0,0 +1,8 @@ +Features + * Partial implementation of the PSA crypto driver interface: Mbed TLS can + now use an external random generator instead of the library's own + entropy collection and DRBG code. Enable MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG + and See the documentatio of mbedtls_psa_external_get_random() for details. + * Applications using PSA crypto can now use its random generator in the + mbedtls_xxx API. See the documentation of mbedtls_psa_get_random() for + details. diff --git a/include/mbedtls/psa_util.h b/include/mbedtls/psa_util.h index d8a32c59e..b4814012e 100644 --- a/include/mbedtls/psa_util.h +++ b/include/mbedtls/psa_util.h @@ -419,4 +419,88 @@ static inline int mbedtls_psa_tls_ecpoint_to_psa_ec( unsigned char const *src, #endif /* MBEDTLS_USE_PSA_CRYPTO */ +/* Expose whatever RNG the PSA subsystem uses to applications using the + * mbedtls_xxx API. The declarations here need to be consistent with the + * implementation in library/psa_crypto_random_impl.h. */ +#if defined(MBEDTLS_PSA_CRYPTO_C) + +/* The type of a `f_rng` random generator function that many library functions + * take. + * + * This type name is not part of the Mbed TLS stable API. It may be renamed + * or moved without warning. + */ +typedef int mbedtls_f_rng_t( void *p_rng, unsigned char *output, size_t output_size ); + +#if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) + +/** The random generator function for the PSA subsystem. + * + * This function is suitable as the `f_rng` random generator function + * parameter of many `mbedtls_xxx` functions. It must be used in combination + * with the random generator state #MBEDTLS_PSA_RANDOM_STATE. + * + * The implementation of this function depends on the configuration of the + * library. + + * \note Depending on the configuration, this may be a function or + * a pointer to a function. + * + * \note This function may only be used if the PSA crypto subsystem is active. + * This means that you must call psa_crypto_init() before any call to + * this function, and you must not call this function after calling + * mbedtls_psa_crypto_free(). + * + * \param p_rng The random generator context. This must be + * #MBEDTLS_PSA_RANDOM_STATE. No other state is + * supported. + * \param output The buffer to fill. It must have room for + * \c output_size bytes. + * \param output_size The number of bytes to write to \p output. + * This function may fail if \p output_size is too + * large. It is guaranteed to accept any output size + * requested by Mbed TLS library functions. The + * maximum request size depends on the library + * configuration. + * + * \return \c 0 on success. + * \return An `MBEDTLS_ERR_ENTROPY_xxx`, + * `MBEDTLS_ERR_CTR_DRBG_xxx` or + * `MBEDTLS_ERR_HMAC_DRBG_xxx` on error. + */ +int mbedtls_psa_get_random( void *p_rng, + unsigned char *output, + size_t output_size ); + +/** The random generator state for the PSA subsystem. + * + * This macro expands to an expression which is suitable as the `p_rng` + * random generator state parameter of many `mbedtls_xxx` functions. + * It must be used in combination with the random generator function + * mbedtls_psa_get_random(). + * + * The implementation of this macro depends on the configuration of the + * library. Do not make any assumption on its nature. + */ +#define MBEDTLS_PSA_RANDOM_STATE NULL + +#else /* !defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) */ + +#if defined(MBEDTLS_CTR_DRBG_C) +#include "mbedtls/ctr_drbg.h" +typedef mbedtls_ctr_drbg_context mbedtls_psa_drbg_context_t; +static mbedtls_f_rng_t *const mbedtls_psa_get_random = mbedtls_ctr_drbg_random; +#elif defined(MBEDTLS_HMAC_DRBG_C) +#include "mbedtls/hmac_drbg.h" +typedef mbedtls_hmac_drbg_context mbedtls_psa_drbg_context_t; +static mbedtls_f_rng_t *const mbedtls_psa_get_random = mbedtls_hmac_drbg_random; +#endif +extern mbedtls_psa_drbg_context_t *const mbedtls_psa_random_state; + +#define MBEDTLS_PSA_RANDOM_STATE mbedtls_psa_random_state + +#endif /* !defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) */ + +#endif /* MBEDTLS_PSA_CRYPTO_C */ + #endif /* MBEDTLS_PSA_UTIL_H */ diff --git a/library/psa_crypto_random_impl.h b/library/psa_crypto_random_impl.h index 1232186c9..4fa54a9fa 100644 --- a/library/psa_crypto_random_impl.h +++ b/library/psa_crypto_random_impl.h @@ -1,6 +1,9 @@ /** \file psa_crypto_random_impl.h * * \brief PSA crypto random generator implementation abstraction. + * + * The definitions here need to be consistent with the declarations + * in include/mbedtls/psa_util.h. */ /* * Copyright The Mbed TLS Contributors diff --git a/tests/suites/test_suite_random.data b/tests/suites/test_suite_random.data index 47f2ec7eb..d781f2ba5 100644 --- a/tests/suites/test_suite_random.data +++ b/tests/suites/test_suite_random.data @@ -13,5 +13,39 @@ Generate random twice with HMAC_DRBG(SHA-512) depends_on:MBEDTLS_SHA512_C random_twice_with_hmac_drbg:MBEDTLS_MD_SHA512 +Generate random twice with PSA classic wrapper +random_twice_with_psa_from_classic: + Generate random twice with PSA API random_twice_with_psa_from_psa: + +# This bad-usage test case currently crashes in the default configuration +# because CTR_DRBG crashes when given an unseeded context. This is arguably +# a good thing because it prevents misuse of mbedtls_psa_get_random(). +#PSA classic wrapper: PSA not active +#mbedtls_psa_get_random_no_init: + +PSA classic wrapper: 0 bytes +mbedtls_psa_get_random_length:0 + +PSA classic wrapper: 1 byte +mbedtls_psa_get_random_length:1 + +PSA classic wrapper: 256 bytes +mbedtls_psa_get_random_length:256 + +PSA classic wrapper: external RNG large +depends_on:MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG +mbedtls_psa_get_random_length:1024 + +PSA classic wrapper: CTR_DRBG max +depends_on:!MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG:MBEDTLS_CTR_DRBG_C +mbedtls_psa_get_random_length:MBEDTLS_CTR_DRBG_MAX_REQUEST + +PSA classic wrapper: HMAC_DRBG max +depends_on:!MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG:!MBEDTLS_CTR_DRBG_C:MBEDTLS_HMAC_DRBG_C +mbedtls_psa_get_random_length:MBEDTLS_HMAC_DRBG_MAX_REQUEST + +PSA classic wrapper: ECDSA signature (SECP256R1) +depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED +mbedtls_psa_get_random_ecdsa_sign:MBEDTLS_ECP_DP_SECP256R1 diff --git a/tests/suites/test_suite_random.function b/tests/suites/test_suite_random.function index 744daf59c..c532c8a3b 100644 --- a/tests/suites/test_suite_random.function +++ b/tests/suites/test_suite_random.function @@ -2,9 +2,12 @@ /* Test random generation as a whole. */ +#include "mbedtls/bignum.h" #include "mbedtls/ctr_drbg.h" +#include "mbedtls/ecdsa.h" #include "mbedtls/entropy.h" #include "mbedtls/hmac_drbg.h" +#include "mbedtls/psa_util.h" #include "psa/crypto.h" /* How many bytes to generate in each test case for repeated generation. @@ -94,6 +97,32 @@ exit: } /* END_CASE */ +/* BEGIN_CASE depends_on:MBEDTLS_PSA_CRYPTO_C:!MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ +void random_twice_with_psa_from_classic( ) +{ + unsigned char output1[OUTPUT_SIZE]; + unsigned char output2[OUTPUT_SIZE]; + + /* First round */ + PSA_ASSERT( psa_crypto_init( ) ); + TEST_EQUAL( 0, mbedtls_psa_get_random( MBEDTLS_PSA_RANDOM_STATE, + output1, sizeof( output1 ) ) ); + PSA_DONE( ); + + /* Second round */ + PSA_ASSERT( psa_crypto_init( ) ); + TEST_EQUAL( 0, mbedtls_psa_get_random( MBEDTLS_PSA_RANDOM_STATE, + output2, sizeof( output2 ) ) ); + PSA_DONE( ); + + /* The two rounds must generate different random data. */ + TEST_ASSERT( memcmp( output1, output2, OUTPUT_SIZE ) != 0 ); + +exit: + PSA_DONE( ); +} +/* END_CASE */ + /* BEGIN_CASE depends_on:MBEDTLS_PSA_CRYPTO_C:!MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ void random_twice_with_psa_from_psa( ) { @@ -117,3 +146,57 @@ exit: PSA_DONE( ); } /* END_CASE */ + +/* BEGIN_CASE depends_on:MBEDTLS_PSA_CRYPTO_C */ +void mbedtls_psa_get_random_no_init( ) +{ + unsigned char output[1]; + + TEST_ASSERT( mbedtls_psa_get_random( MBEDTLS_PSA_RANDOM_STATE, + output, sizeof( output ) ) != 0 ); +} +/* END_CASE */ + +/* BEGIN_CASE depends_on:MBEDTLS_PSA_CRYPTO_C */ +void mbedtls_psa_get_random_length( int n ) +{ + unsigned char *output = NULL; + + PSA_ASSERT( psa_crypto_init( ) ); + ASSERT_ALLOC( output, n ); + + TEST_EQUAL( 0, mbedtls_psa_get_random( MBEDTLS_PSA_RANDOM_STATE, + output, n ) ); +exit: + mbedtls_free( output ); + PSA_DONE( ); +} +/* END_CASE */ + +/* BEGIN_CASE depends_on:MBEDTLS_PSA_CRYPTO_C:MBEDTLS_ECDSA_C */ +void mbedtls_psa_get_random_ecdsa_sign( int curve ) +{ + mbedtls_ecp_group grp; + mbedtls_mpi d, r, s; + unsigned char buf[] = "This is not a hash."; + + mbedtls_ecp_group_init( &grp ); + mbedtls_mpi_init( &d ); + mbedtls_mpi_init( &r ); + mbedtls_mpi_init( &s ); + + TEST_EQUAL( 0, mbedtls_mpi_lset( &d, 123456789 ) ); + TEST_EQUAL( 0, mbedtls_ecp_group_load( &grp, curve ) ); + PSA_ASSERT( psa_crypto_init( ) ); + TEST_EQUAL( 0, mbedtls_ecdsa_sign( &grp, &r, &s, &d, + buf, sizeof( buf ), + mbedtls_psa_get_random, + MBEDTLS_PSA_RANDOM_STATE ) ); +exit: + mbedtls_mpi_free( &d ); + mbedtls_mpi_free( &r ); + mbedtls_mpi_free( &s ); + mbedtls_ecp_group_free( &grp ); + PSA_DONE( ); +} +/* END_CASE */ From 8eb294370515dfbfa02fe5f4110147dc935dc528 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Wed, 3 Feb 2021 20:07:11 +0100 Subject: [PATCH 06/19] 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 () { From 34babfc5b29bd6a1476109c4557ab21548c27767 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Tue, 16 Feb 2021 15:44:37 +0100 Subject: [PATCH 07/19] Add comments to a few #endif closing a long chunk Signed-off-by: Gilles Peskine --- programs/ssl/ssl_client2.c | 11 ++++++----- programs/ssl/ssl_server2.c | 4 ++-- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c index 706541284..8f2b2c159 100644 --- a/programs/ssl/ssl_client2.c +++ b/programs/ssl/ssl_client2.c @@ -703,7 +703,7 @@ int main( int argc, char *argv[] ) #if defined(MBEDTLS_USE_PSA_CRYPTO) psa_key_id_t key_slot = 0; /* invalid key slot */ #endif -#endif +#endif /* MBEDTLS_X509_CRT_PARSE_C */ char *p, *q; const int *list; #if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION) @@ -1882,7 +1882,7 @@ int main( int argc, char *argv[] ) #else fprintf( stderr, "Warning: reproducible option used without constant time\n" ); #endif -#endif +#endif /* MBEDTLS_HAVE_TIME */ } mbedtls_ssl_conf_rng( &conf, rng_get, &rng ); mbedtls_ssl_conf_dbg( &conf, my_debug, stdout ); @@ -1928,7 +1928,7 @@ int main( int argc, char *argv[] ) goto exit; } } -#endif +#endif /* MBEDTLS_X509_CRT_PARSE_C */ #if defined(MBEDTLS_ECP_C) if( opt.curves != NULL && @@ -3000,7 +3000,8 @@ exit: #if defined(MBEDTLS_USE_PSA_CRYPTO) psa_destroy_key( key_slot ); #endif -#endif +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + mbedtls_ssl_session_free( &saved_session ); mbedtls_ssl_free( &ssl ); mbedtls_ssl_config_free( &conf ); @@ -3040,7 +3041,7 @@ exit: mbedtls_memory_buffer_alloc_status(); #endif mbedtls_memory_buffer_alloc_free(); -#endif +#endif /* MBEDTLS_MEMORY_BUFFER_ALLOC_C */ #if defined(_WIN32) if( opt.query_config_mode == DFL_QUERY_CONFIG_MODE ) diff --git a/programs/ssl/ssl_server2.c b/programs/ssl/ssl_server2.c index 5d86e3bf8..0bbf018b0 100644 --- a/programs/ssl/ssl_server2.c +++ b/programs/ssl/ssl_server2.c @@ -2684,7 +2684,7 @@ int main( int argc, char *argv[] ) #else fprintf( stderr, "Warning: reproducible option used without constant time\n" ); #endif -#endif +#endif /* MBEDTLS_HAVE_TIME */ } mbedtls_ssl_conf_rng( &conf, rng_get, &rng ); mbedtls_ssl_conf_dbg( &conf, my_debug, stdout ); @@ -4003,7 +4003,7 @@ exit: mbedtls_memory_buffer_alloc_status(); #endif mbedtls_memory_buffer_alloc_free(); -#endif +#endif /* MBEDTLS_MEMORY_BUFFER_ALLOC_C */ if( opt.query_config_mode == DFL_QUERY_CONFIG_MODE ) { From b8c484088c98ed37205e9ada1e012d8a901f2381 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Mon, 8 Feb 2021 20:28:22 +0100 Subject: [PATCH 08/19] Fix psa_destroy_key called after mbedtls_psa_crypto_free Move the call to destroy the PSK to before freeing the SSL session data and calling rng_free(), which deinitializes the PSA subsystem. This particular ordering was chosen to make the ssl_client2 more similar to ssl_server2. This fixes the client failing on the psa_destroy_key() call in `ssl-opt.sh -f 'opaque psk on client'`. Signed-off-by: Gilles Peskine --- programs/ssl/ssl_client2.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c index 8f2b2c159..7d904d128 100644 --- a/programs/ssl/ssl_client2.c +++ b/programs/ssl/ssl_client2.c @@ -3002,19 +3002,6 @@ exit: #endif #endif /* MBEDTLS_X509_CRT_PARSE_C */ - mbedtls_ssl_session_free( &saved_session ); - mbedtls_ssl_free( &ssl ); - mbedtls_ssl_config_free( &conf ); - rng_free( &rng ); - if( session_data != NULL ) - mbedtls_platform_zeroize( session_data, session_data_len ); - mbedtls_free( session_data ); -#if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION) - if( context_buf != NULL ) - mbedtls_platform_zeroize( context_buf, context_buf_len ); - mbedtls_free( context_buf ); -#endif - #if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) && \ defined(MBEDTLS_USE_PSA_CRYPTO) if( opt.psk_opaque != 0 ) @@ -3036,6 +3023,19 @@ exit: #endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED && MBEDTLS_USE_PSA_CRYPTO */ + mbedtls_ssl_session_free( &saved_session ); + mbedtls_ssl_free( &ssl ); + mbedtls_ssl_config_free( &conf ); + rng_free( &rng ); + if( session_data != NULL ) + mbedtls_platform_zeroize( session_data, session_data_len ); + mbedtls_free( session_data ); +#if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION) + if( context_buf != NULL ) + mbedtls_platform_zeroize( context_buf, context_buf_len ); + mbedtls_free( context_buf ); +#endif + #if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) #if defined(MBEDTLS_MEMORY_DEBUG) mbedtls_memory_buffer_alloc_status(); From 1dc19ffb2911fb4982e4753add0b352e860a4dd4 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Mon, 8 Feb 2021 20:59:39 +0100 Subject: [PATCH 09/19] The PSA external RNG does not require MBEDTLS_USE_PSA_CRYPTO The dependency is on MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG plus MBEDTLS_PSA_CRYPTO_C. MBEDTLS_USE_PSA_CRYPTO is irrelevant. Signed-off-by: Gilles Peskine --- tests/include/test/helpers.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/include/test/helpers.h b/tests/include/test/helpers.h index ce8a1e285..9da2cdb1c 100644 --- a/tests/include/test/helpers.h +++ b/tests/include/test/helpers.h @@ -190,7 +190,7 @@ void* mbedtls_test_param_failed_get_state_buf( void ); void mbedtls_test_param_failed_reset_state( void ); #endif /* MBEDTLS_CHECK_PARAMS */ -#if defined(MBEDTLS_USE_PSA_CRYPTO) && defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) +#if defined(MBEDTLS_PSA_CRYPTO_C) && defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) #include "test/fake_external_rng_for_test.h" #endif From 38c12fd48ee254d3c0f9fc708aa30b0dbe7277a3 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Mon, 8 Feb 2021 21:02:53 +0100 Subject: [PATCH 10/19] In external_rng tests, disable the entropy module The point of having an external RNG is that you can disable all built-in RNG functionality: both the entropy part and the DRBG part. Signed-off-by: Gilles Peskine --- tests/scripts/all.sh | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/scripts/all.sh b/tests/scripts/all.sh index 91d457a08..afc76855b 100755 --- a/tests/scripts/all.sh +++ b/tests/scripts/all.sh @@ -1014,6 +1014,9 @@ component_test_psa_external_rng_no_drbg_classic () { scripts/config.py full scripts/config.py unset MBEDTLS_USE_PSA_CRYPTO scripts/config.py set MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG + scripts/config.py unset MBEDTLS_ENTROPY_C + scripts/config.py unset MBEDTLS_ENTROPY_NV_SEED + scripts/config.py unset MBEDTLS_PLATFORM_NV_SEED_ALT scripts/config.py unset MBEDTLS_CTR_DRBG_C scripts/config.py unset MBEDTLS_HMAC_DRBG_C scripts/config.py unset MBEDTLS_ECDSA_DETERMINISTIC # requires HMAC_DRBG @@ -1034,6 +1037,9 @@ component_test_psa_external_rng_no_drbg_use_psa () { msg "build: PSA_CRYPTO_EXTERNAL_RNG minus *_DRBG, PSA crypto in TLS" scripts/config.py full scripts/config.py set MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG + scripts/config.py unset MBEDTLS_ENTROPY_C + scripts/config.py unset MBEDTLS_ENTROPY_NV_SEED + scripts/config.py unset MBEDTLS_PLATFORM_NV_SEED_ALT scripts/config.py unset MBEDTLS_CTR_DRBG_C scripts/config.py unset MBEDTLS_HMAC_DRBG_C scripts/config.py unset MBEDTLS_ECDSA_DETERMINISTIC # requires HMAC_DRBG From 8133abd746950a06b06af1f34366d75e66442801 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Mon, 8 Feb 2021 21:20:12 +0100 Subject: [PATCH 11/19] SSL test programs: always allow building with the PSA external RNG The SSL test programs can now use the PSA RNG, and the PSA RNG can use an external RNG. The build conditions hadn't been updated and didn't cover the case when MBEDTLS_TEST_USE_PSA_CRYPTO_RNG is enabled but MBEDTLS_USE_PSA_CRYPTO is disabled. Fix this. Signed-off-by: Gilles Peskine --- programs/ssl/ssl_test_lib.h | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/programs/ssl/ssl_test_lib.h b/programs/ssl/ssl_test_lib.h index d605a947b..04ba15874 100644 --- a/programs/ssl/ssl_test_lib.h +++ b/programs/ssl/ssl_test_lib.h @@ -43,23 +43,33 @@ #define MBEDTLS_EXIT_FAILURE EXIT_FAILURE #endif -#if !defined(MBEDTLS_ENTROPY_C) || \ - !defined(MBEDTLS_NET_C) || \ +#undef HAVE_RNG +#if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) && \ + ( defined(MBEDTLS_USE_PSA_CRYPTO) || \ + defined(MBEDTLS_TEST_USE_PSA_CRYPTO_RNG) ) +#define HAVE_RNG +#elif defined(MBEDTLS_ENTROPY_C) && defined(MBEDTLS_CTR_DRBG_C) +#define HAVE_RNG +#elif defined(MBEDTLS_ENTROPY_C) && defined(MBEDTLS_HMAC_DRBG_C) && \ + ( defined(MBEDTLS_SHA256_C) || defined(MBEDTLS_SHA512_C) ) +#define HAVE_RNG +#endif + +#if !defined(MBEDTLS_NET_C) || \ !defined(MBEDTLS_SSL_TLS_C) || \ defined(MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER) #define MBEDTLS_SSL_TEST_IMPOSSIBLE \ - "MBEDTLS_ENTROPY_C and/or " \ "MBEDTLS_NET_C and/or " \ "MBEDTLS_SSL_TLS_C not defined, " \ "and/or MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER defined.\n" -#elif !( defined(MBEDTLS_CTR_DRBG_C) || \ - defined(MBEDTLS_HMAC_DRBG_C) && ( defined(MBEDTLS_SHA256_C) || \ - defined(MBEDTLS_SHA512_C) ) ) -#define MBEDTLS_SSL_TEST_IMPOSSIBLE \ - "Neither MBEDTLS_CTR_DRBG_C, nor MBEDTLS_HMAC_DRBG_C and a supported hash defined.\n" +#elif !defined(HAVE_RNG) +#define MBEDTLS_SSL_TEST_IMPOSSIBLE \ + "No random generator is available.\n" #else #undef MBEDTLS_SSL_TEST_IMPOSSIBLE +#undef HAVE_RNG + #include #include #include @@ -76,7 +86,7 @@ #include "mbedtls/timing.h" #include "mbedtls/base64.h" -#if defined(MBEDTLS_USE_PSA_CRYPTO) +#if defined(MBEDTLS_USE_PSA_CRYPTO) || defined(MBEDTLS_TEST_USE_PSA_CRYPTO_RNG) #include "psa/crypto.h" #include "mbedtls/psa_util.h" #endif From 8e1e46ebb505e6973860839e4dee8e89f575ee1f Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Mon, 8 Feb 2021 22:02:12 +0100 Subject: [PATCH 12/19] Fix the use of unitialized memory with MBEDTLS_TEST_NULL_ENTROPY Signed-off-by: Gilles Peskine --- library/entropy_poll.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/entropy_poll.c b/library/entropy_poll.c index 5250a7bfe..27465f27d 100644 --- a/library/entropy_poll.c +++ b/library/entropy_poll.c @@ -205,13 +205,13 @@ int mbedtls_null_entropy_poll( void *data, { ((void) data); ((void) output); - *olen = 0; + *olen = 0; if( len < sizeof(unsigned char) ) return( 0 ); + output[0] = 0; *olen = sizeof(unsigned char); - return( 0 ); } #endif From ddeb8896ff6dff1ddf9c4e1b67c116c775f10695 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Mon, 8 Feb 2021 22:02:42 +0100 Subject: [PATCH 13/19] Exclude random_twice tests with MBEDTLS_TEST_NULL_ENTROPY Signed-off-by: Gilles Peskine --- tests/suites/test_suite_random.function | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/suites/test_suite_random.function b/tests/suites/test_suite_random.function index c532c8a3b..37fa36ecd 100644 --- a/tests/suites/test_suite_random.function +++ b/tests/suites/test_suite_random.function @@ -18,7 +18,7 @@ /* END_HEADER */ -/* BEGIN_CASE depends_on:MBEDTLS_ENTROPY_C:MBEDTLS_CTR_DRBG_C */ +/* BEGIN_CASE depends_on:MBEDTLS_ENTROPY_C:!MBEDTLS_TEST_NULL_ENTROPY:MBEDTLS_CTR_DRBG_C */ void random_twice_with_ctr_drbg( ) { mbedtls_entropy_context entropy; @@ -57,7 +57,7 @@ exit: } /* END_CASE */ -/* BEGIN_CASE depends_on:MBEDTLS_ENTROPY_C:MBEDTLS_HMAC_DRBG_C */ +/* BEGIN_CASE depends_on:MBEDTLS_ENTROPY_C:!MBEDTLS_TEST_NULL_ENTROPY:MBEDTLS_HMAC_DRBG_C */ void random_twice_with_hmac_drbg( int md_type ) { mbedtls_entropy_context entropy; @@ -97,7 +97,7 @@ exit: } /* END_CASE */ -/* BEGIN_CASE depends_on:MBEDTLS_PSA_CRYPTO_C:!MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ +/* BEGIN_CASE depends_on:MBEDTLS_PSA_CRYPTO_C:!MBEDTLS_TEST_NULL_ENTROPY:!MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ void random_twice_with_psa_from_classic( ) { unsigned char output1[OUTPUT_SIZE]; @@ -123,7 +123,7 @@ exit: } /* END_CASE */ -/* BEGIN_CASE depends_on:MBEDTLS_PSA_CRYPTO_C:!MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ +/* BEGIN_CASE depends_on:MBEDTLS_PSA_CRYPTO_C:!MBEDTLS_TEST_NULL_ENTROPY:!MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ void random_twice_with_psa_from_psa( ) { unsigned char output1[OUTPUT_SIZE]; From 48113ebb6255995f21c926ed520011071af689f3 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Tue, 9 Feb 2021 10:25:20 +0100 Subject: [PATCH 14/19] Initialize the test RNG whenever it's present It's no longer restricted to MBEDTLS_USE_PSA_CRYPTO. Signed-off-by: Gilles Peskine --- programs/ssl/ssl_client2.c | 2 +- programs/ssl/ssl_server2.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c index 7d904d128..4875b785c 100644 --- a/programs/ssl/ssl_client2.c +++ b/programs/ssl/ssl_client2.c @@ -760,10 +760,10 @@ int main( int argc, char *argv[] ) ret = MBEDTLS_ERR_SSL_HW_ACCEL_FAILED; goto exit; } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ #if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) mbedtls_test_enable_insecure_external_rng( ); #endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ -#endif /* MBEDTLS_USE_PSA_CRYPTO */ if( argc == 0 ) { diff --git a/programs/ssl/ssl_server2.c b/programs/ssl/ssl_server2.c index 0bbf018b0..08317b5b0 100644 --- a/programs/ssl/ssl_server2.c +++ b/programs/ssl/ssl_server2.c @@ -1412,10 +1412,10 @@ int main( int argc, char *argv[] ) ret = MBEDTLS_ERR_SSL_HW_ACCEL_FAILED; goto exit; } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ #if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) mbedtls_test_enable_insecure_external_rng( ); #endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ -#endif /* MBEDTLS_USE_PSA_CRYPTO */ #if !defined(_WIN32) /* Abort cleanly on SIGTERM and SIGINT */ From d548d964db22480dd7a00c64fadc0736297da70e Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Mon, 15 Feb 2021 18:34:16 +0100 Subject: [PATCH 15/19] Clarify where mbedtls_psa_get_random might be useful Also fix some typos. Signed-off-by: Gilles Peskine --- ChangeLog.d/mbedtls_psa_get_random.txt | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/ChangeLog.d/mbedtls_psa_get_random.txt b/ChangeLog.d/mbedtls_psa_get_random.txt index 9abbfff78..f6e6b0966 100644 --- a/ChangeLog.d/mbedtls_psa_get_random.txt +++ b/ChangeLog.d/mbedtls_psa_get_random.txt @@ -2,7 +2,8 @@ Features * Partial implementation of the PSA crypto driver interface: Mbed TLS can now use an external random generator instead of the library's own entropy collection and DRBG code. Enable MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG - and See the documentatio of mbedtls_psa_external_get_random() for details. - * Applications using PSA crypto can now use its random generator in the - mbedtls_xxx API. See the documentation of mbedtls_psa_get_random() for - details. + and see the documentation of mbedtls_psa_external_get_random() for details. + * Applications using both mbedtls_xxx and psa_xxx functions (for example, + applications using TLS and MBEDTLS_USE_PSA_CRYPTO) can now use the PSA + random generator with mbedtls_xxx functions. See the documentation of + mbedtls_psa_get_random() for details. From cd2d648b002cd857396d737b1e841aa904c13055 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Tue, 16 Feb 2021 15:33:56 +0100 Subject: [PATCH 16/19] Explain the "external RNG large" test case Signed-off-by: Gilles Peskine --- tests/suites/test_suite_random.data | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/suites/test_suite_random.data b/tests/suites/test_suite_random.data index d781f2ba5..c23d9223f 100644 --- a/tests/suites/test_suite_random.data +++ b/tests/suites/test_suite_random.data @@ -34,6 +34,10 @@ mbedtls_psa_get_random_length:1 PSA classic wrapper: 256 bytes mbedtls_psa_get_random_length:256 +# An external RNG is supposed to handle arbitrary request lengths. Test it +# with something larger than any RNG call made by Mbed TLS itself expects. +# CTR_DRBG and HMAC_DRBG have their own maximum request lengths which may +# be lower than the value chosen here and are tested separately. PSA classic wrapper: external RNG large depends_on:MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG mbedtls_psa_get_random_length:1024 From 2cff7e2a596e3a17a4bc7c91b32745553f729421 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Tue, 16 Feb 2021 16:49:42 +0100 Subject: [PATCH 17/19] Minor clarification in the public documentation Signed-off-by: Gilles Peskine --- include/mbedtls/psa_util.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/include/mbedtls/psa_util.h b/include/mbedtls/psa_util.h index b4814012e..95153d0ae 100644 --- a/include/mbedtls/psa_util.h +++ b/include/mbedtls/psa_util.h @@ -437,12 +437,12 @@ typedef int mbedtls_f_rng_t( void *p_rng, unsigned char *output, size_t output_s /** The random generator function for the PSA subsystem. * * This function is suitable as the `f_rng` random generator function - * parameter of many `mbedtls_xxx` functions. It must be used in combination - * with the random generator state #MBEDTLS_PSA_RANDOM_STATE. + * parameter of many `mbedtls_xxx` functions. Use #MBEDTLS_PSA_RANDOM_STATE + * to obtain the \p p_rng parameter. * * The implementation of this function depends on the configuration of the * library. - + * * \note Depending on the configuration, this may be a function or * a pointer to a function. * @@ -465,6 +465,7 @@ typedef int mbedtls_f_rng_t( void *p_rng, unsigned char *output, size_t output_s * * \return \c 0 on success. * \return An `MBEDTLS_ERR_ENTROPY_xxx`, + * `MBEDTLS_ERR_PLATFORM_xxx, * `MBEDTLS_ERR_CTR_DRBG_xxx` or * `MBEDTLS_ERR_HMAC_DRBG_xxx` on error. */ From 996f2168b635229838ff7597be3a4ffdf051306f Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Tue, 16 Feb 2021 16:50:00 +0100 Subject: [PATCH 18/19] Make it possible to include psa_crypto_random_impl.h with psa_util.h There was some intentional duplication between library/psa_crypto_random_impl.h and include/mbedtls/psa_util.h, with the intent that the compiler would complain if one file was edited in a way that's incompatible with the other file. However, the two files were never included together, and in fact could not be included together because some definitions can't be duplicated (type, static variable). Now library/psa_crypto_random_impl.h includes include/mbedtls/psa_util.h, so the compiler will check what it can. There is less redundancy since it isn't always possible to declare something twice (specifically, types can't be declared). Signed-off-by: Gilles Peskine --- include/mbedtls/psa_util.h | 5 ++-- library/psa_crypto_random_impl.h | 51 +++++++++----------------------- 2 files changed, 17 insertions(+), 39 deletions(-) diff --git a/include/mbedtls/psa_util.h b/include/mbedtls/psa_util.h index 95153d0ae..4fa804d21 100644 --- a/include/mbedtls/psa_util.h +++ b/include/mbedtls/psa_util.h @@ -420,8 +420,9 @@ static inline int mbedtls_psa_tls_ecpoint_to_psa_ec( unsigned char const *src, #endif /* MBEDTLS_USE_PSA_CRYPTO */ /* Expose whatever RNG the PSA subsystem uses to applications using the - * mbedtls_xxx API. The declarations here need to be consistent with the - * implementation in library/psa_crypto_random_impl.h. */ + * mbedtls_xxx API. The declarations and definitions here need to be + * consistent with the implementation in library/psa_crypto_random_impl.h. + * See that file for implementation documentation. */ #if defined(MBEDTLS_PSA_CRYPTO_C) /* The type of a `f_rng` random generator function that many library functions diff --git a/library/psa_crypto_random_impl.h b/library/psa_crypto_random_impl.h index 4fa54a9fa..3b8e3ec9b 100644 --- a/library/psa_crypto_random_impl.h +++ b/library/psa_crypto_random_impl.h @@ -3,7 +3,12 @@ * \brief PSA crypto random generator implementation abstraction. * * The definitions here need to be consistent with the declarations - * in include/mbedtls/psa_util.h. + * in include/mbedtls/psa_util.h. This file contains some redundant + * declarations to increase the chance that a compiler will detect + * inconsistencies if one file is changed without updating the other, + * but not all potential inconsistencies can be enforced, so make sure + * to check the public declarations and contracts in + * include/mbedtls/psa_util.h if you modify this file. */ /* * Copyright The Mbed TLS Contributors @@ -25,6 +30,8 @@ #ifndef PSA_CRYPTO_RANDOM_IMPL_H #define PSA_CRYPTO_RANDOM_IMPL_H +#include + #if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) #include @@ -78,14 +85,6 @@ int mbedtls_psa_get_random( void *p_rng, #include "mbedtls/entropy.h" -/** The type of the PSA DRBG context. - */ -#if defined(MBEDTLS_CTR_DRBG_C) -typedef mbedtls_ctr_drbg_context mbedtls_psa_drbg_context_t; -#elif defined(MBEDTLS_HMAC_DRBG_C) -typedef mbedtls_hmac_drbg_context mbedtls_psa_drbg_context_t; -#endif - /** Initialize the PSA DRBG. * * \param p_rng Pointer to the Mbed TLS DRBG state. @@ -125,34 +124,9 @@ typedef struct mbedtls_psa_drbg_context_t drbg; } mbedtls_psa_random_context_t; -/* The type of an Mbed TLS random generator function. This should be - * part of the public API instead of repeating the type everywhere. - * For the time being, declare it here. Declaring a type is necessary - * to define mbedtls_psa_get_random as a variable of a function pointer - * type without incurring the wrath of check-names.sh. */ -typedef int mbedtls_f_rng_t( void *p_rng, unsigned char *output, size_t output_size ); - -/** Return random data. - * - * This function is suitable as the \p f_rng parameter to Mbed TLS functions - * that require a random generator. Use #MBEDTLS_PSA_RANDOM_STATE to - * obtain the \p p_rng parameter. - * - * \param p_rng The DRBG context. This must be - * #MBEDTLS_PSA_RANDOM_STATE. - * \param output The buffer to fill. - * \param output_len The length of the buffer in bytes. - * It must be at most #MBEDTLS_PSA_RANDOM_MAX_REQUEST. - * - * \retval \c 0 on success. - * \return \c MBEDTLS_ERR_xxx_DRBG_xxx or - * \c MBEDTLS_ERR_PLATFORM_xxx on failure. - */ -#if defined(MBEDTLS_CTR_DRBG_C) -static mbedtls_f_rng_t *const mbedtls_psa_get_random = mbedtls_ctr_drbg_random; -#elif defined(MBEDTLS_HMAC_DRBG_C) -static mbedtls_f_rng_t *const mbedtls_psa_get_random = mbedtls_hmac_drbg_random; -#endif +/* Defined in include/mbedtls/psa_util.h so that it's visible to + * application code. */ +static mbedtls_f_rng_t *const mbedtls_psa_get_random; /** The maximum number of bytes that mbedtls_psa_get_random() is expected to * return. @@ -170,6 +144,9 @@ static mbedtls_f_rng_t *const mbedtls_psa_get_random = mbedtls_hmac_drbg_random; */ /* psa_crypto.c sets this variable to a pointer to the DRBG state in the * global PSA crypto state. */ +/* The type `mbedtls_psa_drbg_context_t` is defined in + * include/mbedtls/psa_util.h so that `mbedtls_psa_random_state` can be + * declared there and be visible to application code. */ extern mbedtls_psa_drbg_context_t *const mbedtls_psa_random_state; /** A pointer to the PSA DRBG state. From 277a3a6609bf800e0b1329c012d66524d4d14c91 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Tue, 16 Feb 2021 18:55:05 +0100 Subject: [PATCH 19/19] Work around MSVC bug with duplicate static declarations Signed-off-by: Gilles Peskine --- library/psa_crypto_random_impl.h | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/library/psa_crypto_random_impl.h b/library/psa_crypto_random_impl.h index 3b8e3ec9b..3c4c09a28 100644 --- a/library/psa_crypto_random_impl.h +++ b/library/psa_crypto_random_impl.h @@ -125,8 +125,18 @@ typedef struct } mbedtls_psa_random_context_t; /* Defined in include/mbedtls/psa_util.h so that it's visible to - * application code. */ + * application code. The declaration here is redundant, but included + * as a safety net to make it more likely that a future change that + * accidentally causes the implementation to diverge from the interface + * will be noticed. */ +/* Do not include the declaration under MSVC because it doesn't accept it + * ("error C2370: 'mbedtls_psa_get_random' : redefinition; different storage class"). + * Observed with Visual Studio 2013. A known bug apparently: + * https://stackoverflow.com/questions/8146541/duplicate-external-static-declarations-not-allowed-in-visual-studio + */ +#if !defined(_MSC_VER) static mbedtls_f_rng_t *const mbedtls_psa_get_random; +#endif /** The maximum number of bytes that mbedtls_psa_get_random() is expected to * return.