Fix no-ec and no-tls1_2
[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 reseed_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 detection: 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     reseed_counter_tmp = drbg->reseed_gen_counter;
382     drbg->reseed_gen_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->reseed_gen_counter, reseed_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     reseed_counter_tmp = drbg->reseed_gen_counter;
407     drbg->reseed_gen_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->reseed_gen_counter, reseed_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  * |reseed_time|: if nonzero, used instead of time(NULL) to set the
576  *                |before_reseed| time.
577  */
578 static int test_drbg_reseed(int expect_success,
579                             RAND_DRBG *master,
580                             RAND_DRBG *public,
581                             RAND_DRBG *private,
582                             int expect_master_reseed,
583                             int expect_public_reseed,
584                             int expect_private_reseed,
585                             time_t reseed_time
586                            )
587 {
588     unsigned char buf[32];
589     time_t before_reseed, after_reseed;
590     int expected_state = (expect_success ? DRBG_READY : DRBG_ERROR);
591
592     /*
593      * step 1: check preconditions
594      */
595
596     /* Test whether seed propagation is enabled */
597     if (!TEST_int_ne(master->reseed_prop_counter, 0)
598         || !TEST_int_ne(public->reseed_prop_counter, 0)
599         || !TEST_int_ne(private->reseed_prop_counter, 0))
600         return 0;
601
602     /* Check whether the master DRBG's reseed counter is the largest one */
603     if (!TEST_int_le(public->reseed_prop_counter, master->reseed_prop_counter)
604         || !TEST_int_le(private->reseed_prop_counter, master->reseed_prop_counter))
605         return 0;
606
607     /*
608      * step 2: generate random output
609      */
610
611     if (reseed_time == 0)
612         reseed_time = time(NULL);
613
614     /* Generate random output from the public and private DRBG */
615     before_reseed = expect_master_reseed == 1 ? reseed_time : 0;
616     if (!TEST_int_eq(RAND_bytes(buf, sizeof(buf)), expect_success)
617         || !TEST_int_eq(RAND_priv_bytes(buf, sizeof(buf)), expect_success))
618         return 0;
619     after_reseed = time(NULL);
620
621
622     /*
623      * step 3: check postconditions
624      */
625
626     /* Test whether reseeding succeeded as expected */
627     if (!TEST_int_eq(master->state, expected_state)
628         || !TEST_int_eq(public->state, expected_state)
629         || !TEST_int_eq(private->state, expected_state))
630         return 0;
631
632     if (expect_master_reseed >= 0) {
633         /* Test whether master DRBG was reseeded as expected */
634         if (!TEST_int_eq(master_ctx.reseed_count, expect_master_reseed))
635             return 0;
636     }
637
638     if (expect_public_reseed >= 0) {
639         /* Test whether public DRBG was reseeded as expected */
640         if (!TEST_int_eq(public_ctx.reseed_count, expect_public_reseed))
641             return 0;
642     }
643
644     if (expect_private_reseed >= 0) {
645         /* Test whether public DRBG was reseeded as expected */
646         if (!TEST_int_eq(private_ctx.reseed_count, expect_private_reseed))
647             return 0;
648     }
649
650     if (expect_success == 1) {
651         /* Test whether all three reseed counters are synchronized */
652         if (!TEST_int_eq(public->reseed_prop_counter, master->reseed_prop_counter)
653             || !TEST_int_eq(private->reseed_prop_counter, master->reseed_prop_counter))
654             return 0;
655
656         /* Test whether reseed time of master DRBG is set correctly */
657         if (!TEST_time_t_le(before_reseed, master->reseed_time)
658             || !TEST_time_t_le(master->reseed_time, after_reseed))
659             return 0;
660
661         /* Test whether reseed times of child DRBGs are synchronized with master */
662         if (!TEST_time_t_ge(public->reseed_time, master->reseed_time)
663             || !TEST_time_t_ge(private->reseed_time, master->reseed_time))
664             return 0;
665     } else {
666         ERR_clear_error();
667     }
668
669     return 1;
670 }
671
672 /*
673  * Test whether the default rand_method (RAND_OpenSSL()) is
674  * setup correctly, in particular whether reseeding  works
675  * as designed.
676  */
677 static int test_rand_drbg_reseed(void)
678 {
679     RAND_DRBG *master, *public, *private;
680     unsigned char rand_add_buf[256];
681     int rv=0;
682     time_t before_reseed;
683
684     /* Check whether RAND_OpenSSL() is the default method */
685     if (!TEST_ptr_eq(RAND_get_rand_method(), RAND_OpenSSL()))
686         return 0;
687
688     /* All three DRBGs should be non-null */
689     if (!TEST_ptr(master = RAND_DRBG_get0_master())
690         || !TEST_ptr(public = RAND_DRBG_get0_public())
691         || !TEST_ptr(private = RAND_DRBG_get0_private()))
692         return 0;
693
694     /* There should be three distinct DRBGs, two of them chained to master */
695     if (!TEST_ptr_ne(public, private)
696         || !TEST_ptr_ne(public, master)
697         || !TEST_ptr_ne(private, master)
698         || !TEST_ptr_eq(public->parent, master)
699         || !TEST_ptr_eq(private->parent, master))
700         return 0;
701
702     /* uninstantiate the three global DRBGs */
703     RAND_DRBG_uninstantiate(private);
704     RAND_DRBG_uninstantiate(public);
705     RAND_DRBG_uninstantiate(master);
706
707
708     /* Install hooks for the following tests */
709     hook_drbg(master,  &master_ctx);
710     hook_drbg(public,  &public_ctx);
711     hook_drbg(private, &private_ctx);
712
713
714     /*
715      * Test initial seeding of shared DRBGs
716      */
717     if (!TEST_true(test_drbg_reseed(1, master, public, private, 1, 1, 1, 0)))
718         goto error;
719     reset_drbg_hook_ctx();
720
721
722     /*
723      * Test initial state of shared DRBGs
724      */
725     if (!TEST_true(test_drbg_reseed(1, master, public, private, 0, 0, 0, 0)))
726         goto error;
727     reset_drbg_hook_ctx();
728
729     /*
730      * Test whether the public and private DRBG are both reseeded when their
731      * reseed counters differ from the master's reseed counter.
732      */
733     master->reseed_prop_counter++;
734     if (!TEST_true(test_drbg_reseed(1, master, public, private, 0, 1, 1, 0)))
735         goto error;
736     reset_drbg_hook_ctx();
737
738     /*
739      * Test whether the public DRBG is reseeded when its reseed counter differs
740      * from the master's reseed counter.
741      */
742     master->reseed_prop_counter++;
743     private->reseed_prop_counter++;
744     if (!TEST_true(test_drbg_reseed(1, master, public, private, 0, 1, 0, 0)))
745         goto error;
746     reset_drbg_hook_ctx();
747
748     /*
749      * Test whether the private DRBG is reseeded when its reseed counter differs
750      * from the master's reseed counter.
751      */
752     master->reseed_prop_counter++;
753     public->reseed_prop_counter++;
754     if (!TEST_true(test_drbg_reseed(1, master, public, private, 0, 0, 1, 0)))
755         goto error;
756     reset_drbg_hook_ctx();
757
758
759     /* fill 'randomness' buffer with some arbitrary data */
760     memset(rand_add_buf, 'r', sizeof(rand_add_buf));
761
762     /*
763      * Test whether all three DRBGs are reseeded by RAND_add().
764      * The before_reseed time has to be measured here and passed into the
765      * test_drbg_reseed() test, because the master DRBG gets already reseeded
766      * in RAND_add(), whence the check for the condition
767      * before_reseed <= master->reseed_time will fail if the time value happens
768      * to increase between the RAND_add() and the test_drbg_reseed() call.
769      */
770     before_reseed = time(NULL);
771     RAND_add(rand_add_buf, sizeof(rand_add_buf), sizeof(rand_add_buf));
772     if (!TEST_true(test_drbg_reseed(1, master, public, private, 1, 1, 1,
773                                     before_reseed)))
774         goto error;
775     reset_drbg_hook_ctx();
776
777
778     /*
779      * Test whether none of the DRBGs is reseed if the master fails to reseed
780      */
781     master_ctx.fail = 1;
782     master->reseed_prop_counter++;
783     RAND_add(rand_add_buf, sizeof(rand_add_buf), sizeof(rand_add_buf));
784     if (!TEST_true(test_drbg_reseed(0, master, public, private, 0, 0, 0, 0)))
785         goto error;
786     reset_drbg_hook_ctx();
787
788     rv = 1;
789
790 error:
791     /* Remove hooks  */
792     unhook_drbg(master);
793     unhook_drbg(public);
794     unhook_drbg(private);
795
796     return rv;
797 }
798
799 #if defined(OPENSSL_THREADS)
800 static int multi_thread_rand_bytes_succeeded = 1;
801 static int multi_thread_rand_priv_bytes_succeeded = 1;
802
803 static void run_multi_thread_test(void)
804 {
805     unsigned char buf[256];
806     time_t start = time(NULL);
807     RAND_DRBG *public = NULL, *private = NULL;
808
809     if (!TEST_ptr(public = RAND_DRBG_get0_public())
810             || !TEST_ptr(private = RAND_DRBG_get0_private())) {
811         multi_thread_rand_bytes_succeeded = 0;
812         return;
813     }
814     RAND_DRBG_set_reseed_time_interval(private, 1);
815     RAND_DRBG_set_reseed_time_interval(public, 1);
816
817     do {
818         if (RAND_bytes(buf, sizeof(buf)) <= 0)
819             multi_thread_rand_bytes_succeeded = 0;
820         if (RAND_priv_bytes(buf, sizeof(buf)) <= 0)
821             multi_thread_rand_priv_bytes_succeeded = 0;
822     }
823     while(time(NULL) - start < 5);
824 }
825
826 # if defined(OPENSSL_SYS_WINDOWS)
827
828 typedef HANDLE thread_t;
829
830 static DWORD WINAPI thread_run(LPVOID arg)
831 {
832     run_multi_thread_test();
833     return 0;
834 }
835
836 static int run_thread(thread_t *t)
837 {
838     *t = CreateThread(NULL, 0, thread_run, NULL, 0, NULL);
839     return *t != NULL;
840 }
841
842 static int wait_for_thread(thread_t thread)
843 {
844     return WaitForSingleObject(thread, INFINITE) == 0;
845 }
846
847 # else
848
849 typedef pthread_t thread_t;
850
851 static void *thread_run(void *arg)
852 {
853     run_multi_thread_test();
854     return NULL;
855 }
856
857 static int run_thread(thread_t *t)
858 {
859     return pthread_create(t, NULL, thread_run, NULL) == 0;
860 }
861
862 static int wait_for_thread(thread_t thread)
863 {
864     return pthread_join(thread, NULL) == 0;
865 }
866
867 # endif
868
869 /*
870  * The main thread will also run the test, so we'll have THREADS+1 parallel
871  * tests running
872  */
873 # define THREADS 3
874
875 static int test_multi_thread(void)
876 {
877     thread_t t[THREADS];
878     int i;
879
880     for (i = 0; i < THREADS; i++)
881         run_thread(&t[i]);
882     run_multi_thread_test();
883     for (i = 0; i < THREADS; i++)
884         wait_for_thread(t[i]);
885
886     if (!TEST_true(multi_thread_rand_bytes_succeeded))
887         return 0;
888     if (!TEST_true(multi_thread_rand_priv_bytes_succeeded))
889         return 0;
890
891     return 1;
892 }
893 #endif
894
895 /*
896  * Test that instantiation with RAND_seed() works as expected
897  *
898  * If no os entropy source is available then RAND_seed(buffer, bufsize)
899  * is expected to succeed if and only if the buffer length is at least
900  * rand_drbg_seedlen(master) bytes.
901  *
902  * If an os entropy source is available then RAND_seed(buffer, bufsize)
903  * is expected to succeed always.
904  */
905 static int test_rand_seed(void)
906 {
907     RAND_DRBG *master = NULL;
908     unsigned char rand_buf[256];
909     size_t rand_buflen;
910     size_t required_seed_buflen = 0;
911
912     if (!TEST_ptr(master = RAND_DRBG_get0_master()))
913         return 0;
914
915 #ifdef OPENSSL_RAND_SEED_NONE
916     required_seed_buflen = rand_drbg_seedlen(master);
917 #endif
918
919     memset(rand_buf, 0xCD, sizeof(rand_buf));
920
921     for ( rand_buflen = 256 ; rand_buflen > 0 ; --rand_buflen ) {
922         RAND_DRBG_uninstantiate(master);
923         RAND_seed(rand_buf, rand_buflen);
924
925         if (!TEST_int_eq(RAND_status(),
926                          (rand_buflen >= required_seed_buflen)))
927             return 0;
928     }
929
930     return 1;
931 }
932
933 /*
934  * Test that adding additional data with RAND_add() works as expected
935  * when the master DRBG is instantiated (and below its reseed limit).
936  *
937  * This should succeed regardless of whether an os entropy source is
938  * available or not.
939  */
940 static int test_rand_add(void)
941 {
942     unsigned char rand_buf[256];
943     size_t rand_buflen;
944
945     memset(rand_buf, 0xCD, sizeof(rand_buf));
946
947     /* make sure it's instantiated */
948     RAND_seed(rand_buf, sizeof(rand_buf));
949     if (!TEST_true(RAND_status()))
950         return 0;
951
952     for ( rand_buflen = 256 ; rand_buflen > 0 ; --rand_buflen ) {
953         RAND_add(rand_buf, rand_buflen, 0.0);
954         if (!TEST_true(RAND_status()))
955             return 0;
956     }
957
958     return 1;
959 }
960
961 int setup_tests(void)
962 {
963     app_data_index = RAND_DRBG_get_ex_new_index(0L, NULL, NULL, NULL, NULL);
964
965     ADD_ALL_TESTS(test_kats, OSSL_NELEM(drbg_test));
966     ADD_ALL_TESTS(test_error_checks, OSSL_NELEM(drbg_test));
967     ADD_TEST(test_rand_drbg_reseed);
968     ADD_TEST(test_rand_seed);
969     ADD_TEST(test_rand_add);
970 #if defined(OPENSSL_THREADS)
971     ADD_TEST(test_multi_thread);
972 #endif
973     return 1;
974 }