From 9a9d5eea5382befa06a939de5f1718f46d6ce532 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Fri, 28 Apr 2023 21:00:28 +0200 Subject: [PATCH 01/11] Fix a build error when MBEDTLS_PSA_INJECT_ENTROPY is enabled Signed-off-by: Gilles Peskine --- ChangeLog.d/inject-entropy.txt | 2 ++ library/psa_crypto.c | 6 ++++-- 2 files changed, 6 insertions(+), 2 deletions(-) create mode 100644 ChangeLog.d/inject-entropy.txt diff --git a/ChangeLog.d/inject-entropy.txt b/ChangeLog.d/inject-entropy.txt new file mode 100644 index 000000000000..7626629693ba --- /dev/null +++ b/ChangeLog.d/inject-entropy.txt @@ -0,0 +1,2 @@ +Bugfix + * Fix the build with MBEDTLS_PSA_INJECT_ENTROPY. Fixes #7516. diff --git a/library/psa_crypto.c b/library/psa_crypto.c index bad7f469781b..fdcdd43d50cb 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -5066,6 +5066,10 @@ psa_status_t psa_raw_key_agreement(psa_algorithm_t alg, /* Random generation */ /****************************************************************/ +#if defined(MBEDTLS_PSA_INJECT_ENTROPY) +#include "mbedtls/entropy_poll.h" +#endif + /** Initialize the PSA random generator. */ static void mbedtls_psa_random_init(mbedtls_psa_random_context_t *rng) @@ -5200,8 +5204,6 @@ int mbedtls_psa_get_random(void *p_rng, #endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ #if defined(MBEDTLS_PSA_INJECT_ENTROPY) -#include "mbedtls/entropy_poll.h" - psa_status_t mbedtls_psa_inject_entropy(const uint8_t *seed, size_t seed_size) { From 73521b071531049265904552109dd7d52d25b4c3 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Fri, 28 Apr 2023 21:01:49 +0200 Subject: [PATCH 02/11] Tests: provide necessary functions for MBEDTLS_PSA_INJECT_ENTROPY The build option MBEDTLS_PSA_INJECT_ENTROPY requires some extra platform functions, for historical reasons. To enable us to test this option, provide a version of these functions for testing. (These versions would actually work in production, but providing them in the library in a way that doesn't break existing users might be slightly tricky, so it's out of scope of this commit.) Signed-off-by: Gilles Peskine --- scripts/config.py | 2 +- tests/configs/user-config-for-test.h | 20 ++++++++++++++++ tests/include/test/psa_crypto_helpers.h | 19 +++++++++++++++ tests/src/psa_crypto_helpers.c | 31 +++++++++++++++++++++++++ 4 files changed, 71 insertions(+), 1 deletion(-) diff --git a/scripts/config.py b/scripts/config.py index 9bf82c9afde9..2db67efaa909 100755 --- a/scripts/config.py +++ b/scripts/config.py @@ -200,7 +200,7 @@ def realfull_adapter(_name, active, section): 'MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG', # behavior change + build dependency 'MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER', # incompatible with USE_PSA_CRYPTO 'MBEDTLS_PSA_CRYPTO_SPM', # platform dependency (PSA SPM) - 'MBEDTLS_PSA_INJECT_ENTROPY', # build dependency (hook functions) + 'MBEDTLS_PSA_INJECT_ENTROPY', # conflicts with platform entropy sources 'MBEDTLS_REMOVE_3DES_CIPHERSUITES', # removes a feature 'MBEDTLS_REMOVE_ARC4_CIPHERSUITES', # removes a feature 'MBEDTLS_RSA_NO_CRT', # influences the use of RSA in X.509 and TLS diff --git a/tests/configs/user-config-for-test.h b/tests/configs/user-config-for-test.h index 6e7c154bae9f..fbec4f4c603e 100644 --- a/tests/configs/user-config-for-test.h +++ b/tests/configs/user-config-for-test.h @@ -57,3 +57,23 @@ #define MBEDTLS_PSA_ACCEL_ALG_HMAC #endif /* PSA_CRYPTO_DRIVER_TEST_ALL */ + + + +#if defined(MBEDTLS_PSA_INJECT_ENTROPY) +/* The #MBEDTLS_PSA_INJECT_ENTROPY feature requires two extra platform + * functions, which must be configured as #MBEDTLS_PLATFORM_NV_SEED_READ_MACRO + * and #MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO. The job of these functions + * is to read and write from the entropy seed file, which is located + * in the PSA ITS file whose uid is #PSA_CRYPTO_ITS_RANDOM_SEED_UID. + * (These could have been provided as library functions, but for historical + * reasons, they weren't, and so each integrator has to provide a copy + * of these functions.) + * + * Provide implementations of these functions for testing. */ +#include +int mbedtls_test_inject_entropy_seed_read(unsigned char *buf, size_t len); +int mbedtls_test_inject_entropy_seed_write(unsigned char *buf, size_t len); +#define MBEDTLS_PLATFORM_NV_SEED_READ_MACRO mbedtls_test_inject_entropy_seed_read +#define MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO mbedtls_test_inject_entropy_seed_write +#endif /* MBEDTLS_PSA_INJECT_ENTROPY */ diff --git a/tests/include/test/psa_crypto_helpers.h b/tests/include/test/psa_crypto_helpers.h index f8b98c07bc30..fd06874d595e 100644 --- a/tests/include/test/psa_crypto_helpers.h +++ b/tests/include/test/psa_crypto_helpers.h @@ -201,6 +201,25 @@ psa_key_usage_t mbedtls_test_update_key_usage_flags(psa_key_usage_t usage_flags) */ int mbedtls_test_fail_if_psa_leaking(int line_no, const char *filename); + + +#if defined(MBEDTLS_PSA_INJECT_ENTROPY) +/* The #MBEDTLS_PSA_INJECT_ENTROPY feature requires two extra platform + * functions, which must be configured as #MBEDTLS_PLATFORM_NV_SEED_READ_MACRO + * and #MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO. The job of these functions + * is to read and write from the entropy seed file, which is located + * in the PSA ITS file whose uid is #PSA_CRYPTO_ITS_RANDOM_SEED_UID. + * (These could have been provided as library functions, but for historical + * reasons, they weren't, and so each integrator has to provide a copy + * of these functions.) + * + * Provide implementations of these functions for testing. */ +int mbedtls_test_inject_entropy_seed_read(unsigned char *buf, size_t len); +int mbedtls_test_inject_entropy_seed_write(unsigned char *buf, size_t len); +#endif /* MBEDTLS_PSA_INJECT_ENTROPY */ + + + /** Skip a test case if the given key is a 192 bits AES key and the AES * implementation is at least partially provided by an accelerator or * alternative implementation. diff --git a/tests/src/psa_crypto_helpers.c b/tests/src/psa_crypto_helpers.c index 77c2f89764ff..7861185ee813 100644 --- a/tests/src/psa_crypto_helpers.c +++ b/tests/src/psa_crypto_helpers.c @@ -149,4 +149,35 @@ int mbedtls_test_fail_if_psa_leaking(int line_no, const char *filename) } } +#if defined(MBEDTLS_PSA_INJECT_ENTROPY) + +#include +#include + +int mbedtls_test_inject_entropy_seed_read(unsigned char *buf, size_t len) +{ + size_t actual_len = 0; + psa_status_t status = psa_its_get(PSA_CRYPTO_ITS_RANDOM_SEED_UID, + 0, len, buf, &actual_len); + if (status != 0) { + return MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR; + } + if (actual_len != len) { + return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED; + } + return 0; +} + +int mbedtls_test_inject_entropy_seed_write(unsigned char *buf, size_t len) +{ + psa_status_t status = psa_its_set(PSA_CRYPTO_ITS_RANDOM_SEED_UID, + len, buf, 0); + if (status != 0) { + return MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR; + } + return 0; +} + +#endif /* MBEDTLS_PSA_INJECT_ENTROPY */ + #endif /* MBEDTLS_PSA_CRYPTO_C */ From 4f8bf3cc548174502033e37191121cf8f9313747 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Fri, 28 Apr 2023 23:39:45 +0200 Subject: [PATCH 03/11] MBEDTLS_PSA_INJECT_ENTROPY: Make sure the seed file exist when running tests The seed file must exist before running tests. Because the location is somewhat platform- and configuration-dependent, and to be friendly to developers who run test suites individually and aren't familiar with this feature, rely on the test framework code rather than on test scripts to create the seed file. Signed-off-by: Gilles Peskine --- tests/include/test/psa_crypto_helpers.h | 16 ++++++++++++++++ tests/src/helpers.c | 18 ++++++++++++++++++ tests/src/psa_crypto_helpers.c | 14 ++++++++++++++ .../test_suite_psa_crypto_entropy.function | 4 ++-- 4 files changed, 50 insertions(+), 2 deletions(-) diff --git a/tests/include/test/psa_crypto_helpers.h b/tests/include/test/psa_crypto_helpers.h index fd06874d595e..8ac09c802bb7 100644 --- a/tests/include/test/psa_crypto_helpers.h +++ b/tests/include/test/psa_crypto_helpers.h @@ -216,6 +216,22 @@ int mbedtls_test_fail_if_psa_leaking(int line_no, const char *filename); * Provide implementations of these functions for testing. */ int mbedtls_test_inject_entropy_seed_read(unsigned char *buf, size_t len); int mbedtls_test_inject_entropy_seed_write(unsigned char *buf, size_t len); + + +/** Make sure that the injected entropy is present. + * + * When MBEDTLS_PSA_INJECT_ENTROPY is enabled, psa_crypto_init() + * will fail if the PSA entropy seed is not present. + * This function must be called at least once in a test suite or other + * program before any call to psa_crypto_init(). + * It does not need to be called in each test case. + * + * The test framework calls this function before running any test case. + * + * The few tests that might remove the entropy file must call this function + * in their cleanup. + */ +int mbedtls_test_inject_entropy_restore(void); #endif /* MBEDTLS_PSA_INJECT_ENTROPY */ diff --git a/tests/src/helpers.c b/tests/src/helpers.c index 6c215d1c0a7d..198a9c01e2bc 100644 --- a/tests/src/helpers.c +++ b/tests/src/helpers.c @@ -24,6 +24,11 @@ #include #endif +#if defined(MBEDTLS_PSA_INJECT_ENTROPY) +#include +#include +#endif + /*----------------------------------------------------------------------------*/ /* Static global variables */ @@ -52,9 +57,22 @@ mbedtls_test_info_t mbedtls_test_info; int mbedtls_test_platform_setup(void) { int ret = 0; + +#if defined(MBEDTLS_PSA_INJECT_ENTROPY) + /* Make sure that injected entropy is present. Otherwise + * psa_crypto_init() will fail. This is not necessary for test suites + * that don't use PSA, but it's harmless (except for leaving a file + * behind). */ + ret = mbedtls_test_inject_entropy_restore(); + if (ret != 0) { + return ret; + } +#endif + #if defined(MBEDTLS_PLATFORM_C) ret = mbedtls_platform_setup(&platform_ctx); #endif /* MBEDTLS_PLATFORM_C */ + return ret; } diff --git a/tests/src/psa_crypto_helpers.c b/tests/src/psa_crypto_helpers.c index 7861185ee813..cab96ab9679b 100644 --- a/tests/src/psa_crypto_helpers.c +++ b/tests/src/psa_crypto_helpers.c @@ -178,6 +178,20 @@ int mbedtls_test_inject_entropy_seed_write(unsigned char *buf, size_t len) return 0; } +int mbedtls_test_inject_entropy_restore(void) +{ + unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE]; + for (size_t i = 0; i < sizeof(buf); i++) { + buf[i] = (unsigned char) i; + } + psa_status_t status = mbedtls_psa_inject_entropy(buf, sizeof(buf)); + /* It's ok if the file was just created, or if it already exists. */ + if (status != PSA_SUCCESS && status != PSA_ERROR_NOT_PERMITTED) { + return status; + } + return PSA_SUCCESS; +} + #endif /* MBEDTLS_PSA_INJECT_ENTROPY */ #endif /* MBEDTLS_PSA_CRYPTO_C */ diff --git a/tests/suites/test_suite_psa_crypto_entropy.function b/tests/suites/test_suite_psa_crypto_entropy.function index 26ce0d3f5d31..f09943820331 100644 --- a/tests/suites/test_suite_psa_crypto_entropy.function +++ b/tests/suites/test_suite_psa_crypto_entropy.function @@ -153,8 +153,8 @@ void validate_entropy_seed_injection(int seed_length_a, TEST_ASSERT(memcmp(output, zeros, sizeof(output)) != 0); exit: mbedtls_free(seed); - remove_seed_file(); PSA_DONE(); + mbedtls_test_inject_entropy_restore(); } /* END_CASE */ @@ -186,7 +186,7 @@ void run_entropy_inject_with_crypto_init() status = mbedtls_psa_inject_entropy(seed, sizeof(seed)); TEST_EQUAL(status, PSA_ERROR_NOT_PERMITTED); exit: - remove_seed_file(); PSA_DONE(); + mbedtls_test_inject_entropy_restore(); } /* END_CASE */ From bfda1a96bbbd70bee4e55e197a665c818d03252b Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Fri, 28 Apr 2023 23:41:38 +0200 Subject: [PATCH 04/11] MBEDTLS_PSA_INJECT_ENTROPY: Skip incompatible tests When MBEDTLS_PSA_INJECT_ENTROPY is enabled, we disable standard entropy sources, so mbedtls_entropy_func() doesn't work out of the box. Disable tests that rely on it. MBEDTLS_PSA_INJECT_ENTROPY is intended for PSA-only environments anyway, so it doesn't matter if some legacy features don't work normally. Signed-off-by: Gilles Peskine --- tests/suites/test_suite_entropy.function | 2 +- tests/suites/test_suite_psa_crypto_init.data | 3 +++ tests/suites/test_suite_random.function | 4 ++-- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/tests/suites/test_suite_entropy.function b/tests/suites/test_suite_entropy.function index b04ed543c70e..5d8487c59989 100644 --- a/tests/suites/test_suite_entropy.function +++ b/tests/suites/test_suite_entropy.function @@ -135,7 +135,7 @@ int read_nv_seed(unsigned char *buf, size_t buf_len) /* END_HEADER */ /* BEGIN_DEPENDENCIES - * depends_on:MBEDTLS_ENTROPY_C + * depends_on:MBEDTLS_ENTROPY_C:!MBEDTLS_PSA_INJECT_ENTROPY * END_DEPENDENCIES */ diff --git a/tests/suites/test_suite_psa_crypto_init.data b/tests/suites/test_suite_psa_crypto_init.data index 9620a642a0d7..8c5b41d6cba2 100644 --- a/tests/suites/test_suite_psa_crypto_init.data +++ b/tests/suites/test_suite_psa_crypto_init.data @@ -25,7 +25,10 @@ validate_module_init_key_based:1 Custom entropy sources: all standard custom_entropy_sources:0x0000ffff:PSA_SUCCESS +# MBEDTLS_PSA_INJECT_ENTROPY means that a source of entropy (the seed file) +# is effectively always available. Custom entropy sources: none +depends_on:!MBEDTLS_PSA_INJECT_ENTROPY custom_entropy_sources:0:PSA_ERROR_INSUFFICIENT_ENTROPY Fake entropy: never returns anything diff --git a/tests/suites/test_suite_random.function b/tests/suites/test_suite_random.function index 0f0c7fa7e128..905ee78f3f7a 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_TEST_NULL_ENTROPY:MBEDTLS_CTR_DRBG_C */ +/* BEGIN_CASE depends_on:MBEDTLS_ENTROPY_C:!MBEDTLS_TEST_NULL_ENTROPY:!MBEDTLS_PSA_INJECT_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_TEST_NULL_ENTROPY:MBEDTLS_HMAC_DRBG_C */ +/* BEGIN_CASE depends_on:MBEDTLS_ENTROPY_C:!MBEDTLS_TEST_NULL_ENTROPY:!MBEDTLS_PSA_INJECT_ENTROPY:MBEDTLS_HMAC_DRBG_C */ void random_twice_with_hmac_drbg(int md_type) { mbedtls_entropy_context entropy; From 55e89985f0f2b2bdbd77f792a51c1963fd8bc182 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Fri, 28 Apr 2023 21:04:28 +0200 Subject: [PATCH 05/11] Test MBEDTLS_PSA_INJECT_ENTROPY Until now, we were never enabling this option in any test. MBEDTLS_PSA_INJECT_ENTROPY requires MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES, so it cannot be enabled in the full config and it gets its own component. Test with MBEDTLS_USE_PSA_CRYPTO enabled, since MBEDTLS_PSA_INJECT_ENTROPY is a very PSA feature (which can break non-PSA applications), and Mbed OS (for whch MBEDTLS_PSA_INJECT_ENTROPY was designed) enables MBEDTLS_USE_PSA_CRYPTO when it enables MBEDTLS_PSA_INJECT_ENTROPY. Signed-off-by: Gilles Peskine --- tests/scripts/all.sh | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/tests/scripts/all.sh b/tests/scripts/all.sh index 9eb5c3931186..73aa29248230 100755 --- a/tests/scripts/all.sh +++ b/tests/scripts/all.sh @@ -1244,6 +1244,21 @@ component_test_psa_external_rng_use_psa_crypto () { tests/ssl-opt.sh -f 'Default\|opaque' } +component_test_psa_inject_entropy () { + msg "build: full + MBEDTLS_PSA_INJECT_ENTROPY" + scripts/config.py full + scripts/config.py set MBEDTLS_PSA_INJECT_ENTROPY + scripts/config.py set MBEDTLS_ENTROPY_NV_SEED + scripts/config.py set MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES + scripts/config.py unset MBEDTLS_PLATFORM_NV_SEED_ALT + scripts/config.py unset MBEDTLS_PLATFORM_STD_NV_SEED_READ + scripts/config.py unset MBEDTLS_PLATFORM_STD_NV_SEED_WRITE + make CFLAGS="$ASAN_CFLAGS '-DMBEDTLS_USER_CONFIG_FILE=\"../tests/configs/user-config-for-test.h\"'" LDFLAGS="$ASAN_CFLAGS" + + msg "test: full + MBEDTLS_PSA_INJECT_ENTROPY" + make test +} + component_test_ecp_no_internal_rng () { msg "build: Default plus ECP_NO_INTERNAL_RNG minus DRBG modules" scripts/config.py set MBEDTLS_ECP_NO_INTERNAL_RNG From cf21e944f6f7ee566a8eeaf169169e74011a5e38 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Fri, 28 Apr 2023 21:07:07 +0200 Subject: [PATCH 06/11] Modernize remove_seed_file() This function was written before the PSA storage layer switched to the PSA ITS API as its storage abstraction. Now we can just call PSA ITS functions unconditionally. Signed-off-by: Gilles Peskine --- .../test_suite_psa_crypto_entropy.function | 22 +++++-------------- 1 file changed, 5 insertions(+), 17 deletions(-) diff --git a/tests/suites/test_suite_psa_crypto_entropy.function b/tests/suites/test_suite_psa_crypto_entropy.function index f09943820331..b109eeecce74 100644 --- a/tests/suites/test_suite_psa_crypto_entropy.function +++ b/tests/suites/test_suite_psa_crypto_entropy.function @@ -12,28 +12,16 @@ MBEDTLS_ENTROPY_BLOCK_SIZE) #if defined(MBEDTLS_PSA_INJECT_ENTROPY) +#include -#if defined(MBEDTLS_PSA_ITS_FILE_C) -#include -#else -#include -#endif -/* 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. */ +/* Remove the entropy seed file. + * + * See check_random_seed_file() regarding abstraction boundaries. + */ 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 } #endif /* MBEDTLS_PSA_INJECT_ENTROPY */ From 154dadfae82d48812a5d8aebdf856f1bddc3578e Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Fri, 28 Apr 2023 21:08:46 +0200 Subject: [PATCH 07/11] MBEDTLS_PSA_INJECT_ENTROPY: check the lifecycle of the seed file The seed file is part of the stable interface of PSA_CRYPTO_INJECT_ENTROPY, because it has to survive a library upgrade on a device. So check that its existence and content are as expected at each point in the tested life cycle. Signed-off-by: Gilles Peskine --- .../test_suite_psa_crypto_entropy.function | 65 +++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/tests/suites/test_suite_psa_crypto_entropy.function b/tests/suites/test_suite_psa_crypto_entropy.function index b109eeecce74..5184611f2d17 100644 --- a/tests/suites/test_suite_psa_crypto_entropy.function +++ b/tests/suites/test_suite_psa_crypto_entropy.function @@ -14,6 +14,40 @@ #if defined(MBEDTLS_PSA_INJECT_ENTROPY) #include +/* Check the entropy seed file. + * + * \param expected_size Expected size in bytes. + * If 0, the file must not exist. + * + * \retval 0 Either \p expected_size is nonzero and + * the entropy seed file exists and has exactly this size, + * or \p expected_size is zero and the file does not exist. + * \retval 1 Either \p expected_size is nonzero and + * the entropy seed file exists, + * or \p expected_size is zero and the file exists. + * In this case, the test case is marked as failed. + * + * \note We enforce that the seed is in a specific ITS file. + * This must not change, otherwise we break backward compatibility if + * the library is upgraded on a device with an existing seed. + */ +int check_random_seed_file(size_t expected_size) +{ + struct psa_storage_info_t info = { 0, 0 }; + psa_status_t status = psa_its_get_info(PSA_CRYPTO_ITS_RANDOM_SEED_UID, + &info); + + if (expected_size == 0) { + TEST_EQUAL(status, PSA_ERROR_DOES_NOT_EXIST); + } else { + TEST_EQUAL(status, PSA_SUCCESS); + TEST_EQUAL(info.size, expected_size); + } + return 1; + +exit: + return 0; +} /* Remove the entropy seed file. * @@ -131,14 +165,30 @@ void validate_entropy_seed_injection(int seed_length_a, status = remove_seed_file(); TEST_ASSERT((status == PSA_SUCCESS) || (status == PSA_ERROR_DOES_NOT_EXIST)); + if (!check_random_seed_file(0)) { + goto exit; + } + status = mbedtls_psa_inject_entropy(seed, seed_length_a); TEST_EQUAL(status, expected_status_a); + if (!check_random_seed_file(expected_status_a == PSA_SUCCESS ? seed_length_a : + 0)) { + goto exit; + } + status = mbedtls_psa_inject_entropy(seed, seed_length_b); TEST_EQUAL(status, expected_status_b); + if (!check_random_seed_file(expected_status_a == PSA_SUCCESS ? seed_length_a : + expected_status_b == PSA_SUCCESS ? seed_length_b : + 0)) { + goto exit; + } + PSA_ASSERT(psa_crypto_init()); PSA_ASSERT(psa_generate_random(output, sizeof(output))); TEST_ASSERT(memcmp(output, zeros, sizeof(output)) != 0); + exit: mbedtls_free(seed); PSA_DONE(); @@ -156,23 +206,38 @@ void run_entropy_inject_with_crypto_init() for (i = 0; i < sizeof(seed); ++i) { seed[i] = i; } + status = remove_seed_file(); TEST_ASSERT((status == PSA_SUCCESS) || (status == PSA_ERROR_DOES_NOT_EXIST)); + if (!check_random_seed_file(0)) { + goto exit; + } status = mbedtls_psa_inject_entropy(seed, sizeof(seed)); PSA_ASSERT(status); + TEST_ASSERT(check_random_seed_file(sizeof(seed))); status = remove_seed_file(); TEST_EQUAL(status, PSA_SUCCESS); + if (!check_random_seed_file(0)) { + goto exit; + } + status = psa_crypto_init(); TEST_EQUAL(status, PSA_ERROR_INSUFFICIENT_ENTROPY); status = mbedtls_psa_inject_entropy(seed, sizeof(seed)); PSA_ASSERT(status); + if (!check_random_seed_file(sizeof(seed))) { + goto exit; + } + status = psa_crypto_init(); PSA_ASSERT(status); PSA_DONE(); + /* The seed is written by nv_seed callback functions therefore the injection will fail */ status = mbedtls_psa_inject_entropy(seed, sizeof(seed)); TEST_EQUAL(status, PSA_ERROR_NOT_PERMITTED); + exit: PSA_DONE(); mbedtls_test_inject_entropy_restore(); From 58d085419cd2c8175673761e7dd4cae17367efec Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Fri, 28 Apr 2023 21:13:43 +0200 Subject: [PATCH 08/11] MBEDTLS_PSA_INJECT_ENTROPY: check the seed file UID The seed file UID is part of the library's stable interface. Signed-off-by: Gilles Peskine --- tests/suites/test_suite_psa_crypto_entropy.function | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/suites/test_suite_psa_crypto_entropy.function b/tests/suites/test_suite_psa_crypto_entropy.function index 5184611f2d17..973740dca96c 100644 --- a/tests/suites/test_suite_psa_crypto_entropy.function +++ b/tests/suites/test_suite_psa_crypto_entropy.function @@ -33,6 +33,12 @@ */ int check_random_seed_file(size_t expected_size) { + /* The value of the random seed UID must not change. Otherwise that would + * break upgrades of the library on devices that already contain a seed + * file. If this test assertion fails, you've presumably broken backward + * compatibility! */ + TEST_EQUAL(PSA_CRYPTO_ITS_RANDOM_SEED_UID, 0xFFFFFF52); + struct psa_storage_info_t info = { 0, 0 }; psa_status_t status = psa_its_get_info(PSA_CRYPTO_ITS_RANDOM_SEED_UID, &info); From 581c6e12ce7f423e4559243ad9b914ba2002d4c4 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Sat, 29 Apr 2023 00:32:34 +0200 Subject: [PATCH 09/11] MBEDTLS_PSA_INJECT_ENTROPY: ignore seed file The test framework leaves the seed file behind (like it does with the corresponding file in the legacy API, namely seedfile), so ignore it. Signed-off-by: Gilles Peskine --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index f2c4a3bc0c96..54b3c5496df0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,7 @@ # Random seed file created by test scripts and sample programs seedfile +# MBEDTLS_PSA_INJECT_ENTROPY seed file created by the test framework +00000000ffffff52.psa_its # CMake build artifacts: CMakeCache.txt From 24d01248680c15be07229fe7d52daba19fd7a9d7 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Thu, 20 Jul 2023 17:54:19 +0200 Subject: [PATCH 10/11] Fix copypasta in function documentation Signed-off-by: Gilles Peskine --- tests/suites/test_suite_psa_crypto_entropy.function | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/suites/test_suite_psa_crypto_entropy.function b/tests/suites/test_suite_psa_crypto_entropy.function index 973740dca96c..0c8f2d5bc20a 100644 --- a/tests/suites/test_suite_psa_crypto_entropy.function +++ b/tests/suites/test_suite_psa_crypto_entropy.function @@ -19,12 +19,12 @@ * \param expected_size Expected size in bytes. * If 0, the file must not exist. * - * \retval 0 Either \p expected_size is nonzero and + * \retval 1 Either \p expected_size is nonzero and * the entropy seed file exists and has exactly this size, * or \p expected_size is zero and the file does not exist. - * \retval 1 Either \p expected_size is nonzero and - * the entropy seed file exists, - * or \p expected_size is zero and the file exists. + * \retval 0 Either \p expected_size is nonzero but + * the entropy seed file does not exist or has a different size, + * or \p expected_size is zero but the file exists. * In this case, the test case is marked as failed. * * \note We enforce that the seed is in a specific ITS file. From 1fc71160b1a7d2a9dda4a18133a852e9ce97d654 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Thu, 20 Jul 2023 20:04:00 +0200 Subject: [PATCH 11/11] Add missing dependencies on real entropy Tests that call mbedtls_test_ssl_endpoint_init() need mbedtls_entropy_func() to work. Signed-off-by: Gilles Peskine --- tests/suites/test_suite_ssl.function | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function index bc999f10a71e..6bcde710ba3b 100644 --- a/tests/suites/test_suite_ssl.function +++ b/tests/suites/test_suite_ssl.function @@ -2126,7 +2126,7 @@ void ssl_session_serialize_version_check(int corrupt_major, } /* END_CASE */ -/* BEGIN_CASE depends_on:MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED:MBEDTLS_CERTS_C:MBEDTLS_RSA_C:MBEDTLS_ECP_DP_SECP384R1_ENABLED:!MBEDTLS_USE_PSA_CRYPTO:MBEDTLS_PKCS1_V15:MBEDTLS_ENTROPY_C:MBEDTLS_ENTROPY_C:MBEDTLS_CTR_DRBG_C:MBEDTLS_SHA256_C */ +/* BEGIN_CASE depends_on:MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED:MBEDTLS_CERTS_C:MBEDTLS_RSA_C:MBEDTLS_ECP_DP_SECP384R1_ENABLED:!MBEDTLS_USE_PSA_CRYPTO:MBEDTLS_PKCS1_V15:MBEDTLS_ENTROPY_C:!MBEDTLS_TEST_NULL_ENTROPY:!MBEDTLS_PSA_INJECT_ENTROPY:MBEDTLS_CTR_DRBG_C:MBEDTLS_SHA256_C */ void mbedtls_endpoint_sanity(int endpoint_type) { enum { BUFFSIZE = 1024 }; @@ -2151,7 +2151,7 @@ exit: } /* END_CASE */ -/* BEGIN_CASE depends_on:MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED:MBEDTLS_CERTS_C:MBEDTLS_RSA_C:MBEDTLS_ECP_DP_SECP384R1_ENABLED:!MBEDTLS_USE_PSA_CRYPTO:MBEDTLS_PKCS1_V15:MBEDTLS_ENTROPY_C:MBEDTLS_ENTROPY_C:MBEDTLS_CTR_DRBG_C:MBEDTLS_ECP_C:MBEDTLS_SHA256_C */ +/* BEGIN_CASE depends_on:MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED:MBEDTLS_CERTS_C:MBEDTLS_RSA_C:MBEDTLS_ECP_DP_SECP384R1_ENABLED:!MBEDTLS_USE_PSA_CRYPTO:MBEDTLS_PKCS1_V15:MBEDTLS_ENTROPY_C:!MBEDTLS_TEST_NULL_ENTROPY:!MBEDTLS_PSA_INJECT_ENTROPY:MBEDTLS_CTR_DRBG_C:MBEDTLS_ECP_C:MBEDTLS_SHA256_C */ void move_handshake_to_state(int endpoint_type, int state, int need_pass) { enum { BUFFSIZE = 1024 }; @@ -2408,7 +2408,7 @@ void resize_buffers_renegotiate_mfl(int mfl, int legacy_renegotiation, } /* END_CASE */ -/* BEGIN_CASE depends_on:MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED:MBEDTLS_CERTS_C:MBEDTLS_USE_PSA_CRYPTO:MBEDTLS_PKCS1_V15:MBEDTLS_SSL_PROTO_TLS1_2:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ENTROPY_C:MBEDTLS_RSA_C:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_CTR_DRBG_C:MBEDTLS_ECP_C:MBEDTLS_ECDSA_C */ +/* BEGIN_CASE depends_on:MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED:MBEDTLS_CERTS_C:MBEDTLS_USE_PSA_CRYPTO:MBEDTLS_PKCS1_V15:MBEDTLS_SSL_PROTO_TLS1_2:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ENTROPY_C:!MBEDTLS_TEST_NULL_ENTROPY:!MBEDTLS_PSA_INJECT_ENTROPY:MBEDTLS_RSA_C:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_CTR_DRBG_C:MBEDTLS_ECP_C:MBEDTLS_ECDSA_C */ void raw_key_agreement_fail(int bad_server_ecdhe_key) { enum { BUFFSIZE = 17000 };