From 4fc21fdeb6ecff1165b1a7e77cea5676b8058ee0 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Fri, 13 Nov 2020 18:47:18 +0100 Subject: [PATCH] Implement MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG Implement support for MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG. For test purposes, write an implementation that uses libc rand(). Signed-off-by: Gilles Peskine --- include/mbedtls/check_config.h | 5 +++ library/psa_crypto.c | 37 ++++++++++++++++++- library/psa_crypto_invasive.h | 2 + library/psa_crypto_random.h | 30 +++++++++++++++ tests/src/psa_crypto_helpers.c | 16 ++++++++ .../test_suite_psa_crypto_init.function | 12 ++++-- 6 files changed, 97 insertions(+), 5 deletions(-) diff --git a/include/mbedtls/check_config.h b/include/mbedtls/check_config.h index 91aaf80dc..949727994 100644 --- a/include/mbedtls/check_config.h +++ b/include/mbedtls/check_config.h @@ -605,6 +605,11 @@ #error "MBEDTLS_PSA_INJECT_ENTROPY is not compatible with actual entropy sources" #endif +#if defined(MBEDTLS_PSA_INJECT_ENTROPY) && \ + !defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) +#error "MBEDTLS_PSA_INJECT_ENTROPY is not compatible with MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG" +#endif + #if defined(MBEDTLS_PSA_ITS_FILE_C) && \ !defined(MBEDTLS_FS_IO) #error "MBEDTLS_PSA_ITS_FILE_C defined, but not all prerequisites" diff --git a/library/psa_crypto.c b/library/psa_crypto.c index a32ce94e4..410d6a191 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -6297,6 +6297,10 @@ exit: */ static void mbedtls_psa_random_init( mbedtls_psa_random_context_t *rng ) { +#if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) + memset( rng, 0, sizeof( *rng ) ); +#else /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ + /* Set default configuration if * mbedtls_psa_crypto_configure_entropy_sources() hasn't been called. */ if( rng->entropy_init == NULL ) @@ -6316,31 +6320,59 @@ static void mbedtls_psa_random_init( mbedtls_psa_random_context_t *rng ) #endif mbedtls_psa_drbg_init( mbedtls_psa_random_state( rng ) ); +#endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ } /** Deinitialize the PSA random generator. */ static void mbedtls_psa_random_free( mbedtls_psa_random_context_t *rng ) { +#if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) + memset( rng, 0, sizeof( *rng ) ); +#else /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ mbedtls_psa_drbg_free( mbedtls_psa_random_state( rng ) ); rng->entropy_free( &rng->entropy ); +#endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ } /** Seed the PSA random generator. */ static psa_status_t mbedtls_psa_random_seed( mbedtls_psa_random_context_t *rng ) { +#if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) + /* Do nothing: the external RNG seeds itself. */ + (void) rng; + return( PSA_SUCCESS ); +#else /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ const unsigned char drbg_seed[] = "PSA"; int ret = mbedtls_psa_drbg_seed( rng, drbg_seed, sizeof( drbg_seed ) - 1 ); return mbedtls_to_psa_error( ret ); +#endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ } psa_status_t psa_generate_random( uint8_t *output, size_t output_size ) { - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; GUARD_MODULE_INITIALIZED; +#if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) + + size_t output_length = 0; + psa_status_t status = mbedtls_psa_external_get_random( &global_data.rng, + output, output_size, + &output_length ); + if( status != PSA_SUCCESS ) + return( status ); + /* Breaking up a request into smaller chunks is currently not supported + * for the extrernal RNG interface. */ + if( output_length != output_size ) + return( PSA_ERROR_INSUFFICIENT_ENTROPY ); + return( PSA_SUCCESS ); + +#else /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ + + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + while( output_size > MBEDTLS_PSA_RANDOM_MAX_REQUEST ) { ret = mbedtls_psa_get_random( @@ -6355,6 +6387,7 @@ psa_status_t psa_generate_random( uint8_t *output, ret = mbedtls_psa_get_random( mbedtls_psa_random_state( &global_data.rng ), output, output_size ); return( mbedtls_to_psa_error( ret ) ); +#endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ } #if defined(MBEDTLS_PSA_INJECT_ENTROPY) @@ -6586,6 +6619,7 @@ exit: /* Module setup */ /****************************************************************/ +#if !defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) psa_status_t mbedtls_psa_crypto_configure_entropy_sources( void (* entropy_init )( mbedtls_entropy_context *ctx ), void (* entropy_free )( mbedtls_entropy_context *ctx ) ) @@ -6596,6 +6630,7 @@ psa_status_t mbedtls_psa_crypto_configure_entropy_sources( global_data.rng.entropy_free = entropy_free; return( PSA_SUCCESS ); } +#endif /* !defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) */ void mbedtls_psa_crypto_free( void ) { diff --git a/library/psa_crypto_invasive.h b/library/psa_crypto_invasive.h index 2b4ee1f34..be127d9f8 100644 --- a/library/psa_crypto_invasive.h +++ b/library/psa_crypto_invasive.h @@ -38,6 +38,7 @@ #include "mbedtls/entropy.h" +#if !defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) /** \brief Configure entropy sources. * * This function may only be called before a call to psa_crypto_init(), @@ -73,5 +74,6 @@ psa_status_t mbedtls_psa_crypto_configure_entropy_sources( void (* entropy_init )( mbedtls_entropy_context *ctx ), void (* entropy_free )( mbedtls_entropy_context *ctx ) ); +#endif /* !defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) */ #endif /* PSA_CRYPTO_INVASIVE_H */ diff --git a/library/psa_crypto_random.h b/library/psa_crypto_random.h index 95974d93e..2e7f94d4c 100644 --- a/library/psa_crypto_random.h +++ b/library/psa_crypto_random.h @@ -22,6 +22,34 @@ #ifndef PSA_CRYPTO_RANDOM_H #define PSA_CRYPTO_RANDOM_H +#if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) + +#include +#include // only for error codes +#include + +typedef mbedtls_psa_external_random_context_t mbedtls_psa_random_context_t; + +static inline int mbedtls_psa_get_random( void *p_rng, + unsigned char *output, + size_t output_size ) +{ + (void) p_rng; + psa_status_t status = psa_generate_random( output, output_size ); + if( status == PSA_SUCCESS ) + return( 0 ); + else + return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); +} + +static inline void *mbedtls_psa_random_state( mbedtls_psa_random_context_t *rng ) +{ + (void) rng; + return( NULL ); +} + +#else /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ + /* Currently, the only supported RNG is Mbed TLS's CTR_DRBG seeded with * mbedtls_entropy_func(). */ @@ -127,4 +155,6 @@ static inline int mbedtls_psa_drbg_seed( custom, len ) ); } +#endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ + #endif /* PSA_CRYPTO_RANDOM_H */ diff --git a/tests/src/psa_crypto_helpers.c b/tests/src/psa_crypto_helpers.c index 40877c7f7..dacda683a 100644 --- a/tests/src/psa_crypto_helpers.c +++ b/tests/src/psa_crypto_helpers.c @@ -27,4 +27,20 @@ #include +#if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) +#include + +psa_status_t mbedtls_psa_external_get_random( + mbedtls_psa_external_random_context_t *context, + uint8_t *output, size_t output_size, size_t *output_length ) +{ + /* This implementation is for test purposes only! + * Use the libc non-cryptographic random generator. */ + (void) context; + mbedtls_test_rnd_std_rand( NULL, output, output_size ); + *output_length = output_size; + return( PSA_SUCCESS ); +} +#endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ + #endif /* MBEDTLS_PSA_CRYPTO_C */ diff --git a/tests/suites/test_suite_psa_crypto_init.function b/tests/suites/test_suite_psa_crypto_init.function index 62ef6e2d7..867e4236c 100644 --- a/tests/suites/test_suite_psa_crypto_init.function +++ b/tests/suites/test_suite_psa_crypto_init.function @@ -17,6 +17,8 @@ #include "mbedtls/ctr_drbg.h" #define ENTROPY_NONCE_LEN MBEDTLS_CTR_DRBG_ENTROPY_NONCE_LEN +#if !defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) + typedef struct { size_t threshold; /* Minimum bytes to make mbedtls_entropy_func happy */ @@ -118,6 +120,8 @@ static void custom_entropy_init( mbedtls_entropy_context *ctx ) MBEDTLS_ENTROPY_SOURCE_STRONG ); } +#endif /* !defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) */ + /* END_HEADER */ /* BEGIN_DEPENDENCIES @@ -125,7 +129,7 @@ static void custom_entropy_init( mbedtls_entropy_context *ctx ) * END_DEPENDENCIES */ -/* BEGIN_CASE depends_on:MBEDTLS_ENTROPY_NV_SEED */ +/* BEGIN_CASE depends_on:MBEDTLS_ENTROPY_NV_SEED:!MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ void create_nv_seed( ) { static unsigned char seed[ENTROPY_MIN_NV_SEED_SIZE]; @@ -201,7 +205,7 @@ void validate_module_init_key_based( int count ) } /* END_CASE */ -/* BEGIN_CASE */ +/* BEGIN_CASE depends_on:!MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ void custom_entropy_sources( int sources_arg, int expected_init_status_arg ) { psa_status_t expected_init_status = expected_init_status_arg; @@ -222,7 +226,7 @@ exit: } /* END_CASE */ -/* BEGIN_CASE */ +/* BEGIN_CASE depends_on:!MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ void fake_entropy_source( int threshold, int amount1, int amount2, @@ -262,7 +266,7 @@ exit: } /* END_CASE */ -/* BEGIN_CASE depends_on:MBEDTLS_ENTROPY_NV_SEED */ +/* BEGIN_CASE depends_on:MBEDTLS_ENTROPY_NV_SEED:!MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ void entropy_from_nv_seed( int seed_size_arg, int expected_init_status_arg ) {