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