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 /crypto | |
parent | 166c0b98fd6e8b1bb341397642527a9396468f6c (diff) |
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)
Diffstat (limited to 'crypto')
-rw-r--r-- | crypto/provider.c | 12 | ||||
-rw-r--r-- | crypto/provider_core.c | 94 |
2 files changed, 65 insertions, 41 deletions
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) { |