summaryrefslogtreecommitdiffstats
path: root/test/threadstest.c
diff options
context:
space:
mode:
authorMatt Caswell <matt@openssl.org>2020-12-10 15:39:58 +0000
committerMatt Caswell <matt@openssl.org>2021-01-14 17:30:46 +0000
commitae95a40e8d453aa9d4f6499568f658ffc88a7d6e (patch)
treef351502980366579dd4d53e49241f57ac3c36fe9 /test/threadstest.c
parentf6b72c7d75658e843ea0864e2f202cdc091020f9 (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.c158
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;
}