]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
Instantiate configuration supplied providers when we need them
authorMatt Caswell <matt@openssl.org>
Fri, 18 Jun 2021 14:56:54 +0000 (15:56 +0100)
committerMatt Caswell <matt@openssl.org>
Thu, 24 Jun 2021 13:48:14 +0000 (14:48 +0100)
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)

crypto/provider_conf.c
crypto/provider_core.c
crypto/provider_local.h
crypto/provider_predefined.c

index 977d469808f5a0346e58b748d402cacfce63197d..d53e1be2dc426e0a776024c908f8efb0cfbd6f01 100644 (file)
@@ -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;
 }
index 2503bf4af0519109258108b4c013a3cf967fdf8f..78a4b7f2cab1d3a93fc2e9172ed67a500e9357c0 100644 (file)
 #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;
index 8ac692130fcfb5b38771eac7ee24c92d81c2631a..6c34bda51a3df931fc9aeaa7d68688b6a4ef5885 100644 (file)
@@ -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);
index 0ef569c06ac63bd8e8ee9c6d027ccb6d5285d031..a190f49b2c772e40a191a1dfacc26f38cc7abe2e 100644 (file)
@@ -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 }
 };