diff options
author | Richard Levitte <levitte@openssl.org> | 2022-04-22 16:44:51 +0200 |
---|---|---|
committer | Richard Levitte <levitte@openssl.org> | 2022-05-05 15:14:37 +0200 |
commit | 215708c53bc3d62fd29ec842d80fa929910178ee (patch) | |
tree | bd09d7354ca07ebec19cfd0e3ae3cbdf1391adeb /crypto/property | |
parent | 8b76db9e2618225f78c84ed2b338cd005f6ef310 (diff) |
Make it possible to remove methods by the provider that provides them
This adds ossl_method_store_remove_all_provided(), which selectively
removes methods from the given store that are provided by the given
provider.
This also adds the EVP specific evp_method_store_remove_all_provided(),
which matches ossl_method_store_remove_all_provided() but can also
retrieve the correct store to manipulate for EVP functions.
This allows us to modify ossl_provider_self_test() to do the job it's
supposed to do, but through clearly defined functions instead of a
cache flushing call that previously did more than that.
ossl_provider_deactivate() is also modified to remove methods associated
with the deactivated provider, and not just clearing the cache.
Reviewed-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/18151)
(cherry picked from commit 2e4d0677ea858c619a33235265dbee19520a9d35)
Diffstat (limited to 'crypto/property')
-rw-r--r-- | crypto/property/property.c | 70 |
1 files changed, 63 insertions, 7 deletions
diff --git a/crypto/property/property.c b/crypto/property/property.c index b4c0cf06d7..93d12afb18 100644 --- a/crypto/property/property.c +++ b/crypto/property/property.c @@ -88,6 +88,8 @@ typedef struct ossl_global_properties_st { #endif } OSSL_GLOBAL_PROPERTIES; +static void ossl_method_cache_flush_alg(OSSL_METHOD_STORE *store, + ALGORITHM *alg); static void ossl_method_cache_flush(OSSL_METHOD_STORE *store, int nid); /* Global properties are stored per library context */ @@ -205,6 +207,12 @@ static void impl_cache_free(QUERY *elem) } } +static void impl_cache_flush_alg(ossl_uintmax_t idx, ALGORITHM *alg) +{ + lh_QUERY_doall(alg->cache, &impl_cache_free); + lh_QUERY_flush(alg->cache); +} + static void alg_cleanup(ossl_uintmax_t idx, ALGORITHM *a) { if (a != NULL) { @@ -374,6 +382,55 @@ int ossl_method_store_remove(OSSL_METHOD_STORE *store, int nid, return 0; } +struct alg_cleanup_by_provider_data_st { + OSSL_METHOD_STORE *store; + const OSSL_PROVIDER *prov; +}; + +static void +alg_cleanup_by_provider(ossl_uintmax_t idx, ALGORITHM *alg, void *arg) +{ + struct alg_cleanup_by_provider_data_st *data = arg; + int i, count; + + /* + * We walk the stack backwards, to avoid having to deal with stack shifts + * caused by deletion + */ + for (count = 0, i = sk_IMPLEMENTATION_num(alg->impls); i-- > 0;) { + IMPLEMENTATION *impl = sk_IMPLEMENTATION_value(alg->impls, i); + + if (impl->provider == data->prov) { + impl_free(impl); + (void)sk_IMPLEMENTATION_delete(alg->impls, i); + count++; + } + } + + /* + * If we removed any implementation, we also clear the whole associated + * cache, 'cause that's the sensible thing to do. + * There's no point flushing the cache entries where we didn't remove + * any implementation, though. + */ + if (count > 0) + ossl_method_cache_flush_alg(data->store, alg); +} + +int ossl_method_store_remove_all_provided(OSSL_METHOD_STORE *store, + const OSSL_PROVIDER *prov) +{ + struct alg_cleanup_by_provider_data_st data; + + if (!ossl_property_write_lock(store)) + return 0; + data.prov = prov; + data.store = store; + ossl_sa_ALGORITHM_doall_arg(store->algs, &alg_cleanup_by_provider, &data); + ossl_property_unlock(store); + return 1; +} + static void alg_do_one(ALGORITHM *alg, IMPLEMENTATION *impl, void (*fn)(int id, void *method, void *fnarg), void *fnarg) @@ -492,20 +549,19 @@ fin: return ret; } -static void impl_cache_flush_alg(ossl_uintmax_t idx, ALGORITHM *alg) +static void ossl_method_cache_flush_alg(OSSL_METHOD_STORE *store, + ALGORITHM *alg) { - lh_QUERY_doall(alg->cache, &impl_cache_free); - lh_QUERY_flush(alg->cache); + store->cache_nelem -= lh_QUERY_num_items(alg->cache); + impl_cache_flush_alg(0, alg); } static void ossl_method_cache_flush(OSSL_METHOD_STORE *store, int nid) { ALGORITHM *alg = ossl_method_store_retrieve(store, nid); - if (alg != NULL) { - store->cache_nelem -= lh_QUERY_num_items(alg->cache); - impl_cache_flush_alg(0, alg); - } + if (alg != NULL) + ossl_method_cache_flush_alg(store, alg); } int ossl_method_store_cache_flush_all(OSSL_METHOD_STORE *store) |