diff options
author | Matt Caswell <matt@openssl.org> | 2020-12-10 15:39:58 +0000 |
---|---|---|
committer | Matt Caswell <matt@openssl.org> | 2021-01-14 17:30:46 +0000 |
commit | ae95a40e8d453aa9d4f6499568f658ffc88a7d6e (patch) | |
tree | f351502980366579dd4d53e49241f57ac3c36fe9 /test/threadstest.c | |
parent | f6b72c7d75658e843ea0864e2f202cdc091020f9 (diff) |
Add a test for performing work in multiple concurrent threads
We test both the default provider and the fips provider
Reviewed-by: Tomas Mraz <tmraz@fedoraproject.org>
(Merged from https://github.com/openssl/openssl/pull/13660)
Diffstat (limited to 'test/threadstest.c')
-rw-r--r-- | test/threadstest.c | 158 |
1 files changed, 157 insertions, 1 deletions
diff --git a/test/threadstest.c b/test/threadstest.c index d7ed59781d..81379a3a04 100644 --- a/test/threadstest.c +++ b/test/threadstest.c @@ -11,9 +11,15 @@ # include <windows.h> #endif +#include <string.h> #include <openssl/crypto.h> +#include <openssl/evp.h> +#include <openssl/aes.h> +#include <openssl/rsa.h> #include "testutil.h" +static int do_fips = 0; + #if !defined(OPENSSL_THREADS) || defined(CRYPTO_TDEBUG) typedef unsigned int thread_t; @@ -254,16 +260,166 @@ static int test_atomic(void) testresult = 1; err: - CRYPTO_THREAD_lock_free(lock); return testresult; } +static OSSL_LIB_CTX *multi_libctx = NULL; +static int multi_success; + +static void thread_multi_worker(void) +{ + EVP_MD_CTX *mdctx = EVP_MD_CTX_new(); + EVP_MD *md = EVP_MD_fetch(multi_libctx, "SHA2-256", NULL); + EVP_CIPHER_CTX *cipherctx = EVP_CIPHER_CTX_new(); + EVP_CIPHER *ciph = EVP_CIPHER_fetch(multi_libctx, "AES-128-CBC", NULL); + const char *message = "Hello World"; + size_t messlen = strlen(message); + /* Should be big enough for encryption output too */ + unsigned char out[EVP_MAX_MD_SIZE]; + const unsigned char key[AES_BLOCK_SIZE] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, + 0x0c, 0x0d, 0x0e, 0x0f + }; + const unsigned char iv[AES_BLOCK_SIZE] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, + 0x0c, 0x0d, 0x0e, 0x0f + }; + unsigned int mdoutl; + int ciphoutl; + EVP_PKEY_CTX *pctx = NULL; + EVP_PKEY *pkey = NULL; + int testresult = 0; + int i, isfips; + + isfips = OSSL_PROVIDER_available(multi_libctx, "fips"); + + if (!TEST_ptr(mdctx) + || !TEST_ptr(md) + || !TEST_ptr(cipherctx) + || !TEST_ptr(ciph)) + goto err; + + /* Do some work */ + for (i = 0; i < 5; i++) { + if (!TEST_true(EVP_DigestInit_ex(mdctx, md, NULL)) + || !TEST_true(EVP_DigestUpdate(mdctx, message, messlen)) + || !TEST_true(EVP_DigestFinal(mdctx, out, &mdoutl))) + goto err; + } + for (i = 0; i < 5; i++) { + if (!TEST_true(EVP_EncryptInit_ex(cipherctx, ciph, NULL, key, iv)) + || !TEST_true(EVP_EncryptUpdate(cipherctx, out, &ciphoutl, + (unsigned char *)message, + messlen)) + || !TEST_true(EVP_EncryptFinal(cipherctx, out, &ciphoutl))) + goto err; + } + + pctx = EVP_PKEY_CTX_new_from_name(multi_libctx, "RSA", NULL); + if (!TEST_ptr(pctx) + || !TEST_int_gt(EVP_PKEY_keygen_init(pctx), 0) + /* + * We want the test to run quickly - not securely. Therefore we + * use an insecure bit length where we can (512). In the FIPS + * module though we must use a longer length. + */ + || !TEST_int_gt(EVP_PKEY_CTX_set_rsa_keygen_bits(pctx, + isfips ? 2048 : 512), + 0) + || !TEST_int_gt(EVP_PKEY_keygen(pctx, &pkey), 0)) + goto err; + + testresult = 1; + err: + EVP_MD_CTX_free(mdctx); + EVP_MD_free(md); + EVP_CIPHER_CTX_free(cipherctx); + EVP_CIPHER_free(ciph); + EVP_PKEY_CTX_free(pctx); + EVP_PKEY_free(pkey); + if (!testresult) + multi_success = 0; +} + +/* + * Do work in multiple worker threads at the same time. + * Test 0: Use the default provider + * Test 1: Use the fips provider + */ +static int test_multi(int idx) +{ + thread_t thread1, thread2; + int testresult = 0; + OSSL_PROVIDER *prov = NULL; + + if (idx == 1 && !do_fips) + return TEST_skip("FIPS not supported"); + + multi_success = 1; + multi_libctx = OSSL_LIB_CTX_new(); + if (!TEST_ptr(multi_libctx)) + goto err; + prov = OSSL_PROVIDER_load(multi_libctx, (idx == 0) ? "default" : "fips"); + if (!TEST_ptr(prov)) + goto err; + + if (!TEST_true(run_thread(&thread1, thread_multi_worker)) + || !TEST_true(run_thread(&thread2, thread_multi_worker))) + goto err; + + thread_multi_worker(); + + if (!TEST_true(wait_for_thread(thread1)) + || !TEST_true(wait_for_thread(thread2)) + || !TEST_true(multi_success)) + goto err; + + testresult = 1; + + err: + OSSL_PROVIDER_unload(prov); + OSSL_LIB_CTX_free(multi_libctx); + return testresult; +} + +typedef enum OPTION_choice { + OPT_ERR = -1, + OPT_EOF = 0, + OPT_FIPS, + OPT_TEST_ENUM +} OPTION_CHOICE; + +const OPTIONS *test_get_options(void) +{ + static const OPTIONS options[] = { + OPT_TEST_OPTIONS_DEFAULT_USAGE, + { "fips", OPT_FIPS, '-', "Test the FIPS provider" }, + { NULL } + }; + return options; +} + int setup_tests(void) { + OPTION_CHOICE o; + + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + case OPT_FIPS: + do_fips = 1; + break; + case OPT_TEST_CASES: + break; + default: + return 0; + } + } + ADD_TEST(test_lock); ADD_TEST(test_once); ADD_TEST(test_thread_local); ADD_TEST(test_atomic); + ADD_ALL_TESTS(test_multi, 2); return 1; } |