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