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