summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatt Caswell <matt@openssl.org>2021-04-21 16:51:41 +0100
committerMatt Caswell <matt@openssl.org>2021-05-11 14:56:55 +0100
commitf12a5690de906c05031f0195b6dec6925ff27231 (patch)
tree9d4ea21b4d574ec86091c27cd1c530356534c2df
parenta16d21744df686a7c005d1f129915d9083476e14 (diff)
Add the concept of a child OSSL_LIB_CTX
Add a child OSSL_LIB_CTX that will mirror the providers loaded into the parent libctx. This is useful for providers that want to use algorithms from other providers and just need to inherit the providers used by the application. Fixes #14925 Reviewed-by: Paul Dale <pauli@openssl.org> (Merged from https://github.com/openssl/openssl/pull/14991)
-rw-r--r--crypto/build.info2
-rw-r--r--crypto/context.c31
-rw-r--r--crypto/provider.c5
-rw-r--r--crypto/provider_child.c232
-rw-r--r--crypto/provider_core.c46
-rw-r--r--doc/man3/OSSL_LIB_CTX.pod12
-rw-r--r--include/internal/core.h1
-rw-r--r--include/internal/cryptlib.h3
-rw-r--r--include/internal/provider.h8
-rw-r--r--include/openssl/core.h1
-rw-r--r--include/openssl/core_dispatch.h17
-rw-r--r--include/openssl/crypto.h.in6
-rw-r--r--include/openssl/provider.h1
-rw-r--r--test/bio_core_test.c2
-rw-r--r--util/libcrypto.num2
15 files changed, 353 insertions, 16 deletions
diff --git a/crypto/build.info b/crypto/build.info
index ffcc2b0183..ed4581eef5 100644
--- a/crypto/build.info
+++ b/crypto/build.info
@@ -99,7 +99,7 @@ $UTIL_COMMON=\
SOURCE[../libcrypto]=$UTIL_COMMON \
mem.c mem_sec.c \
cversion.c info.c cpt_err.c ebcdic.c uid.c o_time.c o_dir.c \
- o_fopen.c getenv.c o_init.c init.c trace.c provider.c \
+ o_fopen.c getenv.c o_init.c init.c trace.c provider.c provider_child.c \
punycode.c
SOURCE[../providers/libfips.a]=$UTIL_COMMON
diff --git a/crypto/context.c b/crypto/context.c
index b21fdf077d..1e0dfa8e01 100644
--- a/crypto/context.c
+++ b/crypto/context.c
@@ -13,6 +13,7 @@
#include "internal/property.h"
#include "internal/core.h"
#include "internal/bio.h"
+#include "internal/provider.h"
struct ossl_lib_ctx_onfree_list_st {
ossl_lib_ctx_onfree_fn *fn;
@@ -39,6 +40,7 @@ struct ossl_lib_ctx_st {
int run_once_done[OSSL_LIB_CTX_MAX_RUN_ONCE];
int run_once_ret[OSSL_LIB_CTX_MAX_RUN_ONCE];
struct ossl_lib_ctx_onfree_list_st *onfreelist;
+ unsigned int ischild:1;
};
int ossl_lib_ctx_write_lock(OSSL_LIB_CTX *ctx)
@@ -56,6 +58,15 @@ int ossl_lib_ctx_unlock(OSSL_LIB_CTX *ctx)
return CRYPTO_THREAD_unlock(ossl_lib_ctx_get_concrete(ctx)->lock);
}
+int ossl_lib_ctx_is_child(OSSL_LIB_CTX *ctx)
+{
+ ctx = ossl_lib_ctx_get_concrete(ctx);
+
+ if (ctx == NULL)
+ return 0;
+ return ctx->ischild;
+}
+
static int context_init(OSSL_LIB_CTX *ctx)
{
size_t i;
@@ -185,7 +196,8 @@ OSSL_LIB_CTX *OSSL_LIB_CTX_new(void)
}
#ifndef FIPS_MODULE
-OSSL_LIB_CTX *OSSL_LIB_CTX_new_from_dispatch(const OSSL_DISPATCH *in)
+OSSL_LIB_CTX *OSSL_LIB_CTX_new_from_dispatch(const OSSL_CORE_HANDLE *handle,
+ const OSSL_DISPATCH *in)
{
OSSL_LIB_CTX *ctx = OSSL_LIB_CTX_new();
@@ -200,6 +212,23 @@ OSSL_LIB_CTX *OSSL_LIB_CTX_new_from_dispatch(const OSSL_DISPATCH *in)
return ctx;
}
+OSSL_LIB_CTX *OSSL_LIB_CTX_new_child(const OSSL_CORE_HANDLE *handle,
+ const OSSL_DISPATCH *in)
+{
+ OSSL_LIB_CTX *ctx = OSSL_LIB_CTX_new_from_dispatch(handle, in);
+
+ if (ctx == NULL)
+ return NULL;
+
+ if (!ossl_provider_init_as_child(ctx, handle, in)) {
+ OSSL_LIB_CTX_free(ctx);
+ return NULL;
+ }
+ ctx->ischild = 1;
+
+ return ctx;
+}
+
int OSSL_LIB_CTX_load_config(OSSL_LIB_CTX *ctx, const char *config_file)
{
return CONF_modules_load_file_ex(ctx, config_file, NULL, 0) > 0;
diff --git a/crypto/provider.c b/crypto/provider.c
index bdff44afb9..743c2f4846 100644
--- a/crypto/provider.c
+++ b/crypto/provider.c
@@ -88,6 +88,11 @@ void *OSSL_PROVIDER_get0_provider_ctx(const OSSL_PROVIDER *prov)
return ossl_provider_prov_ctx(prov);
}
+const OSSL_DISPATCH *OSSL_PROVIDER_get0_dispatch(const OSSL_PROVIDER *prov)
+{
+ return ossl_provider_get0_dispatch(prov);
+}
+
int OSSL_PROVIDER_self_test(const OSSL_PROVIDER *prov)
{
return ossl_provider_self_test(prov);
diff --git a/crypto/provider_child.c b/crypto/provider_child.c
new file mode 100644
index 0000000000..fa1d004122
--- /dev/null
+++ b/crypto/provider_child.c
@@ -0,0 +1,232 @@
+/*
+ * Copyright 2019-2021 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/crypto.h>
+#include <openssl/core_dispatch.h>
+#include <openssl/core_names.h>
+#include <openssl/provider.h>
+#include "internal/provider.h"
+#include "internal/cryptlib.h"
+
+DEFINE_STACK_OF(OSSL_PROVIDER)
+
+struct child_prov_globals {
+ const OSSL_CORE_HANDLE *handle;
+ OSSL_CORE_PROVIDER *curr_prov;
+ STACK_OF(OSSL_PROVIDER) *childprovs;
+ unsigned int isinited:1;
+ CRYPTO_RWLOCK *lock;
+ OSSL_FUNC_core_get_libctx_fn *c_get_libctx;
+ OSSL_FUNC_core_provider_do_all_fn *c_prov_do_all;
+ OSSL_FUNC_core_provider_name_fn *c_prov_name;
+ OSSL_FUNC_core_provider_get0_provider_ctx_fn *c_prov_get0_provider_ctx;
+ OSSL_FUNC_core_provider_get0_dispatch_fn *c_prov_get0_dispatch;
+};
+
+static void *child_prov_ossl_ctx_new(OSSL_LIB_CTX *libctx)
+{
+ return OPENSSL_zalloc(sizeof(struct child_prov_globals));
+}
+
+/* Wrapper with a void return type for use with sk_OSSL_PROVIDER_pop_free */
+static void ossl_prov_free(OSSL_PROVIDER *prov)
+{
+ OSSL_PROVIDER_unload(prov);
+}
+
+static void child_prov_ossl_ctx_free(void *vgbl)
+{
+ struct child_prov_globals *gbl = vgbl;
+
+ sk_OSSL_PROVIDER_pop_free(gbl->childprovs, ossl_prov_free);
+ CRYPTO_THREAD_lock_free(gbl->lock);
+ OPENSSL_free(gbl);
+}
+
+static const OSSL_LIB_CTX_METHOD child_prov_ossl_ctx_method = {
+ OSSL_LIB_CTX_METHOD_DEFAULT_PRIORITY,
+ child_prov_ossl_ctx_new,
+ child_prov_ossl_ctx_free,
+};
+
+static OSSL_provider_init_fn ossl_child_provider_init;
+
+static int ossl_child_provider_init(const OSSL_CORE_HANDLE *handle,
+ const OSSL_DISPATCH *in,
+ const OSSL_DISPATCH **out,
+ void **provctx)
+{
+ OSSL_FUNC_core_get_libctx_fn *c_get_libctx = NULL;
+ OSSL_LIB_CTX *ctx;
+ struct child_prov_globals *gbl;
+
+ for (; in->function_id != 0; in++) {
+ switch (in->function_id) {
+ case OSSL_FUNC_CORE_GET_LIBCTX:
+ c_get_libctx = OSSL_FUNC_core_get_libctx(in);
+ break;
+ default:
+ /* Just ignore anything we don't understand */
+ break;
+ }
+ }
+
+ if (c_get_libctx == NULL)
+ return 0;
+
+ /*
+ * We need an OSSL_LIB_CTX but c_get_libctx returns OPENSSL_CORE_CTX. We are
+ * a built-in provider and so we can get away with this cast. Normal
+ * providers can't do this.
+ */
+ ctx = (OSSL_LIB_CTX *)c_get_libctx(handle);
+
+ gbl = ossl_lib_ctx_get_data(ctx, OSSL_LIB_CTX_CHILD_PROVIDER_INDEX,
+ &child_prov_ossl_ctx_method);
+ if (gbl == NULL)
+ return 0;
+
+ *provctx = gbl->c_prov_get0_provider_ctx(gbl->curr_prov);
+ *out = gbl->c_prov_get0_dispatch(gbl->curr_prov);
+
+ return 1;
+}
+
+static int provider_create_child_cb(OSSL_CORE_PROVIDER *prov, void *cbdata)
+{
+ OSSL_LIB_CTX *ctx = cbdata;
+ struct child_prov_globals *gbl;
+ const char *provname;
+ OSSL_PROVIDER *cprov;
+
+ gbl = ossl_lib_ctx_get_data(ctx, OSSL_LIB_CTX_CHILD_PROVIDER_INDEX,
+ &child_prov_ossl_ctx_method);
+ if (gbl == NULL)
+ return 0;
+
+ provname = gbl->c_prov_name(prov);
+
+ /*
+ * We're operating under a lock so we can store the "current" provider in
+ * the global data.
+ */
+ gbl->curr_prov = prov;
+
+ /*
+ * Create it - passing 1 as final param so we don't try and recursively init
+ * children
+ */
+ if ((cprov = ossl_provider_new(ctx, provname, ossl_child_provider_init,
+ 1)) == NULL)
+ return 0;
+
+ if (!ossl_provider_activate(cprov, 0)) {
+ ossl_provider_free(cprov);
+ return 0;
+ }
+ ossl_provider_set_child(cprov);
+
+ if (!sk_OSSL_PROVIDER_push(gbl->childprovs, cprov)) {
+ OSSL_PROVIDER_unload(cprov);
+ return 0;
+ }
+
+ return 1;
+}
+
+int ossl_provider_init_child_providers(OSSL_LIB_CTX *ctx)
+{
+ struct child_prov_globals *gbl;
+
+ /* Should never happen */
+ if (ctx == NULL)
+ return 0;
+
+ gbl = ossl_lib_ctx_get_data(ctx, OSSL_LIB_CTX_CHILD_PROVIDER_INDEX,
+ &child_prov_ossl_ctx_method);
+ if (gbl == NULL)
+ return 0;
+
+ if (!CRYPTO_THREAD_read_lock(gbl->lock))
+ return 0;
+ if (gbl->isinited) {
+ CRYPTO_THREAD_unlock(gbl->lock);
+ return 1;
+ }
+ CRYPTO_THREAD_unlock(gbl->lock);
+
+ if (!CRYPTO_THREAD_write_lock(gbl->lock))
+ return 0;
+ if (!gbl->isinited) {
+ if (!gbl->c_prov_do_all(gbl->c_get_libctx(gbl->handle),
+ provider_create_child_cb, ctx)) {
+ CRYPTO_THREAD_unlock(gbl->lock);
+ return 0;
+ }
+ gbl->isinited = 1;
+ }
+ CRYPTO_THREAD_unlock(gbl->lock);
+
+ return 1;
+}
+
+int ossl_provider_init_as_child(OSSL_LIB_CTX *ctx,
+ const OSSL_CORE_HANDLE *handle,
+ const OSSL_DISPATCH *in)
+{
+ struct child_prov_globals *gbl;
+
+ if (ctx == NULL)
+ return 0;
+
+ gbl = ossl_lib_ctx_get_data(ctx, OSSL_LIB_CTX_CHILD_PROVIDER_INDEX,
+ &child_prov_ossl_ctx_method);
+ if (gbl == NULL)
+ return 0;
+
+ gbl->handle = handle;
+ for (; in->function_id != 0; in++) {
+ switch (in->function_id) {
+ case OSSL_FUNC_CORE_GET_LIBCTX:
+ gbl->c_get_libctx = OSSL_FUNC_core_get_libctx(in);
+ break;
+ case OSSL_FUNC_CORE_PROVIDER_DO_ALL:
+ gbl->c_prov_do_all = OSSL_FUNC_core_provider_do_all(in);
+ break;
+ case OSSL_FUNC_CORE_PROVIDER_NAME:
+ gbl->c_prov_name = OSSL_FUNC_core_provider_name(in);
+ break;
+ case OSSL_FUNC_CORE_PROVIDER_GET0_PROVIDER_CTX:
+ gbl->c_prov_get0_provider_ctx
+ = OSSL_FUNC_core_provider_get0_provider_ctx(in);
+ break;
+ case OSSL_FUNC_CORE_PROVIDER_GET0_DISPATCH:
+ gbl->c_prov_get0_dispatch = OSSL_FUNC_core_provider_get0_dispatch(in);
+ break;
+ default:
+ /* Just ignore anything we don't understand */
+ break;
+ }
+ }
+
+ if (gbl->c_prov_do_all == NULL
+ || gbl->c_prov_name == NULL
+ || gbl->c_prov_get0_provider_ctx == NULL
+ || gbl->c_prov_get0_dispatch == NULL)
+ return 0;
+
+ gbl->childprovs = sk_OSSL_PROVIDER_new_null();
+ if (gbl->childprovs == NULL)
+ return 0;
+ gbl->lock = CRYPTO_THREAD_lock_new();
+ if (gbl->lock == NULL)
+ return 0;
+
+ return 1;
+}
diff --git a/crypto/provider_core.c b/crypto/provider_core.c
index db8763d50d..3e2e2ac335 100644
--- a/crypto/provider_core.c
+++ b/crypto/provider_core.c
@@ -22,6 +22,7 @@
#include "internal/provider.h"
#include "internal/refcount.h"
#include "internal/bio.h"
+#include "internal/core.h"
#include "provider_local.h"
#ifndef FIPS_MODULE
# include <openssl/self_test.h>
@@ -91,8 +92,12 @@ struct ossl_provider_st {
size_t operation_bits_sz;
CRYPTO_RWLOCK *opbits_lock;
+ /* Whether this provider is the child of some other provider */
+ unsigned int ischild:1;
+
/* Provider side data */
void *provctx;
+ const OSSL_DISPATCH *dispatch;
};
DEFINE_STACK_OF(OSSL_PROVIDER)
@@ -234,8 +239,13 @@ OSSL_PROVIDER *ossl_provider_find(OSSL_LIB_CTX *libctx, const char *name,
* Make sure any providers are loaded from config before we try to find
* them.
*/
- if (!noconfig && ossl_lib_ctx_is_default(libctx))
- OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CONFIG, NULL);
+ if (!noconfig) {
+ if (ossl_lib_ctx_is_default(libctx))
+ OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CONFIG, NULL);
+ if (ossl_lib_ctx_is_child(libctx)
+ && !ossl_provider_init_child_providers(libctx))
+ return NULL;
+ }
#endif
tmpl.name = (char *)name;
@@ -362,8 +372,7 @@ void ossl_provider_free(OSSL_PROVIDER *prov)
*/
if (ref == 0) {
if (prov->flag_initialized) {
- if (prov->teardown != NULL)
- prov->teardown(prov->provctx);
+ ossl_provider_teardown(prov);
#ifndef OPENSSL_NO_ERR
# ifndef FIPS_MODULE
if (prov->error_strings != NULL) {
@@ -581,6 +590,7 @@ static int provider_init(OSSL_PROVIDER *prov, int flag_lock)
goto end;
}
prov->provctx = tmp_provctx;
+ prov->dispatch = provider_dispatch;
for (; provider_dispatch->function_id != 0; provider_dispatch++) {
switch (provider_dispatch->function_id) {
@@ -845,6 +855,9 @@ int ossl_provider_doall_activated(OSSL_LIB_CTX *ctx,
*/
if (ossl_lib_ctx_is_default(ctx))
OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CONFIG, NULL);
+ if (ossl_lib_ctx_is_child(ctx)
+ && !ossl_provider_init_child_providers(ctx))
+ return 0;
#endif
if (store == NULL)
@@ -990,6 +1003,14 @@ void *ossl_provider_prov_ctx(const OSSL_PROVIDER *prov)
return NULL;
}
+const OSSL_DISPATCH *ossl_provider_get0_dispatch(const OSSL_PROVIDER *prov)
+{
+ if (prov != NULL)
+ return prov->dispatch;
+
+ return NULL;
+}
+
OSSL_LIB_CTX *ossl_provider_libctx(const OSSL_PROVIDER *prov)
{
return prov != NULL ? prov->libctx : NULL;
@@ -998,7 +1019,7 @@ OSSL_LIB_CTX *ossl_provider_libctx(const OSSL_PROVIDER *prov)
/* Wrappers around calls to the provider */
void ossl_provider_teardown(const OSSL_PROVIDER *prov)
{
- if (prov->teardown != NULL)
+ if (prov->teardown != NULL && !prov->ischild)
prov->teardown(prov->provctx);
}
@@ -1133,6 +1154,11 @@ int ossl_provider_test_operation_bit(OSSL_PROVIDER *provider, size_t bitnum,
return 1;
}
+void ossl_provider_set_child(OSSL_PROVIDER *prov)
+{
+ prov->ischild = 1;
+}
+
/*-
* Core functions for the provider
* ===============================
@@ -1350,7 +1376,15 @@ static const OSSL_DISPATCH core_dispatch_[] = {
{ OSSL_FUNC_CRYPTO_SECURE_ALLOCATED,
(void (*)(void))CRYPTO_secure_allocated },
{ OSSL_FUNC_OPENSSL_CLEANSE, (void (*)(void))OPENSSL_cleanse },
-
+#ifndef FIPS_MODULE
+ { OSSL_FUNC_CORE_PROVIDER_DO_ALL, (void (*)(void))OSSL_PROVIDER_do_all },
+ { OSSL_FUNC_CORE_PROVIDER_NAME,
+ (void (*)(void))OSSL_PROVIDER_name },
+ { OSSL_FUNC_CORE_PROVIDER_GET0_PROVIDER_CTX,
+ (void (*)(void))OSSL_PROVIDER_get0_provider_ctx },
+ { OSSL_FUNC_CORE_PROVIDER_GET0_DISPATCH,
+ (void (*)(void))OSSL_PROVIDER_get0_dispatch },
+#endif
{ 0, NULL }
};
static const OSSL_DISPATCH *core_dispatch = core_dispatch_;
diff --git a/doc/man3/OSSL_LIB_CTX.pod b/doc/man3/OSSL_LIB_CTX.pod
index 9796c8575c..1af8e53d7b 100644
--- a/doc/man3/OSSL_LIB_CTX.pod
+++ b/doc/man3/OSSL_LIB_CTX.pod
@@ -14,7 +14,8 @@ OSSL_LIB_CTX_set0_default
typedef struct ossl_lib_ctx_st OSSL_LIB_CTX;
OSSL_LIB_CTX *OSSL_LIB_CTX_new(void);
- OSSL_LIB_CTX *OSSL_LIB_CTX_new_from_dispatch(const OSSL_DISPATCH *in);
+ OSSL_LIB_CTX *OSSL_LIB_CTX_new_from_dispatch(const OSSL_CORE_HANDLE *handle,
+ const OSSL_DISPATCH *in);
int OSSL_LIB_CTX_load_config(OSSL_LIB_CTX *ctx, const char *config_file);
void OSSL_LIB_CTX_free(OSSL_LIB_CTX *ctx);
OSSL_LIB_CTX *OSSL_LIB_CTX_get0_global_default(void);
@@ -36,10 +37,11 @@ OSSL_LIB_CTX_new() creates a new OpenSSL library context.
OSSL_LIB_CTX_new_from_dispatch() creates a new OpenSSL library context
initialised to use callbacks from the OSSL_DISPATCH structure. This is primarily
-useful for provider authors. The dispatch structure passed should be the same
-one as passed to a provider's OSSL_provider_init function in the I<in> argument.
-Some OpenSSL functions, such as L<BIO_new_from_core_bio(3)>, require the library
-context to be created in this way in order to work.
+useful for provider authors. The I<handle> and dispatch structure arguments
+passed should be the same ones as passed to a provider's
+OSSL_provider_init function. Some OpenSSL functions, such as
+L<BIO_new_from_core_bio(3)>, require the library context to be created in this
+way in order to work.
OSSL_LIB_CTX_load_config() loads a configuration file using the given C<ctx>.
This can be used to associate a library context with providers that are loaded
diff --git a/include/internal/core.h b/include/internal/core.h
index 68b3943679..091b4b2d04 100644
--- a/include/internal/core.h
+++ b/include/internal/core.h
@@ -64,5 +64,6 @@ char *ossl_algorithm_get1_first_name(const OSSL_ALGORITHM *algo);
__owur int ossl_lib_ctx_write_lock(OSSL_LIB_CTX *ctx);
__owur int ossl_lib_ctx_read_lock(OSSL_LIB_CTX *ctx);
int ossl_lib_ctx_unlock(OSSL_LIB_CTX *ctx);
+int ossl_lib_ctx_is_child(OSSL_LIB_CTX *ctx);
#endif
diff --git a/include/internal/cryptlib.h b/include/internal/cryptlib.h
index 94d93abda2..9245a0b870 100644
--- a/include/internal/cryptlib.h
+++ b/include/internal/cryptlib.h
@@ -165,7 +165,8 @@ typedef struct ossl_ex_data_global_st {
# define OSSL_LIB_CTX_STORE_LOADER_STORE_INDEX 15
# define OSSL_LIB_CTX_PROVIDER_CONF_INDEX 16
# define OSSL_LIB_CTX_BIO_CORE_INDEX 17
-# define OSSL_LIB_CTX_MAX_INDEXES 18
+# define OSSL_LIB_CTX_CHILD_PROVIDER_INDEX 18
+# define OSSL_LIB_CTX_MAX_INDEXES 19
# define OSSL_LIB_CTX_METHOD_DEFAULT_PRIORITY 0
# define OSSL_LIB_CTX_METHOD_HIGH_PRIORITY 1
diff --git a/include/internal/provider.h b/include/internal/provider.h
index 64fe2f1178..13b72ad2de 100644
--- a/include/internal/provider.h
+++ b/include/internal/provider.h
@@ -41,6 +41,7 @@ int ossl_provider_set_fallback(OSSL_PROVIDER *prov);
int ossl_provider_set_module_path(OSSL_PROVIDER *prov, const char *module_path);
int ossl_provider_add_parameter(OSSL_PROVIDER *prov, const char *name,
const char *value);
+void ossl_provider_set_child(OSSL_PROVIDER *prov);
/* Disable fallback loading */
int ossl_provider_disable_fallback_loading(OSSL_LIB_CTX *libctx);
@@ -69,6 +70,7 @@ const DSO *ossl_provider_dso(const OSSL_PROVIDER *prov);
const char *ossl_provider_module_name(const OSSL_PROVIDER *prov);
const char *ossl_provider_module_path(const OSSL_PROVIDER *prov);
void *ossl_provider_prov_ctx(const OSSL_PROVIDER *prov);
+const OSSL_DISPATCH *ossl_provider_get0_dispatch(const OSSL_PROVIDER *prov);
OSSL_LIB_CTX *ossl_provider_libctx(const OSSL_PROVIDER *prov);
/* Thin wrappers around calls to the provider */
@@ -96,6 +98,12 @@ int ossl_provider_clear_all_operation_bits(OSSL_LIB_CTX *libctx);
/* Configuration */
void ossl_provider_add_conf_module(void);
+/* Child providers */
+int ossl_provider_init_child_providers(OSSL_LIB_CTX *ctx);
+int ossl_provider_init_as_child(OSSL_LIB_CTX *ctx,
+ const OSSL_CORE_HANDLE *handle,
+ const OSSL_DISPATCH *in);
+
# ifdef __cplusplus
}
# endif
diff --git a/include/openssl/core.h b/include/openssl/core.h
index 3356ef2088..71e860f99d 100644
--- a/include/openssl/core.h
+++ b/include/openssl/core.h
@@ -30,6 +30,7 @@ extern "C" {
typedef struct ossl_core_handle_st OSSL_CORE_HANDLE;
typedef struct openssl_core_ctx_st OPENSSL_CORE_CTX;
typedef struct ossl_core_bio_st OSSL_CORE_BIO;
+typedef struct ossl_core_provider_st OSSL_CORE_PROVIDER;
/*
* Dispatch table element. function_id numbers and the functions are defined
diff --git a/include/openssl/core_dispatch.h b/include/openssl/core_dispatch.h
index d088a66f30..6b5e2e2935 100644
--- a/include/openssl/core_dispatch.h
+++ b/include/openssl/core_dispatch.h
@@ -183,6 +183,23 @@ OSSL_CORE_MAKE_FUNC(size_t, get_nonce, (const OSSL_CORE_HANDLE *handle,
OSSL_CORE_MAKE_FUNC(void, cleanup_nonce, (const OSSL_CORE_HANDLE *handle,
unsigned char *buf, size_t len))
+/* Functions to access the core's providers */
+#define OSSL_FUNC_CORE_PROVIDER_DO_ALL 105
+#define OSSL_FUNC_CORE_PROVIDER_NAME 106
+#define OSSL_FUNC_CORE_PROVIDER_GET0_PROVIDER_CTX 107
+#define OSSL_FUNC_CORE_PROVIDER_GET0_DISPATCH 108
+
+OSSL_CORE_MAKE_FUNC(int, core_provider_do_all, (const OPENSSL_CORE_CTX *ctx,
+ int (*cb)(OSSL_CORE_PROVIDER *provider,
+ void *cbdata),
+ void *cbdata))
+OSSL_CORE_MAKE_FUNC(const char *, core_provider_name,
+ (const OSSL_CORE_PROVIDER *prov))
+OSSL_CORE_MAKE_FUNC(void *, core_provider_get0_provider_ctx,
+ (const OSSL_CORE_PROVIDER *prov))
+OSSL_CORE_MAKE_FUNC(const OSSL_DISPATCH *, core_provider_get0_dispatch,
+ (const OSSL_CORE_PROVIDER *prov))
+
/* Functions provided by the provider to the Core, reserved numbers 1024-1535 */
# define OSSL_FUNC_PROVIDER_TEARDOWN 1024
OSSL_CORE_MAKE_FUNC(void,provider_teardown,(void *provctx))
diff --git a/include/openssl/crypto.h.in b/include/openssl/crypto.h.in
index e868172acc..724e2ca5da 100644
--- a/include/openssl/crypto.h.in
+++ b/include/openssl/crypto.h.in
@@ -37,6 +37,7 @@ use OpenSSL::stackhash qw(generate_stack_macros);
# include <openssl/types.h>
# include <openssl/opensslconf.h>
# include <openssl/cryptoerr.h>
+# include <openssl/core.h>
# ifdef CHARSET_EBCDIC
# include <openssl/ebcdic.h>
@@ -517,7 +518,10 @@ CRYPTO_THREAD_ID CRYPTO_THREAD_get_current_id(void);
int CRYPTO_THREAD_compare_id(CRYPTO_THREAD_ID a, CRYPTO_THREAD_ID b);
OSSL_LIB_CTX *OSSL_LIB_CTX_new(void);
-OSSL_LIB_CTX *OSSL_LIB_CTX_new_from_dispatch(const OSSL_DISPATCH *in);
+OSSL_LIB_CTX *OSSL_LIB_CTX_new_from_dispatch(const OSSL_CORE_HANDLE *handle,
+ const OSSL_DISPATCH *in);
+OSSL_LIB_CTX *OSSL_LIB_CTX_new_child(const OSSL_CORE_HANDLE *handle,
+ const OSSL_DISPATCH *in);
int OSSL_LIB_CTX_load_config(OSSL_LIB_CTX *ctx, const char *config_file);
void OSSL_LIB_CTX_free(OSSL_LIB_CTX *);
OSSL_LIB_CTX *OSSL_LIB_CTX_get0_global_default(void);
diff --git a/include/openssl/provider.h b/include/openssl/provider.h
index 56b430710f..e66d5324af 100644
--- a/include/openssl/provider.h
+++ b/include/openssl/provider.h
@@ -44,6 +44,7 @@ const OSSL_ALGORITHM *OSSL_PROVIDER_query_operation(const OSSL_PROVIDER *prov,
void OSSL_PROVIDER_unquery_operation(const OSSL_PROVIDER *prov,
int operation_id, const OSSL_ALGORITHM *algs);
void *OSSL_PROVIDER_get0_provider_ctx(const OSSL_PROVIDER *prov);
+const OSSL_DISPATCH *OSSL_PROVIDER_get0_dispatch(const OSSL_PROVIDER *prov);
/* Add a built in providers */
int OSSL_PROVIDER_add_builtin(OSSL_LIB_CTX *, const char *name,
diff --git a/test/bio_core_test.c b/test/bio_core_test.c
index 9ec8af9b8f..ae326cef92 100644
--- a/test/bio_core_test.c
+++ b/test/bio_core_test.c
@@ -55,7 +55,7 @@ static const OSSL_DISPATCH biocbs[] = {
static int test_bio_core(void)
{
BIO *cbio = NULL, *cbiobad = NULL;
- OSSL_LIB_CTX *libctx = OSSL_LIB_CTX_new_from_dispatch(biocbs);
+ OSSL_LIB_CTX *libctx = OSSL_LIB_CTX_new_from_dispatch(NULL, biocbs);
int testresult = 0;
OSSL_CORE_BIO corebio;
const char *msg = "Hello world";
diff --git a/util/libcrypto.num b/util/libcrypto.num
index 1820baf4ad..a99b5aa047 100644
--- a/util/libcrypto.num
+++ b/util/libcrypto.num
@@ -5402,3 +5402,5 @@ BIO_new_from_core_bio ? 3_0_0 EXIST::FUNCTION:
BIO_new_ex ? 3_0_0 EXIST::FUNCTION:
BIO_s_core ? 3_0_0 EXIST::FUNCTION:
OSSL_LIB_CTX_new_from_dispatch ? 3_0_0 EXIST::FUNCTION:
+OSSL_LIB_CTX_new_child ? 3_0_0 EXIST::FUNCTION:
+OSSL_PROVIDER_get0_dispatch ? 3_0_0 EXIST::FUNCTION: