From 6e87830ebcbab6b03970da6a4f1070adb938a5ec Mon Sep 17 00:00:00 2001 From: Richard Levitte Date: Mon, 4 Oct 2021 15:33:37 +0200 Subject: CORE: Encure that cached fetches can be done per provider This mostly entails passing around a provider pointer, and handling queries that includes a pointer to a provider, where NULL means "any". This also means that there's a need to pass the provider pointer, not just down to the cache functions, but also be able to get it from ossl_method_store_fetch(). To this end, that function's OSSL_PROVIDER pointer argument is modified to be a pointer reference, so the function can answer back what provider the method comes from. Test added. Fixes #16614 Reviewed-by: Tomas Mraz Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/16725) (cherry picked from commit dc010ca6ec01d313a84c3c4b040232655a1772ad) --- crypto/property/property.c | 73 +++++++++++++++++++++++++++++++--------------- 1 file changed, 49 insertions(+), 24 deletions(-) (limited to 'crypto/property') diff --git a/crypto/property/property.c b/crypto/property/property.c index a4cd612b9d..5df1bfc221 100644 --- a/crypto/property/property.c +++ b/crypto/property/property.c @@ -45,6 +45,7 @@ typedef struct { DEFINE_STACK_OF(IMPLEMENTATION) typedef struct { + const OSSL_PROVIDER *provider; const char *query; METHOD method; char body[1]; @@ -172,7 +173,13 @@ static unsigned long query_hash(const QUERY *a) static int query_cmp(const QUERY *a, const QUERY *b) { - return strcmp(a->query, b->query); + int res = strcmp(a->query, b->query); + + if (res == 0 && a->provider != NULL && b->provider != NULL) + res = b->provider > a->provider ? 1 + : b->provider < a->provider ? -1 + : 0; + return res; } static void impl_free(IMPLEMENTATION *impl) @@ -260,6 +267,9 @@ int ossl_method_store_add(OSSL_METHOD_STORE *store, const OSSL_PROVIDER *prov, if (properties == NULL) properties = ""; + if (!ossl_assert(prov != NULL)) + return 0; + /* Create new entry */ impl = OPENSSL_malloc(sizeof(*impl)); if (impl == NULL) @@ -393,15 +403,15 @@ void ossl_method_store_do_all(OSSL_METHOD_STORE *store, ossl_sa_ALGORITHM_doall_arg(store->algs, alg_do_each, &data); } -int ossl_method_store_fetch(OSSL_METHOD_STORE *store, int nid, - const char *prop_query, - void **method) +int ossl_method_store_fetch(OSSL_METHOD_STORE *store, + int nid, const char *prop_query, + const OSSL_PROVIDER **prov_rw, void **method) { OSSL_PROPERTY_LIST **plp; ALGORITHM *alg; - IMPLEMENTATION *impl; + IMPLEMENTATION *impl, *best_impl = NULL; OSSL_PROPERTY_LIST *pq = NULL, *p2 = NULL; - METHOD *best_method = NULL; + const OSSL_PROVIDER *prov = prov_rw != NULL ? *prov_rw : NULL; int ret = 0; int j, best = -1, score, optional; @@ -438,29 +448,38 @@ int ossl_method_store_fetch(OSSL_METHOD_STORE *store, int nid, } if (pq == NULL) { - if ((impl = sk_IMPLEMENTATION_value(alg->impls, 0)) != NULL) { - best_method = &impl->method; - ret = 1; + for (j = 0; j < sk_IMPLEMENTATION_num(alg->impls); j++) { + if ((impl = sk_IMPLEMENTATION_value(alg->impls, j)) != NULL + && (prov == NULL || impl->provider == prov)) { + best_impl = impl; + ret = 1; + break; + } } goto fin; } optional = ossl_property_has_optional(pq); for (j = 0; j < sk_IMPLEMENTATION_num(alg->impls); j++) { - impl = sk_IMPLEMENTATION_value(alg->impls, j); - score = ossl_property_match_count(pq, impl->properties); - if (score > best) { - best_method = &impl->method; - best = score; - ret = 1; - if (!optional) - goto fin; + if ((impl = sk_IMPLEMENTATION_value(alg->impls, j)) != NULL + && (prov == NULL || impl->provider == prov)) { + score = ossl_property_match_count(pq, impl->properties); + if (score > best) { + best_impl = impl; + best = score; + ret = 1; + if (!optional) + goto fin; + } } } fin: - if (ret && ossl_method_up_ref(best_method)) - *method = best_method->method; - else + if (ret && ossl_method_up_ref(&best_impl->method)) { + *method = best_impl->method.method; + if (prov_rw != NULL) + *prov_rw = best_impl->provider; + } else { ret = 0; + } ossl_property_unlock(store); ossl_property_free(p2); return ret; @@ -569,8 +588,8 @@ static void ossl_method_cache_flush_some(OSSL_METHOD_STORE *store) store->nelem = state.nelem; } -int ossl_method_store_cache_get(OSSL_METHOD_STORE *store, int nid, - const char *prop_query, void **method) +int ossl_method_store_cache_get(OSSL_METHOD_STORE *store, OSSL_PROVIDER *prov, + int nid, const char *prop_query, void **method) { ALGORITHM *alg; QUERY elem, *r; @@ -586,6 +605,7 @@ int ossl_method_store_cache_get(OSSL_METHOD_STORE *store, int nid, goto err; elem.query = prop_query != NULL ? prop_query : ""; + elem.provider = prov; r = lh_QUERY_retrieve(alg->cache, &elem); if (r == NULL) goto err; @@ -598,8 +618,8 @@ err: return res; } -int ossl_method_store_cache_set(OSSL_METHOD_STORE *store, int nid, - const char *prop_query, void *method, +int ossl_method_store_cache_set(OSSL_METHOD_STORE *store, OSSL_PROVIDER *prov, + int nid, const char *prop_query, void *method, int (*method_up_ref)(void *), void (*method_destruct)(void *)) { @@ -613,6 +633,9 @@ int ossl_method_store_cache_set(OSSL_METHOD_STORE *store, int nid, if (prop_query == NULL) return 1; + if (!ossl_assert(prov != NULL)) + return 0; + if (!ossl_property_write_lock(store)) return 0; if (store->need_flush) @@ -623,6 +646,7 @@ int ossl_method_store_cache_set(OSSL_METHOD_STORE *store, int nid, if (method == NULL) { elem.query = prop_query; + elem.provider = prov; if ((old = lh_QUERY_delete(alg->cache, &elem)) != NULL) { impl_cache_free(old); store->nelem--; @@ -632,6 +656,7 @@ int ossl_method_store_cache_set(OSSL_METHOD_STORE *store, int nid, p = OPENSSL_malloc(sizeof(*p) + (len = strlen(prop_query))); if (p != NULL) { p->query = p->body; + p->provider = prov; p->method.method = method; p->method.up_ref = method_up_ref; p->method.free = method_destruct; -- cgit v1.2.3