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