Replumbing: Add a mechanism to pre-populate the provider store
authorRichard Levitte <levitte@openssl.org>
Sun, 17 Mar 2019 17:06:59 +0000 (18:06 +0100)
committerRichard Levitte <levitte@openssl.org>
Tue, 19 Mar 2019 13:06:58 +0000 (14:06 +0100)
OpenSSL will come with a set of well known providers, some of which
need to be accessible from the start.  These are typically built in
providers, or providers that will work as fallbacks.

We do this when creating a new provider store, which means that this
will happen in every library context, regardless of if it's the global
default one, or an explicitely created one.

We keep the data about the known providers we want to make accessible
this way in crypto/provider_predefined.h, which may become generated.
For now, though, we make it simple and edited manually.

Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/8480)

crypto/build.info
crypto/cpt_err.c
crypto/err/openssl.txt
crypto/provider_core.c
crypto/provider_local.h [new file with mode: 0644]
crypto/provider_predefined.c [new file with mode: 0644]
include/openssl/cryptoerr.h

index 39cd91b..535fa35 100644 (file)
@@ -9,7 +9,7 @@ SUBDIRS=objects buffer bio stack lhash rand evp asn1 pem x509 x509v3 conf \
 
 LIBS=../libcrypto
 # The Core
-SOURCE[../libcrypto]=provider_core.c core_fetch.c
+SOURCE[../libcrypto]=provider_core.c provider_predefined.c core_fetch.c
 
 # Central utilities
 SOURCE[../libcrypto]=\
index 88bee48..3c3265d 100644 (file)
@@ -59,6 +59,9 @@ static const ERR_STRING_DATA CRYPTO_str_functs[] = {
      "pkey_siphash_init"},
     {ERR_PACK(ERR_LIB_CRYPTO, CRYPTO_F_PROVIDER_ACTIVATE, 0),
      "provider_activate"},
+    {ERR_PACK(ERR_LIB_CRYPTO, CRYPTO_F_PROVIDER_NEW, 0), "provider_new"},
+    {ERR_PACK(ERR_LIB_CRYPTO, CRYPTO_F_PROVIDER_STORE_NEW, 0),
+     "provider_store_new"},
     {ERR_PACK(ERR_LIB_CRYPTO, CRYPTO_F_SK_RESERVE, 0), "sk_reserve"},
     {0, NULL}
 };
index 9f84dbc..7309ed8 100644 (file)
@@ -397,6 +397,8 @@ CRYPTO_F_PKEY_HMAC_INIT:123:pkey_hmac_init
 CRYPTO_F_PKEY_POLY1305_INIT:124:pkey_poly1305_init
 CRYPTO_F_PKEY_SIPHASH_INIT:125:pkey_siphash_init
 CRYPTO_F_PROVIDER_ACTIVATE:134:provider_activate
+CRYPTO_F_PROVIDER_NEW:135:provider_new
+CRYPTO_F_PROVIDER_STORE_NEW:136:provider_store_new
 CRYPTO_F_SK_RESERVE:129:sk_reserve
 CT_F_CTLOG_NEW:117:CTLOG_new
 CT_F_CTLOG_NEW_FROM_BASE64:118:CTLOG_new_from_base64
index c136e42..7a184a7 100644 (file)
 #include <openssl/core_numbers.h>
 #include <openssl/opensslv.h>
 #include "internal/cryptlib.h"
+#include "internal/nelem.h"
 #include "internal/thread_once.h"
 #include "internal/provider.h"
 #include "internal/refcount.h"
+#include "provider_local.h"
+
+static OSSL_PROVIDER *provider_new(const char *name,
+                                   OSSL_provider_init_fn *init_function);
 
 /*-
  * Provider Object structure
@@ -78,6 +83,7 @@ static void provider_store_free(void *vstore)
 static void *provider_store_new(void)
 {
     struct provider_store_st *store = OPENSSL_zalloc(sizeof(*store));
+    const struct predefined_providers_st *p = NULL;
 
     if (store == NULL
         || (store->providers = sk_OSSL_PROVIDER_new(ossl_provider_cmp)) == NULL
@@ -86,6 +92,28 @@ static void *provider_store_new(void)
         return NULL;
     }
     store->use_fallbacks = 1;
+
+    for (p = predefined_providers; p->name != NULL; p++) {
+        OSSL_PROVIDER *prov = NULL;
+
+        /*
+         * We use the internal constructor directly here,
+         * otherwise we get a call loop
+         */
+        prov = provider_new(p->name, p->init);
+
+        if (prov == NULL
+            || sk_OSSL_PROVIDER_push(store->providers, prov) == 0) {
+            ossl_provider_free(prov);
+            provider_store_free(store);
+            CRYPTOerr(CRYPTO_F_PROVIDER_STORE_NEW, ERR_R_INTERNAL_ERROR);
+            return NULL;
+        }
+        prov->store = store;
+        if(p->is_fallback)
+            ossl_provider_set_fallback(prov);
+    }
+
     return store;
 }
 
@@ -116,20 +144,6 @@ static struct provider_store_st *get_provider_store(OPENSSL_CTX *libctx)
     return store;
 }
 
-/*-
- * Provider Object methods
- * =======================
- */
-
-int ossl_provider_upref(OSSL_PROVIDER *prov)
-{
-    int ref = 0;
-
-    CRYPTO_UP_REF(&prov->refcnt, &ref, prov->refcnt_lock);
-    return ref;
-}
-
-/* Finder, constructor and destructor */
 OSSL_PROVIDER *ossl_provider_find(OPENSSL_CTX *libctx, const char *name)
 {
     struct provider_store_st *store = NULL;
@@ -151,6 +165,39 @@ OSSL_PROVIDER *ossl_provider_find(OPENSSL_CTX *libctx, const char *name)
     return prov;
 }
 
+/*-
+ * Provider Object methods
+ * =======================
+ */
+
+static OSSL_PROVIDER *provider_new(const char *name,
+                                   OSSL_provider_init_fn *init_function)
+{
+    OSSL_PROVIDER *prov = NULL;
+
+    if ((prov = OPENSSL_zalloc(sizeof(*prov))) == NULL
+#ifndef HAVE_ATOMICS
+        || (prov->refcnt_lock = CRYPTO_THREAD_lock_new()) == NULL
+#endif
+        || !ossl_provider_upref(prov) /* +1 One reference to be returned */
+        || (prov->name = OPENSSL_strdup(name)) == NULL) {
+        ossl_provider_free(prov);
+        CRYPTOerr(CRYPTO_F_PROVIDER_NEW, ERR_R_MALLOC_FAILURE);
+        return NULL;
+    }
+
+    prov->init_function = init_function;
+    return prov;
+}
+
+int ossl_provider_upref(OSSL_PROVIDER *prov)
+{
+    int ref = 0;
+
+    CRYPTO_UP_REF(&prov->refcnt, &ref, prov->refcnt_lock);
+    return ref;
+}
+
 OSSL_PROVIDER *ossl_provider_new(OPENSSL_CTX *libctx, const char *name,
                                  OSSL_provider_init_fn *init_function)
 {
@@ -168,18 +215,9 @@ OSSL_PROVIDER *ossl_provider_new(OPENSSL_CTX *libctx, const char *name,
         return NULL;
     }
 
-    if ((prov = OPENSSL_zalloc(sizeof(*prov))) == NULL
-#ifndef HAVE_ATOMICS
-        || (prov->refcnt_lock = CRYPTO_THREAD_lock_new()) == NULL
-#endif
-        || !ossl_provider_upref(prov) /* +1 One reference to be returned */
-        || (prov->name = OPENSSL_strdup(name)) == NULL) {
-        ossl_provider_free(prov);
-        CRYPTOerr(CRYPTO_F_OSSL_PROVIDER_NEW, ERR_R_MALLOC_FAILURE);
+    /* provider_new() generates an error, so no need here */
+    if ((prov = provider_new(name, init_function)) == NULL)
         return NULL;
-    }
-
-    prov->init_function = init_function;
 
     CRYPTO_THREAD_write_lock(store->lock);
     if (!ossl_provider_upref(prov)) { /* +1 One reference for the store */
diff --git a/crypto/provider_local.h b/crypto/provider_local.h
new file mode 100644 (file)
index 0000000..e4c649a
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+ * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License").  You may not use
+ * this file except in compliance with the License.  You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/core.h>
+
+struct predefined_providers_st {
+    const char *name;
+    OSSL_provider_init_fn *init;
+    unsigned int is_fallback:1;
+};
+
+extern const struct predefined_providers_st predefined_providers[];
diff --git a/crypto/provider_predefined.c b/crypto/provider_predefined.c
new file mode 100644 (file)
index 0000000..be21565
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License").  You may not use
+ * this file except in compliance with the License.  You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/core.h>
+#include "provider_local.h"
+
+#if 0                            /* Until it exists for real */
+OSSL_provider_init_fn ossl_default_provider_init;
+#endif
+
+const struct predefined_providers_st predefined_providers[] = {
+#if 0                            /* Until it exists for real */
+    { "default", ossl_default_provider_init, 1 },
+#endif
+    { NULL, NULL, 0 }
+};
index 42fd3b6..b38b272 100644 (file)
@@ -50,6 +50,8 @@ int ERR_load_CRYPTO_strings(void);
 # define CRYPTO_F_PKEY_POLY1305_INIT                      124
 # define CRYPTO_F_PKEY_SIPHASH_INIT                       125
 # define CRYPTO_F_PROVIDER_ACTIVATE                       134
+# define CRYPTO_F_PROVIDER_NEW                            135
+# define CRYPTO_F_PROVIDER_STORE_NEW                      136
 # define CRYPTO_F_SK_RESERVE                              129
 
 /*