diff options
author | Dr. Matthias St. Pierre <Matthias.St.Pierre@ncp-e.com> | 2019-05-27 21:03:09 +0200 |
---|---|---|
committer | Dr. Matthias St. Pierre <Matthias.St.Pierre@ncp-e.com> | 2019-09-11 11:22:18 +0200 |
commit | 849529257c9979c7ca0d28e8b80a47bc4a36d4f2 (patch) | |
tree | 2e85307b6e252fe6d175fae0bd8ca3282404e3d2 /test | |
parent | dc64dc2edd215d6cc5843c1bfe1f0b64bff26adc (diff) |
drbg: ensure fork-safety without using a pthread_atfork handler
When the new OpenSSL CSPRNG was introduced in version 1.1.1,
it was announced in the release notes that it would be fork-safe,
which the old CSPRNG hadn't been.
The fork-safety was implemented using a fork count, which was
incremented by a pthread_atfork handler. Initially, this handler
was enabled by default. Unfortunately, the default behaviour
had to be changed for other reasons in commit b5319bdbd095, so
the new OpenSSL CSPRNG failed to keep its promise.
This commit restores the fork-safety using a different approach.
It replaces the fork count by a fork id, which coincides with
the process id on UNIX-like operating systems and is zero on other
operating systems. It is used to detect when an automatic reseed
after a fork is necessary.
To prevent a future regression, it also adds a test to verify that
the child reseeds after fork.
CVE-2019-1549
Reviewed-by: Paul Dale <paul.dale@oracle.com>
Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/9832)
Diffstat (limited to 'test')
-rw-r--r-- | test/drbgtest.c | 45 |
1 files changed, 45 insertions, 0 deletions
diff --git a/test/drbgtest.c b/test/drbgtest.c index 9efdd87a4d..4559ffd635 100644 --- a/test/drbgtest.c +++ b/test/drbgtest.c @@ -22,6 +22,13 @@ # include <windows.h> #endif + +#if defined(OPENSSL_SYS_UNIX) +# include <sys/types.h> +# include <sys/wait.h> +# include <unistd.h> +#endif + #include "testutil.h" #include "drbgtest.h" @@ -708,6 +715,40 @@ static int test_drbg_reseed(int expect_success, return 1; } + +#if defined(OPENSSL_SYS_UNIX) +/* + * Test whether master, public and private DRBG are reseeded after + * forking the process. + */ +static int test_drbg_reseed_after_fork(RAND_DRBG *master, + RAND_DRBG *public, + RAND_DRBG *private) +{ + pid_t pid; + int status=0; + + pid = fork(); + if (!TEST_int_ge(pid, 0)) + return 0; + + if (pid > 0) { + /* I'm the parent; wait for the child and check its exit code */ + return TEST_int_eq(waitpid(pid, &status, 0), pid) && TEST_int_eq(status, 0); + } + + /* I'm the child; check whether all three DRBGs reseed. */ + if (!TEST_true(test_drbg_reseed(1, master, public, private, 1, 1, 1, 0))) + status = 1; + + /* Remove hooks */ + unhook_drbg(master); + unhook_drbg(public); + unhook_drbg(private); + exit(status); +} +#endif + /* * Test whether the default rand_method (RAND_OpenSSL()) is * setup correctly, in particular whether reseeding works @@ -798,6 +839,10 @@ static int test_rand_drbg_reseed(void) goto error; reset_drbg_hook_ctx(); +#if defined(OPENSSL_SYS_UNIX) + if (!TEST_true(test_drbg_reseed_after_fork(master, public, private))) + goto error; +#endif /* fill 'randomness' buffer with some arbitrary data */ memset(rand_add_buf, 'r', sizeof(rand_add_buf)); |