Ensure mirroring of properties works for subsequent updates
authorMatt Caswell <matt@openssl.org>
Tue, 11 May 2021 15:50:27 +0000 (16:50 +0100)
committerMatt Caswell <matt@openssl.org>
Thu, 20 May 2021 08:35:41 +0000 (09:35 +0100)
If the global properties are updated after a provider with a child libctx
has already started we need to make sure those updates are mirrored in
that child.

Reviewed-by: Paul Dale <pauli@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/15242)

crypto/evp/evp_cnf.c
crypto/evp/evp_fetch.c
crypto/property/property.c
crypto/provider_child.c
include/internal/property.h
test/p_test.c
test/provider_test.c

index 145f52fe1d777e6a0922f0dfdf94df90eec4ddf3..c13652ca0f0e7f5656af167c58a20170baa6af68 100644 (file)
@@ -51,7 +51,7 @@ static int alg_module_init(CONF_IMODULE *md, const CONF *cnf)
                 return 0;
             }
         } else if (strcmp(oval->name, "default_properties") == 0) {
-            if (!evp_set_default_properties_int(cnf->libctx, oval->value, 0)) {
+            if (!evp_set_default_properties_int(cnf->libctx, oval->value, 0, 0)) {
                 ERR_raise(ERR_LIB_EVP, EVP_R_SET_DEFAULT_PROPERTY_FAILURE);
                 return 0;
             }
index 67e9ad878f8e58ff4a64889a292c40fa89b9316f..e71d827d4b898b75990e65a62532396d7d6857e5 100644 (file)
@@ -384,15 +384,28 @@ int evp_method_store_flush(OSSL_LIB_CTX *libctx)
 
 static int evp_set_parsed_default_properties(OSSL_LIB_CTX *libctx,
                                              OSSL_PROPERTY_LIST *def_prop,
-                                             int loadconfig)
+                                             int loadconfig,
+                                             int mirrored)
 {
     OSSL_METHOD_STORE *store = get_evp_method_store(libctx);
     OSSL_PROPERTY_LIST **plp = ossl_ctx_global_properties(libctx, loadconfig);
 
     if (plp != NULL && store != NULL) {
+#ifndef FIPS_MODULE
         char *propstr = NULL;
         size_t strsz;
 
+        if (mirrored) {
+            if (ossl_global_properties_no_mirrored(libctx))
+                return 0;
+        } else {
+            /*
+             * These properties have been explicitly set on this libctx, so
+             * don't allow any mirroring from a parent libctx.
+             */
+            ossl_global_properties_stop_mirroring(libctx);
+        }
+
         strsz = ossl_property_list_to_string(libctx, def_prop, NULL, 0);
         if (strsz > 0)
             propstr = OPENSSL_malloc(strsz);
@@ -406,10 +419,11 @@ static int evp_set_parsed_default_properties(OSSL_LIB_CTX *libctx,
             ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR);
             return 0;
         }
-        ossl_property_free(*plp);
-        *plp = def_prop;
         ossl_provider_default_props_update(libctx, propstr);
         OPENSSL_free(propstr);
+#endif
+        ossl_property_free(*plp);
+        *plp = def_prop;
         if (store != NULL)
             return ossl_method_store_flush_cache(store, 0);
     }
@@ -418,7 +432,7 @@ static int evp_set_parsed_default_properties(OSSL_LIB_CTX *libctx,
 }
 
 int evp_set_default_properties_int(OSSL_LIB_CTX *libctx, const char *propq,
-                                   int loadconfig)
+                                   int loadconfig, int mirrored)
 {
     OSSL_PROPERTY_LIST *pl = NULL;
 
@@ -426,7 +440,7 @@ int evp_set_default_properties_int(OSSL_LIB_CTX *libctx, const char *propq,
         ERR_raise(ERR_LIB_EVP, EVP_R_DEFAULT_QUERY_PARSE_ERROR);
         return 0;
     }
-    if (!evp_set_parsed_default_properties(libctx, pl, loadconfig)) {
+    if (!evp_set_parsed_default_properties(libctx, pl, loadconfig, mirrored)) {
         ossl_property_free(pl);
         return 0;
     }
@@ -435,7 +449,7 @@ int evp_set_default_properties_int(OSSL_LIB_CTX *libctx, const char *propq,
 
 int EVP_set_default_properties(OSSL_LIB_CTX *libctx, const char *propq)
 {
-    return evp_set_default_properties_int(libctx, propq, 1);
+    return evp_set_default_properties_int(libctx, propq, 1, 0);
 }
 
 static int evp_default_properties_merge(OSSL_LIB_CTX *libctx, const char *propq)
@@ -457,7 +471,7 @@ static int evp_default_properties_merge(OSSL_LIB_CTX *libctx, const char *propq)
         ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
         return 0;
     }
-    if (!evp_set_parsed_default_properties(libctx, pl2, 0)) {
+    if (!evp_set_parsed_default_properties(libctx, pl2, 0, 0)) {
         ossl_property_free(pl2);
         return 0;
     }
index da6bc84e27fab39cb6db40f3e8a73a510efae6fb..a769a7307e3c24a3885c0d032a2d4b791fd4b77e 100644 (file)
@@ -74,25 +74,31 @@ typedef struct {
 
 DEFINE_SPARSE_ARRAY_OF(ALGORITHM);
 
+typedef struct ossl_global_properties_st {
+    OSSL_PROPERTY_LIST *list;
+#ifndef FIPS_MODULE
+    unsigned int no_mirrored : 1;
+#endif
+} OSSL_GLOBAL_PROPERTIES;
+
 static void ossl_method_cache_flush(OSSL_METHOD_STORE *store, int nid);
 
 /* Global properties are stored per library context */
-static void ossl_ctx_global_properties_free(void *vstore)
+static void ossl_ctx_global_properties_free(void *vglobp)
 {
-    OSSL_PROPERTY_LIST **plp = vstore;
+    OSSL_GLOBAL_PROPERTIES *globp = vglobp;
 
-    if (plp != NULL) {
-        ossl_property_free(*plp);
-        OPENSSL_free(plp);
+    if (globp != NULL) {
+        ossl_property_free(globp->list);
+        OPENSSL_free(globp);
     }
 }
 
 static void *ossl_ctx_global_properties_new(OSSL_LIB_CTX *ctx)
 {
-    return OPENSSL_zalloc(sizeof(OSSL_PROPERTY_LIST **));
+    return OPENSSL_zalloc(sizeof(OSSL_GLOBAL_PROPERTIES));
 }
 
-
 static const OSSL_LIB_CTX_METHOD ossl_ctx_global_properties_method = {
     OSSL_LIB_CTX_METHOD_DEFAULT_PRIORITY,
     ossl_ctx_global_properties_new,
@@ -102,13 +108,37 @@ static const OSSL_LIB_CTX_METHOD ossl_ctx_global_properties_method = {
 OSSL_PROPERTY_LIST **ossl_ctx_global_properties(OSSL_LIB_CTX *libctx,
                                                 int loadconfig)
 {
+    OSSL_GLOBAL_PROPERTIES *globp;
+
 #ifndef FIPS_MODULE
     if (loadconfig && !OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CONFIG, NULL))
         return NULL;
 #endif
-    return ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_GLOBAL_PROPERTIES,
-                                 &ossl_ctx_global_properties_method);
+    globp = ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_GLOBAL_PROPERTIES,
+                                  &ossl_ctx_global_properties_method);
+
+    return &globp->list;
+}
+
+#ifndef FIPS_MODULE
+int ossl_global_properties_no_mirrored(OSSL_LIB_CTX *libctx)
+{
+    OSSL_GLOBAL_PROPERTIES *globp
+        = ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_GLOBAL_PROPERTIES,
+                                &ossl_ctx_global_properties_method);
+
+    return globp->no_mirrored ? 1 : 0;
+}
+
+void ossl_global_properties_stop_mirroring(OSSL_LIB_CTX *libctx)
+{
+    OSSL_GLOBAL_PROPERTIES *globp
+        = ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_GLOBAL_PROPERTIES,
+                                &ossl_ctx_global_properties_method);
+
+    globp->no_mirrored = 1;
 }
+#endif
 
 static int ossl_method_up_ref(METHOD *method)
 {
index e4d586bf7d2d0f299af22b4c7f1846eb6a4dc3f3..7ab161b795c20527153da726e92350d740afa0ff 100644 (file)
@@ -15,6 +15,7 @@
 #include <openssl/evp.h>
 #include "internal/provider.h"
 #include "internal/cryptlib.h"
+#include "crypto/evp.h"
 
 DEFINE_STACK_OF(OSSL_PROVIDER)
 
index 85f602d1e5c1aed74aca5ce30e52c4660ba8d521..856cd740ad794466a8bfbc6583641de3d9e33c9a 100644 (file)
@@ -68,4 +68,7 @@ size_t ossl_property_list_to_string(OSSL_LIB_CTX *ctx,
                                     const OSSL_PROPERTY_LIST *list, char *buf,
                                     size_t bufsize);
 
+int ossl_global_properties_no_mirrored(OSSL_LIB_CTX *libctx);
+void ossl_global_properties_stop_mirroring(OSSL_LIB_CTX *libctx);
+
 #endif
index d4e187f94abc8ee82488d3188a322416bdf8c9b8..80f0784dd9d5abd545934146f8cdfe940e532193 100644 (file)
@@ -183,6 +183,22 @@ static int p_get_params(void *provctx, OSSL_PARAM params[])
             } else {
                 ok = 0;
             }
+        } else if (strcmp(p->key, "stop-property-mirror") == 0) {
+            /*
+             * Setting the default properties explicitly should stop mirroring
+             * of properties from the parent libctx.
+             */
+            unsigned int stopsuccess = 0;
+
+#ifdef PROVIDER_INIT_FUNCTION_NAME
+            stopsuccess = EVP_set_default_properties(ctx->libctx, NULL);
+#endif
+            if (p->data_size >= sizeof(stopsuccess)) {
+                *(unsigned int *)p->data = stopsuccess;
+                p->return_size = sizeof(stopsuccess);
+            } else {
+                ok = 0;
+            }
         }
     }
     return ok;
index 79a1a375e8597278da52106f7cc32f9b1ccd1574..807b8fcf22dac33d5ed4110c37c185930d41965d 100644 (file)
@@ -26,6 +26,13 @@ static OSSL_PARAM digest_check[] = {
     { NULL, 0, NULL, 0, 0 }
 };
 
+static unsigned int stopsuccess = 0;
+static OSSL_PARAM stop_property_mirror[] = {
+    { "stop-property-mirror", OSSL_PARAM_UNSIGNED_INTEGER, &stopsuccess,
+      sizeof(stopsuccess) },
+    { NULL, 0, NULL, 0, 0 }
+};
+
 static int test_provider(OSSL_LIB_CTX **libctx, const char *name,
                          OSSL_PROVIDER *legacy)
 {
@@ -66,6 +73,19 @@ static int test_provider(OSSL_LIB_CTX **libctx, const char *name,
         if (!TEST_true(OSSL_PROVIDER_get_params(prov, digest_check))
                 || !TEST_true(digestsuccess))
             goto err;
+
+        /*
+         * Check that a provider can prevent property mirroring if it sets its
+         * own properties explicitly
+         */
+        if (!TEST_true(OSSL_PROVIDER_get_params(prov, stop_property_mirror))
+                || !TEST_true(stopsuccess))
+            goto err;
+        EVP_set_default_properties(*libctx, "fips=yes");
+        if (!TEST_true(OSSL_PROVIDER_get_params(prov, digest_check))
+                || !TEST_true(digestsuccess))
+            goto err;
+        EVP_set_default_properties(*libctx, "");
     }
     if (!TEST_true(OSSL_PROVIDER_get_params(prov, greeting_request))
             || !TEST_ptr(greeting = greeting_request[0].data)