mirror of
https://github.com/openssl/openssl.git
synced 2024-11-27 20:14:20 +08:00
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)
This commit is contained in:
parent
f6b72c7d75
commit
ae95a40e8d
@ -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");
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user