diff options
author | Richard Levitte <levitte@openssl.org> | 2021-10-04 15:33:37 +0200 |
---|---|---|
committer | Richard Levitte <levitte@openssl.org> | 2021-10-27 12:41:15 +0200 |
commit | dc010ca6ec01d313a84c3c4b040232655a1772ad (patch) | |
tree | b925e2db5fad6f5c06e5bbac180fe15c223ae8b7 /crypto | |
parent | 433e13455ede1a39d415b690b8a564b4f36b8dee (diff) |
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 <tomas@openssl.org>
Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/16725)
Diffstat (limited to 'crypto')
-rw-r--r-- | crypto/core_fetch.c | 11 | ||||
-rw-r--r-- | crypto/encode_decode/decoder_meth.c | 9 | ||||
-rw-r--r-- | crypto/encode_decode/encoder_meth.c | 9 | ||||
-rw-r--r-- | crypto/evp/evp_fetch.c | 14 | ||||
-rw-r--r-- | crypto/evp/exchange.c | 2 | ||||
-rw-r--r-- | crypto/evp/kem.c | 2 | ||||
-rw-r--r-- | crypto/evp/signature.c | 2 | ||||
-rw-r--r-- | crypto/property/property.c | 73 | ||||
-rw-r--r-- | crypto/store/store_meth.c | 9 |
9 files changed, 82 insertions, 49 deletions
diff --git a/crypto/core_fetch.c b/crypto/core_fetch.c index 26eeaba3b7..367f6ba8a4 100644 --- a/crypto/core_fetch.c +++ b/crypto/core_fetch.c @@ -105,12 +105,14 @@ static void ossl_method_construct_this(OSSL_PROVIDER *provider, } void *ossl_method_construct(OSSL_LIB_CTX *libctx, int operation_id, - OSSL_PROVIDER *provider, int force_store, + OSSL_PROVIDER **provider_rw, int force_store, OSSL_METHOD_CONSTRUCT_METHOD *mcm, void *mcm_data) { void *method = NULL; - if ((method = mcm->get(NULL, mcm_data)) == NULL) { + if ((method = mcm->get(NULL, (const OSSL_PROVIDER **)provider_rw, + mcm_data)) == NULL) { + OSSL_PROVIDER *provider = provider_rw != NULL ? *provider_rw : NULL; struct construct_data_st cbdata; cbdata.store = NULL; @@ -125,11 +127,12 @@ void *ossl_method_construct(OSSL_LIB_CTX *libctx, int operation_id, /* If there is a temporary store, try there first */ if (cbdata.store != NULL) - method = mcm->get(cbdata.store, mcm_data); + method = mcm->get(cbdata.store, (const OSSL_PROVIDER **)provider_rw, + mcm_data); /* If no method was found yet, try the global store */ if (method == NULL) - method = mcm->get(NULL, mcm_data); + method = mcm->get(NULL, (const OSSL_PROVIDER **)provider_rw, mcm_data); } return method; diff --git a/crypto/encode_decode/decoder_meth.c b/crypto/encode_decode/decoder_meth.c index 82515a14a3..6d44437314 100644 --- a/crypto/encode_decode/decoder_meth.c +++ b/crypto/encode_decode/decoder_meth.c @@ -125,7 +125,8 @@ static OSSL_METHOD_STORE *get_decoder_store(OSSL_LIB_CTX *libctx) } /* Get decoder methods from a store, or put one in */ -static void *get_decoder_from_store(void *store, void *data) +static void *get_decoder_from_store(void *store, const OSSL_PROVIDER **prov, + void *data) { struct decoder_data_st *methdata = data; void *method = NULL; @@ -154,7 +155,7 @@ static void *get_decoder_from_store(void *store, void *data) && (store = get_decoder_store(methdata->libctx)) == NULL) return NULL; - if (!ossl_method_store_fetch(store, id, methdata->propquery, &method)) + if (!ossl_method_store_fetch(store, id, methdata->propquery, prov, &method)) return NULL; return method; } @@ -366,7 +367,7 @@ inner_ossl_decoder_fetch(struct decoder_data_st *methdata, int id, unsupported = 1; if (id == 0 - || !ossl_method_store_cache_get(store, id, properties, &method)) { + || !ossl_method_store_cache_get(store, NULL, id, properties, &method)) { OSSL_METHOD_CONSTRUCT_METHOD mcm = { get_tmp_decoder_store, get_decoder_from_store, @@ -391,7 +392,7 @@ inner_ossl_decoder_fetch(struct decoder_data_st *methdata, int id, if (id == 0 && name != NULL) id = ossl_namemap_name2num(namemap, name); if (id != 0) - ossl_method_store_cache_set(store, id, properties, method, + ossl_method_store_cache_set(store, NULL, id, properties, method, up_ref_decoder, free_decoder); } diff --git a/crypto/encode_decode/encoder_meth.c b/crypto/encode_decode/encoder_meth.c index 6526f5e358..9c0214db6b 100644 --- a/crypto/encode_decode/encoder_meth.c +++ b/crypto/encode_decode/encoder_meth.c @@ -125,7 +125,8 @@ static OSSL_METHOD_STORE *get_encoder_store(OSSL_LIB_CTX *libctx) } /* Get encoder methods from a store, or put one in */ -static void *get_encoder_from_store(void *store, void *data) +static void *get_encoder_from_store(void *store, const OSSL_PROVIDER **prov, + void *data) { struct encoder_data_st *methdata = data; void *method = NULL; @@ -154,7 +155,7 @@ static void *get_encoder_from_store(void *store, void *data) && (store = get_encoder_store(methdata->libctx)) == NULL) return NULL; - if (!ossl_method_store_fetch(store, id, methdata->propquery, &method)) + if (!ossl_method_store_fetch(store, id, methdata->propquery, prov, &method)) return NULL; return method; } @@ -376,7 +377,7 @@ inner_ossl_encoder_fetch(struct encoder_data_st *methdata, int id, unsupported = 1; if (id == 0 - || !ossl_method_store_cache_get(store, id, properties, &method)) { + || !ossl_method_store_cache_get(store, NULL, id, properties, &method)) { OSSL_METHOD_CONSTRUCT_METHOD mcm = { get_tmp_encoder_store, get_encoder_from_store, @@ -400,7 +401,7 @@ inner_ossl_encoder_fetch(struct encoder_data_st *methdata, int id, */ if (id == 0) id = ossl_namemap_name2num(namemap, name); - ossl_method_store_cache_set(store, id, properties, method, + ossl_method_store_cache_set(store, NULL, id, properties, method, up_ref_encoder, free_encoder); } diff --git a/crypto/evp/evp_fetch.c b/crypto/evp/evp_fetch.c index ef9e222411..80da3fa4bf 100644 --- a/crypto/evp/evp_fetch.c +++ b/crypto/evp/evp_fetch.c @@ -115,7 +115,8 @@ static uint32_t evp_method_id(int name_id, unsigned int operation_id) | (operation_id & METHOD_ID_OPERATION_MASK)); } -static void *get_evp_method_from_store(void *store, void *data) +static void *get_evp_method_from_store(void *store, const OSSL_PROVIDER **prov, + void *data) { struct evp_method_data_st *methdata = data; void *method = NULL; @@ -146,7 +147,7 @@ static void *get_evp_method_from_store(void *store, void *data) && (store = get_evp_method_store(methdata->libctx)) == NULL) return NULL; - if (!ossl_method_store_fetch(store, meth_id, methdata->propquery, + if (!ossl_method_store_fetch(store, meth_id, methdata->propquery, prov, &method)) return NULL; return method; @@ -298,7 +299,8 @@ inner_evp_generic_fetch(struct evp_method_data_st *methdata, unsupported = 1; if (meth_id == 0 - || !ossl_method_store_cache_get(store, meth_id, properties, &method)) { + || !ossl_method_store_cache_get(store, prov, meth_id, properties, + &method)) { OSSL_METHOD_CONSTRUCT_METHOD mcm = { get_tmp_evp_method_store, get_evp_method_from_store, @@ -316,7 +318,7 @@ inner_evp_generic_fetch(struct evp_method_data_st *methdata, methdata->destruct_method = free_method; methdata->flag_construct_error_occurred = 0; if ((method = ossl_method_construct(methdata->libctx, operation_id, - prov, 0 /* !force_cache */, + &prov, 0 /* !force_cache */, &mcm, methdata)) != NULL) { /* * If construction did create a method for us, we know that @@ -328,8 +330,8 @@ inner_evp_generic_fetch(struct evp_method_data_st *methdata, name_id = ossl_namemap_name2num(namemap, name); meth_id = evp_method_id(name_id, operation_id); if (name_id != 0) - ossl_method_store_cache_set(store, meth_id, properties, method, - up_ref_method, free_method); + ossl_method_store_cache_set(store, prov, meth_id, properties, + method, up_ref_method, free_method); } /* diff --git a/crypto/evp/exchange.c b/crypto/evp/exchange.c index d12dcee947..e2ca30c94d 100644 --- a/crypto/evp/exchange.c +++ b/crypto/evp/exchange.c @@ -274,7 +274,7 @@ int EVP_PKEY_derive_init_ex(EVP_PKEY_CTX *ctx, const OSSL_PARAM params[]) * the second iteration, or jump to legacy. */ for (iter = 1, provkey = NULL; iter < 3 && provkey == NULL; iter++) { - EVP_KEYMGMT *tmp_keymgmt_tofree; + EVP_KEYMGMT *tmp_keymgmt_tofree = NULL; /* * If we're on the second iteration, free the results from the first. diff --git a/crypto/evp/kem.c b/crypto/evp/kem.c index 6ba598eb98..7594888b97 100644 --- a/crypto/evp/kem.c +++ b/crypto/evp/kem.c @@ -76,7 +76,7 @@ static int evp_kem_init(EVP_PKEY_CTX *ctx, int operation, * the second iteration, or jump to legacy. */ for (iter = 1, provkey = NULL; iter < 3 && provkey == NULL; iter++) { - EVP_KEYMGMT *tmp_keymgmt_tofree; + EVP_KEYMGMT *tmp_keymgmt_tofree = NULL; /* * If we're on the second iteration, free the results from the first. diff --git a/crypto/evp/signature.c b/crypto/evp/signature.c index 026a430fe8..49f40c8cec 100644 --- a/crypto/evp/signature.c +++ b/crypto/evp/signature.c @@ -455,7 +455,7 @@ static int evp_pkey_signature_init(EVP_PKEY_CTX *ctx, int operation, * the second iteration, or jump to legacy. */ for (iter = 1; iter < 3 && provkey == NULL; iter++) { - EVP_KEYMGMT *tmp_keymgmt_tofree; + EVP_KEYMGMT *tmp_keymgmt_tofree = NULL; /* * If we're on the second iteration, free the results from the first. 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; diff --git a/crypto/store/store_meth.c b/crypto/store/store_meth.c index d6b0389af9..e79ec871fd 100644 --- a/crypto/store/store_meth.c +++ b/crypto/store/store_meth.c @@ -128,7 +128,8 @@ static OSSL_METHOD_STORE *get_loader_store(OSSL_LIB_CTX *libctx) } /* Get loader methods from a store, or put one in */ -static void *get_loader_from_store(void *store, void *data) +static void *get_loader_from_store(void *store, const OSSL_PROVIDER **prov, + void *data) { struct loader_data_st *methdata = data; void *method = NULL; @@ -144,7 +145,7 @@ static void *get_loader_from_store(void *store, void *data) && (store = get_loader_store(methdata->libctx)) == NULL) return NULL; - if (!ossl_method_store_fetch(store, id, methdata->propquery, &method)) + if (!ossl_method_store_fetch(store, id, methdata->propquery, prov, &method)) return NULL; return method; } @@ -308,7 +309,7 @@ inner_loader_fetch(struct loader_data_st *methdata, int id, unsupported = 1; if (id == 0 - || !ossl_method_store_cache_get(store, id, properties, &method)) { + || !ossl_method_store_cache_get(store, NULL, id, properties, &method)) { OSSL_METHOD_CONSTRUCT_METHOD mcm = { get_tmp_loader_store, get_loader_from_store, @@ -331,7 +332,7 @@ inner_loader_fetch(struct loader_data_st *methdata, int id, */ if (id == 0) id = ossl_namemap_name2num(namemap, scheme); - ossl_method_store_cache_set(store, id, properties, method, + ossl_method_store_cache_set(store, NULL, id, properties, method, up_ref_loader, free_loader); } |