]>
Commit | Line | Data |
---|---|---|
440e5d80 | 1 | /* |
b6461792 | 2 | * Copyright 2016-2024 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" | |
d0e1a0ae NH |
32 | #include "internal/time.h" |
33 | #include "internal/rcu.h" | |
ee25dd45 | 34 | #include "testutil.h" |
235776b2 | 35 | #include "threadstest.h" |
71a04cfc | 36 | |
d0e1a0ae NH |
37 | #ifdef __SANITIZE_THREAD__ |
38 | #include <sanitizer/tsan_interface.h> | |
39 | #define TSAN_ACQUIRE(s) __tsan_acquire(s) | |
40 | #else | |
41 | #define TSAN_ACQUIRE(s) | |
42 | #endif | |
43 | ||
0855591e | 44 | /* Limit the maximum number of threads */ |
293e251e | 45 | #define MAXIMUM_THREADS 10 |
0855591e P |
46 | |
47 | /* Limit the maximum number of providers loaded into a library context */ | |
48 | #define MAXIMUM_PROVIDERS 4 | |
49 | ||
ae95a40e | 50 | static int do_fips = 0; |
a0134d29 | 51 | static char *privkey; |
9a633a1c | 52 | static char *config_file = NULL; |
b9bc8eb0 | 53 | static int multidefault_run = 0; |
ae95a40e | 54 | |
0855591e P |
55 | static const char *default_provider[] = { "default", NULL }; |
56 | static const char *fips_provider[] = { "fips", NULL }; | |
57 | static const char *fips_and_default_providers[] = { "default", "fips", NULL }; | |
58 | ||
b88ce46e HL |
59 | static CRYPTO_RWLOCK *global_lock; |
60 | ||
3d4d5305 P |
61 | #ifdef TSAN_REQUIRES_LOCKING |
62 | static CRYPTO_RWLOCK *tsan_lock; | |
63 | #endif | |
64 | ||
65 | /* Grab a globally unique integer value, return 0 on failure */ | |
0855591e P |
66 | static int get_new_uid(void) |
67 | { | |
68 | /* | |
69 | * Start with a nice large number to avoid potential conflicts when | |
70 | * we generate a new OID. | |
71 | */ | |
72 | static TSAN_QUALIFIER int current_uid = 1 << (sizeof(int) * 8 - 2); | |
3d4d5305 P |
73 | #ifdef TSAN_REQUIRES_LOCKING |
74 | int r; | |
75 | ||
76 | if (!TEST_true(CRYPTO_THREAD_write_lock(tsan_lock))) | |
77 | return 0; | |
78 | r = ++current_uid; | |
79 | if (!TEST_true(CRYPTO_THREAD_unlock(tsan_lock))) | |
80 | return 0; | |
81 | return r; | |
0855591e | 82 | |
3d4d5305 | 83 | #else |
0855591e | 84 | return tsan_counter(¤t_uid); |
3d4d5305 | 85 | #endif |
0855591e P |
86 | } |
87 | ||
71a04cfc AG |
88 | static int test_lock(void) |
89 | { | |
90 | CRYPTO_RWLOCK *lock = CRYPTO_THREAD_lock_new(); | |
743840d5 | 91 | int res; |
71a04cfc | 92 | |
743840d5 | 93 | res = TEST_true(CRYPTO_THREAD_read_lock(lock)) |
1fc97807 P |
94 | && TEST_true(CRYPTO_THREAD_unlock(lock)) |
95 | && TEST_true(CRYPTO_THREAD_write_lock(lock)) | |
743840d5 | 96 | && TEST_true(CRYPTO_THREAD_unlock(lock)); |
71a04cfc AG |
97 | |
98 | CRYPTO_THREAD_lock_free(lock); | |
99 | ||
743840d5 | 100 | return res; |
71a04cfc AG |
101 | } |
102 | ||
d0e1a0ae NH |
103 | #if defined(OPENSSL_THREADS) |
104 | static int contention = 0; | |
105 | static int rwwriter1_done = 0; | |
106 | static int rwwriter2_done = 0; | |
107 | static int rwreader1_iterations = 0; | |
108 | static int rwreader2_iterations = 0; | |
109 | static int rwwriter1_iterations = 0; | |
110 | static int rwwriter2_iterations = 0; | |
111 | static int *rwwriter_ptr = NULL; | |
112 | static int rw_torture_result = 1; | |
113 | static CRYPTO_RWLOCK *rwtorturelock = NULL; | |
5f8b8129 | 114 | static CRYPTO_RWLOCK *atomiclock = NULL; |
d0e1a0ae NH |
115 | |
116 | static void rwwriter_fn(int id, int *iterations) | |
117 | { | |
118 | int count; | |
119 | int *old, *new; | |
120 | OSSL_TIME t1, t2; | |
121 | t1 = ossl_time_now(); | |
122 | ||
123 | for (count = 0; ; count++) { | |
124 | new = CRYPTO_zalloc(sizeof (int), NULL, 0); | |
125 | if (contention == 0) | |
126 | OSSL_sleep(1000); | |
127 | if (!CRYPTO_THREAD_write_lock(rwtorturelock)) | |
128 | abort(); | |
129 | if (rwwriter_ptr != NULL) { | |
130 | *new = *rwwriter_ptr + 1; | |
131 | } else { | |
132 | *new = 0; | |
133 | } | |
134 | old = rwwriter_ptr; | |
135 | rwwriter_ptr = new; | |
136 | if (!CRYPTO_THREAD_unlock(rwtorturelock)) | |
137 | abort(); | |
138 | if (old != NULL) | |
139 | CRYPTO_free(old, __FILE__, __LINE__); | |
140 | t2 = ossl_time_now(); | |
141 | if ((ossl_time2seconds(t2) - ossl_time2seconds(t1)) >= 4) | |
142 | break; | |
143 | } | |
144 | *iterations = count; | |
145 | return; | |
146 | } | |
147 | ||
148 | static void rwwriter1_fn(void) | |
149 | { | |
150 | int local; | |
151 | ||
152 | TEST_info("Starting writer1"); | |
153 | rwwriter_fn(1, &rwwriter1_iterations); | |
5f8b8129 | 154 | CRYPTO_atomic_add(&rwwriter1_done, 1, &local, atomiclock); |
d0e1a0ae NH |
155 | } |
156 | ||
157 | static void rwwriter2_fn(void) | |
158 | { | |
159 | int local; | |
160 | ||
161 | TEST_info("Starting writer 2"); | |
162 | rwwriter_fn(2, &rwwriter2_iterations); | |
5f8b8129 | 163 | CRYPTO_atomic_add(&rwwriter2_done, 1, &local, atomiclock); |
d0e1a0ae NH |
164 | } |
165 | ||
166 | static void rwreader_fn(int *iterations) | |
167 | { | |
168 | unsigned int count = 0; | |
169 | ||
170 | int old = 0; | |
171 | int lw1 = 0; | |
172 | int lw2 = 0; | |
173 | ||
174 | if (CRYPTO_THREAD_read_lock(rwtorturelock) == 0) | |
175 | abort(); | |
176 | ||
177 | while (lw1 != 1 || lw2 != 1) { | |
5f8b8129 NH |
178 | CRYPTO_atomic_add(&rwwriter1_done, 0, &lw1, atomiclock); |
179 | CRYPTO_atomic_add(&rwwriter2_done, 0, &lw2, atomiclock); | |
d0e1a0ae NH |
180 | |
181 | count++; | |
182 | if (rwwriter_ptr != NULL && old > *rwwriter_ptr) { | |
183 | TEST_info("rwwriter pointer went backwards\n"); | |
184 | rw_torture_result = 0; | |
185 | } | |
186 | if (CRYPTO_THREAD_unlock(rwtorturelock) == 0) | |
187 | abort(); | |
188 | *iterations = count; | |
189 | if (rw_torture_result == 0) { | |
190 | *iterations = count; | |
191 | return; | |
192 | } | |
193 | if (CRYPTO_THREAD_read_lock(rwtorturelock) == 0) | |
194 | abort(); | |
195 | } | |
196 | *iterations = count; | |
197 | if (CRYPTO_THREAD_unlock(rwtorturelock) == 0) | |
198 | abort(); | |
199 | } | |
200 | ||
201 | static void rwreader1_fn(void) | |
202 | { | |
203 | TEST_info("Starting reader 1"); | |
204 | rwreader_fn(&rwreader1_iterations); | |
205 | } | |
206 | ||
207 | static void rwreader2_fn(void) | |
208 | { | |
209 | TEST_info("Starting reader 2"); | |
210 | rwreader_fn(&rwreader2_iterations); | |
211 | } | |
212 | ||
213 | static thread_t rwwriter1; | |
214 | static thread_t rwwriter2; | |
215 | static thread_t rwreader1; | |
216 | static thread_t rwreader2; | |
217 | ||
218 | static int _torture_rw(void) | |
219 | { | |
220 | double tottime = 0; | |
221 | int ret = 0; | |
222 | double avr, avw; | |
223 | OSSL_TIME t1, t2; | |
224 | struct timeval dtime; | |
225 | ||
226 | rwtorturelock = CRYPTO_THREAD_lock_new(); | |
5f8b8129 | 227 | atomiclock = CRYPTO_THREAD_lock_new(); |
d0e1a0ae NH |
228 | rwwriter1_iterations = 0; |
229 | rwwriter2_iterations = 0; | |
230 | rwreader1_iterations = 0; | |
231 | rwreader2_iterations = 0; | |
232 | rwwriter1_done = 0; | |
233 | rwwriter2_done = 0; | |
234 | rw_torture_result = 1; | |
235 | ||
236 | memset(&rwwriter1, 0, sizeof(thread_t)); | |
237 | memset(&rwwriter2, 0, sizeof(thread_t)); | |
238 | memset(&rwreader1, 0, sizeof(thread_t)); | |
239 | memset(&rwreader2, 0, sizeof(thread_t)); | |
240 | ||
241 | TEST_info("Staring rw torture"); | |
242 | t1 = ossl_time_now(); | |
243 | if (!TEST_true(run_thread(&rwreader1, rwreader1_fn)) | |
244 | || !TEST_true(run_thread(&rwreader2, rwreader2_fn)) | |
245 | || !TEST_true(run_thread(&rwwriter1, rwwriter1_fn)) | |
246 | || !TEST_true(run_thread(&rwwriter2, rwwriter2_fn)) | |
247 | || !TEST_true(wait_for_thread(rwwriter1)) | |
248 | || !TEST_true(wait_for_thread(rwwriter2)) | |
249 | || !TEST_true(wait_for_thread(rwreader1)) | |
250 | || !TEST_true(wait_for_thread(rwreader2))) | |
251 | goto out; | |
252 | ||
253 | t2 = ossl_time_now(); | |
254 | dtime = ossl_time_to_timeval(ossl_time_subtract(t2, t1)); | |
255 | tottime = dtime.tv_sec + (dtime.tv_usec / 1e6); | |
256 | TEST_info("rw_torture_result is %d\n", rw_torture_result); | |
257 | TEST_info("performed %d reads and %d writes over 2 read and 2 write threads in %e seconds", | |
258 | rwreader1_iterations + rwreader2_iterations, | |
259 | rwwriter1_iterations + rwwriter2_iterations, tottime); | |
260 | avr = tottime / (rwreader1_iterations + rwreader2_iterations); | |
261 | avw = (tottime / (rwwriter1_iterations + rwwriter2_iterations)); | |
262 | TEST_info("Average read time %e/read", avr); | |
263 | TEST_info("Averate write time %e/write", avw); | |
264 | ||
265 | if (TEST_int_eq(rw_torture_result, 1)) | |
266 | ret = 1; | |
267 | out: | |
268 | CRYPTO_THREAD_lock_free(rwtorturelock); | |
5f8b8129 | 269 | CRYPTO_THREAD_lock_free(atomiclock); |
d0e1a0ae NH |
270 | rwtorturelock = NULL; |
271 | return ret; | |
272 | } | |
273 | ||
274 | static int torture_rw_low(void) | |
275 | { | |
276 | contention = 0; | |
277 | return _torture_rw(); | |
278 | } | |
279 | ||
280 | static int torture_rw_high(void) | |
281 | { | |
282 | contention = 1; | |
283 | return _torture_rw(); | |
284 | } | |
285 | ||
286 | ||
1967539e | 287 | # ifndef OPENSSL_SYS_MACOSX |
d0e1a0ae NH |
288 | static CRYPTO_RCU_LOCK *rcu_lock = NULL; |
289 | ||
290 | static int writer1_done = 0; | |
291 | static int writer2_done = 0; | |
292 | static int reader1_iterations = 0; | |
293 | static int reader2_iterations = 0; | |
294 | static int writer1_iterations = 0; | |
295 | static int writer2_iterations = 0; | |
b50c174e NH |
296 | static uint64_t *writer_ptr = NULL; |
297 | static uint64_t global_ctr = 0; | |
d0e1a0ae | 298 | static int rcu_torture_result = 1; |
d0e1a0ae NH |
299 | static void free_old_rcu_data(void *data) |
300 | { | |
301 | CRYPTO_free(data, NULL, 0); | |
302 | } | |
303 | ||
304 | static void writer_fn(int id, int *iterations) | |
305 | { | |
306 | int count; | |
307 | OSSL_TIME t1, t2; | |
b50c174e | 308 | uint64_t *old, *new; |
d0e1a0ae NH |
309 | |
310 | t1 = ossl_time_now(); | |
311 | ||
312 | for (count = 0; ; count++) { | |
b50c174e | 313 | new = CRYPTO_zalloc(sizeof(uint64_t), NULL, 0); |
d0e1a0ae NH |
314 | if (contention == 0) |
315 | OSSL_sleep(1000); | |
316 | ossl_rcu_write_lock(rcu_lock); | |
317 | old = ossl_rcu_deref(&writer_ptr); | |
318 | TSAN_ACQUIRE(&writer_ptr); | |
319 | *new = global_ctr++; | |
320 | ossl_rcu_assign_ptr(&writer_ptr, &new); | |
321 | if (contention == 0) | |
322 | ossl_rcu_call(rcu_lock, free_old_rcu_data, old); | |
323 | ossl_rcu_write_unlock(rcu_lock); | |
324 | if (contention != 0) { | |
325 | ossl_synchronize_rcu(rcu_lock); | |
326 | CRYPTO_free(old, NULL, 0); | |
327 | } | |
328 | t2 = ossl_time_now(); | |
329 | if ((ossl_time2seconds(t2) - ossl_time2seconds(t1)) >= 4) | |
330 | break; | |
331 | } | |
332 | *iterations = count; | |
333 | return; | |
334 | } | |
335 | ||
336 | static void writer1_fn(void) | |
337 | { | |
338 | int local; | |
339 | ||
340 | TEST_info("Starting writer1"); | |
341 | writer_fn(1, &writer1_iterations); | |
5f8b8129 | 342 | CRYPTO_atomic_add(&writer1_done, 1, &local, atomiclock); |
d0e1a0ae NH |
343 | } |
344 | ||
345 | static void writer2_fn(void) | |
346 | { | |
347 | int local; | |
348 | ||
349 | TEST_info("Starting writer2"); | |
350 | writer_fn(2, &writer2_iterations); | |
5f8b8129 | 351 | CRYPTO_atomic_add(&writer2_done, 1, &local, atomiclock); |
d0e1a0ae NH |
352 | } |
353 | ||
354 | static void reader_fn(int *iterations) | |
355 | { | |
356 | unsigned int count = 0; | |
b50c174e NH |
357 | uint64_t *valp; |
358 | uint64_t val; | |
359 | uint64_t oldval = 0; | |
d0e1a0ae NH |
360 | int lw1 = 0; |
361 | int lw2 = 0; | |
362 | ||
363 | while (lw1 != 1 || lw2 != 1) { | |
5f8b8129 NH |
364 | CRYPTO_atomic_add(&writer1_done, 0, &lw1, atomiclock); |
365 | CRYPTO_atomic_add(&writer2_done, 0, &lw2, atomiclock); | |
d0e1a0ae NH |
366 | count++; |
367 | ossl_rcu_read_lock(rcu_lock); | |
368 | valp = ossl_rcu_deref(&writer_ptr); | |
369 | val = (valp == NULL) ? 0 : *valp; | |
1967539e | 370 | |
d0e1a0ae | 371 | if (oldval > val) { |
1967539e | 372 | TEST_info("rcu torture value went backwards! %llu : %llu", (unsigned long long)oldval, (unsigned long long)val); |
d0e1a0ae NH |
373 | rcu_torture_result = 0; |
374 | } | |
375 | oldval = val; /* just try to deref the pointer */ | |
376 | ossl_rcu_read_unlock(rcu_lock); | |
377 | if (rcu_torture_result == 0) { | |
378 | *iterations = count; | |
379 | return; | |
380 | } | |
381 | } | |
382 | *iterations = count; | |
383 | } | |
384 | ||
385 | static void reader1_fn(void) | |
386 | { | |
387 | TEST_info("Starting reader 1"); | |
388 | reader_fn(&reader1_iterations); | |
389 | } | |
390 | ||
391 | static void reader2_fn(void) | |
392 | { | |
393 | TEST_info("Starting reader 2"); | |
394 | reader_fn(&reader2_iterations); | |
395 | } | |
396 | ||
397 | static thread_t writer1; | |
398 | static thread_t writer2; | |
399 | static thread_t reader1; | |
400 | static thread_t reader2; | |
401 | ||
402 | static int _torture_rcu(void) | |
403 | { | |
404 | OSSL_TIME t1, t2; | |
405 | struct timeval dtime; | |
406 | double tottime; | |
407 | double avr, avw; | |
408 | ||
5f8b8129 | 409 | atomiclock = CRYPTO_THREAD_lock_new(); |
d0e1a0ae NH |
410 | memset(&writer1, 0, sizeof(thread_t)); |
411 | memset(&writer2, 0, sizeof(thread_t)); | |
412 | memset(&reader1, 0, sizeof(thread_t)); | |
413 | memset(&reader2, 0, sizeof(thread_t)); | |
414 | ||
415 | writer1_iterations = 0; | |
416 | writer2_iterations = 0; | |
417 | reader1_iterations = 0; | |
418 | reader2_iterations = 0; | |
419 | writer1_done = 0; | |
420 | writer2_done = 0; | |
421 | rcu_torture_result = 1; | |
422 | ||
423 | rcu_lock = ossl_rcu_lock_new(1); | |
424 | ||
425 | TEST_info("Staring rcu torture"); | |
426 | t1 = ossl_time_now(); | |
427 | if (!TEST_true(run_thread(&reader1, reader1_fn)) | |
428 | || !TEST_true(run_thread(&reader2, reader2_fn)) | |
429 | || !TEST_true(run_thread(&writer1, writer1_fn)) | |
430 | || !TEST_true(run_thread(&writer2, writer2_fn)) | |
431 | || !TEST_true(wait_for_thread(writer1)) | |
432 | || !TEST_true(wait_for_thread(writer2)) | |
433 | || !TEST_true(wait_for_thread(reader1)) | |
434 | || !TEST_true(wait_for_thread(reader2))) | |
435 | return 0; | |
436 | ||
437 | t2 = ossl_time_now(); | |
438 | dtime = ossl_time_to_timeval(ossl_time_subtract(t2, t1)); | |
439 | tottime = dtime.tv_sec + (dtime.tv_usec / 1e6); | |
440 | TEST_info("rcu_torture_result is %d\n", rcu_torture_result); | |
441 | TEST_info("performed %d reads and %d writes over 2 read and 2 write threads in %e seconds", | |
442 | reader1_iterations + reader2_iterations, | |
443 | writer1_iterations + writer2_iterations, tottime); | |
444 | avr = tottime / (reader1_iterations + reader2_iterations); | |
445 | avw = tottime / (writer1_iterations + writer2_iterations); | |
446 | TEST_info("Average read time %e/read", avr); | |
447 | TEST_info("Average write time %e/write", avw); | |
448 | ||
449 | ossl_rcu_lock_free(rcu_lock); | |
5f8b8129 | 450 | CRYPTO_THREAD_lock_free(atomiclock); |
d0e1a0ae NH |
451 | if (!TEST_int_eq(rcu_torture_result, 1)) |
452 | return 0; | |
453 | ||
454 | return 1; | |
455 | } | |
456 | ||
457 | static int torture_rcu_low(void) | |
458 | { | |
459 | contention = 0; | |
460 | return _torture_rcu(); | |
461 | } | |
462 | ||
463 | static int torture_rcu_high(void) | |
464 | { | |
465 | contention = 1; | |
466 | return _torture_rcu(); | |
467 | } | |
1967539e | 468 | # endif |
d0e1a0ae NH |
469 | #endif |
470 | ||
71a04cfc AG |
471 | static CRYPTO_ONCE once_run = CRYPTO_ONCE_STATIC_INIT; |
472 | static unsigned once_run_count = 0; | |
473 | ||
474 | static void once_do_run(void) | |
475 | { | |
476 | once_run_count++; | |
477 | } | |
478 | ||
479 | static void once_run_thread_cb(void) | |
480 | { | |
481 | CRYPTO_THREAD_run_once(&once_run, once_do_run); | |
482 | } | |
483 | ||
484 | static int test_once(void) | |
485 | { | |
486 | thread_t thread; | |
71a04cfc | 487 | |
ee25dd45 P |
488 | if (!TEST_true(run_thread(&thread, once_run_thread_cb)) |
489 | || !TEST_true(wait_for_thread(thread)) | |
490 | || !CRYPTO_THREAD_run_once(&once_run, once_do_run) | |
491 | || !TEST_int_eq(once_run_count, 1)) | |
71a04cfc | 492 | return 0; |
71a04cfc AG |
493 | return 1; |
494 | } | |
495 | ||
496 | static CRYPTO_THREAD_LOCAL thread_local_key; | |
497 | static unsigned destructor_run_count = 0; | |
498 | static int thread_local_thread_cb_ok = 0; | |
499 | ||
500 | static void thread_local_destructor(void *arg) | |
501 | { | |
502 | unsigned *count; | |
503 | ||
504 | if (arg == NULL) | |
505 | return; | |
506 | ||
507 | count = arg; | |
508 | ||
509 | (*count)++; | |
510 | } | |
511 | ||
512 | static void thread_local_thread_cb(void) | |
513 | { | |
514 | void *ptr; | |
515 | ||
516 | ptr = CRYPTO_THREAD_get_local(&thread_local_key); | |
ee25dd45 P |
517 | if (!TEST_ptr_null(ptr) |
518 | || !TEST_true(CRYPTO_THREAD_set_local(&thread_local_key, | |
519 | &destructor_run_count))) | |
71a04cfc | 520 | return; |
71a04cfc AG |
521 | |
522 | ptr = CRYPTO_THREAD_get_local(&thread_local_key); | |
ee25dd45 | 523 | if (!TEST_ptr_eq(ptr, &destructor_run_count)) |
71a04cfc | 524 | return; |
71a04cfc AG |
525 | |
526 | thread_local_thread_cb_ok = 1; | |
527 | } | |
528 | ||
529 | static int test_thread_local(void) | |
530 | { | |
531 | thread_t thread; | |
532 | void *ptr = NULL; | |
533 | ||
ee25dd45 P |
534 | if (!TEST_true(CRYPTO_THREAD_init_local(&thread_local_key, |
535 | thread_local_destructor))) | |
71a04cfc | 536 | return 0; |
71a04cfc AG |
537 | |
538 | ptr = CRYPTO_THREAD_get_local(&thread_local_key); | |
ee25dd45 P |
539 | if (!TEST_ptr_null(ptr) |
540 | || !TEST_true(run_thread(&thread, thread_local_thread_cb)) | |
541 | || !TEST_true(wait_for_thread(thread)) | |
542 | || !TEST_int_eq(thread_local_thread_cb_ok, 1)) | |
71a04cfc | 543 | return 0; |
71a04cfc AG |
544 | |
545 | #if defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG) | |
546 | ||
547 | ptr = CRYPTO_THREAD_get_local(&thread_local_key); | |
ee25dd45 | 548 | if (!TEST_ptr_null(ptr)) |
71a04cfc | 549 | return 0; |
71a04cfc AG |
550 | |
551 | # if !defined(OPENSSL_SYS_WINDOWS) | |
ee25dd45 | 552 | if (!TEST_int_eq(destructor_run_count, 1)) |
71a04cfc | 553 | return 0; |
71a04cfc | 554 | # endif |
71a04cfc AG |
555 | #endif |
556 | ||
ee25dd45 | 557 | if (!TEST_true(CRYPTO_THREAD_cleanup_local(&thread_local_key))) |
71a04cfc | 558 | return 0; |
71a04cfc AG |
559 | return 1; |
560 | } | |
561 | ||
ea08f8b2 MC |
562 | static int test_atomic(void) |
563 | { | |
564 | int val = 0, ret = 0, testresult = 0; | |
565 | uint64_t val64 = 1, ret64 = 0; | |
566 | CRYPTO_RWLOCK *lock = CRYPTO_THREAD_lock_new(); | |
567 | ||
568 | if (!TEST_ptr(lock)) | |
569 | return 0; | |
570 | ||
571 | if (CRYPTO_atomic_add(&val, 1, &ret, NULL)) { | |
572 | /* This succeeds therefore we're on a platform with lockless atomics */ | |
573 | if (!TEST_int_eq(val, 1) || !TEST_int_eq(val, ret)) | |
574 | goto err; | |
575 | } else { | |
576 | /* This failed therefore we're on a platform without lockless atomics */ | |
577 | if (!TEST_int_eq(val, 0) || !TEST_int_eq(val, ret)) | |
578 | goto err; | |
579 | } | |
580 | val = 0; | |
581 | ret = 0; | |
582 | ||
583 | if (!TEST_true(CRYPTO_atomic_add(&val, 1, &ret, lock))) | |
584 | goto err; | |
585 | if (!TEST_int_eq(val, 1) || !TEST_int_eq(val, ret)) | |
586 | goto err; | |
587 | ||
588 | if (CRYPTO_atomic_or(&val64, 2, &ret64, NULL)) { | |
589 | /* This succeeds therefore we're on a platform with lockless atomics */ | |
590 | if (!TEST_uint_eq((unsigned int)val64, 3) | |
591 | || !TEST_uint_eq((unsigned int)val64, (unsigned int)ret64)) | |
592 | goto err; | |
593 | } else { | |
594 | /* This failed therefore we're on a platform without lockless atomics */ | |
595 | if (!TEST_uint_eq((unsigned int)val64, 1) | |
596 | || !TEST_int_eq((unsigned int)ret64, 0)) | |
597 | goto err; | |
598 | } | |
599 | val64 = 1; | |
600 | ret64 = 0; | |
601 | ||
602 | if (!TEST_true(CRYPTO_atomic_or(&val64, 2, &ret64, lock))) | |
603 | goto err; | |
604 | ||
605 | if (!TEST_uint_eq((unsigned int)val64, 3) | |
606 | || !TEST_uint_eq((unsigned int)val64, (unsigned int)ret64)) | |
607 | goto err; | |
608 | ||
609 | ret64 = 0; | |
610 | if (CRYPTO_atomic_load(&val64, &ret64, NULL)) { | |
611 | /* This succeeds therefore we're on a platform with lockless atomics */ | |
612 | if (!TEST_uint_eq((unsigned int)val64, 3) | |
613 | || !TEST_uint_eq((unsigned int)val64, (unsigned int)ret64)) | |
614 | goto err; | |
615 | } else { | |
616 | /* This failed therefore we're on a platform without lockless atomics */ | |
617 | if (!TEST_uint_eq((unsigned int)val64, 3) | |
618 | || !TEST_int_eq((unsigned int)ret64, 0)) | |
619 | goto err; | |
620 | } | |
621 | ||
622 | ret64 = 0; | |
623 | if (!TEST_true(CRYPTO_atomic_load(&val64, &ret64, lock))) | |
624 | goto err; | |
625 | ||
626 | if (!TEST_uint_eq((unsigned int)val64, 3) | |
627 | || !TEST_uint_eq((unsigned int)val64, (unsigned int)ret64)) | |
628 | goto err; | |
629 | ||
630 | testresult = 1; | |
631 | err: | |
ea08f8b2 MC |
632 | CRYPTO_THREAD_lock_free(lock); |
633 | return testresult; | |
634 | } | |
635 | ||
ae95a40e MC |
636 | static OSSL_LIB_CTX *multi_libctx = NULL; |
637 | static int multi_success; | |
0855591e P |
638 | static OSSL_PROVIDER *multi_provider[MAXIMUM_PROVIDERS + 1]; |
639 | static size_t multi_num_threads; | |
640 | static thread_t multi_threads[MAXIMUM_THREADS]; | |
641 | ||
642 | static void multi_intialise(void) | |
643 | { | |
644 | multi_success = 1; | |
645 | multi_libctx = NULL; | |
646 | multi_num_threads = 0; | |
647 | memset(multi_threads, 0, sizeof(multi_threads)); | |
648 | memset(multi_provider, 0, sizeof(multi_provider)); | |
649 | } | |
650 | ||
b88ce46e HL |
651 | static void multi_set_success(int ok) |
652 | { | |
653 | if (CRYPTO_THREAD_write_lock(global_lock) == 0) { | |
654 | /* not synchronized, but better than not reporting failure */ | |
655 | multi_success = ok; | |
656 | return; | |
657 | } | |
658 | ||
659 | multi_success = ok; | |
660 | ||
661 | CRYPTO_THREAD_unlock(global_lock); | |
662 | } | |
663 | ||
0855591e P |
664 | static void thead_teardown_libctx(void) |
665 | { | |
666 | OSSL_PROVIDER **p; | |
667 | ||
668 | for (p = multi_provider; *p != NULL; p++) | |
669 | OSSL_PROVIDER_unload(*p); | |
670 | OSSL_LIB_CTX_free(multi_libctx); | |
671 | multi_intialise(); | |
672 | } | |
673 | ||
674 | static int thread_setup_libctx(int libctx, const char *providers[]) | |
675 | { | |
676 | size_t n; | |
677 | ||
678 | if (libctx && !TEST_true(test_get_libctx(&multi_libctx, NULL, config_file, | |
679 | NULL, NULL))) | |
680 | return 0; | |
681 | ||
682 | if (providers != NULL) | |
683 | for (n = 0; providers[n] != NULL; n++) | |
684 | if (!TEST_size_t_lt(n, MAXIMUM_PROVIDERS) | |
685 | || !TEST_ptr(multi_provider[n] = OSSL_PROVIDER_load(multi_libctx, | |
686 | providers[n]))) { | |
687 | thead_teardown_libctx(); | |
688 | return 0; | |
689 | } | |
690 | return 1; | |
691 | } | |
692 | ||
693 | static int teardown_threads(void) | |
694 | { | |
695 | size_t i; | |
696 | ||
697 | for (i = 0; i < multi_num_threads; i++) | |
698 | if (!TEST_true(wait_for_thread(multi_threads[i]))) | |
699 | return 0; | |
700 | return 1; | |
701 | } | |
702 | ||
703 | static int start_threads(size_t n, void (*thread_func)(void)) | |
704 | { | |
705 | size_t i; | |
706 | ||
707 | if (!TEST_size_t_le(multi_num_threads + n, MAXIMUM_THREADS)) | |
708 | return 0; | |
709 | ||
710 | for (i = 0 ; i < n; i++) | |
711 | if (!TEST_true(run_thread(multi_threads + multi_num_threads++, thread_func))) | |
712 | return 0; | |
713 | return 1; | |
714 | } | |
715 | ||
716 | /* Template multi-threaded test function */ | |
717 | static int thread_run_test(void (*main_func)(void), | |
718 | size_t num_threads, void (*thread_func)(void), | |
719 | int libctx, const char *providers[]) | |
720 | { | |
721 | int testresult = 0; | |
722 | ||
723 | multi_intialise(); | |
724 | if (!thread_setup_libctx(libctx, providers) | |
725 | || !start_threads(num_threads, thread_func)) | |
726 | goto err; | |
727 | ||
728 | if (main_func != NULL) | |
729 | main_func(); | |
730 | ||
731 | if (!teardown_threads() | |
732 | || !TEST_true(multi_success)) | |
733 | goto err; | |
734 | testresult = 1; | |
735 | err: | |
736 | thead_teardown_libctx(); | |
737 | return testresult; | |
738 | } | |
ae95a40e | 739 | |
b457c8f5 | 740 | static void thread_general_worker(void) |
ae95a40e MC |
741 | { |
742 | EVP_MD_CTX *mdctx = EVP_MD_CTX_new(); | |
743 | EVP_MD *md = EVP_MD_fetch(multi_libctx, "SHA2-256", NULL); | |
744 | EVP_CIPHER_CTX *cipherctx = EVP_CIPHER_CTX_new(); | |
745 | EVP_CIPHER *ciph = EVP_CIPHER_fetch(multi_libctx, "AES-128-CBC", NULL); | |
746 | const char *message = "Hello World"; | |
747 | size_t messlen = strlen(message); | |
748 | /* Should be big enough for encryption output too */ | |
749 | unsigned char out[EVP_MAX_MD_SIZE]; | |
750 | const unsigned char key[AES_BLOCK_SIZE] = { | |
751 | 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, | |
752 | 0x0c, 0x0d, 0x0e, 0x0f | |
753 | }; | |
754 | const unsigned char iv[AES_BLOCK_SIZE] = { | |
755 | 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, | |
756 | 0x0c, 0x0d, 0x0e, 0x0f | |
757 | }; | |
758 | unsigned int mdoutl; | |
759 | int ciphoutl; | |
ae95a40e MC |
760 | EVP_PKEY *pkey = NULL; |
761 | int testresult = 0; | |
762 | int i, isfips; | |
763 | ||
764 | isfips = OSSL_PROVIDER_available(multi_libctx, "fips"); | |
765 | ||
766 | if (!TEST_ptr(mdctx) | |
767 | || !TEST_ptr(md) | |
768 | || !TEST_ptr(cipherctx) | |
769 | || !TEST_ptr(ciph)) | |
770 | goto err; | |
771 | ||
772 | /* Do some work */ | |
773 | for (i = 0; i < 5; i++) { | |
774 | if (!TEST_true(EVP_DigestInit_ex(mdctx, md, NULL)) | |
775 | || !TEST_true(EVP_DigestUpdate(mdctx, message, messlen)) | |
776 | || !TEST_true(EVP_DigestFinal(mdctx, out, &mdoutl))) | |
777 | goto err; | |
778 | } | |
779 | for (i = 0; i < 5; i++) { | |
780 | if (!TEST_true(EVP_EncryptInit_ex(cipherctx, ciph, NULL, key, iv)) | |
781 | || !TEST_true(EVP_EncryptUpdate(cipherctx, out, &ciphoutl, | |
782 | (unsigned char *)message, | |
783 | messlen)) | |
784 | || !TEST_true(EVP_EncryptFinal(cipherctx, out, &ciphoutl))) | |
785 | goto err; | |
786 | } | |
787 | ||
f9253152 DDO |
788 | /* |
789 | * We want the test to run quickly - not securely. | |
790 | * Therefore we use an insecure bit length where we can (512). | |
791 | * In the FIPS module though we must use a longer length. | |
792 | */ | |
793 | pkey = EVP_PKEY_Q_keygen(multi_libctx, NULL, "RSA", isfips ? 2048 : 512); | |
794 | if (!TEST_ptr(pkey)) | |
ae95a40e MC |
795 | goto err; |
796 | ||
797 | testresult = 1; | |
798 | err: | |
799 | EVP_MD_CTX_free(mdctx); | |
800 | EVP_MD_free(md); | |
801 | EVP_CIPHER_CTX_free(cipherctx); | |
802 | EVP_CIPHER_free(ciph); | |
ae95a40e MC |
803 | EVP_PKEY_free(pkey); |
804 | if (!testresult) | |
b88ce46e | 805 | multi_set_success(0); |
ae95a40e MC |
806 | } |
807 | ||
b457c8f5 MC |
808 | static void thread_multi_simple_fetch(void) |
809 | { | |
a135dea4 | 810 | EVP_MD *md = EVP_MD_fetch(multi_libctx, "SHA2-256", NULL); |
b457c8f5 MC |
811 | |
812 | if (md != NULL) | |
813 | EVP_MD_free(md); | |
814 | else | |
b88ce46e | 815 | multi_set_success(0); |
b457c8f5 MC |
816 | } |
817 | ||
a0134d29 MC |
818 | static EVP_PKEY *shared_evp_pkey = NULL; |
819 | ||
820 | static void thread_shared_evp_pkey(void) | |
821 | { | |
822 | char *msg = "Hello World"; | |
823 | unsigned char ctbuf[256]; | |
824 | unsigned char ptbuf[256]; | |
0650ac43 | 825 | size_t ptlen, ctlen = sizeof(ctbuf); |
a0134d29 MC |
826 | EVP_PKEY_CTX *ctx = NULL; |
827 | int success = 0; | |
828 | int i; | |
829 | ||
830 | for (i = 0; i < 1 + do_fips; i++) { | |
831 | if (i > 0) | |
832 | EVP_PKEY_CTX_free(ctx); | |
833 | ctx = EVP_PKEY_CTX_new_from_pkey(multi_libctx, shared_evp_pkey, | |
834 | i == 0 ? "provider=default" | |
835 | : "provider=fips"); | |
836 | if (!TEST_ptr(ctx)) | |
837 | goto err; | |
838 | ||
839 | if (!TEST_int_ge(EVP_PKEY_encrypt_init(ctx), 0) | |
840 | || !TEST_int_ge(EVP_PKEY_encrypt(ctx, ctbuf, &ctlen, | |
841 | (unsigned char *)msg, strlen(msg)), | |
842 | 0)) | |
843 | goto err; | |
844 | ||
845 | EVP_PKEY_CTX_free(ctx); | |
846 | ctx = EVP_PKEY_CTX_new_from_pkey(multi_libctx, shared_evp_pkey, NULL); | |
847 | ||
848 | if (!TEST_ptr(ctx)) | |
849 | goto err; | |
850 | ||
0650ac43 | 851 | ptlen = sizeof(ptbuf); |
a0134d29 | 852 | if (!TEST_int_ge(EVP_PKEY_decrypt_init(ctx), 0) |
0650ac43 | 853 | || !TEST_int_gt(EVP_PKEY_decrypt(ctx, ptbuf, &ptlen, ctbuf, ctlen), |
a0134d29 MC |
854 | 0) |
855 | || !TEST_mem_eq(msg, strlen(msg), ptbuf, ptlen)) | |
856 | goto err; | |
857 | } | |
858 | ||
859 | success = 1; | |
860 | ||
861 | err: | |
862 | EVP_PKEY_CTX_free(ctx); | |
863 | if (!success) | |
b88ce46e | 864 | multi_set_success(0); |
a0134d29 MC |
865 | } |
866 | ||
98369ef2 MC |
867 | static void thread_provider_load_unload(void) |
868 | { | |
869 | OSSL_PROVIDER *deflt = OSSL_PROVIDER_load(multi_libctx, "default"); | |
870 | ||
871 | if (!TEST_ptr(deflt) | |
872 | || !TEST_true(OSSL_PROVIDER_available(multi_libctx, "default"))) | |
b88ce46e | 873 | multi_set_success(0); |
98369ef2 MC |
874 | |
875 | OSSL_PROVIDER_unload(deflt); | |
876 | } | |
e8afd78a | 877 | |
0855591e | 878 | static int test_multi_general_worker_default_provider(void) |
ae95a40e | 879 | { |
0855591e P |
880 | return thread_run_test(&thread_general_worker, 2, &thread_general_worker, |
881 | 1, default_provider); | |
882 | } | |
ae95a40e | 883 | |
0855591e P |
884 | static int test_multi_general_worker_fips_provider(void) |
885 | { | |
886 | if (!do_fips) | |
ae95a40e | 887 | return TEST_skip("FIPS not supported"); |
0855591e P |
888 | return thread_run_test(&thread_general_worker, 2, &thread_general_worker, |
889 | 1, fips_provider); | |
890 | } | |
ae95a40e | 891 | |
0855591e P |
892 | static int test_multi_fetch_worker(void) |
893 | { | |
894 | return thread_run_test(&thread_multi_simple_fetch, | |
895 | 2, &thread_multi_simple_fetch, 1, default_provider); | |
896 | } | |
e8afd78a | 897 | |
0855591e P |
898 | static int test_multi_shared_pkey_common(void (*worker)(void)) |
899 | { | |
900 | int testresult = 0; | |
9a633a1c | 901 | |
0855591e P |
902 | multi_intialise(); |
903 | if (!thread_setup_libctx(1, do_fips ? fips_and_default_providers | |
904 | : default_provider) | |
905 | || !TEST_ptr(shared_evp_pkey = load_pkey_pem(privkey, multi_libctx)) | |
906 | || !start_threads(1, &thread_shared_evp_pkey) | |
907 | || !start_threads(1, worker)) | |
ae95a40e MC |
908 | goto err; |
909 | ||
0855591e | 910 | thread_shared_evp_pkey(); |
b457c8f5 | 911 | |
0855591e P |
912 | if (!teardown_threads() |
913 | || !TEST_true(multi_success)) | |
ae95a40e | 914 | goto err; |
ae95a40e | 915 | testresult = 1; |
0855591e P |
916 | err: |
917 | EVP_PKEY_free(shared_evp_pkey); | |
918 | thead_teardown_libctx(); | |
919 | return testresult; | |
920 | } | |
921 | ||
922 | #ifndef OPENSSL_NO_DEPRECATED_3_0 | |
923 | static void thread_downgrade_shared_evp_pkey(void) | |
924 | { | |
c3932c34 | 925 | /* |
0855591e P |
926 | * This test is only relevant for deprecated functions that perform |
927 | * downgrading | |
c3932c34 | 928 | */ |
0855591e | 929 | if (EVP_PKEY_get0_RSA(shared_evp_pkey) == NULL) |
b88ce46e | 930 | multi_set_success(0); |
0855591e P |
931 | } |
932 | ||
933 | static int test_multi_downgrade_shared_pkey(void) | |
934 | { | |
935 | return test_multi_shared_pkey_common(&thread_downgrade_shared_evp_pkey); | |
936 | } | |
937 | #endif | |
938 | ||
939 | static int test_multi_shared_pkey(void) | |
940 | { | |
941 | return test_multi_shared_pkey_common(&thread_shared_evp_pkey); | |
942 | } | |
943 | ||
944 | static int test_multi_load_unload_provider(void) | |
945 | { | |
946 | EVP_MD *sha256 = NULL; | |
947 | OSSL_PROVIDER *prov = NULL; | |
948 | int testresult = 0; | |
949 | ||
950 | multi_intialise(); | |
951 | if (!thread_setup_libctx(1, NULL) | |
952 | || !TEST_ptr(prov = OSSL_PROVIDER_load(multi_libctx, "default")) | |
953 | || !TEST_ptr(sha256 = EVP_MD_fetch(multi_libctx, "SHA2-256", NULL)) | |
954 | || !TEST_true(OSSL_PROVIDER_unload(prov))) | |
955 | goto err; | |
956 | prov = NULL; | |
957 | ||
958 | if (!start_threads(2, &thread_provider_load_unload)) | |
959 | goto err; | |
ae95a40e | 960 | |
0855591e P |
961 | thread_provider_load_unload(); |
962 | ||
963 | if (!teardown_threads() | |
964 | || !TEST_true(multi_success)) | |
965 | goto err; | |
966 | testresult = 1; | |
ae95a40e MC |
967 | err: |
968 | OSSL_PROVIDER_unload(prov); | |
0855591e P |
969 | EVP_MD_free(sha256); |
970 | thead_teardown_libctx(); | |
ae95a40e MC |
971 | return testresult; |
972 | } | |
973 | ||
293e251e | 974 | static char *multi_load_provider = "legacy"; |
2f17e978 RL |
975 | /* |
976 | * This test attempts to load several providers at the same time, and if | |
977 | * run with a thread sanitizer, should crash if the core provider code | |
978 | * doesn't synchronize well enough. | |
979 | */ | |
2f17e978 RL |
980 | static void test_multi_load_worker(void) |
981 | { | |
982 | OSSL_PROVIDER *prov; | |
983 | ||
293e251e | 984 | if (!TEST_ptr(prov = OSSL_PROVIDER_load(multi_libctx, multi_load_provider)) |
0855591e | 985 | || !TEST_true(OSSL_PROVIDER_unload(prov))) |
b88ce46e | 986 | multi_set_success(0); |
2f17e978 RL |
987 | } |
988 | ||
a135dea4 P |
989 | static int test_multi_default(void) |
990 | { | |
b9bc8eb0 P |
991 | /* Avoid running this test twice */ |
992 | if (multidefault_run) { | |
993 | TEST_skip("multi default test already run"); | |
994 | return 1; | |
995 | } | |
996 | multidefault_run = 1; | |
997 | ||
0855591e P |
998 | return thread_run_test(&thread_multi_simple_fetch, |
999 | 2, &thread_multi_simple_fetch, 0, default_provider); | |
a135dea4 P |
1000 | } |
1001 | ||
b9bc8eb0 P |
1002 | static int test_multi_load(void) |
1003 | { | |
0855591e | 1004 | int res = 1; |
293e251e | 1005 | OSSL_PROVIDER *prov; |
b9bc8eb0 P |
1006 | |
1007 | /* The multidefault test must run prior to this test */ | |
1008 | if (!multidefault_run) { | |
1009 | TEST_info("Running multi default test first"); | |
1010 | res = test_multi_default(); | |
1011 | } | |
1012 | ||
293e251e MC |
1013 | /* |
1014 | * We use the legacy provider in test_multi_load_worker because it uses a | |
1015 | * child libctx that might hit more codepaths that might be sensitive to | |
1016 | * threading issues. But in a no-legacy build that won't be loadable so | |
1017 | * we use the default provider instead. | |
1018 | */ | |
1019 | prov = OSSL_PROVIDER_load(NULL, "legacy"); | |
1020 | if (prov == NULL) { | |
1021 | TEST_info("Cannot load legacy provider - assuming this is a no-legacy build"); | |
1022 | multi_load_provider = "default"; | |
1023 | } | |
1024 | OSSL_PROVIDER_unload(prov); | |
1025 | ||
1026 | return thread_run_test(NULL, MAXIMUM_THREADS, &test_multi_load_worker, 0, | |
1027 | NULL) && res; | |
0855591e | 1028 | } |
b9bc8eb0 | 1029 | |
0855591e P |
1030 | static void test_obj_create_one(void) |
1031 | { | |
1032 | char tids[12], oid[40], sn[30], ln[30]; | |
1033 | int id = get_new_uid(); | |
1034 | ||
1035 | BIO_snprintf(tids, sizeof(tids), "%d", id); | |
1036 | BIO_snprintf(oid, sizeof(oid), "1.3.6.1.4.1.16604.%s", tids); | |
1037 | BIO_snprintf(sn, sizeof(sn), "short-name-%s", tids); | |
1038 | BIO_snprintf(ln, sizeof(ln), "long-name-%s", tids); | |
3d4d5305 P |
1039 | if (!TEST_int_ne(id, 0) |
1040 | || !TEST_true(id = OBJ_create(oid, sn, ln)) | |
0855591e | 1041 | || !TEST_true(OBJ_add_sigid(id, NID_sha3_256, NID_rsa))) |
b88ce46e | 1042 | multi_set_success(0); |
0855591e | 1043 | } |
b9bc8eb0 | 1044 | |
0855591e P |
1045 | static int test_obj_add(void) |
1046 | { | |
1047 | return thread_run_test(&test_obj_create_one, | |
1048 | MAXIMUM_THREADS, &test_obj_create_one, | |
1049 | 1, default_provider); | |
b9bc8eb0 P |
1050 | } |
1051 | ||
ef7a9b44 HL |
1052 | static void test_lib_ctx_load_config_worker(void) |
1053 | { | |
1054 | if (!TEST_int_eq(OSSL_LIB_CTX_load_config(multi_libctx, config_file), 1)) | |
b88ce46e | 1055 | multi_set_success(0); |
ef7a9b44 HL |
1056 | } |
1057 | ||
1058 | static int test_lib_ctx_load_config(void) | |
1059 | { | |
1060 | return thread_run_test(&test_lib_ctx_load_config_worker, | |
1061 | MAXIMUM_THREADS, &test_lib_ctx_load_config_worker, | |
1062 | 1, default_provider); | |
1063 | } | |
1064 | ||
b88ce46e HL |
1065 | #if !defined(OPENSSL_NO_DGRAM) && !defined(OPENSSL_NO_SOCK) |
1066 | static BIO *multi_bio1, *multi_bio2; | |
1067 | ||
1068 | static void test_bio_dgram_pair_worker(void) | |
1069 | { | |
1070 | ossl_unused int r; | |
1071 | int ok = 0; | |
1072 | uint8_t ch = 0; | |
1073 | uint8_t scratch[64]; | |
1074 | BIO_MSG msg = {0}; | |
1075 | size_t num_processed = 0; | |
1076 | ||
1077 | if (!TEST_int_eq(RAND_bytes_ex(multi_libctx, &ch, 1, 64), 1)) | |
1078 | goto err; | |
1079 | ||
1080 | msg.data = scratch; | |
1081 | msg.data_len = sizeof(scratch); | |
1082 | ||
1083 | /* | |
1084 | * We do not test for failure here as recvmmsg may fail if no sendmmsg | |
1085 | * has been called yet. The purpose of this code is to exercise tsan. | |
1086 | */ | |
1087 | if (ch & 2) | |
1088 | r = BIO_sendmmsg(ch & 1 ? multi_bio2 : multi_bio1, &msg, | |
1089 | sizeof(BIO_MSG), 1, 0, &num_processed); | |
1090 | else | |
1091 | r = BIO_recvmmsg(ch & 1 ? multi_bio2 : multi_bio1, &msg, | |
1092 | sizeof(BIO_MSG), 1, 0, &num_processed); | |
1093 | ||
1094 | ok = 1; | |
1095 | err: | |
1096 | if (ok == 0) | |
1097 | multi_set_success(0); | |
1098 | } | |
1099 | ||
1100 | static int test_bio_dgram_pair(void) | |
1101 | { | |
1102 | int r; | |
1103 | BIO *bio1 = NULL, *bio2 = NULL; | |
1104 | ||
1105 | r = BIO_new_bio_dgram_pair(&bio1, 0, &bio2, 0); | |
1106 | if (!TEST_int_eq(r, 1)) | |
1107 | goto err; | |
1108 | ||
1109 | multi_bio1 = bio1; | |
1110 | multi_bio2 = bio2; | |
1111 | ||
1112 | r = thread_run_test(&test_bio_dgram_pair_worker, | |
1113 | MAXIMUM_THREADS, &test_bio_dgram_pair_worker, | |
1114 | 1, default_provider); | |
1115 | ||
1116 | err: | |
1117 | BIO_free(bio1); | |
1118 | BIO_free(bio2); | |
1119 | return r; | |
1120 | } | |
1121 | #endif | |
1122 | ||
29f25a10 MC |
1123 | static const char *pemdataraw[] = { |
1124 | "-----BEGIN RSA PRIVATE KEY-----\n", | |
1125 | "MIIBOgIBAAJBAMFcGsaxxdgiuuGmCkVImy4h99CqT7jwY3pexPGcnUFtR2Fh36Bp\n", | |
1126 | "oncwtkZ4cAgtvd4Qs8PkxUdp6p/DlUmObdkCAwEAAQJAUR44xX6zB3eaeyvTRzms\n", | |
1127 | "kHADrPCmPWnr8dxsNwiDGHzrMKLN+i/HAam+97HxIKVWNDH2ba9Mf1SA8xu9dcHZ\n", | |
1128 | "AQIhAOHPCLxbtQFVxlnhSyxYeb7O323c3QulPNn3bhOipElpAiEA2zZpBE8ZXVnL\n", | |
1129 | "74QjG4zINlDfH+EOEtjJJ3RtaYDugvECIBtsQDxXytChsRgDQ1TcXdStXPcDppie\n", | |
1130 | "dZhm8yhRTTBZAiAZjE/U9rsIDC0ebxIAZfn3iplWh84yGB3pgUI3J5WkoQIhAInE\n", | |
1131 | "HTUY5WRj5riZtkyGnbm3DvF+1eMtO2lYV+OuLcfE\n", | |
1132 | "-----END RSA PRIVATE KEY-----\n", | |
1133 | NULL | |
1134 | }; | |
1135 | ||
1136 | static void test_pem_read_one(void) | |
1137 | { | |
1138 | EVP_PKEY *key = NULL; | |
1139 | BIO *pem = NULL; | |
1140 | char *pemdata; | |
1141 | size_t len; | |
1142 | ||
1143 | pemdata = glue_strings(pemdataraw, &len); | |
1144 | if (pemdata == NULL) { | |
1145 | multi_set_success(0); | |
1146 | goto err; | |
1147 | } | |
1148 | ||
1149 | pem = BIO_new_mem_buf(pemdata, len); | |
1150 | if (pem == NULL) { | |
1151 | multi_set_success(0); | |
1152 | goto err; | |
1153 | } | |
1154 | ||
1155 | key = PEM_read_bio_PrivateKey(pem, NULL, NULL, NULL); | |
1156 | if (key == NULL) | |
1157 | multi_set_success(0); | |
1158 | ||
1159 | err: | |
1160 | EVP_PKEY_free(key); | |
1161 | BIO_free(pem); | |
1162 | OPENSSL_free(pemdata); | |
1163 | } | |
1164 | ||
1165 | /* Test reading PEM files in multiple threads */ | |
1166 | static int test_pem_read(void) | |
1167 | { | |
1168 | return thread_run_test(&test_pem_read_one, MAXIMUM_THREADS, | |
1169 | &test_pem_read_one, 1, default_provider); | |
1170 | } | |
1171 | ||
ae95a40e MC |
1172 | typedef enum OPTION_choice { |
1173 | OPT_ERR = -1, | |
1174 | OPT_EOF = 0, | |
9a633a1c | 1175 | OPT_FIPS, OPT_CONFIG_FILE, |
ae95a40e MC |
1176 | OPT_TEST_ENUM |
1177 | } OPTION_CHOICE; | |
1178 | ||
1179 | const OPTIONS *test_get_options(void) | |
1180 | { | |
1181 | static const OPTIONS options[] = { | |
1182 | OPT_TEST_OPTIONS_DEFAULT_USAGE, | |
1183 | { "fips", OPT_FIPS, '-', "Test the FIPS provider" }, | |
9a633a1c P |
1184 | { "config", OPT_CONFIG_FILE, '<', |
1185 | "The configuration file to use for the libctx" }, | |
ae95a40e MC |
1186 | { NULL } |
1187 | }; | |
1188 | return options; | |
1189 | } | |
1190 | ||
ad887416 | 1191 | int setup_tests(void) |
71a04cfc | 1192 | { |
ae95a40e | 1193 | OPTION_CHOICE o; |
a0134d29 | 1194 | char *datadir; |
ae95a40e MC |
1195 | |
1196 | while ((o = opt_next()) != OPT_EOF) { | |
1197 | switch (o) { | |
1198 | case OPT_FIPS: | |
1199 | do_fips = 1; | |
1200 | break; | |
9a633a1c P |
1201 | case OPT_CONFIG_FILE: |
1202 | config_file = opt_arg(); | |
1203 | break; | |
ae95a40e MC |
1204 | case OPT_TEST_CASES: |
1205 | break; | |
1206 | default: | |
1207 | return 0; | |
1208 | } | |
1209 | } | |
1210 | ||
a0134d29 MC |
1211 | if (!TEST_ptr(datadir = test_get_argument(0))) |
1212 | return 0; | |
1213 | ||
1214 | privkey = test_mk_file_path(datadir, "rsakey.pem"); | |
1215 | if (!TEST_ptr(privkey)) | |
1216 | return 0; | |
1217 | ||
b88ce46e HL |
1218 | if (!TEST_ptr(global_lock = CRYPTO_THREAD_lock_new())) |
1219 | return 0; | |
1220 | ||
3d4d5305 P |
1221 | #ifdef TSAN_REQUIRES_LOCKING |
1222 | if (!TEST_ptr(tsan_lock = CRYPTO_THREAD_lock_new())) | |
1223 | return 0; | |
1224 | #endif | |
1225 | ||
a135dea4 P |
1226 | /* Keep first to validate auto creation of default library context */ |
1227 | ADD_TEST(test_multi_default); | |
1228 | ||
ee25dd45 | 1229 | ADD_TEST(test_lock); |
d0e1a0ae NH |
1230 | #if defined(OPENSSL_THREADS) |
1231 | ADD_TEST(torture_rw_low); | |
1232 | ADD_TEST(torture_rw_high); | |
1967539e | 1233 | # ifndef OPENSSL_SYS_MACOSX |
d0e1a0ae NH |
1234 | ADD_TEST(torture_rcu_low); |
1235 | ADD_TEST(torture_rcu_high); | |
1967539e | 1236 | # endif |
d0e1a0ae | 1237 | #endif |
ee25dd45 P |
1238 | ADD_TEST(test_once); |
1239 | ADD_TEST(test_thread_local); | |
ea08f8b2 | 1240 | ADD_TEST(test_atomic); |
2f17e978 | 1241 | ADD_TEST(test_multi_load); |
0855591e P |
1242 | ADD_TEST(test_multi_general_worker_default_provider); |
1243 | ADD_TEST(test_multi_general_worker_fips_provider); | |
1244 | ADD_TEST(test_multi_fetch_worker); | |
1245 | ADD_TEST(test_multi_shared_pkey); | |
1246 | #ifndef OPENSSL_NO_DEPRECATED_3_0 | |
1247 | ADD_TEST(test_multi_downgrade_shared_pkey); | |
1248 | #endif | |
1249 | ADD_TEST(test_multi_load_unload_provider); | |
1250 | ADD_TEST(test_obj_add); | |
ef7a9b44 | 1251 | ADD_TEST(test_lib_ctx_load_config); |
b88ce46e HL |
1252 | #if !defined(OPENSSL_NO_DGRAM) && !defined(OPENSSL_NO_SOCK) |
1253 | ADD_TEST(test_bio_dgram_pair); | |
1254 | #endif | |
29f25a10 | 1255 | ADD_TEST(test_pem_read); |
ad887416 | 1256 | return 1; |
71a04cfc | 1257 | } |
a0134d29 MC |
1258 | |
1259 | void cleanup_tests(void) | |
1260 | { | |
1261 | OPENSSL_free(privkey); | |
3d4d5305 P |
1262 | #ifdef TSAN_REQUIRES_LOCKING |
1263 | CRYPTO_THREAD_lock_free(tsan_lock); | |
1264 | #endif | |
b88ce46e | 1265 | CRYPTO_THREAD_lock_free(global_lock); |
a0134d29 | 1266 | } |