2
0

threadstest.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581
  1. /*
  2. * Copyright 2016-2021 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. /* test_multi below tests the thread safety of a deprecated function */
  10. #define OPENSSL_SUPPRESS_DEPRECATED
  11. #if defined(_WIN32)
  12. # include <windows.h>
  13. #endif
  14. #include <string.h>
  15. #include <openssl/crypto.h>
  16. #include <openssl/rsa.h>
  17. #include <openssl/aes.h>
  18. #include <openssl/rsa.h>
  19. #include "testutil.h"
  20. #include "threadstest.h"
  21. static int do_fips = 0;
  22. static char *privkey;
  23. static char *config_file = NULL;
  24. static int test_lock(void)
  25. {
  26. CRYPTO_RWLOCK *lock = CRYPTO_THREAD_lock_new();
  27. int res;
  28. res = TEST_true(CRYPTO_THREAD_read_lock(lock))
  29. && TEST_true(CRYPTO_THREAD_unlock(lock));
  30. CRYPTO_THREAD_lock_free(lock);
  31. return res;
  32. }
  33. static CRYPTO_ONCE once_run = CRYPTO_ONCE_STATIC_INIT;
  34. static unsigned once_run_count = 0;
  35. static void once_do_run(void)
  36. {
  37. once_run_count++;
  38. }
  39. static void once_run_thread_cb(void)
  40. {
  41. CRYPTO_THREAD_run_once(&once_run, once_do_run);
  42. }
  43. static int test_once(void)
  44. {
  45. thread_t thread;
  46. if (!TEST_true(run_thread(&thread, once_run_thread_cb))
  47. || !TEST_true(wait_for_thread(thread))
  48. || !CRYPTO_THREAD_run_once(&once_run, once_do_run)
  49. || !TEST_int_eq(once_run_count, 1))
  50. return 0;
  51. return 1;
  52. }
  53. static CRYPTO_THREAD_LOCAL thread_local_key;
  54. static unsigned destructor_run_count = 0;
  55. static int thread_local_thread_cb_ok = 0;
  56. static void thread_local_destructor(void *arg)
  57. {
  58. unsigned *count;
  59. if (arg == NULL)
  60. return;
  61. count = arg;
  62. (*count)++;
  63. }
  64. static void thread_local_thread_cb(void)
  65. {
  66. void *ptr;
  67. ptr = CRYPTO_THREAD_get_local(&thread_local_key);
  68. if (!TEST_ptr_null(ptr)
  69. || !TEST_true(CRYPTO_THREAD_set_local(&thread_local_key,
  70. &destructor_run_count)))
  71. return;
  72. ptr = CRYPTO_THREAD_get_local(&thread_local_key);
  73. if (!TEST_ptr_eq(ptr, &destructor_run_count))
  74. return;
  75. thread_local_thread_cb_ok = 1;
  76. }
  77. static int test_thread_local(void)
  78. {
  79. thread_t thread;
  80. void *ptr = NULL;
  81. if (!TEST_true(CRYPTO_THREAD_init_local(&thread_local_key,
  82. thread_local_destructor)))
  83. return 0;
  84. ptr = CRYPTO_THREAD_get_local(&thread_local_key);
  85. if (!TEST_ptr_null(ptr)
  86. || !TEST_true(run_thread(&thread, thread_local_thread_cb))
  87. || !TEST_true(wait_for_thread(thread))
  88. || !TEST_int_eq(thread_local_thread_cb_ok, 1))
  89. return 0;
  90. #if defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG)
  91. ptr = CRYPTO_THREAD_get_local(&thread_local_key);
  92. if (!TEST_ptr_null(ptr))
  93. return 0;
  94. # if !defined(OPENSSL_SYS_WINDOWS)
  95. if (!TEST_int_eq(destructor_run_count, 1))
  96. return 0;
  97. # endif
  98. #endif
  99. if (!TEST_true(CRYPTO_THREAD_cleanup_local(&thread_local_key)))
  100. return 0;
  101. return 1;
  102. }
  103. static int test_atomic(void)
  104. {
  105. int val = 0, ret = 0, testresult = 0;
  106. uint64_t val64 = 1, ret64 = 0;
  107. CRYPTO_RWLOCK *lock = CRYPTO_THREAD_lock_new();
  108. if (!TEST_ptr(lock))
  109. return 0;
  110. if (CRYPTO_atomic_add(&val, 1, &ret, NULL)) {
  111. /* This succeeds therefore we're on a platform with lockless atomics */
  112. if (!TEST_int_eq(val, 1) || !TEST_int_eq(val, ret))
  113. goto err;
  114. } else {
  115. /* This failed therefore we're on a platform without lockless atomics */
  116. if (!TEST_int_eq(val, 0) || !TEST_int_eq(val, ret))
  117. goto err;
  118. }
  119. val = 0;
  120. ret = 0;
  121. if (!TEST_true(CRYPTO_atomic_add(&val, 1, &ret, lock)))
  122. goto err;
  123. if (!TEST_int_eq(val, 1) || !TEST_int_eq(val, ret))
  124. goto err;
  125. if (CRYPTO_atomic_or(&val64, 2, &ret64, NULL)) {
  126. /* This succeeds therefore we're on a platform with lockless atomics */
  127. if (!TEST_uint_eq((unsigned int)val64, 3)
  128. || !TEST_uint_eq((unsigned int)val64, (unsigned int)ret64))
  129. goto err;
  130. } else {
  131. /* This failed therefore we're on a platform without lockless atomics */
  132. if (!TEST_uint_eq((unsigned int)val64, 1)
  133. || !TEST_int_eq((unsigned int)ret64, 0))
  134. goto err;
  135. }
  136. val64 = 1;
  137. ret64 = 0;
  138. if (!TEST_true(CRYPTO_atomic_or(&val64, 2, &ret64, lock)))
  139. goto err;
  140. if (!TEST_uint_eq((unsigned int)val64, 3)
  141. || !TEST_uint_eq((unsigned int)val64, (unsigned int)ret64))
  142. goto err;
  143. ret64 = 0;
  144. if (CRYPTO_atomic_load(&val64, &ret64, NULL)) {
  145. /* This succeeds therefore we're on a platform with lockless atomics */
  146. if (!TEST_uint_eq((unsigned int)val64, 3)
  147. || !TEST_uint_eq((unsigned int)val64, (unsigned int)ret64))
  148. goto err;
  149. } else {
  150. /* This failed therefore we're on a platform without lockless atomics */
  151. if (!TEST_uint_eq((unsigned int)val64, 3)
  152. || !TEST_int_eq((unsigned int)ret64, 0))
  153. goto err;
  154. }
  155. ret64 = 0;
  156. if (!TEST_true(CRYPTO_atomic_load(&val64, &ret64, lock)))
  157. goto err;
  158. if (!TEST_uint_eq((unsigned int)val64, 3)
  159. || !TEST_uint_eq((unsigned int)val64, (unsigned int)ret64))
  160. goto err;
  161. testresult = 1;
  162. err:
  163. CRYPTO_THREAD_lock_free(lock);
  164. return testresult;
  165. }
  166. static OSSL_LIB_CTX *multi_libctx = NULL;
  167. static int multi_success;
  168. static void thread_general_worker(void)
  169. {
  170. EVP_MD_CTX *mdctx = EVP_MD_CTX_new();
  171. EVP_MD *md = EVP_MD_fetch(multi_libctx, "SHA2-256", NULL);
  172. EVP_CIPHER_CTX *cipherctx = EVP_CIPHER_CTX_new();
  173. EVP_CIPHER *ciph = EVP_CIPHER_fetch(multi_libctx, "AES-128-CBC", NULL);
  174. const char *message = "Hello World";
  175. size_t messlen = strlen(message);
  176. /* Should be big enough for encryption output too */
  177. unsigned char out[EVP_MAX_MD_SIZE];
  178. const unsigned char key[AES_BLOCK_SIZE] = {
  179. 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
  180. 0x0c, 0x0d, 0x0e, 0x0f
  181. };
  182. const unsigned char iv[AES_BLOCK_SIZE] = {
  183. 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
  184. 0x0c, 0x0d, 0x0e, 0x0f
  185. };
  186. unsigned int mdoutl;
  187. int ciphoutl;
  188. EVP_PKEY *pkey = NULL;
  189. int testresult = 0;
  190. int i, isfips;
  191. isfips = OSSL_PROVIDER_available(multi_libctx, "fips");
  192. if (!TEST_ptr(mdctx)
  193. || !TEST_ptr(md)
  194. || !TEST_ptr(cipherctx)
  195. || !TEST_ptr(ciph))
  196. goto err;
  197. /* Do some work */
  198. for (i = 0; i < 5; i++) {
  199. if (!TEST_true(EVP_DigestInit_ex(mdctx, md, NULL))
  200. || !TEST_true(EVP_DigestUpdate(mdctx, message, messlen))
  201. || !TEST_true(EVP_DigestFinal(mdctx, out, &mdoutl)))
  202. goto err;
  203. }
  204. for (i = 0; i < 5; i++) {
  205. if (!TEST_true(EVP_EncryptInit_ex(cipherctx, ciph, NULL, key, iv))
  206. || !TEST_true(EVP_EncryptUpdate(cipherctx, out, &ciphoutl,
  207. (unsigned char *)message,
  208. messlen))
  209. || !TEST_true(EVP_EncryptFinal(cipherctx, out, &ciphoutl)))
  210. goto err;
  211. }
  212. /*
  213. * We want the test to run quickly - not securely.
  214. * Therefore we use an insecure bit length where we can (512).
  215. * In the FIPS module though we must use a longer length.
  216. */
  217. pkey = EVP_PKEY_Q_keygen(multi_libctx, NULL, "RSA", isfips ? 2048 : 512);
  218. if (!TEST_ptr(pkey))
  219. goto err;
  220. testresult = 1;
  221. err:
  222. EVP_MD_CTX_free(mdctx);
  223. EVP_MD_free(md);
  224. EVP_CIPHER_CTX_free(cipherctx);
  225. EVP_CIPHER_free(ciph);
  226. EVP_PKEY_free(pkey);
  227. if (!testresult)
  228. multi_success = 0;
  229. }
  230. static void thread_multi_simple_fetch(void)
  231. {
  232. EVP_MD *md = EVP_MD_fetch(multi_libctx, "SHA2-256", NULL);
  233. if (md != NULL)
  234. EVP_MD_free(md);
  235. else
  236. multi_success = 0;
  237. }
  238. static EVP_PKEY *shared_evp_pkey = NULL;
  239. static void thread_shared_evp_pkey(void)
  240. {
  241. char *msg = "Hello World";
  242. unsigned char ctbuf[256];
  243. unsigned char ptbuf[256];
  244. size_t ptlen = sizeof(ptbuf), ctlen = sizeof(ctbuf);
  245. EVP_PKEY_CTX *ctx = NULL;
  246. int success = 0;
  247. int i;
  248. for (i = 0; i < 1 + do_fips; i++) {
  249. if (i > 0)
  250. EVP_PKEY_CTX_free(ctx);
  251. ctx = EVP_PKEY_CTX_new_from_pkey(multi_libctx, shared_evp_pkey,
  252. i == 0 ? "provider=default"
  253. : "provider=fips");
  254. if (!TEST_ptr(ctx))
  255. goto err;
  256. if (!TEST_int_ge(EVP_PKEY_encrypt_init(ctx), 0)
  257. || !TEST_int_ge(EVP_PKEY_encrypt(ctx, ctbuf, &ctlen,
  258. (unsigned char *)msg, strlen(msg)),
  259. 0))
  260. goto err;
  261. EVP_PKEY_CTX_free(ctx);
  262. ctx = EVP_PKEY_CTX_new_from_pkey(multi_libctx, shared_evp_pkey, NULL);
  263. if (!TEST_ptr(ctx))
  264. goto err;
  265. if (!TEST_int_ge(EVP_PKEY_decrypt_init(ctx), 0)
  266. || !TEST_int_ge(EVP_PKEY_decrypt(ctx, ptbuf, &ptlen, ctbuf, ctlen),
  267. 0)
  268. || !TEST_mem_eq(msg, strlen(msg), ptbuf, ptlen))
  269. goto err;
  270. }
  271. success = 1;
  272. err:
  273. EVP_PKEY_CTX_free(ctx);
  274. if (!success)
  275. multi_success = 0;
  276. }
  277. static void thread_downgrade_shared_evp_pkey(void)
  278. {
  279. #ifndef OPENSSL_NO_DEPRECATED_3_0
  280. /*
  281. * This test is only relevant for deprecated functions that perform
  282. * downgrading
  283. */
  284. if (EVP_PKEY_get0_RSA(shared_evp_pkey) == NULL)
  285. multi_success = 0;
  286. #else
  287. /* Shouldn't ever get here */
  288. multi_success = 0;
  289. #endif
  290. }
  291. static void thread_provider_load_unload(void)
  292. {
  293. OSSL_PROVIDER *deflt = OSSL_PROVIDER_load(multi_libctx, "default");
  294. if (!TEST_ptr(deflt)
  295. || !TEST_true(OSSL_PROVIDER_available(multi_libctx, "default")))
  296. multi_success = 0;
  297. OSSL_PROVIDER_unload(deflt);
  298. }
  299. /*
  300. * Do work in multiple worker threads at the same time.
  301. * Test 0: General worker, using the default provider
  302. * Test 1: General worker, using the fips provider
  303. * Test 2: Simple fetch worker
  304. * Test 3: Worker downgrading a shared EVP_PKEY
  305. * Test 4: Worker using a shared EVP_PKEY
  306. * Test 5: Worker loading and unloading a provider
  307. */
  308. static int test_multi(int idx)
  309. {
  310. thread_t thread1, thread2;
  311. int testresult = 0;
  312. OSSL_PROVIDER *prov = NULL, *prov2 = NULL;
  313. void (*worker)(void) = NULL;
  314. void (*worker2)(void) = NULL;
  315. EVP_MD *sha256 = NULL;
  316. if (idx == 1 && !do_fips)
  317. return TEST_skip("FIPS not supported");
  318. #ifdef OPENSSL_NO_DEPRECATED_3_0
  319. if (idx == 3)
  320. return TEST_skip("Skipping tests for deprected functions");
  321. #endif
  322. multi_success = 1;
  323. if (!TEST_true(test_get_libctx(&multi_libctx, NULL, config_file,
  324. NULL, NULL)))
  325. return 0;
  326. prov = OSSL_PROVIDER_load(multi_libctx, (idx == 1) ? "fips" : "default");
  327. if (!TEST_ptr(prov))
  328. goto err;
  329. switch (idx) {
  330. case 0:
  331. case 1:
  332. worker = thread_general_worker;
  333. break;
  334. case 2:
  335. worker = thread_multi_simple_fetch;
  336. break;
  337. case 3:
  338. worker2 = thread_downgrade_shared_evp_pkey;
  339. /* fall through */
  340. case 4:
  341. /*
  342. * If available we have both the default and fips providers for this
  343. * test
  344. */
  345. if (do_fips
  346. && !TEST_ptr(prov2 = OSSL_PROVIDER_load(multi_libctx, "fips")))
  347. goto err;
  348. if (!TEST_ptr(shared_evp_pkey = load_pkey_pem(privkey, multi_libctx)))
  349. goto err;
  350. worker = thread_shared_evp_pkey;
  351. break;
  352. case 5:
  353. /*
  354. * We ensure we get an md from the default provider, and then unload the
  355. * provider. This ensures the provider remains around but in a
  356. * deactivated state.
  357. */
  358. sha256 = EVP_MD_fetch(multi_libctx, "SHA2-256", NULL);
  359. OSSL_PROVIDER_unload(prov);
  360. prov = NULL;
  361. worker = thread_provider_load_unload;
  362. break;
  363. default:
  364. TEST_error("Invalid test index");
  365. goto err;
  366. }
  367. if (worker2 == NULL)
  368. worker2 = worker;
  369. if (!TEST_true(run_thread(&thread1, worker))
  370. || !TEST_true(run_thread(&thread2, worker2)))
  371. goto err;
  372. worker();
  373. if (!TEST_true(wait_for_thread(thread1))
  374. || !TEST_true(wait_for_thread(thread2))
  375. || !TEST_true(multi_success))
  376. goto err;
  377. testresult = 1;
  378. err:
  379. EVP_MD_free(sha256);
  380. OSSL_PROVIDER_unload(prov);
  381. OSSL_PROVIDER_unload(prov2);
  382. OSSL_LIB_CTX_free(multi_libctx);
  383. EVP_PKEY_free(shared_evp_pkey);
  384. shared_evp_pkey = NULL;
  385. multi_libctx = NULL;
  386. return testresult;
  387. }
  388. /*
  389. * This test attempts to load several providers at the same time, and if
  390. * run with a thread sanitizer, should crash if the core provider code
  391. * doesn't synchronize well enough.
  392. */
  393. #define MULTI_LOAD_THREADS 3
  394. static void test_multi_load_worker(void)
  395. {
  396. OSSL_PROVIDER *prov;
  397. (void)TEST_ptr(prov = OSSL_PROVIDER_load(NULL, "default"));
  398. (void)TEST_true(OSSL_PROVIDER_unload(prov));
  399. }
  400. static int test_multi_load(void)
  401. {
  402. thread_t threads[MULTI_LOAD_THREADS];
  403. int i;
  404. for (i = 0; i < MULTI_LOAD_THREADS; i++)
  405. (void)TEST_true(run_thread(&threads[i], test_multi_load_worker));
  406. for (i = 0; i < MULTI_LOAD_THREADS; i++)
  407. (void)TEST_true(wait_for_thread(threads[i]));
  408. return 1;
  409. }
  410. static int test_multi_default(void)
  411. {
  412. thread_t thread1, thread2;
  413. int testresult = 0;
  414. OSSL_PROVIDER *prov = NULL;
  415. multi_success = 1;
  416. multi_libctx = NULL;
  417. prov = OSSL_PROVIDER_load(multi_libctx, "default");
  418. if (!TEST_ptr(prov))
  419. goto err;
  420. if (!TEST_true(run_thread(&thread1, thread_multi_simple_fetch))
  421. || !TEST_true(run_thread(&thread2, thread_multi_simple_fetch)))
  422. goto err;
  423. thread_multi_simple_fetch();
  424. if (!TEST_true(wait_for_thread(thread1))
  425. || !TEST_true(wait_for_thread(thread2))
  426. || !TEST_true(multi_success))
  427. goto err;
  428. testresult = 1;
  429. err:
  430. OSSL_PROVIDER_unload(prov);
  431. return testresult;
  432. }
  433. typedef enum OPTION_choice {
  434. OPT_ERR = -1,
  435. OPT_EOF = 0,
  436. OPT_FIPS, OPT_CONFIG_FILE,
  437. OPT_TEST_ENUM
  438. } OPTION_CHOICE;
  439. const OPTIONS *test_get_options(void)
  440. {
  441. static const OPTIONS options[] = {
  442. OPT_TEST_OPTIONS_DEFAULT_USAGE,
  443. { "fips", OPT_FIPS, '-', "Test the FIPS provider" },
  444. { "config", OPT_CONFIG_FILE, '<',
  445. "The configuration file to use for the libctx" },
  446. { NULL }
  447. };
  448. return options;
  449. }
  450. int setup_tests(void)
  451. {
  452. OPTION_CHOICE o;
  453. char *datadir;
  454. while ((o = opt_next()) != OPT_EOF) {
  455. switch (o) {
  456. case OPT_FIPS:
  457. do_fips = 1;
  458. break;
  459. case OPT_CONFIG_FILE:
  460. config_file = opt_arg();
  461. break;
  462. case OPT_TEST_CASES:
  463. break;
  464. default:
  465. return 0;
  466. }
  467. }
  468. if (!TEST_ptr(datadir = test_get_argument(0)))
  469. return 0;
  470. privkey = test_mk_file_path(datadir, "rsakey.pem");
  471. if (!TEST_ptr(privkey))
  472. return 0;
  473. /* Keep first to validate auto creation of default library context */
  474. ADD_TEST(test_multi_default);
  475. ADD_TEST(test_lock);
  476. ADD_TEST(test_once);
  477. ADD_TEST(test_thread_local);
  478. ADD_TEST(test_atomic);
  479. ADD_TEST(test_multi_load);
  480. ADD_ALL_TESTS(test_multi, 6);
  481. return 1;
  482. }
  483. void cleanup_tests(void)
  484. {
  485. OPENSSL_free(privkey);
  486. }