summaryrefslogtreecommitdiffstats
path: root/crypto
diff options
context:
space:
mode:
authorMatt Caswell <matt@openssl.org>2021-06-18 15:56:54 +0100
committerMatt Caswell <matt@openssl.org>2021-06-24 14:48:14 +0100
commit352d482a2990cc04adff48aeda9c080d4a839f1e (patch)
treebee0041c8a4b777653125cab5ed8280b19def1b0 /crypto
parent1d74203cf5d8542d349fbb2d5f35ad40994dec9f (diff)
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 <pauli@openssl.org> Reviewed-by: Tomas Mraz <tomas@openssl.org> (Merged from https://github.com/openssl/openssl/pull/15854)
Diffstat (limited to 'crypto')
-rw-r--r--crypto/provider_conf.c83
-rw-r--r--crypto/provider_core.c136
-rw-r--r--crypto/provider_local.h15
-rw-r--r--crypto/provider_predefined.c12
4 files changed, 179 insertions, 67 deletions
diff --git a/crypto/provider_conf.c b/crypto/provider_conf.c
index 977d469808..d53e1be2dc 100644
--- a/crypto/provider_conf.c
+++ b/crypto/provider_conf.c
@@ -14,6 +14,7 @@
#include <openssl/safestack.h>
#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 2503bf4af0..78a4b7f2ca 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 8ac692130f..6c34bda51a 100644
--- a/crypto/provider_local.h
+++ b/crypto/provider_local.h
@@ -9,10 +9,25 @@
#include <openssl/core.h>
+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 0ef569c06a..a190f49b2c 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 }
};