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