]> git.ipfire.org Git - thirdparty/openssl.git/blame - test/threadstest.c
Copyright year updates
[thirdparty/openssl.git] / test / threadstest.c
CommitLineData
440e5d80 1/*
da1c088f 2 * Copyright 2016-2023 The OpenSSL Project Authors. All Rights Reserved.
71a04cfc 3 *
909f1a2e 4 * Licensed under the Apache License 2.0 (the "License"). You may not use
440e5d80
RS
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
71a04cfc
AG
8 */
9
0855591e
P
10/*
11 * The test_multi_downgrade_shared_pkey function tests the thread safety of a
12 * deprecated function.
13 */
14#ifndef OPENSSL_NO_DEPRECATED_3_0
15# define OPENSSL_SUPPRESS_DEPRECATED
16#endif
8e53d94d 17
f1f5ee17
AP
18#if defined(_WIN32)
19# include <windows.h>
20#endif
21
ae95a40e 22#include <string.h>
71a04cfc 23#include <openssl/crypto.h>
f9253152 24#include <openssl/rsa.h>
ae95a40e 25#include <openssl/aes.h>
0855591e 26#include <openssl/err.h>
b88ce46e 27#include <openssl/rand.h>
29f25a10
MC
28#include <openssl/pem.h>
29#include <openssl/evp.h>
0855591e
P
30#include "internal/tsan_assist.h"
31#include "internal/nelem.h"
ee25dd45 32#include "testutil.h"
235776b2 33#include "threadstest.h"
71a04cfc 34
0855591e 35/* Limit the maximum number of threads */
293e251e 36#define MAXIMUM_THREADS 10
0855591e
P
37
38/* Limit the maximum number of providers loaded into a library context */
39#define MAXIMUM_PROVIDERS 4
40
ae95a40e 41static int do_fips = 0;
a0134d29 42static char *privkey;
9a633a1c 43static char *config_file = NULL;
b9bc8eb0 44static int multidefault_run = 0;
ae95a40e 45
0855591e
P
46static const char *default_provider[] = { "default", NULL };
47static const char *fips_provider[] = { "fips", NULL };
48static const char *fips_and_default_providers[] = { "default", "fips", NULL };
49
b88ce46e
HL
50static CRYPTO_RWLOCK *global_lock;
51
3d4d5305
P
52#ifdef TSAN_REQUIRES_LOCKING
53static CRYPTO_RWLOCK *tsan_lock;
54#endif
55
56/* Grab a globally unique integer value, return 0 on failure */
0855591e
P
57static int get_new_uid(void)
58{
59 /*
60 * Start with a nice large number to avoid potential conflicts when
61 * we generate a new OID.
62 */
63 static TSAN_QUALIFIER int current_uid = 1 << (sizeof(int) * 8 - 2);
3d4d5305
P
64#ifdef TSAN_REQUIRES_LOCKING
65 int r;
66
67 if (!TEST_true(CRYPTO_THREAD_write_lock(tsan_lock)))
68 return 0;
69 r = ++current_uid;
70 if (!TEST_true(CRYPTO_THREAD_unlock(tsan_lock)))
71 return 0;
72 return r;
0855591e 73
3d4d5305 74#else
0855591e 75 return tsan_counter(&current_uid);
3d4d5305 76#endif
0855591e
P
77}
78
71a04cfc
AG
79static int test_lock(void)
80{
81 CRYPTO_RWLOCK *lock = CRYPTO_THREAD_lock_new();
743840d5 82 int res;
71a04cfc 83
743840d5 84 res = TEST_true(CRYPTO_THREAD_read_lock(lock))
1fc97807
P
85 && TEST_true(CRYPTO_THREAD_unlock(lock))
86 && TEST_true(CRYPTO_THREAD_write_lock(lock))
743840d5 87 && TEST_true(CRYPTO_THREAD_unlock(lock));
71a04cfc
AG
88
89 CRYPTO_THREAD_lock_free(lock);
90
743840d5 91 return res;
71a04cfc
AG
92}
93
94static CRYPTO_ONCE once_run = CRYPTO_ONCE_STATIC_INIT;
95static unsigned once_run_count = 0;
96
97static void once_do_run(void)
98{
99 once_run_count++;
100}
101
102static void once_run_thread_cb(void)
103{
104 CRYPTO_THREAD_run_once(&once_run, once_do_run);
105}
106
107static int test_once(void)
108{
109 thread_t thread;
71a04cfc 110
ee25dd45
P
111 if (!TEST_true(run_thread(&thread, once_run_thread_cb))
112 || !TEST_true(wait_for_thread(thread))
113 || !CRYPTO_THREAD_run_once(&once_run, once_do_run)
114 || !TEST_int_eq(once_run_count, 1))
71a04cfc 115 return 0;
71a04cfc
AG
116 return 1;
117}
118
119static CRYPTO_THREAD_LOCAL thread_local_key;
120static unsigned destructor_run_count = 0;
121static int thread_local_thread_cb_ok = 0;
122
123static void thread_local_destructor(void *arg)
124{
125 unsigned *count;
126
127 if (arg == NULL)
128 return;
129
130 count = arg;
131
132 (*count)++;
133}
134
135static void thread_local_thread_cb(void)
136{
137 void *ptr;
138
139 ptr = CRYPTO_THREAD_get_local(&thread_local_key);
ee25dd45
P
140 if (!TEST_ptr_null(ptr)
141 || !TEST_true(CRYPTO_THREAD_set_local(&thread_local_key,
142 &destructor_run_count)))
71a04cfc 143 return;
71a04cfc
AG
144
145 ptr = CRYPTO_THREAD_get_local(&thread_local_key);
ee25dd45 146 if (!TEST_ptr_eq(ptr, &destructor_run_count))
71a04cfc 147 return;
71a04cfc
AG
148
149 thread_local_thread_cb_ok = 1;
150}
151
152static int test_thread_local(void)
153{
154 thread_t thread;
155 void *ptr = NULL;
156
ee25dd45
P
157 if (!TEST_true(CRYPTO_THREAD_init_local(&thread_local_key,
158 thread_local_destructor)))
71a04cfc 159 return 0;
71a04cfc
AG
160
161 ptr = CRYPTO_THREAD_get_local(&thread_local_key);
ee25dd45
P
162 if (!TEST_ptr_null(ptr)
163 || !TEST_true(run_thread(&thread, thread_local_thread_cb))
164 || !TEST_true(wait_for_thread(thread))
165 || !TEST_int_eq(thread_local_thread_cb_ok, 1))
71a04cfc 166 return 0;
71a04cfc
AG
167
168#if defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG)
169
170 ptr = CRYPTO_THREAD_get_local(&thread_local_key);
ee25dd45 171 if (!TEST_ptr_null(ptr))
71a04cfc 172 return 0;
71a04cfc
AG
173
174# if !defined(OPENSSL_SYS_WINDOWS)
ee25dd45 175 if (!TEST_int_eq(destructor_run_count, 1))
71a04cfc 176 return 0;
71a04cfc 177# endif
71a04cfc
AG
178#endif
179
ee25dd45 180 if (!TEST_true(CRYPTO_THREAD_cleanup_local(&thread_local_key)))
71a04cfc 181 return 0;
71a04cfc
AG
182 return 1;
183}
184
ea08f8b2
MC
185static int test_atomic(void)
186{
187 int val = 0, ret = 0, testresult = 0;
188 uint64_t val64 = 1, ret64 = 0;
189 CRYPTO_RWLOCK *lock = CRYPTO_THREAD_lock_new();
190
191 if (!TEST_ptr(lock))
192 return 0;
193
194 if (CRYPTO_atomic_add(&val, 1, &ret, NULL)) {
195 /* This succeeds therefore we're on a platform with lockless atomics */
196 if (!TEST_int_eq(val, 1) || !TEST_int_eq(val, ret))
197 goto err;
198 } else {
199 /* This failed therefore we're on a platform without lockless atomics */
200 if (!TEST_int_eq(val, 0) || !TEST_int_eq(val, ret))
201 goto err;
202 }
203 val = 0;
204 ret = 0;
205
206 if (!TEST_true(CRYPTO_atomic_add(&val, 1, &ret, lock)))
207 goto err;
208 if (!TEST_int_eq(val, 1) || !TEST_int_eq(val, ret))
209 goto err;
210
211 if (CRYPTO_atomic_or(&val64, 2, &ret64, NULL)) {
212 /* This succeeds therefore we're on a platform with lockless atomics */
213 if (!TEST_uint_eq((unsigned int)val64, 3)
214 || !TEST_uint_eq((unsigned int)val64, (unsigned int)ret64))
215 goto err;
216 } else {
217 /* This failed therefore we're on a platform without lockless atomics */
218 if (!TEST_uint_eq((unsigned int)val64, 1)
219 || !TEST_int_eq((unsigned int)ret64, 0))
220 goto err;
221 }
222 val64 = 1;
223 ret64 = 0;
224
225 if (!TEST_true(CRYPTO_atomic_or(&val64, 2, &ret64, lock)))
226 goto err;
227
228 if (!TEST_uint_eq((unsigned int)val64, 3)
229 || !TEST_uint_eq((unsigned int)val64, (unsigned int)ret64))
230 goto err;
231
232 ret64 = 0;
233 if (CRYPTO_atomic_load(&val64, &ret64, NULL)) {
234 /* This succeeds therefore we're on a platform with lockless atomics */
235 if (!TEST_uint_eq((unsigned int)val64, 3)
236 || !TEST_uint_eq((unsigned int)val64, (unsigned int)ret64))
237 goto err;
238 } else {
239 /* This failed therefore we're on a platform without lockless atomics */
240 if (!TEST_uint_eq((unsigned int)val64, 3)
241 || !TEST_int_eq((unsigned int)ret64, 0))
242 goto err;
243 }
244
245 ret64 = 0;
246 if (!TEST_true(CRYPTO_atomic_load(&val64, &ret64, lock)))
247 goto err;
248
249 if (!TEST_uint_eq((unsigned int)val64, 3)
250 || !TEST_uint_eq((unsigned int)val64, (unsigned int)ret64))
251 goto err;
252
253 testresult = 1;
254 err:
ea08f8b2
MC
255 CRYPTO_THREAD_lock_free(lock);
256 return testresult;
257}
258
ae95a40e
MC
259static OSSL_LIB_CTX *multi_libctx = NULL;
260static int multi_success;
0855591e
P
261static OSSL_PROVIDER *multi_provider[MAXIMUM_PROVIDERS + 1];
262static size_t multi_num_threads;
263static thread_t multi_threads[MAXIMUM_THREADS];
264
265static void multi_intialise(void)
266{
267 multi_success = 1;
268 multi_libctx = NULL;
269 multi_num_threads = 0;
270 memset(multi_threads, 0, sizeof(multi_threads));
271 memset(multi_provider, 0, sizeof(multi_provider));
272}
273
b88ce46e
HL
274static void multi_set_success(int ok)
275{
276 if (CRYPTO_THREAD_write_lock(global_lock) == 0) {
277 /* not synchronized, but better than not reporting failure */
278 multi_success = ok;
279 return;
280 }
281
282 multi_success = ok;
283
284 CRYPTO_THREAD_unlock(global_lock);
285}
286
0855591e
P
287static void thead_teardown_libctx(void)
288{
289 OSSL_PROVIDER **p;
290
291 for (p = multi_provider; *p != NULL; p++)
292 OSSL_PROVIDER_unload(*p);
293 OSSL_LIB_CTX_free(multi_libctx);
294 multi_intialise();
295}
296
297static int thread_setup_libctx(int libctx, const char *providers[])
298{
299 size_t n;
300
301 if (libctx && !TEST_true(test_get_libctx(&multi_libctx, NULL, config_file,
302 NULL, NULL)))
303 return 0;
304
305 if (providers != NULL)
306 for (n = 0; providers[n] != NULL; n++)
307 if (!TEST_size_t_lt(n, MAXIMUM_PROVIDERS)
308 || !TEST_ptr(multi_provider[n] = OSSL_PROVIDER_load(multi_libctx,
309 providers[n]))) {
310 thead_teardown_libctx();
311 return 0;
312 }
313 return 1;
314}
315
316static int teardown_threads(void)
317{
318 size_t i;
319
320 for (i = 0; i < multi_num_threads; i++)
321 if (!TEST_true(wait_for_thread(multi_threads[i])))
322 return 0;
323 return 1;
324}
325
326static int start_threads(size_t n, void (*thread_func)(void))
327{
328 size_t i;
329
330 if (!TEST_size_t_le(multi_num_threads + n, MAXIMUM_THREADS))
331 return 0;
332
333 for (i = 0 ; i < n; i++)
334 if (!TEST_true(run_thread(multi_threads + multi_num_threads++, thread_func)))
335 return 0;
336 return 1;
337}
338
339/* Template multi-threaded test function */
340static int thread_run_test(void (*main_func)(void),
341 size_t num_threads, void (*thread_func)(void),
342 int libctx, const char *providers[])
343{
344 int testresult = 0;
345
346 multi_intialise();
347 if (!thread_setup_libctx(libctx, providers)
348 || !start_threads(num_threads, thread_func))
349 goto err;
350
351 if (main_func != NULL)
352 main_func();
353
354 if (!teardown_threads()
355 || !TEST_true(multi_success))
356 goto err;
357 testresult = 1;
358 err:
359 thead_teardown_libctx();
360 return testresult;
361}
ae95a40e 362
b457c8f5 363static void thread_general_worker(void)
ae95a40e
MC
364{
365 EVP_MD_CTX *mdctx = EVP_MD_CTX_new();
366 EVP_MD *md = EVP_MD_fetch(multi_libctx, "SHA2-256", NULL);
367 EVP_CIPHER_CTX *cipherctx = EVP_CIPHER_CTX_new();
368 EVP_CIPHER *ciph = EVP_CIPHER_fetch(multi_libctx, "AES-128-CBC", NULL);
369 const char *message = "Hello World";
370 size_t messlen = strlen(message);
371 /* Should be big enough for encryption output too */
372 unsigned char out[EVP_MAX_MD_SIZE];
373 const unsigned char key[AES_BLOCK_SIZE] = {
374 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
375 0x0c, 0x0d, 0x0e, 0x0f
376 };
377 const unsigned char iv[AES_BLOCK_SIZE] = {
378 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
379 0x0c, 0x0d, 0x0e, 0x0f
380 };
381 unsigned int mdoutl;
382 int ciphoutl;
ae95a40e
MC
383 EVP_PKEY *pkey = NULL;
384 int testresult = 0;
385 int i, isfips;
386
387 isfips = OSSL_PROVIDER_available(multi_libctx, "fips");
388
389 if (!TEST_ptr(mdctx)
390 || !TEST_ptr(md)
391 || !TEST_ptr(cipherctx)
392 || !TEST_ptr(ciph))
393 goto err;
394
395 /* Do some work */
396 for (i = 0; i < 5; i++) {
397 if (!TEST_true(EVP_DigestInit_ex(mdctx, md, NULL))
398 || !TEST_true(EVP_DigestUpdate(mdctx, message, messlen))
399 || !TEST_true(EVP_DigestFinal(mdctx, out, &mdoutl)))
400 goto err;
401 }
402 for (i = 0; i < 5; i++) {
403 if (!TEST_true(EVP_EncryptInit_ex(cipherctx, ciph, NULL, key, iv))
404 || !TEST_true(EVP_EncryptUpdate(cipherctx, out, &ciphoutl,
405 (unsigned char *)message,
406 messlen))
407 || !TEST_true(EVP_EncryptFinal(cipherctx, out, &ciphoutl)))
408 goto err;
409 }
410
f9253152
DDO
411 /*
412 * We want the test to run quickly - not securely.
413 * Therefore we use an insecure bit length where we can (512).
414 * In the FIPS module though we must use a longer length.
415 */
416 pkey = EVP_PKEY_Q_keygen(multi_libctx, NULL, "RSA", isfips ? 2048 : 512);
417 if (!TEST_ptr(pkey))
ae95a40e
MC
418 goto err;
419
420 testresult = 1;
421 err:
422 EVP_MD_CTX_free(mdctx);
423 EVP_MD_free(md);
424 EVP_CIPHER_CTX_free(cipherctx);
425 EVP_CIPHER_free(ciph);
ae95a40e
MC
426 EVP_PKEY_free(pkey);
427 if (!testresult)
b88ce46e 428 multi_set_success(0);
ae95a40e
MC
429}
430
b457c8f5
MC
431static void thread_multi_simple_fetch(void)
432{
a135dea4 433 EVP_MD *md = EVP_MD_fetch(multi_libctx, "SHA2-256", NULL);
b457c8f5
MC
434
435 if (md != NULL)
436 EVP_MD_free(md);
437 else
b88ce46e 438 multi_set_success(0);
b457c8f5
MC
439}
440
a0134d29
MC
441static EVP_PKEY *shared_evp_pkey = NULL;
442
443static void thread_shared_evp_pkey(void)
444{
445 char *msg = "Hello World";
446 unsigned char ctbuf[256];
447 unsigned char ptbuf[256];
0650ac43 448 size_t ptlen, ctlen = sizeof(ctbuf);
a0134d29
MC
449 EVP_PKEY_CTX *ctx = NULL;
450 int success = 0;
451 int i;
452
453 for (i = 0; i < 1 + do_fips; i++) {
454 if (i > 0)
455 EVP_PKEY_CTX_free(ctx);
456 ctx = EVP_PKEY_CTX_new_from_pkey(multi_libctx, shared_evp_pkey,
457 i == 0 ? "provider=default"
458 : "provider=fips");
459 if (!TEST_ptr(ctx))
460 goto err;
461
462 if (!TEST_int_ge(EVP_PKEY_encrypt_init(ctx), 0)
463 || !TEST_int_ge(EVP_PKEY_encrypt(ctx, ctbuf, &ctlen,
464 (unsigned char *)msg, strlen(msg)),
465 0))
466 goto err;
467
468 EVP_PKEY_CTX_free(ctx);
469 ctx = EVP_PKEY_CTX_new_from_pkey(multi_libctx, shared_evp_pkey, NULL);
470
471 if (!TEST_ptr(ctx))
472 goto err;
473
0650ac43 474 ptlen = sizeof(ptbuf);
a0134d29 475 if (!TEST_int_ge(EVP_PKEY_decrypt_init(ctx), 0)
0650ac43 476 || !TEST_int_gt(EVP_PKEY_decrypt(ctx, ptbuf, &ptlen, ctbuf, ctlen),
a0134d29
MC
477 0)
478 || !TEST_mem_eq(msg, strlen(msg), ptbuf, ptlen))
479 goto err;
480 }
481
482 success = 1;
483
484 err:
485 EVP_PKEY_CTX_free(ctx);
486 if (!success)
b88ce46e 487 multi_set_success(0);
a0134d29
MC
488}
489
98369ef2
MC
490static void thread_provider_load_unload(void)
491{
492 OSSL_PROVIDER *deflt = OSSL_PROVIDER_load(multi_libctx, "default");
493
494 if (!TEST_ptr(deflt)
495 || !TEST_true(OSSL_PROVIDER_available(multi_libctx, "default")))
b88ce46e 496 multi_set_success(0);
98369ef2
MC
497
498 OSSL_PROVIDER_unload(deflt);
499}
e8afd78a 500
0855591e 501static int test_multi_general_worker_default_provider(void)
ae95a40e 502{
0855591e
P
503 return thread_run_test(&thread_general_worker, 2, &thread_general_worker,
504 1, default_provider);
505}
ae95a40e 506
0855591e
P
507static int test_multi_general_worker_fips_provider(void)
508{
509 if (!do_fips)
ae95a40e 510 return TEST_skip("FIPS not supported");
0855591e
P
511 return thread_run_test(&thread_general_worker, 2, &thread_general_worker,
512 1, fips_provider);
513}
ae95a40e 514
0855591e
P
515static int test_multi_fetch_worker(void)
516{
517 return thread_run_test(&thread_multi_simple_fetch,
518 2, &thread_multi_simple_fetch, 1, default_provider);
519}
e8afd78a 520
0855591e
P
521static int test_multi_shared_pkey_common(void (*worker)(void))
522{
523 int testresult = 0;
9a633a1c 524
0855591e
P
525 multi_intialise();
526 if (!thread_setup_libctx(1, do_fips ? fips_and_default_providers
527 : default_provider)
528 || !TEST_ptr(shared_evp_pkey = load_pkey_pem(privkey, multi_libctx))
529 || !start_threads(1, &thread_shared_evp_pkey)
530 || !start_threads(1, worker))
ae95a40e
MC
531 goto err;
532
0855591e 533 thread_shared_evp_pkey();
b457c8f5 534
0855591e
P
535 if (!teardown_threads()
536 || !TEST_true(multi_success))
ae95a40e 537 goto err;
ae95a40e 538 testresult = 1;
0855591e
P
539 err:
540 EVP_PKEY_free(shared_evp_pkey);
541 thead_teardown_libctx();
542 return testresult;
543}
544
545#ifndef OPENSSL_NO_DEPRECATED_3_0
546static void thread_downgrade_shared_evp_pkey(void)
547{
c3932c34 548 /*
0855591e
P
549 * This test is only relevant for deprecated functions that perform
550 * downgrading
c3932c34 551 */
0855591e 552 if (EVP_PKEY_get0_RSA(shared_evp_pkey) == NULL)
b88ce46e 553 multi_set_success(0);
0855591e
P
554}
555
556static int test_multi_downgrade_shared_pkey(void)
557{
558 return test_multi_shared_pkey_common(&thread_downgrade_shared_evp_pkey);
559}
560#endif
561
562static int test_multi_shared_pkey(void)
563{
564 return test_multi_shared_pkey_common(&thread_shared_evp_pkey);
565}
566
567static int test_multi_load_unload_provider(void)
568{
569 EVP_MD *sha256 = NULL;
570 OSSL_PROVIDER *prov = NULL;
571 int testresult = 0;
572
573 multi_intialise();
574 if (!thread_setup_libctx(1, NULL)
575 || !TEST_ptr(prov = OSSL_PROVIDER_load(multi_libctx, "default"))
576 || !TEST_ptr(sha256 = EVP_MD_fetch(multi_libctx, "SHA2-256", NULL))
577 || !TEST_true(OSSL_PROVIDER_unload(prov)))
578 goto err;
579 prov = NULL;
580
581 if (!start_threads(2, &thread_provider_load_unload))
582 goto err;
ae95a40e 583
0855591e
P
584 thread_provider_load_unload();
585
586 if (!teardown_threads()
587 || !TEST_true(multi_success))
588 goto err;
589 testresult = 1;
ae95a40e
MC
590 err:
591 OSSL_PROVIDER_unload(prov);
0855591e
P
592 EVP_MD_free(sha256);
593 thead_teardown_libctx();
ae95a40e
MC
594 return testresult;
595}
596
293e251e 597static char *multi_load_provider = "legacy";
2f17e978
RL
598/*
599 * This test attempts to load several providers at the same time, and if
600 * run with a thread sanitizer, should crash if the core provider code
601 * doesn't synchronize well enough.
602 */
2f17e978
RL
603static void test_multi_load_worker(void)
604{
605 OSSL_PROVIDER *prov;
606
293e251e 607 if (!TEST_ptr(prov = OSSL_PROVIDER_load(multi_libctx, multi_load_provider))
0855591e 608 || !TEST_true(OSSL_PROVIDER_unload(prov)))
b88ce46e 609 multi_set_success(0);
2f17e978
RL
610}
611
a135dea4
P
612static int test_multi_default(void)
613{
b9bc8eb0
P
614 /* Avoid running this test twice */
615 if (multidefault_run) {
616 TEST_skip("multi default test already run");
617 return 1;
618 }
619 multidefault_run = 1;
620
0855591e
P
621 return thread_run_test(&thread_multi_simple_fetch,
622 2, &thread_multi_simple_fetch, 0, default_provider);
a135dea4
P
623}
624
b9bc8eb0
P
625static int test_multi_load(void)
626{
0855591e 627 int res = 1;
293e251e 628 OSSL_PROVIDER *prov;
b9bc8eb0
P
629
630 /* The multidefault test must run prior to this test */
631 if (!multidefault_run) {
632 TEST_info("Running multi default test first");
633 res = test_multi_default();
634 }
635
293e251e
MC
636 /*
637 * We use the legacy provider in test_multi_load_worker because it uses a
638 * child libctx that might hit more codepaths that might be sensitive to
639 * threading issues. But in a no-legacy build that won't be loadable so
640 * we use the default provider instead.
641 */
642 prov = OSSL_PROVIDER_load(NULL, "legacy");
643 if (prov == NULL) {
644 TEST_info("Cannot load legacy provider - assuming this is a no-legacy build");
645 multi_load_provider = "default";
646 }
647 OSSL_PROVIDER_unload(prov);
648
649 return thread_run_test(NULL, MAXIMUM_THREADS, &test_multi_load_worker, 0,
650 NULL) && res;
0855591e 651}
b9bc8eb0 652
0855591e
P
653static void test_obj_create_one(void)
654{
655 char tids[12], oid[40], sn[30], ln[30];
656 int id = get_new_uid();
657
658 BIO_snprintf(tids, sizeof(tids), "%d", id);
659 BIO_snprintf(oid, sizeof(oid), "1.3.6.1.4.1.16604.%s", tids);
660 BIO_snprintf(sn, sizeof(sn), "short-name-%s", tids);
661 BIO_snprintf(ln, sizeof(ln), "long-name-%s", tids);
3d4d5305
P
662 if (!TEST_int_ne(id, 0)
663 || !TEST_true(id = OBJ_create(oid, sn, ln))
0855591e 664 || !TEST_true(OBJ_add_sigid(id, NID_sha3_256, NID_rsa)))
b88ce46e 665 multi_set_success(0);
0855591e 666}
b9bc8eb0 667
0855591e
P
668static int test_obj_add(void)
669{
670 return thread_run_test(&test_obj_create_one,
671 MAXIMUM_THREADS, &test_obj_create_one,
672 1, default_provider);
b9bc8eb0
P
673}
674
ef7a9b44
HL
675static void test_lib_ctx_load_config_worker(void)
676{
677 if (!TEST_int_eq(OSSL_LIB_CTX_load_config(multi_libctx, config_file), 1))
b88ce46e 678 multi_set_success(0);
ef7a9b44
HL
679}
680
681static int test_lib_ctx_load_config(void)
682{
683 return thread_run_test(&test_lib_ctx_load_config_worker,
684 MAXIMUM_THREADS, &test_lib_ctx_load_config_worker,
685 1, default_provider);
686}
687
b88ce46e
HL
688#if !defined(OPENSSL_NO_DGRAM) && !defined(OPENSSL_NO_SOCK)
689static BIO *multi_bio1, *multi_bio2;
690
691static void test_bio_dgram_pair_worker(void)
692{
693 ossl_unused int r;
694 int ok = 0;
695 uint8_t ch = 0;
696 uint8_t scratch[64];
697 BIO_MSG msg = {0};
698 size_t num_processed = 0;
699
700 if (!TEST_int_eq(RAND_bytes_ex(multi_libctx, &ch, 1, 64), 1))
701 goto err;
702
703 msg.data = scratch;
704 msg.data_len = sizeof(scratch);
705
706 /*
707 * We do not test for failure here as recvmmsg may fail if no sendmmsg
708 * has been called yet. The purpose of this code is to exercise tsan.
709 */
710 if (ch & 2)
711 r = BIO_sendmmsg(ch & 1 ? multi_bio2 : multi_bio1, &msg,
712 sizeof(BIO_MSG), 1, 0, &num_processed);
713 else
714 r = BIO_recvmmsg(ch & 1 ? multi_bio2 : multi_bio1, &msg,
715 sizeof(BIO_MSG), 1, 0, &num_processed);
716
717 ok = 1;
718err:
719 if (ok == 0)
720 multi_set_success(0);
721}
722
723static int test_bio_dgram_pair(void)
724{
725 int r;
726 BIO *bio1 = NULL, *bio2 = NULL;
727
728 r = BIO_new_bio_dgram_pair(&bio1, 0, &bio2, 0);
729 if (!TEST_int_eq(r, 1))
730 goto err;
731
732 multi_bio1 = bio1;
733 multi_bio2 = bio2;
734
735 r = thread_run_test(&test_bio_dgram_pair_worker,
736 MAXIMUM_THREADS, &test_bio_dgram_pair_worker,
737 1, default_provider);
738
739err:
740 BIO_free(bio1);
741 BIO_free(bio2);
742 return r;
743}
744#endif
745
29f25a10
MC
746static const char *pemdataraw[] = {
747 "-----BEGIN RSA PRIVATE KEY-----\n",
748 "MIIBOgIBAAJBAMFcGsaxxdgiuuGmCkVImy4h99CqT7jwY3pexPGcnUFtR2Fh36Bp\n",
749 "oncwtkZ4cAgtvd4Qs8PkxUdp6p/DlUmObdkCAwEAAQJAUR44xX6zB3eaeyvTRzms\n",
750 "kHADrPCmPWnr8dxsNwiDGHzrMKLN+i/HAam+97HxIKVWNDH2ba9Mf1SA8xu9dcHZ\n",
751 "AQIhAOHPCLxbtQFVxlnhSyxYeb7O323c3QulPNn3bhOipElpAiEA2zZpBE8ZXVnL\n",
752 "74QjG4zINlDfH+EOEtjJJ3RtaYDugvECIBtsQDxXytChsRgDQ1TcXdStXPcDppie\n",
753 "dZhm8yhRTTBZAiAZjE/U9rsIDC0ebxIAZfn3iplWh84yGB3pgUI3J5WkoQIhAInE\n",
754 "HTUY5WRj5riZtkyGnbm3DvF+1eMtO2lYV+OuLcfE\n",
755 "-----END RSA PRIVATE KEY-----\n",
756 NULL
757};
758
759static void test_pem_read_one(void)
760{
761 EVP_PKEY *key = NULL;
762 BIO *pem = NULL;
763 char *pemdata;
764 size_t len;
765
766 pemdata = glue_strings(pemdataraw, &len);
767 if (pemdata == NULL) {
768 multi_set_success(0);
769 goto err;
770 }
771
772 pem = BIO_new_mem_buf(pemdata, len);
773 if (pem == NULL) {
774 multi_set_success(0);
775 goto err;
776 }
777
778 key = PEM_read_bio_PrivateKey(pem, NULL, NULL, NULL);
779 if (key == NULL)
780 multi_set_success(0);
781
782 err:
783 EVP_PKEY_free(key);
784 BIO_free(pem);
785 OPENSSL_free(pemdata);
786}
787
788/* Test reading PEM files in multiple threads */
789static int test_pem_read(void)
790{
791 return thread_run_test(&test_pem_read_one, MAXIMUM_THREADS,
792 &test_pem_read_one, 1, default_provider);
793}
794
ae95a40e
MC
795typedef enum OPTION_choice {
796 OPT_ERR = -1,
797 OPT_EOF = 0,
9a633a1c 798 OPT_FIPS, OPT_CONFIG_FILE,
ae95a40e
MC
799 OPT_TEST_ENUM
800} OPTION_CHOICE;
801
802const OPTIONS *test_get_options(void)
803{
804 static const OPTIONS options[] = {
805 OPT_TEST_OPTIONS_DEFAULT_USAGE,
806 { "fips", OPT_FIPS, '-', "Test the FIPS provider" },
9a633a1c
P
807 { "config", OPT_CONFIG_FILE, '<',
808 "The configuration file to use for the libctx" },
ae95a40e
MC
809 { NULL }
810 };
811 return options;
812}
813
ad887416 814int setup_tests(void)
71a04cfc 815{
ae95a40e 816 OPTION_CHOICE o;
a0134d29 817 char *datadir;
ae95a40e
MC
818
819 while ((o = opt_next()) != OPT_EOF) {
820 switch (o) {
821 case OPT_FIPS:
822 do_fips = 1;
823 break;
9a633a1c
P
824 case OPT_CONFIG_FILE:
825 config_file = opt_arg();
826 break;
ae95a40e
MC
827 case OPT_TEST_CASES:
828 break;
829 default:
830 return 0;
831 }
832 }
833
a0134d29
MC
834 if (!TEST_ptr(datadir = test_get_argument(0)))
835 return 0;
836
837 privkey = test_mk_file_path(datadir, "rsakey.pem");
838 if (!TEST_ptr(privkey))
839 return 0;
840
b88ce46e
HL
841 if (!TEST_ptr(global_lock = CRYPTO_THREAD_lock_new()))
842 return 0;
843
3d4d5305
P
844#ifdef TSAN_REQUIRES_LOCKING
845 if (!TEST_ptr(tsan_lock = CRYPTO_THREAD_lock_new()))
846 return 0;
847#endif
848
a135dea4
P
849 /* Keep first to validate auto creation of default library context */
850 ADD_TEST(test_multi_default);
851
ee25dd45
P
852 ADD_TEST(test_lock);
853 ADD_TEST(test_once);
854 ADD_TEST(test_thread_local);
ea08f8b2 855 ADD_TEST(test_atomic);
2f17e978 856 ADD_TEST(test_multi_load);
0855591e
P
857 ADD_TEST(test_multi_general_worker_default_provider);
858 ADD_TEST(test_multi_general_worker_fips_provider);
859 ADD_TEST(test_multi_fetch_worker);
860 ADD_TEST(test_multi_shared_pkey);
861#ifndef OPENSSL_NO_DEPRECATED_3_0
862 ADD_TEST(test_multi_downgrade_shared_pkey);
863#endif
864 ADD_TEST(test_multi_load_unload_provider);
865 ADD_TEST(test_obj_add);
ef7a9b44 866 ADD_TEST(test_lib_ctx_load_config);
b88ce46e
HL
867#if !defined(OPENSSL_NO_DGRAM) && !defined(OPENSSL_NO_SOCK)
868 ADD_TEST(test_bio_dgram_pair);
869#endif
29f25a10 870 ADD_TEST(test_pem_read);
ad887416 871 return 1;
71a04cfc 872}
a0134d29
MC
873
874void cleanup_tests(void)
875{
876 OPENSSL_free(privkey);
3d4d5305
P
877#ifdef TSAN_REQUIRES_LOCKING
878 CRYPTO_THREAD_lock_free(tsan_lock);
879#endif
b88ce46e 880 CRYPTO_THREAD_lock_free(global_lock);
a0134d29 881}