xref: /freebsd/crypto/openssl/test/drbgtest.c (revision 0d0c8621fd181e507f0fb50ffcca606faf66a8c2)
1e0c4386eSCy Schubert /*
2e0c4386eSCy Schubert  * Copyright 2011-2022 The OpenSSL Project Authors. All Rights Reserved.
3e0c4386eSCy Schubert  *
4e0c4386eSCy Schubert  * Licensed under the Apache License 2.0 (the "License").  You may not use
5e0c4386eSCy Schubert  * this file except in compliance with the License.  You can obtain a copy
6e0c4386eSCy Schubert  * in the file LICENSE in the source distribution or at
7e0c4386eSCy Schubert  * https://www.openssl.org/source/license.html
8e0c4386eSCy Schubert  */
9e0c4386eSCy Schubert 
10e0c4386eSCy Schubert /* We need to use some deprecated APIs */
11e0c4386eSCy Schubert #define OPENSSL_SUPPRESS_DEPRECATED
12e0c4386eSCy Schubert 
13e0c4386eSCy Schubert #include <string.h>
14e0c4386eSCy Schubert #include "internal/nelem.h"
15e0c4386eSCy Schubert #include <openssl/crypto.h>
16e0c4386eSCy Schubert #include <openssl/err.h>
17e0c4386eSCy Schubert #include <openssl/rand.h>
18e0c4386eSCy Schubert #include <openssl/obj_mac.h>
19e0c4386eSCy Schubert #include <openssl/evp.h>
20e0c4386eSCy Schubert #include <openssl/aes.h>
21e0c4386eSCy Schubert #include "../crypto/rand/rand_local.h"
22e0c4386eSCy Schubert #include "../include/crypto/rand.h"
23e0c4386eSCy Schubert #include "../include/crypto/evp.h"
24e0c4386eSCy Schubert #include "../providers/implementations/rands/drbg_local.h"
25e0c4386eSCy Schubert #include "../crypto/evp/evp_local.h"
26e0c4386eSCy Schubert 
27e0c4386eSCy Schubert #if defined(_WIN32)
28e0c4386eSCy Schubert # include <windows.h>
29e0c4386eSCy Schubert #endif
30e0c4386eSCy Schubert 
31e0c4386eSCy Schubert #if defined(__TANDEM)
32e0c4386eSCy Schubert # if defined(OPENSSL_TANDEM_FLOSS)
33e0c4386eSCy Schubert #  include <floss.h(floss_fork)>
34e0c4386eSCy Schubert # endif
35e0c4386eSCy Schubert #endif
36e0c4386eSCy Schubert 
37e0c4386eSCy Schubert #if defined(OPENSSL_SYS_UNIX)
38e0c4386eSCy Schubert # include <sys/types.h>
39e0c4386eSCy Schubert # include <sys/wait.h>
40e0c4386eSCy Schubert # include <unistd.h>
41e0c4386eSCy Schubert #endif
42e0c4386eSCy Schubert 
43e0c4386eSCy Schubert #include "testutil.h"
44e0c4386eSCy Schubert 
45e0c4386eSCy Schubert /*
46e0c4386eSCy Schubert  * DRBG generate wrappers
47e0c4386eSCy Schubert  */
gen_bytes(EVP_RAND_CTX * drbg,unsigned char * buf,int num)48e0c4386eSCy Schubert static int gen_bytes(EVP_RAND_CTX *drbg, unsigned char *buf, int num)
49e0c4386eSCy Schubert {
50e0c4386eSCy Schubert #ifndef OPENSSL_NO_DEPRECATED_3_0
51e0c4386eSCy Schubert     const RAND_METHOD *meth = RAND_get_rand_method();
52e0c4386eSCy Schubert 
53e0c4386eSCy Schubert     if (meth != NULL && meth != RAND_OpenSSL()) {
54e0c4386eSCy Schubert         if (meth->bytes != NULL)
55e0c4386eSCy Schubert             return meth->bytes(buf, num);
56e0c4386eSCy Schubert         return -1;
57e0c4386eSCy Schubert     }
58e0c4386eSCy Schubert #endif
59e0c4386eSCy Schubert 
60e0c4386eSCy Schubert     if (drbg != NULL)
61e0c4386eSCy Schubert         return EVP_RAND_generate(drbg, buf, num, 0, 0, NULL, 0);
62e0c4386eSCy Schubert     return 0;
63e0c4386eSCy Schubert }
64e0c4386eSCy Schubert 
rand_bytes(unsigned char * buf,int num)65e0c4386eSCy Schubert static int rand_bytes(unsigned char *buf, int num)
66e0c4386eSCy Schubert {
67e0c4386eSCy Schubert     return gen_bytes(RAND_get0_public(NULL), buf, num);
68e0c4386eSCy Schubert }
69e0c4386eSCy Schubert 
rand_priv_bytes(unsigned char * buf,int num)70e0c4386eSCy Schubert static int rand_priv_bytes(unsigned char *buf, int num)
71e0c4386eSCy Schubert {
72e0c4386eSCy Schubert     return gen_bytes(RAND_get0_private(NULL), buf, num);
73e0c4386eSCy Schubert }
74e0c4386eSCy Schubert 
75e0c4386eSCy Schubert 
76e0c4386eSCy Schubert /* size of random output generated in test_drbg_reseed() */
77e0c4386eSCy Schubert #define RANDOM_SIZE 16
78e0c4386eSCy Schubert 
79e0c4386eSCy Schubert /*
80e0c4386eSCy Schubert  * DRBG query functions
81e0c4386eSCy Schubert  */
state(EVP_RAND_CTX * drbg)82e0c4386eSCy Schubert static int state(EVP_RAND_CTX *drbg)
83e0c4386eSCy Schubert {
84e0c4386eSCy Schubert     return EVP_RAND_get_state(drbg);
85e0c4386eSCy Schubert }
86e0c4386eSCy Schubert 
query_rand_uint(EVP_RAND_CTX * drbg,const char * name)87e0c4386eSCy Schubert static unsigned int query_rand_uint(EVP_RAND_CTX *drbg, const char *name)
88e0c4386eSCy Schubert {
89e0c4386eSCy Schubert     OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END };
90e0c4386eSCy Schubert     unsigned int n;
91e0c4386eSCy Schubert 
92e0c4386eSCy Schubert     *params = OSSL_PARAM_construct_uint(name, &n);
93e0c4386eSCy Schubert     if (EVP_RAND_CTX_get_params(drbg, params))
94e0c4386eSCy Schubert         return n;
95e0c4386eSCy Schubert     return 0;
96e0c4386eSCy Schubert }
97e0c4386eSCy Schubert 
98e0c4386eSCy Schubert #define DRBG_UINT(name)                                 \
99e0c4386eSCy Schubert     static unsigned int name(EVP_RAND_CTX *drbg)        \
100e0c4386eSCy Schubert     {                                                   \
101e0c4386eSCy Schubert         return query_rand_uint(drbg, #name);            \
102e0c4386eSCy Schubert     }
DRBG_UINT(reseed_counter)103e0c4386eSCy Schubert DRBG_UINT(reseed_counter)
104e0c4386eSCy Schubert 
105e0c4386eSCy Schubert static PROV_DRBG *prov_rand(EVP_RAND_CTX *drbg)
106e0c4386eSCy Schubert {
107e0c4386eSCy Schubert     return (PROV_DRBG *)drbg->algctx;
108e0c4386eSCy Schubert }
109e0c4386eSCy Schubert 
set_reseed_counter(EVP_RAND_CTX * drbg,unsigned int n)110e0c4386eSCy Schubert static void set_reseed_counter(EVP_RAND_CTX *drbg, unsigned int n)
111e0c4386eSCy Schubert {
112e0c4386eSCy Schubert     PROV_DRBG *p = prov_rand(drbg);
113e0c4386eSCy Schubert 
114e0c4386eSCy Schubert     p->reseed_counter = n;
115e0c4386eSCy Schubert }
116e0c4386eSCy Schubert 
inc_reseed_counter(EVP_RAND_CTX * drbg)117e0c4386eSCy Schubert static void inc_reseed_counter(EVP_RAND_CTX *drbg)
118e0c4386eSCy Schubert {
119e0c4386eSCy Schubert     set_reseed_counter(drbg, reseed_counter(drbg) + 1);
120e0c4386eSCy Schubert }
121e0c4386eSCy Schubert 
reseed_time(EVP_RAND_CTX * drbg)122e0c4386eSCy Schubert static time_t reseed_time(EVP_RAND_CTX *drbg)
123e0c4386eSCy Schubert {
124e0c4386eSCy Schubert     OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END };
125e0c4386eSCy Schubert     time_t t;
126e0c4386eSCy Schubert 
127e0c4386eSCy Schubert     *params = OSSL_PARAM_construct_time_t(OSSL_DRBG_PARAM_RESEED_TIME, &t);
128e0c4386eSCy Schubert     if (EVP_RAND_CTX_get_params(drbg, params))
129e0c4386eSCy Schubert         return t;
130e0c4386eSCy Schubert     return 0;
131e0c4386eSCy Schubert }
132e0c4386eSCy Schubert 
133e0c4386eSCy Schubert /*
134e0c4386eSCy Schubert  * When building the FIPS module, it isn't possible to disable the continuous
135e0c4386eSCy Schubert  * RNG tests.  Tests that require this are skipped and this means a detection
136e0c4386eSCy Schubert  * mechanism for the FIPS provider being in use.
137e0c4386eSCy Schubert  */
using_fips_rng(void)138e0c4386eSCy Schubert static int using_fips_rng(void)
139e0c4386eSCy Schubert {
140e0c4386eSCy Schubert     EVP_RAND_CTX *primary = RAND_get0_primary(NULL);
141e0c4386eSCy Schubert     const OSSL_PROVIDER *prov;
142e0c4386eSCy Schubert     const char *name;
143e0c4386eSCy Schubert 
144e0c4386eSCy Schubert     if (!TEST_ptr(primary))
145e0c4386eSCy Schubert         return 0;
146e0c4386eSCy Schubert 
147e0c4386eSCy Schubert     prov = EVP_RAND_get0_provider(EVP_RAND_CTX_get0_rand(primary));
148e0c4386eSCy Schubert     if (!TEST_ptr(prov))
149e0c4386eSCy Schubert         return 0;
150e0c4386eSCy Schubert     name = OSSL_PROVIDER_get0_name(prov);
151e0c4386eSCy Schubert     return strcmp(name, "OpenSSL FIPS Provider") == 0;
152e0c4386eSCy Schubert }
153e0c4386eSCy Schubert 
154e0c4386eSCy Schubert  /*
155e0c4386eSCy Schubert  * Disable CRNG testing if it is enabled.
156e0c4386eSCy Schubert  * This stub remains to indicate the calling locations where it is necessary.
157e0c4386eSCy Schubert  * Once the RNG infrastructure is able to disable these tests, it should be
158e0c4386eSCy Schubert  * reconstituted.
159e0c4386eSCy Schubert  */
disable_crngt(EVP_RAND_CTX * drbg)160e0c4386eSCy Schubert static int disable_crngt(EVP_RAND_CTX *drbg)
161e0c4386eSCy Schubert {
162e0c4386eSCy Schubert     return 1;
163e0c4386eSCy Schubert }
164e0c4386eSCy Schubert 
165e0c4386eSCy Schubert /*
166e0c4386eSCy Schubert  * Generates random output using rand_bytes() and rand_priv_bytes()
167e0c4386eSCy Schubert  * and checks whether the three shared DRBGs were reseeded as
168e0c4386eSCy Schubert  * expected.
169e0c4386eSCy Schubert  *
170e0c4386eSCy Schubert  * |expect_success|: expected outcome (as reported by RAND_status())
171e0c4386eSCy Schubert  * |primary|, |public|, |private|: pointers to the three shared DRBGs
172e0c4386eSCy Schubert  * |public_random|, |private_random|: generated random output
173e0c4386eSCy Schubert  * |expect_xxx_reseed| =
174e0c4386eSCy Schubert  *       1:  it is expected that the specified DRBG is reseeded
175e0c4386eSCy Schubert  *       0:  it is expected that the specified DRBG is not reseeded
176e0c4386eSCy Schubert  *      -1:  don't check whether the specified DRBG was reseeded or not
177e0c4386eSCy Schubert  * |reseed_when|: if nonzero, used instead of time(NULL) to set the
178e0c4386eSCy Schubert  *                |before_reseed| time.
179e0c4386eSCy Schubert  */
test_drbg_reseed(int expect_success,EVP_RAND_CTX * primary,EVP_RAND_CTX * public,EVP_RAND_CTX * private,unsigned char * public_random,unsigned char * private_random,int expect_primary_reseed,int expect_public_reseed,int expect_private_reseed,time_t reseed_when)180e0c4386eSCy Schubert static int test_drbg_reseed(int expect_success,
181e0c4386eSCy Schubert                             EVP_RAND_CTX *primary,
182e0c4386eSCy Schubert                             EVP_RAND_CTX *public,
183e0c4386eSCy Schubert                             EVP_RAND_CTX *private,
184e0c4386eSCy Schubert                             unsigned char *public_random,
185e0c4386eSCy Schubert                             unsigned char *private_random,
186e0c4386eSCy Schubert                             int expect_primary_reseed,
187e0c4386eSCy Schubert                             int expect_public_reseed,
188e0c4386eSCy Schubert                             int expect_private_reseed,
189e0c4386eSCy Schubert                             time_t reseed_when
190e0c4386eSCy Schubert                            )
191e0c4386eSCy Schubert {
192e0c4386eSCy Schubert     time_t before_reseed, after_reseed;
193e0c4386eSCy Schubert     int expected_state = (expect_success ? DRBG_READY : DRBG_ERROR);
194e0c4386eSCy Schubert     unsigned int primary_reseed, public_reseed, private_reseed;
195e0c4386eSCy Schubert     unsigned char dummy[RANDOM_SIZE];
196e0c4386eSCy Schubert 
197e0c4386eSCy Schubert     if (public_random == NULL)
198e0c4386eSCy Schubert         public_random = dummy;
199e0c4386eSCy Schubert 
200e0c4386eSCy Schubert     if (private_random == NULL)
201e0c4386eSCy Schubert         private_random = dummy;
202e0c4386eSCy Schubert 
203e0c4386eSCy Schubert     /*
204e0c4386eSCy Schubert      * step 1: check preconditions
205e0c4386eSCy Schubert      */
206e0c4386eSCy Schubert 
207e0c4386eSCy Schubert     /* Test whether seed propagation is enabled */
208e0c4386eSCy Schubert     if (!TEST_int_ne(primary_reseed = reseed_counter(primary), 0)
209e0c4386eSCy Schubert         || !TEST_int_ne(public_reseed = reseed_counter(public), 0)
210e0c4386eSCy Schubert         || !TEST_int_ne(private_reseed = reseed_counter(private), 0))
211e0c4386eSCy Schubert         return 0;
212e0c4386eSCy Schubert 
213e0c4386eSCy Schubert     /*
214e0c4386eSCy Schubert      * step 2: generate random output
215e0c4386eSCy Schubert      */
216e0c4386eSCy Schubert 
217e0c4386eSCy Schubert     if (reseed_when == 0)
218e0c4386eSCy Schubert         reseed_when = time(NULL);
219e0c4386eSCy Schubert 
220e0c4386eSCy Schubert     /* Generate random output from the public and private DRBG */
221e0c4386eSCy Schubert     before_reseed = expect_primary_reseed == 1 ? reseed_when : 0;
222e0c4386eSCy Schubert     if (!TEST_int_eq(rand_bytes((unsigned char*)public_random,
223e0c4386eSCy Schubert                                 RANDOM_SIZE), expect_success)
224e0c4386eSCy Schubert         || !TEST_int_eq(rand_priv_bytes((unsigned char*) private_random,
225e0c4386eSCy Schubert                                         RANDOM_SIZE), expect_success))
226e0c4386eSCy Schubert         return 0;
227e0c4386eSCy Schubert     after_reseed = time(NULL);
228e0c4386eSCy Schubert 
229e0c4386eSCy Schubert 
230e0c4386eSCy Schubert     /*
231e0c4386eSCy Schubert      * step 3: check postconditions
232e0c4386eSCy Schubert      */
233e0c4386eSCy Schubert 
234e0c4386eSCy Schubert     /* Test whether reseeding succeeded as expected */
235e0c4386eSCy Schubert     if (!TEST_int_eq(state(primary), expected_state)
236e0c4386eSCy Schubert         || !TEST_int_eq(state(public), expected_state)
237e0c4386eSCy Schubert         || !TEST_int_eq(state(private), expected_state))
238e0c4386eSCy Schubert         return 0;
239e0c4386eSCy Schubert 
240e0c4386eSCy Schubert     if (expect_primary_reseed >= 0) {
241e0c4386eSCy Schubert         /* Test whether primary DRBG was reseeded as expected */
242e0c4386eSCy Schubert         if (!TEST_int_ge(reseed_counter(primary), primary_reseed))
243e0c4386eSCy Schubert             return 0;
244e0c4386eSCy Schubert     }
245e0c4386eSCy Schubert 
246e0c4386eSCy Schubert     if (expect_public_reseed >= 0) {
247e0c4386eSCy Schubert         /* Test whether public DRBG was reseeded as expected */
248e0c4386eSCy Schubert         if (!TEST_int_ge(reseed_counter(public), public_reseed)
249e0c4386eSCy Schubert                 || !TEST_uint_ge(reseed_counter(public),
250e0c4386eSCy Schubert                                  reseed_counter(primary)))
251e0c4386eSCy Schubert             return 0;
252e0c4386eSCy Schubert     }
253e0c4386eSCy Schubert 
254e0c4386eSCy Schubert     if (expect_private_reseed >= 0) {
255e0c4386eSCy Schubert         /* Test whether public DRBG was reseeded as expected */
256e0c4386eSCy Schubert         if (!TEST_int_ge(reseed_counter(private), private_reseed)
257e0c4386eSCy Schubert                 || !TEST_uint_ge(reseed_counter(private),
258e0c4386eSCy Schubert                                  reseed_counter(primary)))
259e0c4386eSCy Schubert             return 0;
260e0c4386eSCy Schubert     }
261e0c4386eSCy Schubert 
262e0c4386eSCy Schubert     if (expect_success == 1) {
263e0c4386eSCy Schubert         /* Test whether reseed time of primary DRBG is set correctly */
264e0c4386eSCy Schubert         if (!TEST_time_t_le(before_reseed, reseed_time(primary))
265e0c4386eSCy Schubert             || !TEST_time_t_le(reseed_time(primary), after_reseed))
266e0c4386eSCy Schubert             return 0;
267e0c4386eSCy Schubert 
268e0c4386eSCy Schubert         /* Test whether reseed times of child DRBGs are synchronized with primary */
269e0c4386eSCy Schubert         if (!TEST_time_t_ge(reseed_time(public), reseed_time(primary))
270e0c4386eSCy Schubert             || !TEST_time_t_ge(reseed_time(private), reseed_time(primary)))
271e0c4386eSCy Schubert             return 0;
272e0c4386eSCy Schubert     } else {
273e0c4386eSCy Schubert         ERR_clear_error();
274e0c4386eSCy Schubert     }
275e0c4386eSCy Schubert 
276e0c4386eSCy Schubert     return 1;
277e0c4386eSCy Schubert }
278e0c4386eSCy Schubert 
279e0c4386eSCy Schubert 
280e0c4386eSCy Schubert #if defined(OPENSSL_SYS_UNIX) && !defined(OPENSSL_RAND_SEED_EGD)
281e0c4386eSCy Schubert /* number of children to fork */
282e0c4386eSCy Schubert #define DRBG_FORK_COUNT 9
283e0c4386eSCy Schubert /* two results per child, two for the parent */
284e0c4386eSCy Schubert #define DRBG_FORK_RESULT_COUNT (2 * (DRBG_FORK_COUNT + 1))
285e0c4386eSCy Schubert 
286e0c4386eSCy Schubert typedef struct drbg_fork_result_st {
287e0c4386eSCy Schubert 
288e0c4386eSCy Schubert     unsigned char random[RANDOM_SIZE]; /* random output */
289e0c4386eSCy Schubert 
290e0c4386eSCy Schubert     int pindex;               /* process index (0: parent, 1,2,3...: children)*/
291e0c4386eSCy Schubert     pid_t pid;                /* process id */
292e0c4386eSCy Schubert     int private;              /* true if the private drbg was used */
293e0c4386eSCy Schubert     char name[10];            /* 'parent' resp. 'child 1', 'child 2', ... */
294e0c4386eSCy Schubert } drbg_fork_result;
295e0c4386eSCy Schubert 
296e0c4386eSCy Schubert /*
297e0c4386eSCy Schubert  * Sort the drbg_fork_result entries in lexicographical order
298e0c4386eSCy Schubert  *
299e0c4386eSCy Schubert  * This simplifies finding duplicate random output and makes
300e0c4386eSCy Schubert  * the printout in case of an error more readable.
301e0c4386eSCy Schubert  */
compare_drbg_fork_result(const void * left,const void * right)302e0c4386eSCy Schubert static int compare_drbg_fork_result(const void * left, const void * right)
303e0c4386eSCy Schubert {
304e0c4386eSCy Schubert     int result;
305e0c4386eSCy Schubert     const drbg_fork_result *l = left;
306e0c4386eSCy Schubert     const drbg_fork_result *r = right;
307e0c4386eSCy Schubert 
308e0c4386eSCy Schubert     /* separate public and private results */
309e0c4386eSCy Schubert     result = l->private - r->private;
310e0c4386eSCy Schubert 
311e0c4386eSCy Schubert     if (result == 0)
312e0c4386eSCy Schubert         result = memcmp(l->random, r->random, RANDOM_SIZE);
313e0c4386eSCy Schubert 
314e0c4386eSCy Schubert     if (result == 0)
315e0c4386eSCy Schubert         result = l->pindex - r->pindex;
316e0c4386eSCy Schubert 
317e0c4386eSCy Schubert     return result;
318e0c4386eSCy Schubert }
319e0c4386eSCy Schubert 
320e0c4386eSCy Schubert /*
321e0c4386eSCy Schubert  * Sort two-byte chunks of random data
322e0c4386eSCy Schubert  *
323e0c4386eSCy Schubert  * Used for finding collisions in two-byte chunks
324e0c4386eSCy Schubert  */
compare_rand_chunk(const void * left,const void * right)325e0c4386eSCy Schubert static int compare_rand_chunk(const void * left, const void * right)
326e0c4386eSCy Schubert {
327e0c4386eSCy Schubert     return memcmp(left, right, 2);
328e0c4386eSCy Schubert }
329e0c4386eSCy Schubert 
330e0c4386eSCy Schubert /*
331e0c4386eSCy Schubert  * Test whether primary, public and private DRBG are reseeded
332e0c4386eSCy Schubert  * in the child after forking the process. Collect the random
333e0c4386eSCy Schubert  * output of the public and private DRBG and send it back to
334e0c4386eSCy Schubert  * the parent process.
335e0c4386eSCy Schubert  */
test_drbg_reseed_in_child(EVP_RAND_CTX * primary,EVP_RAND_CTX * public,EVP_RAND_CTX * private,drbg_fork_result result[2])336e0c4386eSCy Schubert static int test_drbg_reseed_in_child(EVP_RAND_CTX *primary,
337e0c4386eSCy Schubert                                      EVP_RAND_CTX *public,
338e0c4386eSCy Schubert                                      EVP_RAND_CTX *private,
339e0c4386eSCy Schubert                                      drbg_fork_result result[2])
340e0c4386eSCy Schubert {
341e0c4386eSCy Schubert     int rv = 0, status;
342e0c4386eSCy Schubert     int fd[2];
343e0c4386eSCy Schubert     pid_t pid;
344e0c4386eSCy Schubert     unsigned char random[2 * RANDOM_SIZE];
345e0c4386eSCy Schubert 
346e0c4386eSCy Schubert     if (!TEST_int_ge(pipe(fd), 0))
347e0c4386eSCy Schubert         return 0;
348e0c4386eSCy Schubert 
349e0c4386eSCy Schubert     if (!TEST_int_ge(pid = fork(), 0)) {
350e0c4386eSCy Schubert         close(fd[0]);
351e0c4386eSCy Schubert         close(fd[1]);
352e0c4386eSCy Schubert         return 0;
353e0c4386eSCy Schubert     } else if (pid > 0) {
354e0c4386eSCy Schubert 
355e0c4386eSCy Schubert         /* I'm the parent; close the write end */
356e0c4386eSCy Schubert         close(fd[1]);
357e0c4386eSCy Schubert 
358e0c4386eSCy Schubert         /* wait for children to terminate and collect their random output */
359e0c4386eSCy Schubert         if (TEST_int_eq(waitpid(pid, &status, 0), pid)
360e0c4386eSCy Schubert             && TEST_int_eq(status, 0)
361e0c4386eSCy Schubert             && TEST_true(read(fd[0], &random[0], sizeof(random))
362e0c4386eSCy Schubert                           == sizeof(random))) {
363e0c4386eSCy Schubert 
364e0c4386eSCy Schubert             /* random output of public drbg */
365e0c4386eSCy Schubert             result[0].pid = pid;
366e0c4386eSCy Schubert             result[0].private = 0;
367e0c4386eSCy Schubert             memcpy(result[0].random, &random[0], RANDOM_SIZE);
368e0c4386eSCy Schubert 
369e0c4386eSCy Schubert             /* random output of private drbg */
370e0c4386eSCy Schubert             result[1].pid = pid;
371e0c4386eSCy Schubert             result[1].private = 1;
372e0c4386eSCy Schubert             memcpy(result[1].random, &random[RANDOM_SIZE], RANDOM_SIZE);
373e0c4386eSCy Schubert 
374e0c4386eSCy Schubert             rv = 1;
375e0c4386eSCy Schubert         }
376e0c4386eSCy Schubert 
377e0c4386eSCy Schubert         /* close the read end */
378e0c4386eSCy Schubert         close(fd[0]);
379e0c4386eSCy Schubert 
380e0c4386eSCy Schubert         return rv;
381e0c4386eSCy Schubert 
382e0c4386eSCy Schubert     } else {
383e0c4386eSCy Schubert 
384e0c4386eSCy Schubert         /* I'm the child; close the read end */
385e0c4386eSCy Schubert         close(fd[0]);
386e0c4386eSCy Schubert 
387e0c4386eSCy Schubert         /* check whether all three DRBGs reseed and send output to parent */
388e0c4386eSCy Schubert         if (TEST_true(test_drbg_reseed(1, primary, public, private,
389e0c4386eSCy Schubert                                         &random[0], &random[RANDOM_SIZE],
390e0c4386eSCy Schubert                                        1, 1, 1, 0))
391e0c4386eSCy Schubert             && TEST_true(write(fd[1], random, sizeof(random))
392e0c4386eSCy Schubert                          == sizeof(random))) {
393e0c4386eSCy Schubert 
394e0c4386eSCy Schubert             rv = 1;
395e0c4386eSCy Schubert         }
396e0c4386eSCy Schubert 
397e0c4386eSCy Schubert         /* close the write end */
398e0c4386eSCy Schubert         close(fd[1]);
399e0c4386eSCy Schubert 
400e0c4386eSCy Schubert         /* convert boolean to exit code */
401e0c4386eSCy Schubert         exit(rv == 0);
402e0c4386eSCy Schubert     }
403e0c4386eSCy Schubert }
404e0c4386eSCy Schubert 
test_rand_reseed_on_fork(EVP_RAND_CTX * primary,EVP_RAND_CTX * public,EVP_RAND_CTX * private)405e0c4386eSCy Schubert static int test_rand_reseed_on_fork(EVP_RAND_CTX *primary,
406e0c4386eSCy Schubert                                     EVP_RAND_CTX *public,
407e0c4386eSCy Schubert                                     EVP_RAND_CTX *private)
408e0c4386eSCy Schubert {
409e0c4386eSCy Schubert     unsigned int i;
410e0c4386eSCy Schubert     pid_t pid = getpid();
411e0c4386eSCy Schubert     int verbose = (getenv("V") != NULL);
412e0c4386eSCy Schubert     int success = 1;
413e0c4386eSCy Schubert     int duplicate[2] = {0, 0};
414e0c4386eSCy Schubert     unsigned char random[2 * RANDOM_SIZE];
415e0c4386eSCy Schubert     unsigned char sample[DRBG_FORK_RESULT_COUNT * RANDOM_SIZE];
416e0c4386eSCy Schubert     unsigned char *psample = &sample[0];
417e0c4386eSCy Schubert     drbg_fork_result result[DRBG_FORK_RESULT_COUNT];
418e0c4386eSCy Schubert     drbg_fork_result *presult = &result[2];
419e0c4386eSCy Schubert 
420e0c4386eSCy Schubert     memset(&result,  0, sizeof(result));
421e0c4386eSCy Schubert 
422e0c4386eSCy Schubert     for (i = 1 ; i <= DRBG_FORK_COUNT ; ++i) {
423e0c4386eSCy Schubert 
424e0c4386eSCy Schubert         presult[0].pindex = presult[1].pindex = i;
425e0c4386eSCy Schubert 
426*0d0c8621SEnji Cooper         BIO_snprintf(presult[0].name, sizeof(presult[0].name), "child %d", i);
427e0c4386eSCy Schubert         strcpy(presult[1].name, presult[0].name);
428e0c4386eSCy Schubert 
429e0c4386eSCy Schubert         /* collect the random output of the children */
430e0c4386eSCy Schubert         if (!TEST_true(test_drbg_reseed_in_child(primary,
431e0c4386eSCy Schubert                                                  public,
432e0c4386eSCy Schubert                                                  private,
433e0c4386eSCy Schubert                                                  presult)))
434e0c4386eSCy Schubert             return 0;
435e0c4386eSCy Schubert 
436e0c4386eSCy Schubert         presult += 2;
437e0c4386eSCy Schubert     }
438e0c4386eSCy Schubert 
439e0c4386eSCy Schubert     /* collect the random output of the parent */
440e0c4386eSCy Schubert     if (!TEST_true(test_drbg_reseed(1,
441e0c4386eSCy Schubert                                     primary, public, private,
442e0c4386eSCy Schubert                                     &random[0], &random[RANDOM_SIZE],
443e0c4386eSCy Schubert                                     0, 0, 0, 0)))
444e0c4386eSCy Schubert         return 0;
445e0c4386eSCy Schubert 
446e0c4386eSCy Schubert     strcpy(result[0].name, "parent");
447e0c4386eSCy Schubert     strcpy(result[1].name, "parent");
448e0c4386eSCy Schubert 
449e0c4386eSCy Schubert     /* output of public drbg */
450e0c4386eSCy Schubert     result[0].pid = pid;
451e0c4386eSCy Schubert     result[0].private = 0;
452e0c4386eSCy Schubert     memcpy(result[0].random, &random[0], RANDOM_SIZE);
453e0c4386eSCy Schubert 
454e0c4386eSCy Schubert     /* output of private drbg */
455e0c4386eSCy Schubert     result[1].pid = pid;
456e0c4386eSCy Schubert     result[1].private = 1;
457e0c4386eSCy Schubert     memcpy(result[1].random, &random[RANDOM_SIZE], RANDOM_SIZE);
458e0c4386eSCy Schubert 
459e0c4386eSCy Schubert     /* collect all sampled random data in a single buffer */
460e0c4386eSCy Schubert     for (i = 0 ; i < DRBG_FORK_RESULT_COUNT ; ++i) {
461e0c4386eSCy Schubert         memcpy(psample, &result[i].random[0], RANDOM_SIZE);
462e0c4386eSCy Schubert         psample += RANDOM_SIZE;
463e0c4386eSCy Schubert     }
464e0c4386eSCy Schubert 
465e0c4386eSCy Schubert     /* sort the results... */
466e0c4386eSCy Schubert     qsort(result, DRBG_FORK_RESULT_COUNT, sizeof(drbg_fork_result),
467e0c4386eSCy Schubert           compare_drbg_fork_result);
468e0c4386eSCy Schubert 
469e0c4386eSCy Schubert     /* ...and count duplicate prefixes by looking at the first byte only */
470e0c4386eSCy Schubert     for (i = 1 ; i < DRBG_FORK_RESULT_COUNT ; ++i) {
471e0c4386eSCy Schubert         if (result[i].random[0] == result[i-1].random[0]) {
472e0c4386eSCy Schubert             /* count public and private duplicates separately */
473e0c4386eSCy Schubert             ++duplicate[result[i].private];
474e0c4386eSCy Schubert         }
475e0c4386eSCy Schubert     }
476e0c4386eSCy Schubert 
477e0c4386eSCy Schubert     if (duplicate[0] >= DRBG_FORK_COUNT - 1) {
478e0c4386eSCy Schubert         /* just too many duplicates to be a coincidence */
479e0c4386eSCy Schubert         TEST_note("ERROR: %d duplicate prefixes in public random output", duplicate[0]);
480e0c4386eSCy Schubert         success = 0;
481e0c4386eSCy Schubert     }
482e0c4386eSCy Schubert 
483e0c4386eSCy Schubert     if (duplicate[1] >= DRBG_FORK_COUNT - 1) {
484e0c4386eSCy Schubert         /* just too many duplicates to be a coincidence */
485e0c4386eSCy Schubert         TEST_note("ERROR: %d duplicate prefixes in private random output", duplicate[1]);
486e0c4386eSCy Schubert         success = 0;
487e0c4386eSCy Schubert     }
488e0c4386eSCy Schubert 
489e0c4386eSCy Schubert     duplicate[0] = 0;
490e0c4386eSCy Schubert 
491e0c4386eSCy Schubert     /* sort the two-byte chunks... */
492e0c4386eSCy Schubert     qsort(sample, sizeof(sample)/2, 2, compare_rand_chunk);
493e0c4386eSCy Schubert 
494e0c4386eSCy Schubert     /* ...and count duplicate chunks */
495e0c4386eSCy Schubert     for (i = 2, psample = sample + 2 ; i < sizeof(sample) ; i += 2, psample += 2) {
496e0c4386eSCy Schubert         if (compare_rand_chunk(psample - 2, psample) == 0)
497e0c4386eSCy Schubert             ++duplicate[0];
498e0c4386eSCy Schubert     }
499e0c4386eSCy Schubert 
500e0c4386eSCy Schubert     if (duplicate[0] >= DRBG_FORK_COUNT - 1) {
501e0c4386eSCy Schubert         /* just too many duplicates to be a coincidence */
502e0c4386eSCy Schubert         TEST_note("ERROR: %d duplicate chunks in random output", duplicate[0]);
503e0c4386eSCy Schubert         success = 0;
504e0c4386eSCy Schubert     }
505e0c4386eSCy Schubert 
506e0c4386eSCy Schubert     if (verbose || !success) {
507e0c4386eSCy Schubert 
508e0c4386eSCy Schubert         for (i = 0 ; i < DRBG_FORK_RESULT_COUNT ; ++i) {
509e0c4386eSCy Schubert             char *rand_hex = OPENSSL_buf2hexstr(result[i].random, RANDOM_SIZE);
510e0c4386eSCy Schubert 
511e0c4386eSCy Schubert             TEST_note("    random: %s, pid: %d (%s, %s)",
512e0c4386eSCy Schubert                       rand_hex,
513e0c4386eSCy Schubert                       result[i].pid,
514e0c4386eSCy Schubert                       result[i].name,
515e0c4386eSCy Schubert                       result[i].private ? "private" : "public"
516e0c4386eSCy Schubert                       );
517e0c4386eSCy Schubert 
518e0c4386eSCy Schubert             OPENSSL_free(rand_hex);
519e0c4386eSCy Schubert         }
520e0c4386eSCy Schubert     }
521e0c4386eSCy Schubert 
522e0c4386eSCy Schubert     return success;
523e0c4386eSCy Schubert }
524e0c4386eSCy Schubert 
test_rand_fork_safety(int i)525e0c4386eSCy Schubert static int test_rand_fork_safety(int i)
526e0c4386eSCy Schubert {
527e0c4386eSCy Schubert     int success = 1;
528e0c4386eSCy Schubert     unsigned char random[1];
529e0c4386eSCy Schubert     EVP_RAND_CTX *primary, *public, *private;
530e0c4386eSCy Schubert 
531e0c4386eSCy Schubert     /* All three DRBGs should be non-null */
532e0c4386eSCy Schubert     if (!TEST_ptr(primary = RAND_get0_primary(NULL))
533e0c4386eSCy Schubert         || !TEST_ptr(public = RAND_get0_public(NULL))
534e0c4386eSCy Schubert         || !TEST_ptr(private = RAND_get0_private(NULL)))
535e0c4386eSCy Schubert         return 0;
536e0c4386eSCy Schubert 
537e0c4386eSCy Schubert     /* run the actual test */
538e0c4386eSCy Schubert     if (!TEST_true(test_rand_reseed_on_fork(primary, public, private)))
539e0c4386eSCy Schubert         success = 0;
540e0c4386eSCy Schubert 
541e0c4386eSCy Schubert     /* request a single byte from each of the DRBGs before the next run */
542e0c4386eSCy Schubert     if (!TEST_int_gt(RAND_bytes(random, 1), 0) || !TEST_int_gt(RAND_priv_bytes(random, 1), 0))
543e0c4386eSCy Schubert         success = 0;
544e0c4386eSCy Schubert 
545e0c4386eSCy Schubert     return success;
546e0c4386eSCy Schubert }
547e0c4386eSCy Schubert #endif
548e0c4386eSCy Schubert 
549e0c4386eSCy Schubert /*
550e0c4386eSCy Schubert  * Test whether the default rand_method (RAND_OpenSSL()) is
551e0c4386eSCy Schubert  * setup correctly, in particular whether reseeding works
552e0c4386eSCy Schubert  * as designed.
553e0c4386eSCy Schubert  */
test_rand_reseed(void)554e0c4386eSCy Schubert static int test_rand_reseed(void)
555e0c4386eSCy Schubert {
556e0c4386eSCy Schubert     EVP_RAND_CTX *primary, *public, *private;
557e0c4386eSCy Schubert     unsigned char rand_add_buf[256];
558e0c4386eSCy Schubert     int rv = 0;
559e0c4386eSCy Schubert     time_t before_reseed;
560e0c4386eSCy Schubert 
561e0c4386eSCy Schubert     if (using_fips_rng())
562e0c4386eSCy Schubert         return TEST_skip("CRNGT cannot be disabled");
563e0c4386eSCy Schubert 
564e0c4386eSCy Schubert #ifndef OPENSSL_NO_DEPRECATED_3_0
565e0c4386eSCy Schubert     /* Check whether RAND_OpenSSL() is the default method */
566e0c4386eSCy Schubert     if (!TEST_ptr_eq(RAND_get_rand_method(), RAND_OpenSSL()))
567e0c4386eSCy Schubert         return 0;
568e0c4386eSCy Schubert #endif
569e0c4386eSCy Schubert 
570e0c4386eSCy Schubert     /* All three DRBGs should be non-null */
571e0c4386eSCy Schubert     if (!TEST_ptr(primary = RAND_get0_primary(NULL))
572e0c4386eSCy Schubert         || !TEST_ptr(public = RAND_get0_public(NULL))
573e0c4386eSCy Schubert         || !TEST_ptr(private = RAND_get0_private(NULL)))
574e0c4386eSCy Schubert         return 0;
575e0c4386eSCy Schubert 
576e0c4386eSCy Schubert     /* There should be three distinct DRBGs, two of them chained to primary */
577e0c4386eSCy Schubert     if (!TEST_ptr_ne(public, private)
578e0c4386eSCy Schubert         || !TEST_ptr_ne(public, primary)
579e0c4386eSCy Schubert         || !TEST_ptr_ne(private, primary)
580e0c4386eSCy Schubert         || !TEST_ptr_eq(prov_rand(public)->parent, prov_rand(primary))
581e0c4386eSCy Schubert         || !TEST_ptr_eq(prov_rand(private)->parent, prov_rand(primary)))
582e0c4386eSCy Schubert         return 0;
583e0c4386eSCy Schubert 
584e0c4386eSCy Schubert     /* Disable CRNG testing for the primary DRBG */
585e0c4386eSCy Schubert     if (!TEST_true(disable_crngt(primary)))
586e0c4386eSCy Schubert         return 0;
587e0c4386eSCy Schubert 
588e0c4386eSCy Schubert     /* uninstantiate the three global DRBGs */
589e0c4386eSCy Schubert     EVP_RAND_uninstantiate(primary);
590e0c4386eSCy Schubert     EVP_RAND_uninstantiate(private);
591e0c4386eSCy Schubert     EVP_RAND_uninstantiate(public);
592e0c4386eSCy Schubert 
593e0c4386eSCy Schubert     /*
594e0c4386eSCy Schubert      * Test initial seeding of shared DRBGs
595e0c4386eSCy Schubert      */
596e0c4386eSCy Schubert     if (!TEST_true(test_drbg_reseed(1,
597e0c4386eSCy Schubert                                     primary, public, private,
598e0c4386eSCy Schubert                                     NULL, NULL,
599e0c4386eSCy Schubert                                     1, 1, 1, 0)))
600e0c4386eSCy Schubert         goto error;
601e0c4386eSCy Schubert 
602e0c4386eSCy Schubert     /*
603e0c4386eSCy Schubert      * Test initial state of shared DRBGs
604e0c4386eSCy Schubert      */
605e0c4386eSCy Schubert     if (!TEST_true(test_drbg_reseed(1,
606e0c4386eSCy Schubert                                     primary, public, private,
607e0c4386eSCy Schubert                                     NULL, NULL,
608e0c4386eSCy Schubert                                     0, 0, 0, 0)))
609e0c4386eSCy Schubert         goto error;
610e0c4386eSCy Schubert 
611e0c4386eSCy Schubert     /*
612e0c4386eSCy Schubert      * Test whether the public and private DRBG are both reseeded when their
613e0c4386eSCy Schubert      * reseed counters differ from the primary's reseed counter.
614e0c4386eSCy Schubert      */
615e0c4386eSCy Schubert     inc_reseed_counter(primary);
616e0c4386eSCy Schubert     if (!TEST_true(test_drbg_reseed(1,
617e0c4386eSCy Schubert                                     primary, public, private,
618e0c4386eSCy Schubert                                     NULL, NULL,
619e0c4386eSCy Schubert                                     0, 1, 1, 0)))
620e0c4386eSCy Schubert         goto error;
621e0c4386eSCy Schubert 
622e0c4386eSCy Schubert     /*
623e0c4386eSCy Schubert      * Test whether the public DRBG is reseeded when its reseed counter differs
624e0c4386eSCy Schubert      * from the primary's reseed counter.
625e0c4386eSCy Schubert      */
626e0c4386eSCy Schubert     inc_reseed_counter(primary);
627e0c4386eSCy Schubert     inc_reseed_counter(private);
628e0c4386eSCy Schubert     if (!TEST_true(test_drbg_reseed(1,
629e0c4386eSCy Schubert                                     primary, public, private,
630e0c4386eSCy Schubert                                     NULL, NULL,
631e0c4386eSCy Schubert                                     0, 1, 0, 0)))
632e0c4386eSCy Schubert         goto error;
633e0c4386eSCy Schubert 
634e0c4386eSCy Schubert     /*
635e0c4386eSCy Schubert      * Test whether the private DRBG is reseeded when its reseed counter differs
636e0c4386eSCy Schubert      * from the primary's reseed counter.
637e0c4386eSCy Schubert      */
638e0c4386eSCy Schubert     inc_reseed_counter(primary);
639e0c4386eSCy Schubert     inc_reseed_counter(public);
640e0c4386eSCy Schubert     if (!TEST_true(test_drbg_reseed(1,
641e0c4386eSCy Schubert                                     primary, public, private,
642e0c4386eSCy Schubert                                     NULL, NULL,
643e0c4386eSCy Schubert                                     0, 0, 1, 0)))
644e0c4386eSCy Schubert         goto error;
645e0c4386eSCy Schubert 
646e0c4386eSCy Schubert     /* fill 'randomness' buffer with some arbitrary data */
647e0c4386eSCy Schubert     memset(rand_add_buf, 'r', sizeof(rand_add_buf));
648e0c4386eSCy Schubert 
649e0c4386eSCy Schubert     /*
650e0c4386eSCy Schubert      * Test whether all three DRBGs are reseeded by RAND_add().
651e0c4386eSCy Schubert      * The before_reseed time has to be measured here and passed into the
652e0c4386eSCy Schubert      * test_drbg_reseed() test, because the primary DRBG gets already reseeded
653e0c4386eSCy Schubert      * in RAND_add(), whence the check for the condition
654e0c4386eSCy Schubert      * before_reseed <= reseed_time(primary) will fail if the time value happens
655e0c4386eSCy Schubert      * to increase between the RAND_add() and the test_drbg_reseed() call.
656e0c4386eSCy Schubert      */
657e0c4386eSCy Schubert     before_reseed = time(NULL);
658e0c4386eSCy Schubert     RAND_add(rand_add_buf, sizeof(rand_add_buf), sizeof(rand_add_buf));
659e0c4386eSCy Schubert     if (!TEST_true(test_drbg_reseed(1,
660e0c4386eSCy Schubert                                     primary, public, private,
661e0c4386eSCy Schubert                                     NULL, NULL,
662e0c4386eSCy Schubert                                     1, 1, 1,
663e0c4386eSCy Schubert                                     before_reseed)))
664e0c4386eSCy Schubert         goto error;
665e0c4386eSCy Schubert 
666e0c4386eSCy Schubert     rv = 1;
667e0c4386eSCy Schubert 
668e0c4386eSCy Schubert error:
669e0c4386eSCy Schubert    return rv;
670e0c4386eSCy Schubert }
671e0c4386eSCy Schubert 
672e0c4386eSCy Schubert #if defined(OPENSSL_THREADS)
673e0c4386eSCy Schubert static int multi_thread_rand_bytes_succeeded = 1;
674e0c4386eSCy Schubert static int multi_thread_rand_priv_bytes_succeeded = 1;
675e0c4386eSCy Schubert 
set_reseed_time_interval(EVP_RAND_CTX * drbg,int t)676e0c4386eSCy Schubert static int set_reseed_time_interval(EVP_RAND_CTX *drbg, int t)
677e0c4386eSCy Schubert {
678e0c4386eSCy Schubert     OSSL_PARAM params[2];
679e0c4386eSCy Schubert 
680e0c4386eSCy Schubert     params[0] = OSSL_PARAM_construct_int(OSSL_DRBG_PARAM_RESEED_TIME_INTERVAL,
681e0c4386eSCy Schubert                                          &t);
682e0c4386eSCy Schubert     params[1] = OSSL_PARAM_construct_end();
683e0c4386eSCy Schubert     return EVP_RAND_CTX_set_params(drbg, params);
684e0c4386eSCy Schubert }
685e0c4386eSCy Schubert 
run_multi_thread_test(void)686e0c4386eSCy Schubert static void run_multi_thread_test(void)
687e0c4386eSCy Schubert {
688e0c4386eSCy Schubert     unsigned char buf[256];
689e0c4386eSCy Schubert     time_t start = time(NULL);
690e0c4386eSCy Schubert     EVP_RAND_CTX *public = NULL, *private = NULL;
691e0c4386eSCy Schubert 
692e0c4386eSCy Schubert     if (!TEST_ptr(public = RAND_get0_public(NULL))
693e0c4386eSCy Schubert             || !TEST_ptr(private = RAND_get0_private(NULL))
694e0c4386eSCy Schubert             || !TEST_true(set_reseed_time_interval(private, 1))
695e0c4386eSCy Schubert             || !TEST_true(set_reseed_time_interval(public, 1))) {
696e0c4386eSCy Schubert         multi_thread_rand_bytes_succeeded = 0;
697e0c4386eSCy Schubert         return;
698e0c4386eSCy Schubert     }
699e0c4386eSCy Schubert 
700e0c4386eSCy Schubert     do {
701e0c4386eSCy Schubert         if (rand_bytes(buf, sizeof(buf)) <= 0)
702e0c4386eSCy Schubert             multi_thread_rand_bytes_succeeded = 0;
703e0c4386eSCy Schubert         if (rand_priv_bytes(buf, sizeof(buf)) <= 0)
704e0c4386eSCy Schubert             multi_thread_rand_priv_bytes_succeeded = 0;
705e0c4386eSCy Schubert     }
706e0c4386eSCy Schubert     while (time(NULL) - start < 5);
707e0c4386eSCy Schubert }
708e0c4386eSCy Schubert 
709e0c4386eSCy Schubert # if defined(OPENSSL_SYS_WINDOWS)
710e0c4386eSCy Schubert 
711e0c4386eSCy Schubert typedef HANDLE thread_t;
712e0c4386eSCy Schubert 
thread_run(LPVOID arg)713e0c4386eSCy Schubert static DWORD WINAPI thread_run(LPVOID arg)
714e0c4386eSCy Schubert {
715e0c4386eSCy Schubert     run_multi_thread_test();
716e0c4386eSCy Schubert     /*
717e0c4386eSCy Schubert      * Because we're linking with a static library, we must stop each
718e0c4386eSCy Schubert      * thread explicitly, or so says OPENSSL_thread_stop(3)
719e0c4386eSCy Schubert      */
720e0c4386eSCy Schubert     OPENSSL_thread_stop();
721e0c4386eSCy Schubert     return 0;
722e0c4386eSCy Schubert }
723e0c4386eSCy Schubert 
run_thread(thread_t * t)724e0c4386eSCy Schubert static int run_thread(thread_t *t)
725e0c4386eSCy Schubert {
726e0c4386eSCy Schubert     *t = CreateThread(NULL, 0, thread_run, NULL, 0, NULL);
727e0c4386eSCy Schubert     return *t != NULL;
728e0c4386eSCy Schubert }
729e0c4386eSCy Schubert 
wait_for_thread(thread_t thread)730e0c4386eSCy Schubert static int wait_for_thread(thread_t thread)
731e0c4386eSCy Schubert {
732e0c4386eSCy Schubert     return WaitForSingleObject(thread, INFINITE) == 0;
733e0c4386eSCy Schubert }
734e0c4386eSCy Schubert 
735e0c4386eSCy Schubert # else
736e0c4386eSCy Schubert 
737e0c4386eSCy Schubert typedef pthread_t thread_t;
738e0c4386eSCy Schubert 
thread_run(void * arg)739e0c4386eSCy Schubert static void *thread_run(void *arg)
740e0c4386eSCy Schubert {
741e0c4386eSCy Schubert     run_multi_thread_test();
742e0c4386eSCy Schubert     /*
743e0c4386eSCy Schubert      * Because we're linking with a static library, we must stop each
744e0c4386eSCy Schubert      * thread explicitly, or so says OPENSSL_thread_stop(3)
745e0c4386eSCy Schubert      */
746e0c4386eSCy Schubert     OPENSSL_thread_stop();
747e0c4386eSCy Schubert     return NULL;
748e0c4386eSCy Schubert }
749e0c4386eSCy Schubert 
run_thread(thread_t * t)750e0c4386eSCy Schubert static int run_thread(thread_t *t)
751e0c4386eSCy Schubert {
752e0c4386eSCy Schubert     return pthread_create(t, NULL, thread_run, NULL) == 0;
753e0c4386eSCy Schubert }
754e0c4386eSCy Schubert 
wait_for_thread(thread_t thread)755e0c4386eSCy Schubert static int wait_for_thread(thread_t thread)
756e0c4386eSCy Schubert {
757e0c4386eSCy Schubert     return pthread_join(thread, NULL) == 0;
758e0c4386eSCy Schubert }
759e0c4386eSCy Schubert 
760e0c4386eSCy Schubert # endif
761e0c4386eSCy Schubert 
762e0c4386eSCy Schubert /*
763e0c4386eSCy Schubert  * The main thread will also run the test, so we'll have THREADS+1 parallel
764e0c4386eSCy Schubert  * tests running
765e0c4386eSCy Schubert  */
766e0c4386eSCy Schubert # define THREADS 3
767e0c4386eSCy Schubert 
test_multi_thread(void)768e0c4386eSCy Schubert static int test_multi_thread(void)
769e0c4386eSCy Schubert {
770e0c4386eSCy Schubert     thread_t t[THREADS];
771e0c4386eSCy Schubert     int i;
772e0c4386eSCy Schubert 
773e0c4386eSCy Schubert     for (i = 0; i < THREADS; i++)
774e0c4386eSCy Schubert         run_thread(&t[i]);
775e0c4386eSCy Schubert     run_multi_thread_test();
776e0c4386eSCy Schubert     for (i = 0; i < THREADS; i++)
777e0c4386eSCy Schubert         wait_for_thread(t[i]);
778e0c4386eSCy Schubert 
779e0c4386eSCy Schubert     if (!TEST_true(multi_thread_rand_bytes_succeeded))
780e0c4386eSCy Schubert         return 0;
781e0c4386eSCy Schubert     if (!TEST_true(multi_thread_rand_priv_bytes_succeeded))
782e0c4386eSCy Schubert         return 0;
783e0c4386eSCy Schubert 
784e0c4386eSCy Schubert     return 1;
785e0c4386eSCy Schubert }
786e0c4386eSCy Schubert #endif
787e0c4386eSCy Schubert 
new_drbg(EVP_RAND_CTX * parent)788e0c4386eSCy Schubert static EVP_RAND_CTX *new_drbg(EVP_RAND_CTX *parent)
789e0c4386eSCy Schubert {
790e0c4386eSCy Schubert     OSSL_PARAM params[2];
791e0c4386eSCy Schubert     EVP_RAND *rand = NULL;
792e0c4386eSCy Schubert     EVP_RAND_CTX *drbg = NULL;
793e0c4386eSCy Schubert 
794e0c4386eSCy Schubert     params[0] = OSSL_PARAM_construct_utf8_string(OSSL_DRBG_PARAM_CIPHER,
795e0c4386eSCy Schubert                                                  "AES-256-CTR", 0);
796e0c4386eSCy Schubert     params[1] = OSSL_PARAM_construct_end();
797e0c4386eSCy Schubert 
798e0c4386eSCy Schubert     if (!TEST_ptr(rand = EVP_RAND_fetch(NULL, "CTR-DRBG", NULL))
799e0c4386eSCy Schubert             || !TEST_ptr(drbg = EVP_RAND_CTX_new(rand, parent))
800e0c4386eSCy Schubert             || !TEST_true(EVP_RAND_CTX_set_params(drbg, params))) {
801e0c4386eSCy Schubert         EVP_RAND_CTX_free(drbg);
802e0c4386eSCy Schubert         drbg = NULL;
803e0c4386eSCy Schubert     }
804e0c4386eSCy Schubert     EVP_RAND_free(rand);
805e0c4386eSCy Schubert     return drbg;
806e0c4386eSCy Schubert }
807e0c4386eSCy Schubert 
test_rand_prediction_resistance(void)808e0c4386eSCy Schubert static int test_rand_prediction_resistance(void)
809e0c4386eSCy Schubert {
810e0c4386eSCy Schubert     EVP_RAND_CTX *x = NULL, *y = NULL, *z = NULL;
811e0c4386eSCy Schubert     unsigned char buf1[51], buf2[sizeof(buf1)];
812e0c4386eSCy Schubert     int ret = 0, xreseed, yreseed, zreseed;
813e0c4386eSCy Schubert 
814e0c4386eSCy Schubert     if (using_fips_rng())
815e0c4386eSCy Schubert         return TEST_skip("CRNGT cannot be disabled");
816e0c4386eSCy Schubert 
817e0c4386eSCy Schubert     /* Initialise a three long DRBG chain */
818e0c4386eSCy Schubert     if (!TEST_ptr(x = new_drbg(NULL))
819e0c4386eSCy Schubert         || !TEST_true(disable_crngt(x))
820e0c4386eSCy Schubert         || !TEST_true(EVP_RAND_instantiate(x, 0, 0, NULL, 0, NULL))
821e0c4386eSCy Schubert         || !TEST_ptr(y = new_drbg(x))
822e0c4386eSCy Schubert         || !TEST_true(EVP_RAND_instantiate(y, 0, 0, NULL, 0, NULL))
823e0c4386eSCy Schubert         || !TEST_ptr(z = new_drbg(y))
824e0c4386eSCy Schubert         || !TEST_true(EVP_RAND_instantiate(z, 0, 0, NULL, 0, NULL)))
825e0c4386eSCy Schubert         goto err;
826e0c4386eSCy Schubert 
827e0c4386eSCy Schubert     /*
828e0c4386eSCy Schubert      * During a normal reseed, only the last DRBG in the chain should
829e0c4386eSCy Schubert      * be reseeded.
830e0c4386eSCy Schubert      */
831e0c4386eSCy Schubert     inc_reseed_counter(y);
832e0c4386eSCy Schubert     xreseed = reseed_counter(x);
833e0c4386eSCy Schubert     yreseed = reseed_counter(y);
834e0c4386eSCy Schubert     zreseed = reseed_counter(z);
835e0c4386eSCy Schubert     if (!TEST_true(EVP_RAND_reseed(z, 0, NULL, 0, NULL, 0))
836e0c4386eSCy Schubert         || !TEST_int_eq(reseed_counter(x), xreseed)
837e0c4386eSCy Schubert         || !TEST_int_eq(reseed_counter(y), yreseed)
838e0c4386eSCy Schubert         || !TEST_int_gt(reseed_counter(z), zreseed))
839e0c4386eSCy Schubert         goto err;
840e0c4386eSCy Schubert 
841e0c4386eSCy Schubert     /*
842e0c4386eSCy Schubert      * When prediction resistance is requested, the request should be
843e0c4386eSCy Schubert      * propagated to the primary, so that the entire DRBG chain reseeds.
844e0c4386eSCy Schubert      */
845e0c4386eSCy Schubert     zreseed = reseed_counter(z);
846e0c4386eSCy Schubert     if (!TEST_true(EVP_RAND_reseed(z, 1, NULL, 0, NULL, 0))
847e0c4386eSCy Schubert         || !TEST_int_gt(reseed_counter(x), xreseed)
848e0c4386eSCy Schubert         || !TEST_int_gt(reseed_counter(y), yreseed)
849e0c4386eSCy Schubert         || !TEST_int_gt(reseed_counter(z), zreseed))
850e0c4386eSCy Schubert         goto err;
851e0c4386eSCy Schubert 
852e0c4386eSCy Schubert     /*
853e0c4386eSCy Schubert      * During a normal generate, only the last DRBG should be reseed */
854e0c4386eSCy Schubert     inc_reseed_counter(y);
855e0c4386eSCy Schubert     xreseed = reseed_counter(x);
856e0c4386eSCy Schubert     yreseed = reseed_counter(y);
857e0c4386eSCy Schubert     zreseed = reseed_counter(z);
858e0c4386eSCy Schubert     if (!TEST_true(EVP_RAND_generate(z, buf1, sizeof(buf1), 0, 0, NULL, 0))
859e0c4386eSCy Schubert         || !TEST_int_eq(reseed_counter(x), xreseed)
860e0c4386eSCy Schubert         || !TEST_int_eq(reseed_counter(y), yreseed)
861e0c4386eSCy Schubert         || !TEST_int_gt(reseed_counter(z), zreseed))
862e0c4386eSCy Schubert         goto err;
863e0c4386eSCy Schubert 
864e0c4386eSCy Schubert     /*
865e0c4386eSCy Schubert      * When a prediction resistant generate is requested, the request
866e0c4386eSCy Schubert      * should be propagated to the primary, reseeding the entire DRBG chain.
867e0c4386eSCy Schubert      */
868e0c4386eSCy Schubert     zreseed = reseed_counter(z);
869e0c4386eSCy Schubert     if (!TEST_true(EVP_RAND_generate(z, buf2, sizeof(buf2), 0, 1, NULL, 0))
870e0c4386eSCy Schubert         || !TEST_int_gt(reseed_counter(x), xreseed)
871e0c4386eSCy Schubert         || !TEST_int_gt(reseed_counter(y), yreseed)
872e0c4386eSCy Schubert         || !TEST_int_gt(reseed_counter(z), zreseed)
873e0c4386eSCy Schubert         || !TEST_mem_ne(buf1, sizeof(buf1), buf2, sizeof(buf2)))
874e0c4386eSCy Schubert         goto err;
875e0c4386eSCy Schubert 
876e0c4386eSCy Schubert     /* Verify that a normal reseed still only reseeds the last DRBG */
877e0c4386eSCy Schubert     inc_reseed_counter(y);
878e0c4386eSCy Schubert     xreseed = reseed_counter(x);
879e0c4386eSCy Schubert     yreseed = reseed_counter(y);
880e0c4386eSCy Schubert     zreseed = reseed_counter(z);
881e0c4386eSCy Schubert     if (!TEST_true(EVP_RAND_reseed(z, 0, NULL, 0, NULL, 0))
882e0c4386eSCy Schubert         || !TEST_int_eq(reseed_counter(x), xreseed)
883e0c4386eSCy Schubert         || !TEST_int_eq(reseed_counter(y), yreseed)
884e0c4386eSCy Schubert         || !TEST_int_gt(reseed_counter(z), zreseed))
885e0c4386eSCy Schubert         goto err;
886e0c4386eSCy Schubert 
887e0c4386eSCy Schubert     ret = 1;
888e0c4386eSCy Schubert err:
889e0c4386eSCy Schubert     EVP_RAND_CTX_free(z);
890e0c4386eSCy Schubert     EVP_RAND_CTX_free(y);
891e0c4386eSCy Schubert     EVP_RAND_CTX_free(x);
892e0c4386eSCy Schubert     return ret;
893e0c4386eSCy Schubert }
894e0c4386eSCy Schubert 
setup_tests(void)895e0c4386eSCy Schubert int setup_tests(void)
896e0c4386eSCy Schubert {
897e0c4386eSCy Schubert     ADD_TEST(test_rand_reseed);
898e0c4386eSCy Schubert #if defined(OPENSSL_SYS_UNIX) && !defined(OPENSSL_RAND_SEED_EGD)
899e0c4386eSCy Schubert     ADD_ALL_TESTS(test_rand_fork_safety, RANDOM_SIZE);
900e0c4386eSCy Schubert #endif
901e0c4386eSCy Schubert     ADD_TEST(test_rand_prediction_resistance);
902e0c4386eSCy Schubert #if defined(OPENSSL_THREADS)
903e0c4386eSCy Schubert     ADD_TEST(test_multi_thread);
904e0c4386eSCy Schubert #endif
905e0c4386eSCy Schubert     return 1;
906e0c4386eSCy Schubert }
907