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 } 1029