From c41f3ae0d92a87b903a9ed585622adae06791676 Mon Sep 17 00:00:00 2001 From: Richard Levitte Date: Sun, 17 Mar 2019 18:06:59 +0100 Subject: [PATCH] Replumbing: Add a mechanism to pre-populate the provider store 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 (Merged from https://github.com/openssl/openssl/pull/8480) --- crypto/build.info | 2 +- crypto/cpt_err.c | 3 ++ crypto/err/openssl.txt | 2 + crypto/provider_core.c | 88 ++++++++++++++++++++++++++---------- crypto/provider_local.h | 18 ++++++++ crypto/provider_predefined.c | 22 +++++++++ include/openssl/cryptoerr.h | 2 + 7 files changed, 111 insertions(+), 26 deletions(-) create mode 100644 crypto/provider_local.h create mode 100644 crypto/provider_predefined.c diff --git a/crypto/build.info b/crypto/build.info index 39cd91ba50..535fa35a10 100644 --- a/crypto/build.info +++ b/crypto/build.info @@ -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]=\ diff --git a/crypto/cpt_err.c b/crypto/cpt_err.c index 88bee489f2..3c3265dce5 100644 --- a/crypto/cpt_err.c +++ b/crypto/cpt_err.c @@ -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} }; diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt index 9f84dbc99f..7309ed8fe4 100644 --- a/crypto/err/openssl.txt +++ b/crypto/err/openssl.txt @@ -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 diff --git a/crypto/provider_core.c b/crypto/provider_core.c index c136e42e16..7a184a7d67 100644 --- a/crypto/provider_core.c +++ b/crypto/provider_core.c @@ -11,9 +11,14 @@ #include #include #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 index 0000000000..e4c649a736 --- /dev/null +++ b/crypto/provider_local.h @@ -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 + +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 index 0000000000..be21565e9f --- /dev/null +++ b/crypto/provider_predefined.c @@ -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 +#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 } +}; diff --git a/include/openssl/cryptoerr.h b/include/openssl/cryptoerr.h index 42fd3b6544..b38b272a24 100644 --- a/include/openssl/cryptoerr.h +++ b/include/openssl/cryptoerr.h @@ -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 /*