提交 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, ...@@ -105,12 +105,14 @@ static void ossl_method_construct_this(OSSL_PROVIDER *provider,
} }
void *ossl_method_construct(OSSL_LIB_CTX *libctx, int operation_id, 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) OSSL_METHOD_CONSTRUCT_METHOD *mcm, void *mcm_data)
{ {
void *method = NULL; 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; struct construct_data_st cbdata;
cbdata.store = NULL; cbdata.store = NULL;
...@@ -125,11 +127,12 @@ void *ossl_method_construct(OSSL_LIB_CTX *libctx, int operation_id, ...@@ -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 there is a temporary store, try there first */
if (cbdata.store != NULL) 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 no method was found yet, try the global store */
if (method == NULL) if (method == NULL)
method = mcm->get(NULL, mcm_data); method = mcm->get(NULL, (const OSSL_PROVIDER **)provider_rw, mcm_data);
} }
return method; return method;
......
...@@ -125,7 +125,8 @@ static OSSL_METHOD_STORE *get_decoder_store(OSSL_LIB_CTX *libctx) ...@@ -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 */ /* 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; struct decoder_data_st *methdata = data;
void *method = NULL; void *method = NULL;
...@@ -154,7 +155,7 @@ static void *get_decoder_from_store(void *store, void *data) ...@@ -154,7 +155,7 @@ static void *get_decoder_from_store(void *store, void *data)
&& (store = get_decoder_store(methdata->libctx)) == NULL) && (store = get_decoder_store(methdata->libctx)) == NULL)
return 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 NULL;
return method; return method;
} }
...@@ -366,7 +367,7 @@ inner_ossl_decoder_fetch(struct decoder_data_st *methdata, int id, ...@@ -366,7 +367,7 @@ inner_ossl_decoder_fetch(struct decoder_data_st *methdata, int id,
unsupported = 1; unsupported = 1;
if (id == 0 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 = { OSSL_METHOD_CONSTRUCT_METHOD mcm = {
get_tmp_decoder_store, get_tmp_decoder_store,
get_decoder_from_store, get_decoder_from_store,
...@@ -391,7 +392,7 @@ inner_ossl_decoder_fetch(struct decoder_data_st *methdata, int id, ...@@ -391,7 +392,7 @@ inner_ossl_decoder_fetch(struct decoder_data_st *methdata, int id,
if (id == 0 && name != NULL) if (id == 0 && name != NULL)
id = ossl_namemap_name2num(namemap, name); id = ossl_namemap_name2num(namemap, name);
if (id != 0) 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); up_ref_decoder, free_decoder);
} }
......
...@@ -125,7 +125,8 @@ static OSSL_METHOD_STORE *get_encoder_store(OSSL_LIB_CTX *libctx) ...@@ -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 */ /* 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; struct encoder_data_st *methdata = data;
void *method = NULL; void *method = NULL;
...@@ -154,7 +155,7 @@ static void *get_encoder_from_store(void *store, void *data) ...@@ -154,7 +155,7 @@ static void *get_encoder_from_store(void *store, void *data)
&& (store = get_encoder_store(methdata->libctx)) == NULL) && (store = get_encoder_store(methdata->libctx)) == NULL)
return 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 NULL;
return method; return method;
} }
...@@ -376,7 +377,7 @@ inner_ossl_encoder_fetch(struct encoder_data_st *methdata, int id, ...@@ -376,7 +377,7 @@ inner_ossl_encoder_fetch(struct encoder_data_st *methdata, int id,
unsupported = 1; unsupported = 1;
if (id == 0 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 = { OSSL_METHOD_CONSTRUCT_METHOD mcm = {
get_tmp_encoder_store, get_tmp_encoder_store,
get_encoder_from_store, get_encoder_from_store,
...@@ -400,7 +401,7 @@ inner_ossl_encoder_fetch(struct encoder_data_st *methdata, int id, ...@@ -400,7 +401,7 @@ inner_ossl_encoder_fetch(struct encoder_data_st *methdata, int id,
*/ */
if (id == 0) if (id == 0)
id = ossl_namemap_name2num(namemap, name); 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); up_ref_encoder, free_encoder);
} }
......
...@@ -115,7 +115,8 @@ static uint32_t evp_method_id(int name_id, unsigned int operation_id) ...@@ -115,7 +115,8 @@ static uint32_t evp_method_id(int name_id, unsigned int operation_id)
| (operation_id & METHOD_ID_OPERATION_MASK)); | (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; struct evp_method_data_st *methdata = data;
void *method = NULL; void *method = NULL;
...@@ -146,7 +147,7 @@ static void *get_evp_method_from_store(void *store, void *data) ...@@ -146,7 +147,7 @@ static void *get_evp_method_from_store(void *store, void *data)
&& (store = get_evp_method_store(methdata->libctx)) == NULL) && (store = get_evp_method_store(methdata->libctx)) == NULL)
return 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)) &method))
return NULL; return NULL;
return method; return method;
...@@ -298,7 +299,8 @@ inner_evp_generic_fetch(struct evp_method_data_st *methdata, ...@@ -298,7 +299,8 @@ inner_evp_generic_fetch(struct evp_method_data_st *methdata,
unsupported = 1; unsupported = 1;
if (meth_id == 0 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 = { OSSL_METHOD_CONSTRUCT_METHOD mcm = {
get_tmp_evp_method_store, get_tmp_evp_method_store,
get_evp_method_from_store, get_evp_method_from_store,
...@@ -316,7 +318,7 @@ inner_evp_generic_fetch(struct evp_method_data_st *methdata, ...@@ -316,7 +318,7 @@ inner_evp_generic_fetch(struct evp_method_data_st *methdata,
methdata->destruct_method = free_method; methdata->destruct_method = free_method;
methdata->flag_construct_error_occurred = 0; methdata->flag_construct_error_occurred = 0;
if ((method = ossl_method_construct(methdata->libctx, operation_id, if ((method = ossl_method_construct(methdata->libctx, operation_id,
prov, 0 /* !force_cache */, &prov, 0 /* !force_cache */,
&mcm, methdata)) != NULL) { &mcm, methdata)) != NULL) {
/* /*
* If construction did create a method for us, we know that * 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, ...@@ -328,8 +330,8 @@ inner_evp_generic_fetch(struct evp_method_data_st *methdata,
name_id = ossl_namemap_name2num(namemap, name); name_id = ossl_namemap_name2num(namemap, name);
meth_id = evp_method_id(name_id, operation_id); meth_id = evp_method_id(name_id, operation_id);
if (name_id != 0) if (name_id != 0)
ossl_method_store_cache_set(store, meth_id, properties, method, ossl_method_store_cache_set(store, prov, meth_id, properties,
up_ref_method, free_method); method, up_ref_method, free_method);
} }
/* /*
......
...@@ -274,7 +274,7 @@ int EVP_PKEY_derive_init_ex(EVP_PKEY_CTX *ctx, const OSSL_PARAM params[]) ...@@ -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. * the second iteration, or jump to legacy.
*/ */
for (iter = 1, provkey = NULL; iter < 3 && provkey == NULL; iter++) { 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. * 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, ...@@ -76,7 +76,7 @@ static int evp_kem_init(EVP_PKEY_CTX *ctx, int operation,
* the second iteration, or jump to legacy. * the second iteration, or jump to legacy.
*/ */
for (iter = 1, provkey = NULL; iter < 3 && provkey == NULL; iter++) { 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. * 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, ...@@ -455,7 +455,7 @@ static int evp_pkey_signature_init(EVP_PKEY_CTX *ctx, int operation,
* the second iteration, or jump to legacy. * the second iteration, or jump to legacy.
*/ */
for (iter = 1; iter < 3 && provkey == NULL; iter++) { 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. * If we're on the second iteration, free the results from the first.
......
...@@ -45,6 +45,7 @@ typedef struct { ...@@ -45,6 +45,7 @@ typedef struct {
DEFINE_STACK_OF(IMPLEMENTATION) DEFINE_STACK_OF(IMPLEMENTATION)
typedef struct { typedef struct {
const OSSL_PROVIDER *provider;
const char *query; const char *query;
METHOD method; METHOD method;
char body[1]; char body[1];
...@@ -172,7 +173,13 @@ static unsigned long query_hash(const QUERY *a) ...@@ -172,7 +173,13 @@ static unsigned long query_hash(const QUERY *a)
static int query_cmp(const QUERY *a, const QUERY *b) 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) static void impl_free(IMPLEMENTATION *impl)
...@@ -260,6 +267,9 @@ int ossl_method_store_add(OSSL_METHOD_STORE *store, const OSSL_PROVIDER *prov, ...@@ -260,6 +267,9 @@ int ossl_method_store_add(OSSL_METHOD_STORE *store, const OSSL_PROVIDER *prov,
if (properties == NULL) if (properties == NULL)
properties = ""; properties = "";
if (!ossl_assert(prov != NULL))
return 0;
/* Create new entry */ /* Create new entry */
impl = OPENSSL_malloc(sizeof(*impl)); impl = OPENSSL_malloc(sizeof(*impl));
if (impl == NULL) if (impl == NULL)
...@@ -393,15 +403,15 @@ void ossl_method_store_do_all(OSSL_METHOD_STORE *store, ...@@ -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); ossl_sa_ALGORITHM_doall_arg(store->algs, alg_do_each, &data);
} }
int ossl_method_store_fetch(OSSL_METHOD_STORE *store, int nid, int ossl_method_store_fetch(OSSL_METHOD_STORE *store,
const char *prop_query, int nid, const char *prop_query,
void **method) const OSSL_PROVIDER **prov_rw, void **method)
{ {
OSSL_PROPERTY_LIST **plp; OSSL_PROPERTY_LIST **plp;
ALGORITHM *alg; ALGORITHM *alg;
IMPLEMENTATION *impl; IMPLEMENTATION *impl, *best_impl = NULL;
OSSL_PROPERTY_LIST *pq = NULL, *p2 = 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 ret = 0;
int j, best = -1, score, optional; int j, best = -1, score, optional;
...@@ -438,29 +448,38 @@ int ossl_method_store_fetch(OSSL_METHOD_STORE *store, int nid, ...@@ -438,29 +448,38 @@ int ossl_method_store_fetch(OSSL_METHOD_STORE *store, int nid,
} }
if (pq == NULL) { if (pq == NULL) {
if ((impl = sk_IMPLEMENTATION_value(alg->impls, 0)) != NULL) { for (j = 0; j < sk_IMPLEMENTATION_num(alg->impls); j++) {
best_method = &impl->method; if ((impl = sk_IMPLEMENTATION_value(alg->impls, j)) != NULL
ret = 1; && (prov == NULL || impl->provider == prov)) {
best_impl = impl;
ret = 1;
break;
}
} }
goto fin; goto fin;
} }
optional = ossl_property_has_optional(pq); optional = ossl_property_has_optional(pq);
for (j = 0; j < sk_IMPLEMENTATION_num(alg->impls); j++) { for (j = 0; j < sk_IMPLEMENTATION_num(alg->impls); j++) {
impl = sk_IMPLEMENTATION_value(alg->impls, j); if ((impl = sk_IMPLEMENTATION_value(alg->impls, j)) != NULL
score = ossl_property_match_count(pq, impl->properties); && (prov == NULL || impl->provider == prov)) {
if (score > best) { score = ossl_property_match_count(pq, impl->properties);
best_method = &impl->method; if (score > best) {
best = score; best_impl = impl;
ret = 1; best = score;
if (!optional) ret = 1;
goto fin; if (!optional)
goto fin;
}
} }
} }
fin: fin:
if (ret && ossl_method_up_ref(best_method)) if (ret && ossl_method_up_ref(&best_impl->method)) {
*method = best_method->method; *method = best_impl->method.method;
else if (prov_rw != NULL)
*prov_rw = best_impl->provider;
} else {
ret = 0; ret = 0;
}
ossl_property_unlock(store); ossl_property_unlock(store);
ossl_property_free(p2); ossl_property_free(p2);
return ret; return ret;
...@@ -569,8 +588,8 @@ static void ossl_method_cache_flush_some(OSSL_METHOD_STORE *store) ...@@ -569,8 +588,8 @@ static void ossl_method_cache_flush_some(OSSL_METHOD_STORE *store)
store->nelem = state.nelem; store->nelem = state.nelem;
} }
int ossl_method_store_cache_get(OSSL_METHOD_STORE *store, int nid, int ossl_method_store_cache_get(OSSL_METHOD_STORE *store, OSSL_PROVIDER *prov,
const char *prop_query, void **method) int nid, const char *prop_query, void **method)
{ {
ALGORITHM *alg; ALGORITHM *alg;
QUERY elem, *r; QUERY elem, *r;
...@@ -586,6 +605,7 @@ int ossl_method_store_cache_get(OSSL_METHOD_STORE *store, int nid, ...@@ -586,6 +605,7 @@ int ossl_method_store_cache_get(OSSL_METHOD_STORE *store, int nid,
goto err; goto err;
elem.query = prop_query != NULL ? prop_query : ""; elem.query = prop_query != NULL ? prop_query : "";
elem.provider = prov;
r = lh_QUERY_retrieve(alg->cache, &elem); r = lh_QUERY_retrieve(alg->cache, &elem);
if (r == NULL) if (r == NULL)
goto err; goto err;
...@@ -598,8 +618,8 @@ err: ...@@ -598,8 +618,8 @@ err:
return res; return res;
} }
int ossl_method_store_cache_set(OSSL_METHOD_STORE *store, int nid, int ossl_method_store_cache_set(OSSL_METHOD_STORE *store, OSSL_PROVIDER *prov,
const char *prop_query, void *method, int nid, const char *prop_query, void *method,
int (*method_up_ref)(void *), int (*method_up_ref)(void *),
void (*method_destruct)(void *)) void (*method_destruct)(void *))
{ {
...@@ -613,6 +633,9 @@ int ossl_method_store_cache_set(OSSL_METHOD_STORE *store, int nid, ...@@ -613,6 +633,9 @@ int ossl_method_store_cache_set(OSSL_METHOD_STORE *store, int nid,
if (prop_query == NULL) if (prop_query == NULL)
return 1; return 1;
if (!ossl_assert(prov != NULL))
return 0;
if (!ossl_property_write_lock(store)) if (!ossl_property_write_lock(store))
return 0; return 0;
if (store->need_flush) if (store->need_flush)
...@@ -623,6 +646,7 @@ int ossl_method_store_cache_set(OSSL_METHOD_STORE *store, int nid, ...@@ -623,6 +646,7 @@ int ossl_method_store_cache_set(OSSL_METHOD_STORE *store, int nid,
if (method == NULL) { if (method == NULL) {
elem.query = prop_query; elem.query = prop_query;
elem.provider = prov;
if ((old = lh_QUERY_delete(alg->cache, &elem)) != NULL) { if ((old = lh_QUERY_delete(alg->cache, &elem)) != NULL) {
impl_cache_free(old); impl_cache_free(old);
store->nelem--; store->nelem--;
...@@ -632,6 +656,7 @@ int ossl_method_store_cache_set(OSSL_METHOD_STORE *store, int nid, ...@@ -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))); p = OPENSSL_malloc(sizeof(*p) + (len = strlen(prop_query)));
if (p != NULL) { if (p != NULL) {
p->query = p->body; p->query = p->body;
p->provider = prov;
p->method.method = method; p->method.method = method;
p->method.up_ref = method_up_ref; p->method.up_ref = method_up_ref;
p->method.free = method_destruct; p->method.free = method_destruct;
......
...@@ -128,7 +128,8 @@ static OSSL_METHOD_STORE *get_loader_store(OSSL_LIB_CTX *libctx) ...@@ -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 */ /* 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; struct loader_data_st *methdata = data;
void *method = NULL; void *method = NULL;
...@@ -144,7 +145,7 @@ static void *get_loader_from_store(void *store, void *data) ...@@ -144,7 +145,7 @@ static void *get_loader_from_store(void *store, void *data)
&& (store = get_loader_store(methdata->libctx)) == NULL) && (store = get_loader_store(methdata->libctx)) == NULL)
return 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 NULL;
return method; return method;
} }
...@@ -308,7 +309,7 @@ inner_loader_fetch(struct loader_data_st *methdata, int id, ...@@ -308,7 +309,7 @@ inner_loader_fetch(struct loader_data_st *methdata, int id,
unsupported = 1; unsupported = 1;
if (id == 0 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 = { OSSL_METHOD_CONSTRUCT_METHOD mcm = {
get_tmp_loader_store, get_tmp_loader_store,
get_loader_from_store, get_loader_from_store,
...@@ -331,7 +332,7 @@ inner_loader_fetch(struct loader_data_st *methdata, int id, ...@@ -331,7 +332,7 @@ inner_loader_fetch(struct loader_data_st *methdata, int id,
*/ */
if (id == 0) if (id == 0)
id = ossl_namemap_name2num(namemap, scheme); 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); up_ref_loader, free_loader);
} }
......
...@@ -27,14 +27,14 @@ ossl_method_store_flush_cache ...@@ -27,14 +27,14 @@ ossl_method_store_flush_cache
int nid, const void *method); int nid, const void *method);
int ossl_method_store_fetch(OSSL_METHOD_STORE *store, int ossl_method_store_fetch(OSSL_METHOD_STORE *store,
int nid, const char *properties, int nid, const char *properties,
void **method); void **method, const OSSL_PROVIDER **prov_rw);
int ossl_method_store_cache_get(OSSL_METHOD_STORE *store, int nid, int ossl_method_store_cache_get(OSSL_METHOD_STORE *store, OSSL_PROVIDER *prov,
const char *prop_query, void **method); int nid, const char *prop_query, void **method);
int ossl_method_store_cache_set(OSSL_METHOD_STORE *store, int nid, int ossl_method_store_cache_set(OSSL_METHOD_STORE *store, OSSL_PROVIDER *prov,
const char *prop_query, void *method, int nid, const char *prop_query, void *method,
int (*method_up_ref)(void *), int (*method_up_ref)(void *),
void (*method_destruct)(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 =head1 DESCRIPTION
...@@ -79,7 +79,9 @@ I<store>. ...@@ -79,7 +79,9 @@ I<store>.
ossl_method_store_fetch() queries I<store> for a method identified by I<nid> ossl_method_store_fetch() queries I<store> for a method identified by I<nid>
that matches the property query I<prop_query>. 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 ossl_method_store_flush_cache() flushes all cached entries associated with
I<store>. I<store>.
...@@ -89,10 +91,12 @@ I<store>. ...@@ -89,10 +91,12 @@ I<store>.
ossl_method_store_cache_get() queries the cache associated with the 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 for a method identified by I<nid> that matches the property query
I<prop_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>. The result, if any, is returned in I<method>.
ossl_method_store_cache_set() sets a cache entry identified by I<nid> with the ossl_method_store_cache_set() sets a cache entry identified by I<nid> from the
property query I<prop_query> in the I<store>. 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>. 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 The I<method_up_ref> function is called to increment the
reference count of the method and the I<method_destruct> function is called reference count of the method and the I<method_destruct> function is called
......
...@@ -13,16 +13,15 @@ OSSL_METHOD_CONSTRUCT_METHOD, ossl_method_construct ...@@ -13,16 +13,15 @@ OSSL_METHOD_CONSTRUCT_METHOD, ossl_method_construct
/* Get a temporary store */ /* Get a temporary store */
void *(*get_tmp_store)(void *data); void *(*get_tmp_store)(void *data);
/* Get an already existing method from a store */ /* 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 */ /* Store a method in a store */
int (*put)(void *store, void *method, int (*put)(void *store, void *method, const OSSL_PROVIDER *prov,
const OSSL_PROVIDER *prov, const char *name, const char *name, const char *propdef, void *data);
const char *propdef, void *data);
/* Construct a new method */ /* Construct a new method */
void *(*construct)(const char *name, const OSSL_DISPATCH *fns, void *(*construct)(const OSSL_ALGORITHM *algodef, OSSL_PROVIDER *prov,
OSSL_PROVIDER *prov, void *data); void *data);
/* Destruct a method */ /* Destruct a method */
void (*destruct)(void *method); void (*destruct)(void *method, void *data);
}; };
typedef struct ossl_method_construct_method OSSL_METHOD_CONSTRUCT_METHOD; typedef struct ossl_method_construct_method OSSL_METHOD_CONSTRUCT_METHOD;
...@@ -75,17 +74,13 @@ function pointers: ...@@ -75,17 +74,13 @@ function pointers:
=over 4 =over 4
=item alloc_tmp_store() =item get_tmp_store()
Create a temporary method store in the scope of the library context I<ctx>. 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 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 when the provider doesn't want its dispatch table stored in a longer
term cache. term cache.
=item dealloc_tmp_store()
Remove a temporary store.
=item get() =item get()
Look up an already existing method from a store by name. 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> ...@@ -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 In other words, the ossl_method_construct() caller is entirely responsible
for ensuring the necesssary data is made available. 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() =item put()
...@@ -112,7 +110,7 @@ NULL is a valid value and means that a subsystem default store ...@@ -112,7 +110,7 @@ NULL is a valid value and means that a subsystem default store
must be used. must be used.
This default store should be stored in the library context I<libctx>. 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 I<name> and property definition I<propdef> as well as any
identification data given through I<data> (which is the I<mcm_data> identification data given through I<data> (which is the I<mcm_data>
that was passed to ossl_construct_method()). that was passed to ossl_construct_method()).
......
...@@ -31,7 +31,7 @@ typedef struct ossl_method_construct_method_st { ...@@ -31,7 +31,7 @@ typedef struct ossl_method_construct_method_st {
/* Get a temporary store */ /* Get a temporary store */
void *(*get_tmp_store)(void *data); void *(*get_tmp_store)(void *data);
/* Get an already existing method from a store */ /* 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 */ /* Store a method in a store */
int (*put)(void *store, void *method, const OSSL_PROVIDER *prov, int (*put)(void *store, void *method, const OSSL_PROVIDER *prov,
const char *name, const char *propdef, void *data); const char *name, const char *propdef, void *data);
...@@ -43,7 +43,7 @@ typedef struct ossl_method_construct_method_st { ...@@ -43,7 +43,7 @@ typedef struct ossl_method_construct_method_st {
} OSSL_METHOD_CONSTRUCT_METHOD; } OSSL_METHOD_CONSTRUCT_METHOD;
void *ossl_method_construct(OSSL_LIB_CTX *ctx, int operation_id, 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); OSSL_METHOD_CONSTRUCT_METHOD *mcm, void *mcm_data);
void ossl_algorithm_do_all(OSSL_LIB_CTX *libctx, int operation_id, 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, ...@@ -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 ossl_method_store_do_all(OSSL_METHOD_STORE *store,
void (*fn)(int id, void *method, void *fnarg), void (*fn)(int id, void *method, void *fnarg),
void *fnarg); void *fnarg);
int ossl_method_store_fetch(OSSL_METHOD_STORE *store, int nid, int ossl_method_store_fetch(OSSL_METHOD_STORE *store,
const char *prop_query, void **method); int nid, const char *prop_query,
const OSSL_PROVIDER **prov, void **method);
/* Get the global properties associate with the specified library context */ /* Get the global properties associate with the specified library context */
OSSL_PROPERTY_LIST **ossl_ctx_global_properties(OSSL_LIB_CTX *ctx, OSSL_PROPERTY_LIST **ossl_ctx_global_properties(OSSL_LIB_CTX *ctx,
int loadconfig); int loadconfig);
/* property query cache functions */ /* property query cache functions */
int ossl_method_store_cache_get(OSSL_METHOD_STORE *store, int nid, int ossl_method_store_cache_get(OSSL_METHOD_STORE *store, OSSL_PROVIDER *prov,
const char *prop_query, void **result); int nid, const char *prop_query, void **result);
int ossl_method_store_cache_set(OSSL_METHOD_STORE *store, int nid, int ossl_method_store_cache_set(OSSL_METHOD_STORE *store, OSSL_PROVIDER *prov,
const char *prop_query, void *result, int nid, const char *prop_query, void *result,
int (*method_up_ref)(void *), int (*method_up_ref)(void *),
void (*method_destruct)(void *)); void (*method_destruct)(void *));
......
...@@ -15,6 +15,16 @@ ...@@ -15,6 +15,16 @@
#include "internal/property.h" #include "internal/property.h"
#include "../crypto/property/property_local.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, ...) static int add_property_names(const char *n, ...)
{ {
va_list args; va_list args;
...@@ -313,13 +323,14 @@ static int test_register_deregister(void) ...@@ -313,13 +323,14 @@ static int test_register_deregister(void)
size_t i; size_t i;
int ret = 0; int ret = 0;
OSSL_METHOD_STORE *store; OSSL_METHOD_STORE *store;
OSSL_PROVIDER prov = { 1 };
if (!TEST_ptr(store = ossl_method_store_new(NULL)) if (!TEST_ptr(store = ossl_method_store_new(NULL))
|| !add_property_names("position", NULL)) || !add_property_names("position", NULL))
goto err; goto err;
for (i = 0; i < OSSL_NELEM(impls); i++) 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, impls[i].prop, impls[i].impl,
&up_ref, &down_ref))) { &up_ref, &down_ref))) {
TEST_note("iteration %zd", i + 1); TEST_note("iteration %zd", i + 1);
...@@ -348,34 +359,40 @@ err: ...@@ -348,34 +359,40 @@ err:
static int test_property(void) 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 { static const struct {
const OSSL_PROVIDER **prov;
int nid; int nid;
const char *prop; const char *prop;
char *impl; char *impl;
} impls[] = { } impls[] = {
{ 1, "fast=no, colour=green", "a" }, { &fake_prov1, 1, "fast=no, colour=green", "a" },
{ 1, "fast, colour=blue", "b" }, { &fake_prov1, 1, "fast, colour=blue", "b" },
{ 1, "", "-" }, { &fake_prov1, 1, "", "-" },
{ 9, "sky=blue, furry", "c" }, { &fake_prov2, 9, "sky=blue, furry", "c" },
{ 3, NULL, "d" }, { &fake_prov2, 3, NULL, "d" },
{ 6, "sky.colour=blue, sky=green, old.data", "e" }, { &fake_prov2, 6, "sky.colour=blue, sky=green, old.data", "e" },
}; };
static struct { static struct {
const OSSL_PROVIDER **prov;
int nid; int nid;
const char *prop; const char *prop;
char *expected; char *expected;
} queries[] = { } queries[] = {
{ 1, "fast", "b" }, { &fake_prov1, 1, "fast", "b" },
{ 1, "fast=yes", "b" }, { &fake_prov1, 1, "fast=yes", "b" },
{ 1, "fast=no, colour=green", "a" }, { &fake_prov1, 1, "fast=no, colour=green", "a" },
{ 1, "colour=blue, fast", "b" }, { &fake_prov1, 1, "colour=blue, fast", "b" },
{ 1, "colour=blue", "b" }, { &fake_prov1, 1, "colour=blue", "b" },
{ 9, "furry", "c" }, { &fake_prov2, 9, "furry", "c" },
{ 6, "sky.colour=blue", "e" }, { &fake_prov2, 6, "sky.colour=blue", "e" },
{ 6, "old.data", "e" }, { &fake_prov2, 6, "old.data", "e" },
{ 9, "furry=yes, sky=blue", "c" }, { &fake_prov2, 9, "furry=yes, sky=blue", "c" },
{ 1, "", "a" }, { &fake_prov1, 1, "", "a" },
{ 3, "", "d" }, { &fake_prov2, 3, "", "d" },
}; };
OSSL_METHOD_STORE *store; OSSL_METHOD_STORE *store;
size_t i; size_t i;
...@@ -387,17 +404,24 @@ static int test_property(void) ...@@ -387,17 +404,24 @@ static int test_property(void)
goto err; goto err;
for (i = 0; i < OSSL_NELEM(impls); i++) 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, *impls[i].prov,
impls[i].prop, impls[i].impl, impls[i].nid, impls[i].prop,
impls[i].impl,
&up_ref, &down_ref))) { &up_ref, &down_ref))) {
TEST_note("iteration %zd", i + 1); TEST_note("iteration %zd", i + 1);
goto err; 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++) { for (i = 0; i < OSSL_NELEM(queries); i++) {
const OSSL_PROVIDER *nullprov = NULL;
OSSL_PROPERTY_LIST *pq = NULL; OSSL_PROPERTY_LIST *pq = NULL;
if (!TEST_true(ossl_method_store_fetch(store, queries[i].nid, if (!TEST_true(ossl_method_store_fetch(store,
queries[i].prop, &result)) queries[i].nid, queries[i].prop,
&nullprov, &result))
|| !TEST_str_eq((char *)result, queries[i].expected)) { || !TEST_str_eq((char *)result, queries[i].expected)) {
TEST_note("iteration %zd", i + 1); TEST_note("iteration %zd", i + 1);
ossl_property_free(pq); ossl_property_free(pq);
...@@ -405,6 +429,70 @@ static int test_property(void) ...@@ -405,6 +429,70 @@ static int test_property(void)
} }
ossl_property_free(pq); 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; ret = 1;
err: err:
ossl_method_store_free(store); ossl_method_store_free(store);
...@@ -420,6 +508,7 @@ static int test_query_cache_stochastic(void) ...@@ -420,6 +508,7 @@ static int test_query_cache_stochastic(void)
void *result; void *result;
int errors = 0; int errors = 0;
int v[10001]; int v[10001];
OSSL_PROVIDER prov = { 1 };
if (!TEST_ptr(store = ossl_method_store_new(NULL)) if (!TEST_ptr(store = ossl_method_store_new(NULL))
|| !add_property_names("n", NULL)) || !add_property_names("n", NULL))
...@@ -428,20 +517,21 @@ static int test_query_cache_stochastic(void) ...@@ -428,20 +517,21 @@ static int test_query_cache_stochastic(void)
for (i = 1; i <= max; i++) { for (i = 1; i <= max; i++) {
v[i] = 2 * i; v[i] = 2 * i;
BIO_snprintf(buf, sizeof(buf), "n=%d\n", 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)) &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)) &up_ref, &down_ref))
|| !TEST_true(ossl_method_store_cache_set(store, i, "n=1234", || !TEST_true(ossl_method_store_cache_set(store, &prov, i,
"miss", &up_ref, "n=1234", "miss",
&down_ref))) { &up_ref, &down_ref))) {
TEST_note("iteration %d", i); TEST_note("iteration %d", i);
goto err; goto err;
} }
} }
for (i = 1; i <= max; i++) { for (i = 1; i <= max; i++) {
BIO_snprintf(buf, sizeof(buf), "n=%d\n", 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) || result != v + i)
errors++; errors++;
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册