summaryrefslogtreecommitdiffstats
path: root/crypto
diff options
context:
space:
mode:
authorRichard Levitte <levitte@openssl.org>2022-04-22 16:44:51 +0200
committerRichard Levitte <levitte@openssl.org>2022-05-05 15:14:37 +0200
commit215708c53bc3d62fd29ec842d80fa929910178ee (patch)
treebd09d7354ca07ebec19cfd0e3ae3cbdf1391adeb /crypto
parent8b76db9e2618225f78c84ed2b338cd005f6ef310 (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')
-rw-r--r--crypto/evp/evp_fetch.c10
-rw-r--r--crypto/property/property.c70
-rw-r--r--crypto/provider_core.c28
3 files changed, 99 insertions, 9 deletions
diff --git a/crypto/evp/evp_fetch.c b/crypto/evp/evp_fetch.c
index fd2b38c100..90d6a4e6d4 100644
--- a/crypto/evp/evp_fetch.c
+++ b/crypto/evp/evp_fetch.c
@@ -438,6 +438,16 @@ int evp_method_store_cache_flush(OSSL_LIB_CTX *libctx)
return 1;
}
+int evp_method_store_remove_all_provided(const OSSL_PROVIDER *prov)
+{
+ OSSL_LIB_CTX *libctx = ossl_provider_libctx(prov);
+ OSSL_METHOD_STORE *store = get_evp_method_store(libctx);
+
+ if (store != NULL)
+ return ossl_method_store_remove_all_provided(store, prov);
+ return 1;
+}
+
static int evp_set_parsed_default_properties(OSSL_LIB_CTX *libctx,
OSSL_PROPERTY_LIST *def_prop,
int loadconfig,
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)
diff --git a/crypto/provider_core.c b/crypto/provider_core.c
index a2520efa1c..fef6fdca9b 100644
--- a/crypto/provider_core.c
+++ b/crypto/provider_core.c
@@ -1164,6 +1164,30 @@ static int provider_flush_store_cache(const OSSL_PROVIDER *prov)
return 1;
}
+static int provider_remove_store_methods(OSSL_PROVIDER *prov)
+{
+ struct provider_store_st *store;
+ int freeing;
+
+ if ((store = get_provider_store(prov->libctx)) == NULL)
+ return 0;
+
+ if (!CRYPTO_THREAD_read_lock(store->lock))
+ return 0;
+ freeing = store->freeing;
+ CRYPTO_THREAD_unlock(store->lock);
+
+ if (!freeing) {
+ OPENSSL_free(prov->operation_bits);
+ prov->operation_bits = NULL;
+ prov->operation_bits_sz = 0;
+ CRYPTO_THREAD_unlock(prov->opbits_lock);
+
+ return evp_method_store_remove_all_provided(prov);
+ }
+ return 1;
+}
+
int ossl_provider_activate(OSSL_PROVIDER *prov, int upcalls, int aschild)
{
int count;
@@ -1191,7 +1215,7 @@ int ossl_provider_deactivate(OSSL_PROVIDER *prov, int removechildren)
if (prov == NULL
|| (count = provider_deactivate(prov, 1, removechildren)) < 0)
return 0;
- return count == 0 ? provider_flush_store_cache(prov) : 1;
+ return count == 0 ? provider_remove_store_methods(prov) : 1;
}
void *ossl_provider_ctx(const OSSL_PROVIDER *prov)
@@ -1500,7 +1524,7 @@ int ossl_provider_self_test(const OSSL_PROVIDER *prov)
return 1;
ret = prov->self_test(prov->provctx);
if (ret == 0)
- (void)provider_flush_store_cache(prov);
+ (void)provider_remove_store_methods((OSSL_PROVIDER *)prov);
return ret;
}