From e3dbdd8d908218c7b7c3c3a62babb658c5c8a2a4 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Mon, 25 Feb 2019 11:04:06 +0100 Subject: [PATCH] Gate entropy injection through a dedicated configuration option Entropy injection has specific testing requirements. Therefore it should depend on a specific option. --- configs/config-psa-crypto.h | 15 +++++++- include/mbedtls/check_config.h | 11 ++++++ include/mbedtls/config.h | 13 +++++++ include/psa/crypto_extra.h | 7 ++-- library/psa_crypto.c | 23 +++--------- library/psa_crypto_storage.c | 22 +++++++++++ library/psa_crypto_storage.h | 16 ++++++++ library/version_features.c | 3 ++ programs/test/query_config.c | 8 ++++ scripts/config.pl | 1 + .../test_suite_psa_crypto_entropy.function | 37 +++++++++++++++---- 11 files changed, 125 insertions(+), 31 deletions(-) diff --git a/configs/config-psa-crypto.h b/configs/config-psa-crypto.h index 7f7c0cf04..4873c3624 100644 --- a/configs/config-psa-crypto.h +++ b/configs/config-psa-crypto.h @@ -1231,6 +1231,19 @@ */ //#define MBEDTLS_PSA_CRYPTO_SPM +/** + * \def MBEDTLS_PSA_INJECT_ENTROPY + * + * Enable support for entropy injection at first boot. This feature is + * required on systems that do not have a built-in entropy source (TRNG). + * This feature is currently not supported on systems that have a built-in + * entropy source. + * + * Requires: MBEDTLS_PSA_CRYPTO_STORAGE_C, MBEDTLS_ENTROPY_NV_SEED + * + */ +//#define MBEDTLS_PSA_INJECT_ENTROPY + /** * \def MBEDTLS_RSA_NO_CRT * @@ -2715,7 +2728,7 @@ * * Requires: MBEDTLS_FS_IO */ -//#define MBEDTLS_PSA_ITS_FILE_C +#define MBEDTLS_PSA_ITS_FILE_C /** * \def MBEDTLS_RIPEMD160_C diff --git a/include/mbedtls/check_config.h b/include/mbedtls/check_config.h index 607deb96f..c1450dbda 100644 --- a/include/mbedtls/check_config.h +++ b/include/mbedtls/check_config.h @@ -530,6 +530,17 @@ #error "MBEDTLS_PSA_CRYPTO_STORAGE_C defined, but not all prerequisites" #endif +#if defined(MBEDTLS_PSA_INJECT_ENTROPY) && \ + !( defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) && \ + defined(MBEDTLS_ENTROPY_NV_SEED) ) +#error "MBEDTLS_PSA_INJECT_ENTROPY defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PSA_INJECT_ENTROPY) && \ + !defined(MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES) +#error "MBEDTLS_PSA_INJECT_ENTROPY is not compatible with actual entropy sources" +#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/include/mbedtls/config.h b/include/mbedtls/config.h index a358a20c4..5621965f2 100644 --- a/include/mbedtls/config.h +++ b/include/mbedtls/config.h @@ -1251,6 +1251,19 @@ */ //#define MBEDTLS_PSA_CRYPTO_SPM +/** + * \def MBEDTLS_PSA_INJECT_ENTROPY + * + * Enable support for entropy injection at first boot. This feature is + * required on systems that do not have a built-in entropy source (TRNG). + * This feature is currently not supported on systems that have a built-in + * entropy source. + * + * Requires: MBEDTLS_PSA_CRYPTO_STORAGE_C, MBEDTLS_ENTROPY_NV_SEED + * + */ +//#define MBEDTLS_PSA_INJECT_ENTROPY + /** * \def MBEDTLS_RSA_NO_CRT * diff --git a/include/psa/crypto_extra.h b/include/psa/crypto_extra.h index 545dd4bcd..c89c55df3 100644 --- a/include/psa/crypto_extra.h +++ b/include/psa/crypto_extra.h @@ -114,10 +114,9 @@ void mbedtls_psa_crypto_free( void ); * This is an Mbed TLS extension. * * \note This function is only available on the following platforms: - * * If the compile-time options MBEDTLS_ENTROPY_NV_SEED and - * MBEDTLS_PSA_CRYPTO_STORAGE_C are both enabled. Note that you - * must provide compatible implementations of mbedtls_nv_seed_read - * and mbedtls_nv_seed_write. + * * If the compile-time option MBEDTLS_PSA_INJECT_ENTROPY is enabled. + * Note that you must provide compatible implementations of + * mbedtls_nv_seed_read and mbedtls_nv_seed_write. * * In a client-server integration of PSA Cryptography, on the client side, * if the server supports this feature. * \param[in] seed Buffer containing the seed value to inject. diff --git a/library/psa_crypto.c b/library/psa_crypto.c index 1b554b5b0..3b9c78ffc 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -60,7 +60,6 @@ #include "mbedtls/ecdh.h" #include "mbedtls/ecp.h" #include "mbedtls/entropy.h" -#include "mbedtls/entropy_poll.h" #include "mbedtls/error.h" #include "mbedtls/gcm.h" #include "mbedtls/md2.h" @@ -4419,13 +4418,12 @@ psa_status_t psa_generate_random( uint8_t *output, return( mbedtls_to_psa_error( ret ) ); } -#if defined(MBEDTLS_ENTROPY_NV_SEED) && \ - defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) +#if defined(MBEDTLS_PSA_INJECT_ENTROPY) +#include "mbedtls/entropy_poll.h" + psa_status_t mbedtls_psa_inject_entropy( const unsigned char *seed, size_t seed_size ) { - psa_status_t status; - struct psa_storage_info_t p_info; if( global_data.initialized ) return( PSA_ERROR_NOT_PERMITTED ); @@ -4434,20 +4432,9 @@ psa_status_t mbedtls_psa_inject_entropy( const unsigned char *seed, ( seed_size > MBEDTLS_ENTROPY_MAX_SEED_SIZE ) ) return( PSA_ERROR_INVALID_ARGUMENT ); - status = psa_its_get_info( PSA_CRYPTO_ITS_RANDOM_SEED_UID, &p_info ); - - if( PSA_ERROR_DOES_NOT_EXIST == status ) /* No seed exists */ - { - status = psa_its_set( PSA_CRYPTO_ITS_RANDOM_SEED_UID, seed_size, seed, 0 ); - } - else if( PSA_SUCCESS == status ) - { - /* You should not be here. Seed needs to be injected only once */ - status = PSA_ERROR_NOT_PERMITTED; - } - return( status ); + return( mbedtls_psa_storage_inject_entropy( seed, seed_size ) ); } -#endif +#endif /* MBEDTLS_PSA_INJECT_ENTROPY */ psa_status_t psa_generate_key( psa_key_handle_t handle, psa_key_type_t type, diff --git a/library/psa_crypto_storage.c b/library/psa_crypto_storage.c index bda9c0ce8..6c2e86573 100644 --- a/library/psa_crypto_storage.c +++ b/library/psa_crypto_storage.c @@ -391,4 +391,26 @@ exit: return( status ); } +#if defined(MBEDTLS_PSA_INJECT_ENTROPY) +psa_status_t mbedtls_psa_storage_inject_entropy( const unsigned char *seed, + size_t seed_size ) +{ + psa_status_t status; + struct psa_storage_info_t p_info; + + status = psa_its_get_info( PSA_CRYPTO_ITS_RANDOM_SEED_UID, &p_info ); + + if( PSA_ERROR_DOES_NOT_EXIST == status ) /* No seed exists */ + { + status = psa_its_set( PSA_CRYPTO_ITS_RANDOM_SEED_UID, seed_size, seed, 0 ); + } + else if( PSA_SUCCESS == status ) + { + /* You should not be here. Seed needs to be injected only once */ + status = PSA_ERROR_NOT_PERMITTED; + } + return( status ); +} +#endif /* MBEDTLS_PSA_INJECT_ENTROPY */ + #endif /* MBEDTLS_PSA_CRYPTO_STORAGE_C */ diff --git a/library/psa_crypto_storage.h b/library/psa_crypto_storage.h index 902e3026b..5434d0529 100644 --- a/library/psa_crypto_storage.h +++ b/library/psa_crypto_storage.h @@ -203,6 +203,22 @@ psa_status_t psa_parse_key_data_from_storage( const uint8_t *storage_data, psa_key_type_t *type, psa_key_policy_t *policy ); +#if defined(MBEDTLS_PSA_INJECT_ENTROPY) +/** Backend side of mbedtls_psa_inject_entropy(). + * + * This function stores the supplied data into the entropy seed file. + * + * \retval #PSA_SUCCESS + * Success + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_INSUFFICIENT_STORAGE + * \retval #PSA_ERROR_NOT_PERMITTED + * The entropy seed file already exists. + */ +psa_status_t mbedtls_psa_storage_inject_entropy( const unsigned char *seed, + size_t seed_size ); +#endif /* MBEDTLS_PSA_INJECT_ENTROPY */ + #ifdef __cplusplus } #endif diff --git a/library/version_features.c b/library/version_features.c index 92b1af10b..00fd2e90d 100644 --- a/library/version_features.c +++ b/library/version_features.c @@ -432,6 +432,9 @@ static const char *features[] = { #if defined(MBEDTLS_PSA_CRYPTO_SPM) "MBEDTLS_PSA_CRYPTO_SPM", #endif /* MBEDTLS_PSA_CRYPTO_SPM */ +#if defined(MBEDTLS_PSA_INJECT_ENTROPY) + "MBEDTLS_PSA_INJECT_ENTROPY", +#endif /* MBEDTLS_PSA_INJECT_ENTROPY */ #if defined(MBEDTLS_RSA_NO_CRT) "MBEDTLS_RSA_NO_CRT", #endif /* MBEDTLS_RSA_NO_CRT */ diff --git a/programs/test/query_config.c b/programs/test/query_config.c index 52db0b2fc..d940b0d17 100644 --- a/programs/test/query_config.c +++ b/programs/test/query_config.c @@ -1194,6 +1194,14 @@ int query_config( const char *config ) } #endif /* MBEDTLS_PSA_CRYPTO_SPM */ +#if defined(MBEDTLS_PSA_INJECT_ENTROPY) + if( strcmp( "MBEDTLS_PSA_INJECT_ENTROPY", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_PSA_INJECT_ENTROPY ); + return( 0 ); + } +#endif /* MBEDTLS_PSA_INJECT_ENTROPY */ + #if defined(MBEDTLS_RSA_NO_CRT) if( strcmp( "MBEDTLS_RSA_NO_CRT", config ) == 0 ) { diff --git a/scripts/config.pl b/scripts/config.pl index fc71f655d..6927c4b40 100755 --- a/scripts/config.pl +++ b/scripts/config.pl @@ -102,6 +102,7 @@ MBEDTLS_NO_UDBL_DIVISION MBEDTLS_NO_64BIT_MULTIPLICATION MBEDTLS_PSA_CRYPTO_SPM MBEDTLS_PSA_CRYPTO_KEY_FILE_ID_ENCODES_OWNER +MBEDTLS_PSA_INJECT_ENTROPY MBEDTLS_USE_PSA_CRYPTO _ALT\s*$ ); diff --git a/tests/suites/test_suite_psa_crypto_entropy.function b/tests/suites/test_suite_psa_crypto_entropy.function index 76a7b5870..91e210e0e 100644 --- a/tests/suites/test_suite_psa_crypto_entropy.function +++ b/tests/suites/test_suite_psa_crypto_entropy.function @@ -2,17 +2,38 @@ #include #include "psa/crypto.h" -#include "psa_prot_internal_storage.h" #include "mbedtls/entropy.h" #include "mbedtls/entropy_poll.h" +#if defined(MBEDTLS_PSA_ITS_FILE_C) +#include +#else +#include +#endif + /* Calculating the minimum allowed entropy size in bytes */ #define MBEDTLS_PSA_INJECT_ENTROPY_MIN_SIZE MAX(MBEDTLS_ENTROPY_MIN_PLATFORM, MBEDTLS_ENTROPY_BLOCK_SIZE) +/* Remove the entropy seed file. Since the library does not expose a way + * to do this (it would be a security risk if such a function was ever + * accessible in production), implement this functionality in a white-box + * manner. */ +psa_status_t remove_seed_file( void ) +{ +#if defined(MBEDTLS_PSA_ITS_FILE_C) + if( remove( "00000000ffffff52.psa_its" ) == 0 ) + return( PSA_SUCCESS ); + else + return( PSA_ERROR_DOES_NOT_EXIST ); +#else + return( psa_its_remove( PSA_CRYPTO_ITS_RANDOM_SEED_UID ) ); +#endif +} + /* END_HEADER */ /* BEGIN_DEPENDENCIES - * depends_on:MBEDTLS_ENTROPY_NV_SEED:MBEDTLS_PSA_CRYPTO_STORAGE_C + * depends_on:MBEDTLS_PSA_INJECT_ENTROPY * END_DEPENDENCIES */ @@ -42,7 +63,7 @@ void validate_entropy_seed_injection( int seed_length_a, { seed[i] = i; } - status = psa_its_remove( PSA_CRYPTO_ITS_RANDOM_SEED_UID ); + status = remove_seed_file( ); TEST_ASSERT( ( status == PSA_SUCCESS ) || ( status == PSA_ERROR_DOES_NOT_EXIST ) ); status = mbedtls_psa_inject_entropy( seed, seed_length_a ); @@ -55,7 +76,7 @@ void validate_entropy_seed_injection( int seed_length_a, TEST_ASSERT( memcmp( output, zeros, sizeof( output ) ) != 0 ); exit: mbedtls_free( seed ); - psa_its_remove( PSA_CRYPTO_ITS_RANDOM_SEED_UID ); + remove_seed_file( ); mbedtls_psa_crypto_free( ); } /* END_CASE */ @@ -64,19 +85,19 @@ exit: void run_entropy_inject_with_crypto_init( ) { psa_status_t status; - int i; + size_t i; uint8_t seed[MBEDTLS_PSA_INJECT_ENTROPY_MIN_SIZE] = { 0 }; /* fill seed with some data */ for( i = 0; i < sizeof( seed ); ++i ) { seed[i] = i; } - status = psa_its_remove( PSA_CRYPTO_ITS_RANDOM_SEED_UID ); + status = remove_seed_file( ); TEST_ASSERT( ( status == PSA_SUCCESS ) || ( status == PSA_ERROR_DOES_NOT_EXIST ) ); status = mbedtls_psa_inject_entropy( seed, sizeof( seed ) ); PSA_ASSERT( status ); - status = psa_its_remove( PSA_CRYPTO_ITS_RANDOM_SEED_UID ); + status = remove_seed_file( ); TEST_EQUAL( status, PSA_SUCCESS ); status = psa_crypto_init( ); TEST_EQUAL( status, PSA_ERROR_INSUFFICIENT_ENTROPY ); @@ -89,7 +110,7 @@ void run_entropy_inject_with_crypto_init( ) status = mbedtls_psa_inject_entropy( seed, sizeof( seed ) ); TEST_EQUAL( status, PSA_ERROR_NOT_PERMITTED ); exit: - psa_its_remove( PSA_CRYPTO_ITS_RANDOM_SEED_UID ); + remove_seed_file( ); mbedtls_psa_crypto_free( ); } /* END_CASE */