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