1 /* 2 * Copyright 2011-2019 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 static char zero[sizeof(RAND_DRBG)]; 290 RAND_DRBG *drbg = NULL; 291 TEST_CTX t; 292 unsigned char buff[1024]; 293 unsigned int reseed_counter_tmp; 294 int ret = 0; 295 296 if (!TEST_ptr(drbg = RAND_DRBG_new(0, 0, NULL))) 297 goto err; 298 299 /* 300 * Personalisation string tests 301 */ 302 303 /* Test detection of too large personalisation string */ 304 if (!init(drbg, td, &t) 305 || RAND_DRBG_instantiate(drbg, td->pers, drbg->max_perslen + 1) > 0) 306 goto err; 307 308 /* 309 * Entropy source tests 310 */ 311 312 /* Test entropy source failure detection: i.e. returns no data */ 313 t.entropylen = 0; 314 if (TEST_int_le(RAND_DRBG_instantiate(drbg, td->pers, td->perslen), 0)) 315 goto err; 316 317 /* Try to generate output from uninstantiated DRBG */ 318 if (!TEST_false(RAND_DRBG_generate(drbg, buff, td->exlen, 0, 319 td->adin, td->adinlen)) 320 || !uninstantiate(drbg)) 321 goto err; 322 323 /* Test insufficient entropy */ 324 t.entropylen = drbg->min_entropylen - 1; 325 if (!init(drbg, td, &t) 326 || RAND_DRBG_instantiate(drbg, td->pers, td->perslen) > 0 327 || !uninstantiate(drbg)) 328 goto err; 329 330 /* Test too much entropy */ 331 t.entropylen = drbg->max_entropylen + 1; 332 if (!init(drbg, td, &t) 333 || RAND_DRBG_instantiate(drbg, td->pers, td->perslen) > 0 334 || !uninstantiate(drbg)) 335 goto err; 336 337 /* 338 * Nonce tests 339 */ 340 341 /* Test too small nonce */ 342 if (drbg->min_noncelen) { 343 t.noncelen = drbg->min_noncelen - 1; 344 if (!init(drbg, td, &t) 345 || RAND_DRBG_instantiate(drbg, td->pers, td->perslen) > 0 346 || !uninstantiate(drbg)) 347 goto err; 348 } 349 350 /* Test too large nonce */ 351 if (drbg->max_noncelen) { 352 t.noncelen = drbg->max_noncelen + 1; 353 if (!init(drbg, td, &t) 354 || RAND_DRBG_instantiate(drbg, td->pers, td->perslen) > 0 355 || !uninstantiate(drbg)) 356 goto err; 357 } 358 359 /* Instantiate with valid data, Check generation is now OK */ 360 if (!instantiate(drbg, td, &t) 361 || !TEST_true(RAND_DRBG_generate(drbg, buff, td->exlen, 0, 362 td->adin, td->adinlen))) 363 goto err; 364 365 /* Request too much data for one request */ 366 if (!TEST_false(RAND_DRBG_generate(drbg, buff, drbg->max_request + 1, 0, 367 td->adin, td->adinlen))) 368 goto err; 369 370 /* Try too large additional input */ 371 if (!TEST_false(RAND_DRBG_generate(drbg, buff, td->exlen, 0, 372 td->adin, drbg->max_adinlen + 1))) 373 goto err; 374 375 /* 376 * Check prediction resistance request fails if entropy source 377 * failure. 378 */ 379 t.entropylen = 0; 380 if (TEST_false(RAND_DRBG_generate(drbg, buff, td->exlen, 1, 381 td->adin, td->adinlen)) 382 || !uninstantiate(drbg)) 383 goto err; 384 385 /* Instantiate again with valid data */ 386 if (!instantiate(drbg, td, &t)) 387 goto err; 388 reseed_counter_tmp = drbg->reseed_gen_counter; 389 drbg->reseed_gen_counter = drbg->reseed_interval; 390 391 /* Generate output and check entropy has been requested for reseed */ 392 t.entropycnt = 0; 393 if (!TEST_true(RAND_DRBG_generate(drbg, buff, td->exlen, 0, 394 td->adin, td->adinlen)) 395 || !TEST_int_eq(t.entropycnt, 1) 396 || !TEST_int_eq(drbg->reseed_gen_counter, reseed_counter_tmp + 1) 397 || !uninstantiate(drbg)) 398 goto err; 399 400 /* 401 * Check prediction resistance request fails if entropy source 402 * failure. 403 */ 404 t.entropylen = 0; 405 if (!TEST_false(RAND_DRBG_generate(drbg, buff, td->exlen, 1, 406 td->adin, td->adinlen)) 407 || !uninstantiate(drbg)) 408 goto err; 409 410 /* Test reseed counter works */ 411 if (!instantiate(drbg, td, &t)) 412 goto err; 413 reseed_counter_tmp = drbg->reseed_gen_counter; 414 drbg->reseed_gen_counter = drbg->reseed_interval; 415 416 /* Generate output and check entropy has been requested for reseed */ 417 t.entropycnt = 0; 418 if (!TEST_true(RAND_DRBG_generate(drbg, buff, td->exlen, 0, 419 td->adin, td->adinlen)) 420 || !TEST_int_eq(t.entropycnt, 1) 421 || !TEST_int_eq(drbg->reseed_gen_counter, reseed_counter_tmp + 1) 422 || !uninstantiate(drbg)) 423 goto err; 424 425 /* 426 * Explicit reseed tests 427 */ 428 429 /* Test explicit reseed with too large additional input */ 430 if (!instantiate(drbg, td, &t) 431 || RAND_DRBG_reseed(drbg, td->adin, drbg->max_adinlen + 1, 0) > 0) 432 goto err; 433 434 /* Test explicit reseed with entropy source failure */ 435 t.entropylen = 0; 436 if (!TEST_int_le(RAND_DRBG_reseed(drbg, td->adin, td->adinlen, 0), 0) 437 || !uninstantiate(drbg)) 438 goto err; 439 440 /* Test explicit reseed with too much entropy */ 441 if (!instantiate(drbg, td, &t)) 442 goto err; 443 t.entropylen = drbg->max_entropylen + 1; 444 if (!TEST_int_le(RAND_DRBG_reseed(drbg, td->adin, td->adinlen, 0), 0) 445 || !uninstantiate(drbg)) 446 goto err; 447 448 /* Test explicit reseed with too little entropy */ 449 if (!instantiate(drbg, td, &t)) 450 goto err; 451 t.entropylen = drbg->min_entropylen - 1; 452 if (!TEST_int_le(RAND_DRBG_reseed(drbg, td->adin, td->adinlen, 0), 0) 453 || !uninstantiate(drbg)) 454 goto err; 455 456 /* Standard says we have to check uninstantiate really zeroes */ 457 if (!TEST_mem_eq(zero, sizeof(drbg->data), &drbg->data, sizeof(drbg->data))) 458 goto err; 459 460 ret = 1; 461 462 err: 463 uninstantiate(drbg); 464 RAND_DRBG_free(drbg); 465 return ret; 466 } 467 468 static int test_kats(int i) 469 { 470 DRBG_SELFTEST_DATA *td = &drbg_test[i]; 471 int rv = 0; 472 473 if (!single_kat(td)) 474 goto err; 475 rv = 1; 476 477 err: 478 return rv; 479 } 480 481 static int test_error_checks(int i) 482 { 483 DRBG_SELFTEST_DATA *td = &drbg_test[i]; 484 int rv = 0; 485 486 if (error_check(td)) 487 goto err; 488 rv = 1; 489 490 err: 491 return rv; 492 } 493 494 /* 495 * Hook context data, attached as EXDATA to the RAND_DRBG 496 */ 497 typedef struct hook_ctx_st { 498 RAND_DRBG *drbg; 499 /* 500 * Currently, all DRBGs use the same get_entropy() callback. 501 * The tests however, don't assume this and store 502 * the original callback for every DRBG separately. 503 */ 504 RAND_DRBG_get_entropy_fn get_entropy; 505 /* forces a failure of the get_entropy() call if nonzero */ 506 int fail; 507 /* counts successful reseeds */ 508 int reseed_count; 509 } HOOK_CTX; 510 511 static HOOK_CTX master_ctx, public_ctx, private_ctx; 512 513 static HOOK_CTX *get_hook_ctx(RAND_DRBG *drbg) 514 { 515 return (HOOK_CTX *)RAND_DRBG_get_ex_data(drbg, app_data_index); 516 } 517 518 /* Intercepts and counts calls to the get_entropy() callback */ 519 static size_t get_entropy_hook(RAND_DRBG *drbg, unsigned char **pout, 520 int entropy, size_t min_len, size_t max_len, 521 int prediction_resistance) 522 { 523 size_t ret; 524 HOOK_CTX *ctx = get_hook_ctx(drbg); 525 526 if (ctx->fail != 0) 527 return 0; 528 529 ret = ctx->get_entropy(drbg, pout, entropy, min_len, max_len, 530 prediction_resistance); 531 532 if (ret != 0) 533 ctx->reseed_count++; 534 return ret; 535 } 536 537 /* Installs a hook for the get_entropy() callback of the given drbg */ 538 static void hook_drbg(RAND_DRBG *drbg, HOOK_CTX *ctx) 539 { 540 memset(ctx, 0, sizeof(*ctx)); 541 ctx->drbg = drbg; 542 ctx->get_entropy = drbg->get_entropy; 543 drbg->get_entropy = get_entropy_hook; 544 RAND_DRBG_set_ex_data(drbg, app_data_index, ctx); 545 } 546 547 /* Installs the hook for the get_entropy() callback of the given drbg */ 548 static void unhook_drbg(RAND_DRBG *drbg) 549 { 550 HOOK_CTX *ctx = get_hook_ctx(drbg); 551 552 drbg->get_entropy = ctx->get_entropy; 553 CRYPTO_free_ex_data(CRYPTO_EX_INDEX_DRBG, drbg, &drbg->ex_data); 554 } 555 556 /* Resets the given hook context */ 557 static void reset_hook_ctx(HOOK_CTX *ctx) 558 { 559 ctx->fail = 0; 560 ctx->reseed_count = 0; 561 } 562 563 /* Resets all drbg hook contexts */ 564 static void reset_drbg_hook_ctx(void) 565 { 566 reset_hook_ctx(&master_ctx); 567 reset_hook_ctx(&public_ctx); 568 reset_hook_ctx(&private_ctx); 569 } 570 571 /* 572 * Generates random output using RAND_bytes() and RAND_priv_bytes() 573 * and checks whether the three shared DRBGs were reseeded as 574 * expected. 575 * 576 * |expect_success|: expected outcome (as reported by RAND_status()) 577 * |master|, |public|, |private|: pointers to the three shared DRBGs 578 * |expect_xxx_reseed| = 579 * 1: it is expected that the specified DRBG is reseeded 580 * 0: it is expected that the specified DRBG is not reseeded 581 * -1: don't check whether the specified DRBG was reseeded or not 582 * |reseed_time|: if nonzero, used instead of time(NULL) to set the 583 * |before_reseed| time. 584 */ 585 static int test_drbg_reseed(int expect_success, 586 RAND_DRBG *master, 587 RAND_DRBG *public, 588 RAND_DRBG *private, 589 int expect_master_reseed, 590 int expect_public_reseed, 591 int expect_private_reseed, 592 time_t reseed_time 593 ) 594 { 595 unsigned char buf[32]; 596 time_t before_reseed, after_reseed; 597 int expected_state = (expect_success ? DRBG_READY : DRBG_ERROR); 598 599 /* 600 * step 1: check preconditions 601 */ 602 603 /* Test whether seed propagation is enabled */ 604 if (!TEST_int_ne(master->reseed_prop_counter, 0) 605 || !TEST_int_ne(public->reseed_prop_counter, 0) 606 || !TEST_int_ne(private->reseed_prop_counter, 0)) 607 return 0; 608 609 /* Check whether the master DRBG's reseed counter is the largest one */ 610 if (!TEST_int_le(public->reseed_prop_counter, master->reseed_prop_counter) 611 || !TEST_int_le(private->reseed_prop_counter, master->reseed_prop_counter)) 612 return 0; 613 614 /* 615 * step 2: generate random output 616 */ 617 618 if (reseed_time == 0) 619 reseed_time = time(NULL); 620 621 /* Generate random output from the public and private DRBG */ 622 before_reseed = expect_master_reseed == 1 ? reseed_time : 0; 623 if (!TEST_int_eq(RAND_bytes(buf, sizeof(buf)), expect_success) 624 || !TEST_int_eq(RAND_priv_bytes(buf, sizeof(buf)), expect_success)) 625 return 0; 626 after_reseed = time(NULL); 627 628 629 /* 630 * step 3: check postconditions 631 */ 632 633 /* Test whether reseeding succeeded as expected */ 634 if (!TEST_int_eq(master->state, expected_state) 635 || !TEST_int_eq(public->state, expected_state) 636 || !TEST_int_eq(private->state, expected_state)) 637 return 0; 638 639 if (expect_master_reseed >= 0) { 640 /* Test whether master DRBG was reseeded as expected */ 641 if (!TEST_int_eq(master_ctx.reseed_count, expect_master_reseed)) 642 return 0; 643 } 644 645 if (expect_public_reseed >= 0) { 646 /* Test whether public DRBG was reseeded as expected */ 647 if (!TEST_int_eq(public_ctx.reseed_count, expect_public_reseed)) 648 return 0; 649 } 650 651 if (expect_private_reseed >= 0) { 652 /* Test whether public DRBG was reseeded as expected */ 653 if (!TEST_int_eq(private_ctx.reseed_count, expect_private_reseed)) 654 return 0; 655 } 656 657 if (expect_success == 1) { 658 /* Test whether all three reseed counters are synchronized */ 659 if (!TEST_int_eq(public->reseed_prop_counter, master->reseed_prop_counter) 660 || !TEST_int_eq(private->reseed_prop_counter, master->reseed_prop_counter)) 661 return 0; 662 663 /* Test whether reseed time of master DRBG is set correctly */ 664 if (!TEST_time_t_le(before_reseed, master->reseed_time) 665 || !TEST_time_t_le(master->reseed_time, after_reseed)) 666 return 0; 667 668 /* Test whether reseed times of child DRBGs are synchronized with master */ 669 if (!TEST_time_t_ge(public->reseed_time, master->reseed_time) 670 || !TEST_time_t_ge(private->reseed_time, master->reseed_time)) 671 return 0; 672 } else { 673 ERR_clear_error(); 674 } 675 676 return 1; 677 } 678 679 680 #if defined(OPENSSL_SYS_UNIX) 681 /* 682 * Test whether master, public and private DRBG are reseeded after 683 * forking the process. 684 */ 685 static int test_drbg_reseed_after_fork(RAND_DRBG *master, 686 RAND_DRBG *public, 687 RAND_DRBG *private) 688 { 689 pid_t pid; 690 int status=0; 691 692 pid = fork(); 693 if (!TEST_int_ge(pid, 0)) 694 return 0; 695 696 if (pid > 0) { 697 /* I'm the parent; wait for the child and check its exit code */ 698 return TEST_int_eq(waitpid(pid, &status, 0), pid) && TEST_int_eq(status, 0); 699 } 700 701 /* I'm the child; check whether all three DRBGs reseed. */ 702 if (!TEST_true(test_drbg_reseed(1, master, public, private, 1, 1, 1, 0))) 703 status = 1; 704 705 /* Remove hooks */ 706 unhook_drbg(master); 707 unhook_drbg(public); 708 unhook_drbg(private); 709 exit(status); 710 } 711 #endif 712 713 /* 714 * Test whether the default rand_method (RAND_OpenSSL()) is 715 * setup correctly, in particular whether reseeding works 716 * as designed. 717 */ 718 static int test_rand_drbg_reseed(void) 719 { 720 RAND_DRBG *master, *public, *private; 721 unsigned char rand_add_buf[256]; 722 int rv=0; 723 time_t before_reseed; 724 725 /* Check whether RAND_OpenSSL() is the default method */ 726 if (!TEST_ptr_eq(RAND_get_rand_method(), RAND_OpenSSL())) 727 return 0; 728 729 /* All three DRBGs should be non-null */ 730 if (!TEST_ptr(master = RAND_DRBG_get0_master()) 731 || !TEST_ptr(public = RAND_DRBG_get0_public()) 732 || !TEST_ptr(private = RAND_DRBG_get0_private())) 733 return 0; 734 735 /* There should be three distinct DRBGs, two of them chained to master */ 736 if (!TEST_ptr_ne(public, private) 737 || !TEST_ptr_ne(public, master) 738 || !TEST_ptr_ne(private, master) 739 || !TEST_ptr_eq(public->parent, master) 740 || !TEST_ptr_eq(private->parent, master)) 741 return 0; 742 743 /* uninstantiate the three global DRBGs */ 744 RAND_DRBG_uninstantiate(private); 745 RAND_DRBG_uninstantiate(public); 746 RAND_DRBG_uninstantiate(master); 747 748 749 /* Install hooks for the following tests */ 750 hook_drbg(master, &master_ctx); 751 hook_drbg(public, &public_ctx); 752 hook_drbg(private, &private_ctx); 753 754 755 /* 756 * Test initial seeding of shared DRBGs 757 */ 758 if (!TEST_true(test_drbg_reseed(1, master, public, private, 1, 1, 1, 0))) 759 goto error; 760 reset_drbg_hook_ctx(); 761 762 763 /* 764 * Test initial state of shared DRBGs 765 */ 766 if (!TEST_true(test_drbg_reseed(1, master, public, private, 0, 0, 0, 0))) 767 goto error; 768 reset_drbg_hook_ctx(); 769 770 /* 771 * Test whether the public and private DRBG are both reseeded when their 772 * reseed counters differ from the master's reseed counter. 773 */ 774 master->reseed_prop_counter++; 775 if (!TEST_true(test_drbg_reseed(1, master, public, private, 0, 1, 1, 0))) 776 goto error; 777 reset_drbg_hook_ctx(); 778 779 /* 780 * Test whether the public DRBG is reseeded when its reseed counter differs 781 * from the master's reseed counter. 782 */ 783 master->reseed_prop_counter++; 784 private->reseed_prop_counter++; 785 if (!TEST_true(test_drbg_reseed(1, master, public, private, 0, 1, 0, 0))) 786 goto error; 787 reset_drbg_hook_ctx(); 788 789 /* 790 * Test whether the private DRBG is reseeded when its reseed counter differs 791 * from the master's reseed counter. 792 */ 793 master->reseed_prop_counter++; 794 public->reseed_prop_counter++; 795 if (!TEST_true(test_drbg_reseed(1, master, public, private, 0, 0, 1, 0))) 796 goto error; 797 reset_drbg_hook_ctx(); 798 799 #if defined(OPENSSL_SYS_UNIX) 800 if (!TEST_true(test_drbg_reseed_after_fork(master, public, private))) 801 goto error; 802 #endif 803 804 /* fill 'randomness' buffer with some arbitrary data */ 805 memset(rand_add_buf, 'r', sizeof(rand_add_buf)); 806 807 /* 808 * Test whether all three DRBGs are reseeded by RAND_add(). 809 * The before_reseed time has to be measured here and passed into the 810 * test_drbg_reseed() test, because the master DRBG gets already reseeded 811 * in RAND_add(), whence the check for the condition 812 * before_reseed <= master->reseed_time will fail if the time value happens 813 * to increase between the RAND_add() and the test_drbg_reseed() call. 814 */ 815 before_reseed = time(NULL); 816 RAND_add(rand_add_buf, sizeof(rand_add_buf), sizeof(rand_add_buf)); 817 if (!TEST_true(test_drbg_reseed(1, master, public, private, 1, 1, 1, 818 before_reseed))) 819 goto error; 820 reset_drbg_hook_ctx(); 821 822 823 /* 824 * Test whether none of the DRBGs is reseed if the master fails to reseed 825 */ 826 master_ctx.fail = 1; 827 master->reseed_prop_counter++; 828 RAND_add(rand_add_buf, sizeof(rand_add_buf), sizeof(rand_add_buf)); 829 if (!TEST_true(test_drbg_reseed(0, master, public, private, 0, 0, 0, 0))) 830 goto error; 831 reset_drbg_hook_ctx(); 832 833 rv = 1; 834 835 error: 836 /* Remove hooks */ 837 unhook_drbg(master); 838 unhook_drbg(public); 839 unhook_drbg(private); 840 841 return rv; 842 } 843 844 #if defined(OPENSSL_THREADS) 845 static int multi_thread_rand_bytes_succeeded = 1; 846 static int multi_thread_rand_priv_bytes_succeeded = 1; 847 848 static void run_multi_thread_test(void) 849 { 850 unsigned char buf[256]; 851 time_t start = time(NULL); 852 RAND_DRBG *public = NULL, *private = NULL; 853 854 if (!TEST_ptr(public = RAND_DRBG_get0_public()) 855 || !TEST_ptr(private = RAND_DRBG_get0_private())) { 856 multi_thread_rand_bytes_succeeded = 0; 857 return; 858 } 859 RAND_DRBG_set_reseed_time_interval(private, 1); 860 RAND_DRBG_set_reseed_time_interval(public, 1); 861 862 do { 863 if (RAND_bytes(buf, sizeof(buf)) <= 0) 864 multi_thread_rand_bytes_succeeded = 0; 865 if (RAND_priv_bytes(buf, sizeof(buf)) <= 0) 866 multi_thread_rand_priv_bytes_succeeded = 0; 867 } 868 while(time(NULL) - start < 5); 869 } 870 871 # if defined(OPENSSL_SYS_WINDOWS) 872 873 typedef HANDLE thread_t; 874 875 static DWORD WINAPI thread_run(LPVOID arg) 876 { 877 run_multi_thread_test(); 878 /* 879 * Because we're linking with a static library, we must stop each 880 * thread explicitly, or so says OPENSSL_thread_stop(3) 881 */ 882 OPENSSL_thread_stop(); 883 return 0; 884 } 885 886 static int run_thread(thread_t *t) 887 { 888 *t = CreateThread(NULL, 0, thread_run, NULL, 0, NULL); 889 return *t != NULL; 890 } 891 892 static int wait_for_thread(thread_t thread) 893 { 894 return WaitForSingleObject(thread, INFINITE) == 0; 895 } 896 897 # else 898 899 typedef pthread_t thread_t; 900 901 static void *thread_run(void *arg) 902 { 903 run_multi_thread_test(); 904 /* 905 * Because we're linking with a static library, we must stop each 906 * thread explicitly, or so says OPENSSL_thread_stop(3) 907 */ 908 OPENSSL_thread_stop(); 909 return NULL; 910 } 911 912 static int run_thread(thread_t *t) 913 { 914 return pthread_create(t, NULL, thread_run, NULL) == 0; 915 } 916 917 static int wait_for_thread(thread_t thread) 918 { 919 return pthread_join(thread, NULL) == 0; 920 } 921 922 # endif 923 924 /* 925 * The main thread will also run the test, so we'll have THREADS+1 parallel 926 * tests running 927 */ 928 # define THREADS 3 929 930 static int test_multi_thread(void) 931 { 932 thread_t t[THREADS]; 933 int i; 934 935 for (i = 0; i < THREADS; i++) 936 run_thread(&t[i]); 937 run_multi_thread_test(); 938 for (i = 0; i < THREADS; i++) 939 wait_for_thread(t[i]); 940 941 if (!TEST_true(multi_thread_rand_bytes_succeeded)) 942 return 0; 943 if (!TEST_true(multi_thread_rand_priv_bytes_succeeded)) 944 return 0; 945 946 return 1; 947 } 948 #endif 949 950 /* 951 * Test that instantiation with RAND_seed() works as expected 952 * 953 * If no os entropy source is available then RAND_seed(buffer, bufsize) 954 * is expected to succeed if and only if the buffer length is at least 955 * rand_drbg_seedlen(master) bytes. 956 * 957 * If an os entropy source is available then RAND_seed(buffer, bufsize) 958 * is expected to succeed always. 959 */ 960 static int test_rand_seed(void) 961 { 962 RAND_DRBG *master = NULL; 963 unsigned char rand_buf[256]; 964 size_t rand_buflen; 965 size_t required_seed_buflen = 0; 966 967 if (!TEST_ptr(master = RAND_DRBG_get0_master())) 968 return 0; 969 970 #ifdef OPENSSL_RAND_SEED_NONE 971 required_seed_buflen = rand_drbg_seedlen(master); 972 #endif 973 974 memset(rand_buf, 0xCD, sizeof(rand_buf)); 975 976 for ( rand_buflen = 256 ; rand_buflen > 0 ; --rand_buflen ) { 977 RAND_DRBG_uninstantiate(master); 978 RAND_seed(rand_buf, rand_buflen); 979 980 if (!TEST_int_eq(RAND_status(), 981 (rand_buflen >= required_seed_buflen))) 982 return 0; 983 } 984 985 return 1; 986 } 987 988 /* 989 * Test that adding additional data with RAND_add() works as expected 990 * when the master DRBG is instantiated (and below its reseed limit). 991 * 992 * This should succeed regardless of whether an os entropy source is 993 * available or not. 994 */ 995 static int test_rand_add(void) 996 { 997 unsigned char rand_buf[256]; 998 size_t rand_buflen; 999 1000 memset(rand_buf, 0xCD, sizeof(rand_buf)); 1001 1002 /* make sure it's instantiated */ 1003 RAND_seed(rand_buf, sizeof(rand_buf)); 1004 if (!TEST_true(RAND_status())) 1005 return 0; 1006 1007 for ( rand_buflen = 256 ; rand_buflen > 0 ; --rand_buflen ) { 1008 RAND_add(rand_buf, rand_buflen, 0.0); 1009 if (!TEST_true(RAND_status())) 1010 return 0; 1011 } 1012 1013 return 1; 1014 } 1015 1016 int setup_tests(void) 1017 { 1018 app_data_index = RAND_DRBG_get_ex_new_index(0L, NULL, NULL, NULL, NULL); 1019 1020 ADD_ALL_TESTS(test_kats, OSSL_NELEM(drbg_test)); 1021 ADD_ALL_TESTS(test_error_checks, OSSL_NELEM(drbg_test)); 1022 ADD_TEST(test_rand_drbg_reseed); 1023 ADD_TEST(test_rand_seed); 1024 ADD_TEST(test_rand_add); 1025 #if defined(OPENSSL_THREADS) 1026 ADD_TEST(test_multi_thread); 1027 #endif 1028 return 1; 1029 } 1030