2 * Copyright 2011-2023 The OpenSSL Project Authors. All Rights Reserved.
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
10 /* We need to use some deprecated APIs */
11 #define OPENSSL_SUPPRESS_DEPRECATED
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"
31 #if defined(OPENSSL_SYS_UNIX)
32 # include <sys/types.h>
33 # include <sys/wait.h>
40 * DRBG generate wrappers
42 static int gen_bytes(EVP_RAND_CTX
*drbg
, unsigned char *buf
, int num
)
44 #ifndef OPENSSL_NO_DEPRECATED_3_0
45 const RAND_METHOD
*meth
= RAND_get_rand_method();
47 if (meth
!= NULL
&& meth
!= RAND_OpenSSL()) {
48 if (meth
->bytes
!= NULL
)
49 return meth
->bytes(buf
, num
);
55 return EVP_RAND_generate(drbg
, buf
, num
, 0, 0, NULL
, 0);
59 static int rand_bytes(unsigned char *buf
, int num
)
61 return gen_bytes(RAND_get0_public(NULL
), buf
, num
);
64 static int rand_priv_bytes(unsigned char *buf
, int num
)
66 return gen_bytes(RAND_get0_private(NULL
), buf
, num
);
70 /* size of random output generated in test_drbg_reseed() */
71 #define RANDOM_SIZE 16
74 * DRBG query functions
76 static int state(EVP_RAND_CTX
*drbg
)
78 return EVP_RAND_get_state(drbg
);
81 static unsigned int query_rand_uint(EVP_RAND_CTX
*drbg
, const char *name
)
83 OSSL_PARAM params
[2] = { OSSL_PARAM_END
, OSSL_PARAM_END
};
86 *params
= OSSL_PARAM_construct_uint(name
, &n
);
87 if (EVP_RAND_CTX_get_params(drbg
, params
))
92 #define DRBG_UINT(name) \
93 static unsigned int name(EVP_RAND_CTX *drbg) \
95 return query_rand_uint(drbg, #name); \
97 DRBG_UINT(reseed_counter
)
99 static PROV_DRBG
*prov_rand(EVP_RAND_CTX
*drbg
)
101 return (PROV_DRBG
*)drbg
->algctx
;
104 static void set_reseed_counter(EVP_RAND_CTX
*drbg
, unsigned int n
)
106 PROV_DRBG
*p
= prov_rand(drbg
);
108 p
->reseed_counter
= n
;
111 static void inc_reseed_counter(EVP_RAND_CTX
*drbg
)
113 set_reseed_counter(drbg
, reseed_counter(drbg
) + 1);
116 static time_t reseed_time(EVP_RAND_CTX
*drbg
)
118 OSSL_PARAM params
[2] = { OSSL_PARAM_END
, OSSL_PARAM_END
};
121 *params
= OSSL_PARAM_construct_time_t(OSSL_DRBG_PARAM_RESEED_TIME
, &t
);
122 if (EVP_RAND_CTX_get_params(drbg
, params
))
128 * When building the FIPS module, it isn't possible to disable the continuous
129 * RNG tests. Tests that require this are skipped and this means a detection
130 * mechanism for the FIPS provider being in use.
132 static int using_fips_rng(void)
134 EVP_RAND_CTX
*primary
= RAND_get0_primary(NULL
);
135 const OSSL_PROVIDER
*prov
;
138 if (!TEST_ptr(primary
))
141 prov
= EVP_RAND_get0_provider(EVP_RAND_CTX_get0_rand(primary
));
144 name
= OSSL_PROVIDER_get0_name(prov
);
145 return strcmp(name
, "OpenSSL FIPS Provider") == 0;
149 * Disable CRNG testing if it is enabled.
150 * This stub remains to indicate the calling locations where it is necessary.
151 * Once the RNG infrastructure is able to disable these tests, it should be
154 static int disable_crngt(EVP_RAND_CTX
*drbg
)
160 * Generates random output using rand_bytes() and rand_priv_bytes()
161 * and checks whether the three shared DRBGs were reseeded as
164 * |expect_success|: expected outcome (as reported by RAND_status())
165 * |primary|, |public|, |private|: pointers to the three shared DRBGs
166 * |public_random|, |private_random|: generated random output
167 * |expect_xxx_reseed| =
168 * 1: it is expected that the specified DRBG is reseeded
169 * 0: it is expected that the specified DRBG is not reseeded
170 * -1: don't check whether the specified DRBG was reseeded or not
171 * |reseed_when|: if nonzero, used instead of time(NULL) to set the
172 * |before_reseed| time.
174 static int test_drbg_reseed(int expect_success
,
175 EVP_RAND_CTX
*primary
,
176 EVP_RAND_CTX
*public,
177 EVP_RAND_CTX
*private,
178 unsigned char *public_random
,
179 unsigned char *private_random
,
180 int expect_primary_reseed
,
181 int expect_public_reseed
,
182 int expect_private_reseed
,
186 time_t before_reseed
, after_reseed
;
187 int expected_state
= (expect_success
? DRBG_READY
: DRBG_ERROR
);
188 unsigned int primary_reseed
, public_reseed
, private_reseed
;
189 unsigned char dummy
[RANDOM_SIZE
];
191 if (public_random
== NULL
)
192 public_random
= dummy
;
194 if (private_random
== NULL
)
195 private_random
= dummy
;
198 * step 1: check preconditions
201 /* Test whether seed propagation is enabled */
202 if (!TEST_int_ne(primary_reseed
= reseed_counter(primary
), 0)
203 || !TEST_int_ne(public_reseed
= reseed_counter(public), 0)
204 || !TEST_int_ne(private_reseed
= reseed_counter(private), 0))
208 * step 2: generate random output
211 if (reseed_when
== 0)
212 reseed_when
= time(NULL
);
214 /* Generate random output from the public and private DRBG */
215 before_reseed
= expect_primary_reseed
== 1 ? reseed_when
: 0;
216 if (!TEST_int_eq(rand_bytes((unsigned char*)public_random
,
217 RANDOM_SIZE
), expect_success
)
218 || !TEST_int_eq(rand_priv_bytes((unsigned char*) private_random
,
219 RANDOM_SIZE
), expect_success
))
221 after_reseed
= time(NULL
);
225 * step 3: check postconditions
228 /* Test whether reseeding succeeded as expected */
229 if (!TEST_int_eq(state(primary
), expected_state
)
230 || !TEST_int_eq(state(public), expected_state
)
231 || !TEST_int_eq(state(private), expected_state
))
234 if (expect_primary_reseed
>= 0) {
235 /* Test whether primary DRBG was reseeded as expected */
236 if (!TEST_int_ge(reseed_counter(primary
), primary_reseed
))
240 if (expect_public_reseed
>= 0) {
241 /* Test whether public DRBG was reseeded as expected */
242 if (!TEST_int_ge(reseed_counter(public), public_reseed
)
243 || !TEST_uint_ge(reseed_counter(public),
244 reseed_counter(primary
)))
248 if (expect_private_reseed
>= 0) {
249 /* Test whether public DRBG was reseeded as expected */
250 if (!TEST_int_ge(reseed_counter(private), private_reseed
)
251 || !TEST_uint_ge(reseed_counter(private),
252 reseed_counter(primary
)))
256 if (expect_success
== 1) {
257 /* Test whether reseed time of primary DRBG is set correctly */
258 if (!TEST_time_t_le(before_reseed
, reseed_time(primary
))
259 || !TEST_time_t_le(reseed_time(primary
), after_reseed
))
262 /* Test whether reseed times of child DRBGs are synchronized with primary */
263 if (!TEST_time_t_ge(reseed_time(public), reseed_time(primary
))
264 || !TEST_time_t_ge(reseed_time(private), reseed_time(primary
)))
274 #if defined(OPENSSL_SYS_UNIX) && !defined(OPENSSL_RAND_SEED_EGD)
275 /* number of children to fork */
276 #define DRBG_FORK_COUNT 9
277 /* two results per child, two for the parent */
278 #define DRBG_FORK_RESULT_COUNT (2 * (DRBG_FORK_COUNT + 1))
280 typedef struct drbg_fork_result_st
{
282 unsigned char random
[RANDOM_SIZE
]; /* random output */
284 int pindex
; /* process index (0: parent, 1,2,3...: children)*/
285 pid_t pid
; /* process id */
286 int private; /* true if the private drbg was used */
287 char name
[10]; /* 'parent' resp. 'child 1', 'child 2', ... */
291 * Sort the drbg_fork_result entries in lexicographical order
293 * This simplifies finding duplicate random output and makes
294 * the printout in case of an error more readable.
296 static int compare_drbg_fork_result(const void *left
, const void *right
)
299 const drbg_fork_result
*l
= left
;
300 const drbg_fork_result
*r
= right
;
302 /* separate public and private results */
303 result
= l
->private - r
->private;
306 result
= memcmp(l
->random
, r
->random
, RANDOM_SIZE
);
309 result
= l
->pindex
- r
->pindex
;
315 * Sort two-byte chunks of random data
317 * Used for finding collisions in two-byte chunks
319 static int compare_rand_chunk(const void *left
, const void *right
)
321 return memcmp(left
, right
, 2);
325 * Test whether primary, public and private DRBG are reseeded
326 * in the child after forking the process. Collect the random
327 * output of the public and private DRBG and send it back to
328 * the parent process.
330 static int test_drbg_reseed_in_child(EVP_RAND_CTX
*primary
,
331 EVP_RAND_CTX
*public,
332 EVP_RAND_CTX
*private,
333 drbg_fork_result result
[2])
338 unsigned char random
[2 * RANDOM_SIZE
];
340 if (!TEST_int_ge(pipe(fd
), 0))
343 if (!TEST_int_ge(pid
= fork(), 0)) {
347 } else if (pid
> 0) {
349 /* I'm the parent; close the write end */
352 /* wait for children to terminate and collect their random output */
353 if (TEST_int_eq(waitpid(pid
, &status
, 0), pid
)
354 && TEST_int_eq(status
, 0)
355 && TEST_true(read(fd
[0], &random
[0], sizeof(random
))
356 == sizeof(random
))) {
358 /* random output of public drbg */
360 result
[0].private = 0;
361 memcpy(result
[0].random
, &random
[0], RANDOM_SIZE
);
363 /* random output of private drbg */
365 result
[1].private = 1;
366 memcpy(result
[1].random
, &random
[RANDOM_SIZE
], RANDOM_SIZE
);
371 /* close the read end */
378 /* I'm the child; close the read end */
381 /* check whether all three DRBGs reseed and send output to parent */
382 if (TEST_true(test_drbg_reseed(1, primary
, public, private,
383 &random
[0], &random
[RANDOM_SIZE
],
385 && TEST_true(write(fd
[1], random
, sizeof(random
))
386 == sizeof(random
))) {
391 /* close the write end */
394 /* convert boolean to exit code */
399 static int test_rand_reseed_on_fork(EVP_RAND_CTX
*primary
,
400 EVP_RAND_CTX
*public,
401 EVP_RAND_CTX
*private)
404 pid_t pid
= getpid();
405 int verbose
= (getenv("V") != NULL
);
407 int duplicate
[2] = {0, 0};
408 unsigned char random
[2 * RANDOM_SIZE
];
409 unsigned char sample
[DRBG_FORK_RESULT_COUNT
* RANDOM_SIZE
];
410 unsigned char *psample
= &sample
[0];
411 drbg_fork_result result
[DRBG_FORK_RESULT_COUNT
];
412 drbg_fork_result
*presult
= &result
[2];
414 memset(&result
, 0, sizeof(result
));
416 for (i
= 1 ; i
<= DRBG_FORK_COUNT
; ++i
) {
418 presult
[0].pindex
= presult
[1].pindex
= i
;
420 sprintf(presult
[0].name
, "child %d", i
);
421 strcpy(presult
[1].name
, presult
[0].name
);
423 /* collect the random output of the children */
424 if (!TEST_true(test_drbg_reseed_in_child(primary
,
433 /* collect the random output of the parent */
434 if (!TEST_true(test_drbg_reseed(1,
435 primary
, public, private,
436 &random
[0], &random
[RANDOM_SIZE
],
440 strcpy(result
[0].name
, "parent");
441 strcpy(result
[1].name
, "parent");
443 /* output of public drbg */
445 result
[0].private = 0;
446 memcpy(result
[0].random
, &random
[0], RANDOM_SIZE
);
448 /* output of private drbg */
450 result
[1].private = 1;
451 memcpy(result
[1].random
, &random
[RANDOM_SIZE
], RANDOM_SIZE
);
453 /* collect all sampled random data in a single buffer */
454 for (i
= 0 ; i
< DRBG_FORK_RESULT_COUNT
; ++i
) {
455 memcpy(psample
, &result
[i
].random
[0], RANDOM_SIZE
);
456 psample
+= RANDOM_SIZE
;
459 /* sort the results... */
460 qsort(result
, DRBG_FORK_RESULT_COUNT
, sizeof(drbg_fork_result
),
461 compare_drbg_fork_result
);
463 /* ...and count duplicate prefixes by looking at the first byte only */
464 for (i
= 1 ; i
< DRBG_FORK_RESULT_COUNT
; ++i
) {
465 if (result
[i
].random
[0] == result
[i
-1].random
[0]) {
466 /* count public and private duplicates separately */
467 ++duplicate
[result
[i
].private];
471 if (duplicate
[0] >= DRBG_FORK_COUNT
- 1) {
472 /* just too many duplicates to be a coincidence */
473 TEST_note("ERROR: %d duplicate prefixes in public random output", duplicate
[0]);
477 if (duplicate
[1] >= DRBG_FORK_COUNT
- 1) {
478 /* just too many duplicates to be a coincidence */
479 TEST_note("ERROR: %d duplicate prefixes in private random output", duplicate
[1]);
485 /* sort the two-byte chunks... */
486 qsort(sample
, sizeof(sample
)/2, 2, compare_rand_chunk
);
488 /* ...and count duplicate chunks */
489 for (i
= 2, psample
= sample
+ 2 ; i
< sizeof(sample
) ; i
+= 2, psample
+= 2) {
490 if (compare_rand_chunk(psample
- 2, psample
) == 0)
494 if (duplicate
[0] >= DRBG_FORK_COUNT
- 1) {
495 /* just too many duplicates to be a coincidence */
496 TEST_note("ERROR: %d duplicate chunks in random output", duplicate
[0]);
500 if (verbose
|| !success
) {
502 for (i
= 0 ; i
< DRBG_FORK_RESULT_COUNT
; ++i
) {
503 char *rand_hex
= OPENSSL_buf2hexstr(result
[i
].random
, RANDOM_SIZE
);
505 TEST_note(" random: %s, pid: %d (%s, %s)",
509 result
[i
].private ? "private" : "public"
512 OPENSSL_free(rand_hex
);
519 static int test_rand_fork_safety(int i
)
522 unsigned char random
[1];
523 EVP_RAND_CTX
*primary
, *public, *private;
525 /* All three DRBGs should be non-null */
526 if (!TEST_ptr(primary
= RAND_get0_primary(NULL
))
527 || !TEST_ptr(public = RAND_get0_public(NULL
))
528 || !TEST_ptr(private = RAND_get0_private(NULL
)))
531 /* run the actual test */
532 if (!TEST_true(test_rand_reseed_on_fork(primary
, public, private)))
535 /* request a single byte from each of the DRBGs before the next run */
536 if (!TEST_int_gt(RAND_bytes(random
, 1), 0) || !TEST_int_gt(RAND_priv_bytes(random
, 1), 0))
544 * Test whether the default rand_method (RAND_OpenSSL()) is
545 * setup correctly, in particular whether reseeding works
548 static int test_rand_reseed(void)
550 EVP_RAND_CTX
*primary
, *public, *private;
551 unsigned char rand_add_buf
[256];
553 time_t before_reseed
;
555 if (using_fips_rng())
556 return TEST_skip("CRNGT cannot be disabled");
558 #ifndef OPENSSL_NO_DEPRECATED_3_0
559 /* Check whether RAND_OpenSSL() is the default method */
560 if (!TEST_ptr_eq(RAND_get_rand_method(), RAND_OpenSSL()))
564 /* All three DRBGs should be non-null */
565 if (!TEST_ptr(primary
= RAND_get0_primary(NULL
))
566 || !TEST_ptr(public = RAND_get0_public(NULL
))
567 || !TEST_ptr(private = RAND_get0_private(NULL
)))
570 /* There should be three distinct DRBGs, two of them chained to primary */
571 if (!TEST_ptr_ne(public, private)
572 || !TEST_ptr_ne(public, primary
)
573 || !TEST_ptr_ne(private, primary
)
574 || !TEST_ptr_eq(prov_rand(public)->parent
, prov_rand(primary
))
575 || !TEST_ptr_eq(prov_rand(private)->parent
, prov_rand(primary
)))
578 /* Disable CRNG testing for the primary DRBG */
579 if (!TEST_true(disable_crngt(primary
)))
582 /* uninstantiate the three global DRBGs */
583 EVP_RAND_uninstantiate(primary
);
584 EVP_RAND_uninstantiate(private);
585 EVP_RAND_uninstantiate(public);
588 * Test initial seeding of shared DRBGs
590 if (!TEST_true(test_drbg_reseed(1,
591 primary
, public, private,
597 * Test initial state of shared DRBGs
599 if (!TEST_true(test_drbg_reseed(1,
600 primary
, public, private,
606 * Test whether the public and private DRBG are both reseeded when their
607 * reseed counters differ from the primary's reseed counter.
609 inc_reseed_counter(primary
);
610 if (!TEST_true(test_drbg_reseed(1,
611 primary
, public, private,
617 * Test whether the public DRBG is reseeded when its reseed counter differs
618 * from the primary's reseed counter.
620 inc_reseed_counter(primary
);
621 inc_reseed_counter(private);
622 if (!TEST_true(test_drbg_reseed(1,
623 primary
, public, private,
629 * Test whether the private DRBG is reseeded when its reseed counter differs
630 * from the primary's reseed counter.
632 inc_reseed_counter(primary
);
633 inc_reseed_counter(public);
634 if (!TEST_true(test_drbg_reseed(1,
635 primary
, public, private,
640 /* fill 'randomness' buffer with some arbitrary data */
641 memset(rand_add_buf
, 'r', sizeof(rand_add_buf
));
644 * Test whether all three DRBGs are reseeded by RAND_add().
645 * The before_reseed time has to be measured here and passed into the
646 * test_drbg_reseed() test, because the primary DRBG gets already reseeded
647 * in RAND_add(), whence the check for the condition
648 * before_reseed <= reseed_time(primary) will fail if the time value happens
649 * to increase between the RAND_add() and the test_drbg_reseed() call.
651 before_reseed
= time(NULL
);
652 RAND_add(rand_add_buf
, sizeof(rand_add_buf
), sizeof(rand_add_buf
));
653 if (!TEST_true(test_drbg_reseed(1,
654 primary
, public, private,
666 #if defined(OPENSSL_THREADS)
667 static int multi_thread_rand_bytes_succeeded
= 1;
668 static int multi_thread_rand_priv_bytes_succeeded
= 1;
670 static int set_reseed_time_interval(EVP_RAND_CTX
*drbg
, int t
)
672 OSSL_PARAM params
[2];
674 params
[0] = OSSL_PARAM_construct_int(OSSL_DRBG_PARAM_RESEED_TIME_INTERVAL
,
676 params
[1] = OSSL_PARAM_construct_end();
677 return EVP_RAND_CTX_set_params(drbg
, params
);
680 static void run_multi_thread_test(void)
682 unsigned char buf
[256];
683 time_t start
= time(NULL
);
684 EVP_RAND_CTX
*public = NULL
, *private = NULL
;
686 if (!TEST_ptr(public = RAND_get0_public(NULL
))
687 || !TEST_ptr(private = RAND_get0_private(NULL
))
688 || !TEST_true(set_reseed_time_interval(private, 1))
689 || !TEST_true(set_reseed_time_interval(public, 1))) {
690 multi_thread_rand_bytes_succeeded
= 0;
695 if (rand_bytes(buf
, sizeof(buf
)) <= 0)
696 multi_thread_rand_bytes_succeeded
= 0;
697 if (rand_priv_bytes(buf
, sizeof(buf
)) <= 0)
698 multi_thread_rand_priv_bytes_succeeded
= 0;
700 while (time(NULL
) - start
< 5);
703 # if defined(OPENSSL_SYS_WINDOWS)
705 typedef HANDLE thread_t
;
707 static DWORD WINAPI
thread_run(LPVOID arg
)
709 run_multi_thread_test();
711 * Because we're linking with a static library, we must stop each
712 * thread explicitly, or so says OPENSSL_thread_stop(3)
714 OPENSSL_thread_stop();
718 static int run_thread(thread_t
*t
)
720 *t
= CreateThread(NULL
, 0, thread_run
, NULL
, 0, NULL
);
724 static int wait_for_thread(thread_t thread
)
726 return WaitForSingleObject(thread
, INFINITE
) == 0;
731 typedef pthread_t thread_t
;
733 static void *thread_run(void *arg
)
735 run_multi_thread_test();
737 * Because we're linking with a static library, we must stop each
738 * thread explicitly, or so says OPENSSL_thread_stop(3)
740 OPENSSL_thread_stop();
744 static int run_thread(thread_t
*t
)
746 return pthread_create(t
, NULL
, thread_run
, NULL
) == 0;
749 static int wait_for_thread(thread_t thread
)
751 return pthread_join(thread
, NULL
) == 0;
757 * The main thread will also run the test, so we'll have THREADS+1 parallel
762 static int test_multi_thread(void)
767 for (i
= 0; i
< THREADS
; i
++)
769 run_multi_thread_test();
770 for (i
= 0; i
< THREADS
; i
++)
771 wait_for_thread(t
[i
]);
773 if (!TEST_true(multi_thread_rand_bytes_succeeded
))
775 if (!TEST_true(multi_thread_rand_priv_bytes_succeeded
))
782 static EVP_RAND_CTX
*new_drbg(EVP_RAND_CTX
*parent
)
784 OSSL_PARAM params
[2];
785 EVP_RAND
*rand
= NULL
;
786 EVP_RAND_CTX
*drbg
= NULL
;
788 params
[0] = OSSL_PARAM_construct_utf8_string(OSSL_DRBG_PARAM_CIPHER
,
790 params
[1] = OSSL_PARAM_construct_end();
792 if (!TEST_ptr(rand
= EVP_RAND_fetch(NULL
, "CTR-DRBG", NULL
))
793 || !TEST_ptr(drbg
= EVP_RAND_CTX_new(rand
, parent
))
794 || !TEST_true(EVP_RAND_CTX_set_params(drbg
, params
))) {
795 EVP_RAND_CTX_free(drbg
);
802 static int test_rand_prediction_resistance(void)
804 EVP_RAND_CTX
*x
= NULL
, *y
= NULL
, *z
= NULL
;
805 unsigned char buf1
[51], buf2
[sizeof(buf1
)];
806 int ret
= 0, xreseed
, yreseed
, zreseed
;
808 if (using_fips_rng())
809 return TEST_skip("CRNGT cannot be disabled");
811 /* Initialise a three long DRBG chain */
812 if (!TEST_ptr(x
= new_drbg(NULL
))
813 || !TEST_true(disable_crngt(x
))
814 || !TEST_true(EVP_RAND_instantiate(x
, 0, 0, NULL
, 0, NULL
))
815 || !TEST_ptr(y
= new_drbg(x
))
816 || !TEST_true(EVP_RAND_instantiate(y
, 0, 0, NULL
, 0, NULL
))
817 || !TEST_ptr(z
= new_drbg(y
))
818 || !TEST_true(EVP_RAND_instantiate(z
, 0, 0, NULL
, 0, NULL
)))
822 * During a normal reseed, only the last DRBG in the chain should
825 inc_reseed_counter(y
);
826 xreseed
= reseed_counter(x
);
827 yreseed
= reseed_counter(y
);
828 zreseed
= reseed_counter(z
);
829 if (!TEST_true(EVP_RAND_reseed(z
, 0, NULL
, 0, NULL
, 0))
830 || !TEST_int_eq(reseed_counter(x
), xreseed
)
831 || !TEST_int_eq(reseed_counter(y
), yreseed
)
832 || !TEST_int_gt(reseed_counter(z
), zreseed
))
836 * When prediction resistance is requested, the request should be
837 * propagated to the primary, so that the entire DRBG chain reseeds.
839 zreseed
= reseed_counter(z
);
840 if (!TEST_true(EVP_RAND_reseed(z
, 1, NULL
, 0, NULL
, 0))
841 || !TEST_int_gt(reseed_counter(x
), xreseed
)
842 || !TEST_int_gt(reseed_counter(y
), yreseed
)
843 || !TEST_int_gt(reseed_counter(z
), zreseed
))
847 * During a normal generate, only the last DRBG should be reseed */
848 inc_reseed_counter(y
);
849 xreseed
= reseed_counter(x
);
850 yreseed
= reseed_counter(y
);
851 zreseed
= reseed_counter(z
);
852 if (!TEST_true(EVP_RAND_generate(z
, buf1
, sizeof(buf1
), 0, 0, NULL
, 0))
853 || !TEST_int_eq(reseed_counter(x
), xreseed
)
854 || !TEST_int_eq(reseed_counter(y
), yreseed
)
855 || !TEST_int_gt(reseed_counter(z
), zreseed
))
859 * When a prediction resistant generate is requested, the request
860 * should be propagated to the primary, reseeding the entire DRBG chain.
862 zreseed
= reseed_counter(z
);
863 if (!TEST_true(EVP_RAND_generate(z
, buf2
, sizeof(buf2
), 0, 1, NULL
, 0))
864 || !TEST_int_gt(reseed_counter(x
), xreseed
)
865 || !TEST_int_gt(reseed_counter(y
), yreseed
)
866 || !TEST_int_gt(reseed_counter(z
), zreseed
)
867 || !TEST_mem_ne(buf1
, sizeof(buf1
), buf2
, sizeof(buf2
)))
870 /* Verify that a normal reseed still only reseeds the last DRBG */
871 inc_reseed_counter(y
);
872 xreseed
= reseed_counter(x
);
873 yreseed
= reseed_counter(y
);
874 zreseed
= reseed_counter(z
);
875 if (!TEST_true(EVP_RAND_reseed(z
, 0, NULL
, 0, NULL
, 0))
876 || !TEST_int_eq(reseed_counter(x
), xreseed
)
877 || !TEST_int_eq(reseed_counter(y
), yreseed
)
878 || !TEST_int_gt(reseed_counter(z
), zreseed
))
883 EVP_RAND_CTX_free(z
);
884 EVP_RAND_CTX_free(y
);
885 EVP_RAND_CTX_free(x
);
889 int setup_tests(void)
891 ADD_TEST(test_rand_reseed
);
892 #if defined(OPENSSL_SYS_UNIX) && !defined(OPENSSL_RAND_SEED_EGD)
893 ADD_ALL_TESTS(test_rand_fork_safety
, RANDOM_SIZE
);
895 ADD_TEST(test_rand_prediction_resistance
);
896 #if defined(OPENSSL_THREADS)
897 ADD_TEST(test_multi_thread
);