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