From b1c053acdaaee5e653949932f9999370edfc64db Mon Sep 17 00:00:00 2001 From: Matt Caswell Date: Tue, 11 May 2021 16:50:27 +0100 Subject: Ensure mirroring of properties works for subsequent updates 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 (Merged from https://github.com/openssl/openssl/pull/15242) --- crypto/evp/evp_cnf.c | 2 +- crypto/evp/evp_fetch.c | 28 +++++++++++++++++++------- crypto/property/property.c | 48 ++++++++++++++++++++++++++++++++++++--------- crypto/provider_child.c | 1 + include/internal/property.h | 3 +++ test/p_test.c | 16 +++++++++++++++ test/provider_test.c | 20 +++++++++++++++++++ 7 files changed, 101 insertions(+), 17 deletions(-) diff --git a/crypto/evp/evp_cnf.c b/crypto/evp/evp_cnf.c index 145f52fe1d..c13652ca0f 100644 --- a/crypto/evp/evp_cnf.c +++ b/crypto/evp/evp_cnf.c @@ -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; } diff --git a/crypto/evp/evp_fetch.c b/crypto/evp/evp_fetch.c index 67e9ad878f..e71d827d4b 100644 --- a/crypto/evp/evp_fetch.c +++ b/crypto/evp/evp_fetch.c @@ -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; } diff --git a/crypto/property/property.c b/crypto/property/property.c index da6bc84e27..a769a7307e 100644 --- a/crypto/property/property.c +++ b/crypto/property/property.c @@ -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) { diff --git a/crypto/provider_child.c b/crypto/provider_child.c index e4d586bf7d..7ab161b795 100644 --- a/crypto/provider_child.c +++ b/crypto/provider_child.c @@ -15,6 +15,7 @@ #include #include "internal/provider.h" #include "internal/cryptlib.h" +#include "crypto/evp.h" DEFINE_STACK_OF(OSSL_PROVIDER) diff --git a/include/internal/property.h b/include/internal/property.h index 85f602d1e5..856cd740ad 100644 --- a/include/internal/property.h +++ b/include/internal/property.h @@ -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 diff --git a/test/p_test.c b/test/p_test.c index d4e187f94a..80f0784dd9 100644 --- a/test/p_test.c +++ b/test/p_test.c @@ -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; diff --git a/test/provider_test.c b/test/provider_test.c index 79a1a375e8..807b8fcf22 100644 --- a/test/provider_test.c +++ b/test/provider_test.c @@ -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) -- cgit v1.2.3