[openssl] master update

Richard Levitte levitte at openssl.org
Tue Jun 15 14:40:53 UTC 2021


The branch master has been updated
       via  29b3fdad2b078f45f840f6e45b0fe483b77dbc6f (commit)
       via  5d8ad7d385f1be0d2ef6fd3bfc91debdf3835c96 (commit)
       via  27fb7a0a27c2b35b8f385fa2a23588603c7a94a4 (commit)
       via  cd770738796c591f93b2db630bab57cd8d3d5796 (commit)
       via  793b05865a3892258522e875df6ba4dff2ceb817 (commit)
       via  b3f5d5d3684c4059b09e73b951a84fc0d77594e9 (commit)
       via  07562828308417205f39a628af3b78af0d30d308 (commit)
       via  f0191d0b1373bb7b0c50a0103d63791f51ed3398 (commit)
      from  04fb4ec8facc5555e1e289029c289ebc4b487db8 (commit)


- Log -----------------------------------------------------------------
commit 29b3fdad2b078f45f840f6e45b0fe483b77dbc6f
Author: Richard Levitte <levitte at openssl.org>
Date:   Thu Jun 10 07:31:13 2021 +0200

    Refactor OSSL_STORE_LOADER_do_all_provided() to behave like OSSL_STORE_LOADER_fetch()
    
    This is refactored to use inner_loader_fetch() without any given name,
    which is just there to ensure all decoder implementations are made
    into methods, and then use ossl_method_store_do_all() to list them
    all.
    
    This also adds the internal ossl_store_loader_do_all_prefetched(),
    which can be used if pre-fetching needs to be done separately from
    listing all the decoder implementations, or if listing may happen
    multiple times.
    
    Reviewed-by: Matt Caswell <matt at openssl.org>
    Reviewed-by: Tomas Mraz <tomas at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/15604)

commit 5d8ad7d385f1be0d2ef6fd3bfc91debdf3835c96
Author: Richard Levitte <levitte at openssl.org>
Date:   Wed Jun 9 11:00:00 2021 +0200

    test/evp_extra_test.c: Peek at the error instead of getting it.
    
    If there is an error report, we want to get it printed too.
    
    Reviewed-by: Matt Caswell <matt at openssl.org>
    Reviewed-by: Tomas Mraz <tomas at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/15604)

commit 27fb7a0a27c2b35b8f385fa2a23588603c7a94a4
Author: Richard Levitte <levitte at openssl.org>
Date:   Wed Jun 9 10:58:33 2021 +0200

    DECODER & ENCODER: Add better tracing
    
    Now that we have functions to get the name and properties of the
    diverse implementations, we can as well display them for clarity.
    
    Reviewed-by: Matt Caswell <matt at openssl.org>
    Reviewed-by: Tomas Mraz <tomas at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/15604)

commit cd770738796c591f93b2db630bab57cd8d3d5796
Author: Richard Levitte <levitte at openssl.org>
Date:   Wed Jun 9 07:52:09 2021 +0200

    Adapt all public EVP_XXX_do_all_provided() for the changed evp_generic_do_all()
    
    Fixes #15538
    Fixes #14837
    
    Reviewed-by: Matt Caswell <matt at openssl.org>
    Reviewed-by: Tomas Mraz <tomas at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/15604)

commit 793b05865a3892258522e875df6ba4dff2ceb817
Author: Richard Levitte <levitte at openssl.org>
Date:   Wed Jun 9 07:50:08 2021 +0200

    Refactor evp_generic_do_all() to behave like evp_generic_fetch()
    
    This is refactored to use inner_evp_generic_fetch() without any given
    name, which is just there to ensure all decoder implementations are
    made into methods, and then use ossl_method_store_do_all() to list
    them all.
    
    This also adds the internal evp_generic_do_all_prefetched(), which
    can be used if pre-fetching needs to be done separately from listing
    all the decoder implementations, or if listing may happen multiple
    times.
    
    Fixes #15538
    Fixes #14837
    
    Reviewed-by: Matt Caswell <matt at openssl.org>
    Reviewed-by: Tomas Mraz <tomas at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/15604)

commit b3f5d5d3684c4059b09e73b951a84fc0d77594e9
Author: Richard Levitte <levitte at openssl.org>
Date:   Wed Jun 9 07:47:41 2021 +0200

    Refactor OSSL_ENCODER_do_all_provided() to behave like OSSL_ENCODER_fetch()
    
    This is refactored to use inner_ossl_encoder_fetch() without any given
    name, which is just there to ensure all encoder implementations are
    made into methods, and then use ossl_method_store_do_all() to list
    them all.
    
    This also adds the internal ossl_encoder_do_all_prefetched(), which
    can be used if pre-fetching needs to be done separately from listing
    all the encoder implementations, or if listing may happen multiple
    times.
    
    Fixes #15538
    Fixes #14837
    
    Reviewed-by: Matt Caswell <matt at openssl.org>
    Reviewed-by: Tomas Mraz <tomas at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/15604)

commit 07562828308417205f39a628af3b78af0d30d308
Author: Richard Levitte <levitte at openssl.org>
Date:   Fri Jun 4 14:29:07 2021 +0200

    Refactor OSSL_DECODER_do_all_provided() to behave like OSSL_DECODER_fetch()
    
    This is refactored to use inner_ossl_decoder_fetch() without any given
    name, which is just there to ensure all decoder implementations are
    made into methods, and then use ossl_method_store_do_all() to list
    them all.
    
    This also adds the internal ossl_decoder_do_all_prefetched(), which
    can be used if pre-fetching needs to be done separately from listing
    all the decoder implementations, or if listing may happen multiple
    times.
    
    Fixes #15538
    Fixes #14837
    
    Reviewed-by: Matt Caswell <matt at openssl.org>
    Reviewed-by: Tomas Mraz <tomas at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/15604)

commit f0191d0b1373bb7b0c50a0103d63791f51ed3398
Author: Richard Levitte <levitte at openssl.org>
Date:   Thu Jun 3 09:09:19 2021 +0200

    Add the internal function ossl_method_store_do_all()
    
    It will simply call the given callback for every method found in the
    given store.
    
    Fixes #15538
    Fixes #14837
    
    Reviewed-by: Matt Caswell <matt at openssl.org>
    Reviewed-by: Tomas Mraz <tomas at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/15604)

-----------------------------------------------------------------------

Summary of changes:
 crypto/encode_decode/decoder_meth.c | 61 ++++++++++++-------------
 crypto/encode_decode/decoder_pkey.c | 44 ++++++++++++++++++
 crypto/encode_decode/encoder_meth.c | 55 +++++++++--------------
 crypto/evp/asymcipher.c             |  1 +
 crypto/evp/digest.c                 |  2 +-
 crypto/evp/evp_enc.c                |  3 +-
 crypto/evp/evp_fetch.c              | 90 ++++++++++++++++++++-----------------
 crypto/evp/evp_local.h              |  4 ++
 crypto/evp/evp_rand.c               |  3 +-
 crypto/evp/exchange.c               |  1 +
 crypto/evp/kdf_meth.c               |  2 +-
 crypto/evp/kem.c                    |  1 +
 crypto/evp/keymgmt_meth.c           |  1 +
 crypto/evp/mac_meth.c               |  2 +-
 crypto/evp/signature.c              |  1 +
 crypto/property/property.c          | 36 +++++++++++++++
 crypto/store/store_meth.c           | 56 ++++++++++-------------
 include/crypto/decoder.h            |  1 -
 include/internal/property.h         |  3 ++
 test/evp_extra_test.c               |  2 +-
 20 files changed, 222 insertions(+), 147 deletions(-)

diff --git a/crypto/encode_decode/decoder_meth.c b/crypto/encode_decode/decoder_meth.c
index 7afbf6bb25..e25efe532b 100644
--- a/crypto/encode_decode/decoder_meth.c
+++ b/crypto/encode_decode/decoder_meth.c
@@ -321,15 +321,15 @@ inner_ossl_decoder_fetch(struct decoder_data_st *methdata, int id,
     }
 
     /*
-     * If we have been passed neither a name_id or a name, we have an
+     * If we have been passed both an id and a name, we have an
      * internal programming error.
      */
-    if (!ossl_assert(id != 0 || name != NULL)) {
+    if (!ossl_assert(id == 0 || name == NULL)) {
         ERR_raise(ERR_LIB_OSSL_DECODER, ERR_R_INTERNAL_ERROR);
         return NULL;
     }
 
-    if (id == 0)
+    if (id == 0 && name != NULL)
         id = ossl_namemap_name2num(namemap, name);
 
     /*
@@ -363,10 +363,11 @@ inner_ossl_decoder_fetch(struct decoder_data_st *methdata, int id,
              * already been calculated in get_decoder_from_store() and
              * put_decoder_in_store() above.
              */
-            if (id == 0)
+            if (id == 0 && name != NULL)
                 id = ossl_namemap_name2num(namemap, name);
-            ossl_method_store_cache_set(store, id, properties, method,
-                                        up_ref_decoder, free_decoder);
+            if (id != 0)
+                ossl_method_store_cache_set(store, id, properties, method,
+                                            up_ref_decoder, free_decoder);
         }
 
         /*
@@ -376,7 +377,7 @@ inner_ossl_decoder_fetch(struct decoder_data_st *methdata, int id,
         unsupported = !methdata->flag_construct_error_occurred;
     }
 
-    if (method == NULL) {
+    if ((id != 0 || name != NULL) && method == NULL) {
         int code = unsupported ? ERR_R_UNSUPPORTED : ERR_R_FETCH_FAILED;
 
         if (name == NULL)
@@ -483,42 +484,36 @@ int OSSL_DECODER_is_a(const OSSL_DECODER *decoder, const char *name)
     return 0;
 }
 
-struct decoder_do_all_data_st {
-    void (*user_fn)(void *method, void *arg);
+struct do_one_data_st {
+    void (*user_fn)(OSSL_DECODER *decoder, void *arg);
     void *user_arg;
 };
 
-static void decoder_do_one(OSSL_PROVIDER *provider,
-                           const OSSL_ALGORITHM *algodef,
-                           int no_store, void *vdata)
+static void do_one(ossl_unused int id, void *method, void *arg)
 {
-    struct decoder_do_all_data_st *data = vdata;
-    OSSL_LIB_CTX *libctx = ossl_provider_libctx(provider);
-    OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx);
-    const char *names = algodef->algorithm_names;
-    int id = ossl_namemap_add_names(namemap, 0, names, NAME_SEPARATOR);
-    void *method = NULL;
-
-    if (id != 0)
-        method = ossl_decoder_from_algorithm(id, algodef, provider);
+    struct do_one_data_st *data = arg;
 
-    if (method != NULL) {
-        data->user_fn(method, data->user_arg);
-        OSSL_DECODER_free(method);
-    }
+    data->user_fn(method, data->user_arg);
 }
 
 void OSSL_DECODER_do_all_provided(OSSL_LIB_CTX *libctx,
-                                  void (*fn)(OSSL_DECODER *decoder, void *arg),
-                                  void *arg)
+                                  void (*user_fn)(OSSL_DECODER *decoder,
+                                                  void *arg),
+                                  void *user_arg)
 {
-    struct decoder_do_all_data_st data;
+    struct decoder_data_st methdata;
+    struct do_one_data_st data;
+
+    methdata.libctx = libctx;
+    methdata.tmp_store = NULL;
+    (void)inner_ossl_decoder_fetch(&methdata, 0, NULL, NULL /* properties */);
 
-    data.user_fn = (void (*)(void *, void *))fn;
-    data.user_arg = arg;
-    ossl_algorithm_do_all(libctx, OSSL_OP_DECODER, NULL,
-                          NULL, decoder_do_one, NULL,
-                          &data);
+    data.user_fn = user_fn;
+    data.user_arg = user_arg;
+    if (methdata.tmp_store != NULL)
+        ossl_method_store_do_all(methdata.tmp_store, &do_one, &data);
+    ossl_method_store_do_all(get_decoder_store(libctx), &do_one, &data);
+    dealloc_tmp_decoder_store(methdata.tmp_store);
 }
 
 int OSSL_DECODER_names_do_all(const OSSL_DECODER *decoder,
diff --git a/crypto/encode_decode/decoder_pkey.c b/crypto/encode_decode/decoder_pkey.c
index cdd9841ea9..cb66ee4617 100644
--- a/crypto/encode_decode/decoder_pkey.c
+++ b/crypto/encode_decode/decoder_pkey.c
@@ -219,6 +219,7 @@ struct collect_decoder_data_st {
     STACK_OF(OPENSSL_CSTRING) *names;
     OSSL_DECODER_CTX *ctx;
 
+    int total;
     unsigned int error_occurred:1;
 };
 
@@ -247,6 +248,15 @@ static void collect_decoder(OSSL_DECODER *decoder, void *arg)
             && !decoder->does_selection(provctx, data->ctx->selection))
         return;
 
+    OSSL_TRACE_BEGIN(DECODER) {
+        BIO_printf(trc_out,
+                   "(ctx %p) Checking out decoder %p:\n"
+                   "    %s with %s\n",
+                   (void *)data->ctx, (void *)decoder,
+                   OSSL_DECODER_get0_name(decoder),
+                   OSSL_DECODER_get0_properties(decoder));
+    } OSSL_TRACE_END(DECODER);
+
     end_i = sk_OPENSSL_CSTRING_num(data->names);
     for (i = 0; i < end_i; i++) {
         const char *name = sk_OPENSSL_CSTRING_value(data->names, i);
@@ -288,6 +298,7 @@ static void collect_decoder(OSSL_DECODER *decoder, void *arg)
                 data->error_occurred = 1;
                 return;
             }
+            data->total++;
 
             /* Success */
             return;
@@ -306,6 +317,8 @@ int ossl_decoder_ctx_setup_for_pkey(OSSL_DECODER_CTX *ctx,
     struct decoder_pkey_data_st *process_data = NULL;
     STACK_OF(EVP_KEYMGMT) *keymgmts = NULL;
     STACK_OF(OPENSSL_CSTRING) *names = NULL;
+    const char *input_type = ctx->start_input_type;
+    const char *input_structure = ctx->input_structure;
     int ok = 0;
     int isecoid = 0;
 
@@ -314,6 +327,18 @@ int ossl_decoder_ctx_setup_for_pkey(OSSL_DECODER_CTX *ctx,
                 || strcmp(keytype, "1.2.840.10045.2.1") == 0))
         isecoid = 1;
 
+    OSSL_TRACE_BEGIN(DECODER) {
+        BIO_printf(trc_out,
+                   "(ctx %p) Looking for decoders producing %s%s%s%s%s%s\n",
+                   (void *)ctx,
+                   keytype != NULL ? keytype : "",
+                   keytype != NULL ? " keys" : "keys of any type",
+                   input_type != NULL ? " from " : "",
+                   input_type != NULL ? input_type : "",
+                   input_structure != NULL ? " with " : "",
+                   input_structure != NULL ? input_structure : "");
+    } OSSL_TRACE_END(DECODER);
+
     if ((process_data = OPENSSL_zalloc(sizeof(*process_data))) == NULL
         || (propquery != NULL
             && (process_data->propq = OPENSSL_strdup(propquery)) == NULL)
@@ -354,6 +379,19 @@ int ossl_decoder_ctx_setup_for_pkey(OSSL_DECODER_CTX *ctx,
     sk_EVP_KEYMGMT_free(keymgmts);
     keymgmts = NULL;
 
+    OSSL_TRACE_BEGIN(DECODER) {
+        int i, end = sk_OPENSSL_CSTRING_num(names);
+
+        BIO_printf(trc_out,
+                   "    Found %d keytypes (possibly with duplicates)",
+                   end);
+        for (i = 0; i < end; i++)
+            BIO_printf(trc_out, "%s%s",
+                       i == 0 ? ": " : ", ",
+                       sk_OPENSSL_CSTRING_value(names, i));
+        BIO_printf(trc_out, "\n");
+    } OSSL_TRACE_END(DECODER);
+
     /*
      * Finally, find all decoders that have any keymgmt of the collected
      * keymgmt names
@@ -370,6 +408,12 @@ int ossl_decoder_ctx_setup_for_pkey(OSSL_DECODER_CTX *ctx,
 
         if (collect_decoder_data.error_occurred)
             goto err;
+
+        OSSL_TRACE_BEGIN(DECODER) {
+            BIO_printf(trc_out,
+                       "(ctx %p) Got %d decoders producing keys\n",
+                       (void *)ctx, collect_decoder_data.total);
+        } OSSL_TRACE_END(DECODER);
     }
 
     if (OSSL_DECODER_CTX_get_num_decoders(ctx) != 0) {
diff --git a/crypto/encode_decode/encoder_meth.c b/crypto/encode_decode/encoder_meth.c
index eff9ddac54..ac56a29692 100644
--- a/crypto/encode_decode/encoder_meth.c
+++ b/crypto/encode_decode/encoder_meth.c
@@ -331,10 +331,10 @@ inner_ossl_encoder_fetch(struct encoder_data_st *methdata, int id,
     }
 
     /*
-     * If we have been passed neither a name_id or a name, we have an
+     * If we have been passed both an id and a name, we have an
      * internal programming error.
      */
-    if (!ossl_assert(id != 0 || name != NULL)) {
+    if (!ossl_assert(id == 0 || name == NULL)) {
         ERR_raise(ERR_LIB_OSSL_ENCODER, ERR_R_INTERNAL_ERROR);
         return NULL;
     }
@@ -386,7 +386,7 @@ inner_ossl_encoder_fetch(struct encoder_data_st *methdata, int id,
         unsupported = !methdata->flag_construct_error_occurred;
     }
 
-    if (method == NULL) {
+    if ((id != 0 || name != NULL) && method == NULL) {
         int code = unsupported ? ERR_R_UNSUPPORTED : ERR_R_FETCH_FAILED;
 
         if (name == NULL)
@@ -493,47 +493,36 @@ int OSSL_ENCODER_is_a(const OSSL_ENCODER *encoder, const char *name)
     return 0;
 }
 
-struct encoder_do_all_data_st {
-    void (*user_fn)(void *method, void *arg);
+struct do_one_data_st {
+    void (*user_fn)(OSSL_ENCODER *encoder, void *arg);
     void *user_arg;
 };
 
-static void encoder_do_one(OSSL_PROVIDER *provider,
-                           const OSSL_ALGORITHM *algodef,
-                           int no_store, void *vdata)
+static void do_one(ossl_unused int id, void *method, void *arg)
 {
-    struct encoder_do_all_data_st *data = vdata;
-    OSSL_LIB_CTX *libctx = ossl_provider_libctx(provider);
-    OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx);
-    const char *names = algodef->algorithm_names;
-    int id = ossl_namemap_add_names(namemap, 0, names, NAME_SEPARATOR);
-    void *method = NULL;
+    struct do_one_data_st *data = arg;
 
-    if (id != 0)
-        method =
-            encoder_from_algorithm(id, algodef, provider);
-
-    if (method != NULL) {
-        data->user_fn(method, data->user_arg);
-        OSSL_ENCODER_free(method);
-    }
+    data->user_fn(method, data->user_arg);
 }
 
 void OSSL_ENCODER_do_all_provided(OSSL_LIB_CTX *libctx,
-                                  void (*fn)(OSSL_ENCODER *encoder, void *arg),
-                                  void *arg)
+                                  void (*user_fn)(OSSL_ENCODER *encoder,
+                                                  void *arg),
+                                  void *user_arg)
 {
-    struct encoder_do_all_data_st data;
+    struct encoder_data_st methdata;
+    struct do_one_data_st data;
 
-    data.user_fn = (void (*)(void *, void *))fn;
-    data.user_arg = arg;
+    methdata.libctx = libctx;
+    methdata.tmp_store = NULL;
+    (void)inner_ossl_encoder_fetch(&methdata, 0, NULL, NULL /* properties */);
 
-    /*
-     * No pre- or post-condition for this call, as this only creates methods
-     * temporarly and then promptly destroys them.
-     */
-    ossl_algorithm_do_all(libctx, OSSL_OP_ENCODER, NULL, NULL,
-                          encoder_do_one, NULL, &data);
+    data.user_fn = user_fn;
+    data.user_arg = user_arg;
+    if (methdata.tmp_store != NULL)
+        ossl_method_store_do_all(methdata.tmp_store, &do_one, &data);
+    ossl_method_store_do_all(get_encoder_store(libctx), &do_one, &data);
+    dealloc_tmp_encoder_store(methdata.tmp_store);
 }
 
 int OSSL_ENCODER_names_do_all(const OSSL_ENCODER *encoder,
diff --git a/crypto/evp/asymcipher.c b/crypto/evp/asymcipher.c
index 1368f7094e..3150bfa94b 100644
--- a/crypto/evp/asymcipher.c
+++ b/crypto/evp/asymcipher.c
@@ -451,6 +451,7 @@ void EVP_ASYM_CIPHER_do_all_provided(OSSL_LIB_CTX *libctx,
     evp_generic_do_all(libctx, OSSL_OP_ASYM_CIPHER,
                        (void (*)(void *, void *))fn, arg,
                        evp_asym_cipher_from_algorithm,
+                       (int (*)(void *))EVP_ASYM_CIPHER_up_ref,
                        (void (*)(void *))EVP_ASYM_CIPHER_free);
 }
 
diff --git a/crypto/evp/digest.c b/crypto/evp/digest.c
index 00806ae201..98c39343be 100644
--- a/crypto/evp/digest.c
+++ b/crypto/evp/digest.c
@@ -1069,5 +1069,5 @@ void EVP_MD_do_all_provided(OSSL_LIB_CTX *libctx,
 {
     evp_generic_do_all(libctx, OSSL_OP_DIGEST,
                        (void (*)(void *, void *))fn, arg,
-                       evp_md_from_algorithm, evp_md_free);
+                       evp_md_from_algorithm, evp_md_up_ref, evp_md_free);
 }
diff --git a/crypto/evp/evp_enc.c b/crypto/evp/evp_enc.c
index 5188e73602..3a8e2c643e 100644
--- a/crypto/evp/evp_enc.c
+++ b/crypto/evp/evp_enc.c
@@ -1649,5 +1649,6 @@ void EVP_CIPHER_do_all_provided(OSSL_LIB_CTX *libctx,
 {
     evp_generic_do_all(libctx, OSSL_OP_CIPHER,
                        (void (*)(void *, void *))fn, arg,
-                       evp_cipher_from_algorithm, evp_cipher_free);
+                       evp_cipher_from_algorithm, evp_cipher_up_ref,
+                       evp_cipher_free);
 }
diff --git a/crypto/evp/evp_fetch.c b/crypto/evp/evp_fetch.c
index 1a3bb49b52..2ad9bf7dca 100644
--- a/crypto/evp/evp_fetch.c
+++ b/crypto/evp/evp_fetch.c
@@ -87,20 +87,33 @@ static OSSL_METHOD_STORE *get_evp_method_store(OSSL_LIB_CTX *libctx)
 /*
  * To identify the method in the EVP method store, we mix the name identity
  * with the operation identity, under the assumption that we don't have more
- * than 2^24 names or more than 2^8 operation types.
+ * than 2^23 names or more than 2^8 operation types.
  *
- * The resulting identity is a 32-bit integer, composed like this:
+ * The resulting identity is a 31-bit integer, composed like this:
  *
- * +---------24 bits--------+-8 bits-+
+ * +---------23 bits--------+-8 bits-+
  * |      name identity     | op id  |
  * +------------------------+--------+
+ *
+ * We limit this composite number to 31 bits, thus leaving the top uint32_t
+ * bit always zero, to avoid negative sign extension when downshifting after
+ * this number happens to be passed to an int (which happens as soon as it's
+ * passed to ossl_method_store_cache_set(), and it's in that form that it
+ * gets passed along to filter_on_operation_id(), defined further down.
  */
+#define METHOD_ID_OPERATION_MASK        0x000000FF
+#define METHOD_ID_OPERATION_MAX         ((1 << 8) - 1)
+#define METHOD_ID_NAME_MASK             0x7FFFFF00
+#define METHOD_ID_NAME_OFFSET           8
+#define METHOD_ID_NAME_MAX              ((1 << 23) - 1)
 static uint32_t evp_method_id(int name_id, unsigned int operation_id)
 {
-    if (!ossl_assert(name_id > 0 && name_id < (1 << 24))
-        || !ossl_assert(operation_id > 0 && operation_id < (1 << 8)))
+    if (!ossl_assert(name_id > 0 && name_id <= METHOD_ID_NAME_MAX)
+        || !ossl_assert(operation_id > 0
+                        && operation_id <= METHOD_ID_OPERATION_MAX))
         return 0;
-    return ((name_id << 8) & 0xFFFFFF00) | (operation_id & 0x000000FF);
+    return (((name_id << METHOD_ID_NAME_OFFSET) & METHOD_ID_NAME_MASK)
+            | (operation_id & METHOD_ID_OPERATION_MASK));
 }
 
 static void *get_evp_method_from_store(OSSL_LIB_CTX *libctx, void *store,
@@ -108,7 +121,7 @@ static void *get_evp_method_from_store(OSSL_LIB_CTX *libctx, void *store,
 {
     struct evp_method_data_st *methdata = data;
     void *method = NULL;
-    int name_id;
+    int name_id = 0;
     uint32_t meth_id;
 
     /*
@@ -116,7 +129,7 @@ static void *get_evp_method_from_store(OSSL_LIB_CTX *libctx, void *store,
      * that evp_generic_fetch() is asking for, and the operation id as well
      * as the name or name id are passed via methdata.
      */
-    if ((name_id = methdata->name_id) == 0) {
+    if ((name_id = methdata->name_id) == 0 && methdata->names != NULL) {
         OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx);
         const char *names = methdata->names;
         const char *q = strchr(names, NAME_SEPARATOR);
@@ -253,16 +266,16 @@ inner_evp_generic_fetch(struct evp_method_data_st *methdata, int operation_id,
     }
 
     /*
-     * If we have been passed neither a name_id or a name, we have an
+     * If we have been passed both a name_id and a name, we have an
      * internal programming error.
      */
-    if (!ossl_assert(name_id != 0 || name != NULL)) {
+    if (!ossl_assert(name_id == 0 || name == NULL)) {
         ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR);
         return NULL;
     }
 
     /* If we haven't received a name id yet, try to get one for the name */
-    if (name_id == 0)
+    if (name_id == 0 && name != NULL)
         name_id = ossl_namemap_name2num(namemap, name);
 
     /*
@@ -316,8 +329,9 @@ inner_evp_generic_fetch(struct evp_method_data_st *methdata, int operation_id,
             if (name_id == 0)
                 name_id = ossl_namemap_name2num(namemap, name);
             meth_id = evp_method_id(name_id, operation_id);
-            ossl_method_store_cache_set(store, meth_id, properties, method,
-                                        up_ref_method, free_method);
+            if (name_id != 0)
+                ossl_method_store_cache_set(store, meth_id, properties, method,
+                                            up_ref_method, free_method);
         }
 
         /*
@@ -327,7 +341,7 @@ inner_evp_generic_fetch(struct evp_method_data_st *methdata, int operation_id,
         unsupported = !methdata->flag_construct_error_occurred;
     }
 
-    if (method == NULL) {
+    if ((name_id != 0 || name != NULL) && method == NULL) {
         int code = unsupported ? ERR_R_UNSUPPORTED : ERR_R_FETCH_FAILED;
 
         if (name == NULL)
@@ -542,31 +556,18 @@ char *evp_get_global_properties_str(OSSL_LIB_CTX *libctx, int loadconfig)
     return propstr;
 }
 
-struct do_all_data_st {
+struct filter_data_st {
+    int operation_id;
     void (*user_fn)(void *method, void *arg);
     void *user_arg;
-    void *(*new_method)(const int name_id, const OSSL_ALGORITHM *algodef,
-                        OSSL_PROVIDER *prov);
-    void (*free_method)(void *);
 };
 
-static void do_one(OSSL_PROVIDER *provider, const OSSL_ALGORITHM *algo,
-                   int no_store, void *vdata)
+static void filter_on_operation_id(int id, void *method, void *arg)
 {
-    struct do_all_data_st *data = vdata;
-    OSSL_LIB_CTX *libctx = ossl_provider_libctx(provider);
-    OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx);
-    int name_id = ossl_namemap_add_names(namemap, 0, algo->algorithm_names,
-                                         NAME_SEPARATOR);
-    void *method = NULL;
-
-    if (name_id != 0)
-        method = data->new_method(name_id, algo, provider);
+    struct filter_data_st *data = arg;
 
-    if (method != NULL) {
+    if ((id & METHOD_ID_OPERATION_MASK) == data->operation_id)
         data->user_fn(method, data->user_arg);
-        data->free_method(method);
-    }
 }
 
 void evp_generic_do_all(OSSL_LIB_CTX *libctx, int operation_id,
@@ -575,21 +576,26 @@ void evp_generic_do_all(OSSL_LIB_CTX *libctx, int operation_id,
                         void *(*new_method)(int name_id,
                                             const OSSL_ALGORITHM *algodef,
                                             OSSL_PROVIDER *prov),
+                        int (*up_ref_method)(void *),
                         void (*free_method)(void *))
 {
-    struct do_all_data_st data;
+    struct evp_method_data_st methdata;
+    struct filter_data_st data;
+
+    methdata.libctx = libctx;
+    methdata.tmp_store = NULL;
+    (void)inner_evp_generic_fetch(&methdata, operation_id, 0, NULL, NULL,
+                                  new_method, up_ref_method, free_method);
 
-    data.new_method = new_method;
-    data.free_method = free_method;
+    data.operation_id = operation_id;
     data.user_fn = user_fn;
     data.user_arg = user_arg;
-
-    /*
-     * No pre- or post-condition for this call, as this only creates methods
-     * temporarly and then promptly destroys them.
-     */
-    ossl_algorithm_do_all(libctx, operation_id, NULL, NULL, do_one, NULL,
-                          &data);
+    if (methdata.tmp_store != NULL)
+        ossl_method_store_do_all(methdata.tmp_store, &filter_on_operation_id,
+                                 &data);
+    ossl_method_store_do_all(get_evp_method_store(libctx),
+                             &filter_on_operation_id, &data);
+    dealloc_tmp_evp_method_store(methdata.tmp_store);
 }
 
 int evp_is_a(OSSL_PROVIDER *prov, int number,
diff --git a/crypto/evp/evp_local.h b/crypto/evp/evp_local.h
index 137e458f5a..f8fd3f05f5 100644
--- a/crypto/evp/evp_local.h
+++ b/crypto/evp/evp_local.h
@@ -276,12 +276,16 @@ void *evp_generic_fetch_by_number(OSSL_LIB_CTX *ctx, int operation_id,
                                                       OSSL_PROVIDER *prov),
                                   int (*up_ref_method)(void *),
                                   void (*free_method)(void *));
+void evp_generic_do_all_prefetched(OSSL_LIB_CTX *libctx, int operation_id,
+                                   void (*user_fn)(void *method, void *arg),
+                                   void *user_arg);
 void evp_generic_do_all(OSSL_LIB_CTX *libctx, int operation_id,
                         void (*user_fn)(void *method, void *arg),
                         void *user_arg,
                         void *(*new_method)(int name_id,
                                             const OSSL_ALGORITHM *algodef,
                                             OSSL_PROVIDER *prov),
+                        int (*up_ref_method)(void *),
                         void (*free_method)(void *));
 
 /* Internal fetchers for method types that are to be combined with others */
diff --git a/crypto/evp/evp_rand.c b/crypto/evp/evp_rand.c
index a76d746d9a..7b1a44241e 100644
--- a/crypto/evp/evp_rand.c
+++ b/crypto/evp/evp_rand.c
@@ -489,7 +489,8 @@ void EVP_RAND_do_all_provided(OSSL_LIB_CTX *libctx,
 {
     evp_generic_do_all(libctx, OSSL_OP_RAND,
                        (void (*)(void *, void *))fn, arg,
-                       evp_rand_from_algorithm, evp_rand_free);
+                       evp_rand_from_algorithm, evp_rand_up_ref,
+                       evp_rand_free);
 }
 
 int EVP_RAND_names_do_all(const EVP_RAND *rand,
diff --git a/crypto/evp/exchange.c b/crypto/evp/exchange.c
index 72472aaace..ca8a049a1b 100644
--- a/crypto/evp/exchange.c
+++ b/crypto/evp/exchange.c
@@ -485,6 +485,7 @@ void EVP_KEYEXCH_do_all_provided(OSSL_LIB_CTX *libctx,
     evp_generic_do_all(libctx, OSSL_OP_KEYEXCH,
                        (void (*)(void *, void *))fn, arg,
                        evp_keyexch_from_algorithm,
+                       (int (*)(void *))EVP_KEYEXCH_up_ref,
                        (void (*)(void *))EVP_KEYEXCH_free);
 }
 
diff --git a/crypto/evp/kdf_meth.c b/crypto/evp/kdf_meth.c
index 8759021afc..94af5d40a0 100644
--- a/crypto/evp/kdf_meth.c
+++ b/crypto/evp/kdf_meth.c
@@ -228,5 +228,5 @@ void EVP_KDF_do_all_provided(OSSL_LIB_CTX *libctx,
 {
     evp_generic_do_all(libctx, OSSL_OP_KDF,
                        (void (*)(void *, void *))fn, arg,
-                       evp_kdf_from_algorithm, evp_kdf_free);
+                       evp_kdf_from_algorithm, evp_kdf_up_ref, evp_kdf_free);
 }
diff --git a/crypto/evp/kem.c b/crypto/evp/kem.c
index 721b840ea5..cb904a6b26 100644
--- a/crypto/evp/kem.c
+++ b/crypto/evp/kem.c
@@ -364,6 +364,7 @@ void EVP_KEM_do_all_provided(OSSL_LIB_CTX *libctx,
 {
     evp_generic_do_all(libctx, OSSL_OP_KEM, (void (*)(void *, void *))fn, arg,
                        evp_kem_from_algorithm,
+                       (int (*)(void *))EVP_KEM_up_ref,
                        (void (*)(void *))EVP_KEM_free);
 }
 
diff --git a/crypto/evp/keymgmt_meth.c b/crypto/evp/keymgmt_meth.c
index 439b8f035c..ca357b60ef 100644
--- a/crypto/evp/keymgmt_meth.c
+++ b/crypto/evp/keymgmt_meth.c
@@ -278,6 +278,7 @@ void EVP_KEYMGMT_do_all_provided(OSSL_LIB_CTX *libctx,
     evp_generic_do_all(libctx, OSSL_OP_KEYMGMT,
                        (void (*)(void *, void *))fn, arg,
                        keymgmt_from_algorithm,
+                       (int (*)(void *))EVP_KEYMGMT_up_ref,
                        (void (*)(void *))EVP_KEYMGMT_free);
 }
 
diff --git a/crypto/evp/mac_meth.c b/crypto/evp/mac_meth.c
index 74cfecbcdf..99b1e3b003 100644
--- a/crypto/evp/mac_meth.c
+++ b/crypto/evp/mac_meth.c
@@ -233,5 +233,5 @@ void EVP_MAC_do_all_provided(OSSL_LIB_CTX *libctx,
 {
     evp_generic_do_all(libctx, OSSL_OP_MAC,
                        (void (*)(void *, void *))fn, arg,
-                       evp_mac_from_algorithm, evp_mac_free);
+                       evp_mac_from_algorithm, evp_mac_up_ref, evp_mac_free);
 }
diff --git a/crypto/evp/signature.c b/crypto/evp/signature.c
index b31f6a4bd0..e3bfdd56a2 100644
--- a/crypto/evp/signature.c
+++ b/crypto/evp/signature.c
@@ -342,6 +342,7 @@ void EVP_SIGNATURE_do_all_provided(OSSL_LIB_CTX *libctx,
     evp_generic_do_all(libctx, OSSL_OP_SIGNATURE,
                        (void (*)(void *, void *))fn, arg,
                        evp_signature_from_algorithm,
+                       (int (*)(void *))EVP_SIGNATURE_up_ref,
                        (void (*)(void *))EVP_SIGNATURE_free);
 }
 
diff --git a/crypto/property/property.c b/crypto/property/property.c
index a769a7307e..535120b581 100644
--- a/crypto/property/property.c
+++ b/crypto/property/property.c
@@ -362,6 +362,42 @@ int ossl_method_store_remove(OSSL_METHOD_STORE *store, int nid,
     return 0;
 }
 
+static void alg_do_one(ALGORITHM *alg, IMPLEMENTATION *impl,
+                       void (*fn)(int id, void *method, void *fnarg),
+                       void *fnarg)
+{
+    fn(alg->nid, impl->method.method, fnarg);
+}
+
+struct alg_do_each_data_st {
+    void (*fn)(int id, void *method, void *fnarg);
+    void *fnarg;
+};
+
+static void alg_do_each(ossl_uintmax_t idx, ALGORITHM *alg, void *arg)
+{
+    struct alg_do_each_data_st *data = arg;
+    int i, end = sk_IMPLEMENTATION_num(alg->impls);
+
+    for (i = 0; i < end; i++) {
+        IMPLEMENTATION *impl = sk_IMPLEMENTATION_value(alg->impls, i);
+
+        alg_do_one(alg, impl, data->fn, data->fnarg);
+    }
+}
+
+void ossl_method_store_do_all(OSSL_METHOD_STORE *store,
+                              void (*fn)(int id, void *method, void *fnarg),
+                              void *fnarg)
+{
+    struct alg_do_each_data_st data;
+
+    data.fn = fn;
+    data.fnarg = fnarg;
+    if (store != NULL)
+        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)
diff --git a/crypto/store/store_meth.c b/crypto/store/store_meth.c
index efc4a40fa7..7b2f537d49 100644
--- a/crypto/store/store_meth.c
+++ b/crypto/store/store_meth.c
@@ -288,16 +288,16 @@ inner_loader_fetch(struct loader_data_st *methdata, int id,
     }
 
     /*
-     * If we have been passed neither a scheme_id nor a scheme, we have an
+     * If we have been passed both an id and a scheme, we have an
      * internal programming error.
      */
-    if (!ossl_assert(id != 0 || scheme != NULL)) {
+    if (!ossl_assert(id == 0 || scheme == NULL)) {
         ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_INTERNAL_ERROR);
         return NULL;
     }
 
     /* If we haven't received a name id yet, try to get one for the name */
-    if (id == 0)
+    if (id == 0 && scheme != NULL)
         id = ossl_namemap_name2num(namemap, scheme);
 
     /*
@@ -343,7 +343,7 @@ inner_loader_fetch(struct loader_data_st *methdata, int id,
         unsupported = !methdata->flag_construct_error_occurred;
     }
 
-    if (method == NULL) {
+    if ((id != 0 || scheme != NULL) && method == NULL) {
         int code = unsupported ? ERR_R_UNSUPPORTED : ERR_R_FETCH_FAILED;
 
         if (scheme == NULL)
@@ -436,44 +436,36 @@ int OSSL_STORE_LOADER_is_a(const OSSL_STORE_LOADER *loader, const char *name)
     return 0;
 }
 
-struct loader_do_all_data_st {
-    void (*user_fn)(void *method, void *arg);
+struct do_one_data_st {
+    void (*user_fn)(OSSL_STORE_LOADER *loader, void *arg);
     void *user_arg;
 };
 
-static void loader_do_one(OSSL_PROVIDER *provider,
-                          const OSSL_ALGORITHM *algodef,
-                          int no_store, void *vdata)
+static void do_one(ossl_unused int id, void *method, void *arg)
 {
-    struct loader_do_all_data_st *data = vdata;
-    OSSL_LIB_CTX *libctx = ossl_provider_libctx(provider);
-    OSSL_NAMEMAP *namemap = ossl_namemap_stored(libctx);
-    const char *name = algodef->algorithm_names;
-    int id = ossl_namemap_add_name(namemap, 0, name);
-    void *method = NULL;
+    struct do_one_data_st *data = arg;
 
-    if (id != 0)
-        method =
-            loader_from_algorithm(id, algodef, provider);
-
-    if (method != NULL) {
-        data->user_fn(method, data->user_arg);
-        OSSL_STORE_LOADER_free(method);
-    }
+    data->user_fn(method, data->user_arg);
 }
 
 void OSSL_STORE_LOADER_do_all_provided(OSSL_LIB_CTX *libctx,
-                                       void (*fn)(OSSL_STORE_LOADER *loader,
-                                                  void *arg),
-                                       void *arg)
+                                       void (*user_fn)(OSSL_STORE_LOADER *loader,
+                                                       void *arg),
+                                       void *user_arg)
 {
-    struct loader_do_all_data_st data;
+    struct loader_data_st methdata;
+    struct do_one_data_st data;
 
-    data.user_fn = (void (*)(void *, void *))fn;
-    data.user_arg = arg;
-    ossl_algorithm_do_all(libctx, OSSL_OP_STORE, NULL,
-                          NULL, loader_do_one, NULL,
-                          &data);
+    methdata.libctx = libctx;
+    methdata.tmp_store = NULL;
+    (void)inner_loader_fetch(&methdata, 0, NULL, NULL /* properties */);
+
+    data.user_fn = user_fn;
+    data.user_arg = user_arg;
+    if (methdata.tmp_store != NULL)
+        ossl_method_store_do_all(methdata.tmp_store, &do_one, &data);
+    ossl_method_store_do_all(get_loader_store(libctx), &do_one, &data);
+    dealloc_tmp_loader_store(methdata.tmp_store);
 }
 
 int OSSL_STORE_LOADER_names_do_all(const OSSL_STORE_LOADER *loader,
diff --git a/include/crypto/decoder.h b/include/crypto/decoder.h
index 3cf1077fca..cc06ef2926 100644
--- a/include/crypto/decoder.h
+++ b/include/crypto/decoder.h
@@ -40,4 +40,3 @@ int ossl_decoder_ctx_setup_for_pkey(OSSL_DECODER_CTX *ctx,
 int ossl_decoder_get_number(const OSSL_DECODER *encoder);
 
 #endif
-
diff --git a/include/internal/property.h b/include/internal/property.h
index bcea21d80c..dd9a2dc2d8 100644
--- a/include/internal/property.h
+++ b/include/internal/property.h
@@ -58,6 +58,9 @@ int ossl_method_store_add(OSSL_METHOD_STORE *store, const OSSL_PROVIDER *prov,
                           void (*method_destruct)(void *));
 int ossl_method_store_remove(OSSL_METHOD_STORE *store, int nid,
                              const void *method);
+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);
 
diff --git a/test/evp_extra_test.c b/test/evp_extra_test.c
index 33bb698ff3..f10e0077ec 100644
--- a/test/evp_extra_test.c
+++ b/test/evp_extra_test.c
@@ -1294,7 +1294,7 @@ static int test_EVP_PKCS82PKEY_wrong_tag(void)
         || !TEST_int_gt(BIO_get_mem_data(membio, &membuf), 0)
         || !TEST_ptr(p8inf = d2i_PKCS8_PRIV_KEY_INFO_bio(membio, NULL))
         || !TEST_ptr(pkey2 = EVP_PKCS82PKEY(p8inf))
-        || !TEST_int_eq(ERR_get_error(), 0)) {
+        || !TEST_int_eq(ERR_peek_last_error(), 0)) {
         goto done;
     }
 


More information about the openssl-commits mailing list