From: Matt Caswell Date: Fri, 18 Jun 2021 14:56:54 +0000 (+0100) Subject: Instantiate configuration supplied providers when we need them X-Git-Tag: openssl-3.0.0-beta2~215 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=352d482a2990cc04adff48aeda9c080d4a839f1e;p=thirdparty%2Fopenssl.git Instantiate configuration supplied providers when we need them If provider specified in a config file are not "activated" then we defer instantiating the provider object until it is actually needed. Reviewed-by: Paul Dale Reviewed-by: Tomas Mraz (Merged from https://github.com/openssl/openssl/pull/15854) --- diff --git a/crypto/provider_conf.c b/crypto/provider_conf.c index 977d469808f..d53e1be2dc4 100644 --- a/crypto/provider_conf.c +++ b/crypto/provider_conf.c @@ -14,6 +14,7 @@ #include #include "internal/provider.h" #include "internal/cryptlib.h" +#include "provider_local.h" DEFINE_STACK_OF(OSSL_PROVIDER) @@ -61,6 +62,7 @@ static const char *skip_dot(const char *name) } static int provider_conf_params(OSSL_PROVIDER *prov, + struct provider_info_st *provinfo, const char *name, const char *value, const CONF *cnf) { @@ -88,14 +90,18 @@ static int provider_conf_params(OSSL_PROVIDER *prov, return 0; buffer[buffer_len] = '\0'; OPENSSL_strlcat(buffer, sectconf->name, sizeof(buffer)); - if (!provider_conf_params(prov, buffer, sectconf->value, cnf)) + if (!provider_conf_params(prov, provinfo, buffer, sectconf->value, + cnf)) return 0; } OSSL_TRACE1(CONF, "Provider params: finish section %s\n", value); } else { OSSL_TRACE2(CONF, "Provider params: %s = %s\n", name, value); - ok = ossl_provider_add_parameter(prov, name, value); + if (prov != NULL) + ok = ossl_provider_add_parameter(prov, name, value); + else + ok = ossl_provider_info_add_parameter(provinfo, name, value); } return ok; @@ -149,33 +155,62 @@ static int provider_conf_load(OSSL_LIB_CTX *libctx, const char *name, activate = 1; } - prov = ossl_provider_find(libctx, name, 1); - if (prov == NULL) - prov = ossl_provider_new(libctx, name, NULL, 1); - if (prov == NULL) { - if (soft) - ERR_clear_error(); - return 0; - } + if (activate) { + prov = ossl_provider_find(libctx, name, 1); + if (prov == NULL) + prov = ossl_provider_new(libctx, name, NULL, 1); + if (prov == NULL) { + if (soft) + ERR_clear_error(); + return 0; + } - if (path != NULL) - ossl_provider_set_module_path(prov, path); + if (path != NULL) + ossl_provider_set_module_path(prov, path); - ok = provider_conf_params(prov, NULL, value, cnf); + ok = provider_conf_params(prov, NULL, NULL, value, cnf); - if (ok && activate) { - if (!ossl_provider_activate(prov, 0, 1)) { - ok = 0; - } else { - if (pcgbl->activated_providers == NULL) - pcgbl->activated_providers = sk_OSSL_PROVIDER_new_null(); - sk_OSSL_PROVIDER_push(pcgbl->activated_providers, prov); - ok = 1; + if (ok) { + if (!ossl_provider_activate(prov, 0, 1)) { + ok = 0; + } else { + if (pcgbl->activated_providers == NULL) + pcgbl->activated_providers = sk_OSSL_PROVIDER_new_null(); + sk_OSSL_PROVIDER_push(pcgbl->activated_providers, prov); + ok = 1; + } } - } - if (!(activate && ok)) - ossl_provider_free(prov); + if (!(activate && ok)) + ossl_provider_free(prov); + } else { + struct provider_info_st entry; + + memset(&entry, 0, sizeof(entry)); + ok = 1; + if (name != NULL) { + entry.name = OPENSSL_strdup(name); + if (entry.name == NULL) { + ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE); + ok = 0; + } + } + if (ok && path != NULL) { + entry.path = OPENSSL_strdup(path); + if (entry.path == NULL) { + ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE); + ok = 0; + } + } + if (ok) + ok = provider_conf_params(NULL, &entry, NULL, value, cnf); + if (ok && (entry.path != NULL || entry.parameters != NULL)) + ok = ossl_provider_info_add_to_store(libctx, &entry); + if (!ok || (entry.path == NULL && entry.parameters == NULL)) { + ossl_provider_info_clear(&entry); + } + + } return ok; } diff --git a/crypto/provider_core.c b/crypto/provider_core.c index 2503bf4af05..78a4b7f2cab 100644 --- a/crypto/provider_core.c +++ b/crypto/provider_core.c @@ -29,19 +29,14 @@ #endif static OSSL_PROVIDER *provider_new(const char *name, - OSSL_provider_init_fn *init_function); + OSSL_provider_init_fn *init_function, + STACK_OF(INFOPAIR) *parameters); /*- * Provider Object structure * ========================= */ -typedef struct { - char *name; - char *value; -} INFOPAIR; -DEFINE_STACK_OF(INFOPAIR) - #ifndef FIPS_MODULE typedef struct { OSSL_PROVIDER *prov; @@ -166,6 +161,43 @@ static void ossl_provider_child_cb_free(OSSL_PROVIDER_CHILD_CB *cb) } #endif +static void infopair_free(INFOPAIR *pair) +{ + OPENSSL_free(pair->name); + OPENSSL_free(pair->value); + OPENSSL_free(pair); +} + +static INFOPAIR *infopair_copy(const INFOPAIR *src) +{ + INFOPAIR *dest = OPENSSL_zalloc(sizeof(*dest)); + + if (dest == NULL) + return NULL; + if (src->name != NULL) { + dest->name = OPENSSL_strdup(src->name); + if (dest->name == NULL) + goto err; + } + if (src->value != NULL) { + dest->value = OPENSSL_strdup(src->value); + if (dest->value == NULL) + goto err; + } + return dest; + err: + OPENSSL_free(dest->name); + OPENSSL_free(dest); + return NULL; +} + +void ossl_provider_info_clear(struct provider_info_st *info) +{ + OPENSSL_free(info->name); + OPENSSL_free(info->path); + sk_INFOPAIR_pop_free(info->parameters, infopair_free); +} + static void provider_store_free(void *vstore) { struct provider_store_st *store = vstore; @@ -183,7 +215,7 @@ static void provider_store_free(void *vstore) CRYPTO_THREAD_lock_free(store->default_path_lock); CRYPTO_THREAD_lock_free(store->lock); for (i = 0; i < store->numprovinfo; i++) - OPENSSL_free(store->provinfo[i].name); + ossl_provider_info_clear(&store->provinfo[i]); OPENSSL_free(store->provinfo); OPENSSL_free(store); } @@ -242,13 +274,13 @@ int ossl_provider_disable_fallback_loading(OSSL_LIB_CTX *libctx) #define BUILTINS_BLOCK_SIZE 10 -int OSSL_PROVIDER_add_builtin(OSSL_LIB_CTX *libctx, const char *name, - OSSL_provider_init_fn *init_fn) +int ossl_provider_info_add_to_store(OSSL_LIB_CTX *libctx, + const struct provider_info_st *entry) { struct provider_store_st *store = get_provider_store(libctx); int ret = 0; - if (name == NULL || init_fn == NULL) { + if (entry->name == NULL) { ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_NULL_PARAMETER); return 0; } @@ -281,13 +313,7 @@ int OSSL_PROVIDER_add_builtin(OSSL_LIB_CTX *libctx, const char *name, store->provinfo = tmpbuiltins; store->provinfosz = newsz; } - store->provinfo[store->numprovinfo].name = OPENSSL_strdup(name); - if (store->provinfo[store->numprovinfo].name == NULL) { - ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE); - goto err; - } - store->provinfo[store->numprovinfo].init = init_fn; - store->provinfo[store->numprovinfo].is_fallback = 0; + store->provinfo[store->numprovinfo] = *entry; store->numprovinfo++; ret = 1; @@ -296,6 +322,29 @@ int OSSL_PROVIDER_add_builtin(OSSL_LIB_CTX *libctx, const char *name, return ret; } +int OSSL_PROVIDER_add_builtin(OSSL_LIB_CTX *libctx, const char *name, + OSSL_provider_init_fn *init_fn) +{ + struct provider_info_st entry; + + if (name == NULL || init_fn == NULL) { + ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + memset(&entry, 0, sizeof(entry)); + entry.name = OPENSSL_strdup(name); + if (entry.name == NULL) { + ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE); + return 0; + } + entry.init = init_fn; + if (!ossl_provider_info_add_to_store(libctx, &entry)) { + ossl_provider_info_clear(&entry); + return 0; + } + return 1; +} + OSSL_PROVIDER *ossl_provider_find(OSSL_LIB_CTX *libctx, const char *name, int noconfig) { @@ -336,7 +385,8 @@ OSSL_PROVIDER *ossl_provider_find(OSSL_LIB_CTX *libctx, const char *name, */ static OSSL_PROVIDER *provider_new(const char *name, - OSSL_provider_init_fn *init_function) + OSSL_provider_init_fn *init_function, + STACK_OF(INFOPAIR) *parameters) { OSSL_PROVIDER *prov = NULL; @@ -346,7 +396,10 @@ static OSSL_PROVIDER *provider_new(const char *name, #endif || (prov->opbits_lock = CRYPTO_THREAD_lock_new()) == NULL || (prov->flag_lock = CRYPTO_THREAD_lock_new()) == NULL - || (prov->name = OPENSSL_strdup(name)) == NULL) { + || (prov->name = OPENSSL_strdup(name)) == NULL + || (prov->parameters = sk_INFOPAIR_deep_copy(parameters, + infopair_copy, + infopair_free)) == NULL) { ossl_provider_free(prov); ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE); return NULL; @@ -357,6 +410,7 @@ static OSSL_PROVIDER *provider_new(const char *name, #ifndef FIPS_MODULE prov->flag_couldbechild = 1; #endif + return prov; } @@ -403,6 +457,7 @@ OSSL_PROVIDER *ossl_provider_new(OSSL_LIB_CTX *libctx, const char *name, int noconfig) { struct provider_store_st *store = NULL; + struct provider_info_st template; OSSL_PROVIDER *prov = NULL; if ((store = get_provider_store(libctx)) == NULL) @@ -416,6 +471,7 @@ OSSL_PROVIDER *ossl_provider_new(OSSL_LIB_CTX *libctx, const char *name, return NULL; } + memset(&template, 0, sizeof(template)); if (init_function == NULL) { const struct provider_info_st *p; size_t i; @@ -423,7 +479,7 @@ OSSL_PROVIDER *ossl_provider_new(OSSL_LIB_CTX *libctx, const char *name, /* Check if this is a predefined builtin provider */ for (p = ossl_predefined_providers; p->name != NULL; p++) { if (strcmp(p->name, name) == 0) { - init_function = p->init; + template = *p; break; } } @@ -433,7 +489,7 @@ OSSL_PROVIDER *ossl_provider_new(OSSL_LIB_CTX *libctx, const char *name, return NULL; for (i = 0, p = store->provinfo; i < store->numprovinfo; p++, i++) { if (strcmp(p->name, name) == 0) { - init_function = p->init; + template = *p; break; } } @@ -444,7 +500,7 @@ OSSL_PROVIDER *ossl_provider_new(OSSL_LIB_CTX *libctx, const char *name, } /* provider_new() generates an error, so no need here */ - if ((prov = provider_new(name, init_function)) == NULL) + if ((prov = provider_new(name, template.init, template.parameters)) == NULL) return NULL; prov->libctx = libctx; @@ -476,13 +532,6 @@ OSSL_PROVIDER *ossl_provider_new(OSSL_LIB_CTX *libctx, const char *name, return prov; } -static void free_infopair(INFOPAIR *pair) -{ - OPENSSL_free(pair->name); - OPENSSL_free(pair->value); - OPENSSL_free(pair); -} - void ossl_provider_free(OSSL_PROVIDER *prov) { if (prov != NULL) { @@ -527,7 +576,7 @@ void ossl_provider_free(OSSL_PROVIDER *prov) #endif OPENSSL_free(prov->name); OPENSSL_free(prov->path); - sk_INFOPAIR_pop_free(prov->parameters, free_infopair); + sk_INFOPAIR_pop_free(prov->parameters, infopair_free); CRYPTO_THREAD_lock_free(prov->opbits_lock); CRYPTO_THREAD_lock_free(prov->flag_lock); #ifndef HAVE_ATOMICS @@ -556,17 +605,17 @@ int ossl_provider_set_module_path(OSSL_PROVIDER *prov, const char *module_path) return 0; } -int ossl_provider_add_parameter(OSSL_PROVIDER *prov, - const char *name, const char *value) +static int infopair_add(STACK_OF(INFOPAIR) **infopairsk, const char *name, + const char *value) { INFOPAIR *pair = NULL; if ((pair = OPENSSL_zalloc(sizeof(*pair))) != NULL - && (prov->parameters != NULL - || (prov->parameters = sk_INFOPAIR_new_null()) != NULL) + && (*infopairsk != NULL + || (*infopairsk = sk_INFOPAIR_new_null()) != NULL) && (pair->name = OPENSSL_strdup(name)) != NULL && (pair->value = OPENSSL_strdup(value)) != NULL - && sk_INFOPAIR_push(prov->parameters, pair) > 0) + && sk_INFOPAIR_push(*infopairsk, pair) > 0) return 1; if (pair != NULL) { @@ -578,6 +627,19 @@ int ossl_provider_add_parameter(OSSL_PROVIDER *prov, return 0; } +int ossl_provider_add_parameter(OSSL_PROVIDER *prov, + const char *name, const char *value) +{ + return infopair_add(&prov->parameters, name, value); +} + +int ossl_provider_info_add_parameter(struct provider_info_st *provinfo, + const char *name, + const char *value) +{ + return infopair_add(&provinfo->parameters, name, value); +} + /* * Provider activation. * @@ -1035,7 +1097,7 @@ static int provider_activate_fallbacks(struct provider_store_st *store) * We use the internal constructor directly here, * otherwise we get a call loop */ - prov = provider_new(p->name, p->init); + prov = provider_new(p->name, p->init, NULL); if (prov == NULL) goto err; prov->libctx = store->libctx; diff --git a/crypto/provider_local.h b/crypto/provider_local.h index 8ac692130fc..6c34bda51a3 100644 --- a/crypto/provider_local.h +++ b/crypto/provider_local.h @@ -9,10 +9,25 @@ #include +typedef struct { + char *name; + char *value; +} INFOPAIR; +DEFINE_STACK_OF(INFOPAIR) + struct provider_info_st { char *name; + char *path; OSSL_provider_init_fn *init; + STACK_OF(INFOPAIR) *parameters; unsigned int is_fallback:1; }; extern const struct provider_info_st ossl_predefined_providers[]; + +void ossl_provider_info_clear(struct provider_info_st *info); +int ossl_provider_info_add_to_store(OSSL_LIB_CTX *libctx, + const struct provider_info_st *entry); +int ossl_provider_info_add_parameter(struct provider_info_st *provinfo, + const char *name, + const char *value); diff --git a/crypto/provider_predefined.c b/crypto/provider_predefined.c index 0ef569c06ac..a190f49b2c7 100644 --- a/crypto/provider_predefined.c +++ b/crypto/provider_predefined.c @@ -19,14 +19,14 @@ OSSL_provider_init_fn ossl_legacy_provider_init; #endif const struct provider_info_st ossl_predefined_providers[] = { #ifdef FIPS_MODULE - { "fips", ossl_fips_intern_provider_init, 1 }, + { "fips", NULL, ossl_fips_intern_provider_init, NULL, 1 }, #else - { "default", ossl_default_provider_init, 1 }, + { "default", NULL, ossl_default_provider_init, NULL, 1 }, # ifdef STATIC_LEGACY - { "legacy", ossl_legacy_provider_init, 0 }, + { "legacy", NULL, ossl_legacy_provider_init, NULL, 0 }, # endif - { "base", ossl_base_provider_init, 0 }, - { "null", ossl_null_provider_init, 0 }, + { "base", NULL, ossl_base_provider_init, NULL, 0 }, + { "null", NULL, ossl_null_provider_init, NULL, 0 }, #endif - { NULL, NULL, 0 } + { NULL, NULL, NULL, NULL, 0 } };