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