[openssl] master update

Matt Caswell matt at openssl.org
Fri Apr 16 14:13:23 UTC 2021


The branch master has been updated
       via  7b9f02798f68d9108623f5879f3fc73c06f9a2c7 (commit)
       via  6ce58488bdce66584a7075e19821add29445d746 (commit)
      from  81cc5ce1a0f996f88051f031bda1079961ee4a5c (commit)


- Log -----------------------------------------------------------------
commit 7b9f02798f68d9108623f5879f3fc73c06f9a2c7
Author: Matt Caswell <matt at openssl.org>
Date:   Mon Apr 12 15:22:56 2021 +0100

    Sanity check provider up-calls
    
    When we store references to up-calls for future reference we run a sanity
    check to make sure we either previously haven't set these values or they
    are the same as last time. We don't support the scenario where an
    application is linked against multiple versions of libcrypto but using a
    shared fips.so file. This would result in different up-calls for different
    calls to OSSL_provider_init(), which we currently can't handle.
    
    Reviewed-by: Tomas Mraz <tomas at openssl.org>
    Reviewed-by: Paul Dale <pauli at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/14814)

commit 6ce58488bdce66584a7075e19821add29445d746
Author: Matt Caswell <matt at openssl.org>
Date:   Fri Apr 9 17:26:34 2021 +0100

    Store some FIPS global variables in the FIPS_GLOBAL structure
    
    We had some FIPS global variables that were based on values from the
    config file. In theory if two instances of the fips module are loaded
    they could be based on different config files which would cause this to
    fail. Instead we store them in the FIPS_GLOBAL structure.
    
    Fixes #14364
    
    Reviewed-by: Tomas Mraz <tomas at openssl.org>
    Reviewed-by: Paul Dale <pauli at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/14814)

-----------------------------------------------------------------------

Summary of changes:
 providers/common/include/prov/securitycheck.h   |  18 +-
 providers/common/provider_seeding.c             |  18 +-
 providers/common/securitycheck.c                |  25 +--
 providers/common/securitycheck_default.c        |   6 +-
 providers/common/securitycheck_fips.c           |  13 +-
 providers/fips/fipsprov.c                       | 258 +++++++++++++++---------
 providers/implementations/asymciphers/rsa_enc.c |   2 +-
 providers/implementations/exchange/dh_exch.c    |   5 +-
 providers/implementations/exchange/ecdh_exch.c  |   6 +-
 providers/implementations/kem/rsa_kem.c         |   2 +-
 providers/implementations/signature/dsa.c       |   6 +-
 providers/implementations/signature/ecdsa.c     |   5 +-
 providers/implementations/signature/rsa.c       |   7 +-
 providers/legacyprov.c                          |  28 +--
 14 files changed, 226 insertions(+), 173 deletions(-)

diff --git a/providers/common/include/prov/securitycheck.h b/providers/common/include/prov/securitycheck.h
index 7d163f70fa..7635c24973 100644
--- a/providers/common/include/prov/securitycheck.h
+++ b/providers/common/include/prov/securitycheck.h
@@ -10,18 +10,20 @@
 #include "crypto/types.h"
 
 /* Functions that are common */
-int ossl_rsa_check_key(const RSA *rsa, int operation);
-int ossl_ec_check_key(const EC_KEY *ec, int protect);
-int ossl_dsa_check_key(const DSA *dsa, int sign);
-int ossl_dh_check_key(const DH *dh);
+int ossl_rsa_check_key(OSSL_LIB_CTX *ctx, const RSA *rsa, int operation);
+int ossl_ec_check_key(OSSL_LIB_CTX *ctx, const EC_KEY *ec, int protect);
+int ossl_dsa_check_key(OSSL_LIB_CTX *ctx, const DSA *dsa, int sign);
+int ossl_dh_check_key(OSSL_LIB_CTX *ctx, const DH *dh);
 
-int ossl_digest_is_allowed(const EVP_MD *md);
-int ossl_digest_get_approved_nid_with_sha1(const EVP_MD *md, int sha1_allowed);
+int ossl_digest_is_allowed(OSSL_LIB_CTX *ctx, const EVP_MD *md);
+int ossl_digest_get_approved_nid_with_sha1(OSSL_LIB_CTX *ctx, const EVP_MD *md,
+                                           int sha1_allowed);
 
 /* Functions that are common */
 int ossl_digest_md_to_nid(const EVP_MD *md, const OSSL_ITEM *it, size_t it_len);
 int ossl_digest_get_approved_nid(const EVP_MD *md);
 
 /* Functions that have different implementations for the FIPS_MODULE */
-int ossl_digest_rsa_sign_get_md_nid(const EVP_MD *md, int sha1_allowed);
-int ossl_securitycheck_enabled(void);
+int ossl_digest_rsa_sign_get_md_nid(OSSL_LIB_CTX *ctx, const EVP_MD *md,
+                                    int sha1_allowed);
+int ossl_securitycheck_enabled(OSSL_LIB_CTX *libctx);
diff --git a/providers/common/provider_seeding.c b/providers/common/provider_seeding.c
index 98704a2cdf..73a2a14187 100644
--- a/providers/common/provider_seeding.c
+++ b/providers/common/provider_seeding.c
@@ -18,22 +18,24 @@ static OSSL_FUNC_cleanup_nonce_fn *c_cleanup_nonce = NULL;
 int ossl_prov_seeding_from_dispatch(const OSSL_DISPATCH *fns)
 {
     for (; fns->function_id != 0; fns++) {
+        /*
+         * We do not support the scenario of an application linked against
+         * multiple versions of libcrypto (e.g. one static and one dynamic), but
+         * sharing a single fips.so. We do a simple sanity check here.
+         */
+#define set_func(c, f) if (c == NULL) c = f; else if (c != f) return 0;
         switch (fns->function_id) {
         case OSSL_FUNC_GET_ENTROPY:
-            if (c_get_entropy == NULL)
-                c_get_entropy = OSSL_FUNC_get_entropy(fns);
+            set_func(c_get_entropy, OSSL_FUNC_get_entropy(fns));
             break;
         case OSSL_FUNC_CLEANUP_ENTROPY:
-            if (c_cleanup_entropy == NULL)
-                c_cleanup_entropy = OSSL_FUNC_cleanup_entropy(fns);
+            set_func(c_cleanup_entropy, OSSL_FUNC_cleanup_entropy(fns));
             break;
         case OSSL_FUNC_GET_NONCE:
-            if (c_get_nonce == NULL)
-                c_get_nonce = OSSL_FUNC_get_nonce(fns);
+            set_func(c_get_nonce, OSSL_FUNC_get_nonce(fns));
             break;
         case OSSL_FUNC_CLEANUP_NONCE:
-            if (c_cleanup_nonce == NULL)
-                c_cleanup_nonce = OSSL_FUNC_cleanup_nonce(fns);
+            set_func(c_cleanup_nonce, OSSL_FUNC_cleanup_nonce(fns));
             break;
         }
     }
diff --git a/providers/common/securitycheck.c b/providers/common/securitycheck.c
index 08582d6346..4f36ce4593 100644
--- a/providers/common/securitycheck.c
+++ b/providers/common/securitycheck.c
@@ -26,7 +26,7 @@
  * Set protect = 1 for encryption or signing operations, or 0 otherwise. See
  * https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-131Ar2.pdf.
  */
-int ossl_rsa_check_key(const RSA *rsa, int operation)
+int ossl_rsa_check_key(OSSL_LIB_CTX *ctx, const RSA *rsa, int operation)
 {
     int protect = 0;
 
@@ -58,7 +58,7 @@ int ossl_rsa_check_key(const RSA *rsa, int operation)
     }
 
 #if !defined(OPENSSL_NO_FIPS_SECURITYCHECKS)
-    if (ossl_securitycheck_enabled()) {
+    if (ossl_securitycheck_enabled(ctx)) {
         int sz = RSA_bits(rsa);
 
         if (protect ? (sz < 2048) : (sz < 1024)) {
@@ -89,10 +89,10 @@ int ossl_rsa_check_key(const RSA *rsa, int operation)
  * https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-131Ar2.pdf
  * "Table 2"
  */
-int ossl_ec_check_key(const EC_KEY *ec, int protect)
+int ossl_ec_check_key(OSSL_LIB_CTX *ctx, const EC_KEY *ec, int protect)
 {
 # if !defined(OPENSSL_NO_FIPS_SECURITYCHECKS)
-    if (ossl_securitycheck_enabled()) {
+    if (ossl_securitycheck_enabled(ctx)) {
         int nid, strength;
         const char *curve_name;
         const EC_GROUP *group = EC_KEY_get0_group(ec);
@@ -147,10 +147,10 @@ int ossl_ec_check_key(const EC_KEY *ec, int protect)
  * https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-131Ar2.pdf
  * "Table 2"
  */
-int ossl_dsa_check_key(const DSA *dsa, int sign)
+int ossl_dsa_check_key(OSSL_LIB_CTX *ctx, const DSA *dsa, int sign)
 {
 # if !defined(OPENSSL_NO_FIPS_SECURITYCHECKS)
-    if (ossl_securitycheck_enabled()) {
+    if (ossl_securitycheck_enabled(ctx)) {
         size_t L, N;
         const BIGNUM *p, *q;
 
@@ -191,10 +191,10 @@ int ossl_dsa_check_key(const DSA *dsa, int sign)
  * "Section 5.5.1.1FFC Domain Parameter Selection/Generation" and
  * "Appendix D" FFC Safe-prime Groups
  */
-int ossl_dh_check_key(const DH *dh)
+int ossl_dh_check_key(OSSL_LIB_CTX *ctx, const DH *dh)
 {
 # if !defined(OPENSSL_NO_FIPS_SECURITYCHECKS)
-    if (ossl_securitycheck_enabled()) {
+    if (ossl_securitycheck_enabled(ctx)) {
         size_t L, N;
         const BIGNUM *p, *q;
 
@@ -224,12 +224,13 @@ int ossl_dh_check_key(const DH *dh)
 }
 #endif /* OPENSSL_NO_DH */
 
-int ossl_digest_get_approved_nid_with_sha1(const EVP_MD *md, int sha1_allowed)
+int ossl_digest_get_approved_nid_with_sha1(OSSL_LIB_CTX *ctx, const EVP_MD *md,
+                                           int sha1_allowed)
 {
     int mdnid = ossl_digest_get_approved_nid(md);
 
 # if !defined(OPENSSL_NO_FIPS_SECURITYCHECKS)
-    if (ossl_securitycheck_enabled()) {
+    if (ossl_securitycheck_enabled(ctx)) {
         if (mdnid == NID_sha1 && !sha1_allowed)
             mdnid = NID_undef;
     }
@@ -237,10 +238,10 @@ int ossl_digest_get_approved_nid_with_sha1(const EVP_MD *md, int sha1_allowed)
     return mdnid;
 }
 
-int ossl_digest_is_allowed(const EVP_MD *md)
+int ossl_digest_is_allowed(OSSL_LIB_CTX *ctx, const EVP_MD *md)
 {
 # if !defined(OPENSSL_NO_FIPS_SECURITYCHECKS)
-    if (ossl_securitycheck_enabled())
+    if (ossl_securitycheck_enabled(ctx))
         return ossl_digest_get_approved_nid(md) != NID_undef;
 # endif /* OPENSSL_NO_FIPS_SECURITYCHECKS */
     return 1;
diff --git a/providers/common/securitycheck_default.c b/providers/common/securitycheck_default.c
index c3a9325a1f..de7f0d3a0a 100644
--- a/providers/common/securitycheck_default.c
+++ b/providers/common/securitycheck_default.c
@@ -17,12 +17,12 @@
 #include "internal/nelem.h"
 
 /* Disable the security checks in the default provider */
-int ossl_securitycheck_enabled(void)
+int ossl_securitycheck_enabled(OSSL_LIB_CTX *libctx)
 {
     return 0;
 }
 
-int ossl_digest_rsa_sign_get_md_nid(const EVP_MD *md,
+int ossl_digest_rsa_sign_get_md_nid(OSSL_LIB_CTX *ctx, const EVP_MD *md,
                                     ossl_unused int sha1_allowed)
 {
     int mdnid;
@@ -36,7 +36,7 @@ int ossl_digest_rsa_sign_get_md_nid(const EVP_MD *md,
         { NID_ripemd160, OSSL_DIGEST_NAME_RIPEMD160 },
     };
 
-    mdnid = ossl_digest_get_approved_nid_with_sha1(md, 1);
+    mdnid = ossl_digest_get_approved_nid_with_sha1(ctx, md, 1);
     if (mdnid == NID_undef)
         mdnid = ossl_digest_md_to_nid(md, name_to_nid, OSSL_NELEM(name_to_nid));
     return mdnid;
diff --git a/providers/common/securitycheck_fips.c b/providers/common/securitycheck_fips.c
index 42e5f46009..b7659bd395 100644
--- a/providers/common/securitycheck_fips.c
+++ b/providers/common/securitycheck_fips.c
@@ -19,22 +19,23 @@
 #include <openssl/obj_mac.h>
 #include "prov/securitycheck.h"
 
-extern int FIPS_security_check_enabled(void);
+int FIPS_security_check_enabled(OSSL_LIB_CTX *libctx);
 
-int ossl_securitycheck_enabled(void)
+int ossl_securitycheck_enabled(OSSL_LIB_CTX *libctx)
 {
 #if !defined(OPENSSL_NO_FIPS_SECURITYCHECKS)
-    return FIPS_security_check_enabled();
+    return FIPS_security_check_enabled(libctx);
 #else
     return 0;
 #endif /* OPENSSL_NO_FIPS_SECURITYCHECKS */
 }
 
-int ossl_digest_rsa_sign_get_md_nid(const EVP_MD *md, int sha1_allowed)
+int ossl_digest_rsa_sign_get_md_nid(OSSL_LIB_CTX *ctx, const EVP_MD *md,
+                                    int sha1_allowed)
 {
 #if !defined(OPENSSL_NO_FIPS_SECURITYCHECKS)
-    if (ossl_securitycheck_enabled())
-        return ossl_digest_get_approved_nid_with_sha1(md, sha1_allowed);
+    if (ossl_securitycheck_enabled(ctx))
+        return ossl_digest_get_approved_nid_with_sha1(ctx, md, sha1_allowed);
 #endif /* OPENSSL_NO_FIPS_SECURITYCHECKS */
     return ossl_digest_get_approved_nid(md);
 }
diff --git a/providers/fips/fipsprov.c b/providers/fips/fipsprov.c
index f6a405d58e..aeea8f296f 100644
--- a/providers/fips/fipsprov.c
+++ b/providers/fips/fipsprov.c
@@ -7,6 +7,7 @@
  * https://www.openssl.org/source/license.html
  */
 
+#include <assert.h>
 #include <openssl/core_dispatch.h>
 #include <openssl/core_names.h>
 #include <openssl/params.h>
@@ -37,19 +38,13 @@ static OSSL_FUNC_provider_query_operation_fn fips_query;
 #define ALG(NAMES, FUNC) ALGC(NAMES, FUNC, NULL)
 
 extern OSSL_FUNC_core_thread_start_fn *c_thread_start;
-int FIPS_security_check_enabled(void);
+int FIPS_security_check_enabled(OSSL_LIB_CTX *libctx);
 
 /*
- * TODO(3.0): Should these be stored in the provider side provctx? Could they
- * ever be different from one init to the next? Unfortunately we can't do this
- * at the moment because c_put_error/c_add_error_vdata do not provide
- * us with the OSSL_LIB_CTX as a parameter.
+ * Should these function pointers be stored in the provider side provctx? Could
+ * they ever be different from one init to the next? We assume not for now.
  */
 
-static SELF_TEST_POST_PARAMS selftest_params;
-static int fips_security_checks = 1;
-static const char *fips_security_check_option = "1";
-
 /* Functions provided by the core */
 static OSSL_FUNC_core_gettable_params_fn *c_gettable_params;
 static OSSL_FUNC_core_get_params_fn *c_get_params;
@@ -77,12 +72,20 @@ static OSSL_FUNC_core_get_libctx_fn *c_get_libctx = NULL;
 
 typedef struct fips_global_st {
     const OSSL_CORE_HANDLE *handle;
+    SELF_TEST_POST_PARAMS selftest_params;
+    int fips_security_checks;
+    const char *fips_security_check_option;
 } FIPS_GLOBAL;
 
 static void *fips_prov_ossl_ctx_new(OSSL_LIB_CTX *libctx)
 {
     FIPS_GLOBAL *fgbl = OPENSSL_zalloc(sizeof(*fgbl));
 
+    if (fgbl == NULL)
+        return NULL;
+    fgbl->fips_security_checks = 1;
+    fgbl->fips_security_check_option = "1";
+
     return fgbl;
 }
 
@@ -107,38 +110,54 @@ static const OSSL_PARAM fips_param_types[] = {
     OSSL_PARAM_END
 };
 
-/*
- * Parameters to retrieve from the core provider - required for self testing.
- * NOTE: inside core_get_params() these will be loaded from config items
- * stored inside prov->parameters (except for
- * OSSL_PROV_PARAM_CORE_MODULE_FILENAME).
- * OSSL_PROV_FIPS_PARAM_SECURITY_CHECKS is not a self test parameter.
- */
-static OSSL_PARAM core_params[] =
-{
-    OSSL_PARAM_utf8_ptr(OSSL_PROV_PARAM_CORE_MODULE_FILENAME,
-                        &selftest_params.module_filename,
-                        sizeof(selftest_params.module_filename)),
-    OSSL_PARAM_utf8_ptr(OSSL_PROV_FIPS_PARAM_MODULE_MAC,
-                        &selftest_params.module_checksum_data,
-                        sizeof(selftest_params.module_checksum_data)),
-    OSSL_PARAM_utf8_ptr(OSSL_PROV_FIPS_PARAM_INSTALL_MAC,
-                        &selftest_params.indicator_checksum_data,
-                        sizeof(selftest_params.indicator_checksum_data)),
-    OSSL_PARAM_utf8_ptr(OSSL_PROV_FIPS_PARAM_INSTALL_STATUS,
-                        &selftest_params.indicator_data,
-                        sizeof(selftest_params.indicator_data)),
-    OSSL_PARAM_utf8_ptr(OSSL_PROV_FIPS_PARAM_INSTALL_VERSION,
-                        &selftest_params.indicator_version,
-                        sizeof(selftest_params.indicator_version)),
-    OSSL_PARAM_utf8_ptr(OSSL_PROV_FIPS_PARAM_CONDITIONAL_ERRORS,
-                        &selftest_params.conditional_error_check,
-                        sizeof(selftest_params.conditional_error_check)),
-    OSSL_PARAM_utf8_ptr(OSSL_PROV_FIPS_PARAM_SECURITY_CHECKS,
-                        &fips_security_check_option,
-                        sizeof(fips_security_check_option)),
-    OSSL_PARAM_END
-};
+static int fips_get_params_from_core(FIPS_GLOBAL *fgbl)
+{
+    /*
+    * Parameters to retrieve from the core provider - required for self testing.
+    * NOTE: inside core_get_params() these will be loaded from config items
+    * stored inside prov->parameters (except for
+    * OSSL_PROV_PARAM_CORE_MODULE_FILENAME).
+    * OSSL_PROV_FIPS_PARAM_SECURITY_CHECKS is not a self test parameter.
+    */
+    OSSL_PARAM core_params[8], *p = core_params;
+
+    *p++ = OSSL_PARAM_construct_utf8_ptr(
+            OSSL_PROV_PARAM_CORE_MODULE_FILENAME,
+            (char **)&fgbl->selftest_params.module_filename,
+            sizeof(fgbl->selftest_params.module_filename));
+    *p++ = OSSL_PARAM_construct_utf8_ptr(
+            OSSL_PROV_FIPS_PARAM_MODULE_MAC,
+            (char **)&fgbl->selftest_params.module_checksum_data,
+            sizeof(fgbl->selftest_params.module_checksum_data));
+    *p++ = OSSL_PARAM_construct_utf8_ptr(
+            OSSL_PROV_FIPS_PARAM_INSTALL_MAC,
+            (char **)&fgbl->selftest_params.indicator_checksum_data,
+            sizeof(fgbl->selftest_params.indicator_checksum_data));
+    *p++ = OSSL_PARAM_construct_utf8_ptr(
+            OSSL_PROV_FIPS_PARAM_INSTALL_STATUS,
+            (char **)&fgbl->selftest_params.indicator_data,
+            sizeof(fgbl->selftest_params.indicator_data));
+    *p++ = OSSL_PARAM_construct_utf8_ptr(
+            OSSL_PROV_FIPS_PARAM_INSTALL_VERSION,
+            (char **)&fgbl->selftest_params.indicator_version,
+            sizeof(fgbl->selftest_params.indicator_version));
+    *p++ = OSSL_PARAM_construct_utf8_ptr(
+            OSSL_PROV_FIPS_PARAM_CONDITIONAL_ERRORS,
+            (char **)&fgbl->selftest_params.conditional_error_check,
+            sizeof(fgbl->selftest_params.conditional_error_check));
+    *p++ = OSSL_PARAM_construct_utf8_ptr(
+            OSSL_PROV_FIPS_PARAM_SECURITY_CHECKS,
+            (char **)&fgbl->fips_security_check_option,
+            sizeof(fgbl->fips_security_check_option));
+    *p = OSSL_PARAM_construct_end();
+
+    if (!c_get_params(fgbl->handle, core_params)) {
+        ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
+        return 0;
+    }
+
+    return 1;
+}
 
 static const OSSL_PARAM *fips_gettable_params(void *provctx)
 {
@@ -148,6 +167,9 @@ static const OSSL_PARAM *fips_gettable_params(void *provctx)
 static int fips_get_params(void *provctx, OSSL_PARAM params[])
 {
     OSSL_PARAM *p;
+    FIPS_GLOBAL *fgbl = ossl_lib_ctx_get_data(ossl_prov_ctx_get0_libctx(provctx),
+                                              OSSL_LIB_CTX_FIPS_PROV_INDEX,
+                                              &fips_prov_ossl_ctx_method);
 
     p = OSSL_PARAM_locate(params, OSSL_PROV_PARAM_NAME);
     if (p != NULL && !OSSL_PARAM_set_utf8_ptr(p, "OpenSSL FIPS Provider"))
@@ -162,26 +184,33 @@ static int fips_get_params(void *provctx, OSSL_PARAM params[])
     if (p != NULL && !OSSL_PARAM_set_int(p, ossl_prov_is_running()))
         return 0;
     p = OSSL_PARAM_locate(params, OSSL_PROV_PARAM_SECURITY_CHECKS);
-    if (p != NULL && !OSSL_PARAM_set_int(p, fips_security_checks))
+    if (p != NULL && !OSSL_PARAM_set_int(p, fgbl->fips_security_checks))
         return 0;
     return 1;
 }
 
-static void set_self_test_cb(const OSSL_CORE_HANDLE *handle)
+static void set_self_test_cb(FIPS_GLOBAL *fgbl)
 {
+    const OSSL_CORE_HANDLE *handle =
+        FIPS_get_core_handle(fgbl->selftest_params.libctx);
+
     if (c_stcbfn != NULL && c_get_libctx != NULL) {
-        c_stcbfn(c_get_libctx(handle), &selftest_params.cb,
-                              &selftest_params.cb_arg);
+        c_stcbfn(c_get_libctx(handle), &fgbl->selftest_params.cb,
+                              &fgbl->selftest_params.cb_arg);
     } else {
-        selftest_params.cb = NULL;
-        selftest_params.cb_arg = NULL;
+        fgbl->selftest_params.cb = NULL;
+        fgbl->selftest_params.cb_arg = NULL;
     }
 }
 
 static int fips_self_test(void *provctx)
 {
-    set_self_test_cb(FIPS_get_core_handle(selftest_params.libctx));
-    return SELF_TEST_post(&selftest_params, 1) ? 1 : 0;
+    FIPS_GLOBAL *fgbl = ossl_lib_ctx_get_data(ossl_prov_ctx_get0_libctx(provctx),
+                                              OSSL_LIB_CTX_FIPS_PROV_INDEX,
+                                              &fips_prov_ossl_ctx_method);
+
+    set_self_test_cb(fgbl);
+    return SELF_TEST_post(&fgbl->selftest_params, 1) ? 1 : 0;
 }
 
 /*
@@ -506,91 +535,110 @@ int OSSL_provider_init(const OSSL_CORE_HANDLE *handle,
 {
     FIPS_GLOBAL *fgbl;
     OSSL_LIB_CTX *libctx = NULL;
+    SELF_TEST_POST_PARAMS selftest_params;
+
+    memset(&selftest_params, 0, sizeof(selftest_params));
 
     if (!ossl_prov_seeding_from_dispatch(in))
         return 0;
     for (; in->function_id != 0; in++) {
+        /*
+         * We do not support the scenario of an application linked against
+         * multiple versions of libcrypto (e.g. one static and one dynamic), but
+         * sharing a single fips.so. We do a simple sanity check here.
+         */
+#define set_func(c, f) if (c == NULL) c = f; else if (c != f) return 0;
         switch (in->function_id) {
         case OSSL_FUNC_CORE_GET_LIBCTX:
-            c_get_libctx = OSSL_FUNC_core_get_libctx(in);
+            set_func(c_get_libctx, OSSL_FUNC_core_get_libctx(in));
             break;
         case OSSL_FUNC_CORE_GETTABLE_PARAMS:
-            c_gettable_params = OSSL_FUNC_core_gettable_params(in);
+            set_func(c_gettable_params, OSSL_FUNC_core_gettable_params(in));
             break;
         case OSSL_FUNC_CORE_GET_PARAMS:
-            c_get_params = OSSL_FUNC_core_get_params(in);
+            set_func(c_get_params, OSSL_FUNC_core_get_params(in));
             break;
         case OSSL_FUNC_CORE_THREAD_START:
-            c_thread_start = OSSL_FUNC_core_thread_start(in);
+            set_func(c_thread_start, OSSL_FUNC_core_thread_start(in));
             break;
         case OSSL_FUNC_CORE_NEW_ERROR:
-            c_new_error = OSSL_FUNC_core_new_error(in);
+            set_func(c_new_error, OSSL_FUNC_core_new_error(in));
             break;
         case OSSL_FUNC_CORE_SET_ERROR_DEBUG:
-            c_set_error_debug = OSSL_FUNC_core_set_error_debug(in);
+            set_func(c_set_error_debug, OSSL_FUNC_core_set_error_debug(in));
             break;
         case OSSL_FUNC_CORE_VSET_ERROR:
-            c_vset_error = OSSL_FUNC_core_vset_error(in);
+            set_func(c_vset_error, OSSL_FUNC_core_vset_error(in));
             break;
         case OSSL_FUNC_CORE_SET_ERROR_MARK:
-            c_set_error_mark = OSSL_FUNC_core_set_error_mark(in);
+            set_func(c_set_error_mark, OSSL_FUNC_core_set_error_mark(in));
             break;
         case OSSL_FUNC_CORE_CLEAR_LAST_ERROR_MARK:
-            c_clear_last_error_mark = OSSL_FUNC_core_clear_last_error_mark(in);
+            set_func(c_clear_last_error_mark,
+                     OSSL_FUNC_core_clear_last_error_mark(in));
             break;
         case OSSL_FUNC_CORE_POP_ERROR_TO_MARK:
-            c_pop_error_to_mark = OSSL_FUNC_core_pop_error_to_mark(in);
+            set_func(c_pop_error_to_mark, OSSL_FUNC_core_pop_error_to_mark(in));
             break;
         case OSSL_FUNC_CRYPTO_MALLOC:
-            c_CRYPTO_malloc = OSSL_FUNC_CRYPTO_malloc(in);
+            set_func(c_CRYPTO_malloc, OSSL_FUNC_CRYPTO_malloc(in));
             break;
         case OSSL_FUNC_CRYPTO_ZALLOC:
-            c_CRYPTO_zalloc = OSSL_FUNC_CRYPTO_zalloc(in);
+            set_func(c_CRYPTO_zalloc, OSSL_FUNC_CRYPTO_zalloc(in));
             break;
         case OSSL_FUNC_CRYPTO_FREE:
-            c_CRYPTO_free = OSSL_FUNC_CRYPTO_free(in);
+            set_func(c_CRYPTO_free, OSSL_FUNC_CRYPTO_free(in));
             break;
         case OSSL_FUNC_CRYPTO_CLEAR_FREE:
-            c_CRYPTO_clear_free = OSSL_FUNC_CRYPTO_clear_free(in);
+            set_func(c_CRYPTO_clear_free, OSSL_FUNC_CRYPTO_clear_free(in));
             break;
         case OSSL_FUNC_CRYPTO_REALLOC:
-            c_CRYPTO_realloc = OSSL_FUNC_CRYPTO_realloc(in);
+            set_func(c_CRYPTO_realloc, OSSL_FUNC_CRYPTO_realloc(in));
             break;
         case OSSL_FUNC_CRYPTO_CLEAR_REALLOC:
-            c_CRYPTO_clear_realloc = OSSL_FUNC_CRYPTO_clear_realloc(in);
+            set_func(c_CRYPTO_clear_realloc,
+                     OSSL_FUNC_CRYPTO_clear_realloc(in));
             break;
         case OSSL_FUNC_CRYPTO_SECURE_MALLOC:
-            c_CRYPTO_secure_malloc = OSSL_FUNC_CRYPTO_secure_malloc(in);
+            set_func(c_CRYPTO_secure_malloc,
+                     OSSL_FUNC_CRYPTO_secure_malloc(in));
             break;
         case OSSL_FUNC_CRYPTO_SECURE_ZALLOC:
-            c_CRYPTO_secure_zalloc = OSSL_FUNC_CRYPTO_secure_zalloc(in);
+            set_func(c_CRYPTO_secure_zalloc,
+                     OSSL_FUNC_CRYPTO_secure_zalloc(in));
             break;
         case OSSL_FUNC_CRYPTO_SECURE_FREE:
-            c_CRYPTO_secure_free = OSSL_FUNC_CRYPTO_secure_free(in);
+            set_func(c_CRYPTO_secure_free,
+                     OSSL_FUNC_CRYPTO_secure_free(in));
             break;
         case OSSL_FUNC_CRYPTO_SECURE_CLEAR_FREE:
-            c_CRYPTO_secure_clear_free = OSSL_FUNC_CRYPTO_secure_clear_free(in);
+            set_func(c_CRYPTO_secure_clear_free,
+                     OSSL_FUNC_CRYPTO_secure_clear_free(in));
             break;
         case OSSL_FUNC_CRYPTO_SECURE_ALLOCATED:
-            c_CRYPTO_secure_allocated = OSSL_FUNC_CRYPTO_secure_allocated(in);
+            set_func(c_CRYPTO_secure_allocated,
+                     OSSL_FUNC_CRYPTO_secure_allocated(in));
             break;
         case OSSL_FUNC_BIO_NEW_FILE:
-            selftest_params.bio_new_file_cb = OSSL_FUNC_BIO_new_file(in);
+            set_func(selftest_params.bio_new_file_cb,
+                     OSSL_FUNC_BIO_new_file(in));
             break;
         case OSSL_FUNC_BIO_NEW_MEMBUF:
-            selftest_params.bio_new_buffer_cb = OSSL_FUNC_BIO_new_membuf(in);
+            set_func(selftest_params.bio_new_buffer_cb,
+                     OSSL_FUNC_BIO_new_membuf(in));
             break;
         case OSSL_FUNC_BIO_READ_EX:
-            selftest_params.bio_read_ex_cb = OSSL_FUNC_BIO_read_ex(in);
+            set_func(selftest_params.bio_read_ex_cb,
+                     OSSL_FUNC_BIO_read_ex(in));
             break;
         case OSSL_FUNC_BIO_FREE:
-            selftest_params.bio_free_cb = OSSL_FUNC_BIO_free(in);
+            set_func(selftest_params.bio_free_cb, OSSL_FUNC_BIO_free(in));
             break;
         case OSSL_FUNC_BIO_VSNPRINTF:
-            c_BIO_vsnprintf = OSSL_FUNC_BIO_vsnprintf(in);
+            set_func(c_BIO_vsnprintf, OSSL_FUNC_BIO_vsnprintf(in));
             break;
         case OSSL_FUNC_SELF_TEST_CB:
-            c_stcbfn = OSSL_FUNC_self_test_cb(in);
+            set_func(c_stcbfn, OSSL_FUNC_self_test_cb(in));
             break;
         default:
             /* Just ignore anything we don't understand */
@@ -598,22 +646,6 @@ int OSSL_provider_init(const OSSL_CORE_HANDLE *handle,
         }
     }
 
-    set_self_test_cb(handle);
-
-    if (!c_get_params(handle, core_params)) {
-        ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
-        return 0;
-    }
-    /* Disable the conditional error check if is disabled in the fips config file*/
-    if (selftest_params.conditional_error_check != NULL
-        && strcmp(selftest_params.conditional_error_check, "0") == 0)
-        SELF_TEST_disable_conditional_error_state();
-
-    /* Disable the security check if is disabled in the fips config file*/
-    if (fips_security_check_option != NULL
-        && strcmp(fips_security_check_option, "0") == 0)
-        fips_security_checks = 0;
-
     /*  Create a context. */
     if ((*provctx = ossl_prov_ctx_new()) == NULL
         || (libctx = OSSL_LIB_CTX_new()) == NULL) {
@@ -634,10 +666,37 @@ int OSSL_provider_init(const OSSL_CORE_HANDLE *handle,
 
     fgbl->handle = handle;
 
+    /*
+     * We did initial set up of selftest_params in a local copy, because we
+     * could not create fgbl until c_CRYPTO_zalloc was defined in the loop
+     * above.
+     */
+    fgbl->selftest_params = selftest_params;
+
+    fgbl->selftest_params.libctx = libctx;
+
+    set_self_test_cb(fgbl);
+
+    if (!fips_get_params_from_core(fgbl)) {
+        /* Error already raised */
+        return 0;
+    }
+    /*
+     * Disable the conditional error check if is disabled in the fips config
+     * file
+     */
+    if (fgbl->selftest_params.conditional_error_check != NULL
+        && strcmp(fgbl->selftest_params.conditional_error_check, "0") == 0)
+        SELF_TEST_disable_conditional_error_state();
+
+    /* Disable the security check if is disabled in the fips config file */
+    if (fgbl->fips_security_check_option != NULL
+        && strcmp(fgbl->fips_security_check_option, "0") == 0)
+        fgbl->fips_security_checks = 0;
+
     ossl_prov_cache_exported_algorithms(fips_ciphers, exported_fips_ciphers);
 
-    selftest_params.libctx = libctx;
-    if (!SELF_TEST_post(&selftest_params, 0)) {
+    if (!SELF_TEST_post(&fgbl->selftest_params, 0)) {
         ERR_raise(ERR_LIB_PROV, PROV_R_SELF_TEST_POST_FAILURE);
         goto err;
     }
@@ -819,16 +878,19 @@ int BIO_snprintf(char *buf, size_t n, const char *format, ...)
     return ret;
 }
 
-int FIPS_security_check_enabled(void)
+int FIPS_security_check_enabled(OSSL_LIB_CTX *libctx)
 {
-    return fips_security_checks;
+    FIPS_GLOBAL *fgbl = ossl_lib_ctx_get_data(libctx,
+                                              OSSL_LIB_CTX_FIPS_PROV_INDEX,
+                                              &fips_prov_ossl_ctx_method);
+
+    return fgbl->fips_security_checks;
 }
 
 void OSSL_SELF_TEST_get_callback(OSSL_LIB_CTX *libctx, OSSL_CALLBACK **cb,
                                  void **cbarg)
 {
-    if (libctx == NULL)
-        libctx = selftest_params.libctx;
+    assert(libctx != NULL);
 
     if (c_stcbfn != NULL && c_get_libctx != NULL) {
         /* Get the parent libctx */
diff --git a/providers/implementations/asymciphers/rsa_enc.c b/providers/implementations/asymciphers/rsa_enc.c
index ab84d53512..354c234939 100644
--- a/providers/implementations/asymciphers/rsa_enc.c
+++ b/providers/implementations/asymciphers/rsa_enc.c
@@ -99,7 +99,7 @@ static int rsa_init(void *vprsactx, void *vrsa, const OSSL_PARAM params[],
     if (!ossl_prov_is_running() || prsactx == NULL || vrsa == NULL)
         return 0;
 
-    if (!ossl_rsa_check_key(vrsa, operation))
+    if (!ossl_rsa_check_key(prsactx->libctx, vrsa, operation))
         return 0;
 
     if (!RSA_up_ref(vrsa))
diff --git a/providers/implementations/exchange/dh_exch.c b/providers/implementations/exchange/dh_exch.c
index 0ecc6c7a4c..67a73d36ef 100644
--- a/providers/implementations/exchange/dh_exch.c
+++ b/providers/implementations/exchange/dh_exch.c
@@ -105,7 +105,8 @@ static int dh_init(void *vpdhctx, void *vdh, const OSSL_PARAM params[])
     DH_free(pdhctx->dh);
     pdhctx->dh = vdh;
     pdhctx->kdf_type = PROV_DH_KDF_NONE;
-    return dh_set_ctx_params(pdhctx, params) && ossl_dh_check_key(vdh);
+    return dh_set_ctx_params(pdhctx, params)
+           && ossl_dh_check_key(pdhctx->libctx, vdh);
 }
 
 /* The 2 parties must share the same domain parameters */
@@ -345,7 +346,7 @@ static int dh_set_ctx_params(void *vpdhctx, const OSSL_PARAM params[])
 
         EVP_MD_free(pdhctx->kdf_md);
         pdhctx->kdf_md = EVP_MD_fetch(pdhctx->libctx, name, mdprops);
-        if (!ossl_digest_is_allowed(pdhctx->kdf_md)) {
+        if (!ossl_digest_is_allowed(pdhctx->libctx, pdhctx->kdf_md)) {
             EVP_MD_free(pdhctx->kdf_md);
             pdhctx->kdf_md = NULL;
         }
diff --git a/providers/implementations/exchange/ecdh_exch.c b/providers/implementations/exchange/ecdh_exch.c
index ba2b493a76..7748340248 100644
--- a/providers/implementations/exchange/ecdh_exch.c
+++ b/providers/implementations/exchange/ecdh_exch.c
@@ -113,7 +113,7 @@ int ecdh_init(void *vpecdhctx, void *vecdh, const OSSL_PARAM params[])
     pecdhctx->cofactor_mode = -1;
     pecdhctx->kdf_type = PROV_ECDH_KDF_NONE;
     return ecdh_set_ctx_params(pecdhctx, params)
-           && ossl_ec_check_key(vecdh, 1);
+           && ossl_ec_check_key(pecdhctx->libctx, vecdh, 1);
 }
 
 static
@@ -147,7 +147,7 @@ int ecdh_set_peer(void *vpecdhctx, void *vecdh)
             || pecdhctx == NULL
             || vecdh == NULL
             || !ecdh_match_params(pecdhctx->k, vecdh)
-            || !ossl_ec_check_key(vecdh, 1)
+            || !ossl_ec_check_key(pecdhctx->libctx, vecdh, 1)
             || !EC_KEY_up_ref(vecdh))
         return 0;
 
@@ -283,7 +283,7 @@ int ecdh_set_ctx_params(void *vpecdhctx, const OSSL_PARAM params[])
 
         EVP_MD_free(pectx->kdf_md);
         pectx->kdf_md = EVP_MD_fetch(pectx->libctx, name, mdprops);
-        if (!ossl_digest_is_allowed(pectx->kdf_md)) {
+        if (!ossl_digest_is_allowed(pectx->libctx, pectx->kdf_md)) {
             EVP_MD_free(pectx->kdf_md);
             pectx->kdf_md = NULL;
         }
diff --git a/providers/implementations/kem/rsa_kem.c b/providers/implementations/kem/rsa_kem.c
index 3809bfb8b1..9aa0a7aaee 100644
--- a/providers/implementations/kem/rsa_kem.c
+++ b/providers/implementations/kem/rsa_kem.c
@@ -125,7 +125,7 @@ static int rsakem_init(void *vprsactx, void *vrsa,
     if (prsactx == NULL || vrsa == NULL)
         return 0;
 
-    if (!ossl_rsa_check_key(vrsa, operation))
+    if (!ossl_rsa_check_key(prsactx->libctx, vrsa, operation))
         return 0;
 
     if (!RSA_up_ref(vrsa))
diff --git a/providers/implementations/signature/dsa.c b/providers/implementations/signature/dsa.c
index 88a8102cff..dde689903d 100644
--- a/providers/implementations/signature/dsa.c
+++ b/providers/implementations/signature/dsa.c
@@ -127,7 +127,8 @@ static int dsa_setup_md(PROV_DSA_CTX *ctx,
         int sha1_allowed = (ctx->operation != EVP_PKEY_OP_SIGN);
         WPACKET pkt;
         EVP_MD *md = EVP_MD_fetch(ctx->libctx, mdname, mdprops);
-        int md_nid = ossl_digest_get_approved_nid_with_sha1(md, sha1_allowed);
+        int md_nid = ossl_digest_get_approved_nid_with_sha1(ctx->libctx, md,
+                                                            sha1_allowed);
         size_t mdname_len = strlen(mdname);
 
         if (md == NULL || md_nid == NID_undef) {
@@ -188,7 +189,8 @@ static int dsa_signverify_init(void *vpdsactx, void *vdsa,
     if (!dsa_set_ctx_params(pdsactx, params))
         return 0;
 
-    if (!ossl_dsa_check_key(vdsa, operation == EVP_PKEY_OP_SIGN)) {
+    if (!ossl_dsa_check_key(pdsactx->libctx, vdsa,
+                            operation == EVP_PKEY_OP_SIGN)) {
         ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH);
         return 0;
     }
diff --git a/providers/implementations/signature/ecdsa.c b/providers/implementations/signature/ecdsa.c
index 4f90032af3..8c4648106f 100644
--- a/providers/implementations/signature/ecdsa.c
+++ b/providers/implementations/signature/ecdsa.c
@@ -140,7 +140,7 @@ static int ecdsa_signverify_init(void *vctx, void *ec,
     ctx->operation = operation;
     if (!ecdsa_set_ctx_params(ctx, params))
         return 0;
-    return ossl_ec_check_key(ec, operation == EVP_PKEY_OP_SIGN);
+    return ossl_ec_check_key(ctx->libctx, ec, operation == EVP_PKEY_OP_SIGN);
 }
 
 static int ecdsa_sign_init(void *vctx, void *ec, const OSSL_PARAM params[])
@@ -225,7 +225,8 @@ static int ecdsa_setup_md(PROV_ECDSA_CTX *ctx, const char *mdname,
         return 0;
     }
     sha1_allowed = (ctx->operation != EVP_PKEY_OP_SIGN);
-    md_nid = ossl_digest_get_approved_nid_with_sha1(md, sha1_allowed);
+    md_nid = ossl_digest_get_approved_nid_with_sha1(ctx->libctx, md,
+                                                    sha1_allowed);
     if (md_nid == NID_undef) {
         ERR_raise_data(ERR_LIB_PROV, PROV_R_DIGEST_NOT_ALLOWED,
                        "digest=%s", mdname);
diff --git a/providers/implementations/signature/rsa.c b/providers/implementations/signature/rsa.c
index 96366a9a6b..16025bffc0 100644
--- a/providers/implementations/signature/rsa.c
+++ b/providers/implementations/signature/rsa.c
@@ -284,7 +284,8 @@ static int rsa_setup_md(PROV_RSA_CTX *ctx, const char *mdname,
     if (mdname != NULL) {
         EVP_MD *md = EVP_MD_fetch(ctx->libctx, mdname, mdprops);
         int sha1_allowed = (ctx->operation != EVP_PKEY_OP_SIGN);
-        int md_nid = ossl_digest_rsa_sign_get_md_nid(md, sha1_allowed);
+        int md_nid = ossl_digest_rsa_sign_get_md_nid(ctx->libctx, md,
+                                                     sha1_allowed);
         size_t mdname_len = strlen(mdname);
 
         if (md == NULL
@@ -343,7 +344,7 @@ static int rsa_setup_mgf1_md(PROV_RSA_CTX *ctx, const char *mdname,
         return 0;
     }
     /* The default for mgf1 is SHA1 - so allow SHA1 */
-    if ((mdnid = ossl_digest_rsa_sign_get_md_nid(md, 1)) == NID_undef
+    if ((mdnid = ossl_digest_rsa_sign_get_md_nid(ctx->libctx, md, 1)) == NID_undef
         || !rsa_check_padding(ctx, NULL, mdname, mdnid)) {
         if (mdnid == NID_undef)
             ERR_raise_data(ERR_LIB_PROV, PROV_R_DIGEST_NOT_ALLOWED,
@@ -377,7 +378,7 @@ static int rsa_signverify_init(void *vprsactx, void *vrsa,
     if (prsactx == NULL || vrsa == NULL)
         return 0;
 
-    if (!ossl_rsa_check_key(vrsa, operation))
+    if (!ossl_rsa_check_key(prsactx->libctx, vrsa, operation))
         return 0;
 
     if (!RSA_up_ref(vrsa))
diff --git a/providers/legacyprov.c b/providers/legacyprov.c
index f4e0bc9278..e3690e0559 100644
--- a/providers/legacyprov.c
+++ b/providers/legacyprov.c
@@ -32,10 +32,6 @@ OSSL_provider_init_fn ossl_legacy_provider_init;
 # define OSSL_provider_init ossl_legacy_provider_init
 #endif
 
-/* Functions provided by the core */
-static OSSL_FUNC_core_gettable_params_fn *c_gettable_params = NULL;
-static OSSL_FUNC_core_get_params_fn *c_get_params = NULL;
-
 /* Parameters we provide to the core */
 static const OSSL_PARAM legacy_param_types[] = {
     OSSL_PARAM_DEFN(OSSL_PROV_PARAM_NAME, OSSL_PARAM_UTF8_PTR, NULL, 0),
@@ -179,28 +175,12 @@ int OSSL_provider_init(const OSSL_CORE_HANDLE *handle,
                        const OSSL_DISPATCH **out,
                        void **provctx)
 {
-    OSSL_FUNC_core_get_libctx_fn *c_get_libctx = NULL;
     OSSL_LIB_CTX *libctx = NULL;
 
-    for (; in->function_id != 0; in++) {
-        switch (in->function_id) {
-        case OSSL_FUNC_CORE_GETTABLE_PARAMS:
-            c_gettable_params = OSSL_FUNC_core_gettable_params(in);
-            break;
-        case OSSL_FUNC_CORE_GET_PARAMS:
-            c_get_params = OSSL_FUNC_core_get_params(in);
-            break;
-        case OSSL_FUNC_CORE_GET_LIBCTX:
-            c_get_libctx = OSSL_FUNC_core_get_libctx(in);
-            break;
-        /* Just ignore anything we don't understand */
-        default:
-            break;
-        }
-    }
-
-    if (c_get_libctx == NULL)
-        return 0;
+    /*
+     * We do not need to use any up-calls provided by libcrypto, so we ignore
+     * the "in" dispatch table.
+     */
 
     if ((*provctx = ossl_prov_ctx_new()) == NULL
         || (libctx = OSSL_LIB_CTX_new()) == NULL) {


More information about the openssl-commits mailing list