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 | |
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)
-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 | ||||
-rw-r--r-- | doc/internal/man3/OSSL_METHOD_STORE.pod | 22 | ||||
-rw-r--r-- | doc/internal/man3/ossl_method_construct.pod | 26 | ||||
-rw-r--r-- | include/internal/core.h | 4 | ||||
-rw-r--r-- | include/internal/property.h | 13 | ||||
-rw-r--r-- | test/property_test.c | 146 |
14 files changed, 234 insertions, 108 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); } diff --git a/doc/internal/man3/OSSL_METHOD_STORE.pod b/doc/internal/man3/OSSL_METHOD_STORE.pod index 7d9b80778d..5d9219fd0e 100644 --- a/doc/internal/man3/OSSL_METHOD_STORE.pod +++ b/doc/internal/man3/OSSL_METHOD_STORE.pod @@ -27,14 +27,14 @@ ossl_method_store_flush_cache int nid, const void *method); int ossl_method_store_fetch(OSSL_METHOD_STORE *store, int nid, const char *properties, - void **method); - int ossl_method_store_cache_get(OSSL_METHOD_STORE *store, int nid, - const char *prop_query, void **method); - int ossl_method_store_cache_set(OSSL_METHOD_STORE *store, int nid, - const char *prop_query, void *method, + void **method, const OSSL_PROVIDER **prov_rw); + int ossl_method_store_cache_get(OSSL_METHOD_STORE *store, OSSL_PROVIDER *prov, + 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 *)); - void ossl_method_store_flush_cache(OSSL_METHOD_STORE *store); + void ossl_method_store_flush_cache(OSSL_METHOD_STORE *store, int all); =head1 DESCRIPTION @@ -79,7 +79,9 @@ I<store>. ossl_method_store_fetch() queries I<store> for a method identified by I<nid> that matches the property query I<prop_query>. -The result, if any, is returned in I<method>. +I<*prop> may be a pointer to a provider, which will narrow the search +to methods from that provider. +The result, if any, is returned in I<*method>, and its provider in I<*prov>. ossl_method_store_flush_cache() flushes all cached entries associated with I<store>. @@ -89,10 +91,12 @@ I<store>. ossl_method_store_cache_get() queries the cache associated with the I<store> for a method identified by I<nid> that matches the property query I<prop_query>. +Additionally, if I<prov> isn't NULL, it will be used to narrow the search +to only include methods from that provider. The result, if any, is returned in I<method>. -ossl_method_store_cache_set() sets a cache entry identified by I<nid> with the -property query I<prop_query> in the I<store>. +ossl_method_store_cache_set() sets a cache entry identified by I<nid> from the +provider I<prov>, with the property query I<prop_query> in the I<store>. Future calls to ossl_method_store_cache_get() will return the specified I<method>. The I<method_up_ref> function is called to increment the reference count of the method and the I<method_destruct> function is called diff --git a/doc/internal/man3/ossl_method_construct.pod b/doc/internal/man3/ossl_method_construct.pod index f30e5609dc..3683798b06 100644 --- a/doc/internal/man3/ossl_method_construct.pod +++ b/doc/internal/man3/ossl_method_construct.pod @@ -13,16 +13,15 @@ OSSL_METHOD_CONSTRUCT_METHOD, ossl_method_construct /* Get a temporary store */ void *(*get_tmp_store)(void *data); /* Get an already existing method from a store */ - void *(*get)(void *store, void *data); + void *(*get)(void *store, const OSSL_PROVIDER *prov, void *data); /* Store a method in a store */ - int (*put)(void *store, void *method, - const OSSL_PROVIDER *prov, const char *name, - const char *propdef, void *data); + int (*put)(void *store, void *method, const OSSL_PROVIDER *prov, + const char *name, const char *propdef, void *data); /* Construct a new method */ - void *(*construct)(const char *name, const OSSL_DISPATCH *fns, - OSSL_PROVIDER *prov, void *data); + void *(*construct)(const OSSL_ALGORITHM *algodef, OSSL_PROVIDER *prov, + void *data); /* Destruct a method */ - void (*destruct)(void *method); + void (*destruct)(void *method, void *data); }; typedef struct ossl_method_construct_method OSSL_METHOD_CONSTRUCT_METHOD; @@ -75,17 +74,13 @@ function pointers: =over 4 -=item alloc_tmp_store() +=item get_tmp_store() Create a temporary method store in the scope of the library context I<ctx>. This store is used to temporarily store methods for easier lookup, for when the provider doesn't want its dispatch table stored in a longer term cache. -=item dealloc_tmp_store() - -Remove a temporary store. - =item get() Look up an already existing method from a store by name. @@ -100,7 +95,10 @@ The method to be looked up should be identified with data found in I<data> In other words, the ossl_method_construct() caller is entirely responsible for ensuring the necesssary data is made available. -This function is expected to increment the method's reference count. +Optionally, I<prov> may be given as a search criterion, to narrow down the +search of a method belonging to just one provider. + +This function is expected to increment the resulting method's reference count. =item put() @@ -112,7 +110,7 @@ NULL is a valid value and means that a subsystem default store must be used. This default store should be stored in the library context I<libctx>. -The method should be associated with the given I<operation_id>, +The method should be associated with the given provider I<prov>, I<name> and property definition I<propdef> as well as any identification data given through I<data> (which is the I<mcm_data> that was passed to ossl_construct_method()). diff --git a/include/internal/core.h b/include/internal/core.h index 277f2bdac5..d9dc424164 100644 --- a/include/internal/core.h +++ b/include/internal/core.h @@ -31,7 +31,7 @@ typedef struct ossl_method_construct_method_st { /* Get a temporary store */ void *(*get_tmp_store)(void *data); /* Get an already existing method from a store */ - void *(*get)(void *store, void *data); + void *(*get)(void *store, const OSSL_PROVIDER **prov, void *data); /* Store a method in a store */ int (*put)(void *store, void *method, const OSSL_PROVIDER *prov, const char *name, const char *propdef, void *data); @@ -43,7 +43,7 @@ typedef struct ossl_method_construct_method_st { } OSSL_METHOD_CONSTRUCT_METHOD; void *ossl_method_construct(OSSL_LIB_CTX *ctx, int operation_id, - OSSL_PROVIDER *prov, int force_cache, + OSSL_PROVIDER **provider_rw, int force_cache, OSSL_METHOD_CONSTRUCT_METHOD *mcm, void *mcm_data); void ossl_algorithm_do_all(OSSL_LIB_CTX *libctx, int operation_id, diff --git a/include/internal/property.h b/include/internal/property.h index dd9a2dc2d8..8211974595 100644 --- a/include/internal/property.h +++ b/include/internal/property.h @@ -61,18 +61,19 @@ int ossl_method_store_remove(OSSL_METHOD_STORE *store, int nid, void ossl_method_store_do_all(OSSL_METHOD_STORE *store, void (*fn)(int id, void *method, void *fnarg), void *fnarg); -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, void **method); /* Get the global properties associate with the specified library context */ OSSL_PROPERTY_LIST **ossl_ctx_global_properties(OSSL_LIB_CTX *ctx, int loadconfig); /* property query cache functions */ -int ossl_method_store_cache_get(OSSL_METHOD_STORE *store, int nid, - const char *prop_query, void **result); -int ossl_method_store_cache_set(OSSL_METHOD_STORE *store, int nid, - const char *prop_query, void *result, +int ossl_method_store_cache_get(OSSL_METHOD_STORE *store, OSSL_PROVIDER *prov, + int nid, const char *prop_query, void **result); +int ossl_method_store_cache_set(OSSL_METHOD_STORE *store, OSSL_PROVIDER *prov, + int nid, const char *prop_query, void *result, int (*method_up_ref)(void *), void (*method_destruct)(void *)); diff --git a/test/property_test.c b/test/property_test.c index c23ddb0f99..ad44cf1513 100644 --- a/test/property_test.c +++ b/test/property_test.c @@ -15,6 +15,16 @@ #include "internal/property.h" #include "../crypto/property/property_local.h" +/* + * We make our OSSL_PROVIDER for testing purposes. All we really need is + * a pointer. We know that as long as we don't try to use the method + * cache flush functions, the provider pointer is merely a pointer being + * passed around, and used as a tag of sorts. + */ +struct ossl_provider_st { + int x; +}; + static int add_property_names(const char *n, ...) { va_list args; @@ -313,13 +323,14 @@ static int test_register_deregister(void) size_t i; int ret = 0; OSSL_METHOD_STORE *store; + OSSL_PROVIDER prov = { 1 }; if (!TEST_ptr(store = ossl_method_store_new(NULL)) || !add_property_names("position", NULL)) goto err; for (i = 0; i < OSSL_NELEM(impls); i++) - if (!TEST_true(ossl_method_store_add(store, NULL, impls[i].nid, + if (!TEST_true(ossl_method_store_add(store, &prov, impls[i].nid, impls[i].prop, impls[i].impl, &up_ref, &down_ref))) { TEST_note("iteration %zd", i + 1); @@ -348,34 +359,40 @@ err: static int test_property(void) { + static OSSL_PROVIDER fake_provider1 = { 1 }; + static OSSL_PROVIDER fake_provider2 = { 2 }; + static const OSSL_PROVIDER *fake_prov1 = &fake_provider1; + static const OSSL_PROVIDER *fake_prov2 = &fake_provider2; static const struct { + const OSSL_PROVIDER **prov; int nid; const char *prop; char *impl; } impls[] = { - { 1, "fast=no, colour=green", "a" }, - { 1, "fast, colour=blue", "b" }, - { 1, "", "-" }, - { 9, "sky=blue, furry", "c" }, - { 3, NULL, "d" }, - { 6, "sky.colour=blue, sky=green, old.data", "e" }, + { &fake_prov1, 1, "fast=no, colour=green", "a" }, + { &fake_prov1, 1, "fast, colour=blue", "b" }, + { &fake_prov1, 1, "", "-" }, + { &fake_prov2, 9, "sky=blue, furry", "c" }, + { &fake_prov2, 3, NULL, "d" }, + { &fake_prov2, 6, "sky.colour=blue, sky=green, old.data", "e" }, }; static struct { + const OSSL_PROVIDER **prov; int nid; const char *prop; char *expected; } queries[] = { - { 1, "fast", "b" }, - { 1, "fast=yes", "b" }, - { 1, "fast=no, colour=green", "a" }, - { 1, "colour=blue, fast", "b" }, - { 1, "colour=blue", "b" }, - { 9, "furry", "c" }, - { 6, "sky.colour=blue", "e" }, - { 6, "old.data", "e" }, - { 9, "furry=yes, sky=blue", "c" }, - { 1, "", "a" }, - { 3, "", "d" }, + { &fake_prov1, 1, "fast", "b" }, + { &fake_prov1, 1, "fast=yes", "b" }, + { &fake_prov1, 1, "fast=no, colour=green", "a" }, + { &fake_prov1, 1, "colour=blue, fast", "b" }, + { &fake_prov1, 1, "colour=blue", "b" }, + { &fake_prov2, 9, "furry", "c" }, + { &fake_prov2, 6, "sky.colour=blue", "e" }, + { &fake_prov2, 6, "old.data", "e" }, + { &fake_prov2, 9, "furry=yes, sky=blue", "c" }, + { &fake_prov1, 1, "", "a" }, + { &fake_prov2, 3, "", "d" }, }; OSSL_METHOD_STORE *store; size_t i; @@ -387,17 +404,24 @@ static int test_property(void) goto err; for (i = 0; i < OSSL_NELEM(impls); i++) - if (!TEST_true(ossl_method_store_add(store, NULL, impls[i].nid, - impls[i].prop, impls[i].impl, + if (!TEST_true(ossl_method_store_add(store, *impls[i].prov, + impls[i].nid, impls[i].prop, + impls[i].impl, &up_ref, &down_ref))) { TEST_note("iteration %zd", i + 1); goto err; } + /* + * The first check of queries is with NULL given as provider. All + * queries are expected to succeed. + */ for (i = 0; i < OSSL_NELEM(queries); i++) { + const OSSL_PROVIDER *nullprov = NULL; OSSL_PROPERTY_LIST *pq = NULL; - if (!TEST_true(ossl_method_store_fetch(store, queries[i].nid, - queries[i].prop, &result)) + if (!TEST_true(ossl_method_store_fetch(store, + queries[i].nid, queries[i].prop, + &nullprov, &result)) || !TEST_str_eq((char *)result, queries[i].expected)) { TEST_note("iteration %zd", i + 1); ossl_property_free(pq); @@ -405,6 +429,70 @@ static int test_property(void) } ossl_property_free(pq); } + /* + * The second check of queries is with &address1 given as provider. + */ + for (i = 0; i < OSSL_NELEM(queries); i++) { + OSSL_PROPERTY_LIST *pq = NULL; + + result = NULL; + if (queries[i].prov == &fake_prov1) { + if (!TEST_true(ossl_method_store_fetch(store, + queries[i].nid, + queries[i].prop, + &fake_prov1, &result)) + || !TEST_ptr_eq(fake_prov1, &fake_provider1) + || !TEST_str_eq((char *)result, queries[i].expected)) { + TEST_note("iteration %zd", i + 1); + ossl_property_free(pq); + goto err; |