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)
bio_callback_test bio_memleak_test bio_core_test param_build_test \
bioprinttest sslapitest dtlstest sslcorrupttest \
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 \
x509_time_test x509_dup_cert_test x509_check_cert_pkey_test \
recordlentest drbgtest rand_status_test sslbuffertest \
INCLUDE[threadstest]=../include ../apps/include
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
INCLUDE[afalgtest]=../include ../apps/include
DEPEND[afalgtest]=../libcrypto libtestutil.a
my $config_path = abs_path(srctop_file("test", $no_fips ? "default.cnf"
: "default-and-fips.cnf"));
-plan tests => 1;
+plan tests => 2;
if ($no_fips) {
ok(run(test(["threadstest", "-config", $config_path, data_dir()])),
ok(run(test(["threadstest", "-fips", "-config", $config_path, data_dir()])),
"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");
#include <openssl/aes.h>
#include <openssl/rsa.h>
#include "testutil.h"
+#include "threadstest.h"
static int do_fips = 0;
static char *privkey;
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)
{
CRYPTO_RWLOCK *lock = CRYPTO_THREAD_lock_new();
--- /dev/null
+/*
+ * 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
+
--- /dev/null
+/*
+ * 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;
+}