1 /* 2 * Copyright 2016-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 /* test_multi below tests the thread safety of a deprecated function */ 11 #define OPENSSL_SUPPRESS_DEPRECATED 12 13 #if defined(_WIN32) 14 # include <windows.h> 15 #endif 16 17 #include <string.h> 18 #include <openssl/crypto.h> 19 #include <openssl/rsa.h> 20 #include <openssl/aes.h> 21 #include <openssl/rsa.h> 22 #include "testutil.h" 23 #include "threadstest.h" 24 25 /* Limit the maximum number of threads */ 26 #define MAXIMUM_THREADS 10 27 28 /* Limit the maximum number of providers loaded into a library context */ 29 #define MAXIMUM_PROVIDERS 4 30 31 static int do_fips = 0; 32 static char *privkey; 33 static char *config_file = NULL; 34 static int multidefault_run = 0; 35 static const char *default_provider[] = { "default", NULL }; 36 37 static int test_lock(void) 38 { 39 CRYPTO_RWLOCK *lock = CRYPTO_THREAD_lock_new(); 40 int res; 41 42 res = TEST_true(CRYPTO_THREAD_read_lock(lock)) 43 && TEST_true(CRYPTO_THREAD_unlock(lock)) 44 && TEST_true(CRYPTO_THREAD_write_lock(lock)) 45 && TEST_true(CRYPTO_THREAD_unlock(lock)); 46 47 CRYPTO_THREAD_lock_free(lock); 48 49 return res; 50 } 51 52 static CRYPTO_ONCE once_run = CRYPTO_ONCE_STATIC_INIT; 53 static unsigned once_run_count = 0; 54 55 static void once_do_run(void) 56 { 57 once_run_count++; 58 } 59 60 static void once_run_thread_cb(void) 61 { 62 CRYPTO_THREAD_run_once(&once_run, once_do_run); 63 } 64 65 static int test_once(void) 66 { 67 thread_t thread; 68 69 if (!TEST_true(run_thread(&thread, once_run_thread_cb)) 70 || !TEST_true(wait_for_thread(thread)) 71 || !CRYPTO_THREAD_run_once(&once_run, once_do_run) 72 || !TEST_int_eq(once_run_count, 1)) 73 return 0; 74 return 1; 75 } 76 77 static CRYPTO_THREAD_LOCAL thread_local_key; 78 static unsigned destructor_run_count = 0; 79 static int thread_local_thread_cb_ok = 0; 80 81 static void thread_local_destructor(void *arg) 82 { 83 unsigned *count; 84 85 if (arg == NULL) 86 return; 87 88 count = arg; 89 90 (*count)++; 91 } 92 93 static void thread_local_thread_cb(void) 94 { 95 void *ptr; 96 97 ptr = CRYPTO_THREAD_get_local(&thread_local_key); 98 if (!TEST_ptr_null(ptr) 99 || !TEST_true(CRYPTO_THREAD_set_local(&thread_local_key, 100 &destructor_run_count))) 101 return; 102 103 ptr = CRYPTO_THREAD_get_local(&thread_local_key); 104 if (!TEST_ptr_eq(ptr, &destructor_run_count)) 105 return; 106 107 thread_local_thread_cb_ok = 1; 108 } 109 110 static int test_thread_local(void) 111 { 112 thread_t thread; 113 void *ptr = NULL; 114 115 if (!TEST_true(CRYPTO_THREAD_init_local(&thread_local_key, 116 thread_local_destructor))) 117 return 0; 118 119 ptr = CRYPTO_THREAD_get_local(&thread_local_key); 120 if (!TEST_ptr_null(ptr) 121 || !TEST_true(run_thread(&thread, thread_local_thread_cb)) 122 || !TEST_true(wait_for_thread(thread)) 123 || !TEST_int_eq(thread_local_thread_cb_ok, 1)) 124 return 0; 125 126 #if defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG) 127 128 ptr = CRYPTO_THREAD_get_local(&thread_local_key); 129 if (!TEST_ptr_null(ptr)) 130 return 0; 131 132 # if !defined(OPENSSL_SYS_WINDOWS) 133 if (!TEST_int_eq(destructor_run_count, 1)) 134 return 0; 135 # endif 136 #endif 137 138 if (!TEST_true(CRYPTO_THREAD_cleanup_local(&thread_local_key))) 139 return 0; 140 return 1; 141 } 142 143 static int test_atomic(void) 144 { 145 int val = 0, ret = 0, testresult = 0; 146 uint64_t val64 = 1, ret64 = 0; 147 CRYPTO_RWLOCK *lock = CRYPTO_THREAD_lock_new(); 148 149 if (!TEST_ptr(lock)) 150 return 0; 151 152 if (CRYPTO_atomic_add(&val, 1, &ret, NULL)) { 153 /* This succeeds therefore we're on a platform with lockless atomics */ 154 if (!TEST_int_eq(val, 1) || !TEST_int_eq(val, ret)) 155 goto err; 156 } else { 157 /* This failed therefore we're on a platform without lockless atomics */ 158 if (!TEST_int_eq(val, 0) || !TEST_int_eq(val, ret)) 159 goto err; 160 } 161 val = 0; 162 ret = 0; 163 164 if (!TEST_true(CRYPTO_atomic_add(&val, 1, &ret, lock))) 165 goto err; 166 if (!TEST_int_eq(val, 1) || !TEST_int_eq(val, ret)) 167 goto err; 168 169 if (CRYPTO_atomic_or(&val64, 2, &ret64, NULL)) { 170 /* This succeeds therefore we're on a platform with lockless atomics */ 171 if (!TEST_uint_eq((unsigned int)val64, 3) 172 || !TEST_uint_eq((unsigned int)val64, (unsigned int)ret64)) 173 goto err; 174 } else { 175 /* This failed therefore we're on a platform without lockless atomics */ 176 if (!TEST_uint_eq((unsigned int)val64, 1) 177 || !TEST_int_eq((unsigned int)ret64, 0)) 178 goto err; 179 } 180 val64 = 1; 181 ret64 = 0; 182 183 if (!TEST_true(CRYPTO_atomic_or(&val64, 2, &ret64, lock))) 184 goto err; 185 186 if (!TEST_uint_eq((unsigned int)val64, 3) 187 || !TEST_uint_eq((unsigned int)val64, (unsigned int)ret64)) 188 goto err; 189 190 ret64 = 0; 191 if (CRYPTO_atomic_load(&val64, &ret64, NULL)) { 192 /* This succeeds therefore we're on a platform with lockless atomics */ 193 if (!TEST_uint_eq((unsigned int)val64, 3) 194 || !TEST_uint_eq((unsigned int)val64, (unsigned int)ret64)) 195 goto err; 196 } else { 197 /* This failed therefore we're on a platform without lockless atomics */ 198 if (!TEST_uint_eq((unsigned int)val64, 3) 199 || !TEST_int_eq((unsigned int)ret64, 0)) 200 goto err; 201 } 202 203 ret64 = 0; 204 if (!TEST_true(CRYPTO_atomic_load(&val64, &ret64, lock))) 205 goto err; 206 207 if (!TEST_uint_eq((unsigned int)val64, 3) 208 || !TEST_uint_eq((unsigned int)val64, (unsigned int)ret64)) 209 goto err; 210 211 testresult = 1; 212 err: 213 CRYPTO_THREAD_lock_free(lock); 214 return testresult; 215 } 216 217 static OSSL_LIB_CTX *multi_libctx = NULL; 218 static int multi_success; 219 static OSSL_PROVIDER *multi_provider[MAXIMUM_PROVIDERS + 1]; 220 static size_t multi_num_threads; 221 static thread_t multi_threads[MAXIMUM_THREADS]; 222 223 static void multi_intialise(void) 224 { 225 multi_success = 1; 226 multi_libctx = NULL; 227 multi_num_threads = 0; 228 memset(multi_threads, 0, sizeof(multi_threads)); 229 memset(multi_provider, 0, sizeof(multi_provider)); 230 } 231 232 static void thead_teardown_libctx(void) 233 { 234 OSSL_PROVIDER **p; 235 236 for (p = multi_provider; *p != NULL; p++) 237 OSSL_PROVIDER_unload(*p); 238 OSSL_LIB_CTX_free(multi_libctx); 239 multi_intialise(); 240 } 241 242 static int thread_setup_libctx(int libctx, const char *providers[]) 243 { 244 size_t n; 245 246 if (libctx && !TEST_true(test_get_libctx(&multi_libctx, NULL, config_file, 247 NULL, NULL))) 248 return 0; 249 250 if (providers != NULL) 251 for (n = 0; providers[n] != NULL; n++) 252 if (!TEST_size_t_lt(n, MAXIMUM_PROVIDERS) 253 || !TEST_ptr(multi_provider[n] = OSSL_PROVIDER_load(multi_libctx, 254 providers[n]))) { 255 thead_teardown_libctx(); 256 return 0; 257 } 258 return 1; 259 } 260 261 static int teardown_threads(void) 262 { 263 size_t i; 264 265 for (i = 0; i < multi_num_threads; i++) 266 if (!TEST_true(wait_for_thread(multi_threads[i]))) 267 return 0; 268 return 1; 269 } 270 271 static int start_threads(size_t n, void (*thread_func)(void)) 272 { 273 size_t i; 274 275 if (!TEST_size_t_le(multi_num_threads + n, MAXIMUM_THREADS)) 276 return 0; 277 278 for (i = 0 ; i < n; i++) 279 if (!TEST_true(run_thread(multi_threads + multi_num_threads++, thread_func))) 280 return 0; 281 return 1; 282 } 283 284 /* Template multi-threaded test function */ 285 static int thread_run_test(void (*main_func)(void), 286 size_t num_threads, void (*thread_func)(void), 287 int libctx, const char *providers[]) 288 { 289 int testresult = 0; 290 291 multi_intialise(); 292 if (!thread_setup_libctx(libctx, providers) 293 || !start_threads(num_threads, thread_func)) 294 goto err; 295 296 if (main_func != NULL) 297 main_func(); 298 299 if (!teardown_threads() 300 || !TEST_true(multi_success)) 301 goto err; 302 testresult = 1; 303 err: 304 thead_teardown_libctx(); 305 return testresult; 306 } 307 308 static void thread_general_worker(void) 309 { 310 EVP_MD_CTX *mdctx = EVP_MD_CTX_new(); 311 EVP_MD *md = EVP_MD_fetch(multi_libctx, "SHA2-256", NULL); 312 EVP_CIPHER_CTX *cipherctx = EVP_CIPHER_CTX_new(); 313 EVP_CIPHER *ciph = EVP_CIPHER_fetch(multi_libctx, "AES-128-CBC", NULL); 314 const char *message = "Hello World"; 315 size_t messlen = strlen(message); 316 /* Should be big enough for encryption output too */ 317 unsigned char out[EVP_MAX_MD_SIZE]; 318 const unsigned char key[AES_BLOCK_SIZE] = { 319 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 320 0x0c, 0x0d, 0x0e, 0x0f 321 }; 322 const unsigned char iv[AES_BLOCK_SIZE] = { 323 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 324 0x0c, 0x0d, 0x0e, 0x0f 325 }; 326 unsigned int mdoutl; 327 int ciphoutl; 328 EVP_PKEY *pkey = NULL; 329 int testresult = 0; 330 int i, isfips; 331 332 isfips = OSSL_PROVIDER_available(multi_libctx, "fips"); 333 334 if (!TEST_ptr(mdctx) 335 || !TEST_ptr(md) 336 || !TEST_ptr(cipherctx) 337 || !TEST_ptr(ciph)) 338 goto err; 339 340 /* Do some work */ 341 for (i = 0; i < 5; i++) { 342 if (!TEST_true(EVP_DigestInit_ex(mdctx, md, NULL)) 343 || !TEST_true(EVP_DigestUpdate(mdctx, message, messlen)) 344 || !TEST_true(EVP_DigestFinal(mdctx, out, &mdoutl))) 345 goto err; 346 } 347 for (i = 0; i < 5; i++) { 348 if (!TEST_true(EVP_EncryptInit_ex(cipherctx, ciph, NULL, key, iv)) 349 || !TEST_true(EVP_EncryptUpdate(cipherctx, out, &ciphoutl, 350 (unsigned char *)message, 351 messlen)) 352 || !TEST_true(EVP_EncryptFinal(cipherctx, out, &ciphoutl))) 353 goto err; 354 } 355 356 /* 357 * We want the test to run quickly - not securely. 358 * Therefore we use an insecure bit length where we can (512). 359 * In the FIPS module though we must use a longer length. 360 */ 361 pkey = EVP_PKEY_Q_keygen(multi_libctx, NULL, "RSA", isfips ? 2048 : 512); 362 if (!TEST_ptr(pkey)) 363 goto err; 364 365 testresult = 1; 366 err: 367 EVP_MD_CTX_free(mdctx); 368 EVP_MD_free(md); 369 EVP_CIPHER_CTX_free(cipherctx); 370 EVP_CIPHER_free(ciph); 371 EVP_PKEY_free(pkey); 372 if (!testresult) 373 multi_success = 0; 374 } 375 376 static void thread_multi_simple_fetch(void) 377 { 378 EVP_MD *md = EVP_MD_fetch(multi_libctx, "SHA2-256", NULL); 379 380 if (md != NULL) 381 EVP_MD_free(md); 382 else 383 multi_success = 0; 384 } 385 386 static EVP_PKEY *shared_evp_pkey = NULL; 387 388 static void thread_shared_evp_pkey(void) 389 { 390 char *msg = "Hello World"; 391 unsigned char ctbuf[256]; 392 unsigned char ptbuf[256]; 393 size_t ptlen, ctlen = sizeof(ctbuf); 394 EVP_PKEY_CTX *ctx = NULL; 395 int success = 0; 396 int i; 397 398 for (i = 0; i < 1 + do_fips; i++) { 399 if (i > 0) 400 EVP_PKEY_CTX_free(ctx); 401 ctx = EVP_PKEY_CTX_new_from_pkey(multi_libctx, shared_evp_pkey, 402 i == 0 ? "provider=default" 403 : "provider=fips"); 404 if (!TEST_ptr(ctx)) 405 goto err; 406 407 if (!TEST_int_ge(EVP_PKEY_encrypt_init(ctx), 0) 408 || !TEST_int_ge(EVP_PKEY_encrypt(ctx, ctbuf, &ctlen, 409 (unsigned char *)msg, strlen(msg)), 410 0)) 411 goto err; 412 413 EVP_PKEY_CTX_free(ctx); 414 ctx = EVP_PKEY_CTX_new_from_pkey(multi_libctx, shared_evp_pkey, NULL); 415 416 if (!TEST_ptr(ctx)) 417 goto err; 418 419 ptlen = sizeof(ptbuf); 420 if (!TEST_int_ge(EVP_PKEY_decrypt_init(ctx), 0) 421 || !TEST_int_gt(EVP_PKEY_decrypt(ctx, ptbuf, &ptlen, ctbuf, ctlen), 422 0) 423 || !TEST_mem_eq(msg, strlen(msg), ptbuf, ptlen)) 424 goto err; 425 } 426 427 success = 1; 428 429 err: 430 EVP_PKEY_CTX_free(ctx); 431 if (!success) 432 multi_success = 0; 433 } 434 435 static void thread_downgrade_shared_evp_pkey(void) 436 { 437 #ifndef OPENSSL_NO_DEPRECATED_3_0 438 /* 439 * This test is only relevant for deprecated functions that perform 440 * downgrading 441 */ 442 if (EVP_PKEY_get0_RSA(shared_evp_pkey) == NULL) 443 multi_success = 0; 444 #else 445 /* Shouldn't ever get here */ 446 multi_success = 0; 447 #endif 448 } 449 450 static void thread_provider_load_unload(void) 451 { 452 OSSL_PROVIDER *deflt = OSSL_PROVIDER_load(multi_libctx, "default"); 453 454 if (!TEST_ptr(deflt) 455 || !TEST_true(OSSL_PROVIDER_available(multi_libctx, "default"))) 456 multi_success = 0; 457 458 OSSL_PROVIDER_unload(deflt); 459 } 460 461 /* 462 * Do work in multiple worker threads at the same time. 463 * Test 0: General worker, using the default provider 464 * Test 1: General worker, using the fips provider 465 * Test 2: Simple fetch worker 466 * Test 3: Worker downgrading a shared EVP_PKEY 467 * Test 4: Worker using a shared EVP_PKEY 468 * Test 5: Worker loading and unloading a provider 469 */ 470 static int test_multi(int idx) 471 { 472 thread_t thread1, thread2; 473 int testresult = 0; 474 OSSL_PROVIDER *prov = NULL, *prov2 = NULL; 475 void (*worker)(void) = NULL; 476 void (*worker2)(void) = NULL; 477 EVP_MD *sha256 = NULL; 478 479 if (idx == 1 && !do_fips) 480 return TEST_skip("FIPS not supported"); 481 482 #ifdef OPENSSL_NO_DEPRECATED_3_0 483 if (idx == 3) 484 return TEST_skip("Skipping tests for deprected functions"); 485 #endif 486 487 multi_success = 1; 488 if (!TEST_true(test_get_libctx(&multi_libctx, NULL, config_file, 489 NULL, NULL))) 490 return 0; 491 492 prov = OSSL_PROVIDER_load(multi_libctx, (idx == 1) ? "fips" : "default"); 493 if (!TEST_ptr(prov)) 494 goto err; 495 496 switch (idx) { 497 case 0: 498 case 1: 499 worker = thread_general_worker; 500 break; 501 case 2: 502 worker = thread_multi_simple_fetch; 503 break; 504 case 3: 505 worker2 = thread_downgrade_shared_evp_pkey; 506 /* fall through */ 507 case 4: 508 /* 509 * If available we have both the default and fips providers for this 510 * test 511 */ 512 if (do_fips 513 && !TEST_ptr(prov2 = OSSL_PROVIDER_load(multi_libctx, "fips"))) 514 goto err; 515 if (!TEST_ptr(shared_evp_pkey = load_pkey_pem(privkey, multi_libctx))) 516 goto err; 517 worker = thread_shared_evp_pkey; 518 break; 519 case 5: 520 /* 521 * We ensure we get an md from the default provider, and then unload the 522 * provider. This ensures the provider remains around but in a 523 * deactivated state. 524 */ 525 sha256 = EVP_MD_fetch(multi_libctx, "SHA2-256", NULL); 526 OSSL_PROVIDER_unload(prov); 527 prov = NULL; 528 worker = thread_provider_load_unload; 529 break; 530 default: 531 TEST_error("Invalid test index"); 532 goto err; 533 } 534 if (worker2 == NULL) 535 worker2 = worker; 536 537 if (!TEST_true(run_thread(&thread1, worker)) 538 || !TEST_true(run_thread(&thread2, worker2))) 539 goto err; 540 541 worker(); 542 543 testresult = 1; 544 /* 545 * Don't combine these into one if statement; must wait for both threads. 546 */ 547 if (!TEST_true(wait_for_thread(thread1))) 548 testresult = 0; 549 if (!TEST_true(wait_for_thread(thread2))) 550 testresult = 0; 551 if (!TEST_true(multi_success)) 552 testresult = 0; 553 554 err: 555 EVP_MD_free(sha256); 556 OSSL_PROVIDER_unload(prov); 557 OSSL_PROVIDER_unload(prov2); 558 OSSL_LIB_CTX_free(multi_libctx); 559 EVP_PKEY_free(shared_evp_pkey); 560 shared_evp_pkey = NULL; 561 multi_libctx = NULL; 562 return testresult; 563 } 564 565 static char *multi_load_provider = "legacy"; 566 /* 567 * This test attempts to load several providers at the same time, and if 568 * run with a thread sanitizer, should crash if the core provider code 569 * doesn't synchronize well enough. 570 */ 571 #define MULTI_LOAD_THREADS 10 572 static void test_multi_load_worker(void) 573 { 574 OSSL_PROVIDER *prov; 575 576 if (!TEST_ptr(prov = OSSL_PROVIDER_load(NULL, multi_load_provider)) 577 || !TEST_true(OSSL_PROVIDER_unload(prov))) 578 multi_success = 0; 579 } 580 581 static int test_multi_default(void) 582 { 583 thread_t thread1, thread2; 584 int testresult = 0; 585 OSSL_PROVIDER *prov = NULL; 586 587 /* Avoid running this test twice */ 588 if (multidefault_run) { 589 TEST_skip("multi default test already run"); 590 return 1; 591 } 592 multidefault_run = 1; 593 594 multi_success = 1; 595 multi_libctx = NULL; 596 prov = OSSL_PROVIDER_load(multi_libctx, "default"); 597 if (!TEST_ptr(prov)) 598 goto err; 599 600 if (!TEST_true(run_thread(&thread1, thread_multi_simple_fetch)) 601 || !TEST_true(run_thread(&thread2, thread_multi_simple_fetch))) 602 goto err; 603 604 thread_multi_simple_fetch(); 605 606 if (!TEST_true(wait_for_thread(thread1)) 607 || !TEST_true(wait_for_thread(thread2)) 608 || !TEST_true(multi_success)) 609 goto err; 610 611 testresult = 1; 612 613 err: 614 OSSL_PROVIDER_unload(prov); 615 return testresult; 616 } 617 618 static int test_multi_load(void) 619 { 620 thread_t threads[MULTI_LOAD_THREADS]; 621 int i, res = 1; 622 OSSL_PROVIDER *prov; 623 624 /* The multidefault test must run prior to this test */ 625 if (!multidefault_run) { 626 TEST_info("Running multi default test first"); 627 res = test_multi_default(); 628 } 629 630 /* 631 * We use the legacy provider in test_multi_load_worker because it uses a 632 * child libctx that might hit more codepaths that might be sensitive to 633 * threading issues. But in a no-legacy build that won't be loadable so 634 * we use the default provider instead. 635 */ 636 prov = OSSL_PROVIDER_load(NULL, "legacy"); 637 if (prov == NULL) { 638 TEST_info("Cannot load legacy provider - assuming this is a no-legacy build"); 639 multi_load_provider = "default"; 640 } 641 OSSL_PROVIDER_unload(prov); 642 643 multi_success = 1; 644 for (i = 0; i < MULTI_LOAD_THREADS; i++) 645 (void)TEST_true(run_thread(&threads[i], test_multi_load_worker)); 646 647 for (i = 0; i < MULTI_LOAD_THREADS; i++) 648 (void)TEST_true(wait_for_thread(threads[i])); 649 650 return res && multi_success; 651 } 652 653 static void test_lib_ctx_load_config_worker(void) 654 { 655 if (!TEST_int_eq(OSSL_LIB_CTX_load_config(multi_libctx, config_file), 1)) 656 multi_success = 0; 657 } 658 659 static int test_lib_ctx_load_config(void) 660 { 661 return thread_run_test(&test_lib_ctx_load_config_worker, 662 MAXIMUM_THREADS, &test_lib_ctx_load_config_worker, 663 1, default_provider); 664 } 665 666 typedef enum OPTION_choice { 667 OPT_ERR = -1, 668 OPT_EOF = 0, 669 OPT_FIPS, OPT_CONFIG_FILE, 670 OPT_TEST_ENUM 671 } OPTION_CHOICE; 672 673 const OPTIONS *test_get_options(void) 674 { 675 static const OPTIONS options[] = { 676 OPT_TEST_OPTIONS_DEFAULT_USAGE, 677 { "fips", OPT_FIPS, '-', "Test the FIPS provider" }, 678 { "config", OPT_CONFIG_FILE, '<', 679 "The configuration file to use for the libctx" }, 680 { NULL } 681 }; 682 return options; 683 } 684 685 int setup_tests(void) 686 { 687 OPTION_CHOICE o; 688 char *datadir; 689 690 while ((o = opt_next()) != OPT_EOF) { 691 switch (o) { 692 case OPT_FIPS: 693 do_fips = 1; 694 break; 695 case OPT_CONFIG_FILE: 696 config_file = opt_arg(); 697 break; 698 case OPT_TEST_CASES: 699 break; 700 default: 701 return 0; 702 } 703 } 704 705 if (!TEST_ptr(datadir = test_get_argument(0))) 706 return 0; 707 708 privkey = test_mk_file_path(datadir, "rsakey.pem"); 709 if (!TEST_ptr(privkey)) 710 return 0; 711 712 /* Keep first to validate auto creation of default library context */ 713 ADD_TEST(test_multi_default); 714 715 ADD_TEST(test_lock); 716 ADD_TEST(test_once); 717 ADD_TEST(test_thread_local); 718 ADD_TEST(test_atomic); 719 ADD_TEST(test_multi_load); 720 ADD_ALL_TESTS(test_multi, 6); 721 ADD_TEST(test_lib_ctx_load_config); 722 return 1; 723 } 724 725 void cleanup_tests(void) 726 { 727 OPENSSL_free(privkey); 728 } 729