[openssl] master update
Matt Caswell
matt at openssl.org
Fri Nov 29 16:19:03 UTC 2019
The branch master has been updated
via cc38e643cbfb6da84fb2bb6a188698d0bc082a20 (commit)
via 14a684bfb091b12aa3094a6097932f76f799990a (commit)
from 17197a2f61d04314b465b71a4ce164b5e219f15c (commit)
- Log -----------------------------------------------------------------
commit cc38e643cbfb6da84fb2bb6a188698d0bc082a20
Author: Matt Caswell <matt at openssl.org>
Date: Thu Sep 19 11:52:45 2019 +0100
Disable mem leak checking for the self test lock
The fips self test lock is deallocated in platform specific ways that may
occur after we do mem leak checking. If we don't know how to free it for
a particular platform then we just leak it deliberately. So we
temporarily disable the mem leak checking while we allocate the lock.
Reviewed-by: Paul Dale <paul.dale at oracle.com>
Reviewed-by: Richard Levitte <levitte at openssl.org>
(Merged from https://github.com/openssl/openssl/pull/9939)
commit 14a684bfb091b12aa3094a6097932f76f799990a
Author: Matt Caswell <matt at openssl.org>
Date: Wed Sep 18 17:27:10 2019 +0100
Make sure we only run the self tests once
Fixes #9909
Reviewed-by: Paul Dale <paul.dale at oracle.com>
Reviewed-by: Richard Levitte <levitte at openssl.org>
(Merged from https://github.com/openssl/openssl/pull/9939)
-----------------------------------------------------------------------
Summary of changes:
crypto/provider_core.c | 1 +
doc/man7/provider-base.pod | 3 +-
include/internal/thread_once.h | 2 +-
include/openssl/core_numbers.h | 10 ++--
providers/fips/build.info | 2 +-
providers/fips/fipsprov.c | 11 +++-
providers/fips/selftest.c | 113 ++++++++++++++++++++++++++++++++++++++---
providers/fips/selftest.h | 2 +-
8 files changed, 129 insertions(+), 15 deletions(-)
diff --git a/crypto/provider_core.c b/crypto/provider_core.c
index 4f3123d672..9e92e96b10 100644
--- a/crypto/provider_core.c
+++ b/crypto/provider_core.c
@@ -889,6 +889,7 @@ static const OSSL_DISPATCH core_dispatch_[] = {
{ OSSL_FUNC_CRYPTO_SECURE_ALLOCATED,
(void (*)(void))CRYPTO_secure_allocated },
{ OSSL_FUNC_OPENSSL_CLEANSE, (void (*)(void))OPENSSL_cleanse },
+ { OSSL_FUNC_CRYPTO_MEM_CTRL, (void (*)(void))CRYPTO_mem_ctrl },
{ 0, NULL }
};
diff --git a/doc/man7/provider-base.pod b/doc/man7/provider-base.pod
index 1b4b47d02a..08d807f572 100644
--- a/doc/man7/provider-base.pod
+++ b/doc/man7/provider-base.pod
@@ -108,6 +108,7 @@ provider):
CRYPTO_secure_free OSSL_FUNC_CRYPTO_SECURE_FREE
CRYPTO_secure_clear_free OSSL_FUNC_CRYPTO_SECURE_CLEAR_FREE
CRYPTO_secure_allocated OSSL_FUNC_CRYPTO_SECURE_ALLOCATED
+ CRYPTO_mem_ctrl OSSL_FUNC_CRYPTO_MEM_CTRL
BIO_new_file OSSL_FUNC_BIO_NEW_FILE
BIO_new_mem_buf OSSL_FUNC_BIO_NEW_MEMBUF
BIO_read_ex OSSL_FUNC_BIO_READ_EX
@@ -181,7 +182,7 @@ CRYPTO_malloc(), CRYPTO_zalloc(), CRYPTO_memdup(), CRYPTO_strdup(),
CRYPTO_strndup(), CRYPTO_free(), CRYPTO_clear_free(),
CRYPTO_realloc(), CRYPTO_clear_realloc(), CRYPTO_secure_malloc(),
CRYPTO_secure_zalloc(), CRYPTO_secure_free(),
-CRYPTO_secure_clear_free(), CRYPTO_secure_allocated(),
+CRYPTO_secure_clear_free(), CRYPTO_secure_allocated(), CRYPTO_mem_ctrl(),
BIO_new_file(), BIO_new_mem_buf(), BIO_read_ex(), BIO_free(),
OPENSSL_cleanse(), and OPENSSL_hexstr2buf() correspond exactly to the
public functions with the same name.
diff --git a/include/internal/thread_once.h b/include/internal/thread_once.h
index 0b38ade6c6..177974f020 100644
--- a/include/internal/thread_once.h
+++ b/include/internal/thread_once.h
@@ -15,7 +15,7 @@
* OPENSSL_CTX object. In this way data will get cleaned up correctly when the
* module gets unloaded.
*/
-#ifndef FIPS_MODE
+#if !defined(FIPS_MODE) || defined(ALLOW_RUN_ONCE_IN_FIPS)
/*
* DEFINE_RUN_ONCE: Define an initialiser function that should be run exactly
* once. It takes no arguments and returns and int result (1 for success or
diff --git a/include/openssl/core_numbers.h b/include/openssl/core_numbers.h
index 686944c28d..d07ef556d9 100644
--- a/include/openssl/core_numbers.h
+++ b/include/openssl/core_numbers.h
@@ -119,12 +119,14 @@ OSSL_CORE_MAKE_FUNC(int,
#define OSSL_FUNC_OPENSSL_CLEANSE 21
OSSL_CORE_MAKE_FUNC(void,
OPENSSL_cleanse, (void *ptr, size_t len))
+#define OSSL_FUNC_CRYPTO_MEM_CTRL 22
+OSSL_CORE_MAKE_FUNC(int, CRYPTO_mem_ctrl, (int mode))
/* Bio functions provided by the core */
-#define OSSL_FUNC_BIO_NEW_FILE 22
-#define OSSL_FUNC_BIO_NEW_MEMBUF 23
-#define OSSL_FUNC_BIO_READ_EX 24
-#define OSSL_FUNC_BIO_FREE 25
+#define OSSL_FUNC_BIO_NEW_FILE 23
+#define OSSL_FUNC_BIO_NEW_MEMBUF 24
+#define OSSL_FUNC_BIO_READ_EX 25
+#define OSSL_FUNC_BIO_FREE 26
OSSL_CORE_MAKE_FUNC(BIO *, BIO_new_file, (const char *filename, const char *mode))
OSSL_CORE_MAKE_FUNC(BIO *, BIO_new_membuf, (const void *buf, int len))
diff --git a/providers/fips/build.info b/providers/fips/build.info
index 4dfbb4623a..12ca452073 100644
--- a/providers/fips/build.info
+++ b/providers/fips/build.info
@@ -1,3 +1,3 @@
SOURCE[../fips]=fipsprov.c selftest.c
-INCLUDE[../fips]=../implementations/include ../common/include
+INCLUDE[../fips]=../implementations/include ../common/include ../..
diff --git a/providers/fips/fipsprov.c b/providers/fips/fipsprov.c
index a12163fa97..6a5ae3a3f1 100644
--- a/providers/fips/fipsprov.c
+++ b/providers/fips/fipsprov.c
@@ -60,6 +60,7 @@ static OSSL_CRYPTO_secure_zalloc_fn *c_CRYPTO_secure_zalloc;
static OSSL_CRYPTO_secure_free_fn *c_CRYPTO_secure_free;
static OSSL_CRYPTO_secure_clear_free_fn *c_CRYPTO_secure_clear_free;
static OSSL_CRYPTO_secure_allocated_fn *c_CRYPTO_secure_allocated;
+static OSSL_CRYPTO_mem_ctrl_fn *c_CRYPTO_mem_ctrl;
typedef struct fips_global_st {
const OSSL_PROVIDER *prov;
@@ -515,6 +516,9 @@ int OSSL_provider_init(const OSSL_PROVIDER *provider,
case OSSL_FUNC_CRYPTO_SECURE_ALLOCATED:
c_CRYPTO_secure_allocated = OSSL_get_CRYPTO_secure_allocated(in);
break;
+ case OSSL_FUNC_CRYPTO_MEM_CTRL:
+ c_CRYPTO_mem_ctrl = OSSL_get_CRYPTO_mem_ctrl(in);
+ break;
case OSSL_FUNC_BIO_NEW_FILE:
selftest_params.bio_new_file_cb = OSSL_get_BIO_new_file(in);
break;
@@ -548,7 +552,7 @@ int OSSL_provider_init(const OSSL_PROVIDER *provider,
fgbl->prov = provider;
selftest_params.libctx = PROV_LIBRARY_CONTEXT_OF(ctx);
- if (!SELF_TEST_post(&selftest_params)) {
+ if (!SELF_TEST_post(&selftest_params, 0)) {
OPENSSL_CTX_free(ctx);
return 0;
}
@@ -700,3 +704,8 @@ int CRYPTO_secure_allocated(const void *ptr)
{
return c_CRYPTO_secure_allocated(ptr);
}
+
+int CRYPTO_mem_ctrl(int mode)
+{
+ return c_CRYPTO_mem_ctrl(mode);
+}
diff --git a/providers/fips/selftest.c b/providers/fips/selftest.c
index d954073d64..369a6bab3b 100644
--- a/providers/fips/selftest.c
+++ b/providers/fips/selftest.c
@@ -10,11 +10,21 @@
#include <string.h>
#include <openssl/evp.h>
#include <openssl/params.h>
+#include <openssl/crypto.h>
+#include "e_os.h"
+/*
+ * We're cheating here. Normally we don't allow RUN_ONCE usage inside the FIPS
+ * module because all such initialisation should be associated with an
+ * individual OPENSSL_CTX. That doesn't work with the self test though because
+ * it should be run once regardless of the number of OPENSSL_CTXs we have.
+ */
+#define ALLOW_RUN_ONCE_IN_FIPS
+#include <internal/thread_once.h>
#include "selftest.h"
#define FIPS_STATE_INIT 0
-#define FIPS_STATE_RUNNING 1
-#define FIPS_STATE_SELFTEST 2
+#define FIPS_STATE_SELFTEST 1
+#define FIPS_STATE_RUNNING 2
#define FIPS_STATE_ERROR 3
/* The size of a temp buffer used to read in data */
@@ -24,8 +34,75 @@
#define DIGEST_NAME "SHA256"
static int FIPS_state = FIPS_STATE_INIT;
+static CRYPTO_RWLOCK *self_test_lock = NULL;
static unsigned char fixed_key[32] = { 0 };
+static CRYPTO_ONCE fips_self_test_init = CRYPTO_ONCE_STATIC_INIT;
+DEFINE_RUN_ONCE_STATIC(do_fips_self_test_init)
+{
+ /*
+ * This lock gets freed in platform specific ways that may occur after we
+ * do mem leak checking. If we don't know how to free it for a particular
+ * platform then we just leak it deliberately. So we temporarily disable the
+ * mem leak checking while we allocate this.
+ */
+ CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_DISABLE);
+ self_test_lock = CRYPTO_THREAD_lock_new();
+ CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ENABLE);
+
+ return self_test_lock != NULL;
+}
+
+/*
+ * This is the Default Entry Point (DEP) code. Every platform must have a DEP.
+ * See FIPS 140-2 IG 9.10
+ *
+ * If we're run on a platform where we don't know how to define the DEP then
+ * the self-tests will never get triggered (FIPS_state never moves to
+ * FIPS_STATE_SELFTEST). This will be detected as an error when SELF_TEST_post()
+ * is called from OSSL_provider_init(), and so the fips module will be unusable
+ * on those platforms.
+ */
+#if defined(_WIN32) || defined(__CYGWIN__)
+# ifdef __CYGWIN__
+/* pick DLL_[PROCESS|THREAD]_[ATTACH|DETACH] definitions */
+# include <windows.h>
+/*
+ * this has side-effect of _WIN32 getting defined, which otherwise is
+ * mutually exclusive with __CYGWIN__...
+ */
+# endif
+
+BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved);
+BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
+{
+ switch (fdwReason) {
+ case DLL_PROCESS_ATTACH:
+ FIPS_state = FIPS_STATE_SELFTEST;
+ break;
+ case DLL_PROCESS_DETACH:
+ CRYPTO_THREAD_lock_free(self_test_lock);
+ break;
+ default:
+ break;
+ }
+ return TRUE;
+}
+#elif defined(__GNUC__)
+
+static __attribute__((constructor)) void init(void)
+{
+ FIPS_state = FIPS_STATE_SELFTEST;
+}
+
+
+static __attribute__((destructor)) void cleanup(void)
+{
+ CRYPTO_THREAD_lock_free(self_test_lock);
+}
+
+#endif
+
/*
* Calculate the HMAC SHA256 of data read using a BIO and read_cb, and verify
* the result matches the expected value.
@@ -79,19 +156,42 @@ err:
}
/* This API is triggered either on loading of the FIPS module or on demand */
-int SELF_TEST_post(SELF_TEST_POST_PARAMS *st)
+int SELF_TEST_post(SELF_TEST_POST_PARAMS *st, int on_demand_test)
{
int ok = 0;
int kats_already_passed = 0;
- int on_demand_test = (FIPS_state != FIPS_STATE_INIT);
long checksum_len;
BIO *bio_module = NULL, *bio_indicator = NULL;
unsigned char *module_checksum = NULL;
unsigned char *indicator_checksum = NULL;
+ int loclstate;
+
+ if (!RUN_ONCE(&fips_self_test_init, do_fips_self_test_init))
+ return 0;
+
+ CRYPTO_THREAD_read_lock(self_test_lock);
+ loclstate = FIPS_state;
+ CRYPTO_THREAD_unlock(self_test_lock);
+ if (loclstate == FIPS_STATE_RUNNING) {
+ if (!on_demand_test)
+ return 1;
+ } else if (loclstate != FIPS_STATE_SELFTEST) {
+ return 0;
+ }
+
+ CRYPTO_THREAD_write_lock(self_test_lock);
+ if (FIPS_state == FIPS_STATE_RUNNING) {
+ if (!on_demand_test) {
+ CRYPTO_THREAD_unlock(self_test_lock);
+ return 1;
+ }
+ FIPS_state = FIPS_STATE_SELFTEST;
+ } else if (FIPS_state != FIPS_STATE_SELFTEST) {
+ CRYPTO_THREAD_unlock(self_test_lock);
+ return 0;
+ }
if (st == NULL
- || FIPS_state == FIPS_STATE_ERROR
- || FIPS_state == FIPS_STATE_SELFTEST
|| st->module_checksum_data == NULL)
goto end;
@@ -146,6 +246,7 @@ end:
(*st->bio_free_cb)(bio_module);
}
FIPS_state = ok ? FIPS_STATE_RUNNING : FIPS_STATE_ERROR;
+ CRYPTO_THREAD_unlock(self_test_lock);
return ok;
}
diff --git a/providers/fips/selftest.h b/providers/fips/selftest.h
index 230d448b1d..a56e42c7ab 100644
--- a/providers/fips/selftest.h
+++ b/providers/fips/selftest.h
@@ -29,4 +29,4 @@ typedef struct self_test_post_params_st {
} SELF_TEST_POST_PARAMS;
-int SELF_TEST_post(SELF_TEST_POST_PARAMS *st);
+int SELF_TEST_post(SELF_TEST_POST_PARAMS *st, int on_demand_test);
More information about the openssl-commits
mailing list