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
test_lock(void)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
once_do_run(void)55*e0c4386eSCy Schubert static void once_do_run(void)
56*e0c4386eSCy Schubert {
57*e0c4386eSCy Schubert once_run_count++;
58*e0c4386eSCy Schubert }
59*e0c4386eSCy Schubert
once_run_thread_cb(void)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
test_once(void)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
thread_local_destructor(void * arg)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
thread_local_thread_cb(void)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
test_thread_local(void)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
test_atomic(void)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
multi_intialise(void)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
thead_teardown_libctx(void)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
thread_setup_libctx(int libctx,const char * providers[])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
teardown_threads(void)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
start_threads(size_t n,void (* thread_func)(void))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 */
thread_run_test(void (* main_func)(void),size_t num_threads,void (* thread_func)(void),int libctx,const char * providers[])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
thread_general_worker(void)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
thread_multi_simple_fetch(void)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
thread_shared_evp_pkey(void)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
thread_downgrade_shared_evp_pkey(void)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
thread_provider_load_unload(void)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 */
test_multi(int idx)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
test_multi_load_worker(void)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
test_multi_default(void)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
test_multi_load(void)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
test_lib_ctx_load_config_worker(void)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
test_lib_ctx_load_config(void)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
test_get_options(void)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
setup_tests(void)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
cleanup_tests(void)725*e0c4386eSCy Schubert void cleanup_tests(void)
726*e0c4386eSCy Schubert {
727*e0c4386eSCy Schubert OPENSSL_free(privkey);
728*e0c4386eSCy Schubert }
729