From: Richard Levitte Date: Mon, 4 Oct 2021 13:33:37 +0000 (+0200) Subject: CORE: Encure that cached fetches can be done per provider X-Git-Tag: openssl-3.2.0-alpha1~3409 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=dc010ca6ec01d313a84c3c4b040232655a1772ad;p=thirdparty%2Fopenssl.git 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) --- diff --git a/crypto/core_fetch.c b/crypto/core_fetch.c index 26eeaba3b7a..367f6ba8a47 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 82515a14a33..6d444373147 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 6526f5e3581..9c0214db6bc 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 ef9e222411c..80da3fa4bf8 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 d12dcee9479..e2ca30c94d0 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 6ba598eb98f..7594888b97d 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 026a430fe84..49f40c8cec2 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 a4cd612b9da..5df1bfc221d 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 d6b0389af99..e79ec871fd7 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 7d9b80778db..5d9219fd0e9 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. ossl_method_store_fetch() queries I for a method identified by I that matches the property query I. -The result, if any, is returned in I. +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. @@ -89,10 +91,12 @@ I. ossl_method_store_cache_get() queries the cache associated with the I for a method identified by I that matches the property query I. +Additionally, if I 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. -ossl_method_store_cache_set() sets a cache entry identified by I with the -property query I in the I. +ossl_method_store_cache_set() sets a cache entry identified by I from the +provider I, with the property query I in the I. Future calls to ossl_method_store_cache_get() will return the specified I. The I function is called to increment the reference count of the method and the I function is called diff --git a/doc/internal/man3/ossl_method_construct.pod b/doc/internal/man3/ossl_method_construct.pod index f30e5609dce..3683798b06b 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. 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 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 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. -The method should be associated with the given I, +The method should be associated with the given provider I, I and property definition I as well as any identification data given through I (which is the I that was passed to ossl_construct_method()). diff --git a/include/internal/core.h b/include/internal/core.h index 277f2bdac56..d9dc424164c 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 dd9a2dc2d8f..8211974595d 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 c23ddb0f995..ad44cf15130 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; + } + } else { + if (!TEST_false(ossl_method_store_fetch(store, + queries[i].nid, + queries[i].prop, + &fake_prov1, &result)) + || !TEST_ptr_eq(fake_prov1, &fake_provider1) + || !TEST_ptr_null(result)) { + TEST_note("iteration %zd", i + 1); + ossl_property_free(pq); + goto err; + } + } + ossl_property_free(pq); + } + /* + * The third check of queries is with &address2 given as provider. + */ + for (i = 0; i < OSSL_NELEM(queries); i++) { + OSSL_PROPERTY_LIST *pq = NULL; + + result = NULL; + if (queries[i].prov == &fake_prov2) { + if (!TEST_true(ossl_method_store_fetch(store, + queries[i].nid, + queries[i].prop, + &fake_prov2, &result)) + || !TEST_ptr_eq(fake_prov2, &fake_provider2) + || !TEST_str_eq((char *)result, queries[i].expected)) { + TEST_note("iteration %zd", i + 1); + ossl_property_free(pq); + goto err; + } + } else { + if (!TEST_false(ossl_method_store_fetch(store, + queries[i].nid, + queries[i].prop, + &fake_prov2, &result)) + || !TEST_ptr_eq(fake_prov2, &fake_provider2) + || !TEST_ptr_null(result)) { + TEST_note("iteration %zd", i + 1); + ossl_property_free(pq); + goto err; + } + } + ossl_property_free(pq); + } ret = 1; err: ossl_method_store_free(store); @@ -420,6 +508,7 @@ static int test_query_cache_stochastic(void) void *result; int errors = 0; int v[10001]; + OSSL_PROVIDER prov = { 1 }; if (!TEST_ptr(store = ossl_method_store_new(NULL)) || !add_property_names("n", NULL)) @@ -428,20 +517,21 @@ static int test_query_cache_stochastic(void) for (i = 1; i <= max; i++) { v[i] = 2 * i; BIO_snprintf(buf, sizeof(buf), "n=%d\n", i); - if (!TEST_true(ossl_method_store_add(store, NULL, i, buf, "abc", + if (!TEST_true(ossl_method_store_add(store, &prov, i, buf, "abc", &up_ref, &down_ref)) - || !TEST_true(ossl_method_store_cache_set(store, i, buf, v + i, + || !TEST_true(ossl_method_store_cache_set(store, &prov, i, + buf, v + i, &up_ref, &down_ref)) - || !TEST_true(ossl_method_store_cache_set(store, i, "n=1234", - "miss", &up_ref, - &down_ref))) { + || !TEST_true(ossl_method_store_cache_set(store, &prov, i, + "n=1234", "miss", + &up_ref, &down_ref))) { TEST_note("iteration %d", i); goto err; } } for (i = 1; i <= max; i++) { BIO_snprintf(buf, sizeof(buf), "n=%d\n", i); - if (!ossl_method_store_cache_get(store, i, buf, &result) + if (!ossl_method_store_cache_get(store, NULL, i, buf, &result) || result != v + i) errors++; }