[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