summaryrefslogtreecommitdiffstats
path: root/crypto
diff options
context:
space:
mode:
authorRichard Levitte <levitte@openssl.org>2021-10-04 15:33:37 +0200
committerRichard Levitte <levitte@openssl.org>2021-10-27 12:41:15 +0200
commitdc010ca6ec01d313a84c3c4b040232655a1772ad (patch)
treeb925e2db5fad6f5c06e5bbac180fe15c223ae8b7 /crypto
parent433e13455ede1a39d415b690b8a564b4f36b8dee (diff)
CORE: Encure that cached fetches can be done per provider
This mostly entails passing around a provider pointer, and handling queries that includes a pointer to a provider, where NULL means "any". This also means that there's a need to pass the provider pointer, not just down to the cache functions, but also be able to get it from ossl_method_store_fetch(). To this end, that function's OSSL_PROVIDER pointer argument is modified to be a pointer reference, so the function can answer back what provider the method comes from. Test added. Fixes #16614 Reviewed-by: Tomas Mraz <tomas@openssl.org> Reviewed-by: Matt Caswell <matt@openssl.org> (Merged from https://github.com/openssl/openssl/pull/16725)
Diffstat (limited to 'crypto')
-rw-r--r--crypto/core_fetch.c11
-rw-r--r--crypto/encode_decode/decoder_meth.c9
-rw-r--r--crypto/encode_decode/encoder_meth.c9
-rw-r--r--crypto/evp/evp_fetch.c14
-rw-r--r--crypto/evp/exchange.c2
-rw-r--r--crypto/evp/kem.c2
-rw-r--r--crypto/evp/signature.c2
-rw-r--r--crypto/property/property.c73
-rw-r--r--crypto/store/store_meth.c9
9 files changed, 82 insertions, 49 deletions
diff --git a/crypto/core_fetch.c b/crypto/core_fetch.c
index 26eeaba3b7..367f6ba8a4 100644
--- a/crypto/core_fetch.c
+++ b/crypto/core_fetch.c
@@ -105,12 +105,14 @@ static void ossl_method_construct_this(OSSL_PROVIDER *provider,
}
void *ossl_method_construct(OSSL_LIB_CTX *libctx, int operation_id,
- OSSL_PROVIDER *provider, int force_store,
+ OSSL_PROVIDER **provider_rw, int force_store,
OSSL_METHOD_CONSTRUCT_METHOD *mcm, void *mcm_data)
{
void *method = NULL;
- if ((method = mcm->get(NULL, mcm_data)) == NULL) {
+ if ((method = mcm->get(NULL, (const OSSL_PROVIDER **)provider_rw,
+ mcm_data)) == NULL) {
+ OSSL_PROVIDER *provider = provider_rw != NULL ? *provider_rw : NULL;
struct construct_data_st cbdata;
cbdata.store = NULL;
@@ -125,11 +127,12 @@ void *ossl_method_construct(OSSL_LIB_CTX *libctx, int operation_id,
/* If there is a temporary store, try there first */
if (cbdata.store != NULL)
- method = mcm->get(cbdata.store, mcm_data);
+ method = mcm->get(cbdata.store, (const OSSL_PROVIDER **)provider_rw,
+ mcm_data);
/* If no method was found yet, try the global store */
if (method == NULL)
- method = mcm->get(NULL, mcm_data);
+ method = mcm->get(NULL, (const OSSL_PROVIDER **)provider_rw, mcm_data);
}
return method;
diff --git a/crypto/encode_decode/decoder_meth.c b/crypto/encode_decode/decoder_meth.c
index 82515a14a3..6d44437314 100644
--- a/crypto/encode_decode/decoder_meth.c
+++ b/crypto/encode_decode/decoder_meth.c
@@ -125,7 +125,8 @@ static OSSL_METHOD_STORE *get_decoder_store(OSSL_LIB_CTX *libctx)
}
/* Get decoder methods from a store, or put one in */
-static void *get_decoder_from_store(void *store, void *data)
+static void *get_decoder_from_store(void *store, const OSSL_PROVIDER **prov,
+ void *data)
{
struct decoder_data_st *methdata = data;
void *method = NULL;
@@ -154,7 +155,7 @@ static void *get_decoder_from_store(void *store, void *data)
&& (store = get_decoder_store(methdata->libctx)) == NULL)
return NULL;
- if (!ossl_method_store_fetch(store, id, methdata->propquery, &method))
+ if (!ossl_method_store_fetch(store, id, methdata->propquery, prov, &method))
return NULL;
return method;
}
@@ -366,7 +367,7 @@ inner_ossl_decoder_fetch(struct decoder_data_st *methdata, int id,
unsupported = 1;
if (id == 0
- || !ossl_method_store_cache_get(store, id, properties, &method)) {
+ || !ossl_method_store_cache_get(store, NULL, id, properties, &method)) {
OSSL_METHOD_CONSTRUCT_METHOD mcm = {
get_tmp_decoder_store,
get_decoder_from_store,
@@ -391,7 +392,7 @@ inner_ossl_decoder_fetch(struct decoder_data_st *methdata, int id,
if (id == 0 && name != NULL)
id = ossl_namemap_name2num(namemap, name);
if (id != 0)
- ossl_method_store_cache_set(store, id, properties, method,
+ ossl_method_store_cache_set(store, NULL, id, properties, method,
up_ref_decoder, free_decoder);
}
diff --git a/crypto/encode_decode/encoder_meth.c b/crypto/encode_decode/encoder_meth.c
index 6526f5e358..9c0214db6b 100644
--- a/crypto/encode_decode/encoder_meth.c
+++ b/crypto/encode_decode/encoder_meth.c
@@ -125,7 +125,8 @@ static OSSL_METHOD_STORE *get_encoder_store(OSSL_LIB_CTX *libctx)
}
/* Get encoder methods from a store, or put one in */
-static void *get_encoder_from_store(void *store, void *data)
+static void *get_encoder_from_store(void *store, const OSSL_PROVIDER **prov,
+ void *data)
{
struct encoder_data_st *methdata = data;
void *method = NULL;
@@ -154,7 +155,7 @@ static void *get_encoder_from_store(void *store, void *data)
&& (store = get_encoder_store(methdata->libctx)) == NULL)
return NULL;
- if (!ossl_method_store_fetch(store, id, methdata->propquery, &method))
+ if (!ossl_method_store_fetch(store, id, methdata->propquery, prov, &method))
return NULL;
return method;
}
@@ -376,7 +377,7 @@ inner_ossl_encoder_fetch(struct encoder_data_st *methdata, int id,
unsupported = 1;
if (id == 0
- || !ossl_method_store_cache_get(store, id, properties, &method)) {
+ || !ossl_method_store_cache_get(store, NULL, id, properties, &method)) {
OSSL_METHOD_CONSTRUCT_METHOD mcm = {
get_tmp_encoder_store,
get_encoder_from_store,
@@ -400,7 +401,7 @@ inner_ossl_encoder_fetch(struct encoder_data_st *methdata, int id,
*/
if (id == 0)
id = ossl_namemap_name2num(namemap, name);
- ossl_method_store_cache_set(store, id, properties, method,
+ ossl_method_store_cache_set(store, NULL, id, properties, method,
up_ref_encoder, free_encoder);
}
diff --git a/crypto/evp/evp_fetch.c b/crypto/evp/evp_fetch.c
index ef9e222411..80da3fa4bf 100644
--- a/crypto/evp/evp_fetch.c
+++ b/crypto/evp/evp_fetch.c
@@ -115,7 +115,8 @@ static uint32_t evp_method_id(int name_id, unsigned int operation_id)
| (operation_id & METHOD_ID_OPERATION_MASK));
}
-static void *get_evp_method_from_store(void *store, void *data)
+static void *get_evp_method_from_store(void *store, const OSSL_PROVIDER **prov,
+ void *data)
{
struct evp_method_data_st *methdata = data;
void *method = NULL;
@@ -146,7 +147,7 @@ static void *get_evp_method_from_store(void *store, void *data)
&& (store = get_evp_method_store(methdata->libctx)) == NULL)
return NULL;
- if (!ossl_method_store_fetch(store, meth_id, methdata->propquery,
+ if (!ossl_method_store_fetch(store, meth_id, methdata->propquery, prov,
&method))
return NULL;
return method;
@@ -298,7 +299,8 @@ inner_evp_generic_fetch(struct evp_method_data_st *methdata,
unsupported = 1;
if (meth_id == 0
- || !ossl_method_store_cache_get(store, meth_id, properties, &method)) {
+ || !ossl_method_store_cache_get(store, prov, meth_id, properties,
+ &method)) {
OSSL_METHOD_CONSTRUCT_METHOD mcm = {
get_tmp_evp_method_store,
get_evp_method_from_store,
@@ -316,7 +318,7 @@ inner_evp_generic_fetch(struct evp_method_data_st *methdata,
methdata->destruct_method = free_method;
methdata->flag_construct_error_occurred = 0;
if ((method = ossl_method_construct(methdata->libctx, operation_id,
- prov, 0 /* !force_cache */,
+ &prov, 0 /* !force_cache */,
&mcm, methdata)) != NULL) {
/*
* If construction did create a method for us, we know that
@@ -328,8 +330,8 @@ inner_evp_generic_fetch(struct evp_method_data_st *methdata,
name_id = ossl_namemap_name2num(namemap, name);
meth_id = evp_method_id(name_id, operation_id);
if (name_id != 0)
- ossl_method_store_cache_set(store, meth_id, properties, method,
- up_ref_method, free_method);
+ ossl_method_store_cache_set(store, prov, meth_id, properties,
+ method, up_ref_method, free_method);
}
/*
diff --git a/crypto/evp/exchange.c b/crypto/evp/exchange.c
index d12dcee947..e2ca30c94d 100644
--- a/crypto/evp/exchange.c
+++ b/crypto/evp/exchange.c
@@ -274,7 +274,7 @@ int EVP_PKEY_derive_init_ex(EVP_PKEY_CTX *ctx, const OSSL_PARAM params[])
* the second iteration, or jump to legacy.
*/
for (iter = 1, provkey = NULL; iter < 3 && provkey == NULL; iter++) {
- EVP_KEYMGMT *tmp_keymgmt_tofree;
+ EVP_KEYMGMT *tmp_keymgmt_tofree = NULL;
/*
* If we're on the second iteration, free the results from the first.
diff --git a/crypto/evp/kem.c b/crypto/evp/kem.c
index 6ba598eb98..7594888b97 100644
--- a/crypto/evp/kem.c
+++ b/crypto/evp/kem.c
@@ -76,7 +76,7 @@ static int evp_kem_init(EVP_PKEY_CTX *ctx, int operation,
* the second iteration, or jump to legacy.
*/
for (iter = 1, provkey = NULL; iter < 3 && provkey == NULL; iter++) {
- EVP_KEYMGMT *tmp_keymgmt_tofree;
+ EVP_KEYMGMT *tmp_keymgmt_tofree = NULL;
/*
* If we're on the second iteration, free the results from the first.
diff --git a/crypto/evp/signature.c b/crypto/evp/signature.c
index 026a430fe8..49f40c8cec 100644
--- a/crypto/evp/signature.c
+++ b/crypto/evp/signature.c
@@ -455,7 +455,7 @@ static int evp_pkey_signature_init(EVP_PKEY_CTX *ctx, int operation,
* the second iteration, or jump to legacy.
*/
for (iter = 1; iter < 3 && provkey == NULL; iter++) {
- EVP_KEYMGMT *tmp_keymgmt_tofree;
+ EVP_KEYMGMT *tmp_keymgmt_tofree = NULL;
/*
* If we're on the second iteration, free the results from the first.
diff --git a/crypto/property/property.c b/crypto/property/property.c
index a4cd612b9d..5df1bfc221 100644
--- a/crypto/property/property.c
+++ b/crypto/property/property.c
@@ -45,6 +45,7 @@ typedef struct {
DEFINE_STACK_OF(IMPLEMENTATION)
typedef struct {
+ const OSSL_PROVIDER *provider;
const char *query;
METHOD method;
char body[1];
@@ -172,7 +173,13 @@ static unsigned long query_hash(const QUERY *a)
static int query_cmp(const QUERY *a, const QUERY *b)
{
- return strcmp(a->query, b->query);
+ int res = strcmp(a->query, b->query);
+
+ if (res == 0 && a->provider != NULL && b->provider != NULL)
+ res = b->provider > a->provider ? 1
+ : b->provider < a->provider ? -1
+ : 0;
+ return res;
}
static void impl_free(IMPLEMENTATION *impl)
@@ -260,6 +267,9 @@ int ossl_method_store_add(OSSL_METHOD_STORE *store, const OSSL_PROVIDER *prov,
if (properties == NULL)
properties = "";
+ if (!ossl_assert(prov != NULL))
+ return 0;
+
/* Create new entry */
impl = OPENSSL_malloc(sizeof(*impl));
if (impl == NULL)
@@ -393,15 +403,15 @@ void ossl_method_store_do_all(OSSL_METHOD_STORE *store,
ossl_sa_ALGORITHM_doall_arg(store->algs, alg_do_each, &data);
}
-int ossl_method_store_fetch(OSSL_METHOD_STORE *store, int nid,
- const char *prop_query,
- void **method)
+int ossl_method_store_fetch(OSSL_METHOD_STORE *store,
+ int nid, const char *prop_query,
+ const OSSL_PROVIDER **prov_rw, void **method)
{
OSSL_PROPERTY_LIST **plp;
ALGORITHM *alg;
- IMPLEMENTATION *impl;
+ IMPLEMENTATION *impl, *best_impl = NULL;
OSSL_PROPERTY_LIST *pq = NULL, *p2 = NULL;
- METHOD *best_method = NULL;
+ const OSSL_PROVIDER *prov = prov_rw != NULL ? *prov_rw : NULL;
int ret = 0;
int j, best = -1, score, optional;
@@ -438,29 +448,38 @@ int ossl_method_store_fetch(OSSL_METHOD_STORE *store, int nid,
}
if (pq == NULL) {
- if ((impl = sk_IMPLEMENTATION_value(alg->impls, 0)) != NULL) {
- best_method = &impl->method;
- ret = 1;
+ for (j = 0; j < sk_IMPLEMENTATION_num(alg->impls); j++) {
+ if ((impl = sk_IMPLEMENTATION_value(alg->impls, j)) != NULL
+ && (prov == NULL || impl->provider == prov)) {
+ best_impl = impl;
+ ret = 1;
+ break;
+ }
}
goto fin;
}
optional = ossl_property_has_optional(pq);
for (j = 0; j < sk_IMPLEMENTATION_num(alg->impls); j++) {
- impl = sk_IMPLEMENTATION_value(alg->impls, j);
- score = ossl_property_match_count(pq, impl->properties);
- if (score > best) {
- best_method = &impl->method;
- best = score;
- ret = 1;
- if (!optional)
- goto fin;
+ if ((impl = sk_IMPLEMENTATION_value(alg->impls, j)) != NULL
+ && (prov == NULL || impl->provider == prov)) {
+ score = ossl_property_match_count(pq, impl->properties);
+ if (score > best) {
+ best_impl = impl;
+ best = score;
+ ret = 1;
+ if (!optional)
+ goto fin;
+ }
}
}
fin:
- if (ret && ossl_method_up_ref(best_method))
- *method = best_method->method;
- else
+ if (ret && ossl_method_up_ref(&best_impl->method)) {
+ *method = best_impl->method.method;
+ if (prov_rw != NULL)
+ *prov_rw = best_impl->provider;
+ } else {
ret = 0;
+ }
ossl_property_unlock(store);
ossl_property_free(p2);
return ret;
@@ -569,8 +588,8 @@ static void ossl_method_cache_flush_some(OSSL_METHOD_STORE *store)
store->nelem = state.nelem;
}
-int ossl_method_store_cache_get(OSSL_METHOD_STORE *store, int nid,
- const char *prop_query, void **method)
+int ossl_method_store_cache_get(OSSL_METHOD_STORE *store, OSSL_PROVIDER *prov,
+ int nid, const char *prop_query, void **method)
{
ALGORITHM *alg;
QUERY elem, *r;
@@ -586,6 +605,7 @@ int ossl_method_store_cache_get(OSSL_METHOD_STORE *store, int nid,
goto err;
elem.query = prop_query != NULL ? prop_query : "";
+ elem.provider = prov;
r = lh_QUERY_retrieve(alg->cache, &elem);
if (r == NULL)
goto err;
@@ -598,8 +618,8 @@ err:
return res;
}
-int ossl_method_store_cache_set(OSSL_METHOD_STORE *store, int nid,
- const char *prop_query, void *method,
+int ossl_method_store_cache_set(OSSL_METHOD_STORE *store, OSSL_PROVIDER *prov,
+ int nid, const char *prop_query, void *method,
int (*method_up_ref)(void *),
void (*method_destruct)(void *))
{
@@ -613,6 +633,9 @@ int ossl_method_store_cache_set(OSSL_METHOD_STORE *store, int nid,
if (prop_query == NULL)
return 1;
+ if (!ossl_assert(prov != NULL))
+ return 0;
+
if (!ossl_property_write_lock(store))
return 0;
if (store->need_flush)
@@ -623,6 +646,7 @@ int ossl_method_store_cache_set(OSSL_METHOD_STORE *store, int nid,
if (method == NULL) {
elem.query = prop_query;
+ elem.provider = prov;
if ((old = lh_QUERY_delete(alg->cache, &elem)) != NULL) {
impl_cache_free(old);
store->nelem--;
@@ -632,6 +656,7 @@ int ossl_method_store_cache_set(OSSL_METHOD_STORE *store, int nid,
p = OPENSSL_malloc(sizeof(*p) + (len = strlen(prop_query)));
if (p != NULL) {
p->query = p->body;
+ p->provider = prov;
p->method.method = method;
p->method.up_ref = method_up_ref;
p->method.free = method_destruct;
diff --git a/crypto/store/store_meth.c b/crypto/store/store_meth.c
index d6b0389af9..e79ec871fd 100644
--- a/crypto/store/store_meth.c
+++ b/crypto/store/store_meth.c
@@ -128,7 +128,8 @@ static OSSL_METHOD_STORE *get_loader_store(OSSL_LIB_CTX *libctx)
}
/* Get loader methods from a store, or put one in */
-static void *get_loader_from_store(void *store, void *data)
+static void *get_loader_from_store(void *store, const OSSL_PROVIDER **prov,
+ void *data)
{
struct loader_data_st *methdata = data;
void *method = NULL;
@@ -144,7 +145,7 @@ static void *get_loader_from_store(void *store, void *data)
&& (store = get_loader_store(methdata->libctx)) == NULL)
return NULL;
- if (!ossl_method_store_fetch(store, id, methdata->propquery, &method))
+ if (!ossl_method_store_fetch(store, id, methdata->propquery, prov, &method))
return NULL;
return method;
}
@@ -308,7 +309,7 @@ inner_loader_fetch(struct loader_data_st *methdata, int id,
unsupported = 1;
if (id == 0
- || !ossl_method_store_cache_get(store, id, properties, &method)) {
+ || !ossl_method_store_cache_get(store, NULL, id, properties, &method)) {
OSSL_METHOD_CONSTRUCT_METHOD mcm = {
get_tmp_loader_store,
get_loader_from_store,
@@ -331,7 +332,7 @@ inner_loader_fetch(struct loader_data_st *methdata, int id,
*/
if (id == 0)
id = ossl_namemap_name2num(namemap, scheme);
- ossl_method_store_cache_set(store, id, properties, method,
+ ossl_method_store_cache_set(store, NULL, id, properties, method,
up_ref_loader, free_loader);
}