From: Richard Levitte Date: Wed, 22 Jul 2020 20:54:54 +0000 (+0200) Subject: STORE: Add the base functions to support provider based loaders X-Git-Tag: openssl-3.0.0-alpha7~490 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=c4fc564d48456be622509886d3ea5618fce2a02e;p=thirdparty%2Fopenssl.git STORE: Add the base functions to support provider based loaders This includes fixing a bug that could only be discovered when no loaders were registered. Reviewed-by: Shane Lontis (Merged from https://github.com/openssl/openssl/pull/12512) --- diff --git a/crypto/store/build.info b/crypto/store/build.info index 7d882f313ea..338c40efccf 100644 --- a/crypto/store/build.info +++ b/crypto/store/build.info @@ -1,4 +1,4 @@ LIBS=../../libcrypto SOURCE[../../libcrypto]=\ store_err.c store_init.c store_lib.c store_register.c store_strings.c \ - loader_file.c + store_meth.c loader_file.c diff --git a/crypto/store/store_local.h b/crypto/store/store_local.h index 47cba87f869..15d40228569 100644 --- a/crypto/store/store_local.h +++ b/crypto/store/store_local.h @@ -7,7 +7,9 @@ * https://www.openssl.org/source/license.html */ +#include #include "internal/thread_once.h" +#include "internal/refcount.h" #include #include #include @@ -100,6 +102,7 @@ OSSL_STORE_LOADER *ossl_store_unregister_loader_int(const char *scheme); /* loader stuff */ struct ossl_store_loader_st { + /* Legacy stuff */ const char *scheme; ENGINE *engine; OSSL_STORE_open_fn open; @@ -112,6 +115,23 @@ struct ossl_store_loader_st { OSSL_STORE_error_fn error; OSSL_STORE_close_fn close; OSSL_STORE_open_with_libctx_fn open_with_libctx; + + /* Provider stuff */ + OSSL_PROVIDER *prov; + int scheme_id; + const char *propdef; + + CRYPTO_REF_COUNT refcnt; + CRYPTO_RWLOCK *lock; + + OSSL_FUNC_store_open_fn *p_open; + OSSL_FUNC_store_attach_fn *p_attach; + OSSL_FUNC_store_settable_ctx_params_fn *p_settable_ctx_params; + OSSL_FUNC_store_set_ctx_params_fn *p_set_ctx_params; + OSSL_FUNC_store_load_fn *p_load; + OSSL_FUNC_store_eof_fn *p_eof; + OSSL_FUNC_store_close_fn *p_close; + OSSL_FUNC_store_export_object_fn *p_export_object; }; DEFINE_LHASH_OF(OSSL_STORE_LOADER); @@ -125,3 +145,22 @@ void ossl_store_destroy_loaders_int(void); int ossl_store_init_once(void); int ossl_store_file_loader_init(void); + +/*- + * 'file' scheme stuff + * ------------------- + */ + +OSSL_STORE_LOADER_CTX *ossl_store_file_attach_pem_bio_int(BIO *bp); +int ossl_store_file_detach_pem_bio_int(OSSL_STORE_LOADER_CTX *ctx); + +/*- + * Provider stuff + * ------------------- + */ +OSSL_STORE_LOADER *ossl_store_loader_fetch(OPENSSL_CTX *libctx, + const char *scheme, + const char *properties); +OSSL_STORE_LOADER *ossl_store_loader_fetch_by_number(OPENSSL_CTX *libctx, + int scheme_id, + const char *properties); diff --git a/crypto/store/store_meth.c b/crypto/store/store_meth.c new file mode 100644 index 00000000000..6af5ec14f24 --- /dev/null +++ b/crypto/store/store_meth.c @@ -0,0 +1,425 @@ +/* + * Copyright 2020 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 +#include "internal/core.h" +#include "internal/namemap.h" +#include "internal/property.h" +#include "internal/provider.h" +#include "store_local.h" + +int OSSL_STORE_LOADER_up_ref(OSSL_STORE_LOADER *loader) +{ + int ref = 0; + + if (loader->prov != NULL) + CRYPTO_UP_REF(&loader->refcnt, &ref, loader->lock); + return 1; +} + +void OSSL_STORE_LOADER_free(OSSL_STORE_LOADER *loader) +{ + if (loader != NULL && loader->prov != NULL) { + int i; + + CRYPTO_DOWN_REF(&loader->refcnt, &i, loader->lock); + if (i > 0) + return; + ossl_provider_free(loader->prov); + CRYPTO_THREAD_lock_free(loader->lock); + } + OPENSSL_free(loader); +} + +/* + * OSSL_STORE_LOADER_new() expects the scheme as a constant string, + * which we currently don't have, so we need an alternative allocator. + */ +static OSSL_STORE_LOADER *new_loader(OSSL_PROVIDER *prov) +{ + OSSL_STORE_LOADER *loader; + + if ((loader = OPENSSL_zalloc(sizeof(*loader))) == NULL + || (loader->lock = CRYPTO_THREAD_lock_new()) == NULL) { + OPENSSL_free(loader); + return NULL; + } + loader->prov = prov; + ossl_provider_up_ref(prov); + loader->refcnt = 1; + + return loader; +} + +static int up_ref_loader(void *method) +{ + return OSSL_STORE_LOADER_up_ref(method); +} + +static void free_loader(void *method) +{ + OSSL_STORE_LOADER_free(method); +} + +/* Permanent loader method store, constructor and destructor */ +static void loader_store_free(void *vstore) +{ + ossl_method_store_free(vstore); +} + +static void *loader_store_new(OPENSSL_CTX *ctx) +{ + return ossl_method_store_new(ctx); +} + + +static const OPENSSL_CTX_METHOD loader_store_method = { + loader_store_new, + loader_store_free, +}; + +/* Data to be passed through ossl_method_construct() */ +struct loader_data_st { + OPENSSL_CTX *libctx; + OSSL_METHOD_CONSTRUCT_METHOD *mcm; + int scheme_id; /* For get_loader_from_store() */ + const char *scheme; /* For get_loader_from_store() */ + const char *propquery; /* For get_loader_from_store() */ +}; + +/* + * Generic routines to fetch / create OSSL_STORE methods with + * ossl_method_construct() + */ + +/* Temporary loader method store, constructor and destructor */ +static void *alloc_tmp_loader_store(OPENSSL_CTX *ctx) +{ + return ossl_method_store_new(ctx); +} + + static void dealloc_tmp_loader_store(void *store) +{ + if (store != NULL) + ossl_method_store_free(store); +} + +/* Get the permanent loader store */ +static OSSL_METHOD_STORE *get_loader_store(OPENSSL_CTX *libctx) +{ + return openssl_ctx_get_data(libctx, OPENSSL_CTX_STORE_LOADER_STORE_INDEX, + &loader_store_method); +} + +/* Get loader methods from a store, or put one in */ +static void *get_loader_from_store(OPENSSL_CTX *libctx, void *store, + void *data) +{ + struct loader_data_st *methdata = data; + void *method = NULL; + int id; + + if ((id = methdata->scheme_id) == 0) { + OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx); + + id = ossl_namemap_name2num(namemap, methdata->scheme); + } + + if (store == NULL + && (store = get_loader_store(libctx)) == NULL) + return NULL; + + if (!ossl_method_store_fetch(store, id, methdata->propquery, &method)) + return NULL; + return method; +} + +static int put_loader_in_store(OPENSSL_CTX *libctx, void *store, + void *method, const OSSL_PROVIDER *prov, + int operation_id, const char *scheme, + const char *propdef, void *unused) +{ + OSSL_NAMEMAP *namemap; + int id; + + if ((namemap = ossl_namemap_stored(libctx)) == NULL + || (id = ossl_namemap_name2num(namemap, scheme)) == 0) + return 0; + + if (store == NULL && (store = get_loader_store(libctx)) == NULL) + return 0; + + return ossl_method_store_add(store, prov, id, propdef, method, + up_ref_loader, free_loader); +} + +static void *loader_from_dispatch(int scheme_id, const OSSL_ALGORITHM *algodef, + OSSL_PROVIDER *prov) +{ + OSSL_STORE_LOADER *loader = NULL; + const OSSL_DISPATCH *fns = algodef->implementation; + + if ((loader = new_loader(prov)) == NULL) + return NULL; + loader->scheme_id = scheme_id; + loader->propdef = algodef->property_definition; + + for (; fns->function_id != 0; fns++) { + switch (fns->function_id) { + case OSSL_FUNC_STORE_OPEN: + if (loader->p_open == NULL) + loader->p_open = OSSL_FUNC_store_open(fns); + break; + case OSSL_FUNC_STORE_ATTACH: + if (loader->p_attach == NULL) + loader->p_attach = OSSL_FUNC_store_attach(fns); + break; + case OSSL_FUNC_STORE_SETTABLE_CTX_PARAMS: + if (loader->p_settable_ctx_params == NULL) + loader->p_settable_ctx_params = + OSSL_FUNC_store_settable_ctx_params(fns); + break; + case OSSL_FUNC_STORE_SET_CTX_PARAMS: + if (loader->p_set_ctx_params == NULL) + loader->p_set_ctx_params = OSSL_FUNC_store_set_ctx_params(fns); + break; + case OSSL_FUNC_STORE_LOAD: + if (loader->p_load == NULL) + loader->p_load = OSSL_FUNC_store_load(fns); + break; + case OSSL_FUNC_STORE_EOF: + if (loader->p_eof == NULL) + loader->p_eof = OSSL_FUNC_store_eof(fns); + break; + case OSSL_FUNC_STORE_CLOSE: + if (loader->p_close == NULL) + loader->p_close = OSSL_FUNC_store_close(fns); + break; + case OSSL_FUNC_STORE_EXPORT_OBJECT: + if (loader->p_export_object == NULL) + loader->p_export_object = OSSL_FUNC_store_export_object(fns); + break; + } + } + + if ((loader->p_open == NULL && loader->p_attach == NULL) + || loader->p_load == NULL + || loader->p_eof == NULL + || loader->p_close == NULL) { + /* Only set_ctx_params is optionaal */ + OSSL_STORE_LOADER_free(loader); + ERR_raise(ERR_LIB_OSSL_STORE, OSSL_STORE_R_LOADER_INCOMPLETE); + return NULL; + } + return loader; +} + +/* + * The core fetching functionality passes the scheme of the implementation. + * This function is responsible to getting an identity number for them, + * then call loader_from_dispatch() with that identity number. + */ +static void *construct_loader(const OSSL_ALGORITHM *algodef, + OSSL_PROVIDER *prov, void *unused) +{ + /* + * This function is only called if get_loader_from_store() returned + * NULL, so it's safe to say that of all the spots to create a new + * namemap entry, this is it. Should the scheme already exist there, we + * know that ossl_namemap_add() will return its corresponding number. + */ + OPENSSL_CTX *libctx = ossl_provider_library_context(prov); + OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx); + const char *scheme = algodef->algorithm_names; + int id = ossl_namemap_add_name(namemap, 0, scheme); + void *method = NULL; + + if (id != 0) + method = loader_from_dispatch(id, algodef, prov); + + return method; +} + +/* Intermediary function to avoid ugly casts, used below */ +static void destruct_loader(void *method, void *data) +{ + OSSL_STORE_LOADER_free(method); +} + +/* Fetching support. Can fetch by numeric identity or by scheme */ +static OSSL_STORE_LOADER *inner_loader_fetch(OPENSSL_CTX *libctx, + int id, const char *scheme, + const char *properties) +{ + OSSL_METHOD_STORE *store = get_loader_store(libctx); + OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx); + void *method = NULL; + + if (store == NULL || namemap == NULL) + return NULL; + + /* + * If we have been passed neither a scheme_id or a scheme, we have an + * internal programming error. + */ + if (!ossl_assert(id != 0 || scheme != NULL)) + return NULL; + + if (id == 0) + id = ossl_namemap_name2num(namemap, scheme); + + if (id == 0 + || !ossl_method_store_cache_get(store, id, properties, &method)) { + OSSL_METHOD_CONSTRUCT_METHOD mcm = { + alloc_tmp_loader_store, + dealloc_tmp_loader_store, + get_loader_from_store, + put_loader_in_store, + construct_loader, + destruct_loader + }; + struct loader_data_st mcmdata; + + mcmdata.libctx = libctx; + mcmdata.mcm = &mcm; + mcmdata.scheme_id = id; + mcmdata.scheme = scheme; + mcmdata.propquery = properties; + if ((method = ossl_method_construct(libctx, OSSL_OP_STORE, + 0 /* !force_cache */, + &mcm, &mcmdata)) != NULL) { + /* + * If construction did create a method for us, we know that there + * is a correct scheme_id, since those have already been calculated + * in get_loader_from_store() and put_loader_in_store() above. + */ + if (id == 0) + id = ossl_namemap_name2num(namemap, scheme); + ossl_method_store_cache_set(store, id, properties, method, + up_ref_loader, free_loader); + } + } + + return method; +} + +OSSL_STORE_LOADER *OSSL_STORE_LOADER_fetch(const char *scheme, + OPENSSL_CTX *libctx, + const char *properties) +{ + return inner_loader_fetch(libctx, 0, scheme, properties); +} + +OSSL_STORE_LOADER *ossl_store_loader_fetch_by_number(OPENSSL_CTX *libctx, + int scheme_id, + const char *properties) +{ + return inner_loader_fetch(libctx, scheme_id, NULL, properties); +} + +/* + * Library of basic method functions + */ + +const OSSL_PROVIDER *OSSL_STORE_LOADER_provider(const OSSL_STORE_LOADER *loader) +{ + if (!ossl_assert(loader != NULL)) { + ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + return loader->prov; +} + +const char *OSSL_STORE_LOADER_properties(const OSSL_STORE_LOADER *loader) +{ + if (!ossl_assert(loader != NULL)) { + ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + return loader->propdef; +} + +int OSSL_STORE_LOADER_number(const OSSL_STORE_LOADER *loader) +{ + if (!ossl_assert(loader != NULL)) { + ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + + return loader->scheme_id; +} + +int OSSL_STORE_LOADER_is_a(const OSSL_STORE_LOADER *loader, const char *name) +{ + if (loader->prov != NULL) { + OPENSSL_CTX *libctx = ossl_provider_library_context(loader->prov); + OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx); + + return ossl_namemap_name2num(namemap, name) == loader->scheme_id; + } + return 0; +} + +struct loader_do_all_data_st { + void (*user_fn)(void *method, void *arg); + void *user_arg; +}; + +static void loader_do_one(OSSL_PROVIDER *provider, + const OSSL_ALGORITHM *algodef, + int no_store, void *vdata) +{ + struct loader_do_all_data_st *data = vdata; + OPENSSL_CTX *libctx = ossl_provider_library_context(provider); + OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx); + const char *name = algodef->algorithm_names; + int id = ossl_namemap_add_name(namemap, 0, name); + void *method = NULL; + + if (id != 0) + method = + loader_from_dispatch(id, algodef, provider); + + if (method != NULL) { + data->user_fn(method, data->user_arg); + OSSL_STORE_LOADER_free(method); + } +} + +void OSSL_STORE_LOADER_do_all_provided(OPENSSL_CTX *libctx, + void (*fn)(OSSL_STORE_LOADER *loader, + void *arg), + void *arg) +{ + struct loader_do_all_data_st data; + + data.user_fn = (void (*)(void *, void *))fn; + data.user_arg = arg; + ossl_algorithm_do_all(libctx, OSSL_OP_STORE, NULL, + NULL, loader_do_one, NULL, + &data); +} + +void OSSL_STORE_LOADER_names_do_all(const OSSL_STORE_LOADER *loader, + void (*fn)(const char *name, void *data), + void *data) +{ + if (loader == NULL) + return; + + if (loader->prov != NULL) { + OPENSSL_CTX *libctx = ossl_provider_library_context(loader->prov); + OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx); + + ossl_namemap_doall_names(namemap, loader->scheme_id, fn, data); + } +} diff --git a/crypto/store/store_register.c b/crypto/store/store_register.c index f5106f00772..94865ee9e03 100644 --- a/crypto/store/store_register.c +++ b/crypto/store/store_register.c @@ -135,11 +135,6 @@ int OSSL_STORE_LOADER_set_close(OSSL_STORE_LOADER *loader, return 1; } -void OSSL_STORE_LOADER_free(OSSL_STORE_LOADER *loader) -{ - OPENSSL_free(loader); -} - /* * Functions for registering OSSL_STORE_LOADERs */ @@ -157,6 +152,14 @@ static int store_loader_cmp(const OSSL_STORE_LOADER *a, } static LHASH_OF(OSSL_STORE_LOADER) *loader_register = NULL; +static int ossl_store_register_init(void) +{ + if (loader_register == NULL) { + loader_register = lh_OSSL_STORE_LOADER_new(store_loader_hash, + store_loader_cmp); + } + return loader_register != NULL; +} int ossl_store_register_loader_int(OSSL_STORE_LOADER *loader) { @@ -197,12 +200,7 @@ int ossl_store_register_loader_int(OSSL_STORE_LOADER *loader) } CRYPTO_THREAD_write_lock(registry_lock); - if (loader_register == NULL) { - loader_register = lh_OSSL_STORE_LOADER_new(store_loader_hash, - store_loader_cmp); - } - - if (loader_register != NULL + if (ossl_store_register_init() && (lh_OSSL_STORE_LOADER_insert(loader_register, loader) != NULL || lh_OSSL_STORE_LOADER_error(loader_register) == 0)) ok = 1; @@ -240,9 +238,11 @@ const OSSL_STORE_LOADER *ossl_store_get0_loader_int(const char *scheme) } CRYPTO_THREAD_write_lock(registry_lock); - loader = lh_OSSL_STORE_LOADER_retrieve(loader_register, &template); - - if (loader == NULL) { + if (!ossl_store_register_init()) { + OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_GET0_LOADER_INT, + ERR_R_INTERNAL_ERROR); + } else if ((loader = lh_OSSL_STORE_LOADER_retrieve(loader_register, + &template)) == NULL) { OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_GET0_LOADER_INT, OSSL_STORE_R_UNREGISTERED_SCHEME); ERR_add_error_data(2, "scheme=", scheme); @@ -271,9 +271,11 @@ OSSL_STORE_LOADER *ossl_store_unregister_loader_int(const char *scheme) } CRYPTO_THREAD_write_lock(registry_lock); - loader = lh_OSSL_STORE_LOADER_delete(loader_register, &template); - - if (loader == NULL) { + if (!ossl_store_register_init()) { + OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_UNREGISTER_LOADER_INT, + ERR_R_INTERNAL_ERROR); + } else if ((loader = lh_OSSL_STORE_LOADER_delete(loader_register, + &template)) == NULL) { OSSL_STOREerr(OSSL_STORE_F_OSSL_STORE_UNREGISTER_LOADER_INT, OSSL_STORE_R_UNREGISTERED_SCHEME); ERR_add_error_data(2, "scheme=", scheme); @@ -292,7 +294,6 @@ OSSL_STORE_LOADER *OSSL_STORE_unregister_loader(const char *scheme) void ossl_store_destroy_loaders_int(void) { - assert(lh_OSSL_STORE_LOADER_num_items(loader_register) == 0); lh_OSSL_STORE_LOADER_free(loader_register); loader_register = NULL; CRYPTO_THREAD_lock_free(registry_lock); @@ -308,6 +309,7 @@ int OSSL_STORE_do_all_loaders(void (*do_function) (const OSSL_STORE_LOADER *loader, void *do_arg), void *do_arg) { - lh_OSSL_STORE_LOADER_doall_void(loader_register, do_function, do_arg); + if (ossl_store_register_init()) + lh_OSSL_STORE_LOADER_doall_void(loader_register, do_function, do_arg); return 1; } diff --git a/doc/man3/OSSL_STORE_LOADER.pod b/doc/man3/OSSL_STORE_LOADER.pod index 3b6c178a9b5..4e25f79f9eb 100644 --- a/doc/man3/OSSL_STORE_LOADER.pod +++ b/doc/man3/OSSL_STORE_LOADER.pod @@ -2,15 +2,24 @@ =head1 NAME -OSSL_STORE_LOADER, OSSL_STORE_LOADER_CTX, OSSL_STORE_LOADER_new, +OSSL_STORE_LOADER, +OSSL_STORE_LOADER_fetch, +OSSL_STORE_LOADER_up_ref, +OSSL_STORE_LOADER_free, +OSSL_STORE_LOADER_provider, +OSSL_STORE_LOADER_properties, +OSSL_STORE_LOADER_is_a, +OSSL_STORE_LOADER_number, +OSSL_STORE_LOADER_do_all_provided, +OSSL_STORE_LOADER_names_do_all, +OSSL_STORE_LOADER_CTX, OSSL_STORE_LOADER_new, OSSL_STORE_LOADER_get0_engine, OSSL_STORE_LOADER_get0_scheme, OSSL_STORE_LOADER_set_open, OSSL_STORE_LOADER_set_open_with_libctx, OSSL_STORE_LOADER_set_attach, OSSL_STORE_LOADER_set_ctrl, OSSL_STORE_LOADER_set_expect, OSSL_STORE_LOADER_set_find, OSSL_STORE_LOADER_set_load, OSSL_STORE_LOADER_set_eof, OSSL_STORE_LOADER_set_error, OSSL_STORE_LOADER_set_close, -OSSL_STORE_LOADER_free, OSSL_STORE_register_loader, -OSSL_STORE_unregister_loader, +OSSL_STORE_register_loader, OSSL_STORE_unregister_loader, OSSL_STORE_open_fn, OSSL_STORE_open_with_libctx_fn, OSSL_STORE_attach_fn, OSSL_STORE_ctrl_fn, OSSL_STORE_expect_fn, OSSL_STORE_find_fn, @@ -24,6 +33,28 @@ unregister STORE loaders for different URI schemes typedef struct ossl_store_loader_st OSSL_STORE_LOADER; + OSSL_STORE_LOADER *OSSL_STORE_LOADER_fetch(const char *scheme, + OPENSSL_CTX *libctx, + const char *properties); + int OSSL_STORE_LOADER_up_ref(OSSL_STORE_LOADER *loader); + void OSSL_STORE_LOADER_free(OSSL_STORE_LOADER *loader); + const OSSL_PROVIDER *OSSL_STORE_LOADER_provider(const OSSL_STORE_LOADER * + loader); + const char *OSSL_STORE_LOADER_properties(const OSSL_STORE_LOADER *loader); + int OSSL_STORE_LOADER_number(const OSSL_STORE_LOADER *loader); + int OSSL_STORE_LOADER_is_a(const OSSL_STORE_LOADER *loader, + const char *scheme); + void OSSL_STORE_LOADER_do_all_provided(OPENSSL_CTX *libctx, + void (*fn)(OSSL_STORE_LOADER *loader, + void *arg), + void *arg); + void OSSL_STORE_LOADER_names_do_all(const OSSL_STORE_LOADER *loader, + void (*fn)(const char *name, void *data), + void *data); + +Legacy functions, still present to support Bs provided +by B: + OSSL_STORE_LOADER *OSSL_STORE_LOADER_new(ENGINE *e, const char *scheme); const ENGINE *OSSL_STORE_LOADER_get0_engine(const OSSL_STORE_LOADER *store_loader); @@ -80,19 +111,49 @@ unregister STORE loaders for different URI schemes =head1 DESCRIPTION -These functions help applications and engines to create loaders for -schemes they support. +B is a method for OSSL_STORE loaders, which implement +OSSL_STORE_open(), OSSL_STORE_open_with_libctx(), OSSL_STORE_load(), +OSSL_STORE_eof(), OSSL_STORE_error() and OSSL_STORE_close() for specific +storage schemes. -=head2 Types +OSSL_STORE_LOADER_fetch() looks for an implementation for a storage +I within the providers that has been loaded into the B +given by I, and with the properties given by I. -B is the type to hold a loader. -It contains a scheme and the functions needed to implement -OSSL_STORE_open(), OSSL_STORE_open_with_libctx(), OSSL_STORE_load(), -OSSL_STORE_eof(), OSSL_STORE_error() and OSSL_STORE_close() for this -scheme. +OSSL_STORE_LOADER_up_ref() increments the reference count for the given +I. + +OSSL_STORE_LOADER_free() decrements the reference count for the given +I, and when the count reaches zero, frees it. + +OSSL_STORE_LOADER_provider() returns the provider of the given +I. + +OSSL_STORE_LOADER_properties() returns the property definition associated +with the given I. + +OSSL_STORE_LOADER_is_a() checks if I is an implementation +of an algorithm that's identifiable with I. + +OSSL_STORE_LOADER_number() returns the internal dynamic number assigned +to the given I. + +OSSL_STORE_LOADER_do_all_provided() traverses all store implementations +by all activated providers in the library context I, and for each +of the implementations, calls I with the implementation method and +I as arguments. + +OSSL_STORE_LOADER_names_do_all() traverses all names for the given +I, and calls I with each name and I. + +=head2 Legacy Types and Functions + +These functions help applications and engines to create loaders for +schemes they support. These are all discouraged in favour of provider +implementations, see L. B is a type template, to be defined by each loader -using B. +using C. B, B, B, B, B, @@ -127,13 +188,13 @@ B. =item B This function takes a B pointer, a command number -B and a B B and is used to manipulate loader +I and a B I and is used to manipulate loader specific parameters. =begin comment Globally known command numbers are documented in L, -along with what B are expected with each of them. +along with what I are expected with each of them. =end comment @@ -146,9 +207,9 @@ This function is expected to return 1 on success, 0 on error. =item B This function takes a B pointer and a B -identity B, and is used to tell the loader what object type is +identity I, and is used to tell the loader what object type is expected. -B may be zero to signify that no specific object type is expected. +I may be zero to signify that no specific object type is expected. This function is expected to return 1 on success, 0 on error. @@ -158,10 +219,10 @@ This function takes a B pointer and a B search criterion, and is used to tell the loader what to search for. -When called with the loader context being B, this function is expected +When called with the loader context being NULL, this function is expected to return 1 if the loader supports the criterion, otherwise 0. -When called with the loader context being something other than B, this +When called with the loader context being something other than NULL, this function is expected to return 1 on success, 0 on error. =item B @@ -200,56 +261,68 @@ It returns 1 on success and 0 on error. =back -=head2 Functions - OSSL_STORE_LOADER_new() creates a new B. -It takes an B B and a string B. -B must I be set. -Both B and B are used as is and must therefore be alive as +It takes an B I and a string I. +I must I be set. +Both I and I are used as is and must therefore be alive as long as the created loader is. -OSSL_STORE_LOADER_get0_engine() returns the engine of the B. -OSSL_STORE_LOADER_get0_scheme() returns the scheme of the B. +OSSL_STORE_LOADER_get0_engine() returns the engine of the I. +OSSL_STORE_LOADER_get0_scheme() returns the scheme of the I. OSSL_STORE_LOADER_set_open() sets the opener function for the -B. +I. OSSL_STORE_LOADER_set_open_with_libctx() sets the opener with library context function for the I. OSSL_STORE_LOADER_set_attach() sets the attacher function for the -B. +I. OSSL_STORE_LOADER_set_ctrl() sets the control function for the -B. +I. OSSL_STORE_LOADER_set_expect() sets the expect function for the -B. +I. OSSL_STORE_LOADER_set_load() sets the loader function for the -B. +I. OSSL_STORE_LOADER_set_eof() sets the end of file checker function for the -B. +I. OSSL_STORE_LOADER_set_close() sets the closing function for the -B. +I. -OSSL_STORE_LOADER_free() frees the given B. +OSSL_STORE_LOADER_free() frees the given I. -OSSL_STORE_register_loader() register the given B and +OSSL_STORE_register_loader() register the given I and thereby makes it available for use with OSSL_STORE_open(), OSSL_STORE_open_with_libctx(), OSSL_STORE_load(), OSSL_STORE_eof() and OSSL_STORE_close(). OSSL_STORE_unregister_loader() unregister the store loader for the given -B. +I. -=head1 NOTES +=head1 RETURN VALUES -The B scheme has built in support. +OSSL_STORE_LOADER_fetch() returns a pointer to an OSSL_STORE_LOADER object, +or NULL on error. -=head1 RETURN VALUES +OSSL_STORE_LOADER_up_ref() returns 1 on success, or 0 on error. + +OSSL_STORE_LOADER_free() doesn't return any value. + +OSSL_STORE_LOADER_provider() returns a pointer to a provider object, or +NULL on error. + +OSSL_STORE_LOADER_properties() returns a pointer to a property +definition string, or NULL on error. + +OSSL_STORE_LOADER_is_a() returns 1 if I was identifiable, +otherwise 0. + +OSSL_STORE_LOADER_number() returns an integer. The functions with the types B, B, B, @@ -259,7 +332,7 @@ OSSL_STORE_open_with_libctx(), OSSL_STORE_ctrl(), OSSL_STORE_expect(), OSSL_STORE_load(), OSSL_STORE_eof() and OSSL_STORE_close(), respectively. OSSL_STORE_LOADER_new() returns a pointer to a B on success, -or B on failure. +or NULL on failure. OSSL_STORE_LOADER_set_open(), OSSL_STORE_LOADER_set_open_with_libctx(), OSSL_STORE_LOADER_set_ctrl(), OSSL_STORE_LOADER_set_load(), @@ -269,14 +342,21 @@ on success, or 0 on failure. OSSL_STORE_register_loader() returns 1 on success, or 0 on failure. OSSL_STORE_unregister_loader() returns the unregistered loader on success, -or B on failure. +or NULL on failure. =head1 SEE ALSO -L, L, L +L, L, L, +L =head1 HISTORY +OSSL_STORE_LOADER_fetch(), OSSL_STORE_LOADER_up_ref(), +OSSL_STORE_LOADER_free(), OSSL_STORE_LOADER_provider(), +OSSL_STORE_LOADER_properties(), OSSL_STORE_LOADER_is_a(), +OSSL_STORE_LOADER_number(), OSSL_STORE_LOADER_do_all_provided() and +OSSL_STORE_LOADER_names_do_all() were added in OpenSSL 3.0. + OSSL_STORE_open_with_libctx_fn() was added in OpenSSL 3.0. B, B, OSSL_STORE_LOADER_new(), diff --git a/include/internal/cryptlib.h b/include/internal/cryptlib.h index 3075bd70c09..1df0c5df343 100644 --- a/include/internal/cryptlib.h +++ b/include/internal/cryptlib.h @@ -160,7 +160,8 @@ typedef struct ossl_ex_data_global_st { # define OPENSSL_CTX_SELF_TEST_CB_INDEX 12 # define OPENSSL_CTX_BIO_PROV_INDEX 13 # define OPENSSL_CTX_GLOBAL_PROPERTIES 14 -# define OPENSSL_CTX_MAX_INDEXES 15 +# define OPENSSL_CTX_STORE_LOADER_STORE_INDEX 15 +# define OPENSSL_CTX_MAX_INDEXES 16 typedef struct openssl_ctx_method { void *(*new_func)(OPENSSL_CTX *ctx); diff --git a/include/openssl/store.h b/include/openssl/store.h index 64a36672319..34f2910202d 100644 --- a/include/openssl/store.h +++ b/include/openssl/store.h @@ -234,6 +234,32 @@ int OSSL_STORE_expect(OSSL_STORE_CTX *ctx, int expected_type); int OSSL_STORE_find(OSSL_STORE_CTX *ctx, const OSSL_STORE_SEARCH *search); +/*- + * Function to fetch a loader and extract data from it + * --------------------------------------------------- + */ + +typedef struct ossl_store_loader_st OSSL_STORE_LOADER; + +OSSL_STORE_LOADER *OSSL_STORE_LOADER_fetch(const char *scheme, + OPENSSL_CTX *libctx, + const char *properties); +int OSSL_STORE_LOADER_up_ref(OSSL_STORE_LOADER *loader); +void OSSL_STORE_LOADER_free(OSSL_STORE_LOADER *loader); +const OSSL_PROVIDER *OSSL_STORE_LOADER_provider(const OSSL_STORE_LOADER * + loader); +const char *OSSL_STORE_LOADER_properties(const OSSL_STORE_LOADER *loader); +int OSSL_STORE_LOADER_number(const OSSL_STORE_LOADER *loader); +int OSSL_STORE_LOADER_is_a(const OSSL_STORE_LOADER *loader, + const char *scheme); +void OSSL_STORE_LOADER_do_all_provided(OPENSSL_CTX *libctx, + void (*fn)(OSSL_STORE_LOADER *loader, + void *arg), + void *arg); +void OSSL_STORE_LOADER_names_do_all(const OSSL_STORE_LOADER *loader, + void (*fn)(const char *name, void *data), + void *data); + /*- * Function to register a loader for the given URI scheme. * ------------------------------------------------------- @@ -242,10 +268,6 @@ int OSSL_STORE_find(OSSL_STORE_CTX *ctx, const OSSL_STORE_SEARCH *search); * scheme. */ -typedef struct ossl_store_loader_st OSSL_STORE_LOADER; -OSSL_STORE_LOADER *OSSL_STORE_LOADER_new(ENGINE *e, const char *scheme); -const ENGINE *OSSL_STORE_LOADER_get0_engine(const OSSL_STORE_LOADER *loader); -const char *OSSL_STORE_LOADER_get0_scheme(const OSSL_STORE_LOADER *loader); /* struct ossl_store_loader_ctx_st is defined differently by each loader */ typedef struct ossl_store_loader_ctx_st OSSL_STORE_LOADER_CTX; typedef OSSL_STORE_LOADER_CTX *(*OSSL_STORE_open_fn) @@ -256,44 +278,47 @@ typedef OSSL_STORE_LOADER_CTX *(*OSSL_STORE_open_with_libctx_fn) const char *uri, OPENSSL_CTX *libctx, const char *propq, const UI_METHOD *ui_method, void *ui_data); +typedef OSSL_STORE_LOADER_CTX *(*OSSL_STORE_attach_fn) + (const OSSL_STORE_LOADER *loader, BIO *bio, + OPENSSL_CTX *libctx, const char *propq, + const UI_METHOD *ui_method, void *ui_data); +typedef int (*OSSL_STORE_ctrl_fn) + (OSSL_STORE_LOADER_CTX *ctx, int cmd, va_list args); +typedef int (*OSSL_STORE_expect_fn) + (OSSL_STORE_LOADER_CTX *ctx, int expected); +typedef int (*OSSL_STORE_find_fn) + (OSSL_STORE_LOADER_CTX *ctx, const OSSL_STORE_SEARCH *criteria); +typedef OSSL_STORE_INFO *(*OSSL_STORE_load_fn) + (OSSL_STORE_LOADER_CTX *ctx, const UI_METHOD *ui_method, void *ui_data); +typedef int (*OSSL_STORE_eof_fn)(OSSL_STORE_LOADER_CTX *ctx); +typedef int (*OSSL_STORE_error_fn)(OSSL_STORE_LOADER_CTX *ctx); +typedef int (*OSSL_STORE_close_fn)(OSSL_STORE_LOADER_CTX *ctx); + +OSSL_STORE_LOADER *OSSL_STORE_LOADER_new(ENGINE *e, const char *scheme); int OSSL_STORE_LOADER_set_open(OSSL_STORE_LOADER *loader, OSSL_STORE_open_fn open_function); int OSSL_STORE_LOADER_set_open_with_libctx (OSSL_STORE_LOADER *loader, OSSL_STORE_open_with_libctx_fn open_with_libctx_function); -typedef OSSL_STORE_LOADER_CTX *(*OSSL_STORE_attach_fn) - (const OSSL_STORE_LOADER *loader, BIO *bio, - OPENSSL_CTX *libctx, const char *propq, - const UI_METHOD *ui_method, void *ui_data); int OSSL_STORE_LOADER_set_attach(OSSL_STORE_LOADER *loader, OSSL_STORE_attach_fn attach_function); -typedef int (*OSSL_STORE_ctrl_fn)(OSSL_STORE_LOADER_CTX *ctx, int cmd, - va_list args); int OSSL_STORE_LOADER_set_ctrl(OSSL_STORE_LOADER *loader, OSSL_STORE_ctrl_fn ctrl_function); -typedef int (*OSSL_STORE_expect_fn)(OSSL_STORE_LOADER_CTX *ctx, int expected); int OSSL_STORE_LOADER_set_expect(OSSL_STORE_LOADER *loader, OSSL_STORE_expect_fn expect_function); -typedef int (*OSSL_STORE_find_fn)(OSSL_STORE_LOADER_CTX *ctx, - const OSSL_STORE_SEARCH *criteria); int OSSL_STORE_LOADER_set_find(OSSL_STORE_LOADER *loader, OSSL_STORE_find_fn find_function); -typedef OSSL_STORE_INFO *(*OSSL_STORE_load_fn)(OSSL_STORE_LOADER_CTX *ctx, - const UI_METHOD *ui_method, - void *ui_data); int OSSL_STORE_LOADER_set_load(OSSL_STORE_LOADER *loader, OSSL_STORE_load_fn load_function); - -typedef int (*OSSL_STORE_eof_fn)(OSSL_STORE_LOADER_CTX *ctx); int OSSL_STORE_LOADER_set_eof(OSSL_STORE_LOADER *loader, OSSL_STORE_eof_fn eof_function); -typedef int (*OSSL_STORE_error_fn)(OSSL_STORE_LOADER_CTX *ctx); int OSSL_STORE_LOADER_set_error(OSSL_STORE_LOADER *loader, OSSL_STORE_error_fn error_function); -typedef int (*OSSL_STORE_close_fn)(OSSL_STORE_LOADER_CTX *ctx); int OSSL_STORE_LOADER_set_close(OSSL_STORE_LOADER *loader, OSSL_STORE_close_fn close_function); -void OSSL_STORE_LOADER_free(OSSL_STORE_LOADER *loader); + +const ENGINE *OSSL_STORE_LOADER_get0_engine(const OSSL_STORE_LOADER *loader); +const char * OSSL_STORE_LOADER_get0_scheme(const OSSL_STORE_LOADER *loader); int OSSL_STORE_register_loader(OSSL_STORE_LOADER *loader); OSSL_STORE_LOADER *OSSL_STORE_unregister_loader(const char *scheme); diff --git a/util/libcrypto.num b/util/libcrypto.num index 54c28ad6886..575731b1454 100644 --- a/util/libcrypto.num +++ b/util/libcrypto.num @@ -5273,3 +5273,11 @@ PEM_read_PUBKEY_ex ? 3_0_0 EXIST::FUNCTION:STDIO PEM_read_bio_Parameters_ex ? 3_0_0 EXIST::FUNCTION: EC_GROUP_new_from_params ? 3_0_0 EXIST::FUNCTION:EC OSSL_STORE_LOADER_set_open_with_libctx ? 3_0_0 EXIST::FUNCTION: +OSSL_STORE_LOADER_fetch ? 3_0_0 EXIST::FUNCTION: +OSSL_STORE_LOADER_up_ref ? 3_0_0 EXIST::FUNCTION: +OSSL_STORE_LOADER_provider ? 3_0_0 EXIST::FUNCTION: +OSSL_STORE_LOADER_properties ? 3_0_0 EXIST::FUNCTION: +OSSL_STORE_LOADER_number ? 3_0_0 EXIST::FUNCTION: +OSSL_STORE_LOADER_is_a ? 3_0_0 EXIST::FUNCTION: +OSSL_STORE_LOADER_do_all_provided ? 3_0_0 EXIST::FUNCTION: +OSSL_STORE_LOADER_names_do_all ? 3_0_0 EXIST::FUNCTION: