提交 dc010ca6 编写于 作者: R Richard Levitte

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: NTomas Mraz <tomas@openssl.org>
Reviewed-by: NMatt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/16725)
上级 433e1345
......@@ -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;
......
......@@ -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);
}
......
......@@ -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);
}
......
......@@ -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);
}
/*
......
......@@ -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.
......
......@@ -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.
......
......@@ -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.
......
......@@ -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;
......
......@@ -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);
}
......
......@@ -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
......
......@@ -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()).
......
......@@ -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,
......
......@@ -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 *));
......
......@@ -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++;
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册