Return a fatal error if application data is encountered during shutdown
[openssl.git] / test / drbgtest.c
1 /*
2  * Copyright 2011-2018 The OpenSSL Project Authors. All Rights Reserved.
3  *
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
8  */
9
10 #include <string.h>
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_lcl.h"
19 #include "../crypto/include/internal/rand_int.h"
20
21 #if defined(_WIN32)
22 # include <windows.h>
23 #endif
24
25 #include "testutil.h"
26 #include "drbgtest.h"
27
28 typedef struct drbg_selftest_data_st {
29     int post;
30     int nid;
31     unsigned int flags;
32
33     /* KAT data for no PR */
34     const unsigned char *entropy;
35     size_t entropylen;
36     const unsigned char *nonce;
37     size_t noncelen;
38     const unsigned char *pers;
39     size_t perslen;
40     const unsigned char *adin;
41     size_t adinlen;
42     const unsigned char *entropyreseed;
43     size_t entropyreseedlen;
44     const unsigned char *adinreseed;
45     size_t adinreseedlen;
46     const unsigned char *adin2;
47     size_t adin2len;
48     const unsigned char *expected;
49     size_t exlen;
50     const unsigned char *kat2;
51     size_t kat2len;
52
53     /* KAT data for PR */
54     const unsigned char *entropy_pr;
55     size_t entropylen_pr;
56     const unsigned char *nonce_pr;
57     size_t noncelen_pr;
58     const unsigned char *pers_pr;
59     size_t perslen_pr;
60     const unsigned char *adin_pr;
61     size_t adinlen_pr;
62     const unsigned char *entropypr_pr;
63     size_t entropyprlen_pr;
64     const unsigned char *ading_pr;
65     size_t adinglen_pr;
66     const unsigned char *entropyg_pr;
67     size_t entropyglen_pr;
68     const unsigned char *kat_pr;
69     size_t katlen_pr;
70     const unsigned char *kat2_pr;
71     size_t kat2len_pr;
72 } DRBG_SELFTEST_DATA;
73
74 #define make_drbg_test_data(nid, flag, pr, post) {\
75     post, nid, flag, \
76     pr##_entropyinput, sizeof(pr##_entropyinput), \
77     pr##_nonce, sizeof(pr##_nonce), \
78     pr##_personalizationstring, sizeof(pr##_personalizationstring), \
79     pr##_additionalinput, sizeof(pr##_additionalinput), \
80     pr##_entropyinputreseed, sizeof(pr##_entropyinputreseed), \
81     pr##_additionalinputreseed, sizeof(pr##_additionalinputreseed), \
82     pr##_additionalinput2, sizeof(pr##_additionalinput2), \
83     pr##_int_returnedbits, sizeof(pr##_int_returnedbits), \
84     pr##_returnedbits, sizeof(pr##_returnedbits), \
85     pr##_pr_entropyinput, sizeof(pr##_pr_entropyinput), \
86     pr##_pr_nonce, sizeof(pr##_pr_nonce), \
87     pr##_pr_personalizationstring, sizeof(pr##_pr_personalizationstring), \
88     pr##_pr_additionalinput, sizeof(pr##_pr_additionalinput), \
89     pr##_pr_entropyinputpr, sizeof(pr##_pr_entropyinputpr), \
90     pr##_pr_additionalinput2, sizeof(pr##_pr_additionalinput2), \
91     pr##_pr_entropyinputpr2, sizeof(pr##_pr_entropyinputpr2), \
92     pr##_pr_int_returnedbits, sizeof(pr##_pr_int_returnedbits), \
93     pr##_pr_returnedbits, sizeof(pr##_pr_returnedbits) \
94     }
95
96 #define make_drbg_test_data_use_df(nid, pr, p) \
97     make_drbg_test_data(nid, 0, pr, p)
98
99 #define make_drbg_test_data_no_df(nid, pr, p)                      \
100     make_drbg_test_data(nid, RAND_DRBG_FLAG_CTR_NO_DF, pr, p)
101
102 static DRBG_SELFTEST_DATA drbg_test[] = {
103     make_drbg_test_data_no_df (NID_aes_128_ctr, aes_128_no_df,  0),
104     make_drbg_test_data_no_df (NID_aes_192_ctr, aes_192_no_df,  0),
105     make_drbg_test_data_no_df (NID_aes_256_ctr, aes_256_no_df,  1),
106     make_drbg_test_data_use_df(NID_aes_128_ctr, aes_128_use_df, 0),
107     make_drbg_test_data_use_df(NID_aes_192_ctr, aes_192_use_df, 0),
108     make_drbg_test_data_use_df(NID_aes_256_ctr, aes_256_use_df, 1),
109 };
110
111 static int app_data_index;
112
113 /*
114  * Test context data, attached as EXDATA to the RAND_DRBG
115  */
116 typedef struct test_ctx_st {
117     const unsigned char *entropy;
118     size_t entropylen;
119     int entropycnt;
120     const unsigned char *nonce;
121     size_t noncelen;
122     int noncecnt;
123 } TEST_CTX;
124
125 static size_t kat_entropy(RAND_DRBG *drbg, unsigned char **pout,
126                           int entropy, size_t min_len, size_t max_len,
127                           int prediction_resistance)
128 {
129     TEST_CTX *t = (TEST_CTX *)RAND_DRBG_get_ex_data(drbg, app_data_index);
130
131     t->entropycnt++;
132     *pout = (unsigned char *)t->entropy;
133     return t->entropylen;
134 }
135
136 static size_t kat_nonce(RAND_DRBG *drbg, unsigned char **pout,
137                         int entropy, size_t min_len, size_t max_len)
138 {
139     TEST_CTX *t = (TEST_CTX *)RAND_DRBG_get_ex_data(drbg, app_data_index);
140
141     t->noncecnt++;
142     *pout = (unsigned char *)t->nonce;
143     return t->noncelen;
144 }
145
146 static int uninstantiate(RAND_DRBG *drbg)
147 {
148     int ret = drbg == NULL ? 1 : RAND_DRBG_uninstantiate(drbg);
149
150     ERR_clear_error();
151     return ret;
152 }
153
154 /*
155  * Do a single KAT test.  Return 0 on failure.
156  */
157 static int single_kat(DRBG_SELFTEST_DATA *td)
158 {
159     RAND_DRBG *drbg = NULL;
160     TEST_CTX t;
161     int failures = 0;
162     unsigned char buff[1024];
163
164     /*
165      * Test without PR: Instantiate DRBG with test entropy, nonce and
166      * personalisation string.
167      */
168     if (!TEST_ptr(drbg = RAND_DRBG_new(td->nid, td->flags, NULL)))
169         return 0;
170     if (!TEST_true(RAND_DRBG_set_callbacks(drbg, kat_entropy, NULL,
171                                            kat_nonce, NULL))) {
172         failures++;
173         goto err;
174     }
175     memset(&t, 0, sizeof(t));
176     t.entropy = td->entropy;
177     t.entropylen = td->entropylen;
178     t.nonce = td->nonce;
179     t.noncelen = td->noncelen;
180     RAND_DRBG_set_ex_data(drbg, app_data_index, &t);
181
182     if (!TEST_true(RAND_DRBG_instantiate(drbg, td->pers, td->perslen))
183             || !TEST_true(RAND_DRBG_generate(drbg, buff, td->exlen, 0,
184                                              td->adin, td->adinlen))
185             || !TEST_mem_eq(td->expected, td->exlen, buff, td->exlen))
186         failures++;
187
188     /* Reseed DRBG with test entropy and additional input */
189     t.entropy = td->entropyreseed;
190     t.entropylen = td->entropyreseedlen;
191     if (!TEST_true(RAND_DRBG_reseed(drbg, td->adinreseed, td->adinreseedlen, 0)
192             || !TEST_true(RAND_DRBG_generate(drbg, buff, td->kat2len, 0,
193                                              td->adin2, td->adin2len))
194             || !TEST_mem_eq(td->kat2, td->kat2len, buff, td->kat2len)))
195         failures++;
196     uninstantiate(drbg);
197
198     /*
199      * Now test with PR: Instantiate DRBG with test entropy, nonce and
200      * personalisation string.
201      */
202     if (!TEST_true(RAND_DRBG_set(drbg, td->nid, td->flags))
203             || !TEST_true(RAND_DRBG_set_callbacks(drbg, kat_entropy, NULL,
204                                                   kat_nonce, NULL)))
205         failures++;
206     RAND_DRBG_set_ex_data(drbg, app_data_index, &t);
207     t.entropy = td->entropy_pr;
208     t.entropylen = td->entropylen_pr;
209     t.nonce = td->nonce_pr;
210     t.noncelen = td->noncelen_pr;
211     t.entropycnt = 0;
212     t.noncecnt = 0;
213     if (!TEST_true(RAND_DRBG_instantiate(drbg, td->pers_pr, td->perslen_pr)))
214         failures++;
215
216     /*
217      * Now generate with PR: we need to supply entropy as this will
218      * perform a reseed operation.
219      */
220     t.entropy = td->entropypr_pr;
221     t.entropylen = td->entropyprlen_pr;
222     if (!TEST_true(RAND_DRBG_generate(drbg, buff, td->katlen_pr, 1,
223                                       td->adin_pr, td->adinlen_pr))
224             || !TEST_mem_eq(td->kat_pr, td->katlen_pr, buff, td->katlen_pr))
225         failures++;
226
227     /*
228      * Now generate again with PR: supply new entropy again.
229      */
230     t.entropy = td->entropyg_pr;
231     t.entropylen = td->entropyglen_pr;
232
233     if (!TEST_true(RAND_DRBG_generate(drbg, buff, td->kat2len_pr, 1,
234                                       td->ading_pr, td->adinglen_pr))
235                 || !TEST_mem_eq(td->kat2_pr, td->kat2len_pr,
236                                 buff, td->kat2len_pr))
237         failures++;
238
239 err:
240     uninstantiate(drbg);
241     RAND_DRBG_free(drbg);
242     return failures == 0;
243 }
244
245 /*
246  * Initialise a DRBG based on selftest data
247  */
248 static int init(RAND_DRBG *drbg, DRBG_SELFTEST_DATA *td, TEST_CTX *t)
249 {
250     if (!TEST_true(RAND_DRBG_set(drbg, td->nid, td->flags))
251             || !TEST_true(RAND_DRBG_set_callbacks(drbg, kat_entropy, NULL,
252                                                   kat_nonce, NULL)))
253         return 0;
254     RAND_DRBG_set_ex_data(drbg, app_data_index, t);
255     t->entropy = td->entropy;
256     t->entropylen = td->entropylen;
257     t->nonce = td->nonce;
258     t->noncelen = td->noncelen;
259     t->entropycnt = 0;
260     t->noncecnt = 0;
261     return 1;
262 }
263
264 /*
265  * Initialise and instantiate DRBG based on selftest data
266  */
267 static int instantiate(RAND_DRBG *drbg, DRBG_SELFTEST_DATA *td,
268                        TEST_CTX *t)
269 {
270     if (!TEST_true(init(drbg, td, t))
271             || !TEST_true(RAND_DRBG_instantiate(drbg, td->pers, td->perslen)))
272         return 0;
273     return 1;
274 }
275
276 /*
277  * Perform extensive error checking as required by SP800-90.
278  * Induce several failure modes and check an error condition is set.
279  */
280 static int error_check(DRBG_SELFTEST_DATA *td)
281 {
282     static char zero[sizeof(RAND_DRBG)];
283     RAND_DRBG *drbg = NULL;
284     TEST_CTX t;
285     unsigned char buff[1024];
286     unsigned int generate_counter_tmp;
287     int ret = 0;
288
289     if (!TEST_ptr(drbg = RAND_DRBG_new(0, 0, NULL)))
290         goto err;
291
292     /*
293      * Personalisation string tests
294      */
295
296     /* Test detection of too large personlisation string */
297     if (!init(drbg, td, &t)
298             || RAND_DRBG_instantiate(drbg, td->pers, drbg->max_perslen + 1) > 0)
299         goto err;
300
301     /*
302      * Entropy source tests
303      */
304
305     /* Test entropy source failure detecion: i.e. returns no data */
306     t.entropylen = 0;
307     if (TEST_int_le(RAND_DRBG_instantiate(drbg, td->pers, td->perslen), 0))
308         goto err;
309
310     /* Try to generate output from uninstantiated DRBG */
311     if (!TEST_false(RAND_DRBG_generate(drbg, buff, td->exlen, 0,
312                                        td->adin, td->adinlen))
313             || !uninstantiate(drbg))
314         goto err;
315
316     /* Test insufficient entropy */
317     t.entropylen = drbg->min_entropylen - 1;
318     if (!init(drbg, td, &t)
319             || RAND_DRBG_instantiate(drbg, td->pers, td->perslen) > 0
320             || !uninstantiate(drbg))
321         goto err;
322
323     /* Test too much entropy */
324     t.entropylen = drbg->max_entropylen + 1;
325     if (!init(drbg, td, &t)
326             || RAND_DRBG_instantiate(drbg, td->pers, td->perslen) > 0
327             || !uninstantiate(drbg))
328         goto err;
329
330     /*
331      * Nonce tests
332      */
333
334     /* Test too small nonce */
335     if (drbg->min_noncelen) {
336         t.noncelen = drbg->min_noncelen - 1;
337         if (!init(drbg, td, &t)
338                 || RAND_DRBG_instantiate(drbg, td->pers, td->perslen) > 0
339                 || !uninstantiate(drbg))
340             goto err;
341     }
342
343     /* Test too large nonce */
344     if (drbg->max_noncelen) {
345         t.noncelen = drbg->max_noncelen + 1;
346         if (!init(drbg, td, &t)
347                 || RAND_DRBG_instantiate(drbg, td->pers, td->perslen) > 0
348                 || !uninstantiate(drbg))
349             goto err;
350     }
351
352     /* Instantiate with valid data, Check generation is now OK */
353     if (!instantiate(drbg, td, &t)
354             || !TEST_true(RAND_DRBG_generate(drbg, buff, td->exlen, 0,
355                                              td->adin, td->adinlen)))
356         goto err;
357
358     /* Request too much data for one request */
359     if (!TEST_false(RAND_DRBG_generate(drbg, buff, drbg->max_request + 1, 0,
360                                        td->adin, td->adinlen)))
361         goto err;
362
363     /* Try too large additional input */
364     if (!TEST_false(RAND_DRBG_generate(drbg, buff, td->exlen, 0,
365                                        td->adin, drbg->max_adinlen + 1)))
366         goto err;
367
368     /*
369      * Check prediction resistance request fails if entropy source
370      * failure.
371      */
372     t.entropylen = 0;
373     if (TEST_false(RAND_DRBG_generate(drbg, buff, td->exlen, 1,
374                                       td->adin, td->adinlen))
375             || !uninstantiate(drbg))
376         goto err;
377
378     /* Instantiate again with valid data */
379     if (!instantiate(drbg, td, &t))
380         goto err;
381     generate_counter_tmp = drbg->generate_counter;
382     drbg->generate_counter = drbg->reseed_interval;
383
384     /* Generate output and check entropy has been requested for reseed */
385     t.entropycnt = 0;
386     if (!TEST_true(RAND_DRBG_generate(drbg, buff, td->exlen, 0,
387                                       td->adin, td->adinlen))
388             || !TEST_int_eq(t.entropycnt, 1)
389             || !TEST_int_eq(drbg->generate_counter, generate_counter_tmp + 1)
390             || !uninstantiate(drbg))
391         goto err;
392
393     /*
394      * Check prediction resistance request fails if entropy source
395      * failure.
396      */
397     t.entropylen = 0;
398     if (!TEST_false(RAND_DRBG_generate(drbg, buff, td->exlen, 1,
399                                        td->adin, td->adinlen))
400             || !uninstantiate(drbg))
401         goto err;
402
403     /* Test reseed counter works */
404     if (!instantiate(drbg, td, &t))
405         goto err;
406     generate_counter_tmp = drbg->generate_counter;
407     drbg->generate_counter = drbg->reseed_interval;
408
409     /* Generate output and check entropy has been requested for reseed */
410     t.entropycnt = 0;
411     if (!TEST_true(RAND_DRBG_generate(drbg, buff, td->exlen, 0,
412                                       td->adin, td->adinlen))
413             || !TEST_int_eq(t.entropycnt, 1)
414             || !TEST_int_eq(drbg->generate_counter, generate_counter_tmp + 1)
415             || !uninstantiate(drbg))
416         goto err;
417
418     /*
419      * Explicit reseed tests
420      */
421
422     /* Test explicit reseed with too large additional input */
423     if (!init(drbg, td, &t)
424             || RAND_DRBG_reseed(drbg, td->adin, drbg->max_adinlen + 1, 0) > 0)
425         goto err;
426
427     /* Test explicit reseed with entropy source failure */
428     t.entropylen = 0;
429     if (!TEST_int_le(RAND_DRBG_reseed(drbg, td->adin, td->adinlen, 0), 0)
430             || !uninstantiate(drbg))
431         goto err;
432
433     /* Test explicit reseed with too much entropy */
434     if (!init(drbg, td, &t))
435         goto err;
436     t.entropylen = drbg->max_entropylen + 1;
437     if (!TEST_int_le(RAND_DRBG_reseed(drbg, td->adin, td->adinlen, 0), 0)
438             || !uninstantiate(drbg))
439         goto err;
440
441     /* Test explicit reseed with too little entropy */
442     if (!init(drbg, td, &t))
443         goto err;
444     t.entropylen = drbg->min_entropylen - 1;
445     if (!TEST_int_le(RAND_DRBG_reseed(drbg, td->adin, td->adinlen, 0), 0)
446             || !uninstantiate(drbg))
447         goto err;
448
449     /* Standard says we have to check uninstantiate really zeroes */
450     if (!TEST_mem_eq(zero, sizeof(drbg->data), &drbg->data, sizeof(drbg->data)))
451         goto err;
452
453     ret = 1;
454
455 err:
456     uninstantiate(drbg);
457     RAND_DRBG_free(drbg);
458     return ret;
459 }
460
461 static int test_kats(int i)
462 {
463     DRBG_SELFTEST_DATA *td = &drbg_test[i];
464     int rv = 0;
465
466     if (!single_kat(td))
467         goto err;
468     rv = 1;
469
470 err:
471     return rv;
472 }
473
474 static int test_error_checks(int i)
475 {
476     DRBG_SELFTEST_DATA *td = &drbg_test[i];
477     int rv = 0;
478
479     if (error_check(td))
480         goto err;
481     rv = 1;
482
483 err:
484     return rv;
485 }
486
487 /*
488  * Hook context data, attached as EXDATA to the RAND_DRBG
489  */
490 typedef struct hook_ctx_st {
491     RAND_DRBG *drbg;
492     /*
493      * Currently, all DRBGs use the same get_entropy() callback.
494      * The tests however, don't assume this and store
495      * the original callback for every DRBG separately.
496      */
497     RAND_DRBG_get_entropy_fn get_entropy;
498     /* forces a failure of the get_entropy() call if nonzero */
499     int fail;
500     /* counts successful reseeds */
501     int reseed_count;
502 } HOOK_CTX;
503
504 static HOOK_CTX master_ctx, public_ctx, private_ctx;
505
506 static HOOK_CTX *get_hook_ctx(RAND_DRBG *drbg)
507 {
508     return (HOOK_CTX *)RAND_DRBG_get_ex_data(drbg, app_data_index);
509 }
510
511 /* Intercepts and counts calls to the get_entropy() callback */
512 static size_t get_entropy_hook(RAND_DRBG *drbg, unsigned char **pout,
513                               int entropy, size_t min_len, size_t max_len,
514                               int prediction_resistance)
515 {
516     size_t ret;
517     HOOK_CTX *ctx = get_hook_ctx(drbg);
518
519     if (ctx->fail != 0)
520         return 0;
521
522     ret = ctx->get_entropy(drbg, pout, entropy, min_len, max_len,
523                            prediction_resistance);
524
525     if (ret != 0)
526         ctx->reseed_count++;
527     return ret;
528 }
529
530 /* Installs a hook for the get_entropy() callback of the given drbg */
531 static void hook_drbg(RAND_DRBG *drbg, HOOK_CTX *ctx)
532 {
533     memset(ctx, 0, sizeof(*ctx));
534     ctx->drbg = drbg;
535     ctx->get_entropy = drbg->get_entropy;
536     drbg->get_entropy = get_entropy_hook;
537     RAND_DRBG_set_ex_data(drbg, app_data_index, ctx);
538 }
539
540 /* Installs the hook for the get_entropy() callback of the given drbg */
541 static void unhook_drbg(RAND_DRBG *drbg)
542 {
543     HOOK_CTX *ctx = get_hook_ctx(drbg);
544
545     drbg->get_entropy = ctx->get_entropy;
546     CRYPTO_free_ex_data(CRYPTO_EX_INDEX_DRBG, drbg, &drbg->ex_data);
547 }
548
549 /* Resets the given hook context */
550 static void reset_hook_ctx(HOOK_CTX *ctx)
551 {
552     ctx->fail = 0;
553     ctx->reseed_count = 0;
554 }
555
556 /* Resets all drbg hook contexts */
557 static void reset_drbg_hook_ctx(void)
558 {
559     reset_hook_ctx(&master_ctx);
560     reset_hook_ctx(&public_ctx);
561     reset_hook_ctx(&private_ctx);
562 }
563
564 /*
565  * Generates random output using RAND_bytes() and RAND_priv_bytes()
566  * and checks whether the three shared DRBGs were reseeded as
567  * expected.
568  *
569  * |expect_success|: expected outcome (as reported by RAND_status())
570  * |master|, |public|, |private|: pointers to the three shared DRBGs
571  * |expect_xxx_reseed| =
572  *       1:  it is expected that the specified DRBG is reseeded
573  *       0:  it is expected that the specified DRBG is not reseeded
574  *      -1:  don't check whether the specified DRBG was reseeded or not
575  */
576 static int test_drbg_reseed(int expect_success,
577                             RAND_DRBG *master,
578                             RAND_DRBG *public,
579                             RAND_DRBG *private,
580                             int expect_master_reseed,
581                             int expect_public_reseed,
582                             int expect_private_reseed
583                            )
584 {
585     unsigned char buf[32];
586     time_t before_reseed, after_reseed;
587     int expected_state = (expect_success ? DRBG_READY : DRBG_ERROR);
588
589     /*
590      * step 1: check preconditions
591      */
592
593     /* Test whether seed propagation is enabled */
594     if (!TEST_int_ne(master->reseed_counter, 0)
595         || !TEST_int_ne(public->reseed_counter, 0)
596         || !TEST_int_ne(private->reseed_counter, 0))
597         return 0;
598
599     /* Check whether the master DRBG's reseed counter is the largest one */
600     if (!TEST_int_le(public->reseed_counter, master->reseed_counter)
601         || !TEST_int_le(private->reseed_counter, master->reseed_counter))
602         return 0;
603
604     /*
605      * step 2: generate random output
606      */
607
608     /* Generate random output from the public and private DRBG */
609     before_reseed = expect_master_reseed == 1 ? time(NULL) : 0;
610     if (!TEST_int_eq(RAND_bytes(buf, sizeof(buf)), expect_success)
611         || !TEST_int_eq(RAND_priv_bytes(buf, sizeof(buf)), expect_success))
612         return 0;
613     after_reseed = time(NULL);
614
615
616     /*
617      * step 3: check postconditions
618      */
619
620     /* Test whether reseeding succeeded as expected */
621     if (!TEST_int_eq(master->state, expected_state)
622         || !TEST_int_eq(public->state, expected_state)
623         || !TEST_int_eq(private->state, expected_state))
624         return 0;
625
626     if (expect_master_reseed >= 0) {
627         /* Test whether master DRBG was reseeded as expected */
628         if (!TEST_int_eq(master_ctx.reseed_count, expect_master_reseed))
629             return 0;
630     }
631
632     if (expect_public_reseed >= 0) {
633         /* Test whether public DRBG was reseeded as expected */
634         if (!TEST_int_eq(public_ctx.reseed_count, expect_public_reseed))
635             return 0;
636     }
637
638     if (expect_private_reseed >= 0) {
639         /* Test whether public DRBG was reseeded as expected */
640         if (!TEST_int_eq(private_ctx.reseed_count, expect_private_reseed))
641             return 0;
642     }
643
644     if (expect_success == 1) {
645         /* Test whether all three reseed counters are synchronized */
646         if (!TEST_int_eq(public->reseed_counter, master->reseed_counter)
647             || !TEST_int_eq(private->reseed_counter, master->reseed_counter))
648             return 0;
649
650         /* Test whether reseed time of master DRBG is set correctly */
651         if (!TEST_time_t_le(before_reseed, master->reseed_time)
652             || !TEST_time_t_le(master->reseed_time, after_reseed))
653             return 0;
654
655         /* Test whether reseed times of child DRBGs are synchronized with master */
656         if (!TEST_time_t_ge(public->reseed_time, master->reseed_time)
657             || !TEST_time_t_ge(private->reseed_time, master->reseed_time))
658             return 0;
659     } else {
660         ERR_clear_error();
661     }
662
663     return 1;
664 }
665
666 /*
667  * Test whether the default rand_method (RAND_OpenSSL()) is
668  * setup correctly, in particular whether reseeding  works
669  * as designed.
670  */
671 static int test_rand_reseed(void)
672 {
673     RAND_DRBG *master, *public, *private;
674     unsigned char rand_add_buf[256];
675     int rv=0;
676
677     /* Check whether RAND_OpenSSL() is the default method */
678     if (!TEST_ptr_eq(RAND_get_rand_method(), RAND_OpenSSL()))
679         return 0;
680
681     /* All three DRBGs should be non-null */
682     if (!TEST_ptr(master = RAND_DRBG_get0_master())
683         || !TEST_ptr(public = RAND_DRBG_get0_public())
684         || !TEST_ptr(private = RAND_DRBG_get0_private()))
685         return 0;
686
687     /* There should be three distinct DRBGs, two of them chained to master */
688     if (!TEST_ptr_ne(public, private)
689         || !TEST_ptr_ne(public, master)
690         || !TEST_ptr_ne(private, master)
691         || !TEST_ptr_eq(public->parent, master)
692         || !TEST_ptr_eq(private->parent, master))
693         return 0;
694
695     /* uninstantiate the three global DRBGs */
696     RAND_DRBG_uninstantiate(private);
697     RAND_DRBG_uninstantiate(public);
698     RAND_DRBG_uninstantiate(master);
699
700
701     /* Install hooks for the following tests */
702     hook_drbg(master,  &master_ctx);
703     hook_drbg(public,  &public_ctx);
704     hook_drbg(private, &private_ctx);
705
706
707     /*
708      * Test initial seeding of shared DRBGs
709      */
710     if (!TEST_true(test_drbg_reseed(1, master, public, private, 1, 1, 1)))
711         goto error;
712     reset_drbg_hook_ctx();
713
714
715     /*
716      * Test initial state of shared DRBGs
717      */
718     if (!TEST_true(test_drbg_reseed(1, master, public, private, 0, 0, 0)))
719         goto error;
720     reset_drbg_hook_ctx();
721
722     /*
723      * Test whether the public and private DRBG are both reseeded when their
724      * reseed counters differ from the master's reseed counter.
725      */
726     master->reseed_counter++;
727     if (!TEST_true(test_drbg_reseed(1, master, public, private, 0, 1, 1)))
728         goto error;
729     reset_drbg_hook_ctx();
730
731     /*
732      * Test whether the public DRBG is reseeded when its reseed counter differs
733      * from the master's reseed counter.
734      */
735     master->reseed_counter++;
736     private->reseed_counter++;
737     if (!TEST_true(test_drbg_reseed(1, master, public, private, 0, 1, 0)))
738         goto error;
739     reset_drbg_hook_ctx();
740
741     /*
742      * Test whether the private DRBG is reseeded when its reseed counter differs
743      * from the master's reseed counter.
744      */
745     master->reseed_counter++;
746     public->reseed_counter++;
747     if (!TEST_true(test_drbg_reseed(1, master, public, private, 0, 0, 1)))
748         goto error;
749     reset_drbg_hook_ctx();
750
751
752     /* fill 'randomness' buffer with some arbitrary data */
753     memset(rand_add_buf, 'r', sizeof(rand_add_buf));
754
755     /*
756      * Test whether all three DRBGs are reseeded by RAND_add()
757      */
758     RAND_add(rand_add_buf, sizeof(rand_add_buf), sizeof(rand_add_buf));
759     if (!TEST_true(test_drbg_reseed(1, master, public, private, 1, 1, 1)))
760         goto error;
761     reset_drbg_hook_ctx();
762
763
764     /*
765      * Test whether none of the DRBGs is reseed if the master fails to reseed
766      */
767     master_ctx.fail = 1;
768     master->reseed_counter++;
769     RAND_add(rand_add_buf, sizeof(rand_add_buf), sizeof(rand_add_buf));
770     if (!TEST_true(test_drbg_reseed(0, master, public, private, 0, 0, 0)))
771         goto error;
772     reset_drbg_hook_ctx();
773
774     rv = 1;
775
776 error:
777     /* Remove hooks  */
778     unhook_drbg(master);
779     unhook_drbg(public);
780     unhook_drbg(private);
781
782     return rv;
783 }
784
785 #if defined(OPENSSL_THREADS)
786 static int multi_thread_rand_bytes_succeeded = 1;
787 static int multi_thread_rand_priv_bytes_succeeded = 1;
788
789 static void run_multi_thread_test(void)
790 {
791     unsigned char buf[256];
792     time_t start = time(NULL);
793     RAND_DRBG *public, *private;
794
795     public = RAND_DRBG_get0_public();
796     private = RAND_DRBG_get0_private();
797     RAND_DRBG_set_reseed_time_interval(public, 1);
798     RAND_DRBG_set_reseed_time_interval(private, 1);
799
800     do {
801         if (RAND_bytes(buf, sizeof(buf)) <= 0)
802             multi_thread_rand_bytes_succeeded = 0;
803         if (RAND_priv_bytes(buf, sizeof(buf)) <= 0)
804             multi_thread_rand_priv_bytes_succeeded = 0;
805     }
806     while(time(NULL) - start < 5);
807 }
808
809 # if defined(OPENSSL_SYS_WINDOWS)
810
811 typedef HANDLE thread_t;
812
813 static DWORD WINAPI thread_run(LPVOID arg)
814 {
815     run_multi_thread_test();
816     return 0;
817 }
818
819 static int run_thread(thread_t *t)
820 {
821     *t = CreateThread(NULL, 0, thread_run, NULL, 0, NULL);
822     return *t != NULL;
823 }
824
825 static int wait_for_thread(thread_t thread)
826 {
827     return WaitForSingleObject(thread, INFINITE) == 0;
828 }
829
830 # else
831
832 typedef pthread_t thread_t;
833
834 static void *thread_run(void *arg)
835 {
836     run_multi_thread_test();
837     return NULL;
838 }
839
840 static int run_thread(thread_t *t)
841 {
842     return pthread_create(t, NULL, thread_run, NULL) == 0;
843 }
844
845 static int wait_for_thread(thread_t thread)
846 {
847     return pthread_join(thread, NULL) == 0;
848 }
849
850 # endif
851
852 /*
853  * The main thread will also run the test, so we'll have THREADS+1 parallel
854  * tests running
855  */
856 # define THREADS 3
857
858 static int test_multi_thread(void)
859 {
860     thread_t t[THREADS];
861     int i;
862
863     for (i = 0; i < THREADS; i++)
864         run_thread(&t[i]);
865     run_multi_thread_test();
866     for (i = 0; i < THREADS; i++)
867         wait_for_thread(t[i]);
868
869     if (!TEST_true(multi_thread_rand_bytes_succeeded))
870         return 0;
871     if (!TEST_true(multi_thread_rand_priv_bytes_succeeded))
872         return 0;
873
874     return 1;
875 }
876 #endif
877
878 /*
879  * This function only returns the entropy already added with RAND_add(),
880  * and does not get entropy from the OS.
881  *
882  * Returns 0 on failure and the size of the buffer on success.
883  */
884 static size_t get_pool_entropy(RAND_DRBG *drbg,
885                                unsigned char **pout,
886                                int entropy, size_t min_len, size_t max_len,
887                                int prediction_resistance)
888 {
889     if (drbg->pool == NULL)
890         return 0;
891
892     if (drbg->pool->entropy < (size_t)entropy || drbg->pool->len < min_len
893         || drbg->pool->len > max_len)
894         return 0;
895
896     *pout = drbg->pool->buffer;
897     return drbg->pool->len;
898 }
899
900 /*
901  * Clean up the entropy that get_pool_entropy() returned.
902  */
903 static void cleanup_pool_entropy(RAND_DRBG *drbg, unsigned char *out, size_t outlen)
904 {
905     OPENSSL_secure_clear_free(drbg->pool->buffer, drbg->pool->max_len);
906     OPENSSL_free(drbg->pool);
907     drbg->pool = NULL;
908 }
909
910 /*
911  * Test that instantiating works when OS entropy is not available and that
912  * RAND_add() is enough to reseed it.
913  */
914 static int test_rand_add(void)
915 {
916     RAND_DRBG *master = RAND_DRBG_get0_master();
917     RAND_DRBG_get_entropy_fn old_get_entropy = master->get_entropy;
918     RAND_DRBG_cleanup_entropy_fn old_cleanup_entropy = master->cleanup_entropy;
919     int rv = 0;
920     unsigned char rand_add_buf[256];
921
922     master->get_entropy = get_pool_entropy;
923     master->cleanup_entropy = cleanup_pool_entropy;
924     master->reseed_counter++;
925     RAND_DRBG_uninstantiate(master);
926     memset(rand_add_buf, 0xCD, sizeof(rand_add_buf));
927     RAND_add(rand_add_buf, sizeof(rand_add_buf), sizeof(rand_add_buf));
928     if (!TEST_true(RAND_DRBG_instantiate(master, NULL, 0)))
929         goto error;
930
931     rv = 1;
932
933 error:
934     master->get_entropy = old_get_entropy;
935     master->cleanup_entropy = old_cleanup_entropy;
936     return rv;
937 }
938
939 int setup_tests(void)
940 {
941     app_data_index = RAND_DRBG_get_ex_new_index(0L, NULL, NULL, NULL, NULL);
942
943     ADD_ALL_TESTS(test_kats, OSSL_NELEM(drbg_test));
944     ADD_ALL_TESTS(test_error_checks, OSSL_NELEM(drbg_test));
945     ADD_TEST(test_rand_reseed);
946     ADD_TEST(test_rand_add);
947 #if defined(OPENSSL_THREADS)
948     ADD_TEST(test_multi_thread);
949 #endif
950     return 1;
951 }