2 * Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved.
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
15 #include <openssl/crypto.h>
16 #include <openssl/evp.h>
17 #include <openssl/aes.h>
18 #include <openssl/rsa.h>
21 static int do_fips
= 0;
23 #if !defined(OPENSSL_THREADS) || defined(CRYPTO_TDEBUG)
25 typedef unsigned int thread_t
;
27 static int run_thread(thread_t
*t
, void (*f
)(void))
33 static int wait_for_thread(thread_t thread
)
38 #elif defined(OPENSSL_SYS_WINDOWS)
40 typedef HANDLE thread_t
;
42 static DWORD WINAPI
thread_run(LPVOID arg
)
46 *(void **) (&f
) = arg
;
52 static int run_thread(thread_t
*t
, void (*f
)(void))
54 *t
= CreateThread(NULL
, 0, thread_run
, *(void **) &f
, 0, NULL
);
58 static int wait_for_thread(thread_t thread
)
60 return WaitForSingleObject(thread
, INFINITE
) == 0;
65 typedef pthread_t thread_t
;
67 static void *thread_run(void *arg
)
71 *(void **) (&f
) = arg
;
77 static int run_thread(thread_t
*t
, void (*f
)(void))
79 return pthread_create(t
, NULL
, thread_run
, *(void **) &f
) == 0;
82 static int wait_for_thread(thread_t thread
)
84 return pthread_join(thread
, NULL
) == 0;
89 static int test_lock(void)
91 CRYPTO_RWLOCK
*lock
= CRYPTO_THREAD_lock_new();
93 if (!TEST_true(CRYPTO_THREAD_read_lock(lock
))
94 || !TEST_true(CRYPTO_THREAD_unlock(lock
)))
97 CRYPTO_THREAD_lock_free(lock
);
102 static CRYPTO_ONCE once_run
= CRYPTO_ONCE_STATIC_INIT
;
103 static unsigned once_run_count
= 0;
105 static void once_do_run(void)
110 static void once_run_thread_cb(void)
112 CRYPTO_THREAD_run_once(&once_run
, once_do_run
);
115 static int test_once(void)
119 if (!TEST_true(run_thread(&thread
, once_run_thread_cb
))
120 || !TEST_true(wait_for_thread(thread
))
121 || !CRYPTO_THREAD_run_once(&once_run
, once_do_run
)
122 || !TEST_int_eq(once_run_count
, 1))
127 static CRYPTO_THREAD_LOCAL thread_local_key
;
128 static unsigned destructor_run_count
= 0;
129 static int thread_local_thread_cb_ok
= 0;
131 static void thread_local_destructor(void *arg
)
143 static void thread_local_thread_cb(void)
147 ptr
= CRYPTO_THREAD_get_local(&thread_local_key
);
148 if (!TEST_ptr_null(ptr
)
149 || !TEST_true(CRYPTO_THREAD_set_local(&thread_local_key
,
150 &destructor_run_count
)))
153 ptr
= CRYPTO_THREAD_get_local(&thread_local_key
);
154 if (!TEST_ptr_eq(ptr
, &destructor_run_count
))
157 thread_local_thread_cb_ok
= 1;
160 static int test_thread_local(void)
165 if (!TEST_true(CRYPTO_THREAD_init_local(&thread_local_key
,
166 thread_local_destructor
)))
169 ptr
= CRYPTO_THREAD_get_local(&thread_local_key
);
170 if (!TEST_ptr_null(ptr
)
171 || !TEST_true(run_thread(&thread
, thread_local_thread_cb
))
172 || !TEST_true(wait_for_thread(thread
))
173 || !TEST_int_eq(thread_local_thread_cb_ok
, 1))
176 #if defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG)
178 ptr
= CRYPTO_THREAD_get_local(&thread_local_key
);
179 if (!TEST_ptr_null(ptr
))
182 # if !defined(OPENSSL_SYS_WINDOWS)
183 if (!TEST_int_eq(destructor_run_count
, 1))
188 if (!TEST_true(CRYPTO_THREAD_cleanup_local(&thread_local_key
)))
193 static int test_atomic(void)
195 int val
= 0, ret
= 0, testresult
= 0;
196 uint64_t val64
= 1, ret64
= 0;
197 CRYPTO_RWLOCK
*lock
= CRYPTO_THREAD_lock_new();
202 if (CRYPTO_atomic_add(&val
, 1, &ret
, NULL
)) {
203 /* This succeeds therefore we're on a platform with lockless atomics */
204 if (!TEST_int_eq(val
, 1) || !TEST_int_eq(val
, ret
))
207 /* This failed therefore we're on a platform without lockless atomics */
208 if (!TEST_int_eq(val
, 0) || !TEST_int_eq(val
, ret
))
214 if (!TEST_true(CRYPTO_atomic_add(&val
, 1, &ret
, lock
)))
216 if (!TEST_int_eq(val
, 1) || !TEST_int_eq(val
, ret
))
219 if (CRYPTO_atomic_or(&val64
, 2, &ret64
, NULL
)) {
220 /* This succeeds therefore we're on a platform with lockless atomics */
221 if (!TEST_uint_eq((unsigned int)val64
, 3)
222 || !TEST_uint_eq((unsigned int)val64
, (unsigned int)ret64
))
225 /* This failed therefore we're on a platform without lockless atomics */
226 if (!TEST_uint_eq((unsigned int)val64
, 1)
227 || !TEST_int_eq((unsigned int)ret64
, 0))
233 if (!TEST_true(CRYPTO_atomic_or(&val64
, 2, &ret64
, lock
)))
236 if (!TEST_uint_eq((unsigned int)val64
, 3)
237 || !TEST_uint_eq((unsigned int)val64
, (unsigned int)ret64
))
241 if (CRYPTO_atomic_load(&val64
, &ret64
, NULL
)) {
242 /* This succeeds therefore we're on a platform with lockless atomics */
243 if (!TEST_uint_eq((unsigned int)val64
, 3)
244 || !TEST_uint_eq((unsigned int)val64
, (unsigned int)ret64
))
247 /* This failed therefore we're on a platform without lockless atomics */
248 if (!TEST_uint_eq((unsigned int)val64
, 3)
249 || !TEST_int_eq((unsigned int)ret64
, 0))
254 if (!TEST_true(CRYPTO_atomic_load(&val64
, &ret64
, lock
)))
257 if (!TEST_uint_eq((unsigned int)val64
, 3)
258 || !TEST_uint_eq((unsigned int)val64
, (unsigned int)ret64
))
263 CRYPTO_THREAD_lock_free(lock
);
267 static OSSL_LIB_CTX
*multi_libctx
= NULL
;
268 static int multi_success
;
270 static void thread_general_worker(void)
272 EVP_MD_CTX
*mdctx
= EVP_MD_CTX_new();
273 EVP_MD
*md
= EVP_MD_fetch(multi_libctx
, "SHA2-256", NULL
);
274 EVP_CIPHER_CTX
*cipherctx
= EVP_CIPHER_CTX_new();
275 EVP_CIPHER
*ciph
= EVP_CIPHER_fetch(multi_libctx
, "AES-128-CBC", NULL
);
276 const char *message
= "Hello World";
277 size_t messlen
= strlen(message
);
278 /* Should be big enough for encryption output too */
279 unsigned char out
[EVP_MAX_MD_SIZE
];
280 const unsigned char key
[AES_BLOCK_SIZE
] = {
281 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
282 0x0c, 0x0d, 0x0e, 0x0f
284 const unsigned char iv
[AES_BLOCK_SIZE
] = {
285 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
286 0x0c, 0x0d, 0x0e, 0x0f
290 EVP_PKEY_CTX
*pctx
= NULL
;
291 EVP_PKEY
*pkey
= NULL
;
295 isfips
= OSSL_PROVIDER_available(multi_libctx
, "fips");
299 || !TEST_ptr(cipherctx
)
304 for (i
= 0; i
< 5; i
++) {
305 if (!TEST_true(EVP_DigestInit_ex(mdctx
, md
, NULL
))
306 || !TEST_true(EVP_DigestUpdate(mdctx
, message
, messlen
))
307 || !TEST_true(EVP_DigestFinal(mdctx
, out
, &mdoutl
)))
310 for (i
= 0; i
< 5; i
++) {
311 if (!TEST_true(EVP_EncryptInit_ex(cipherctx
, ciph
, NULL
, key
, iv
))
312 || !TEST_true(EVP_EncryptUpdate(cipherctx
, out
, &ciphoutl
,
313 (unsigned char *)message
,
315 || !TEST_true(EVP_EncryptFinal(cipherctx
, out
, &ciphoutl
)))
319 pctx
= EVP_PKEY_CTX_new_from_name(multi_libctx
, "RSA", NULL
);
321 || !TEST_int_gt(EVP_PKEY_keygen_init(pctx
), 0)
323 * We want the test to run quickly - not securely. Therefore we
324 * use an insecure bit length where we can (512). In the FIPS
325 * module though we must use a longer length.
327 || !TEST_int_gt(EVP_PKEY_CTX_set_rsa_keygen_bits(pctx
,
328 isfips
? 2048 : 512),
330 || !TEST_int_gt(EVP_PKEY_keygen(pctx
, &pkey
), 0))
335 EVP_MD_CTX_free(mdctx
);
337 EVP_CIPHER_CTX_free(cipherctx
);
338 EVP_CIPHER_free(ciph
);
339 EVP_PKEY_CTX_free(pctx
);
345 static void thread_multi_simple_fetch(void)
347 EVP_MD
*md
= EVP_MD_fetch(NULL
, "SHA2-256", NULL
);
356 * Do work in multiple worker threads at the same time.
357 * Test 0: General worker, using the default provider
358 * Test 1: General worker, using the fips provider
359 * Test 2: Simple fetch worker
361 static int test_multi(int idx
)
363 thread_t thread1
, thread2
;
365 OSSL_PROVIDER
*prov
= NULL
;
366 void (*worker
)(void);
368 if (idx
== 1 && !do_fips
)
369 return TEST_skip("FIPS not supported");
372 multi_libctx
= OSSL_LIB_CTX_new();
373 if (!TEST_ptr(multi_libctx
))
375 prov
= OSSL_PROVIDER_load(multi_libctx
, (idx
== 1) ? "fips" : "default");
382 worker
= thread_general_worker
;
385 worker
= thread_multi_simple_fetch
;
388 TEST_error("Invalid test index");
392 if (!TEST_true(run_thread(&thread1
, worker
))
393 || !TEST_true(run_thread(&thread2
, worker
)))
398 if (!TEST_true(wait_for_thread(thread1
))
399 || !TEST_true(wait_for_thread(thread2
))
400 || !TEST_true(multi_success
))
406 OSSL_PROVIDER_unload(prov
);
407 OSSL_LIB_CTX_free(multi_libctx
);
411 typedef enum OPTION_choice
{
418 const OPTIONS
*test_get_options(void)
420 static const OPTIONS options
[] = {
421 OPT_TEST_OPTIONS_DEFAULT_USAGE
,
422 { "fips", OPT_FIPS
, '-', "Test the FIPS provider" },
428 int setup_tests(void)
432 while ((o
= opt_next()) != OPT_EOF
) {
446 ADD_TEST(test_thread_local
);
447 ADD_TEST(test_atomic
);
448 ADD_ALL_TESTS(test_multi
, 3);