[openssl] master update

Matt Caswell matt at openssl.org
Thu May 23 10:07:43 UTC 2019


The branch master has been updated
       via  b1eb3fd732adc9afaae730426f48bbfec17694d1 (commit)
       via  16da72a824eddebb7d85297bea868be3a6f43c0e (commit)
       via  319e518a5ae17fb8def2bd9209675acbaa6c22c2 (commit)
       via  3593266d1c924ea595a1074e78381890f964392c (commit)
      from  ecb0f148a94c9b0076240ca1d7904ab50a7dc9a4 (commit)


- Log -----------------------------------------------------------------
commit b1eb3fd732adc9afaae730426f48bbfec17694d1
Author: Matt Caswell <matt at openssl.org>
Date:   Tue May 21 16:25:24 2019 +0100

    Add more commentary about recursive Provider intialisation in the FIPS module
    
    In addition this commit ensures that the "provctx" value is defaulted to the current
    library context when we are recurively initialising the FIPS provider when already inside
    the FIPS module.
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/8728)

commit 16da72a824eddebb7d85297bea868be3a6f43c0e
Author: Matt Caswell <matt at openssl.org>
Date:   Fri Apr 19 10:31:18 2019 +0100

    Move where include path for providers/common/include gets specified
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/8728)

commit 319e518a5ae17fb8def2bd9209675acbaa6c22c2
Author: Matt Caswell <matt at openssl.org>
Date:   Mon May 13 06:41:06 2019 +0100

    Make some EVP code available from within the FIPS module
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/8728)

commit 3593266d1c924ea595a1074e78381890f964392c
Author: Matt Caswell <matt at openssl.org>
Date:   Wed Apr 10 15:01:40 2019 +0100

    Make core code available within the FIPS module
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/8728)

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

Summary of changes:
 build.info                     |   2 +-
 crypto/build.info              |   7 ++-
 crypto/context.c               |   2 +-
 crypto/evp/build.info          |   4 ++
 crypto/evp/digest.c            |  39 ++++++++++---
 crypto/evp/evp_enc.c           |  32 ++++++++---
 crypto/evp/evp_lib.c           |  25 ++++++---
 crypto/lhash/build.info        |   2 +
 crypto/property/build.info     |   2 +
 crypto/property/property.c     |   3 +
 crypto/provider_core.c         |  48 ++++++++++++++--
 crypto/provider_predefined.c   |   5 ++
 crypto/stack/build.info        |   1 +
 crypto/threads_pthread.c       |  12 ++--
 include/openssl/core_numbers.h |   7 +++
 providers/build.info           |   2 +
 providers/fips/fipsprov.c      | 122 +++++++++++++++++++++++++++++++++++++++++
 17 files changed, 280 insertions(+), 35 deletions(-)

diff --git a/build.info b/build.info
index ce5dfd0..a0ecb21 100644
--- a/build.info
+++ b/build.info
@@ -3,7 +3,7 @@
 SUBDIRS=crypto ssl apps test util tools fuzz engines providers
 
 LIBS=libcrypto libssl
-INCLUDE[libcrypto]=. crypto/include include providers/common/include
+INCLUDE[libcrypto]=. crypto/include include
 INCLUDE[libssl]=. include
 DEPEND[libssl]=libcrypto
 
diff --git a/crypto/build.info b/crypto/build.info
index 63913f4..db6d6af 100644
--- a/crypto/build.info
+++ b/crypto/build.info
@@ -12,6 +12,9 @@ LIBS=../libcrypto
 SOURCE[../libcrypto]=provider_core.c provider_predefined.c provider_conf.c \
         core_fetch.c core_namemap.c
 
+SOURCE[../providers/fips]=provider_core.c provider_predefined.c \
+        core_fetch.c core_namemap.c
+
 # Central utilities
 SOURCE[../libcrypto]=\
         cryptlib.c mem.c mem_dbg.c cversion.c info.c ex_data.c cpt_err.c \
@@ -23,7 +26,9 @@ SOURCE[../libcrypto]=\
 
 # FIPS module
 SOURCE[../providers/fips]=\
-        cryptlib.c mem.c mem_clr.c params.c bsearch.c
+        cryptlib.c mem.c mem_clr.c params.c bsearch.c ex_data.c o_str.c \
+        ctype.c threads_pthread.c threads_win.c threads_none.c context.c \
+        sparse_array.c
 
 
 DEPEND[cversion.o]=buildinf.h
diff --git a/crypto/context.c b/crypto/context.c
index be2d348..7a976c0 100644
--- a/crypto/context.c
+++ b/crypto/context.c
@@ -36,10 +36,10 @@ struct openssl_ctx_st {
 
 #ifndef FIPS_MODE
 static OPENSSL_CTX default_context_int;
-#endif
 
 /* Always points at default_context_int if it has been initialised */
 static OPENSSL_CTX *default_context = NULL;
+#endif
 
 static int context_init(OPENSSL_CTX *ctx)
 {
diff --git a/crypto/evp/build.info b/crypto/evp/build.info
index 23aa733..61e8880 100644
--- a/crypto/evp/build.info
+++ b/crypto/evp/build.info
@@ -20,6 +20,10 @@ SOURCE[../../libcrypto]=\
 SOURCE[../../libcrypto]=\
 	evp_fetch.c
 
+# FIPS Module
+SOURCE[../../providers/fips]=\
+        digest.c evp_enc.c evp_lib.c evp_fetch.c cmeth_lib.c
+
 INCLUDE[e_aes.o]=.. ../modes
 INCLUDE[e_aes_cbc_hmac_sha1.o]=../modes
 INCLUDE[e_aes_cbc_hmac_sha256.o]=../modes
diff --git a/crypto/evp/digest.c b/crypto/evp/digest.c
index dc50528..a1f0154 100644
--- a/crypto/evp/digest.c
+++ b/crypto/evp/digest.c
@@ -55,10 +55,14 @@ int EVP_MD_CTX_reset(EVP_MD_CTX *ctx)
      * pctx should be freed by the user of EVP_MD_CTX
      * if EVP_MD_CTX_FLAG_KEEP_PKEY_CTX is set
      */
+#ifndef FIPS_MODE
+    /* TODO(3.0): Temporarily no support for EVP_DigestSign* in FIPS module */
     if (!EVP_MD_CTX_test_flags(ctx, EVP_MD_CTX_FLAG_KEEP_PKEY_CTX))
         EVP_PKEY_CTX_free(ctx->pctx);
-#ifndef OPENSSL_NO_ENGINE
+
+# ifndef OPENSSL_NO_ENGINE
     ENGINE_finish(ctx->engine);
+# endif
 #endif
     OPENSSL_cleanse(ctx, sizeof(*ctx));
 
@@ -102,8 +106,9 @@ int EVP_DigestInit(EVP_MD_CTX *ctx, const EVP_MD *type)
 
 int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl)
 {
-    EVP_MD *provmd;
+#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODE)
     ENGINE *tmpimpl = NULL;
+#endif
 
     EVP_MD_CTX_clear_flags(ctx, EVP_MD_CTX_FLAG_CLEANED);
 
@@ -111,7 +116,7 @@ int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl)
         ctx->reqdigest = type;
 
     /* TODO(3.0): Legacy work around code below. Remove this */
-#ifndef OPENSSL_NO_ENGINE
+#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODE)
     /*
      * Whether it's nice or not, "Inits" can be used on "Final"'d contexts so
      * this context may already have an ENGINE! Try to avoid releasing the
@@ -132,7 +137,9 @@ int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl)
      */
     if (ctx->engine != NULL
             || impl != NULL
+#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODE)
             || tmpimpl != NULL
+#endif
             || ctx->pctx != NULL
             || (ctx->flags & EVP_MD_CTX_FLAG_NO_INIT) != 0) {
         if (ctx->digest == ctx->fetched_digest)
@@ -160,7 +167,13 @@ int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl)
     /* TODO(3.0): Start of non-legacy code below */
 
     if (type->prov == NULL) {
-        provmd = EVP_MD_fetch(NULL, OBJ_nid2sn(type->type), "");
+#ifdef FIPS_MODE
+        /* We only do explict fetches inside the FIPS module */
+        EVPerr(EVP_F_EVP_DIGESTINIT_EX, EVP_R_INITIALIZATION_ERROR);
+        return 0;
+#else
+        EVP_MD *provmd = EVP_MD_fetch(NULL, OBJ_nid2sn(type->type), "");
+
         if (provmd == NULL) {
             EVPerr(EVP_F_EVP_DIGESTINIT_EX, EVP_R_INITIALIZATION_ERROR);
             return 0;
@@ -168,6 +181,7 @@ int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl)
         type = provmd;
         EVP_MD_meth_free(ctx->fetched_digest);
         ctx->fetched_digest = provmd;
+#endif
     }
 
     ctx->digest = type;
@@ -189,7 +203,7 @@ int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl)
     /* TODO(3.0): Remove legacy code below */
  legacy:
 
-#ifndef OPENSSL_NO_ENGINE
+#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODE)
     if (type) {
         /*
          * Ensure an ENGINE left lying around from last time is cleared (the
@@ -247,16 +261,19 @@ int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl)
             }
         }
     }
-#ifndef OPENSSL_NO_ENGINE
+#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODE)
  skip_to_init:
 #endif
-    if (ctx->pctx) {
+#ifndef FIPS_MODE
+    /* TODO(3.0): Temporarily no support for EVP_DigestSign* in FIPS module */
+    if (ctx->pctx != NULL) {
         int r;
         r = EVP_PKEY_CTX_ctrl(ctx->pctx, -1, EVP_PKEY_OP_TYPE_SIG,
                               EVP_PKEY_CTRL_DIGESTINIT, 0, ctx);
         if (r <= 0 && (r != -2))
             return 0;
     }
+#endif
     if (ctx->flags & EVP_MD_CTX_FLAG_NO_INIT)
         return 1;
     return ctx->digest->init(ctx);
@@ -397,6 +414,8 @@ int EVP_MD_CTX_copy_ex(EVP_MD_CTX *out, const EVP_MD_CTX *in)
 
     /* copied EVP_MD_CTX should free the copied EVP_PKEY_CTX */
     EVP_MD_CTX_clear_flags(out, EVP_MD_CTX_FLAG_KEEP_PKEY_CTX);
+#ifndef FIPS_MODE
+    /* TODO(3.0): Temporarily no support for EVP_DigestSign* in FIPS module */
     if (in->pctx != NULL) {
         out->pctx = EVP_PKEY_CTX_dup(in->pctx);
         if (out->pctx == NULL) {
@@ -405,12 +424,13 @@ int EVP_MD_CTX_copy_ex(EVP_MD_CTX *out, const EVP_MD_CTX *in)
             return 0;
         }
     }
+#endif
 
     return 1;
 
     /* TODO(3.0): Remove legacy code below */
  legacy:
-#ifndef OPENSSL_NO_ENGINE
+#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODE)
     /* Make sure it's safe to copy a digest context using an ENGINE */
     if (in->engine && !ENGINE_init(in->engine)) {
         EVPerr(EVP_F_EVP_MD_CTX_COPY_EX, ERR_R_ENGINE_LIB);
@@ -451,6 +471,8 @@ int EVP_MD_CTX_copy_ex(EVP_MD_CTX *out, const EVP_MD_CTX *in)
 
     out->update = in->update;
 
+#ifndef FIPS_MODE
+    /* TODO(3.0): Temporarily no support for EVP_DigestSign* in FIPS module */
     if (in->pctx) {
         out->pctx = EVP_PKEY_CTX_dup(in->pctx);
         if (!out->pctx) {
@@ -458,6 +480,7 @@ int EVP_MD_CTX_copy_ex(EVP_MD_CTX *out, const EVP_MD_CTX *in)
             return 0;
         }
     }
+#endif
 
     if (out->digest->copy)
         return out->digest->copy(out, in);
diff --git a/crypto/evp/evp_enc.c b/crypto/evp/evp_enc.c
index d0566ad..b3e97d0 100644
--- a/crypto/evp/evp_enc.c
+++ b/crypto/evp/evp_enc.c
@@ -51,7 +51,7 @@ int EVP_CIPHER_CTX_reset(EVP_CIPHER_CTX *ctx)
             OPENSSL_cleanse(ctx->cipher_data, ctx->cipher->ctx_size);
     }
     OPENSSL_free(ctx->cipher_data);
-#ifndef OPENSSL_NO_ENGINE
+#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODE)
     ENGINE_finish(ctx->engine);
 #endif
     memset(ctx, 0, sizeof(*ctx));
@@ -81,8 +81,9 @@ int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
                       ENGINE *impl, const unsigned char *key,
                       const unsigned char *iv, int enc)
 {
-    EVP_CIPHER *provciph = NULL;
+#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODE)
     ENGINE *tmpimpl = NULL;
+#endif
     const EVP_CIPHER *tmpcipher;
 
     /*
@@ -105,7 +106,7 @@ int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
 
     /* TODO(3.0): Legacy work around code below. Remove this */
 
-#ifndef OPENSSL_NO_ENGINE
+#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODE)
     /*
      * Whether it's nice or not, "Inits" can be used on "Final"'d contexts so
      * this context may already have an ENGINE! Try to avoid releasing the
@@ -126,8 +127,10 @@ int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
      * If there are engines involved then we should use legacy handling for now.
      */
     if (ctx->engine != NULL
-            || impl != NULL
-            || tmpimpl != NULL) {
+#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODE)
+            || tmpimpl != NULL
+#endif
+            || impl != NULL) {
         if (ctx->cipher == ctx->fetched_cipher)
             ctx->cipher = NULL;
         EVP_CIPHER_meth_free(ctx->fetched_cipher);
@@ -194,7 +197,14 @@ int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
         cipher = ctx->cipher;
 
     if (cipher->prov == NULL) {
-        provciph = EVP_CIPHER_fetch(NULL, OBJ_nid2sn(cipher->nid), "");
+#ifdef FIPS_MODE
+        /* We only do explict fetches inside the FIPS module */
+        EVPerr(EVP_F_EVP_CIPHERINIT_EX, EVP_R_INITIALIZATION_ERROR);
+        return 0;
+#else
+        EVP_CIPHER *provciph =
+            EVP_CIPHER_fetch(NULL, OBJ_nid2sn(cipher->nid), "");
+
         if (provciph == NULL) {
             EVPerr(EVP_F_EVP_CIPHERINIT_EX, EVP_R_INITIALIZATION_ERROR);
             return 0;
@@ -202,6 +212,7 @@ int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
         cipher = provciph;
         EVP_CIPHER_meth_free(ctx->fetched_cipher);
         ctx->fetched_cipher = provciph;
+#endif
     }
 
     ctx->cipher = cipher;
@@ -279,7 +290,7 @@ int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
             ctx->encrypt = enc;
             ctx->flags = flags;
         }
-#ifndef OPENSSL_NO_ENGINE
+#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODE)
         if (impl != NULL) {
             if (!ENGINE_init(impl)) {
                 EVPerr(EVP_F_EVP_CIPHERINIT_EX, EVP_R_INITIALIZATION_ERROR);
@@ -335,7 +346,7 @@ int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
             }
         }
     }
-#ifndef OPENSSL_NO_ENGINE
+#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODE)
  skip_to_init:
 #endif
     if (ctx->cipher == NULL)
@@ -966,6 +977,8 @@ int EVP_CIPHER_CTX_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr)
     return ret;
 }
 
+#if !defined(FIPS_MODE)
+/* TODO(3.0): No support for RAND yet in the FIPS module */
 int EVP_CIPHER_CTX_rand_key(EVP_CIPHER_CTX *ctx, unsigned char *key)
 {
     int kl;
@@ -976,6 +989,7 @@ int EVP_CIPHER_CTX_rand_key(EVP_CIPHER_CTX *ctx, unsigned char *key)
         return 0;
     return 1;
 }
+#endif
 
 int EVP_CIPHER_CTX_copy(EVP_CIPHER_CTX *out, const EVP_CIPHER_CTX *in)
 {
@@ -1013,7 +1027,7 @@ int EVP_CIPHER_CTX_copy(EVP_CIPHER_CTX *out, const EVP_CIPHER_CTX *in)
     /* TODO(3.0): Remove legacy code below */
  legacy:
 
-#ifndef OPENSSL_NO_ENGINE
+#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODE)
     /* Make sure it's safe to copy a cipher context using an ENGINE */
     if (in->engine && !ENGINE_init(in->engine)) {
         EVPerr(EVP_F_EVP_CIPHER_CTX_COPY, ERR_R_ENGINE_LIB);
diff --git a/crypto/evp/evp_lib.c b/crypto/evp/evp_lib.c
index 34b9382..faaa69d 100644
--- a/crypto/evp/evp_lib.c
+++ b/crypto/evp/evp_lib.c
@@ -17,6 +17,7 @@
 #include "internal/provider.h"
 #include "evp_locl.h"
 
+#if !defined(FIPS_MODE)
 int EVP_CIPHER_param_to_asn1(EVP_CIPHER_CTX *c, ASN1_TYPE *type)
 {
     int ret;
@@ -146,12 +147,12 @@ int EVP_CIPHER_set_asn1_iv(EVP_CIPHER_CTX *c, ASN1_TYPE *type)
     }
     return i;
 }
+#endif /* !defined(FIPS_MODE) */
 
 /* Convert the various cipher NIDs and dummies to a proper OID NID */
 int EVP_CIPHER_type(const EVP_CIPHER *ctx)
 {
     int nid;
-    ASN1_OBJECT *otmp;
     nid = EVP_CIPHER_nid(ctx);
 
     switch (nid) {
@@ -198,12 +199,19 @@ int EVP_CIPHER_type(const EVP_CIPHER *ctx)
         return NID_des_cfb64;
 
     default:
-        /* Check it has an OID and it is valid */
-        otmp = OBJ_nid2obj(nid);
-        if (OBJ_get0_data(otmp) == NULL)
-            nid = NID_undef;
-        ASN1_OBJECT_free(otmp);
-        return nid;
+#ifdef FIPS_MODE
+        return NID_undef;
+#else
+        {
+            /* Check it has an OID and it is valid */
+            ASN1_OBJECT *otmp = OBJ_nid2obj(nid);
+
+            if (OBJ_get0_data(otmp) == NULL)
+                nid = NID_undef;
+            ASN1_OBJECT_free(otmp);
+            return nid;
+        }
+#endif
     }
 }
 
@@ -596,6 +604,8 @@ EVP_PKEY_CTX *EVP_MD_CTX_pkey_ctx(const EVP_MD_CTX *ctx)
     return ctx->pctx;
 }
 
+#if !defined(FIPS_MODE)
+/* TODO(3.0): EVP_DigestSign* not yet supported in FIPS module */
 void EVP_MD_CTX_set_pkey_ctx(EVP_MD_CTX *ctx, EVP_PKEY_CTX *pctx)
 {
     /*
@@ -614,6 +624,7 @@ void EVP_MD_CTX_set_pkey_ctx(EVP_MD_CTX *ctx, EVP_PKEY_CTX *pctx)
         EVP_MD_CTX_clear_flags(ctx, EVP_MD_CTX_FLAG_KEEP_PKEY_CTX);
     }
 }
+#endif /* !defined(FIPS_MODE) */
 
 void *EVP_MD_CTX_md_data(const EVP_MD_CTX *ctx)
 {
diff --git a/crypto/lhash/build.info b/crypto/lhash/build.info
index 30797f2..0aa12a1 100644
--- a/crypto/lhash/build.info
+++ b/crypto/lhash/build.info
@@ -1,3 +1,5 @@
 LIBS=../../libcrypto
 SOURCE[../../libcrypto]=\
         lhash.c lh_stats.c
+SOURCE[../../providers/fips]=\
+        lhash.c
diff --git a/crypto/property/build.info b/crypto/property/build.info
index 3a86b6e..3bdf307 100644
--- a/crypto/property/build.info
+++ b/crypto/property/build.info
@@ -1,3 +1,5 @@
 LIBS=../../libcrypto
 SOURCE[../../libcrypto]=property_string.c property_parse.c property.c \
                         property_err.c defn_cache.c
+SOURCE[../../providers/fips]=\
+    property_string.c property_parse.c property.c defn_cache.c
diff --git a/crypto/property/property.c b/crypto/property/property.c
index 9dd8f6a..4c328ff 100644
--- a/crypto/property/property.c
+++ b/crypto/property/property.c
@@ -391,6 +391,8 @@ IMPLEMENT_LHASH_DOALL_ARG(QUERY, IMPL_CACHE_FLUSH);
  */
 static void impl_cache_flush_cache(QUERY *c, IMPL_CACHE_FLUSH *state)
 {
+#if !defined(FIPS_MODE)
+/* TODO(3.0): No RAND_bytes yet in FIPS module. Add this back when available */
     OSSL_METHOD_STORE *store = state->store;
     unsigned int n;
 
@@ -404,6 +406,7 @@ static void impl_cache_flush_cache(QUERY *c, IMPL_CACHE_FLUSH *state)
         OPENSSL_free(lh_QUERY_delete(state->cache, c));
     else
         state->nelem++;
+#endif /* !defined(FIPS_MODE) */
 }
 
 static void impl_cache_flush_one_alg(ossl_uintmax_t idx, ALGORITHM *alg,
diff --git a/crypto/provider_core.c b/crypto/provider_core.c
index 36af527..d17ff93 100644
--- a/crypto/provider_core.c
+++ b/crypto/provider_core.c
@@ -275,7 +275,9 @@ void ossl_provider_free(OSSL_PROVIDER *prov)
          * the store.  All we have to do here is clean it out.
          */
         if (ref == 0) {
+#ifndef FIPS_MODE
             DSO_free(prov->module);
+#endif
             OPENSSL_free(prov->name);
             OPENSSL_free(prov->path);
             sk_INFOPAIR_pop_free(prov->parameters, free_infopair);
@@ -338,9 +340,11 @@ static const OSSL_DISPATCH *core_dispatch; /* Define further down */
 /*
  * Internal version that doesn't affect the store flags, and thereby avoid
  * locking.  Direct callers must remember to set the store flags when
- * appropriate
+ * appropriate. The libctx parameter is only necessary when FIPS_MODE is set
+ * (i.e. we are being called from inside the FIPS module) - it is ignored for
+ * other uses.
  */
-static int provider_activate(OSSL_PROVIDER *prov)
+static int provider_activate(OSSL_PROVIDER *prov, OPENSSL_CTX *libctx)
 {
     const OSSL_DISPATCH *provider_dispatch = NULL;
 
@@ -352,6 +356,9 @@ static int provider_activate(OSSL_PROVIDER *prov)
      * a loadable module.
      */
     if (prov->init_function == NULL) {
+#ifdef FIPS_MODE
+        return 0;
+#else
         if (prov->module == NULL) {
             char *allocated_path = NULL;
             const char *module_path = NULL;
@@ -389,15 +396,38 @@ static int provider_activate(OSSL_PROVIDER *prov)
         if (prov->module != NULL)
             prov->init_function = (OSSL_provider_init_fn *)
                 DSO_bind_func(prov->module, "OSSL_provider_init");
+#endif
     }
 
+    /*
+     * We call the initialise function for the provider.
+     *
+     * If FIPS_MODE is defined then we are inside the FIPS module and are about
+     * to recursively initialise ourselves. We need to do this so that we can
+     * get all the provider callback functions set up in order for us to be able
+     * to make EVP calls from within the FIPS module itself. Only algorithms
+     * from the FIPS module itself are available via the FIPS module EVP
+     * interface, i.e. we only ever have one provider available inside the FIPS
+     * module - the FIPS provider itself.
+     *
+     * For modules in general we cannot know what value will be used for the
+     * provctx - it is a "black box". But for the FIPS module we know that the
+     * provctx is really a library context. We default the provctx value to the
+     * same library context as was used for the EVP call that caused this call
+     * to "provider_activate".
+     */
+#ifdef FIPS_MODE
+    prov->provctx = libctx;
+#endif
     if (prov->init_function == NULL
         || !prov->init_function(prov, core_dispatch, &provider_dispatch,
                                 &prov->provctx)) {
         CRYPTOerr(CRYPTO_F_PROVIDER_ACTIVATE, ERR_R_INIT_FAIL);
         ERR_add_error_data(2, "name=", prov->name);
+#ifndef FIPS_MODE
         DSO_free(prov->module);
         prov->module = NULL;
+#endif
         return 0;
     }
 
@@ -430,7 +460,7 @@ static int provider_activate(OSSL_PROVIDER *prov)
 
 int ossl_provider_activate(OSSL_PROVIDER *prov)
 {
-    if (provider_activate(prov)) {
+    if (provider_activate(prov, NULL)) {
         CRYPTO_THREAD_write_lock(prov->store->lock);
         prov->store->use_fallbacks = 0;
         CRYPTO_THREAD_unlock(prov->store->lock);
@@ -507,7 +537,7 @@ int ossl_provider_forall_loaded(OPENSSL_CTX *ctx,
                  */
                 if (prov->flag_fallback) {
                     activated_fallback_count++;
-                    provider_activate(prov);
+                    provider_activate(prov, ctx);
                 }
             }
 
@@ -557,13 +587,21 @@ const DSO *ossl_provider_dso(OSSL_PROVIDER *prov)
 
 const char *ossl_provider_module_name(OSSL_PROVIDER *prov)
 {
+#ifdef FIPS_MODE
+    return NULL;
+#else
     return DSO_get_filename(prov->module);
+#endif
 }
 
 const char *ossl_provider_module_path(OSSL_PROVIDER *prov)
 {
+#ifdef FIPS_MODE
+    return NULL;
+#else
     /* FIXME: Ensure it's a full path */
     return DSO_get_filename(prov->module);
+#endif
 }
 
 /* Wrappers around calls to the provider */
@@ -643,6 +681,8 @@ static int core_get_params(const OSSL_PROVIDER *prov, const OSSL_PARAM params[])
 static const OSSL_DISPATCH core_dispatch_[] = {
     { OSSL_FUNC_CORE_GET_PARAM_TYPES, (void (*)(void))core_get_param_types },
     { OSSL_FUNC_CORE_GET_PARAMS, (void (*)(void))core_get_params },
+    { OSSL_FUNC_CORE_PUT_ERROR, (void (*)(void))ERR_put_error },
+    { OSSL_FUNC_CORE_ADD_ERROR_VDATA, (void (*)(void))ERR_add_error_vdata },
     { 0, NULL }
 };
 static const OSSL_DISPATCH *core_dispatch = core_dispatch_;
diff --git a/crypto/provider_predefined.c b/crypto/provider_predefined.c
index d14cd5b..d1423b1 100644
--- a/crypto/provider_predefined.c
+++ b/crypto/provider_predefined.c
@@ -11,8 +11,13 @@
 #include "provider_local.h"
 
 OSSL_provider_init_fn ossl_default_provider_init;
+OSSL_provider_init_fn fips_intern_provider_init;
 
 const struct predefined_providers_st predefined_providers[] = {
+#ifdef FIPS_MODE
+    { "fips", fips_intern_provider_init, 1 },
+#else
     { "default", ossl_default_provider_init, 1 },
+#endif
     { NULL, NULL, 0 }
 };
diff --git a/crypto/stack/build.info b/crypto/stack/build.info
index e587021..e4183e0 100644
--- a/crypto/stack/build.info
+++ b/crypto/stack/build.info
@@ -1,2 +1,3 @@
 LIBS=../../libcrypto
 SOURCE[../../libcrypto]=stack.c
+SOURCE[../../providers/fips]=stack.c
diff --git a/crypto/threads_pthread.c b/crypto/threads_pthread.c
index 0a6c903..0d351ca 100644
--- a/crypto/threads_pthread.c
+++ b/crypto/threads_pthread.c
@@ -175,7 +175,10 @@ int CRYPTO_atomic_add(int *val, int amount, int *ret, CRYPTO_RWLOCK *lock)
     return 1;
 }
 
-# ifdef OPENSSL_SYS_UNIX
+# ifndef FIPS_MODE
+/* TODO(3.0): No fork protection in FIPS module yet! */
+
+#  ifdef OPENSSL_SYS_UNIX
 static pthread_once_t fork_once_control = PTHREAD_ONCE_INIT;
 
 static void fork_once_func(void)
@@ -183,14 +186,15 @@ static void fork_once_func(void)
     pthread_atfork(OPENSSL_fork_prepare,
                    OPENSSL_fork_parent, OPENSSL_fork_child);
 }
-# endif
+#  endif
 
 int openssl_init_fork_handlers(void)
 {
-# ifdef OPENSSL_SYS_UNIX
+#  ifdef OPENSSL_SYS_UNIX
     if (pthread_once(&fork_once_control, fork_once_func) == 0)
         return 1;
-# endif
+#  endif
     return 0;
 }
+# endif /* FIPS_MODE */
 #endif
diff --git a/include/openssl/core_numbers.h b/include/openssl/core_numbers.h
index 8ce00c3..8d026f4 100644
--- a/include/openssl/core_numbers.h
+++ b/include/openssl/core_numbers.h
@@ -10,6 +10,7 @@
 #ifndef OSSL_CORE_NUMBERS_H
 # define OSSL_CORE_NUMBERS_H
 
+# include <stdarg.h>
 # include <openssl/core.h>
 
 # ifdef __cplusplus
@@ -57,6 +58,12 @@ OSSL_CORE_MAKE_FUNC(const OSSL_ITEM *,
 # define OSSL_FUNC_CORE_GET_PARAMS             2
 OSSL_CORE_MAKE_FUNC(int,core_get_params,(const OSSL_PROVIDER *prov,
                                          const OSSL_PARAM params[]))
+# define OSSL_FUNC_CORE_PUT_ERROR              3
+OSSL_CORE_MAKE_FUNC(void,core_put_error,(int lib, int func, int reason,
+                                         const char *file, int line))
+# define OSSL_FUNC_CORE_ADD_ERROR_VDATA        4
+OSSL_CORE_MAKE_FUNC(void,core_add_error_vdata,(int num, va_list args))
+
 
 /* Functions provided by the provider to the Core, reserved numbers 1024-1535 */
 # define OSSL_FUNC_PROVIDER_TEARDOWN         1024
diff --git a/providers/build.info b/providers/build.info
index ef107a7..f379f74 100644
--- a/providers/build.info
+++ b/providers/build.info
@@ -1,5 +1,7 @@
 SUBDIRS=common default
 
+INCLUDE[../libcrypto]=common/include
+
 IF[{- !$disabled{fips} -}]
   SUBDIRS=fips
   MODULES=fips
diff --git a/providers/fips/fipsprov.c b/providers/fips/fipsprov.c
index 1b83163..7842f90 100644
--- a/providers/fips/fipsprov.c
+++ b/providers/fips/fipsprov.c
@@ -13,10 +13,19 @@
 #include <openssl/core_numbers.h>
 #include <openssl/core_names.h>
 #include <openssl/params.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+/* TODO(3.0): Needed for dummy_evp_call(). To be removed */
+#include <openssl/sha.h>
+#include "internal/cryptlib.h"
+#include "internal/property.h"
+#include "internal/evp_int.h"
 
 /* Functions provided by the core */
 static OSSL_core_get_param_types_fn *c_get_param_types = NULL;
 static OSSL_core_get_params_fn *c_get_params = NULL;
+static OSSL_core_put_error_fn *c_put_error = NULL;
+static OSSL_core_add_error_vdata_fn *c_add_error_vdata = NULL;
 
 /* Parameters we provide to the core */
 static const OSSL_ITEM fips_param_types[] = {
@@ -26,6 +35,40 @@ static const OSSL_ITEM fips_param_types[] = {
     { 0, NULL }
 };
 
+/* TODO(3.0): To be removed */
+static int dummy_evp_call(OPENSSL_CTX *libctx)
+{
+    EVP_MD_CTX *ctx = EVP_MD_CTX_new();
+    EVP_MD *sha256 = EVP_MD_fetch(libctx, "SHA256", NULL);
+    char msg[] = "Hello World!";
+    const unsigned char exptd[] = {
+        0x7f, 0x83, 0xb1, 0x65, 0x7f, 0xf1, 0xfc, 0x53, 0xb9, 0x2d, 0xc1, 0x81,
+        0x48, 0xa1, 0xd6, 0x5d, 0xfc, 0x2d, 0x4b, 0x1f, 0xa3, 0xd6, 0x77, 0x28,
+        0x4a, 0xdd, 0xd2, 0x00, 0x12, 0x6d, 0x90, 0x69
+    };
+    unsigned int dgstlen = 0;
+    unsigned char dgst[SHA256_DIGEST_LENGTH];
+    int ret = 0;
+
+    if (ctx == NULL || sha256 == NULL)
+        goto err;
+
+    if (!EVP_DigestInit_ex(ctx, sha256, NULL))
+        goto err;
+    if (!EVP_DigestUpdate(ctx, msg, sizeof(msg) - 1))
+        goto err;
+    if (!EVP_DigestFinal(ctx, dgst, &dgstlen))
+        goto err;
+    if (dgstlen != sizeof(exptd) || memcmp(dgst, exptd, sizeof(exptd)) != 0)
+        goto err;
+
+    ret = 1;
+ err:
+    EVP_MD_CTX_free(ctx);
+    EVP_MD_meth_free(sha256);
+    return ret;
+}
+
 static const OSSL_ITEM *fips_get_param_types(const OSSL_PROVIDER *prov)
 {
     return fips_param_types;
@@ -70,17 +113,31 @@ static const OSSL_ALGORITHM *fips_query(OSSL_PROVIDER *prov,
 
 /* Functions we provide to the core */
 static const OSSL_DISPATCH fips_dispatch_table[] = {
+    /*
+     * To release our resources we just need to free the OPENSSL_CTX so we just
+     * use OPENSSL_CTX_free directly as our teardown function
+     */
+    { OSSL_FUNC_PROVIDER_TEARDOWN, (void (*)(void))OPENSSL_CTX_free },
     { OSSL_FUNC_PROVIDER_GET_PARAM_TYPES, (void (*)(void))fips_get_param_types },
     { OSSL_FUNC_PROVIDER_GET_PARAMS, (void (*)(void))fips_get_params },
     { OSSL_FUNC_PROVIDER_QUERY_OPERATION, (void (*)(void))fips_query },
     { 0, NULL }
 };
 
+/* Functions we provide to ourself */
+static const OSSL_DISPATCH intern_dispatch_table[] = {
+    { OSSL_FUNC_PROVIDER_QUERY_OPERATION, (void (*)(void))fips_query },
+    { 0, NULL }
+};
+
+
 int OSSL_provider_init(const OSSL_PROVIDER *provider,
                        const OSSL_DISPATCH *in,
                        const OSSL_DISPATCH **out,
                        void **provctx)
 {
+    OPENSSL_CTX *ctx;
+
     for (; in->function_id != 0; in++) {
         switch (in->function_id) {
         case OSSL_FUNC_CORE_GET_PARAM_TYPES:
@@ -89,12 +146,77 @@ int OSSL_provider_init(const OSSL_PROVIDER *provider,
         case OSSL_FUNC_CORE_GET_PARAMS:
             c_get_params = OSSL_get_core_get_params(in);
             break;
+        case OSSL_FUNC_CORE_PUT_ERROR:
+            c_put_error = OSSL_get_core_put_error(in);
+            break;
+        case OSSL_FUNC_CORE_ADD_ERROR_VDATA:
+            c_add_error_vdata = OSSL_get_core_add_error_vdata(in);
+            break;
         /* Just ignore anything we don't understand */
         default:
             break;
         }
     }
 
+    ctx = OPENSSL_CTX_new();
+    if (ctx == NULL)
+        return 0;
+
+    /*
+     * TODO(3.0): Remove me. This is just a dummy call to demonstrate making
+     * EVP calls from within the FIPS module.
+     */
+    if (!dummy_evp_call(ctx)) {
+        OPENSSL_CTX_free(ctx);
+        return 0;
+    }
+
     *out = fips_dispatch_table;
+    *provctx = ctx;
     return 1;
 }
+
+/*
+ * The internal init function used when the FIPS module uses EVP to call
+ * another algorithm also in the FIPS module. This is a recursive call that has
+ * been made from within the FIPS module itself. Normally we are responsible for
+ * providing our own provctx value, but in this recursive case it has been
+ * pre-populated for us with the same library context that was used in the EVP
+ * call that initiated this recursive call - so we don't need to do anything
+ * further with that parameter. This only works because we *know* in the core
+ * code that the FIPS module uses a library context for its provctx. This is
+ * not generally true for all providers.
+ */
+OSSL_provider_init_fn fips_intern_provider_init;
+int fips_intern_provider_init(const OSSL_PROVIDER *provider,
+                              const OSSL_DISPATCH *in,
+                              const OSSL_DISPATCH **out,
+                              void **provctx)
+{
+    *out = intern_dispatch_table;
+    return 1;
+}
+
+void ERR_put_error(int lib, int func, int reason, const char *file, int line)
+{
+    /*
+     * TODO(3.0): This works for the FIPS module because we're going to be
+     * using lib/func/reason codes that libcrypto already knows about. This
+     * won't work for third party providers that have their own error mechanisms,
+     * so we'll need to come up with something else for them.
+     */
+    c_put_error(lib, func, reason, file, line);
+}
+
+void ERR_add_error_data(int num, ...)
+{
+    va_list args;
+    va_start(args, num);
+    ERR_add_error_vdata(num, args);
+    va_end(args);
+}
+
+void ERR_add_error_vdata(int num, va_list args)
+{
+    c_add_error_vdata(num, args);
+}


More information about the openssl-commits mailing list