2 * Copyright 2011-2019 The OpenSSL Project Authors. All Rights Reserved.
4 * Licensed under the OpenSSL license (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
11 #include "internal/nelem.h"
12 #include <openssl/crypto.h>
13 #include <openssl/err.h>
14 #include <openssl/rand.h>
15 #include <openssl/obj_mac.h>
16 #include <openssl/evp.h>
17 #include <openssl/aes.h>
18 #include "../crypto/rand/rand_local.h"
19 #include "../include/crypto/rand.h"
26 #if defined(OPENSSL_SYS_UNIX)
27 # include <sys/types.h>
28 # include <sys/wait.h>
35 typedef struct drbg_selftest_data_st
{
40 /* KAT data for no PR */
41 const unsigned char *entropy
;
43 const unsigned char *nonce
;
45 const unsigned char *pers
;
47 const unsigned char *adin
;
49 const unsigned char *entropyreseed
;
50 size_t entropyreseedlen
;
51 const unsigned char *adinreseed
;
53 const unsigned char *adin2
;
55 const unsigned char *expected
;
57 const unsigned char *kat2
;
61 const unsigned char *entropy_pr
;
63 const unsigned char *nonce_pr
;
65 const unsigned char *pers_pr
;
67 const unsigned char *adin_pr
;
69 const unsigned char *entropypr_pr
;
70 size_t entropyprlen_pr
;
71 const unsigned char *ading_pr
;
73 const unsigned char *entropyg_pr
;
74 size_t entropyglen_pr
;
75 const unsigned char *kat_pr
;
77 const unsigned char *kat2_pr
;
81 #define make_drbg_test_data(nid, flag, pr, post) {\
83 pr##_entropyinput, sizeof(pr##_entropyinput), \
84 pr##_nonce, sizeof(pr##_nonce), \
85 pr##_personalizationstring, sizeof(pr##_personalizationstring), \
86 pr##_additionalinput, sizeof(pr##_additionalinput), \
87 pr##_entropyinputreseed, sizeof(pr##_entropyinputreseed), \
88 pr##_additionalinputreseed, sizeof(pr##_additionalinputreseed), \
89 pr##_additionalinput2, sizeof(pr##_additionalinput2), \
90 pr##_int_returnedbits, sizeof(pr##_int_returnedbits), \
91 pr##_returnedbits, sizeof(pr##_returnedbits), \
92 pr##_pr_entropyinput, sizeof(pr##_pr_entropyinput), \
93 pr##_pr_nonce, sizeof(pr##_pr_nonce), \
94 pr##_pr_personalizationstring, sizeof(pr##_pr_personalizationstring), \
95 pr##_pr_additionalinput, sizeof(pr##_pr_additionalinput), \
96 pr##_pr_entropyinputpr, sizeof(pr##_pr_entropyinputpr), \
97 pr##_pr_additionalinput2, sizeof(pr##_pr_additionalinput2), \
98 pr##_pr_entropyinputpr2, sizeof(pr##_pr_entropyinputpr2), \
99 pr##_pr_int_returnedbits, sizeof(pr##_pr_int_returnedbits), \
100 pr##_pr_returnedbits, sizeof(pr##_pr_returnedbits) \
103 #define make_drbg_test_data_use_df(nid, pr, p) \
104 make_drbg_test_data(nid, 0, pr, p)
106 #define make_drbg_test_data_no_df(nid, pr, p) \
107 make_drbg_test_data(nid, RAND_DRBG_FLAG_CTR_NO_DF, pr, p)
109 static DRBG_SELFTEST_DATA drbg_test
[] = {
110 make_drbg_test_data_no_df (NID_aes_128_ctr
, aes_128_no_df
, 0),
111 make_drbg_test_data_no_df (NID_aes_192_ctr
, aes_192_no_df
, 0),
112 make_drbg_test_data_no_df (NID_aes_256_ctr
, aes_256_no_df
, 1),
113 make_drbg_test_data_use_df(NID_aes_128_ctr
, aes_128_use_df
, 0),
114 make_drbg_test_data_use_df(NID_aes_192_ctr
, aes_192_use_df
, 0),
115 make_drbg_test_data_use_df(NID_aes_256_ctr
, aes_256_use_df
, 1),
118 static int app_data_index
;
121 * Test context data, attached as EXDATA to the RAND_DRBG
123 typedef struct test_ctx_st
{
124 const unsigned char *entropy
;
127 const unsigned char *nonce
;
132 static size_t kat_entropy(RAND_DRBG
*drbg
, unsigned char **pout
,
133 int entropy
, size_t min_len
, size_t max_len
,
134 int prediction_resistance
)
136 TEST_CTX
*t
= (TEST_CTX
*)RAND_DRBG_get_ex_data(drbg
, app_data_index
);
139 *pout
= (unsigned char *)t
->entropy
;
140 return t
->entropylen
;
143 static size_t kat_nonce(RAND_DRBG
*drbg
, unsigned char **pout
,
144 int entropy
, size_t min_len
, size_t max_len
)
146 TEST_CTX
*t
= (TEST_CTX
*)RAND_DRBG_get_ex_data(drbg
, app_data_index
);
149 *pout
= (unsigned char *)t
->nonce
;
153 static int uninstantiate(RAND_DRBG
*drbg
)
155 int ret
= drbg
== NULL
? 1 : RAND_DRBG_uninstantiate(drbg
);
162 * Do a single KAT test. Return 0 on failure.
164 static int single_kat(DRBG_SELFTEST_DATA
*td
)
166 RAND_DRBG
*drbg
= NULL
;
169 unsigned char buff
[1024];
172 * Test without PR: Instantiate DRBG with test entropy, nonce and
173 * personalisation string.
175 if (!TEST_ptr(drbg
= RAND_DRBG_new(td
->nid
, td
->flags
, NULL
)))
177 if (!TEST_true(RAND_DRBG_set_callbacks(drbg
, kat_entropy
, NULL
,
182 memset(&t
, 0, sizeof(t
));
183 t
.entropy
= td
->entropy
;
184 t
.entropylen
= td
->entropylen
;
186 t
.noncelen
= td
->noncelen
;
187 RAND_DRBG_set_ex_data(drbg
, app_data_index
, &t
);
189 if (!TEST_true(RAND_DRBG_instantiate(drbg
, td
->pers
, td
->perslen
))
190 || !TEST_true(RAND_DRBG_generate(drbg
, buff
, td
->exlen
, 0,
191 td
->adin
, td
->adinlen
))
192 || !TEST_mem_eq(td
->expected
, td
->exlen
, buff
, td
->exlen
))
195 /* Reseed DRBG with test entropy and additional input */
196 t
.entropy
= td
->entropyreseed
;
197 t
.entropylen
= td
->entropyreseedlen
;
198 if (!TEST_true(RAND_DRBG_reseed(drbg
, td
->adinreseed
, td
->adinreseedlen
, 0)
199 || !TEST_true(RAND_DRBG_generate(drbg
, buff
, td
->kat2len
, 0,
200 td
->adin2
, td
->adin2len
))
201 || !TEST_mem_eq(td
->kat2
, td
->kat2len
, buff
, td
->kat2len
)))
206 * Now test with PR: Instantiate DRBG with test entropy, nonce and
207 * personalisation string.
209 if (!TEST_true(RAND_DRBG_set(drbg
, td
->nid
, td
->flags
))
210 || !TEST_true(RAND_DRBG_set_callbacks(drbg
, kat_entropy
, NULL
,
213 RAND_DRBG_set_ex_data(drbg
, app_data_index
, &t
);
214 t
.entropy
= td
->entropy_pr
;
215 t
.entropylen
= td
->entropylen_pr
;
216 t
.nonce
= td
->nonce_pr
;
217 t
.noncelen
= td
->noncelen_pr
;
220 if (!TEST_true(RAND_DRBG_instantiate(drbg
, td
->pers_pr
, td
->perslen_pr
)))
224 * Now generate with PR: we need to supply entropy as this will
225 * perform a reseed operation.
227 t
.entropy
= td
->entropypr_pr
;
228 t
.entropylen
= td
->entropyprlen_pr
;
229 if (!TEST_true(RAND_DRBG_generate(drbg
, buff
, td
->katlen_pr
, 1,
230 td
->adin_pr
, td
->adinlen_pr
))
231 || !TEST_mem_eq(td
->kat_pr
, td
->katlen_pr
, buff
, td
->katlen_pr
))
235 * Now generate again with PR: supply new entropy again.
237 t
.entropy
= td
->entropyg_pr
;
238 t
.entropylen
= td
->entropyglen_pr
;
240 if (!TEST_true(RAND_DRBG_generate(drbg
, buff
, td
->kat2len_pr
, 1,
241 td
->ading_pr
, td
->adinglen_pr
))
242 || !TEST_mem_eq(td
->kat2_pr
, td
->kat2len_pr
,
243 buff
, td
->kat2len_pr
))
248 RAND_DRBG_free(drbg
);
249 return failures
== 0;
253 * Initialise a DRBG based on selftest data
255 static int init(RAND_DRBG
*drbg
, DRBG_SELFTEST_DATA
*td
, TEST_CTX
*t
)
257 if (!TEST_true(RAND_DRBG_set(drbg
, td
->nid
, td
->flags
))
258 || !TEST_true(RAND_DRBG_set_callbacks(drbg
, kat_entropy
, NULL
,
261 RAND_DRBG_set_ex_data(drbg
, app_data_index
, t
);
262 t
->entropy
= td
->entropy
;
263 t
->entropylen
= td
->entropylen
;
264 t
->nonce
= td
->nonce
;
265 t
->noncelen
= td
->noncelen
;
272 * Initialise and instantiate DRBG based on selftest data
274 static int instantiate(RAND_DRBG
*drbg
, DRBG_SELFTEST_DATA
*td
,
277 if (!TEST_true(init(drbg
, td
, t
))
278 || !TEST_true(RAND_DRBG_instantiate(drbg
, td
->pers
, td
->perslen
)))
284 * Perform extensive error checking as required by SP800-90.
285 * Induce several failure modes and check an error condition is set.
287 static int error_check(DRBG_SELFTEST_DATA
*td
)
289 static char zero
[sizeof(RAND_DRBG
)];
290 RAND_DRBG
*drbg
= NULL
;
292 unsigned char buff
[1024];
293 unsigned int reseed_counter_tmp
;
296 if (!TEST_ptr(drbg
= RAND_DRBG_new(0, 0, NULL
)))
300 * Personalisation string tests
303 /* Test detection of too large personalisation string */
304 if (!init(drbg
, td
, &t
)
305 || RAND_DRBG_instantiate(drbg
, td
->pers
, drbg
->max_perslen
+ 1) > 0)
309 * Entropy source tests
312 /* Test entropy source failure detection: i.e. returns no data */
314 if (TEST_int_le(RAND_DRBG_instantiate(drbg
, td
->pers
, td
->perslen
), 0))
317 /* Try to generate output from uninstantiated DRBG */
318 if (!TEST_false(RAND_DRBG_generate(drbg
, buff
, td
->exlen
, 0,
319 td
->adin
, td
->adinlen
))
320 || !uninstantiate(drbg
))
323 /* Test insufficient entropy */
324 t
.entropylen
= drbg
->min_entropylen
- 1;
325 if (!init(drbg
, td
, &t
)
326 || RAND_DRBG_instantiate(drbg
, td
->pers
, td
->perslen
) > 0
327 || !uninstantiate(drbg
))
330 /* Test too much entropy */
331 t
.entropylen
= drbg
->max_entropylen
+ 1;
332 if (!init(drbg
, td
, &t
)
333 || RAND_DRBG_instantiate(drbg
, td
->pers
, td
->perslen
) > 0
334 || !uninstantiate(drbg
))
341 /* Test too small nonce */
342 if (drbg
->min_noncelen
) {
343 t
.noncelen
= drbg
->min_noncelen
- 1;
344 if (!init(drbg
, td
, &t
)
345 || RAND_DRBG_instantiate(drbg
, td
->pers
, td
->perslen
) > 0
346 || !uninstantiate(drbg
))
350 /* Test too large nonce */
351 if (drbg
->max_noncelen
) {
352 t
.noncelen
= drbg
->max_noncelen
+ 1;
353 if (!init(drbg
, td
, &t
)
354 || RAND_DRBG_instantiate(drbg
, td
->pers
, td
->perslen
) > 0
355 || !uninstantiate(drbg
))
359 /* Instantiate with valid data, Check generation is now OK */
360 if (!instantiate(drbg
, td
, &t
)
361 || !TEST_true(RAND_DRBG_generate(drbg
, buff
, td
->exlen
, 0,
362 td
->adin
, td
->adinlen
)))
365 /* Request too much data for one request */
366 if (!TEST_false(RAND_DRBG_generate(drbg
, buff
, drbg
->max_request
+ 1, 0,
367 td
->adin
, td
->adinlen
)))
370 /* Try too large additional input */
371 if (!TEST_false(RAND_DRBG_generate(drbg
, buff
, td
->exlen
, 0,
372 td
->adin
, drbg
->max_adinlen
+ 1)))
376 * Check prediction resistance request fails if entropy source
380 if (TEST_false(RAND_DRBG_generate(drbg
, buff
, td
->exlen
, 1,
381 td
->adin
, td
->adinlen
))
382 || !uninstantiate(drbg
))
385 /* Instantiate again with valid data */
386 if (!instantiate(drbg
, td
, &t
))
388 reseed_counter_tmp
= drbg
->reseed_gen_counter
;
389 drbg
->reseed_gen_counter
= drbg
->reseed_interval
;
391 /* Generate output and check entropy has been requested for reseed */
393 if (!TEST_true(RAND_DRBG_generate(drbg
, buff
, td
->exlen
, 0,
394 td
->adin
, td
->adinlen
))
395 || !TEST_int_eq(t
.entropycnt
, 1)
396 || !TEST_int_eq(drbg
->reseed_gen_counter
, reseed_counter_tmp
+ 1)
397 || !uninstantiate(drbg
))
401 * Check prediction resistance request fails if entropy source
405 if (!TEST_false(RAND_DRBG_generate(drbg
, buff
, td
->exlen
, 1,
406 td
->adin
, td
->adinlen
))
407 || !uninstantiate(drbg
))
410 /* Test reseed counter works */
411 if (!instantiate(drbg
, td
, &t
))
413 reseed_counter_tmp
= drbg
->reseed_gen_counter
;
414 drbg
->reseed_gen_counter
= drbg
->reseed_interval
;
416 /* Generate output and check entropy has been requested for reseed */
418 if (!TEST_true(RAND_DRBG_generate(drbg
, buff
, td
->exlen
, 0,
419 td
->adin
, td
->adinlen
))
420 || !TEST_int_eq(t
.entropycnt
, 1)
421 || !TEST_int_eq(drbg
->reseed_gen_counter
, reseed_counter_tmp
+ 1)
422 || !uninstantiate(drbg
))
426 * Explicit reseed tests
429 /* Test explicit reseed with too large additional input */
430 if (!instantiate(drbg
, td
, &t
)
431 || RAND_DRBG_reseed(drbg
, td
->adin
, drbg
->max_adinlen
+ 1, 0) > 0)
434 /* Test explicit reseed with entropy source failure */
436 if (!TEST_int_le(RAND_DRBG_reseed(drbg
, td
->adin
, td
->adinlen
, 0), 0)
437 || !uninstantiate(drbg
))
440 /* Test explicit reseed with too much entropy */
441 if (!instantiate(drbg
, td
, &t
))
443 t
.entropylen
= drbg
->max_entropylen
+ 1;
444 if (!TEST_int_le(RAND_DRBG_reseed(drbg
, td
->adin
, td
->adinlen
, 0), 0)
445 || !uninstantiate(drbg
))
448 /* Test explicit reseed with too little entropy */
449 if (!instantiate(drbg
, td
, &t
))
451 t
.entropylen
= drbg
->min_entropylen
- 1;
452 if (!TEST_int_le(RAND_DRBG_reseed(drbg
, td
->adin
, td
->adinlen
, 0), 0)
453 || !uninstantiate(drbg
))
456 /* Standard says we have to check uninstantiate really zeroes */
457 if (!TEST_mem_eq(zero
, sizeof(drbg
->data
), &drbg
->data
, sizeof(drbg
->data
)))
464 RAND_DRBG_free(drbg
);
468 static int test_kats(int i
)
470 DRBG_SELFTEST_DATA
*td
= &drbg_test
[i
];
481 static int test_error_checks(int i
)
483 DRBG_SELFTEST_DATA
*td
= &drbg_test
[i
];
495 * Hook context data, attached as EXDATA to the RAND_DRBG
497 typedef struct hook_ctx_st
{
500 * Currently, all DRBGs use the same get_entropy() callback.
501 * The tests however, don't assume this and store
502 * the original callback for every DRBG separately.
504 RAND_DRBG_get_entropy_fn get_entropy
;
505 /* forces a failure of the get_entropy() call if nonzero */
507 /* counts successful reseeds */
511 static HOOK_CTX master_ctx
, public_ctx
, private_ctx
;
513 static HOOK_CTX
*get_hook_ctx(RAND_DRBG
*drbg
)
515 return (HOOK_CTX
*)RAND_DRBG_get_ex_data(drbg
, app_data_index
);
518 /* Intercepts and counts calls to the get_entropy() callback */
519 static size_t get_entropy_hook(RAND_DRBG
*drbg
, unsigned char **pout
,
520 int entropy
, size_t min_len
, size_t max_len
,
521 int prediction_resistance
)
524 HOOK_CTX
*ctx
= get_hook_ctx(drbg
);
529 ret
= ctx
->get_entropy(drbg
, pout
, entropy
, min_len
, max_len
,
530 prediction_resistance
);
537 /* Installs a hook for the get_entropy() callback of the given drbg */
538 static void hook_drbg(RAND_DRBG
*drbg
, HOOK_CTX
*ctx
)
540 memset(ctx
, 0, sizeof(*ctx
));
542 ctx
->get_entropy
= drbg
->get_entropy
;
543 drbg
->get_entropy
= get_entropy_hook
;
544 RAND_DRBG_set_ex_data(drbg
, app_data_index
, ctx
);
547 /* Installs the hook for the get_entropy() callback of the given drbg */
548 static void unhook_drbg(RAND_DRBG
*drbg
)
550 HOOK_CTX
*ctx
= get_hook_ctx(drbg
);
552 drbg
->get_entropy
= ctx
->get_entropy
;
553 CRYPTO_free_ex_data(CRYPTO_EX_INDEX_DRBG
, drbg
, &drbg
->ex_data
);
556 /* Resets the given hook context */
557 static void reset_hook_ctx(HOOK_CTX
*ctx
)
560 ctx
->reseed_count
= 0;
563 /* Resets all drbg hook contexts */
564 static void reset_drbg_hook_ctx(void)
566 reset_hook_ctx(&master_ctx
);
567 reset_hook_ctx(&public_ctx
);
568 reset_hook_ctx(&private_ctx
);
572 * Generates random output using RAND_bytes() and RAND_priv_bytes()
573 * and checks whether the three shared DRBGs were reseeded as
576 * |expect_success|: expected outcome (as reported by RAND_status())
577 * |master|, |public|, |private|: pointers to the three shared DRBGs
578 * |expect_xxx_reseed| =
579 * 1: it is expected that the specified DRBG is reseeded
580 * 0: it is expected that the specified DRBG is not reseeded
581 * -1: don't check whether the specified DRBG was reseeded or not
582 * |reseed_time|: if nonzero, used instead of time(NULL) to set the
583 * |before_reseed| time.
585 static int test_drbg_reseed(int expect_success
,
589 int expect_master_reseed
,
590 int expect_public_reseed
,
591 int expect_private_reseed
,
595 unsigned char buf
[32];
596 time_t before_reseed
, after_reseed
;
597 int expected_state
= (expect_success
? DRBG_READY
: DRBG_ERROR
);
600 * step 1: check preconditions
603 /* Test whether seed propagation is enabled */
604 if (!TEST_int_ne(master
->reseed_prop_counter
, 0)
605 || !TEST_int_ne(public->reseed_prop_counter
, 0)
606 || !TEST_int_ne(private->reseed_prop_counter
, 0))
609 /* Check whether the master DRBG's reseed counter is the largest one */
610 if (!TEST_int_le(public->reseed_prop_counter
, master
->reseed_prop_counter
)
611 || !TEST_int_le(private->reseed_prop_counter
, master
->reseed_prop_counter
))
615 * step 2: generate random output
618 if (reseed_time
== 0)
619 reseed_time
= time(NULL
);
621 /* Generate random output from the public and private DRBG */
622 before_reseed
= expect_master_reseed
== 1 ? reseed_time
: 0;
623 if (!TEST_int_eq(RAND_bytes(buf
, sizeof(buf
)), expect_success
)
624 || !TEST_int_eq(RAND_priv_bytes(buf
, sizeof(buf
)), expect_success
))
626 after_reseed
= time(NULL
);
630 * step 3: check postconditions
633 /* Test whether reseeding succeeded as expected */
634 if (!TEST_int_eq(master
->state
, expected_state
)
635 || !TEST_int_eq(public->state
, expected_state
)
636 || !TEST_int_eq(private->state
, expected_state
))
639 if (expect_master_reseed
>= 0) {
640 /* Test whether master DRBG was reseeded as expected */
641 if (!TEST_int_eq(master_ctx
.reseed_count
, expect_master_reseed
))
645 if (expect_public_reseed
>= 0) {
646 /* Test whether public DRBG was reseeded as expected */
647 if (!TEST_int_eq(public_ctx
.reseed_count
, expect_public_reseed
))
651 if (expect_private_reseed
>= 0) {
652 /* Test whether public DRBG was reseeded as expected */
653 if (!TEST_int_eq(private_ctx
.reseed_count
, expect_private_reseed
))
657 if (expect_success
== 1) {
658 /* Test whether all three reseed counters are synchronized */
659 if (!TEST_int_eq(public->reseed_prop_counter
, master
->reseed_prop_counter
)
660 || !TEST_int_eq(private->reseed_prop_counter
, master
->reseed_prop_counter
))
663 /* Test whether reseed time of master DRBG is set correctly */
664 if (!TEST_time_t_le(before_reseed
, master
->reseed_time
)
665 || !TEST_time_t_le(master
->reseed_time
, after_reseed
))
668 /* Test whether reseed times of child DRBGs are synchronized with master */
669 if (!TEST_time_t_ge(public->reseed_time
, master
->reseed_time
)
670 || !TEST_time_t_ge(private->reseed_time
, master
->reseed_time
))
680 #if defined(OPENSSL_SYS_UNIX)
682 * Test whether master, public and private DRBG are reseeded after
683 * forking the process.
685 static int test_drbg_reseed_after_fork(RAND_DRBG
*master
,
693 if (!TEST_int_ge(pid
, 0))
697 /* I'm the parent; wait for the child and check its exit code */
698 return TEST_int_eq(waitpid(pid
, &status
, 0), pid
) && TEST_int_eq(status
, 0);
701 /* I'm the child; check whether all three DRBGs reseed. */
702 if (!TEST_true(test_drbg_reseed(1, master
, public, private, 1, 1, 1, 0)))
708 unhook_drbg(private);
714 * Test whether the default rand_method (RAND_OpenSSL()) is
715 * setup correctly, in particular whether reseeding works
718 static int test_rand_drbg_reseed(void)
720 RAND_DRBG
*master
, *public, *private;
721 unsigned char rand_add_buf
[256];
723 time_t before_reseed
;
725 /* Check whether RAND_OpenSSL() is the default method */
726 if (!TEST_ptr_eq(RAND_get_rand_method(), RAND_OpenSSL()))
729 /* All three DRBGs should be non-null */
730 if (!TEST_ptr(master
= RAND_DRBG_get0_master())
731 || !TEST_ptr(public = RAND_DRBG_get0_public())
732 || !TEST_ptr(private = RAND_DRBG_get0_private()))
735 /* There should be three distinct DRBGs, two of them chained to master */
736 if (!TEST_ptr_ne(public, private)
737 || !TEST_ptr_ne(public, master
)
738 || !TEST_ptr_ne(private, master
)
739 || !TEST_ptr_eq(public->parent
, master
)
740 || !TEST_ptr_eq(private->parent
, master
))
743 /* uninstantiate the three global DRBGs */
744 RAND_DRBG_uninstantiate(private);
745 RAND_DRBG_uninstantiate(public);
746 RAND_DRBG_uninstantiate(master
);
749 /* Install hooks for the following tests */
750 hook_drbg(master
, &master_ctx
);
751 hook_drbg(public, &public_ctx
);
752 hook_drbg(private, &private_ctx
);
756 * Test initial seeding of shared DRBGs
758 if (!TEST_true(test_drbg_reseed(1, master
, public, private, 1, 1, 1, 0)))
760 reset_drbg_hook_ctx();
764 * Test initial state of shared DRBGs
766 if (!TEST_true(test_drbg_reseed(1, master
, public, private, 0, 0, 0, 0)))
768 reset_drbg_hook_ctx();
771 * Test whether the public and private DRBG are both reseeded when their
772 * reseed counters differ from the master's reseed counter.
774 master
->reseed_prop_counter
++;
775 if (!TEST_true(test_drbg_reseed(1, master
, public, private, 0, 1, 1, 0)))
777 reset_drbg_hook_ctx();
780 * Test whether the public DRBG is reseeded when its reseed counter differs
781 * from the master's reseed counter.
783 master
->reseed_prop_counter
++;
784 private->reseed_prop_counter
++;
785 if (!TEST_true(test_drbg_reseed(1, master
, public, private, 0, 1, 0, 0)))
787 reset_drbg_hook_ctx();
790 * Test whether the private DRBG is reseeded when its reseed counter differs
791 * from the master's reseed counter.
793 master
->reseed_prop_counter
++;
794 public->reseed_prop_counter
++;
795 if (!TEST_true(test_drbg_reseed(1, master
, public, private, 0, 0, 1, 0)))
797 reset_drbg_hook_ctx();
799 #if defined(OPENSSL_SYS_UNIX)
800 if (!TEST_true(test_drbg_reseed_after_fork(master
, public, private)))
804 /* fill 'randomness' buffer with some arbitrary data */
805 memset(rand_add_buf
, 'r', sizeof(rand_add_buf
));
808 * Test whether all three DRBGs are reseeded by RAND_add().
809 * The before_reseed time has to be measured here and passed into the
810 * test_drbg_reseed() test, because the master DRBG gets already reseeded
811 * in RAND_add(), whence the check for the condition
812 * before_reseed <= master->reseed_time will fail if the time value happens
813 * to increase between the RAND_add() and the test_drbg_reseed() call.
815 before_reseed
= time(NULL
);
816 RAND_add(rand_add_buf
, sizeof(rand_add_buf
), sizeof(rand_add_buf
));
817 if (!TEST_true(test_drbg_reseed(1, master
, public, private, 1, 1, 1,
820 reset_drbg_hook_ctx();
824 * Test whether none of the DRBGs is reseed if the master fails to reseed
827 master
->reseed_prop_counter
++;
828 RAND_add(rand_add_buf
, sizeof(rand_add_buf
), sizeof(rand_add_buf
));
829 if (!TEST_true(test_drbg_reseed(0, master
, public, private, 0, 0, 0, 0)))
831 reset_drbg_hook_ctx();
839 unhook_drbg(private);
844 #if defined(OPENSSL_THREADS)
845 static int multi_thread_rand_bytes_succeeded
= 1;
846 static int multi_thread_rand_priv_bytes_succeeded
= 1;
848 static void run_multi_thread_test(void)
850 unsigned char buf
[256];
851 time_t start
= time(NULL
);
852 RAND_DRBG
*public = NULL
, *private = NULL
;
854 if (!TEST_ptr(public = RAND_DRBG_get0_public())
855 || !TEST_ptr(private = RAND_DRBG_get0_private())) {
856 multi_thread_rand_bytes_succeeded
= 0;
859 RAND_DRBG_set_reseed_time_interval(private, 1);
860 RAND_DRBG_set_reseed_time_interval(public, 1);
863 if (RAND_bytes(buf
, sizeof(buf
)) <= 0)
864 multi_thread_rand_bytes_succeeded
= 0;
865 if (RAND_priv_bytes(buf
, sizeof(buf
)) <= 0)
866 multi_thread_rand_priv_bytes_succeeded
= 0;
868 while(time(NULL
) - start
< 5);
871 # if defined(OPENSSL_SYS_WINDOWS)
873 typedef HANDLE thread_t
;
875 static DWORD WINAPI
thread_run(LPVOID arg
)
877 run_multi_thread_test();
879 * Because we're linking with a static library, we must stop each
880 * thread explicitly, or so says OPENSSL_thread_stop(3)
882 OPENSSL_thread_stop();
886 static int run_thread(thread_t
*t
)
888 *t
= CreateThread(NULL
, 0, thread_run
, NULL
, 0, NULL
);
892 static int wait_for_thread(thread_t thread
)
894 return WaitForSingleObject(thread
, INFINITE
) == 0;
899 typedef pthread_t thread_t
;
901 static void *thread_run(void *arg
)
903 run_multi_thread_test();
905 * Because we're linking with a static library, we must stop each
906 * thread explicitly, or so says OPENSSL_thread_stop(3)
908 OPENSSL_thread_stop();
912 static int run_thread(thread_t
*t
)
914 return pthread_create(t
, NULL
, thread_run
, NULL
) == 0;
917 static int wait_for_thread(thread_t thread
)
919 return pthread_join(thread
, NULL
) == 0;
925 * The main thread will also run the test, so we'll have THREADS+1 parallel
930 static int test_multi_thread(void)
935 for (i
= 0; i
< THREADS
; i
++)
937 run_multi_thread_test();
938 for (i
= 0; i
< THREADS
; i
++)
939 wait_for_thread(t
[i
]);
941 if (!TEST_true(multi_thread_rand_bytes_succeeded
))
943 if (!TEST_true(multi_thread_rand_priv_bytes_succeeded
))
951 * Test that instantiation with RAND_seed() works as expected
953 * If no os entropy source is available then RAND_seed(buffer, bufsize)
954 * is expected to succeed if and only if the buffer length is at least
955 * rand_drbg_seedlen(master) bytes.
957 * If an os entropy source is available then RAND_seed(buffer, bufsize)
958 * is expected to succeed always.
960 static int test_rand_seed(void)
962 RAND_DRBG
*master
= NULL
;
963 unsigned char rand_buf
[256];
965 size_t required_seed_buflen
= 0;
967 if (!TEST_ptr(master
= RAND_DRBG_get0_master()))
970 #ifdef OPENSSL_RAND_SEED_NONE
971 required_seed_buflen
= rand_drbg_seedlen(master
);
974 memset(rand_buf
, 0xCD, sizeof(rand_buf
));
976 for ( rand_buflen
= 256 ; rand_buflen
> 0 ; --rand_buflen
) {
977 RAND_DRBG_uninstantiate(master
);
978 RAND_seed(rand_buf
, rand_buflen
);
980 if (!TEST_int_eq(RAND_status(),
981 (rand_buflen
>= required_seed_buflen
)))
989 * Test that adding additional data with RAND_add() works as expected
990 * when the master DRBG is instantiated (and below its reseed limit).
992 * This should succeed regardless of whether an os entropy source is
995 static int test_rand_add(void)
997 unsigned char rand_buf
[256];
1000 memset(rand_buf
, 0xCD, sizeof(rand_buf
));
1002 /* make sure it's instantiated */
1003 RAND_seed(rand_buf
, sizeof(rand_buf
));
1004 if (!TEST_true(RAND_status()))
1007 for ( rand_buflen
= 256 ; rand_buflen
> 0 ; --rand_buflen
) {
1008 RAND_add(rand_buf
, rand_buflen
, 0.0);
1009 if (!TEST_true(RAND_status()))
1016 int setup_tests(void)
1018 app_data_index
= RAND_DRBG_get_ex_new_index(0L, NULL
, NULL
, NULL
, NULL
);
1020 ADD_ALL_TESTS(test_kats
, OSSL_NELEM(drbg_test
));
1021 ADD_ALL_TESTS(test_error_checks
, OSSL_NELEM(drbg_test
));
1022 ADD_TEST(test_rand_drbg_reseed
);
1023 ADD_TEST(test_rand_seed
);
1024 ADD_TEST(test_rand_add
);
1025 #if defined(OPENSSL_THREADS)
1026 ADD_TEST(test_multi_thread
);