diff --git a/tests/s2n_test.h b/tests/s2n_test.h index 24ae0dca31a..7b79981355d 100644 --- a/tests/s2n_test.h +++ b/tests/s2n_test.h @@ -61,17 +61,12 @@ int test_count; * not initialise at the start of the test. Useful for tests that e.g spawn a * number of independent childs at the start of a unit test and where you want * each child to have its own independently initialised s2n. - * - * BEGIN_TEST() prints unit test information to stdout. But this often gets - * buffered by the kernel and will then be flushed in each child spawned. The - * result is a number of repeated messages being send to stdout and, in turn, - * appear in the logs. At the moment, we think this is better than risking not - * having any printing at all. */ #define BEGIN_TEST_NO_INIT() \ do { \ test_count = 0; \ fprintf(stdout, "Running %-50s ... ", __FILE__); \ + fflush(stdout); \ EXPECT_SUCCESS_WITHOUT_COUNT(s2n_in_unit_test_set(true)); \ S2N_TEST_OPTIONALLY_ENABLE_FIPS_MODE(); \ } while(0) diff --git a/tests/unit/s2n_random_test.c b/tests/unit/s2n_random_test.c index 80b21eb39b4..dcc57dcc4f1 100644 --- a/tests/unit/s2n_random_test.c +++ b/tests/unit/s2n_random_test.c @@ -792,6 +792,30 @@ static int s2n_random_rand_bytes_after_cleanup_cb(struct random_test_case *test_ return S2N_SUCCESS; } +static int s2n_random_rand_bytes_before_init(struct random_test_case *test_case) +{ +#if S2N_LIBCRYPTO_SUPPORTS_CUSTOM_RAND + /* Calling RAND_bytes will set a global random method */ + unsigned char rndbytes[16] = { 0 }; + EXPECT_EQUAL(RAND_bytes(rndbytes, sizeof(rndbytes)), 1); + const RAND_METHOD *rand_method = RAND_get_rand_method(); + EXPECT_NOT_NULL(rand_method); + EXPECT_NOT_EQUAL(rand_method->bytes, s2n_openssl_compat_rand); + + EXPECT_SUCCESS(s2n_init()); + + /* The global random method is overridden after calling s2n_init() */ + const RAND_METHOD *custom_rand_method = RAND_get_rand_method(); + EXPECT_NOT_NULL(custom_rand_method); + EXPECT_EQUAL(custom_rand_method->bytes, s2n_openssl_compat_rand); + + /* RAND_bytes is still successful */ + EXPECT_EQUAL(RAND_bytes(rndbytes, sizeof(rndbytes)), 1); + +#endif + return S2N_SUCCESS; +} + static int s2n_random_invalid_urandom_fd_cb(struct random_test_case *test_case) { EXPECT_SUCCESS(s2n_disable_atexit()); @@ -862,6 +886,7 @@ struct random_test_case random_test_cases[] = { { "Test failure.", s2n_random_test_case_failure_cb, CLONE_TEST_DETERMINE_AT_RUNTIME, 1 }, { "Test libcrypto's RAND engine is reset correctly after manual s2n_cleanup()", s2n_random_rand_bytes_after_cleanup_cb, CLONE_TEST_DETERMINE_AT_RUNTIME, EXIT_SUCCESS }, { "Test getting entropy with an invalid file descriptor", s2n_random_invalid_urandom_fd_cb, CLONE_TEST_DETERMINE_AT_RUNTIME, EXIT_SUCCESS }, + { "Test libcrypto's global RAND is unset after calling s2n_init()", s2n_random_rand_bytes_before_init, CLONE_TEST_DETERMINE_AT_RUNTIME, EXIT_SUCCESS }, }; int main(int argc, char **argv) diff --git a/utils/s2n_random.c b/utils/s2n_random.c index 5656ba1e94c..7bb24bbfbf8 100644 --- a/utils/s2n_random.c +++ b/utils/s2n_random.c @@ -553,6 +553,9 @@ S2N_RESULT s2n_rand_init(void) return S2N_RESULT_OK; } + /* Unset any existing random engine */ + RESULT_GUARD_OSSL(RAND_set_rand_engine(NULL), S2N_ERR_OPEN_RANDOM); + /* Create an engine */ ENGINE *e = ENGINE_new(); diff --git a/utils/s2n_random.h b/utils/s2n_random.h index 72237054818..5284e6271a8 100644 --- a/utils/s2n_random.h +++ b/utils/s2n_random.h @@ -40,3 +40,4 @@ S2N_RESULT s2n_get_public_random_bytes_used(uint64_t *bytes_used); S2N_RESULT s2n_get_private_random_data(struct s2n_blob *blob); S2N_RESULT s2n_get_private_random_bytes_used(uint64_t *bytes_used); S2N_RESULT s2n_public_random(int64_t max, uint64_t *output); +int s2n_openssl_compat_rand(unsigned char *buf, int num);