CORE: Encure that cached fetches can be done per provider
authorRichard Levitte <levitte@openssl.org>
Mon, 4 Oct 2021 13:33:37 +0000 (15:33 +0200)
committerRichard Levitte <levitte@openssl.org>
Wed, 27 Oct 2021 10:41:15 +0000 (12:41 +0200)
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)

14 files changed:
crypto/core_fetch.c
crypto/encode_decode/decoder_meth.c
crypto/encode_decode/encoder_meth.c
crypto/evp/evp_fetch.c
crypto/evp/exchange.c
crypto/evp/kem.c
crypto/evp/signature.c
crypto/property/property.c
crypto/store/store_meth.c
doc/internal/man3/OSSL_METHOD_STORE.pod
doc/internal/man3/ossl_method_construct.pod
include/internal/core.h
include/internal/property.h
test/property_test.c

index 26eeaba3b7a210bee63d850b15425f798253bd75..367f6ba8a47b11c90d51c43f84c52cd78b610def 100644 (file)
@@ -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;
index 82515a14a33abfdf1839d68ad897cb7a2d4097a2..6d444373147dbda20db3d8d2960f520f90d3cb9c 100644 (file)
@@ -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);
         }
 
index 6526f5e35810048cd2ad5f4d0adf1a263381e133..9c0214db6bc74141a6d3e1d9915afac5a190e1ab 100644 (file)
@@ -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);
         }
 
index ef9e222411cf0fcd58042f4a02c07c03df544c88..80da3fa4bf8e345c52f2bcf9a6aa2909da77cd9a 100644 (file)
@@ -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);
         }
 
         /*
index d12dcee9479da5e70316abe33f21180d4008c470..e2ca30c94d06ebc58368c009697bd84cd092547b 100644 (file)
@@ -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.
index 6ba598eb98f3b9418ca80e3ee04b2e61d7485ba9..7594888b97d13bfcf32643deed3777b07b2e1f45 100644 (file)
@@ -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.
index 026a430fe8439f91a602c3bc6df7ca08d3b60ed1..49f40c8cec241a58b2caa9347375956e2d42cc9f 100644 (file)
@@ -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.
index a4cd612b9daa261e6a2acdb25f6a8628599c34e3..5df1bfc221d56ff04c6c794824f69a60ec98d236 100644 (file)
@@ -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;
index d6b0389af99661af0d954649c471cc24b757db09..e79ec871fd79c912f907956a5e12c794036e3b62 100644 (file)
@@ -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);
         }
 
index 7d9b80778dbf51e665d663fd3b79fea8fe3475f8..5d9219fd0e98c1fec9de5a0cf23203e45f067b7d 100644 (file)
@@ -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
index f30e5609dce388196ece471f0ed2ede5b09b15ca..3683798b06b49b8c65b7a7592d7a8cc0c05b0c92 100644 (file)
@@ -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()).
index 277f2bdac56486d3a4d996bea7e627764dc087f9..d9dc424164c9358c42e05178a41524d6d15f2d8c 100644 (file)
@@ -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,
index dd9a2dc2d8f3da9f96cb3a42d1d169da52b48a7e..8211974595de6d196f450fa6dde82c2150dd5d65 100644 (file)
@@ -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 *));
 
index c23ddb0f995eb6815f8b7ed978f92835286f7dde..ad44cf151308456d561806a2d8540d33e592abca 100644 (file)
 #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++;
     }