]> git.ipfire.org Git - thirdparty/openssl.git/blame - test/drbgtest.c
"foo * bar" should be "foo *bar"
[thirdparty/openssl.git] / test / drbgtest.c
CommitLineData
12fb8c3d 1/*
4333b89f 2 * Copyright 2011-2021 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
0a89ae97
P
10/* We need to use some deprecated APIs */
11#define OPENSSL_SUPPRESS_DEPRECATED
12
12fb8c3d 13#include <string.h>
176db6dc 14#include "internal/nelem.h"
12fb8c3d
RS
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>
706457b7 21#include "../crypto/rand/rand_local.h"
25f2138b 22#include "../include/crypto/rand.h"
924663c3 23#include "../include/crypto/evp.h"
3f078163
P
24#include "../providers/implementations/rands/drbg_local.h"
25#include "../crypto/evp/evp_local.h"
12fb8c3d 26
440bce8f
KR
27#if defined(_WIN32)
28# include <windows.h>
29#endif
30
08073700
RB
31#if defined(__TANDEM)
32# if defined(OPENSSL_TANDEM_FLOSS)
33# include <floss.h(floss_fork)>
34# endif
35#endif
84952925
DMSP
36
37#if defined(OPENSSL_SYS_UNIX)
38# include <sys/types.h>
39# include <sys/wait.h>
40# include <unistd.h>
41#endif
42
12fb8c3d 43#include "testutil.h"
12fb8c3d 44
7d615e21
P
45/*
46 * DRBG generate wrappers
47 */
48static int gen_bytes(EVP_RAND_CTX *drbg, unsigned char *buf, int num)
49{
d994ce12 50#ifndef OPENSSL_NO_DEPRECATED_3_0
7d615e21 51 const RAND_METHOD *meth = RAND_get_rand_method();
12fb8c3d 52
7d615e21
P
53 if (meth != NULL && meth != RAND_OpenSSL()) {
54 if (meth->bytes != NULL)
55 return meth->bytes(buf, num);
56 return -1;
57 }
d994ce12 58#endif
8164d91d 59
7d615e21
P
60 if (drbg != NULL)
61 return EVP_RAND_generate(drbg, buf, num, 0, 0, NULL, 0);
62 return 0;
63}
12fb8c3d 64
7d615e21
P
65static int rand_bytes(unsigned char *buf, int num)
66{
67 return gen_bytes(RAND_get0_public(NULL), buf, num);
68}
8bf36651 69
7d615e21
P
70static int rand_priv_bytes(unsigned char *buf, int num)
71{
72 return gen_bytes(RAND_get0_private(NULL), buf, num);
73}
12fb8c3d 74
09e76c5d
DMSP
75
76/* size of random output generated in test_drbg_reseed() */
77#define RANDOM_SIZE 16
78
3f078163
P
79/*
80 * DRBG query functions
81 */
7d615e21 82static int state(EVP_RAND_CTX *drbg)
3f078163 83{
ed576acd 84 return EVP_RAND_get_state(drbg);
3f078163
P
85}
86
7d615e21 87static unsigned int query_rand_uint(EVP_RAND_CTX *drbg, const char *name)
3f078163
P
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);
e494fac7 93 if (EVP_RAND_CTX_get_params(drbg, params))
3f078163
P
94 return n;
95 return 0;
96}
97
3f078163 98#define DRBG_UINT(name) \
7d615e21 99 static unsigned int name(EVP_RAND_CTX *drbg) \
3f078163
P
100 { \
101 return query_rand_uint(drbg, #name); \
102 }
3f078163
P
103DRBG_UINT(reseed_counter)
104
7d615e21 105static PROV_DRBG *prov_rand(EVP_RAND_CTX *drbg)
d1768e82 106{
7c14d0c1 107 return (PROV_DRBG *)drbg->algctx;
d1768e82
DMSP
108}
109
7d615e21 110static void set_reseed_counter(EVP_RAND_CTX *drbg, unsigned int n)
3f078163
P
111{
112 PROV_DRBG *p = prov_rand(drbg);
113
114 p->reseed_counter = n;
115}
116
7d615e21 117static void inc_reseed_counter(EVP_RAND_CTX *drbg)
3f078163
P
118{
119 set_reseed_counter(drbg, reseed_counter(drbg) + 1);
120}
121
7d615e21 122static time_t reseed_time(EVP_RAND_CTX *drbg)
3f078163
P
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);
e494fac7 128 if (EVP_RAND_CTX_get_params(drbg, params))
3f078163
P
129 return t;
130 return 0;
131}
132
3f078163
P
133/*
134 * When building the FIPS module, it isn't possible to disable the continuous
c91f972c
P
135 * RNG tests. Tests that require this are skipped and this means a detection
136 * mechanism for the FIPS provider being in use.
3f078163 137 */
c91f972c 138static int using_fips_rng(void)
3f078163 139{
c91f972c
P
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;
3f078163
P
152}
153
d69226a3
P
154 /*
155 * Disable CRNG testing if it is enabled.
3f078163
P
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.
d69226a3 159 */
7d615e21 160static int disable_crngt(EVP_RAND_CTX *drbg)
12fb8c3d 161{
12fb8c3d
RS
162 return 1;
163}
164
165/*
7d615e21 166 * Generates random output using rand_bytes() and rand_priv_bytes()
a93ba405
DMSP
167 * and checks whether the three shared DRBGs were reseeded as
168 * expected.
169 *
170 * |expect_success|: expected outcome (as reported by RAND_status())
ce3080e9 171 * |primary|, |public|, |private|: pointers to the three shared DRBGs
09e76c5d 172 * |public_random|, |private_random|: generated random output
a93ba405
DMSP
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
09e76c5d 177 * |reseed_when|: if nonzero, used instead of time(NULL) to set the
2bb1b5dd 178 * |before_reseed| time.
a93ba405
DMSP
179 */
180static int test_drbg_reseed(int expect_success,
7d615e21
P
181 EVP_RAND_CTX *primary,
182 EVP_RAND_CTX *public,
183 EVP_RAND_CTX *private,
09e76c5d
DMSP
184 unsigned char *public_random,
185 unsigned char *private_random,
ce3080e9 186 int expect_primary_reseed,
a93ba405 187 int expect_public_reseed,
2bb1b5dd 188 int expect_private_reseed,
3f078163 189 time_t reseed_when
a93ba405
DMSP
190 )
191{
08a65d96 192 time_t before_reseed, after_reseed;
a93ba405 193 int expected_state = (expect_success ? DRBG_READY : DRBG_ERROR);
ce3080e9 194 unsigned int primary_reseed, public_reseed, private_reseed;
09e76c5d
DMSP
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;
a93ba405
DMSP
202
203 /*
204 * step 1: check preconditions
205 */
206
207 /* Test whether seed propagation is enabled */
ce3080e9 208 if (!TEST_int_ne(primary_reseed = reseed_counter(primary), 0)
3f078163
P
209 || !TEST_int_ne(public_reseed = reseed_counter(public), 0)
210 || !TEST_int_ne(private_reseed = reseed_counter(private), 0))
a93ba405
DMSP
211 return 0;
212
213 /*
214 * step 2: generate random output
215 */
216
3f078163
P
217 if (reseed_when == 0)
218 reseed_when = time(NULL);
2bb1b5dd 219
a93ba405 220 /* Generate random output from the public and private DRBG */
ce3080e9 221 before_reseed = expect_primary_reseed == 1 ? reseed_when : 0;
09e76c5d
DMSP
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))
a93ba405 226 return 0;
08a65d96 227 after_reseed = time(NULL);
a93ba405
DMSP
228
229
230 /*
231 * step 3: check postconditions
232 */
75e2c877 233
a93ba405 234 /* Test whether reseeding succeeded as expected */
7d615e21
P
235 if (!TEST_int_eq(state(primary), expected_state)
236 || !TEST_int_eq(state(public), expected_state)
3f078163 237 || !TEST_int_eq(state(private), expected_state))
75e2c877 238 return 0;
a93ba405 239
ce3080e9
P
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))
a93ba405
DMSP
243 return 0;
244 }
245
246 if (expect_public_reseed >= 0) {
247 /* Test whether public DRBG was reseeded as expected */
3f078163
P
248 if (!TEST_int_ge(reseed_counter(public), public_reseed)
249 || !TEST_uint_ge(reseed_counter(public),
ce3080e9 250 reseed_counter(primary)))
a93ba405
DMSP
251 return 0;
252 }
253
254 if (expect_private_reseed >= 0) {
255 /* Test whether public DRBG was reseeded as expected */
3f078163
P
256 if (!TEST_int_ge(reseed_counter(private), private_reseed)
257 || !TEST_uint_ge(reseed_counter(private),
ce3080e9 258 reseed_counter(primary)))
a93ba405
DMSP
259 return 0;
260 }
261
262 if (expect_success == 1) {
ce3080e9
P
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))
08a65d96
DMSP
266 return 0;
267
ce3080e9
P
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)))
08a65d96 271 return 0;
a93ba405
DMSP
272 } else {
273 ERR_clear_error();
274 }
275
75e2c877
RS
276 return 1;
277}
278
84952925 279
04d07ffb 280#if defined(OPENSSL_SYS_UNIX) && !defined(OPENSSL_RAND_SEED_EGD)
09e76c5d
DMSP
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
84952925 296/*
09e76c5d
DMSP
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.
84952925 301 */
bbaeadb0 302static int compare_drbg_fork_result(const void *left, const void *right)
84952925 303{
09e76c5d
DMSP
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 */
bbaeadb0 325static int compare_rand_chunk(const void *left, const void *right)
09e76c5d
DMSP
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];
84952925 343 pid_t pid;
09e76c5d
DMSP
344 unsigned char random[2 * RANDOM_SIZE];
345
346 if (!TEST_int_ge(pipe(fd), 0))
347 return 0;
84952925 348
09e76c5d
DMSP
349 if (!TEST_int_ge(pid = fork(), 0)) {
350 close(fd[0]);
351 close(fd[1]);
84952925 352 return 0;
09e76c5d
DMSP
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;
84952925 435
09e76c5d 436 presult += 2;
84952925
DMSP
437 }
438
09e76c5d
DMSP
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 */
c2f7614f 542 if (!TEST_int_gt(RAND_bytes(random, 1), 0) || !TEST_int_gt(RAND_priv_bytes(random, 1), 0))
09e76c5d
DMSP
543 success = 0;
544
545 return success;
84952925
DMSP
546}
547#endif
548
a93ba405
DMSP
549/*
550 * Test whether the default rand_method (RAND_OpenSSL()) is
c91f972c 551 * setup correctly, in particular whether reseeding works
a93ba405
DMSP
552 * as designed.
553 */
09e76c5d 554static int test_rand_reseed(void)
a93ba405 555{
7d615e21 556 EVP_RAND_CTX *primary, *public, *private;
a93ba405 557 unsigned char rand_add_buf[256];
3f078163 558 int rv = 0;
2bb1b5dd 559 time_t before_reseed;
a93ba405 560
c91f972c 561 if (using_fips_rng())
3f078163
P
562 return TEST_skip("CRNGT cannot be disabled");
563
d994ce12 564#ifndef OPENSSL_NO_DEPRECATED_3_0
a93ba405
DMSP
565 /* Check whether RAND_OpenSSL() is the default method */
566 if (!TEST_ptr_eq(RAND_get_rand_method(), RAND_OpenSSL()))
567 return 0;
d994ce12 568#endif
a93ba405
DMSP
569
570 /* All three DRBGs should be non-null */
7d615e21
P
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)))
a93ba405
DMSP
574 return 0;
575
ce3080e9 576 /* There should be three distinct DRBGs, two of them chained to primary */
a93ba405 577 if (!TEST_ptr_ne(public, private)
ce3080e9
P
578 || !TEST_ptr_ne(public, primary)
579 || !TEST_ptr_ne(private, primary)
7d615e21
P
580 || !TEST_ptr_eq(prov_rand(public)->parent, prov_rand(primary))
581 || !TEST_ptr_eq(prov_rand(private)->parent, prov_rand(primary)))
a93ba405
DMSP
582 return 0;
583
ce3080e9
P
584 /* Disable CRNG testing for the primary DRBG */
585 if (!TEST_true(disable_crngt(primary)))
d69226a3
P
586 return 0;
587
59f124f9 588 /* uninstantiate the three global DRBGs */
7d615e21
P
589 EVP_RAND_uninstantiate(primary);
590 EVP_RAND_uninstantiate(private);
591 EVP_RAND_uninstantiate(public);
a93ba405 592
59f124f9
DMSP
593 /*
594 * Test initial seeding of shared DRBGs
595 */
09e76c5d
DMSP
596 if (!TEST_true(test_drbg_reseed(1,
597 primary, public, private,
598 NULL, NULL,
599 1, 1, 1, 0)))
59f124f9 600 goto error;
59f124f9 601
a93ba405 602 /*
59f124f9 603 * Test initial state of shared DRBGs
a93ba405 604 */
09e76c5d
DMSP
605 if (!TEST_true(test_drbg_reseed(1,
606 primary, public, private,
607 NULL, NULL,
608 0, 0, 0, 0)))
a93ba405 609 goto error;
a93ba405
DMSP
610
611 /*
612 * Test whether the public and private DRBG are both reseeded when their
ce3080e9 613 * reseed counters differ from the primary's reseed counter.
a93ba405 614 */
ce3080e9 615 inc_reseed_counter(primary);
09e76c5d
DMSP
616 if (!TEST_true(test_drbg_reseed(1,
617 primary, public, private,
618 NULL, NULL,
619 0, 1, 1, 0)))
a93ba405 620 goto error;
a93ba405
DMSP
621
622 /*
623 * Test whether the public DRBG is reseeded when its reseed counter differs
ce3080e9 624 * from the primary's reseed counter.
a93ba405 625 */
ce3080e9 626 inc_reseed_counter(primary);
3f078163 627 inc_reseed_counter(private);
09e76c5d
DMSP
628 if (!TEST_true(test_drbg_reseed(1,
629 primary, public, private,
630 NULL, NULL,
631 0, 1, 0, 0)))
a93ba405 632 goto error;
a93ba405
DMSP
633
634 /*
635 * Test whether the private DRBG is reseeded when its reseed counter differs
ce3080e9 636 * from the primary's reseed counter.
a93ba405 637 */
ce3080e9 638 inc_reseed_counter(primary);
3f078163 639 inc_reseed_counter(public);
09e76c5d
DMSP
640 if (!TEST_true(test_drbg_reseed(1,
641 primary, public, private,
642 NULL, NULL,
643 0, 0, 1, 0)))
a93ba405 644 goto error;
a93ba405 645
a93ba405
DMSP
646 /* fill 'randomness' buffer with some arbitrary data */
647 memset(rand_add_buf, 'r', sizeof(rand_add_buf));
648
649 /*
2bb1b5dd
BE
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
ce3080e9 652 * test_drbg_reseed() test, because the primary DRBG gets already reseeded
2bb1b5dd 653 * in RAND_add(), whence the check for the condition
ce3080e9 654 * before_reseed <= reseed_time(primary) will fail if the time value happens
2bb1b5dd 655 * to increase between the RAND_add() and the test_drbg_reseed() call.
a93ba405 656 */
2bb1b5dd 657 before_reseed = time(NULL);
a93ba405 658 RAND_add(rand_add_buf, sizeof(rand_add_buf), sizeof(rand_add_buf));
09e76c5d
DMSP
659 if (!TEST_true(test_drbg_reseed(1,
660 primary, public, private,
661 NULL, NULL,
662 1, 1, 1,
2bb1b5dd 663 before_reseed)))
a93ba405 664 goto error;
a93ba405
DMSP
665
666 rv = 1;
667
668error:
3f078163 669 return rv;
a93ba405
DMSP
670}
671
440bce8f 672#if defined(OPENSSL_THREADS)
43687d68
DMSP
673static int multi_thread_rand_bytes_succeeded = 1;
674static int multi_thread_rand_priv_bytes_succeeded = 1;
440bce8f 675
7d615e21
P
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();
e494fac7 683 return EVP_RAND_CTX_set_params(drbg, params);
7d615e21
P
684}
685
440bce8f
KR
686static void run_multi_thread_test(void)
687{
688 unsigned char buf[256];
689 time_t start = time(NULL);
7d615e21 690 EVP_RAND_CTX *public = NULL, *private = NULL;
440bce8f 691
7d615e21
P
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))) {
7ecd6c51
BE
696 multi_thread_rand_bytes_succeeded = 0;
697 return;
698 }
440bce8f
KR
699
700 do {
7d615e21 701 if (rand_bytes(buf, sizeof(buf)) <= 0)
43687d68 702 multi_thread_rand_bytes_succeeded = 0;
7d615e21 703 if (rand_priv_bytes(buf, sizeof(buf)) <= 0)
43687d68 704 multi_thread_rand_priv_bytes_succeeded = 0;
440bce8f 705 }
7d615e21 706 while (time(NULL) - start < 5);
440bce8f
KR
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();
03cdfe1e
RL
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();
440bce8f
KR
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();
03cdfe1e
RL
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();
440bce8f
KR
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 */
43687d68 766# define THREADS 3
440bce8f
KR
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]);
43687d68
DMSP
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
440bce8f
KR
784 return 1;
785}
786#endif
12fb8c3d 787
7d615e21
P
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))
e494fac7 800 || !TEST_true(EVP_RAND_CTX_set_params(drbg, params))) {
c23add36 801 EVP_RAND_CTX_free(drbg);
7d615e21
P
802 drbg = NULL;
803 }
c23add36 804 EVP_RAND_free(rand);
7d615e21
P
805 return drbg;
806}
807
09e76c5d 808static int test_rand_prediction_resistance(void)
65175163 809{
7d615e21 810 EVP_RAND_CTX *x = NULL, *y = NULL, *z = NULL;
65175163 811 unsigned char buf1[51], buf2[sizeof(buf1)];
ce3080e9 812 int ret = 0, xreseed, yreseed, zreseed;
65175163 813
c91f972c 814 if (using_fips_rng())
3f078163
P
815 return TEST_skip("CRNGT cannot be disabled");
816
65175163 817 /* Initialise a three long DRBG chain */
7d615e21 818 if (!TEST_ptr(x = new_drbg(NULL))
ce3080e9 819 || !TEST_true(disable_crngt(x))
7198bd1a 820 || !TEST_true(EVP_RAND_instantiate(x, 0, 0, NULL, 0, NULL))
7d615e21 821 || !TEST_ptr(y = new_drbg(x))
7198bd1a 822 || !TEST_true(EVP_RAND_instantiate(y, 0, 0, NULL, 0, NULL))
7d615e21 823 || !TEST_ptr(z = new_drbg(y))
7198bd1a 824 || !TEST_true(EVP_RAND_instantiate(z, 0, 0, NULL, 0, NULL)))
65175163
P
825 goto err;
826
ce3080e9
P
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);
7d615e21 835 if (!TEST_true(EVP_RAND_reseed(z, 0, NULL, 0, NULL, 0))
ce3080e9
P
836 || !TEST_int_eq(reseed_counter(x), xreseed)
837 || !TEST_int_eq(reseed_counter(y), yreseed)
838 || !TEST_int_gt(reseed_counter(z), zreseed))
65175163
P
839 goto err;
840
841 /*
842 * When prediction resistance is requested, the request should be
ce3080e9 843 * propagated to the primary, so that the entire DRBG chain reseeds.
65175163 844 */
ce3080e9 845 zreseed = reseed_counter(z);
7d615e21 846 if (!TEST_true(EVP_RAND_reseed(z, 1, NULL, 0, NULL, 0))
ce3080e9
P
847 || !TEST_int_gt(reseed_counter(x), xreseed)
848 || !TEST_int_gt(reseed_counter(y), yreseed)
849 || !TEST_int_gt(reseed_counter(z), zreseed))
65175163
P
850 goto err;
851
ce3080e9
P
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);
7d615e21 858 if (!TEST_true(EVP_RAND_generate(z, buf1, sizeof(buf1), 0, 0, NULL, 0))
ce3080e9
P
859 || !TEST_int_eq(reseed_counter(x), xreseed)
860 || !TEST_int_eq(reseed_counter(y), yreseed)
861 || !TEST_int_gt(reseed_counter(z), zreseed))
65175163
P
862 goto err;
863
864 /*
865 * When a prediction resistant generate is requested, the request
ce3080e9 866 * should be propagated to the primary, reseeding the entire DRBG chain.
65175163 867 */
ce3080e9 868 zreseed = reseed_counter(z);
7d615e21 869 if (!TEST_true(EVP_RAND_generate(z, buf2, sizeof(buf2), 0, 1, NULL, 0))
ce3080e9
P
870 || !TEST_int_gt(reseed_counter(x), xreseed)
871 || !TEST_int_gt(reseed_counter(y), yreseed)
872 || !TEST_int_gt(reseed_counter(z), zreseed)
65175163
P
873 || !TEST_mem_ne(buf1, sizeof(buf1), buf2, sizeof(buf2)))
874 goto err;
875
ce3080e9
P
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);
7d615e21 881 if (!TEST_true(EVP_RAND_reseed(z, 0, NULL, 0, NULL, 0))
ce3080e9
P
882 || !TEST_int_eq(reseed_counter(x), xreseed)
883 || !TEST_int_eq(reseed_counter(y), yreseed)
884 || !TEST_int_gt(reseed_counter(z), zreseed))
65175163
P
885 goto err;
886
887 ret = 1;
888err:
7d615e21
P
889 EVP_RAND_CTX_free(z);
890 EVP_RAND_CTX_free(y);
891 EVP_RAND_CTX_free(x);
65175163
P
892 return ret;
893}
894
ad887416 895int setup_tests(void)
12fb8c3d 896{
09e76c5d 897 ADD_TEST(test_rand_reseed);
04d07ffb 898#if defined(OPENSSL_SYS_UNIX) && !defined(OPENSSL_RAND_SEED_EGD)
09e76c5d
DMSP
899 ADD_ALL_TESTS(test_rand_fork_safety, RANDOM_SIZE);
900#endif
901 ADD_TEST(test_rand_prediction_resistance);
440bce8f
KR
902#if defined(OPENSSL_THREADS)
903 ADD_TEST(test_multi_thread);
904#endif
ad887416 905 return 1;
12fb8c3d 906}