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