1 /* 2 * Copyright 2011-2022 The OpenSSL Project Authors. All Rights Reserved. 3 * 4 * Licensed under the Apache License 2.0 (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 /* We need to use some deprecated APIs */ 11 #define OPENSSL_SUPPRESS_DEPRECATED 12 13 #include <string.h> 14 #include "internal/nelem.h" 15 #include <openssl/crypto.h> 16 #include <openssl/err.h> 17 #include <openssl/rand.h> 18 #include <openssl/obj_mac.h> 19 #include <openssl/evp.h> 20 #include <openssl/aes.h> 21 #include "../crypto/rand/rand_local.h" 22 #include "../include/crypto/rand.h" 23 #include "../include/crypto/evp.h" 24 #include "../providers/implementations/rands/drbg_local.h" 25 #include "../crypto/evp/evp_local.h" 26 27 #if defined(_WIN32) 28 # include <windows.h> 29 #endif 30 31 #if defined(__TANDEM) 32 # if defined(OPENSSL_TANDEM_FLOSS) 33 # include <floss.h(floss_fork)> 34 # endif 35 #endif 36 37 #if defined(OPENSSL_SYS_UNIX) 38 # include <sys/types.h> 39 # include <sys/wait.h> 40 # include <unistd.h> 41 #endif 42 43 #include "testutil.h" 44 45 /* 46 * DRBG generate wrappers 47 */ 48 static int gen_bytes(EVP_RAND_CTX *drbg, unsigned char *buf, int num) 49 { 50 #ifndef OPENSSL_NO_DEPRECATED_3_0 51 const RAND_METHOD *meth = RAND_get_rand_method(); 52 53 if (meth != NULL && meth != RAND_OpenSSL()) { 54 if (meth->bytes != NULL) 55 return meth->bytes(buf, num); 56 return -1; 57 } 58 #endif 59 60 if (drbg != NULL) 61 return EVP_RAND_generate(drbg, buf, num, 0, 0, NULL, 0); 62 return 0; 63 } 64 65 static int rand_bytes(unsigned char *buf, int num) 66 { 67 return gen_bytes(RAND_get0_public(NULL), buf, num); 68 } 69 70 static int rand_priv_bytes(unsigned char *buf, int num) 71 { 72 return gen_bytes(RAND_get0_private(NULL), buf, num); 73 } 74 75 76 /* size of random output generated in test_drbg_reseed() */ 77 #define RANDOM_SIZE 16 78 79 /* 80 * DRBG query functions 81 */ 82 static int state(EVP_RAND_CTX *drbg) 83 { 84 return EVP_RAND_get_state(drbg); 85 } 86 87 static unsigned int query_rand_uint(EVP_RAND_CTX *drbg, const char *name) 88 { 89 OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END }; 90 unsigned int n; 91 92 *params = OSSL_PARAM_construct_uint(name, &n); 93 if (EVP_RAND_CTX_get_params(drbg, params)) 94 return n; 95 return 0; 96 } 97 98 #define DRBG_UINT(name) \ 99 static unsigned int name(EVP_RAND_CTX *drbg) \ 100 { \ 101 return query_rand_uint(drbg, #name); \ 102 } 103 DRBG_UINT(reseed_counter) 104 105 static PROV_DRBG *prov_rand(EVP_RAND_CTX *drbg) 106 { 107 return (PROV_DRBG *)drbg->algctx; 108 } 109 110 static void set_reseed_counter(EVP_RAND_CTX *drbg, unsigned int n) 111 { 112 PROV_DRBG *p = prov_rand(drbg); 113 114 p->reseed_counter = n; 115 } 116 117 static void inc_reseed_counter(EVP_RAND_CTX *drbg) 118 { 119 set_reseed_counter(drbg, reseed_counter(drbg) + 1); 120 } 121 122 static time_t reseed_time(EVP_RAND_CTX *drbg) 123 { 124 OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END }; 125 time_t t; 126 127 *params = OSSL_PARAM_construct_time_t(OSSL_DRBG_PARAM_RESEED_TIME, &t); 128 if (EVP_RAND_CTX_get_params(drbg, params)) 129 return t; 130 return 0; 131 } 132 133 /* 134 * When building the FIPS module, it isn't possible to disable the continuous 135 * RNG tests. Tests that require this are skipped and this means a detection 136 * mechanism for the FIPS provider being in use. 137 */ 138 static int using_fips_rng(void) 139 { 140 EVP_RAND_CTX *primary = RAND_get0_primary(NULL); 141 const OSSL_PROVIDER *prov; 142 const char *name; 143 144 if (!TEST_ptr(primary)) 145 return 0; 146 147 prov = EVP_RAND_get0_provider(EVP_RAND_CTX_get0_rand(primary)); 148 if (!TEST_ptr(prov)) 149 return 0; 150 name = OSSL_PROVIDER_get0_name(prov); 151 return strcmp(name, "OpenSSL FIPS Provider") == 0; 152 } 153 154 /* 155 * Disable CRNG testing if it is enabled. 156 * This stub remains to indicate the calling locations where it is necessary. 157 * Once the RNG infrastructure is able to disable these tests, it should be 158 * reconstituted. 159 */ 160 static int disable_crngt(EVP_RAND_CTX *drbg) 161 { 162 return 1; 163 } 164 165 /* 166 * Generates random output using rand_bytes() and rand_priv_bytes() 167 * and checks whether the three shared DRBGs were reseeded as 168 * expected. 169 * 170 * |expect_success|: expected outcome (as reported by RAND_status()) 171 * |primary|, |public|, |private|: pointers to the three shared DRBGs 172 * |public_random|, |private_random|: generated random output 173 * |expect_xxx_reseed| = 174 * 1: it is expected that the specified DRBG is reseeded 175 * 0: it is expected that the specified DRBG is not reseeded 176 * -1: don't check whether the specified DRBG was reseeded or not 177 * |reseed_when|: if nonzero, used instead of time(NULL) to set the 178 * |before_reseed| time. 179 */ 180 static int test_drbg_reseed(int expect_success, 181 EVP_RAND_CTX *primary, 182 EVP_RAND_CTX *public, 183 EVP_RAND_CTX *private, 184 unsigned char *public_random, 185 unsigned char *private_random, 186 int expect_primary_reseed, 187 int expect_public_reseed, 188 int expect_private_reseed, 189 time_t reseed_when 190 ) 191 { 192 time_t before_reseed, after_reseed; 193 int expected_state = (expect_success ? DRBG_READY : DRBG_ERROR); 194 unsigned int primary_reseed, public_reseed, private_reseed; 195 unsigned char dummy[RANDOM_SIZE]; 196 197 if (public_random == NULL) 198 public_random = dummy; 199 200 if (private_random == NULL) 201 private_random = dummy; 202 203 /* 204 * step 1: check preconditions 205 */ 206 207 /* Test whether seed propagation is enabled */ 208 if (!TEST_int_ne(primary_reseed = reseed_counter(primary), 0) 209 || !TEST_int_ne(public_reseed = reseed_counter(public), 0) 210 || !TEST_int_ne(private_reseed = reseed_counter(private), 0)) 211 return 0; 212 213 /* 214 * step 2: generate random output 215 */ 216 217 if (reseed_when == 0) 218 reseed_when = time(NULL); 219 220 /* Generate random output from the public and private DRBG */ 221 before_reseed = expect_primary_reseed == 1 ? reseed_when : 0; 222 if (!TEST_int_eq(rand_bytes((unsigned char*)public_random, 223 RANDOM_SIZE), expect_success) 224 || !TEST_int_eq(rand_priv_bytes((unsigned char*) private_random, 225 RANDOM_SIZE), expect_success)) 226 return 0; 227 after_reseed = time(NULL); 228 229 230 /* 231 * step 3: check postconditions 232 */ 233 234 /* Test whether reseeding succeeded as expected */ 235 if (!TEST_int_eq(state(primary), expected_state) 236 || !TEST_int_eq(state(public), expected_state) 237 || !TEST_int_eq(state(private), expected_state)) 238 return 0; 239 240 if (expect_primary_reseed >= 0) { 241 /* Test whether primary DRBG was reseeded as expected */ 242 if (!TEST_int_ge(reseed_counter(primary), primary_reseed)) 243 return 0; 244 } 245 246 if (expect_public_reseed >= 0) { 247 /* Test whether public DRBG was reseeded as expected */ 248 if (!TEST_int_ge(reseed_counter(public), public_reseed) 249 || !TEST_uint_ge(reseed_counter(public), 250 reseed_counter(primary))) 251 return 0; 252 } 253 254 if (expect_private_reseed >= 0) { 255 /* Test whether public DRBG was reseeded as expected */ 256 if (!TEST_int_ge(reseed_counter(private), private_reseed) 257 || !TEST_uint_ge(reseed_counter(private), 258 reseed_counter(primary))) 259 return 0; 260 } 261 262 if (expect_success == 1) { 263 /* Test whether reseed time of primary DRBG is set correctly */ 264 if (!TEST_time_t_le(before_reseed, reseed_time(primary)) 265 || !TEST_time_t_le(reseed_time(primary), after_reseed)) 266 return 0; 267 268 /* Test whether reseed times of child DRBGs are synchronized with primary */ 269 if (!TEST_time_t_ge(reseed_time(public), reseed_time(primary)) 270 || !TEST_time_t_ge(reseed_time(private), reseed_time(primary))) 271 return 0; 272 } else { 273 ERR_clear_error(); 274 } 275 276 return 1; 277 } 278 279 280 #if defined(OPENSSL_SYS_UNIX) && !defined(OPENSSL_RAND_SEED_EGD) 281 /* number of children to fork */ 282 #define DRBG_FORK_COUNT 9 283 /* two results per child, two for the parent */ 284 #define DRBG_FORK_RESULT_COUNT (2 * (DRBG_FORK_COUNT + 1)) 285 286 typedef struct drbg_fork_result_st { 287 288 unsigned char random[RANDOM_SIZE]; /* random output */ 289 290 int pindex; /* process index (0: parent, 1,2,3...: children)*/ 291 pid_t pid; /* process id */ 292 int private; /* true if the private drbg was used */ 293 char name[10]; /* 'parent' resp. 'child 1', 'child 2', ... */ 294 } drbg_fork_result; 295 296 /* 297 * Sort the drbg_fork_result entries in lexicographical order 298 * 299 * This simplifies finding duplicate random output and makes 300 * the printout in case of an error more readable. 301 */ 302 static int compare_drbg_fork_result(const void * left, const void * right) 303 { 304 int result; 305 const drbg_fork_result *l = left; 306 const drbg_fork_result *r = right; 307 308 /* separate public and private results */ 309 result = l->private - r->private; 310 311 if (result == 0) 312 result = memcmp(l->random, r->random, RANDOM_SIZE); 313 314 if (result == 0) 315 result = l->pindex - r->pindex; 316 317 return result; 318 } 319 320 /* 321 * Sort two-byte chunks of random data 322 * 323 * Used for finding collisions in two-byte chunks 324 */ 325 static int compare_rand_chunk(const void * left, const void * right) 326 { 327 return memcmp(left, right, 2); 328 } 329 330 /* 331 * Test whether primary, public and private DRBG are reseeded 332 * in the child after forking the process. Collect the random 333 * output of the public and private DRBG and send it back to 334 * the parent process. 335 */ 336 static int test_drbg_reseed_in_child(EVP_RAND_CTX *primary, 337 EVP_RAND_CTX *public, 338 EVP_RAND_CTX *private, 339 drbg_fork_result result[2]) 340 { 341 int rv = 0, status; 342 int fd[2]; 343 pid_t pid; 344 unsigned char random[2 * RANDOM_SIZE]; 345 346 if (!TEST_int_ge(pipe(fd), 0)) 347 return 0; 348 349 if (!TEST_int_ge(pid = fork(), 0)) { 350 close(fd[0]); 351 close(fd[1]); 352 return 0; 353 } else if (pid > 0) { 354 355 /* I'm the parent; close the write end */ 356 close(fd[1]); 357 358 /* wait for children to terminate and collect their random output */ 359 if (TEST_int_eq(waitpid(pid, &status, 0), pid) 360 && TEST_int_eq(status, 0) 361 && TEST_true(read(fd[0], &random[0], sizeof(random)) 362 == sizeof(random))) { 363 364 /* random output of public drbg */ 365 result[0].pid = pid; 366 result[0].private = 0; 367 memcpy(result[0].random, &random[0], RANDOM_SIZE); 368 369 /* random output of private drbg */ 370 result[1].pid = pid; 371 result[1].private = 1; 372 memcpy(result[1].random, &random[RANDOM_SIZE], RANDOM_SIZE); 373 374 rv = 1; 375 } 376 377 /* close the read end */ 378 close(fd[0]); 379 380 return rv; 381 382 } else { 383 384 /* I'm the child; close the read end */ 385 close(fd[0]); 386 387 /* check whether all three DRBGs reseed and send output to parent */ 388 if (TEST_true(test_drbg_reseed(1, primary, public, private, 389 &random[0], &random[RANDOM_SIZE], 390 1, 1, 1, 0)) 391 && TEST_true(write(fd[1], random, sizeof(random)) 392 == sizeof(random))) { 393 394 rv = 1; 395 } 396 397 /* close the write end */ 398 close(fd[1]); 399 400 /* convert boolean to exit code */ 401 exit(rv == 0); 402 } 403 } 404 405 static int test_rand_reseed_on_fork(EVP_RAND_CTX *primary, 406 EVP_RAND_CTX *public, 407 EVP_RAND_CTX *private) 408 { 409 unsigned int i; 410 pid_t pid = getpid(); 411 int verbose = (getenv("V") != NULL); 412 int success = 1; 413 int duplicate[2] = {0, 0}; 414 unsigned char random[2 * RANDOM_SIZE]; 415 unsigned char sample[DRBG_FORK_RESULT_COUNT * RANDOM_SIZE]; 416 unsigned char *psample = &sample[0]; 417 drbg_fork_result result[DRBG_FORK_RESULT_COUNT]; 418 drbg_fork_result *presult = &result[2]; 419 420 memset(&result, 0, sizeof(result)); 421 422 for (i = 1 ; i <= DRBG_FORK_COUNT ; ++i) { 423 424 presult[0].pindex = presult[1].pindex = i; 425 426 sprintf(presult[0].name, "child %d", i); 427 strcpy(presult[1].name, presult[0].name); 428 429 /* collect the random output of the children */ 430 if (!TEST_true(test_drbg_reseed_in_child(primary, 431 public, 432 private, 433 presult))) 434 return 0; 435 436 presult += 2; 437 } 438 439 /* collect the random output of the parent */ 440 if (!TEST_true(test_drbg_reseed(1, 441 primary, public, private, 442 &random[0], &random[RANDOM_SIZE], 443 0, 0, 0, 0))) 444 return 0; 445 446 strcpy(result[0].name, "parent"); 447 strcpy(result[1].name, "parent"); 448 449 /* output of public drbg */ 450 result[0].pid = pid; 451 result[0].private = 0; 452 memcpy(result[0].random, &random[0], RANDOM_SIZE); 453 454 /* output of private drbg */ 455 result[1].pid = pid; 456 result[1].private = 1; 457 memcpy(result[1].random, &random[RANDOM_SIZE], RANDOM_SIZE); 458 459 /* collect all sampled random data in a single buffer */ 460 for (i = 0 ; i < DRBG_FORK_RESULT_COUNT ; ++i) { 461 memcpy(psample, &result[i].random[0], RANDOM_SIZE); 462 psample += RANDOM_SIZE; 463 } 464 465 /* sort the results... */ 466 qsort(result, DRBG_FORK_RESULT_COUNT, sizeof(drbg_fork_result), 467 compare_drbg_fork_result); 468 469 /* ...and count duplicate prefixes by looking at the first byte only */ 470 for (i = 1 ; i < DRBG_FORK_RESULT_COUNT ; ++i) { 471 if (result[i].random[0] == result[i-1].random[0]) { 472 /* count public and private duplicates separately */ 473 ++duplicate[result[i].private]; 474 } 475 } 476 477 if (duplicate[0] >= DRBG_FORK_COUNT - 1) { 478 /* just too many duplicates to be a coincidence */ 479 TEST_note("ERROR: %d duplicate prefixes in public random output", duplicate[0]); 480 success = 0; 481 } 482 483 if (duplicate[1] >= DRBG_FORK_COUNT - 1) { 484 /* just too many duplicates to be a coincidence */ 485 TEST_note("ERROR: %d duplicate prefixes in private random output", duplicate[1]); 486 success = 0; 487 } 488 489 duplicate[0] = 0; 490 491 /* sort the two-byte chunks... */ 492 qsort(sample, sizeof(sample)/2, 2, compare_rand_chunk); 493 494 /* ...and count duplicate chunks */ 495 for (i = 2, psample = sample + 2 ; i < sizeof(sample) ; i += 2, psample += 2) { 496 if (compare_rand_chunk(psample - 2, psample) == 0) 497 ++duplicate[0]; 498 } 499 500 if (duplicate[0] >= DRBG_FORK_COUNT - 1) { 501 /* just too many duplicates to be a coincidence */ 502 TEST_note("ERROR: %d duplicate chunks in random output", duplicate[0]); 503 success = 0; 504 } 505 506 if (verbose || !success) { 507 508 for (i = 0 ; i < DRBG_FORK_RESULT_COUNT ; ++i) { 509 char *rand_hex = OPENSSL_buf2hexstr(result[i].random, RANDOM_SIZE); 510 511 TEST_note(" random: %s, pid: %d (%s, %s)", 512 rand_hex, 513 result[i].pid, 514 result[i].name, 515 result[i].private ? "private" : "public" 516 ); 517 518 OPENSSL_free(rand_hex); 519 } 520 } 521 522 return success; 523 } 524 525 static int test_rand_fork_safety(int i) 526 { 527 int success = 1; 528 unsigned char random[1]; 529 EVP_RAND_CTX *primary, *public, *private; 530 531 /* All three DRBGs should be non-null */ 532 if (!TEST_ptr(primary = RAND_get0_primary(NULL)) 533 || !TEST_ptr(public = RAND_get0_public(NULL)) 534 || !TEST_ptr(private = RAND_get0_private(NULL))) 535 return 0; 536 537 /* run the actual test */ 538 if (!TEST_true(test_rand_reseed_on_fork(primary, public, private))) 539 success = 0; 540 541 /* request a single byte from each of the DRBGs before the next run */ 542 if (!TEST_int_gt(RAND_bytes(random, 1), 0) || !TEST_int_gt(RAND_priv_bytes(random, 1), 0)) 543 success = 0; 544 545 return success; 546 } 547 #endif 548 549 /* 550 * Test whether the default rand_method (RAND_OpenSSL()) is 551 * setup correctly, in particular whether reseeding works 552 * as designed. 553 */ 554 static int test_rand_reseed(void) 555 { 556 EVP_RAND_CTX *primary, *public, *private; 557 unsigned char rand_add_buf[256]; 558 int rv = 0; 559 time_t before_reseed; 560 561 if (using_fips_rng()) 562 return TEST_skip("CRNGT cannot be disabled"); 563 564 #ifndef OPENSSL_NO_DEPRECATED_3_0 565 /* Check whether RAND_OpenSSL() is the default method */ 566 if (!TEST_ptr_eq(RAND_get_rand_method(), RAND_OpenSSL())) 567 return 0; 568 #endif 569 570 /* All three DRBGs should be non-null */ 571 if (!TEST_ptr(primary = RAND_get0_primary(NULL)) 572 || !TEST_ptr(public = RAND_get0_public(NULL)) 573 || !TEST_ptr(private = RAND_get0_private(NULL))) 574 return 0; 575 576 /* There should be three distinct DRBGs, two of them chained to primary */ 577 if (!TEST_ptr_ne(public, private) 578 || !TEST_ptr_ne(public, primary) 579 || !TEST_ptr_ne(private, primary) 580 || !TEST_ptr_eq(prov_rand(public)->parent, prov_rand(primary)) 581 || !TEST_ptr_eq(prov_rand(private)->parent, prov_rand(primary))) 582 return 0; 583 584 /* Disable CRNG testing for the primary DRBG */ 585 if (!TEST_true(disable_crngt(primary))) 586 return 0; 587 588 /* uninstantiate the three global DRBGs */ 589 EVP_RAND_uninstantiate(primary); 590 EVP_RAND_uninstantiate(private); 591 EVP_RAND_uninstantiate(public); 592 593 /* 594 * Test initial seeding of shared DRBGs 595 */ 596 if (!TEST_true(test_drbg_reseed(1, 597 primary, public, private, 598 NULL, NULL, 599 1, 1, 1, 0))) 600 goto error; 601 602 /* 603 * Test initial state of shared DRBGs 604 */ 605 if (!TEST_true(test_drbg_reseed(1, 606 primary, public, private, 607 NULL, NULL, 608 0, 0, 0, 0))) 609 goto error; 610 611 /* 612 * Test whether the public and private DRBG are both reseeded when their 613 * reseed counters differ from the primary's reseed counter. 614 */ 615 inc_reseed_counter(primary); 616 if (!TEST_true(test_drbg_reseed(1, 617 primary, public, private, 618 NULL, NULL, 619 0, 1, 1, 0))) 620 goto error; 621 622 /* 623 * Test whether the public DRBG is reseeded when its reseed counter differs 624 * from the primary's reseed counter. 625 */ 626 inc_reseed_counter(primary); 627 inc_reseed_counter(private); 628 if (!TEST_true(test_drbg_reseed(1, 629 primary, public, private, 630 NULL, NULL, 631 0, 1, 0, 0))) 632 goto error; 633 634 /* 635 * Test whether the private DRBG is reseeded when its reseed counter differs 636 * from the primary's reseed counter. 637 */ 638 inc_reseed_counter(primary); 639 inc_reseed_counter(public); 640 if (!TEST_true(test_drbg_reseed(1, 641 primary, public, private, 642 NULL, NULL, 643 0, 0, 1, 0))) 644 goto error; 645 646 /* fill 'randomness' buffer with some arbitrary data */ 647 memset(rand_add_buf, 'r', sizeof(rand_add_buf)); 648 649 /* 650 * Test whether all three DRBGs are reseeded by RAND_add(). 651 * The before_reseed time has to be measured here and passed into the 652 * test_drbg_reseed() test, because the primary DRBG gets already reseeded 653 * in RAND_add(), whence the check for the condition 654 * before_reseed <= reseed_time(primary) will fail if the time value happens 655 * to increase between the RAND_add() and the test_drbg_reseed() call. 656 */ 657 before_reseed = time(NULL); 658 RAND_add(rand_add_buf, sizeof(rand_add_buf), sizeof(rand_add_buf)); 659 if (!TEST_true(test_drbg_reseed(1, 660 primary, public, private, 661 NULL, NULL, 662 1, 1, 1, 663 before_reseed))) 664 goto error; 665 666 rv = 1; 667 668 error: 669 return rv; 670 } 671 672 #if defined(OPENSSL_THREADS) 673 static int multi_thread_rand_bytes_succeeded = 1; 674 static int multi_thread_rand_priv_bytes_succeeded = 1; 675 676 static int set_reseed_time_interval(EVP_RAND_CTX *drbg, int t) 677 { 678 OSSL_PARAM params[2]; 679 680 params[0] = OSSL_PARAM_construct_int(OSSL_DRBG_PARAM_RESEED_TIME_INTERVAL, 681 &t); 682 params[1] = OSSL_PARAM_construct_end(); 683 return EVP_RAND_CTX_set_params(drbg, params); 684 } 685 686 static void run_multi_thread_test(void) 687 { 688 unsigned char buf[256]; 689 time_t start = time(NULL); 690 EVP_RAND_CTX *public = NULL, *private = NULL; 691 692 if (!TEST_ptr(public = RAND_get0_public(NULL)) 693 || !TEST_ptr(private = RAND_get0_private(NULL)) 694 || !TEST_true(set_reseed_time_interval(private, 1)) 695 || !TEST_true(set_reseed_time_interval(public, 1))) { 696 multi_thread_rand_bytes_succeeded = 0; 697 return; 698 } 699 700 do { 701 if (rand_bytes(buf, sizeof(buf)) <= 0) 702 multi_thread_rand_bytes_succeeded = 0; 703 if (rand_priv_bytes(buf, sizeof(buf)) <= 0) 704 multi_thread_rand_priv_bytes_succeeded = 0; 705 } 706 while (time(NULL) - start < 5); 707 } 708 709 # if defined(OPENSSL_SYS_WINDOWS) 710 711 typedef HANDLE thread_t; 712 713 static DWORD WINAPI thread_run(LPVOID arg) 714 { 715 run_multi_thread_test(); 716 /* 717 * Because we're linking with a static library, we must stop each 718 * thread explicitly, or so says OPENSSL_thread_stop(3) 719 */ 720 OPENSSL_thread_stop(); 721 return 0; 722 } 723 724 static int run_thread(thread_t *t) 725 { 726 *t = CreateThread(NULL, 0, thread_run, NULL, 0, NULL); 727 return *t != NULL; 728 } 729 730 static int wait_for_thread(thread_t thread) 731 { 732 return WaitForSingleObject(thread, INFINITE) == 0; 733 } 734 735 # else 736 737 typedef pthread_t thread_t; 738 739 static void *thread_run(void *arg) 740 { 741 run_multi_thread_test(); 742 /* 743 * Because we're linking with a static library, we must stop each 744 * thread explicitly, or so says OPENSSL_thread_stop(3) 745 */ 746 OPENSSL_thread_stop(); 747 return NULL; 748 } 749 750 static int run_thread(thread_t *t) 751 { 752 return pthread_create(t, NULL, thread_run, NULL) == 0; 753 } 754 755 static int wait_for_thread(thread_t thread) 756 { 757 return pthread_join(thread, NULL) == 0; 758 } 759 760 # endif 761 762 /* 763 * The main thread will also run the test, so we'll have THREADS+1 parallel 764 * tests running 765 */ 766 # define THREADS 3 767 768 static int test_multi_thread(void) 769 { 770 thread_t t[THREADS]; 771 int i; 772 773 for (i = 0; i < THREADS; i++) 774 run_thread(&t[i]); 775 run_multi_thread_test(); 776 for (i = 0; i < THREADS; i++) 777 wait_for_thread(t[i]); 778 779 if (!TEST_true(multi_thread_rand_bytes_succeeded)) 780 return 0; 781 if (!TEST_true(multi_thread_rand_priv_bytes_succeeded)) 782 return 0; 783 784 return 1; 785 } 786 #endif 787 788 static EVP_RAND_CTX *new_drbg(EVP_RAND_CTX *parent) 789 { 790 OSSL_PARAM params[2]; 791 EVP_RAND *rand = NULL; 792 EVP_RAND_CTX *drbg = NULL; 793 794 params[0] = OSSL_PARAM_construct_utf8_string(OSSL_DRBG_PARAM_CIPHER, 795 "AES-256-CTR", 0); 796 params[1] = OSSL_PARAM_construct_end(); 797 798 if (!TEST_ptr(rand = EVP_RAND_fetch(NULL, "CTR-DRBG", NULL)) 799 || !TEST_ptr(drbg = EVP_RAND_CTX_new(rand, parent)) 800 || !TEST_true(EVP_RAND_CTX_set_params(drbg, params))) { 801 EVP_RAND_CTX_free(drbg); 802 drbg = NULL; 803 } 804 EVP_RAND_free(rand); 805 return drbg; 806 } 807 808 static int test_rand_prediction_resistance(void) 809 { 810 EVP_RAND_CTX *x = NULL, *y = NULL, *z = NULL; 811 unsigned char buf1[51], buf2[sizeof(buf1)]; 812 int ret = 0, xreseed, yreseed, zreseed; 813 814 if (using_fips_rng()) 815 return TEST_skip("CRNGT cannot be disabled"); 816 817 /* Initialise a three long DRBG chain */ 818 if (!TEST_ptr(x = new_drbg(NULL)) 819 || !TEST_true(disable_crngt(x)) 820 || !TEST_true(EVP_RAND_instantiate(x, 0, 0, NULL, 0, NULL)) 821 || !TEST_ptr(y = new_drbg(x)) 822 || !TEST_true(EVP_RAND_instantiate(y, 0, 0, NULL, 0, NULL)) 823 || !TEST_ptr(z = new_drbg(y)) 824 || !TEST_true(EVP_RAND_instantiate(z, 0, 0, NULL, 0, NULL))) 825 goto err; 826 827 /* 828 * During a normal reseed, only the last DRBG in the chain should 829 * be reseeded. 830 */ 831 inc_reseed_counter(y); 832 xreseed = reseed_counter(x); 833 yreseed = reseed_counter(y); 834 zreseed = reseed_counter(z); 835 if (!TEST_true(EVP_RAND_reseed(z, 0, NULL, 0, NULL, 0)) 836 || !TEST_int_eq(reseed_counter(x), xreseed) 837 || !TEST_int_eq(reseed_counter(y), yreseed) 838 || !TEST_int_gt(reseed_counter(z), zreseed)) 839 goto err; 840 841 /* 842 * When prediction resistance is requested, the request should be 843 * propagated to the primary, so that the entire DRBG chain reseeds. 844 */ 845 zreseed = reseed_counter(z); 846 if (!TEST_true(EVP_RAND_reseed(z, 1, NULL, 0, NULL, 0)) 847 || !TEST_int_gt(reseed_counter(x), xreseed) 848 || !TEST_int_gt(reseed_counter(y), yreseed) 849 || !TEST_int_gt(reseed_counter(z), zreseed)) 850 goto err; 851 852 /* 853 * During a normal generate, only the last DRBG should be reseed */ 854 inc_reseed_counter(y); 855 xreseed = reseed_counter(x); 856 yreseed = reseed_counter(y); 857 zreseed = reseed_counter(z); 858 if (!TEST_true(EVP_RAND_generate(z, buf1, sizeof(buf1), 0, 0, NULL, 0)) 859 || !TEST_int_eq(reseed_counter(x), xreseed) 860 || !TEST_int_eq(reseed_counter(y), yreseed) 861 || !TEST_int_gt(reseed_counter(z), zreseed)) 862 goto err; 863 864 /* 865 * When a prediction resistant generate is requested, the request 866 * should be propagated to the primary, reseeding the entire DRBG chain. 867 */ 868 zreseed = reseed_counter(z); 869 if (!TEST_true(EVP_RAND_generate(z, buf2, sizeof(buf2), 0, 1, NULL, 0)) 870 || !TEST_int_gt(reseed_counter(x), xreseed) 871 || !TEST_int_gt(reseed_counter(y), yreseed) 872 || !TEST_int_gt(reseed_counter(z), zreseed) 873 || !TEST_mem_ne(buf1, sizeof(buf1), buf2, sizeof(buf2))) 874 goto err; 875 876 /* Verify that a normal reseed still only reseeds the last DRBG */ 877 inc_reseed_counter(y); 878 xreseed = reseed_counter(x); 879 yreseed = reseed_counter(y); 880 zreseed = reseed_counter(z); 881 if (!TEST_true(EVP_RAND_reseed(z, 0, NULL, 0, NULL, 0)) 882 || !TEST_int_eq(reseed_counter(x), xreseed) 883 || !TEST_int_eq(reseed_counter(y), yreseed) 884 || !TEST_int_gt(reseed_counter(z), zreseed)) 885 goto err; 886 887 ret = 1; 888 err: 889 EVP_RAND_CTX_free(z); 890 EVP_RAND_CTX_free(y); 891 EVP_RAND_CTX_free(x); 892 return ret; 893 } 894 895 int setup_tests(void) 896 { 897 ADD_TEST(test_rand_reseed); 898 #if defined(OPENSSL_SYS_UNIX) && !defined(OPENSSL_RAND_SEED_EGD) 899 ADD_ALL_TESTS(test_rand_fork_safety, RANDOM_SIZE); 900 #endif 901 ADD_TEST(test_rand_prediction_resistance); 902 #if defined(OPENSSL_THREADS) 903 ADD_TEST(test_multi_thread); 904 #endif 905 return 1; 906 } 907