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