VirtualBox

source: vbox/trunk/src/libs/openssl-3.1.7/test/threadstest.c@ 105943

最後變更 在這個檔案從105943是 104078,由 vboxsync 提交於 8 月 前

openssl-3.1.5: Applied and adjusted our OpenSSL changes to 3.1.4. bugref:10638

檔案大小: 19.9 KB
 
1/*
2 * Copyright 2016-2022 The OpenSSL Project Authors. All Rights Reserved.
3 *
4 * Licensed under the Apache License 2.0 (the "License"). You may not use
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
8 */
9
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
17
18#if defined(_WIN32)
19# include <windows.h>
20#endif
21
22#include <string.h>
23#include <openssl/crypto.h>
24#include <openssl/rsa.h>
25#include <openssl/aes.h>
26#include <openssl/err.h>
27#include "internal/tsan_assist.h"
28#include "internal/nelem.h"
29#include "testutil.h"
30#include "threadstest.h"
31
32/* Limit the maximum number of threads */
33#define MAXIMUM_THREADS 10
34
35/* Limit the maximum number of providers loaded into a library context */
36#define MAXIMUM_PROVIDERS 4
37
38static int do_fips = 0;
39static char *privkey;
40static char *config_file = NULL;
41static int multidefault_run = 0;
42
43static const char *default_provider[] = { "default", NULL };
44static const char *fips_provider[] = { "fips", NULL };
45static const char *fips_and_default_providers[] = { "default", "fips", NULL };
46
47/* Grab a globally unique integer value */
48static int get_new_uid(void)
49{
50 /*
51 * Start with a nice large number to avoid potential conflicts when
52 * we generate a new OID.
53 */
54 static TSAN_QUALIFIER int current_uid = 1 << (sizeof(int) * 8 - 2);
55
56 return tsan_counter(&current_uid);
57}
58
59static int test_lock(void)
60{
61 CRYPTO_RWLOCK *lock = CRYPTO_THREAD_lock_new();
62 int res;
63
64 res = TEST_true(CRYPTO_THREAD_read_lock(lock))
65 && TEST_true(CRYPTO_THREAD_unlock(lock))
66 && TEST_true(CRYPTO_THREAD_write_lock(lock))
67 && TEST_true(CRYPTO_THREAD_unlock(lock));
68
69 CRYPTO_THREAD_lock_free(lock);
70
71 return res;
72}
73
74static CRYPTO_ONCE once_run = CRYPTO_ONCE_STATIC_INIT;
75static unsigned once_run_count = 0;
76
77static void once_do_run(void)
78{
79 once_run_count++;
80}
81
82static void once_run_thread_cb(void)
83{
84 CRYPTO_THREAD_run_once(&once_run, once_do_run);
85}
86
87static int test_once(void)
88{
89 thread_t thread;
90
91 if (!TEST_true(run_thread(&thread, once_run_thread_cb))
92 || !TEST_true(wait_for_thread(thread))
93 || !CRYPTO_THREAD_run_once(&once_run, once_do_run)
94 || !TEST_int_eq(once_run_count, 1))
95 return 0;
96 return 1;
97}
98
99static CRYPTO_THREAD_LOCAL thread_local_key;
100static unsigned destructor_run_count = 0;
101static int thread_local_thread_cb_ok = 0;
102
103static void thread_local_destructor(void *arg)
104{
105 unsigned *count;
106
107 if (arg == NULL)
108 return;
109
110 count = arg;
111
112 (*count)++;
113}
114
115static void thread_local_thread_cb(void)
116{
117 void *ptr;
118
119 ptr = CRYPTO_THREAD_get_local(&thread_local_key);
120 if (!TEST_ptr_null(ptr)
121 || !TEST_true(CRYPTO_THREAD_set_local(&thread_local_key,
122 &destructor_run_count)))
123 return;
124
125 ptr = CRYPTO_THREAD_get_local(&thread_local_key);
126 if (!TEST_ptr_eq(ptr, &destructor_run_count))
127 return;
128
129 thread_local_thread_cb_ok = 1;
130}
131
132static int test_thread_local(void)
133{
134 thread_t thread;
135 void *ptr = NULL;
136
137 if (!TEST_true(CRYPTO_THREAD_init_local(&thread_local_key,
138 thread_local_destructor)))
139 return 0;
140
141 ptr = CRYPTO_THREAD_get_local(&thread_local_key);
142 if (!TEST_ptr_null(ptr)
143 || !TEST_true(run_thread(&thread, thread_local_thread_cb))
144 || !TEST_true(wait_for_thread(thread))
145 || !TEST_int_eq(thread_local_thread_cb_ok, 1))
146 return 0;
147
148#if defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG)
149
150 ptr = CRYPTO_THREAD_get_local(&thread_local_key);
151 if (!TEST_ptr_null(ptr))
152 return 0;
153
154# if !defined(OPENSSL_SYS_WINDOWS)
155 if (!TEST_int_eq(destructor_run_count, 1))
156 return 0;
157# endif
158#endif
159
160 if (!TEST_true(CRYPTO_THREAD_cleanup_local(&thread_local_key)))
161 return 0;
162 return 1;
163}
164
165static int test_atomic(void)
166{
167 int val = 0, ret = 0, testresult = 0;
168 uint64_t val64 = 1, ret64 = 0;
169 CRYPTO_RWLOCK *lock = CRYPTO_THREAD_lock_new();
170
171 if (!TEST_ptr(lock))
172 return 0;
173
174 if (CRYPTO_atomic_add(&val, 1, &ret, NULL)) {
175 /* This succeeds therefore we're on a platform with lockless atomics */
176 if (!TEST_int_eq(val, 1) || !TEST_int_eq(val, ret))
177 goto err;
178 } else {
179 /* This failed therefore we're on a platform without lockless atomics */
180 if (!TEST_int_eq(val, 0) || !TEST_int_eq(val, ret))
181 goto err;
182 }
183 val = 0;
184 ret = 0;
185
186 if (!TEST_true(CRYPTO_atomic_add(&val, 1, &ret, lock)))
187 goto err;
188 if (!TEST_int_eq(val, 1) || !TEST_int_eq(val, ret))
189 goto err;
190
191 if (CRYPTO_atomic_or(&val64, 2, &ret64, NULL)) {
192 /* This succeeds therefore we're on a platform with lockless atomics */
193 if (!TEST_uint_eq((unsigned int)val64, 3)
194 || !TEST_uint_eq((unsigned int)val64, (unsigned int)ret64))
195 goto err;
196 } else {
197 /* This failed therefore we're on a platform without lockless atomics */
198 if (!TEST_uint_eq((unsigned int)val64, 1)
199 || !TEST_int_eq((unsigned int)ret64, 0))
200 goto err;
201 }
202 val64 = 1;
203 ret64 = 0;
204
205 if (!TEST_true(CRYPTO_atomic_or(&val64, 2, &ret64, lock)))
206 goto err;
207
208 if (!TEST_uint_eq((unsigned int)val64, 3)
209 || !TEST_uint_eq((unsigned int)val64, (unsigned int)ret64))
210 goto err;
211
212 ret64 = 0;
213 if (CRYPTO_atomic_load(&val64, &ret64, NULL)) {
214 /* This succeeds therefore we're on a platform with lockless atomics */
215 if (!TEST_uint_eq((unsigned int)val64, 3)
216 || !TEST_uint_eq((unsigned int)val64, (unsigned int)ret64))
217 goto err;
218 } else {
219 /* This failed therefore we're on a platform without lockless atomics */
220 if (!TEST_uint_eq((unsigned int)val64, 3)
221 || !TEST_int_eq((unsigned int)ret64, 0))
222 goto err;
223 }
224
225 ret64 = 0;
226 if (!TEST_true(CRYPTO_atomic_load(&val64, &ret64, lock)))
227 goto err;
228
229 if (!TEST_uint_eq((unsigned int)val64, 3)
230 || !TEST_uint_eq((unsigned int)val64, (unsigned int)ret64))
231 goto err;
232
233 testresult = 1;
234 err:
235 CRYPTO_THREAD_lock_free(lock);
236 return testresult;
237}
238
239static OSSL_LIB_CTX *multi_libctx = NULL;
240static int multi_success;
241static OSSL_PROVIDER *multi_provider[MAXIMUM_PROVIDERS + 1];
242static size_t multi_num_threads;
243static thread_t multi_threads[MAXIMUM_THREADS];
244
245static void multi_intialise(void)
246{
247 multi_success = 1;
248 multi_libctx = NULL;
249 multi_num_threads = 0;
250 memset(multi_threads, 0, sizeof(multi_threads));
251 memset(multi_provider, 0, sizeof(multi_provider));
252}
253
254static void thead_teardown_libctx(void)
255{
256 OSSL_PROVIDER **p;
257
258 for (p = multi_provider; *p != NULL; p++)
259 OSSL_PROVIDER_unload(*p);
260 OSSL_LIB_CTX_free(multi_libctx);
261 multi_intialise();
262}
263
264static int thread_setup_libctx(int libctx, const char *providers[])
265{
266 size_t n;
267
268 if (libctx && !TEST_true(test_get_libctx(&multi_libctx, NULL, config_file,
269 NULL, NULL)))
270 return 0;
271
272 if (providers != NULL)
273 for (n = 0; providers[n] != NULL; n++)
274 if (!TEST_size_t_lt(n, MAXIMUM_PROVIDERS)
275 || !TEST_ptr(multi_provider[n] = OSSL_PROVIDER_load(multi_libctx,
276 providers[n]))) {
277 thead_teardown_libctx();
278 return 0;
279 }
280 return 1;
281}
282
283static int teardown_threads(void)
284{
285 size_t i;
286
287 for (i = 0; i < multi_num_threads; i++)
288 if (!TEST_true(wait_for_thread(multi_threads[i])))
289 return 0;
290 return 1;
291}
292
293static int start_threads(size_t n, void (*thread_func)(void))
294{
295 size_t i;
296
297 if (!TEST_size_t_le(multi_num_threads + n, MAXIMUM_THREADS))
298 return 0;
299
300 for (i = 0 ; i < n; i++)
301 if (!TEST_true(run_thread(multi_threads + multi_num_threads++, thread_func)))
302 return 0;
303 return 1;
304}
305
306/* Template multi-threaded test function */
307static int thread_run_test(void (*main_func)(void),
308 size_t num_threads, void (*thread_func)(void),
309 int libctx, const char *providers[])
310{
311 int testresult = 0;
312
313 multi_intialise();
314 if (!thread_setup_libctx(libctx, providers)
315 || !start_threads(num_threads, thread_func))
316 goto err;
317
318 if (main_func != NULL)
319 main_func();
320
321 if (!teardown_threads()
322 || !TEST_true(multi_success))
323 goto err;
324 testresult = 1;
325 err:
326 thead_teardown_libctx();
327 return testresult;
328}
329
330static void thread_general_worker(void)
331{
332 EVP_MD_CTX *mdctx = EVP_MD_CTX_new();
333 EVP_MD *md = EVP_MD_fetch(multi_libctx, "SHA2-256", NULL);
334 EVP_CIPHER_CTX *cipherctx = EVP_CIPHER_CTX_new();
335 EVP_CIPHER *ciph = EVP_CIPHER_fetch(multi_libctx, "AES-128-CBC", NULL);
336 const char *message = "Hello World";
337 size_t messlen = strlen(message);
338 /* Should be big enough for encryption output too */
339 unsigned char out[EVP_MAX_MD_SIZE];
340 const unsigned char key[AES_BLOCK_SIZE] = {
341 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
342 0x0c, 0x0d, 0x0e, 0x0f
343 };
344 const unsigned char iv[AES_BLOCK_SIZE] = {
345 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
346 0x0c, 0x0d, 0x0e, 0x0f
347 };
348 unsigned int mdoutl;
349 int ciphoutl;
350 EVP_PKEY *pkey = NULL;
351 int testresult = 0;
352 int i, isfips;
353
354 isfips = OSSL_PROVIDER_available(multi_libctx, "fips");
355
356 if (!TEST_ptr(mdctx)
357 || !TEST_ptr(md)
358 || !TEST_ptr(cipherctx)
359 || !TEST_ptr(ciph))
360 goto err;
361
362 /* Do some work */
363 for (i = 0; i < 5; i++) {
364 if (!TEST_true(EVP_DigestInit_ex(mdctx, md, NULL))
365 || !TEST_true(EVP_DigestUpdate(mdctx, message, messlen))
366 || !TEST_true(EVP_DigestFinal(mdctx, out, &mdoutl)))
367 goto err;
368 }
369 for (i = 0; i < 5; i++) {
370 if (!TEST_true(EVP_EncryptInit_ex(cipherctx, ciph, NULL, key, iv))
371 || !TEST_true(EVP_EncryptUpdate(cipherctx, out, &ciphoutl,
372 (unsigned char *)message,
373 messlen))
374 || !TEST_true(EVP_EncryptFinal(cipherctx, out, &ciphoutl)))
375 goto err;
376 }
377
378 /*
379 * We want the test to run quickly - not securely.
380 * Therefore we use an insecure bit length where we can (512).
381 * In the FIPS module though we must use a longer length.
382 */
383 pkey = EVP_PKEY_Q_keygen(multi_libctx, NULL, "RSA", isfips ? 2048 : 512);
384 if (!TEST_ptr(pkey))
385 goto err;
386
387 testresult = 1;
388 err:
389 EVP_MD_CTX_free(mdctx);
390 EVP_MD_free(md);
391 EVP_CIPHER_CTX_free(cipherctx);
392 EVP_CIPHER_free(ciph);
393 EVP_PKEY_free(pkey);
394 if (!testresult)
395 multi_success = 0;
396}
397
398static void thread_multi_simple_fetch(void)
399{
400 EVP_MD *md = EVP_MD_fetch(multi_libctx, "SHA2-256", NULL);
401
402 if (md != NULL)
403 EVP_MD_free(md);
404 else
405 multi_success = 0;
406}
407
408static EVP_PKEY *shared_evp_pkey = NULL;
409
410static void thread_shared_evp_pkey(void)
411{
412 char *msg = "Hello World";
413 unsigned char ctbuf[256];
414 unsigned char ptbuf[256];
415 size_t ptlen, ctlen = sizeof(ctbuf);
416 EVP_PKEY_CTX *ctx = NULL;
417 int success = 0;
418 int i;
419
420 for (i = 0; i < 1 + do_fips; i++) {
421 if (i > 0)
422 EVP_PKEY_CTX_free(ctx);
423 ctx = EVP_PKEY_CTX_new_from_pkey(multi_libctx, shared_evp_pkey,
424 i == 0 ? "provider=default"
425 : "provider=fips");
426 if (!TEST_ptr(ctx))
427 goto err;
428
429 if (!TEST_int_ge(EVP_PKEY_encrypt_init(ctx), 0)
430 || !TEST_int_ge(EVP_PKEY_encrypt(ctx, ctbuf, &ctlen,
431 (unsigned char *)msg, strlen(msg)),
432 0))
433 goto err;
434
435 EVP_PKEY_CTX_free(ctx);
436 ctx = EVP_PKEY_CTX_new_from_pkey(multi_libctx, shared_evp_pkey, NULL);
437
438 if (!TEST_ptr(ctx))
439 goto err;
440
441 ptlen = sizeof(ptbuf);
442 if (!TEST_int_ge(EVP_PKEY_decrypt_init(ctx), 0)
443 || !TEST_int_gt(EVP_PKEY_decrypt(ctx, ptbuf, &ptlen, ctbuf, ctlen),
444 0)
445 || !TEST_mem_eq(msg, strlen(msg), ptbuf, ptlen))
446 goto err;
447 }
448
449 success = 1;
450
451 err:
452 EVP_PKEY_CTX_free(ctx);
453 if (!success)
454 multi_success = 0;
455}
456
457static void thread_provider_load_unload(void)
458{
459 OSSL_PROVIDER *deflt = OSSL_PROVIDER_load(multi_libctx, "default");
460
461 if (!TEST_ptr(deflt)
462 || !TEST_true(OSSL_PROVIDER_available(multi_libctx, "default")))
463 multi_success = 0;
464
465 OSSL_PROVIDER_unload(deflt);
466}
467
468static int test_multi_general_worker_default_provider(void)
469{
470 return thread_run_test(&thread_general_worker, 2, &thread_general_worker,
471 1, default_provider);
472}
473
474static int test_multi_general_worker_fips_provider(void)
475{
476 if (!do_fips)
477 return TEST_skip("FIPS not supported");
478 return thread_run_test(&thread_general_worker, 2, &thread_general_worker,
479 1, fips_provider);
480}
481
482static int test_multi_fetch_worker(void)
483{
484 return thread_run_test(&thread_multi_simple_fetch,
485 2, &thread_multi_simple_fetch, 1, default_provider);
486}
487
488static int test_multi_shared_pkey_common(void (*worker)(void))
489{
490 int testresult = 0;
491
492 multi_intialise();
493 if (!thread_setup_libctx(1, do_fips ? fips_and_default_providers
494 : default_provider)
495 || !TEST_ptr(shared_evp_pkey = load_pkey_pem(privkey, multi_libctx))
496 || !start_threads(1, &thread_shared_evp_pkey)
497 || !start_threads(1, worker))
498 goto err;
499
500 thread_shared_evp_pkey();
501
502 if (!teardown_threads()
503 || !TEST_true(multi_success))
504 goto err;
505 testresult = 1;
506 err:
507 EVP_PKEY_free(shared_evp_pkey);
508 thead_teardown_libctx();
509 return testresult;
510}
511
512#ifndef OPENSSL_NO_DEPRECATED_3_0
513static void thread_downgrade_shared_evp_pkey(void)
514{
515 /*
516 * This test is only relevant for deprecated functions that perform
517 * downgrading
518 */
519 if (EVP_PKEY_get0_RSA(shared_evp_pkey) == NULL)
520 multi_success = 0;
521}
522
523static int test_multi_downgrade_shared_pkey(void)
524{
525 return test_multi_shared_pkey_common(&thread_downgrade_shared_evp_pkey);
526}
527#endif
528
529static int test_multi_shared_pkey(void)
530{
531 return test_multi_shared_pkey_common(&thread_shared_evp_pkey);
532}
533
534static int test_multi_load_unload_provider(void)
535{
536 EVP_MD *sha256 = NULL;
537 OSSL_PROVIDER *prov = NULL;
538 int testresult = 0;
539
540 multi_intialise();
541 if (!thread_setup_libctx(1, NULL)
542 || !TEST_ptr(prov = OSSL_PROVIDER_load(multi_libctx, "default"))
543 || !TEST_ptr(sha256 = EVP_MD_fetch(multi_libctx, "SHA2-256", NULL))
544 || !TEST_true(OSSL_PROVIDER_unload(prov)))
545 goto err;
546 prov = NULL;
547
548 if (!start_threads(2, &thread_provider_load_unload))
549 goto err;
550
551 thread_provider_load_unload();
552
553 if (!teardown_threads()
554 || !TEST_true(multi_success))
555 goto err;
556 testresult = 1;
557 err:
558 OSSL_PROVIDER_unload(prov);
559 EVP_MD_free(sha256);
560 thead_teardown_libctx();
561 return testresult;
562}
563
564static char *multi_load_provider = "legacy";
565/*
566 * This test attempts to load several providers at the same time, and if
567 * run with a thread sanitizer, should crash if the core provider code
568 * doesn't synchronize well enough.
569 */
570#define MULTI_LOAD_THREADS 10
571static void test_multi_load_worker(void)
572{
573 OSSL_PROVIDER *prov;
574
575 if (!TEST_ptr(prov = OSSL_PROVIDER_load(NULL, multi_load_provider))
576 || !TEST_true(OSSL_PROVIDER_unload(prov)))
577 multi_success = 0;
578}
579
580static int test_multi_default(void)
581{
582 /* Avoid running this test twice */
583 if (multidefault_run) {
584 TEST_skip("multi default test already run");
585 return 1;
586 }
587 multidefault_run = 1;
588
589 return thread_run_test(&thread_multi_simple_fetch,
590 2, &thread_multi_simple_fetch, 0, default_provider);
591}
592
593static int test_multi_load(void)
594{
595 int res = 1;
596 OSSL_PROVIDER *prov;
597
598 /* The multidefault test must run prior to this test */
599 if (!multidefault_run) {
600 TEST_info("Running multi default test first");
601 res = test_multi_default();
602 }
603
604 /*
605 * We use the legacy provider in test_multi_load_worker because it uses a
606 * child libctx that might hit more codepaths that might be sensitive to
607 * threading issues. But in a no-legacy build that won't be loadable so
608 * we use the default provider instead.
609 */
610 prov = OSSL_PROVIDER_load(NULL, "legacy");
611 if (prov == NULL) {
612 TEST_info("Cannot load legacy provider - assuming this is a no-legacy build");
613 multi_load_provider = "default";
614 }
615 OSSL_PROVIDER_unload(prov);
616
617 return thread_run_test(NULL, MULTI_LOAD_THREADS, &test_multi_load_worker,
618 0, NULL) && res;
619}
620
621static void test_obj_create_one(void)
622{
623 char tids[12], oid[40], sn[30], ln[30];
624 int id = get_new_uid();
625
626 BIO_snprintf(tids, sizeof(tids), "%d", id);
627 BIO_snprintf(oid, sizeof(oid), "1.3.6.1.4.1.16604.%s", tids);
628 BIO_snprintf(sn, sizeof(sn), "short-name-%s", tids);
629 BIO_snprintf(ln, sizeof(ln), "long-name-%s", tids);
630 if (!TEST_true(id = OBJ_create(oid, sn, ln))
631 || !TEST_true(OBJ_add_sigid(id, NID_sha3_256, NID_rsa)))
632 multi_success = 0;
633}
634
635static int test_obj_add(void)
636{
637 return thread_run_test(&test_obj_create_one,
638 MAXIMUM_THREADS, &test_obj_create_one,
639 1, default_provider);
640}
641
642static void test_lib_ctx_load_config_worker(void)
643{
644 if (!TEST_int_eq(OSSL_LIB_CTX_load_config(multi_libctx, config_file), 1))
645 multi_success = 0;
646}
647
648static int test_lib_ctx_load_config(void)
649{
650 return thread_run_test(&test_lib_ctx_load_config_worker,
651 MAXIMUM_THREADS, &test_lib_ctx_load_config_worker,
652 1, default_provider);
653}
654
655typedef enum OPTION_choice {
656 OPT_ERR = -1,
657 OPT_EOF = 0,
658 OPT_FIPS, OPT_CONFIG_FILE,
659 OPT_TEST_ENUM
660} OPTION_CHOICE;
661
662const OPTIONS *test_get_options(void)
663{
664 static const OPTIONS options[] = {
665 OPT_TEST_OPTIONS_DEFAULT_USAGE,
666 { "fips", OPT_FIPS, '-', "Test the FIPS provider" },
667 { "config", OPT_CONFIG_FILE, '<',
668 "The configuration file to use for the libctx" },
669 { NULL }
670 };
671 return options;
672}
673
674int setup_tests(void)
675{
676 OPTION_CHOICE o;
677 char *datadir;
678
679 while ((o = opt_next()) != OPT_EOF) {
680 switch (o) {
681 case OPT_FIPS:
682 do_fips = 1;
683 break;
684 case OPT_CONFIG_FILE:
685 config_file = opt_arg();
686 break;
687 case OPT_TEST_CASES:
688 break;
689 default:
690 return 0;
691 }
692 }
693
694 if (!TEST_ptr(datadir = test_get_argument(0)))
695 return 0;
696
697 privkey = test_mk_file_path(datadir, "rsakey.pem");
698 if (!TEST_ptr(privkey))
699 return 0;
700
701 /* Keep first to validate auto creation of default library context */
702 ADD_TEST(test_multi_default);
703
704 ADD_TEST(test_lock);
705 ADD_TEST(test_once);
706 ADD_TEST(test_thread_local);
707 ADD_TEST(test_atomic);
708 ADD_TEST(test_multi_load);
709 ADD_TEST(test_multi_general_worker_default_provider);
710 ADD_TEST(test_multi_general_worker_fips_provider);
711 ADD_TEST(test_multi_fetch_worker);
712 ADD_TEST(test_multi_shared_pkey);
713#ifndef OPENSSL_NO_DEPRECATED_3_0
714 ADD_TEST(test_multi_downgrade_shared_pkey);
715#endif
716 ADD_TEST(test_multi_load_unload_provider);
717 ADD_TEST(test_obj_add);
718 ADD_TEST(test_lib_ctx_load_config);
719 return 1;
720}
721
722void cleanup_tests(void)
723{
724 OPENSSL_free(privkey);
725}
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette