Add more commentary about recursive Provider intialisation in the FIPS module
authorMatt Caswell <matt@openssl.org>
Tue, 21 May 2019 15:25:24 +0000 (16:25 +0100)
committerMatt Caswell <matt@openssl.org>
Thu, 23 May 2019 10:02:19 +0000 (11:02 +0100)
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@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/8728)

crypto/provider_core.c
providers/fips/fipsprov.c

index 36692b6..d17ff93 100644 (file)
@@ -340,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;
 
@@ -397,6 +399,26 @@ static int provider_activate(OSSL_PROVIDER *prov)
 #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)) {
@@ -438,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);
@@ -515,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);
                 }
             }
 
index 801a9fd..7842f90 100644 (file)
@@ -178,7 +178,14 @@ int OSSL_provider_init(const OSSL_PROVIDER *provider,
 
 /*
  * The internal init function used when the FIPS module uses EVP to call
- * another algorithm also in the FIPS module.
+ * 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,