test: add test case to reliably reproduce RAND leak during POST
The FIPS provider leaks a RAND if the POST is run at initialisation time. This test case reliably reproduces this event. Reviewed-by: Matt Caswell <matt@openssl.org> (Merged from https://github.com/openssl/openssl/pull/15278)
This commit is contained in:
parent
b6f0f050fd
commit
235776b2c7
@ -47,7 +47,7 @@ IF[{- !$disabled{tests} -}]
|
|||||||
bio_callback_test bio_memleak_test bio_core_test param_build_test \
|
bio_callback_test bio_memleak_test bio_core_test param_build_test \
|
||||||
bioprinttest sslapitest dtlstest sslcorrupttest \
|
bioprinttest sslapitest dtlstest sslcorrupttest \
|
||||||
bio_enc_test pkey_meth_test pkey_meth_kdf_test evp_kdf_test uitest \
|
bio_enc_test pkey_meth_test pkey_meth_kdf_test evp_kdf_test uitest \
|
||||||
cipherbytes_test \
|
cipherbytes_test threadstest_fips \
|
||||||
asn1_encode_test asn1_decode_test asn1_string_table_test \
|
asn1_encode_test asn1_decode_test asn1_string_table_test \
|
||||||
x509_time_test x509_dup_cert_test x509_check_cert_pkey_test \
|
x509_time_test x509_dup_cert_test x509_check_cert_pkey_test \
|
||||||
recordlentest drbgtest rand_status_test sslbuffertest \
|
recordlentest drbgtest rand_status_test sslbuffertest \
|
||||||
@ -271,6 +271,10 @@ IF[{- !$disabled{tests} -}]
|
|||||||
INCLUDE[threadstest]=../include ../apps/include
|
INCLUDE[threadstest]=../include ../apps/include
|
||||||
DEPEND[threadstest]=../libcrypto libtestutil.a
|
DEPEND[threadstest]=../libcrypto libtestutil.a
|
||||||
|
|
||||||
|
SOURCE[threadstest_fips]=threadstest_fips.c
|
||||||
|
INCLUDE[threadstest_fips]=../include ../apps/include
|
||||||
|
DEPEND[threadstest_fips]=../libcrypto libtestutil.a
|
||||||
|
|
||||||
SOURCE[afalgtest]=afalgtest.c
|
SOURCE[afalgtest]=afalgtest.c
|
||||||
INCLUDE[afalgtest]=../include ../apps/include
|
INCLUDE[afalgtest]=../include ../apps/include
|
||||||
DEPEND[afalgtest]=../libcrypto libtestutil.a
|
DEPEND[afalgtest]=../libcrypto libtestutil.a
|
||||||
|
@ -23,7 +23,7 @@ my $no_fips = disabled('fips') || ($ENV{NO_FIPS} // 0);
|
|||||||
my $config_path = abs_path(srctop_file("test", $no_fips ? "default.cnf"
|
my $config_path = abs_path(srctop_file("test", $no_fips ? "default.cnf"
|
||||||
: "default-and-fips.cnf"));
|
: "default-and-fips.cnf"));
|
||||||
|
|
||||||
plan tests => 1;
|
plan tests => 2;
|
||||||
|
|
||||||
if ($no_fips) {
|
if ($no_fips) {
|
||||||
ok(run(test(["threadstest", "-config", $config_path, data_dir()])),
|
ok(run(test(["threadstest", "-config", $config_path, data_dir()])),
|
||||||
@ -32,3 +32,25 @@ if ($no_fips) {
|
|||||||
ok(run(test(["threadstest", "-fips", "-config", $config_path, data_dir()])),
|
ok(run(test(["threadstest", "-fips", "-config", $config_path, data_dir()])),
|
||||||
"running test_threads with FIPS");
|
"running test_threads with FIPS");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Merge the configuration files into one filtering the contents so the failure
|
||||||
|
# condition is reproducable. A working FIPS configuration without the install
|
||||||
|
# status is required.
|
||||||
|
|
||||||
|
open CFGBASE, '<', $config_path;
|
||||||
|
open CFGINC, '<', bldtop_file('/providers/fipsmodule.cnf');
|
||||||
|
open CFGOUT, '>', 'thread.cnf';
|
||||||
|
|
||||||
|
while (<CFGBASE>) {
|
||||||
|
print CFGOUT unless m/^[.]include/;
|
||||||
|
}
|
||||||
|
close CFGBASE;
|
||||||
|
print CFGOUT "\n\n";
|
||||||
|
while (<CFGINC>) {
|
||||||
|
print CFGOUT unless m/^install-status/;
|
||||||
|
}
|
||||||
|
close CFGINC;
|
||||||
|
close CFGOUT;
|
||||||
|
|
||||||
|
$ENV{OPENSSL_CONF} = 'thread.cnf';
|
||||||
|
ok(run(test(["threadstest_fips"])), "running test_threads_fips");
|
||||||
|
@ -20,77 +20,12 @@
|
|||||||
#include <openssl/aes.h>
|
#include <openssl/aes.h>
|
||||||
#include <openssl/rsa.h>
|
#include <openssl/rsa.h>
|
||||||
#include "testutil.h"
|
#include "testutil.h"
|
||||||
|
#include "threadstest.h"
|
||||||
|
|
||||||
static int do_fips = 0;
|
static int do_fips = 0;
|
||||||
static char *privkey;
|
static char *privkey;
|
||||||
static char *config_file = NULL;
|
static char *config_file = NULL;
|
||||||
|
|
||||||
#if !defined(OPENSSL_THREADS) || defined(CRYPTO_TDEBUG)
|
|
||||||
|
|
||||||
typedef unsigned int thread_t;
|
|
||||||
|
|
||||||
static int run_thread(thread_t *t, void (*f)(void))
|
|
||||||
{
|
|
||||||
f();
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int wait_for_thread(thread_t thread)
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
#elif defined(OPENSSL_SYS_WINDOWS)
|
|
||||||
|
|
||||||
typedef HANDLE thread_t;
|
|
||||||
|
|
||||||
static DWORD WINAPI thread_run(LPVOID arg)
|
|
||||||
{
|
|
||||||
void (*f)(void);
|
|
||||||
|
|
||||||
*(void **) (&f) = arg;
|
|
||||||
|
|
||||||
f();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int run_thread(thread_t *t, void (*f)(void))
|
|
||||||
{
|
|
||||||
*t = CreateThread(NULL, 0, thread_run, *(void **) &f, 0, NULL);
|
|
||||||
return *t != NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int wait_for_thread(thread_t thread)
|
|
||||||
{
|
|
||||||
return WaitForSingleObject(thread, INFINITE) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
typedef pthread_t thread_t;
|
|
||||||
|
|
||||||
static void *thread_run(void *arg)
|
|
||||||
{
|
|
||||||
void (*f)(void);
|
|
||||||
|
|
||||||
*(void **) (&f) = arg;
|
|
||||||
|
|
||||||
f();
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int run_thread(thread_t *t, void (*f)(void))
|
|
||||||
{
|
|
||||||
return pthread_create(t, NULL, thread_run, *(void **) &f) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int wait_for_thread(thread_t thread)
|
|
||||||
{
|
|
||||||
return pthread_join(thread, NULL) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static int test_lock(void)
|
static int test_lock(void)
|
||||||
{
|
{
|
||||||
CRYPTO_RWLOCK *lock = CRYPTO_THREAD_lock_new();
|
CRYPTO_RWLOCK *lock = CRYPTO_THREAD_lock_new();
|
||||||
|
82
test/threadstest.h
Normal file
82
test/threadstest.h
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2021 The OpenSSL Project Authors. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License 2.0 (the "License"). You may not use
|
||||||
|
* this file except in compliance with the License. You can obtain a copy
|
||||||
|
* in the file LICENSE in the source distribution or at
|
||||||
|
* https://www.openssl.org/source/license.html
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if defined(_WIN32)
|
||||||
|
# include <windows.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include "testutil.h"
|
||||||
|
|
||||||
|
#if !defined(OPENSSL_THREADS) || defined(CRYPTO_TDEBUG)
|
||||||
|
|
||||||
|
typedef unsigned int thread_t;
|
||||||
|
|
||||||
|
static int run_thread(thread_t *t, void (*f)(void))
|
||||||
|
{
|
||||||
|
f();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int wait_for_thread(thread_t thread)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif defined(OPENSSL_SYS_WINDOWS)
|
||||||
|
|
||||||
|
typedef HANDLE thread_t;
|
||||||
|
|
||||||
|
static DWORD WINAPI thread_run(LPVOID arg)
|
||||||
|
{
|
||||||
|
void (*f)(void);
|
||||||
|
|
||||||
|
*(void **) (&f) = arg;
|
||||||
|
|
||||||
|
f();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int run_thread(thread_t *t, void (*f)(void))
|
||||||
|
{
|
||||||
|
*t = CreateThread(NULL, 0, thread_run, *(void **) &f, 0, NULL);
|
||||||
|
return *t != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int wait_for_thread(thread_t thread)
|
||||||
|
{
|
||||||
|
return WaitForSingleObject(thread, INFINITE) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
typedef pthread_t thread_t;
|
||||||
|
|
||||||
|
static void *thread_run(void *arg)
|
||||||
|
{
|
||||||
|
void (*f)(void);
|
||||||
|
|
||||||
|
*(void **) (&f) = arg;
|
||||||
|
|
||||||
|
f();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int run_thread(thread_t *t, void (*f)(void))
|
||||||
|
{
|
||||||
|
return pthread_create(t, NULL, thread_run, *(void **) &f) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int wait_for_thread(thread_t thread)
|
||||||
|
{
|
||||||
|
return pthread_join(thread, NULL) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
49
test/threadstest_fips.c
Normal file
49
test/threadstest_fips.c
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2021 The OpenSSL Project Authors. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License 2.0 (the "License"). You may not use
|
||||||
|
* this file except in compliance with the License. You can obtain a copy
|
||||||
|
* in the file LICENSE in the source distribution or at
|
||||||
|
* https://www.openssl.org/source/license.html
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if defined(_WIN32)
|
||||||
|
# include <windows.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "testutil.h"
|
||||||
|
#include "threadstest.h"
|
||||||
|
|
||||||
|
static int success;
|
||||||
|
|
||||||
|
static void thread_fips_rand_fetch(void)
|
||||||
|
{
|
||||||
|
EVP_MD *md;
|
||||||
|
|
||||||
|
if (!TEST_true(md = EVP_MD_fetch(NULL, "SHA2-256", NULL)))
|
||||||
|
success = 0;
|
||||||
|
EVP_MD_free(md);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int test_fips_rand_leak(void)
|
||||||
|
{
|
||||||
|
thread_t thread;
|
||||||
|
|
||||||
|
success = 1;
|
||||||
|
|
||||||
|
if (!TEST_true(run_thread(&thread, thread_fips_rand_fetch)))
|
||||||
|
return 0;
|
||||||
|
if (!TEST_true(wait_for_thread(thread)))
|
||||||
|
return 0;
|
||||||
|
return TEST_true(success);
|
||||||
|
}
|
||||||
|
|
||||||
|
int setup_tests(void)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* This test MUST be run first. Once the default library context is set
|
||||||
|
* up, this test will always pass.
|
||||||
|
*/
|
||||||
|
ADD_TEST(test_fips_rand_leak);
|
||||||
|
return 1;
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user