]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
Instantiate user-added builtin providers when we need them
authorMatt Caswell <matt@openssl.org>
Fri, 18 Jun 2021 11:28:40 +0000 (12:28 +0100)
committerMatt Caswell <matt@openssl.org>
Thu, 24 Jun 2021 13:48:14 +0000 (14:48 +0100)
Previously we created the provider object for builtin providers at the
point that OPENSSL_add_builtin() was called. Instead we delay that until
the provider is actually loaded.

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.c
crypto/provider_core.c
crypto/provider_local.h
crypto/provider_predefined.c

index 60664e9e24e049c8d9d38f196d19383ac2da5464..5aec157c1f14cffdf2b4b736a55d39f34eefc347 100644 (file)
@@ -94,29 +94,6 @@ int OSSL_PROVIDER_get_capabilities(const OSSL_PROVIDER *prov,
     return ossl_provider_get_capabilities(prov, capability, cb, arg);
 }
 
-int OSSL_PROVIDER_add_builtin(OSSL_LIB_CTX *libctx, const char *name,
-                              OSSL_provider_init_fn *init_fn)
-{
-    OSSL_PROVIDER *prov = NULL;
-
-    if (name == NULL || init_fn == NULL) {
-        ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_NULL_PARAMETER);
-        return 0;
-    }
-
-    /* Create it */
-    if ((prov = ossl_provider_new(libctx, name, init_fn, 0)) == NULL)
-        return 0;
-
-    /*
-     * It's safely stored in the internal store at this point,
-     * free the returned extra reference
-     */
-    ossl_provider_free(prov);
-
-    return 1;
-}
-
 const char *OSSL_PROVIDER_get0_name(const OSSL_PROVIDER *prov)
 {
     return ossl_provider_name(prov);
index 24c88e431d876d812cca35b2364ee941f409df62..2503bf4af0519109258108b4c013a3cf967fdf8f 100644 (file)
@@ -139,6 +139,9 @@ struct provider_store_st {
     CRYPTO_RWLOCK *default_path_lock;
     CRYPTO_RWLOCK *lock;
     char *default_path;
+    struct provider_info_st *provinfo;
+    size_t numprovinfo;
+    size_t provinfosz;
     unsigned int use_fallbacks:1;
     unsigned int freeing:1;
 };
@@ -166,6 +169,7 @@ static void ossl_provider_child_cb_free(OSSL_PROVIDER_CHILD_CB *cb)
 static void provider_store_free(void *vstore)
 {
     struct provider_store_st *store = vstore;
+    size_t i;
 
     if (store == NULL)
         return;
@@ -178,6 +182,9 @@ static void provider_store_free(void *vstore)
 #endif
     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);
+    OPENSSL_free(store->provinfo);
     OPENSSL_free(store);
 }
 
@@ -233,6 +240,62 @@ int ossl_provider_disable_fallback_loading(OSSL_LIB_CTX *libctx)
     return 0;
 }
 
+#define BUILTINS_BLOCK_SIZE     10
+
+int OSSL_PROVIDER_add_builtin(OSSL_LIB_CTX *libctx, const char *name,
+                              OSSL_provider_init_fn *init_fn)
+{
+    struct provider_store_st *store = get_provider_store(libctx);
+    int ret = 0;
+
+    if (name == NULL || init_fn == NULL) {
+        ERR_raise(ERR_LIB_CRYPTO, ERR_R_PASSED_NULL_PARAMETER);
+        return 0;
+    }
+
+    if (store == NULL) {
+        ERR_raise(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR);
+        return 0;
+    }
+
+    if (!CRYPTO_THREAD_write_lock(store->lock))
+        return 0;
+    if (store->provinfosz == 0) {
+        store->provinfo = OPENSSL_zalloc(sizeof(*store->provinfo)
+                                         * BUILTINS_BLOCK_SIZE);
+        if (store->provinfo == NULL) {
+            ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE);
+            goto err;
+        }
+        store->provinfosz = BUILTINS_BLOCK_SIZE;
+    } else if (store->numprovinfo == store->provinfosz) {
+        struct provider_info_st *tmpbuiltins;
+        size_t newsz = store->provinfosz + BUILTINS_BLOCK_SIZE;
+
+        tmpbuiltins = OPENSSL_realloc(store->provinfo,
+                                      sizeof(*store->provinfo) * newsz);
+        if (tmpbuiltins == NULL) {
+            ERR_raise(ERR_LIB_CRYPTO, ERR_R_MALLOC_FAILURE);
+            goto err;
+        }
+        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->numprovinfo++;
+
+    ret = 1;
+ err:
+    CRYPTO_THREAD_unlock(store->lock);
+    return ret;
+}
+
 OSSL_PROVIDER *ossl_provider_find(OSSL_LIB_CTX *libctx, const char *name,
                                   int noconfig)
 {
@@ -354,15 +417,30 @@ OSSL_PROVIDER *ossl_provider_new(OSSL_LIB_CTX *libctx, const char *name,
     }
 
     if (init_function == NULL) {
-        const struct predefined_providers_st *p;
+        const struct provider_info_st *p;
+        size_t i;
 
-        /* Check if this is a built-in provider */
+        /* 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;
                 break;
             }
         }
+        if (p->name == NULL) {
+            /* Check if this is a user added builtin provider */
+            if (!CRYPTO_THREAD_read_lock(store->lock))
+                return NULL;
+            for (i = 0, p = store->provinfo; i < store->numprovinfo; p++, i++) {
+                if (strcmp(p->name, name) == 0) {
+                    init_function = p->init;
+                    break;
+                }
+            }
+            CRYPTO_THREAD_unlock(store->lock);
+        }
+    } else {
+        template.init = init_function;
     }
 
     /* provider_new() generates an error, so no need here */
@@ -930,7 +1008,7 @@ static int provider_activate_fallbacks(struct provider_store_st *store)
     int use_fallbacks;
     int activated_fallback_count = 0;
     int ret = 0;
-    const struct predefined_providers_st *p;
+    const struct provider_info_st *p;
 
     if (!CRYPTO_THREAD_read_lock(store->lock))
         return 0;
index 12baf032f1daaa74c1e944c544530322737d1b12..8ac692130fcfb5b38771eac7ee24c92d81c2631a 100644 (file)
@@ -9,10 +9,10 @@
 
 #include <openssl/core.h>
 
-struct predefined_providers_st {
-    const char *name;
+struct provider_info_st {
+    char *name;
     OSSL_provider_init_fn *init;
     unsigned int is_fallback:1;
 };
 
-extern const struct predefined_providers_st ossl_predefined_providers[];
+extern const struct provider_info_st ossl_predefined_providers[];
index 142a6d97d1c62f4f48e6f52628858e7154cf812f..0ef569c06ac63bd8e8ee9c6d027ccb6d5285d031 100644 (file)
@@ -17,7 +17,7 @@ OSSL_provider_init_fn ossl_fips_intern_provider_init;
 #ifdef STATIC_LEGACY
 OSSL_provider_init_fn ossl_legacy_provider_init;
 #endif
-const struct predefined_providers_st ossl_predefined_providers[] = {
+const struct provider_info_st ossl_predefined_providers[] = {
 #ifdef FIPS_MODULE
     { "fips", ossl_fips_intern_provider_init, 1 },
 #else