Add a multi-thread test for shared EVP_PKEYs

EVP_PKEYs may be shared across mutliple threads. For example this is
common for users of libssl who provide a single EVP_PKEY private key for
an SSL_CTX, which is then shared between multiple threads for each SSL
object.

Reviewed-by: Paul Dale <pauli@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/13987)
This commit is contained in:
Matt Caswell 2021-01-26 13:30:06 +00:00
parent 7ff9fdd4b3
commit a0134d293e
3 changed files with 111 additions and 5 deletions

View File

@ -8,7 +8,7 @@
use OpenSSL::Test::Simple;
use OpenSSL::Test qw/:DEFAULT srctop_file srctop_dir bldtop_dir bldtop_file/;
use OpenSSL::Test qw/:DEFAULT srctop_file srctop_dir bldtop_dir bldtop_file data_dir/;
use OpenSSL::Test::Utils;
use Cwd qw(abs_path);
@ -35,8 +35,8 @@ if (!$no_fips) {
if ($no_fips) {
$ENV{OPENSSL_CONF} = abs_path(srctop_file("test", "default.cnf"));
ok(run(test(["threadstest"])), "running test_threads");
ok(run(test(["threadstest", data_dir()])), "running test_threads");
} else {
$ENV{OPENSSL_CONF} = abs_path(srctop_file("test", "default-and-fips.cnf"));
ok(run(test(["threadstest", "-fips"])), "running test_threads");
ok(run(test(["threadstest", "-fips", data_dir()])), "running test_threads");
}

View File

@ -0,0 +1,28 @@
-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDVXWBq3/xh7kiq
jBFIQ6VttlJdqphJsWGSNbH8OgQlDG15/7TVyelcHDvgq7O4faPebb3g3ddavxRH
EUJepoLQYcF/3RNG5gmFBw7y1PwaZNIKrSCrIGuW8K3MxBlTVdwBHaSz74q0SVNd
igUc8dzhRL/F1+J3GVdclwt17ohDcQ/KbMG0slCnd0ZsWA8Rv/F2JFquOUK3UWcp
4dBVMG8X5JHqrfgowkNvomSp+52YkmJIPusNT4JKiv8/cu6Wta6hwZi6732QdW3/
WlKeq/XAftCHQ9uFBwcPfTh6/dHT7mUd0+o5aoc37krT4A1u9XCswr3xbvOSlV6p
8KFllZONAgMBAAECggEADLTt7A+A2Vg2jamf0dztejY0e42QWjstI2b9PZc67fXq
gyx+WYkX07t+uWegYWliG/oPJ9guXiIpE/5sJHToL37S5kmFP2CtynVcJ4wVo4DD
nY0n9+kLX0bgIuS+2V6wpoRcbbbjXM9NHrH8kfe5ftT4UtEDlLI2qLX6IcDd7p4u
OYjILChR8GSGTw96yIy2Ws/1Uq9PMw64JoT4RcK5QqnkcPMDFRH1SeLOL+zXP2c4
nEl9yOy3HauZKxwl/Ry/XK1s3DdjopIAU29ut+hAuMiTb06kzZnumL9NoplKoZtU
otw/gVcCKhT+Ep+p6i8InLF0XEME8A0qUR0niWebgQKBgQD6vkxR49B8ZZQrzjw4
XKs1lI9cP7cgPiuWlDHMNjYou3WbOaGrMeScvbB1Ldh9A8pjAhxlw8AaV/xs4qcA
trmVmSISVMVyc1wSGlJXWi2nUzTNs9OE3vj22SyStihf8UUZtWwX2b5Y4JrYhA/V
+ThGGqHR03oLNLShNLtJc2c7YQKBgQDZ1nkibEyrepexw/fnwkw61IJKq9wRIh1G
PREakhbe9wU5ie0knuf9razt7awzQiwFmlixmWqsM7UEtLuXNnNPciwdrKhhbvrd
vD/rkbIEHEPllIhFlDtOzn3hRBWTzWmXFjpou/2LvHTSbVis4IYVZymTp2jb1ZLs
7VbiG9JTrQKBgQDc6n75g1szzpdehQT/r33U5j/syeJBUSU8NPMu9fB/sLHsgjlT
SNEf2+y1QSBE/Or6kmiMrIv7advn30W+Vj9qc5HWTsPrk4HiHTjA553jl2alebN5
lK4LZspjtIQcC8mS3goPdXPEgJdM/gWpwzr2YQ6DfOxBJT2j7n64NyoT4QKBgH7/
yx+GhCx1DHtXBPDZFhg2TL+78lEK0oZgk9gp06up2CHzh44SFq6O0oLkTcCUk5Ww
poTkLIy4mJBlzfgahp+KsK2cO46SZS9g0ONFzcMXt33hWpE2Gl2XhUwPpYTF/QlY
rDTjZK5S8Mi9dzVSsNlJi7PJphiEK2R1+nFYRwcBAoGBANWoIG85jpXAOnq/Kcgx
Rl3YivR0Ke6r1tFlP58rT7X3EkiboXyQl5vLIFCAwUte6RGrLl1dy3Qyh80B9ySL
Jx6vj42CK7vgv6A96TuVYhnXTnEI6ZvwAQ2VGaw4BizhjALs/kdSE/og9aSCs3ws
KQypwAFz0tbHxaNag/bSAN0J
-----END PRIVATE KEY-----

View File

@ -19,6 +19,7 @@
#include "testutil.h"
static int do_fips = 0;
static char *privkey;
#if !defined(OPENSSL_THREADS) || defined(CRYPTO_TDEBUG)
@ -352,17 +353,66 @@ static void thread_multi_simple_fetch(void)
multi_success = 0;
}
static EVP_PKEY *shared_evp_pkey = NULL;
static void thread_shared_evp_pkey(void)
{
char *msg = "Hello World";
unsigned char ctbuf[256];
unsigned char ptbuf[256];
size_t ptlen = sizeof(ptbuf), ctlen = sizeof(ctbuf);
EVP_PKEY_CTX *ctx = NULL;
int success = 0;
int i;
for (i = 0; i < 1 + do_fips; i++) {
if (i > 0)
EVP_PKEY_CTX_free(ctx);
ctx = EVP_PKEY_CTX_new_from_pkey(multi_libctx, shared_evp_pkey,
i == 0 ? "provider=default"
: "provider=fips");
if (!TEST_ptr(ctx))
goto err;
if (!TEST_int_ge(EVP_PKEY_encrypt_init(ctx), 0)
|| !TEST_int_ge(EVP_PKEY_encrypt(ctx, ctbuf, &ctlen,
(unsigned char *)msg, strlen(msg)),
0))
goto err;
EVP_PKEY_CTX_free(ctx);
ctx = EVP_PKEY_CTX_new_from_pkey(multi_libctx, shared_evp_pkey, NULL);
if (!TEST_ptr(ctx))
goto err;
if (!TEST_int_ge(EVP_PKEY_decrypt_init(ctx), 0)
|| !TEST_int_ge(EVP_PKEY_decrypt(ctx, ptbuf, &ptlen, ctbuf, ctlen),
0)
|| !TEST_mem_eq(msg, strlen(msg), ptbuf, ptlen))
goto err;
}
success = 1;
err:
EVP_PKEY_CTX_free(ctx);
if (!success)
multi_success = 0;
}
/*
* Do work in multiple worker threads at the same time.
* Test 0: General worker, using the default provider
* Test 1: General worker, using the fips provider
* Test 2: Simple fetch worker
* Test 3: Worker using a shared EVP_PKEY
*/
static int test_multi(int idx)
{
thread_t thread1, thread2;
int testresult = 0;
OSSL_PROVIDER *prov = NULL;
OSSL_PROVIDER *prov = NULL, *prov2 = NULL;
void (*worker)(void);
if (idx == 1 && !do_fips)
@ -384,6 +434,18 @@ static int test_multi(int idx)
case 2:
worker = thread_multi_simple_fetch;
break;
case 3:
/*
* If available we have both the default and fips providers for this
* test
*/
if (do_fips
&& !TEST_ptr(prov2 = OSSL_PROVIDER_load(multi_libctx, "fips")))
goto err;
if (!TEST_ptr(shared_evp_pkey = load_pkey_pem(privkey, multi_libctx)))
goto err;
worker = thread_shared_evp_pkey;
break;
default:
TEST_error("Invalid test index");
goto err;
@ -404,7 +466,10 @@ static int test_multi(int idx)
err:
OSSL_PROVIDER_unload(prov);
OSSL_PROVIDER_unload(prov2);
OSSL_LIB_CTX_free(multi_libctx);
EVP_PKEY_free(shared_evp_pkey);
shared_evp_pkey = NULL;
return testresult;
}
@ -428,6 +493,7 @@ const OPTIONS *test_get_options(void)
int setup_tests(void)
{
OPTION_CHOICE o;
char *datadir;
while ((o = opt_next()) != OPT_EOF) {
switch (o) {
@ -441,10 +507,22 @@ int setup_tests(void)
}
}
if (!TEST_ptr(datadir = test_get_argument(0)))
return 0;
privkey = test_mk_file_path(datadir, "rsakey.pem");
if (!TEST_ptr(privkey))
return 0;
ADD_TEST(test_lock);
ADD_TEST(test_once);
ADD_TEST(test_thread_local);
ADD_TEST(test_atomic);
ADD_ALL_TESTS(test_multi, 3);
ADD_ALL_TESTS(test_multi, 4);
return 1;
}
void cleanup_tests(void)
{
OPENSSL_free(privkey);
}