diff options
author | Richard Levitte <levitte@openssl.org> | 2019-07-17 11:29:04 +0200 |
---|---|---|
committer | Richard Levitte <levitte@openssl.org> | 2019-07-26 18:14:41 +0200 |
commit | 36f5ec55e69716024f70df53074a2871e091a3e1 (patch) | |
tree | f8b0a1f6b8a846e6124ac91f50149f2f805395c4 | |
parent | Don't generate an unnecessary Diffie-Hellman key in TLS 1.3 clients. (diff) | |
download | openssl-36f5ec55e69716024f70df53074a2871e091a3e1.tar.xz openssl-36f5ec55e69716024f70df53074a2871e091a3e1.zip |
Add functions to see if a provider is available for use.
Public function OSSL_PROVIDER_available() takes a library context and
a provider name, and returns 1 if it's available for use, i.e. if it's
possible to fetch implementations from it, otherwise 0.
Internal function ossl_provider_activated() returns 1 if the given
OSSL_PROVIDER is activated, otherwise 0.
To make this possible, the activation of fallbacks got refactored out
to a separate function, which ended up simplifying the code.
Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/9398)
-rw-r--r-- | CHANGES | 5 | ||||
-rw-r--r-- | crypto/provider.c | 12 | ||||
-rw-r--r-- | crypto/provider_core.c | 94 | ||||
-rw-r--r-- | doc/internal/man3/ossl_provider_new.pod | 11 | ||||
-rw-r--r-- | doc/man3/OSSL_PROVIDER.pod | 17 | ||||
-rw-r--r-- | include/internal/provider.h | 2 | ||||
-rw-r--r-- | include/internal/symhacks.h | 3 | ||||
-rw-r--r-- | include/openssl/provider.h | 1 | ||||
-rw-r--r-- | util/libcrypto.num | 1 |
9 files changed, 101 insertions, 45 deletions
@@ -9,6 +9,11 @@ Changes between 1.1.1 and 3.0.0 [xx XXX xxxx] + *) Introduced a new function, OSSL_PROVIDER_available(), which can be used + to check if a named provider is loaded and available. When called, it + will also activate all fallback providers if such are still present. + [Richard Levitte] + *) Enforce a minimum DH modulus size of 512 bits. [Bernd Edlinger] diff --git a/crypto/provider.c b/crypto/provider.c index f81260cdab..0250955a70 100644 --- a/crypto/provider.c +++ b/crypto/provider.c @@ -35,6 +35,18 @@ int OSSL_PROVIDER_unload(OSSL_PROVIDER *prov) return 1; } +int OSSL_PROVIDER_available(OPENSSL_CTX *libctx, const char *name) +{ + OSSL_PROVIDER *prov = NULL; + int available = 0; + + /* Find it or create it */ + prov = ossl_provider_find(libctx, name); + available = ossl_provider_available(prov); + ossl_provider_free(prov); + return available; +} + const OSSL_PARAM *OSSL_PROVIDER_get_param_types(const OSSL_PROVIDER *prov) { return ossl_provider_get_param_types(prov); diff --git a/crypto/provider_core.c b/crypto/provider_core.c index 0e86097cd0..385a632653 100644 --- a/crypto/provider_core.c +++ b/crypto/provider_core.c @@ -572,67 +572,79 @@ static int provider_forall_loaded(struct provider_store_st *store, return ret; } +/* + * This function only does something once when store->use_fallbacks == 1, + * and then sets store->use_fallbacks = 0, so the second call and so on is + * effectively a no-op. + */ +static void provider_activate_fallbacks(struct provider_store_st *store) +{ + if (store->use_fallbacks) { + int num_provs = sk_OSSL_PROVIDER_num(store->providers); + int activated_fallback_count = 0; + int i; + + for (i = 0; i < num_provs; i++) { + OSSL_PROVIDER *prov = sk_OSSL_PROVIDER_value(store->providers, i); + + /* + * Note that we don't care if the activation succeeds or not. + * If it doesn't succeed, then any attempt to use any of the + * fallback providers will fail anyway. + */ + if (prov->flag_fallback) { + activated_fallback_count++; + provider_activate(prov); + } + } + + /* + * We assume that all fallbacks have been added to the store before + * any fallback is activated. + * TODO: We may have to reconsider this, IF we find ourselves adding + * fallbacks after any previous fallback has been activated. + */ + if (activated_fallback_count > 0) + store->use_fallbacks = 0; + } +} + int ossl_provider_forall_loaded(OPENSSL_CTX *ctx, int (*cb)(OSSL_PROVIDER *provider, void *cbdata), void *cbdata) { int ret = 1; - int i; struct provider_store_st *store = get_provider_store(ctx); if (store != NULL) { - int found_activated = 0; - CRYPTO_THREAD_read_lock(store->lock); - ret = provider_forall_loaded(store, &found_activated, cb, cbdata); + + provider_activate_fallbacks(store); /* - * If there's nothing activated ever in this store, try to activate - * all fallbacks. + * Now, we sweep through all providers */ - if (!found_activated && store->use_fallbacks) { - int num_provs = sk_OSSL_PROVIDER_num(store->providers); - int activated_fallback_count = 0; - - for (i = 0; i < num_provs; i++) { - OSSL_PROVIDER *prov = - sk_OSSL_PROVIDER_value(store->providers, i); - - /* - * Note that we don't care if the activation succeeds or - * not. If it doesn't succeed, then the next loop will - * fail anyway. - */ - if (prov->flag_fallback) { - activated_fallback_count++; - provider_activate(prov); - } - } + ret = provider_forall_loaded(store, NULL, cb, cbdata); - if (activated_fallback_count > 0) { - /* - * We assume that all fallbacks have been added to the store - * before any fallback is activated. - * TODO: We may have to reconsider this, IF we find ourselves - * adding fallbacks after any previous fallback has been - * activated. - */ - store->use_fallbacks = 0; - - /* - * Now that we've activated available fallbacks, try a - * second sweep - */ - ret = provider_forall_loaded(store, NULL, cb, cbdata); - } - } CRYPTO_THREAD_unlock(store->lock); } return ret; } +int ossl_provider_available(OSSL_PROVIDER *prov) +{ + if (prov != NULL) { + CRYPTO_THREAD_read_lock(prov->store->lock); + provider_activate_fallbacks(prov->store); + CRYPTO_THREAD_unlock(prov->store->lock); + + return prov->flag_initialized; + } + return 0; +} + /* Setters of Provider Object data */ int ossl_provider_set_fallback(OSSL_PROVIDER *prov) { diff --git a/doc/internal/man3/ossl_provider_new.pod b/doc/internal/man3/ossl_provider_new.pod index 426d95393d..255f194e03 100644 --- a/doc/internal/man3/ossl_provider_new.pod +++ b/doc/internal/man3/ossl_provider_new.pod @@ -6,7 +6,7 @@ ossl_provider_find, ossl_provider_new, ossl_provider_up_ref, ossl_provider_free, ossl_provider_set_fallback, ossl_provider_set_module_path, ossl_provider_add_parameter, -ossl_provider_activate, +ossl_provider_activate, ossl_provider_available, ossl_provider_ctx, ossl_provider_forall_loaded, ossl_provider_name, ossl_provider_dso, @@ -33,6 +33,8 @@ ossl_provider_get_params, ossl_provider_query_operation /* Load and initialize the Provider */ int ossl_provider_activate(OSSL_PROVIDER *prov); + /* Check if provider is available */ + int ossl_provider_available(OSSL_PROVIDER *prov); /* Return pointer to the provider's context */ void *ossl_provider_ctx(const OSSL_PROVIDER *prov); @@ -148,6 +150,10 @@ be located in that module, and called. =back +ossl_provider_available() activates all fallbacks if no provider is +activated yet, then checks if given provider object I<prov> is +activated. + ossl_provider_ctx() returns a context created by the provider. Outside of the provider, it's completely opaque, but it needs to be passed back to some of the provider functions. @@ -228,6 +234,9 @@ ossl_provider_free() doesn't return any value. ossl_provider_set_module_path(), ossl_provider_set_fallback() and ossl_provider_activate() return 1 on success, or 0 on error. +ossl_provider_available() return 1 if the provider is available, +otherwise 0. + ossl_provider_name(), ossl_provider_dso(), ossl_provider_module_name(), and ossl_provider_module_path() return a pointer to their respective data if it's available, otherwise NULL diff --git a/doc/man3/OSSL_PROVIDER.pod b/doc/man3/OSSL_PROVIDER.pod index 1453fcc50a..5608bf394c 100644 --- a/doc/man3/OSSL_PROVIDER.pod +++ b/doc/man3/OSSL_PROVIDER.pod @@ -3,6 +3,7 @@ =head1 NAME OSSL_PROVIDER, OSSL_PROVIDER_load, OSSL_PROVIDER_unload, +OSSL_PROVIDER_available, OSSL_PROVIDER_get_param_types, OSSL_PROVIDER_get_params, OSSL_PROVIDER_add_builtin, OSSL_PROVIDER_name - provider routines @@ -12,13 +13,14 @@ OSSL_PROVIDER_add_builtin, OSSL_PROVIDER_name - provider routines typedef struct ossl_provider_st OSSL_PROVIDER; - OSSL_PROVIDER *OSSL_PROVIDER_load(OPENSSL_CTX *, const char *name); + OSSL_PROVIDER *OSSL_PROVIDER_load(OPENSSL_CTX *libctx, const char *name); int OSSL_PROVIDER_unload(OSSL_PROVIDER *prov); + int OSSL_PROVIDER_available(OPENSSL_CTX *libctx, const char *name); const OSSL_PARAM *OSSL_PROVIDER_get_param_types(OSSL_PROVIDER *prov); int OSSL_PROVIDER_get_params(OSSL_PROVIDER *prov, OSSL_PARAM params[]); - int OSSL_PROVIDER_add_builtin(OPENSSL_CTX *, const char *name, + int OSSL_PROVIDER_add_builtin(OPENSSL_CTX *libctx, const char *name, ossl_provider_init_fn *init_fn); const char *OSSL_PROVIDER_name(const OSSL_PROVIDER *prov); @@ -32,6 +34,9 @@ A provider can be built in to the application or the OpenSSL libraries, or can be a loadable module. The functions described here handle both forms. +Some of these functions operate within a library context, please see +L<OPENSSL_CTX(3)> for further details. + =head2 Functions OSSL_PROVIDER_add_builtin() is used to add a built in provider to @@ -49,6 +54,9 @@ OSSL_PROVIDER_unload() unloads the given provider. For a provider added with OSSL_PROVIDER_add_builtin(), this simply runs its teardown function. +OSSL_PROVIDER_available() checks if a named provider is available +for use. + OSSL_PROVIDER_get_param_types() is used to get a provider parameter descriptor set as a constant B<OSSL_PARAM> array. See L<OSSL_PARAM(3)> for more information. @@ -69,6 +77,9 @@ success, or B<NULL> on error. OSSL_PROVIDER_unload() returns 1 on success, or 0 on error. +OSSL_PROVIDER_available() returns 1 if the named provider is available, +otherwise 0. + OSSL_PROVIDER_get_param_types() returns a pointer to an array of constant B<OSSL_PARAM>, or NULL if none is provided. @@ -95,7 +106,7 @@ its build number. =head1 SEE ALSO -L<openssl-core.h(7)>, L<provider(7)> +L<openssl-core.h(7)>, L<OPENSSL_CTX(3)>, L<provider(7)> =head1 HISTORY diff --git a/include/internal/provider.h b/include/internal/provider.h index fbc60fc6ee..aa1876498d 100644 --- a/include/internal/provider.h +++ b/include/internal/provider.h @@ -44,6 +44,8 @@ int ossl_provider_add_parameter(OSSL_PROVIDER *prov, const char *name, * Inactivation is done by freeing the Provider */ int ossl_provider_activate(OSSL_PROVIDER *prov); +/* Check if the provider is available */ +int ossl_provider_available(OSSL_PROVIDER *prov); /* Return pointer to the provider's context */ void *ossl_provider_ctx(const OSSL_PROVIDER *prov); diff --git a/include/internal/symhacks.h b/include/internal/symhacks.h index 2b09604619..6e8f78e642 100644 --- a/include/internal/symhacks.h +++ b/include/internal/symhacks.h @@ -14,6 +14,9 @@ # if defined(OPENSSL_SYS_VMS) +/* ossl_provider_available vs OSSL_PROVIDER_available */ +# undef ossl_provider_available +# define ossl_provider_available ossl_int_prov_available /* ossl_provider_get_param_types vs OSSL_PROVIDER_get_param_types */ # undef ossl_provider_get_param_types # define ossl_provider_get_param_types ossl_int_prov_get_param_types diff --git a/include/openssl/provider.h b/include/openssl/provider.h index 68d5d10a12..d5a62926a7 100644 --- a/include/openssl/provider.h +++ b/include/openssl/provider.h @@ -19,6 +19,7 @@ extern "C" { /* Load and unload a provider */ OSSL_PROVIDER *OSSL_PROVIDER_load(OPENSSL_CTX *, const char *name); int OSSL_PROVIDER_unload(OSSL_PROVIDER *prov); +int OSSL_PROVIDER_available(OPENSSL_CTX *, const char *name); const OSSL_PARAM *OSSL_PROVIDER_get_param_types(const OSSL_PROVIDER *prov); int OSSL_PROVIDER_get_params(const OSSL_PROVIDER *prov, OSSL_PARAM params[]); diff --git a/util/libcrypto.num b/util/libcrypto.num index 1533a88a93..81462480ca 100644 --- a/util/libcrypto.num +++ b/util/libcrypto.num @@ -4699,3 +4699,4 @@ OSSL_PROVIDER_name 4804 3_0_0 EXIST::FUNCTION: EVP_CIPHER_do_all_ex 4805 3_0_0 EXIST::FUNCTION: EVP_MD_do_all_ex 4806 3_0_0 EXIST::FUNCTION: EVP_KEYEXCH_provider 4807 3_0_0 EXIST::FUNCTION: +OSSL_PROVIDER_available 4808 3_0_0 EXIST::FUNCTION: |