]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
Add a test for performing work in multiple concurrent threads
authorMatt Caswell <matt@openssl.org>
Thu, 10 Dec 2020 15:39:58 +0000 (15:39 +0000)
committerMatt Caswell <matt@openssl.org>
Thu, 14 Jan 2021 17:30:46 +0000 (17:30 +0000)
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)

test/recipes/90-test_threads.t
test/threadstest.c

index e629f24d1c5cf515a932d28ecfc3155f95289fc3..fa4d2b8de975882679785eecfc7c969ee72e95e2 100644 (file)
@@ -8,5 +8,35 @@
 
 
 use OpenSSL::Test::Simple;
+use OpenSSL::Test qw/:DEFAULT srctop_file srctop_dir bldtop_dir bldtop_file/;
+use OpenSSL::Test::Utils;
+use Cwd qw(abs_path);
 
-simple_test("test_threads", "threadstest");
+BEGIN {
+setup("test_threads");
+}
+
+use lib srctop_dir('Configurations');
+use lib bldtop_dir('.');
+use platform;
+
+my $no_fips = disabled('fips') || ($ENV{NO_FIPS} // 0);
+
+
+plan tests => 1 + ($no_fips ? 0 : 1);
+
+if (!$no_fips) {
+    my $infile = bldtop_file('providers', platform->dso('fips'));
+    ok(run(app(['openssl', 'fipsinstall',
+            '-out', bldtop_file('providers', 'fipsmodule.cnf'),
+            '-module', $infile])),
+    "fipsinstall");
+}
+
+if ($no_fips) {
+    $ENV{OPENSSL_CONF} = abs_path(srctop_file("test", "default.cnf"));
+    ok(run(test(["threadstest"])), "running test_threads");
+} else {
+    $ENV{OPENSSL_CONF} = abs_path(srctop_file("test", "default-and-fips.cnf"));
+    ok(run(test(["threadstest", "-fips"])), "running test_threads");
+}
index d7ed59781d95b86d435b7e395c35c78f62d22461..81379a3a04a5f59a73cd179245f6acc3c8989ebc 100644 (file)
 # 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;
 }