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