[openssl] master update

Richard Levitte levitte at openssl.org
Tue Jul 23 04:38:38 UTC 2019


The branch master has been updated
       via  b8441adb593392e224eccc95495e9a7451d04821 (commit)
       via  c540f00f383754fa490be76c2c3398ccd4d2a869 (commit)
       via  3d96a51c09296cb5c283efb5681105a7691e6fbc (commit)
       via  84d167f6eb1c3cb3cf9092122349967f717c56ca (commit)
       via  a883c02faa2549c98256577fd881af17b95444cf (commit)
       via  b37066fdf731dc186f87d816c59ea412418f3d9d (commit)
       via  1d2622d4f357a7994cf6fdc3fdba27317a6a6597 (commit)
       via  c750bc08516f1273751ba03fa533e3eb2418b92d (commit)
       via  6b9e37246d5fd8e701b825c71fa1a018916af33c (commit)
      from  da2addc515d547b0d724a4fc730c4345ed713221 (commit)


- Log -----------------------------------------------------------------
commit b8441adb593392e224eccc95495e9a7451d04821
Author: Richard Levitte <levitte at openssl.org>
Date:   Sat Jul 13 07:04:01 2019 +0200

    Re-implement the cipher and digest listings for 'openssl list'
    
    They now display both legacy and provided algorithms.
    
    Reviewed-by: Paul Dale <paul.dale at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/9356)

commit c540f00f383754fa490be76c2c3398ccd4d2a869
Author: Richard Levitte <levitte at openssl.org>
Date:   Sat Jul 13 07:02:54 2019 +0200

    Add EVP_CIPHER_do_all_ex() and EVP_MD_do_all_ex()
    
    Reviewed-by: Paul Dale <paul.dale at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/9356)

commit 3d96a51c09296cb5c283efb5681105a7691e6fbc
Author: Richard Levitte <levitte at openssl.org>
Date:   Sat Jul 13 06:53:44 2019 +0200

    Add internal function evp_generic_do_all()
    
    This function is used to traverse all algorithm implementations for a
    given operation type, and execute the given function for each of them.
    
    For each algorithm implementation, a method is created and passed to
    the given function, and then freed after that function's return.  If
    the caller wishes to keep the method for longer, they must call the
    appropriate up_ref function on the method, and they must also make
    sure to free the passed methods at some point.
    
    Reviewed-by: Paul Dale <paul.dale at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/9356)

commit 84d167f6eb1c3cb3cf9092122349967f717c56ca
Author: Richard Levitte <levitte at openssl.org>
Date:   Wed Jul 10 23:14:03 2019 +0200

    Refactor ossl_method_construct() in terms of ossl_algorithm_do_all()
    
    Reviewed-by: Paul Dale <paul.dale at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/9356)

commit a883c02faa2549c98256577fd881af17b95444cf
Author: Richard Levitte <levitte at openssl.org>
Date:   Wed Jul 10 23:11:27 2019 +0200

    Add internal function ossl_algorithm_do_all()
    
    This function is used to traverse all the implementations provided by
    one provider, or all implementation for a specific operation across
    all loaded providers, or both, and execute a given function for each
    occurence.
    
    This will be used by ossl_method_construct(), but also by information
    processing functions.
    
    Reviewed-by: Paul Dale <paul.dale at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/9356)

commit b37066fdf731dc186f87d816c59ea412418f3d9d
Author: Richard Levitte <levitte at openssl.org>
Date:   Wed Jul 10 23:00:22 2019 +0200

    Add OSSL_PROVIDER_name()
    
    Reviewed-by: Paul Dale <paul.dale at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/9356)

commit 1d2622d4f357a7994cf6fdc3fdba27317a6a6597
Author: Richard Levitte <levitte at openssl.org>
Date:   Wed Jul 10 22:59:07 2019 +0200

    Add EVP_MD_provider() and EVP_CIPHER_provider()
    
    Reviewed-by: Paul Dale <paul.dale at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/9356)

commit c750bc08516f1273751ba03fa533e3eb2418b92d
Author: Richard Levitte <levitte at openssl.org>
Date:   Wed Jul 10 22:24:00 2019 +0200

    Re-implement EVP_MD_name() and EVP_CIPHER_name() as functions
    
    They will do the same as usual for non-provider algorithms
    implementations, but can handle provider implementations as well.
    
    Reviewed-by: Paul Dale <paul.dale at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/9356)

commit 6b9e37246d5fd8e701b825c71fa1a018916af33c
Author: Richard Levitte <levitte at openssl.org>
Date:   Wed Jul 10 22:22:16 2019 +0200

    Add a mechnism to save the name of fetched methods
    
    This will be useful for information display, as well as for code that
    want to check the name of an algorithm.  This can eventually replace
    all NID checks.
    
    Reviewed-by: Paul Dale <paul.dale at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/9356)

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

Summary of changes:
 apps/list.c                                 | 97 +++++++++++++++++++++++++++--
 crypto/build.info                           |  3 +-
 crypto/core_algorithm.c                     | 75 ++++++++++++++++++++++
 crypto/core_fetch.c                         | 78 ++++++++++-------------
 crypto/evp/cmeth_lib.c                      |  1 +
 crypto/evp/digest.c                         | 17 ++++-
 crypto/evp/evp_enc.c                        | 18 +++++-
 crypto/evp/evp_fetch.c                      | 46 +++++++++++++-
 crypto/evp/evp_lib.c                        | 33 ++++++++++
 crypto/evp/evp_locl.h                       | 13 +++-
 crypto/evp/exchange.c                       | 10 ++-
 crypto/evp/keymgmt_meth.c                   |  9 ++-
 crypto/include/internal/evp_int.h           |  2 +
 crypto/provider.c                           |  5 ++
 doc/internal/man3/ossl_algorithm_do_all.pod | 63 +++++++++++++++++++
 doc/man1/list.pod                           |  4 ++
 doc/man3/EVP_DigestInit.pod                 | 36 +++++++++--
 doc/man3/EVP_EncryptInit.pod                | 24 ++++++-
 doc/man3/OSSL_PROVIDER.pod                  |  6 +-
 include/internal/core.h                     |  7 +++
 include/openssl/core_numbers.h              |  3 +
 include/openssl/evp.h                       | 14 ++++-
 include/openssl/provider.h                  |  3 +
 util/libcrypto.num                          |  7 +++
 util/private.num                            |  1 +
 25 files changed, 503 insertions(+), 72 deletions(-)
 create mode 100644 crypto/core_algorithm.c
 create mode 100644 doc/internal/man3/ossl_algorithm_do_all.pod

diff --git a/apps/list.c b/apps/list.c
index 8e4f005..5f05fb9 100644
--- a/apps/list.c
+++ b/apps/list.c
@@ -10,6 +10,8 @@
 #include <string.h>
 #include <openssl/evp.h>
 #include <openssl/err.h>
+#include <openssl/provider.h>
+#include <openssl/safestack.h>
 #include "apps.h"
 #include "progs.h"
 #include "opt.h"
@@ -18,28 +20,111 @@ static void list_cipher_fn(const EVP_CIPHER *c,
                            const char *from, const char *to, void *arg)
 {
     if (c != NULL) {
-        BIO_printf(arg, "%s\n", EVP_CIPHER_name(c));
+        BIO_printf(arg, "  %s\n", EVP_CIPHER_name(c));
     } else {
         if (from == NULL)
             from = "<undefined>";
         if (to == NULL)
             to = "<undefined>";
-        BIO_printf(arg, "%s => %s\n", from, to);
+        BIO_printf(arg, "  %s => %s\n", from, to);
+    }
+}
+
+DEFINE_STACK_OF(EVP_CIPHER)
+static int cipher_cmp(const EVP_CIPHER * const *a,
+                      const EVP_CIPHER * const *b)
+{
+    int ret = strcasecmp(EVP_CIPHER_name(*a), EVP_CIPHER_name(*b));
+
+    if (ret == 0)
+        ret = strcmp(OSSL_PROVIDER_name(EVP_CIPHER_provider(*a)),
+                     OSSL_PROVIDER_name(EVP_CIPHER_provider(*b)));
+
+    return ret;
+}
+
+static void collect_ciphers(EVP_CIPHER *cipher, void *stack)
+{
+    STACK_OF(EVP_CIPHER) *cipher_stack = stack;
+
+    sk_EVP_CIPHER_push(cipher_stack, cipher);
+    EVP_CIPHER_up_ref(cipher);
+}
+
+static void list_ciphers(void)
+{
+    STACK_OF(EVP_CIPHER) *ciphers = sk_EVP_CIPHER_new(cipher_cmp);
+    int i;
+
+    BIO_printf(bio_out, "Legacy:\n");
+    EVP_CIPHER_do_all_sorted(list_cipher_fn, bio_out);
+
+    BIO_printf(bio_out, "Provided:\n");
+    EVP_CIPHER_do_all_ex(NULL, collect_ciphers, ciphers);
+    sk_EVP_CIPHER_sort(ciphers);
+    for (i = 0; i < sk_EVP_CIPHER_num(ciphers); i++) {
+        const EVP_CIPHER *c = sk_EVP_CIPHER_value(ciphers, i);
+
+        BIO_printf(bio_out, "  %s", EVP_CIPHER_name(c));
+        BIO_printf(bio_out, " @ %s\n",
+                   OSSL_PROVIDER_name(EVP_CIPHER_provider(c)));
     }
+    sk_EVP_CIPHER_pop_free(ciphers, EVP_CIPHER_meth_free);
 }
 
 static void list_md_fn(const EVP_MD *m,
                        const char *from, const char *to, void *arg)
 {
     if (m != NULL) {
-        BIO_printf(arg, "%s\n", EVP_MD_name(m));
+        BIO_printf(arg, "  %s\n", EVP_MD_name(m));
     } else {
         if (from == NULL)
             from = "<undefined>";
         if (to == NULL)
             to = "<undefined>";
-        BIO_printf((BIO *)arg, "%s => %s\n", from, to);
+        BIO_printf((BIO *)arg, "  %s => %s\n", from, to);
+    }
+}
+
+DEFINE_STACK_OF(EVP_MD)
+static int md_cmp(const EVP_MD * const *a, const EVP_MD * const *b)
+{
+    int ret = strcasecmp(EVP_MD_name(*a), EVP_MD_name(*b));
+
+    if (ret == 0)
+        ret = strcmp(OSSL_PROVIDER_name(EVP_MD_provider(*a)),
+                     OSSL_PROVIDER_name(EVP_MD_provider(*b)));
+
+    return ret;
+}
+
+static void collect_digests(EVP_MD *md, void *stack)
+{
+    STACK_OF(EVP_MD) *digest_stack = stack;
+
+    sk_EVP_MD_push(digest_stack, md);
+    EVP_MD_up_ref(md);
+}
+
+static void list_digests(void)
+{
+    STACK_OF(EVP_MD) *digests = sk_EVP_MD_new(md_cmp);
+    int i;
+
+    BIO_printf(bio_out, "Legacy:\n");
+    EVP_MD_do_all_sorted(list_md_fn, bio_out);
+
+    BIO_printf(bio_out, "Provided:\n");
+    EVP_MD_do_all_ex(NULL, collect_digests, digests);
+    sk_EVP_MD_sort(digests);
+    for (i = 0; i < sk_EVP_MD_num(digests); i++) {
+        const EVP_MD *c = sk_EVP_MD_value(digests, i);
+
+        BIO_printf(bio_out, "  %s", EVP_MD_name(c));
+        BIO_printf(bio_out, " @ %s\n",
+                   OSSL_PROVIDER_name(EVP_MD_provider(c)));
     }
+    sk_EVP_MD_pop_free(digests, EVP_MD_meth_free);
 }
 
 static void list_mac_fn(const EVP_MAC *m,
@@ -450,7 +535,7 @@ opthelp:
             list_type(FT_md, one);
             break;
         case OPT_DIGEST_ALGORITHMS:
-            EVP_MD_do_all_sorted(list_md_fn, bio_out);
+            list_digests();
             break;
         case OPT_MAC_ALGORITHMS:
             EVP_MAC_do_all_sorted(list_mac_fn, bio_out);
@@ -459,7 +544,7 @@ opthelp:
             list_type(FT_cipher, one);
             break;
         case OPT_CIPHER_ALGORITHMS:
-            EVP_CIPHER_do_all_sorted(list_cipher_fn, bio_out);
+            list_ciphers();
             break;
         case OPT_PK_ALGORITHMS:
             list_pkey();
diff --git a/crypto/build.info b/crypto/build.info
index 088ec87..3f9eb52 100644
--- a/crypto/build.info
+++ b/crypto/build.info
@@ -59,7 +59,8 @@ IF[{- !$disabled{asm} && $config{processor} ne '386' -}]
 ENDIF
 
 # The Core
-$CORE_COMMON=provider_core.c provider_predefined.c core_fetch.c core_namemap.c
+$CORE_COMMON=provider_core.c provider_predefined.c \
+        core_fetch.c core_algorithm.c core_namemap.c
 
 SOURCE[../libcrypto]=$CORE_COMMON provider_conf.c
 SOURCE[../providers/fips]=$CORE_COMMON
diff --git a/crypto/core_algorithm.c b/crypto/core_algorithm.c
new file mode 100644
index 0000000..f88a045
--- /dev/null
+++ b/crypto/core_algorithm.c
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License").  You may not use
+ * this file except in compliance with the License.  You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/core.h>
+#include <openssl/core_numbers.h>
+#include "internal/core.h"
+#include "internal/property.h"
+#include "internal/provider.h"
+
+struct algorithm_data_st {
+    OPENSSL_CTX *libctx;
+    int operation_id;            /* May be zero for finding them all */
+    void (*fn)(OSSL_PROVIDER *, const OSSL_ALGORITHM *, int no_store,
+               void *data);
+    void *data;
+};
+
+static int algorithm_do_this(OSSL_PROVIDER *provider, void *cbdata)
+{
+    struct algorithm_data_st *data = cbdata;
+    int no_store = 0;    /* Assume caching is ok */
+    int first_operation = 1;
+    int last_operation = OSSL_OP__HIGHEST;
+    int cur_operation;
+    int ok = 0;
+
+    if (data->operation_id != 0)
+        first_operation = last_operation = data->operation_id;
+
+    for (cur_operation = first_operation;
+         cur_operation <= last_operation;
+         cur_operation++) {
+        const OSSL_ALGORITHM *map =
+            ossl_provider_query_operation(provider, data->operation_id,
+                                          &no_store);
+
+        if (map == NULL)
+            break;
+
+        ok = 1;                  /* As long as we've found *something* */
+        while (map->algorithm_name != NULL) {
+            const OSSL_ALGORITHM *thismap = map++;
+
+            data->fn(provider, thismap, no_store, data->data);
+        }
+    }
+
+    return ok;
+}
+
+void ossl_algorithm_do_all(OPENSSL_CTX *libctx, int operation_id,
+                           OSSL_PROVIDER *provider,
+                           void (*fn)(OSSL_PROVIDER *provider,
+                                      const OSSL_ALGORITHM *algo,
+                                      int no_store, void *data),
+                           void *data)
+{
+    struct algorithm_data_st cbdata;
+
+    cbdata.libctx = libctx;
+    cbdata.operation_id = operation_id;
+    cbdata.fn = fn;
+    cbdata.data = data;
+
+    if (provider == NULL)
+        ossl_provider_forall_loaded(libctx, algorithm_do_this, &cbdata);
+    else
+        algorithm_do_this(provider, &cbdata);
+}
diff --git a/crypto/core_fetch.c b/crypto/core_fetch.c
index 56a3c5c..c1c8158 100644
--- a/crypto/core_fetch.c
+++ b/crypto/core_fetch.c
@@ -24,55 +24,45 @@ struct construct_data_st {
     void *mcm_data;
 };
 
-static int ossl_method_construct_this(OSSL_PROVIDER *provider, void *cbdata)
+static void ossl_method_construct_this(OSSL_PROVIDER *provider,
+                                       const OSSL_ALGORITHM *algo,
+                                       int no_store, void *cbdata)
 {
     struct construct_data_st *data = cbdata;
-    int no_store = 0;    /* Assume caching is ok */
-    const OSSL_ALGORITHM *map =
-        ossl_provider_query_operation(provider, data->operation_id, &no_store);
-
-    if (map == NULL)
-        return 0;
-
-    while (map->algorithm_name != NULL) {
-        const OSSL_ALGORITHM *thismap = map++;
-        void *method = NULL;
-
-        if ((method = data->mcm->construct(thismap->algorithm_name,
-                                           thismap->implementation, provider,
-                                           data->mcm_data)) == NULL)
-            continue;
+    void *method = NULL;
 
+    if ((method = data->mcm->construct(algo->algorithm_name,
+                                       algo->implementation, provider,
+                                       data->mcm_data)) == NULL)
+        return;
+
+    /*
+     * Note regarding putting the method in stores:
+     *
+     * we don't need to care if it actually got in or not here.
+     * If it didn't get in, it will simply not be available when
+     * ossl_method_construct() tries to get it from the store.
+     *
+     * It is *expected* that the put function increments the refcnt
+     * of the passed method.
+     */
+
+    if (data->force_store || !no_store) {
         /*
-         * Note regarding putting the method in stores:
-         *
-         * we don't need to care if it actually got in or not here.
-         * If it didn't get in, it will simply not be available when
-         * ossl_method_construct() tries to get it from the store.
-         *
-         * It is *expected* that the put function increments the refcnt
-         * of the passed method.
+         * If we haven't been told not to store,
+         * add to the global store
          */
-
-        if (data->force_store || !no_store) {
-            /*
-             * If we haven't been told not to store,
-             * add to the global store
-             */
-            data->mcm->put(data->libctx, NULL, method, data->operation_id,
-                           thismap->algorithm_name,
-                           thismap->property_definition, data->mcm_data);
-        }
-
-        data->mcm->put(data->libctx, data->store, method, data->operation_id,
-                       thismap->algorithm_name, thismap->property_definition,
-                       data->mcm_data);
-
-        /* refcnt-- because we're dropping the reference */
-        data->mcm->destruct(method, data->mcm_data);
+        data->mcm->put(data->libctx, NULL, method, data->operation_id,
+                       algo->algorithm_name,
+                       algo->property_definition, data->mcm_data);
     }
 
-    return 1;
+    data->mcm->put(data->libctx, data->store, method, data->operation_id,
+                   algo->algorithm_name, algo->property_definition,
+                   data->mcm_data);
+
+    /* refcnt-- because we're dropping the reference */
+    data->mcm->destruct(method, data->mcm_data);
 }
 
 void *ossl_method_construct(OPENSSL_CTX *libctx, int operation_id,
@@ -99,8 +89,8 @@ void *ossl_method_construct(OPENSSL_CTX *libctx, int operation_id,
         cbdata.force_store = force_store;
         cbdata.mcm = mcm;
         cbdata.mcm_data = mcm_data;
-        ossl_provider_forall_loaded(libctx, ossl_method_construct_this,
-                                    &cbdata);
+        ossl_algorithm_do_all(libctx, operation_id, NULL,
+                              ossl_method_construct_this, &cbdata);
 
         method = mcm->get(libctx, cbdata.store, operation_id, name,
                           propquery, mcm_data);
diff --git a/crypto/evp/cmeth_lib.c b/crypto/evp/cmeth_lib.c
index 40aca34..51c9b6e 100644
--- a/crypto/evp/cmeth_lib.c
+++ b/crypto/evp/cmeth_lib.c
@@ -55,6 +55,7 @@ void EVP_CIPHER_meth_free(EVP_CIPHER *cipher)
         if (i > 0)
             return;
         ossl_provider_free(cipher->prov);
+        OPENSSL_free(cipher->name);
         CRYPTO_THREAD_lock_free(cipher->lock);
         OPENSSL_free(cipher);
     }
diff --git a/crypto/evp/digest.c b/crypto/evp/digest.c
index 65b12e3..78e8756 100644
--- a/crypto/evp/digest.c
+++ b/crypto/evp/digest.c
@@ -577,15 +577,19 @@ int EVP_MD_CTX_ctrl(EVP_MD_CTX *ctx, int cmd, int p1, void *p2)
     return 0;
 }
 
-static void *evp_md_from_dispatch(const OSSL_DISPATCH *fns,
+static void *evp_md_from_dispatch(const char *name, const OSSL_DISPATCH *fns,
                                   OSSL_PROVIDER *prov)
 {
     EVP_MD *md = NULL;
     int fncnt = 0;
 
     /* EVP_MD_fetch() will set the legacy NID if available */
-    if ((md = EVP_MD_meth_new(NID_undef, NID_undef)) == NULL)
+    if ((md = EVP_MD_meth_new(NID_undef, NID_undef)) == NULL
+        || (md->name = OPENSSL_strdup(name)) == NULL) {
+        EVP_MD_meth_free(md);
+        EVPerr(0, ERR_R_MALLOC_FAILURE);
         return NULL;
+    }
 
     for (; fns->function_id != 0; fns++) {
         switch (fns->function_id) {
@@ -697,3 +701,12 @@ EVP_MD *EVP_MD_fetch(OPENSSL_CTX *ctx, const char *algorithm,
 
     return md;
 }
+
+void EVP_MD_do_all_ex(OPENSSL_CTX *libctx,
+                          void (*fn)(EVP_MD *mac, void *arg),
+                          void *arg)
+{
+    evp_generic_do_all(libctx, OSSL_OP_DIGEST,
+                       (void (*)(void *, void *))fn, arg,
+                       evp_md_from_dispatch, evp_md_free);
+}
diff --git a/crypto/evp/evp_enc.c b/crypto/evp/evp_enc.c
index c1f7e77..0873bae 100644
--- a/crypto/evp/evp_enc.c
+++ b/crypto/evp/evp_enc.c
@@ -1127,7 +1127,8 @@ int EVP_CIPHER_CTX_copy(EVP_CIPHER_CTX *out, const EVP_CIPHER_CTX *in)
     return 1;
 }
 
-static void *evp_cipher_from_dispatch(const OSSL_DISPATCH *fns,
+static void *evp_cipher_from_dispatch(const char *name,
+                                      const OSSL_DISPATCH *fns,
                                       OSSL_PROVIDER *prov)
 {
     EVP_CIPHER *cipher = NULL;
@@ -1137,8 +1138,12 @@ static void *evp_cipher_from_dispatch(const OSSL_DISPATCH *fns,
      * The legacy NID is set by EVP_CIPHER_fetch() if the name exists in
      * the object database.
      */
-    if ((cipher = EVP_CIPHER_meth_new(0, 0, 0)) == NULL)
+    if ((cipher = EVP_CIPHER_meth_new(0, 0, 0)) == NULL
+        || (cipher->name = OPENSSL_strdup(name)) == NULL) {
+        EVP_CIPHER_meth_free(cipher);
+        EVPerr(0, ERR_R_MALLOC_FAILURE);
         return NULL;
+    }
 
     for (; fns->function_id != 0; fns++) {
         switch (fns->function_id) {
@@ -1258,3 +1263,12 @@ EVP_CIPHER *EVP_CIPHER_fetch(OPENSSL_CTX *ctx, const char *algorithm,
 
     return cipher;
 }
+
+void EVP_CIPHER_do_all_ex(OPENSSL_CTX *libctx,
+                          void (*fn)(EVP_CIPHER *mac, void *arg),
+                          void *arg)
+{
+    evp_generic_do_all(libctx, OSSL_OP_CIPHER,
+                       (void (*)(void *, void *))fn, arg,
+                       evp_cipher_from_dispatch, evp_cipher_free);
+}
diff --git a/crypto/evp/evp_fetch.c b/crypto/evp/evp_fetch.c
index 0c25f0d..5c100dd 100644
--- a/crypto/evp/evp_fetch.c
+++ b/crypto/evp/evp_fetch.c
@@ -40,7 +40,8 @@ struct method_data_st {
     OPENSSL_CTX *libctx;
     const char *name;
     OSSL_METHOD_CONSTRUCT_METHOD *mcm;
-    void *(*method_from_dispatch)(const OSSL_DISPATCH *, OSSL_PROVIDER *);
+    void *(*method_from_dispatch)(const char *, const OSSL_DISPATCH *,
+                                  OSSL_PROVIDER *);
     int (*refcnt_up_method)(void *method);
     void (*destruct_method)(void *method);
 };
@@ -143,7 +144,7 @@ static void *construct_method(const char *name, const OSSL_DISPATCH *fns,
 {
     struct method_data_st *methdata = data;
 
-    return methdata->method_from_dispatch(fns, prov);
+    return methdata->method_from_dispatch(name, fns, prov);
 }
 
 static void destruct_method(void *method, void *data)
@@ -155,7 +156,8 @@ static void destruct_method(void *method, void *data)
 
 void *evp_generic_fetch(OPENSSL_CTX *libctx, int operation_id,
                         const char *name, const char *properties,
-                        void *(*new_method)(const OSSL_DISPATCH *fns,
+                        void *(*new_method)(const char *name,
+                                            const OSSL_DISPATCH *fns,
                                             OSSL_PROVIDER *prov),
                         int (*up_ref_method)(void *),
                         void (*free_method)(void *))
@@ -234,3 +236,41 @@ int EVP_set_default_properties(OPENSSL_CTX *libctx, const char *propq)
     EVPerr(EVP_F_EVP_SET_DEFAULT_PROPERTIES, ERR_R_INTERNAL_ERROR);
     return 0;
 }
+
+struct do_all_data_st {
+    void (*user_fn)(void *method, void *arg);
+    void *user_arg;
+    void *(*new_method)(const char *name, const OSSL_DISPATCH *fns,
+                        OSSL_PROVIDER *prov);
+    void (*free_method)(void *);
+};
+
+static void do_one(OSSL_PROVIDER *provider, const OSSL_ALGORITHM *algo,
+                   int no_store, void *vdata)
+{
+    struct do_all_data_st *data = vdata;
+    void *method = data->new_method(algo->algorithm_name,
+                                    algo->implementation, provider);
+
+    if (method != NULL) {
+        data->user_fn(method, data->user_arg);
+        data->free_method(method);
+    }
+}
+
+void evp_generic_do_all(OPENSSL_CTX *libctx, int operation_id,
+                        void (*user_fn)(void *method, void *arg),
+                        void *user_arg,
+                        void *(*new_method)(const char *name,
+                                            const OSSL_DISPATCH *fns,
+                                            OSSL_PROVIDER *prov),
+                        void (*free_method)(void *))
+{
+    struct do_all_data_st data;
+
+    data.new_method = new_method;
+    data.free_method = free_method;
+    data.user_fn = user_fn;
+    data.user_arg = user_arg;
+    ossl_algorithm_do_all(libctx, operation_id, NULL, do_one, &data);
+}
diff --git a/crypto/evp/evp_lib.c b/crypto/evp/evp_lib.c
index 47bbb2b..0825c10 100644
--- a/crypto/evp/evp_lib.c
+++ b/crypto/evp/evp_lib.c
@@ -415,6 +415,22 @@ int EVP_CIPHER_CTX_nid(const EVP_CIPHER_CTX *ctx)
     return ctx->cipher->nid;
 }
 
+const char *EVP_CIPHER_name(const EVP_CIPHER *cipher)
+{
+    if (cipher->prov != NULL)
+        return cipher->name;
+#ifndef FIPS_MODE
+    return OBJ_nid2sn(EVP_CIPHER_nid(cipher));
+#else
+    return NULL;
+#endif
+}
+
+const OSSL_PROVIDER *EVP_CIPHER_provider(const EVP_CIPHER *cipher)
+{
+    return cipher->prov;
+}
+
 int EVP_CIPHER_mode(const EVP_CIPHER *cipher)
 {
     int ok, v = EVP_CIPHER_flags(cipher) & EVP_CIPH_MODE;
@@ -426,6 +442,22 @@ int EVP_CIPHER_mode(const EVP_CIPHER *cipher)
     return ok != 0 ? v : 0;
 }
 
+const char *EVP_MD_name(const EVP_MD *md)
+{
+    if (md->prov != NULL)
+        return md->name;
+#ifndef FIPS_MODE
+    return OBJ_nid2sn(EVP_MD_nid(md));
+#else
+    return NULL;
+#endif
+}
+
+const OSSL_PROVIDER *EVP_MD_provider(const EVP_MD *md)
+{
+    return md->prov;
+}
+
 int EVP_MD_block_size(const EVP_MD *md)
 {
     if (md == NULL) {
@@ -513,6 +545,7 @@ void EVP_MD_meth_free(EVP_MD *md)
         if (i > 0)
             return;
         ossl_provider_free(md->prov);
+        OPENSSL_free(md->name);
         CRYPTO_THREAD_lock_free(md->lock);
         OPENSSL_free(md);
     }
diff --git a/crypto/evp/evp_locl.h b/crypto/evp/evp_locl.h
index 740c159..ce46163 100644
--- a/crypto/evp/evp_locl.h
+++ b/crypto/evp/evp_locl.h
@@ -65,7 +65,7 @@ struct evp_kdf_ctx_st {
 struct evp_keymgmt_st {
     int id;                      /* libcrypto internal */
 
-    const char *name;
+    char *name;
     OSSL_PROVIDER *prov;
     CRYPTO_REF_COUNT refcnt;
     CRYPTO_RWLOCK *lock;
@@ -89,6 +89,7 @@ struct evp_keymgmt_st {
 } /* EVP_KEYMGMT */ ;
 
 struct evp_keyexch_st {
+    char *name;
     OSSL_PROVIDER *prov;
     CRYPTO_REF_COUNT refcnt;
     CRYPTO_RWLOCK *lock;
@@ -133,10 +134,18 @@ int is_partially_overlapping(const void *ptr1, const void *ptr2, int len);
 
 void *evp_generic_fetch(OPENSSL_CTX *ctx, int operation_id,
                         const char *algorithm, const char *properties,
-                        void *(*new_method)(const OSSL_DISPATCH *fns,
+                        void *(*new_method)(const char *name,
+                                            const OSSL_DISPATCH *fns,
                                             OSSL_PROVIDER *prov),
                         int (*up_ref_method)(void *),
                         void (*free_method)(void *));
+void evp_generic_do_all(OPENSSL_CTX *libctx, int operation_id,
+                        void (*user_fn)(void *method, void *arg),
+                        void *user_arg,
+                        void *(*new_method)(const char *name,
+                                            const OSSL_DISPATCH *fns,
+                                            OSSL_PROVIDER *prov),
+                        void (*free_method)(void *));
 
 /* Helper functions to avoid duplicating code */
 
diff --git a/crypto/evp/exchange.c b/crypto/evp/exchange.c
index 208bb98..d8afcbd 100644
--- a/crypto/evp/exchange.c
+++ b/crypto/evp/exchange.c
@@ -31,14 +31,19 @@ static EVP_KEYEXCH *evp_keyexch_new(OSSL_PROVIDER *prov)
     return exchange;
 }
 
-static void *evp_keyexch_from_dispatch(const OSSL_DISPATCH *fns,
+static void *evp_keyexch_from_dispatch(const char *name,
+                                       const OSSL_DISPATCH *fns,
                                        OSSL_PROVIDER *prov)
 {
     EVP_KEYEXCH *exchange = NULL;
     int fncnt = 0;
 
-    if ((exchange = evp_keyexch_new(prov)) == NULL)
+    if ((exchange = evp_keyexch_new(prov)) == NULL
+        || (exchange->name = OPENSSL_strdup(name)) == NULL) {
+        EVP_KEYEXCH_free(exchange);
+        EVPerr(0, ERR_R_MALLOC_FAILURE);
         return NULL;
+    }
 
     for (; fns->function_id != 0; fns++) {
         switch (fns->function_id) {
@@ -108,6 +113,7 @@ void EVP_KEYEXCH_free(EVP_KEYEXCH *exchange)
         if (i > 0)
             return;
         ossl_provider_free(exchange->prov);
+        OPENSSL_free(exchange->name);
         CRYPTO_THREAD_lock_free(exchange->lock);
         OPENSSL_free(exchange);
     }
diff --git a/crypto/evp/keymgmt_meth.c b/crypto/evp/keymgmt_meth.c
index 9723820..67c33eb 100644
--- a/crypto/evp/keymgmt_meth.c
+++ b/crypto/evp/keymgmt_meth.c
@@ -24,6 +24,7 @@ static void *keymgmt_new(void)
     if ((keymgmt = OPENSSL_zalloc(sizeof(*keymgmt))) == NULL
         || (keymgmt->lock = CRYPTO_THREAD_lock_new()) == NULL) {
         EVP_KEYMGMT_free(keymgmt);
+        EVPerr(0, ERR_R_MALLOC_FAILURE);
         return NULL;
     }
 
@@ -32,13 +33,16 @@ static void *keymgmt_new(void)
     return keymgmt;
 }
 
-static void *keymgmt_from_dispatch(const OSSL_DISPATCH *fns,
+static void *keymgmt_from_dispatch(const char *name, const OSSL_DISPATCH *fns,
                                    OSSL_PROVIDER *prov)
 {
     EVP_KEYMGMT *keymgmt = NULL;
 
-    if ((keymgmt = keymgmt_new()) == NULL)
+    if ((keymgmt = keymgmt_new()) == NULL
+        || (keymgmt->name = OPENSSL_strdup(name)) == NULL) {
+        EVP_KEYMGMT_free(keymgmt);
         return NULL;
+    }
 
     for (; fns->function_id != 0; fns++) {
         switch (fns->function_id) {
@@ -178,6 +182,7 @@ void EVP_KEYMGMT_free(EVP_KEYMGMT *keymgmt)
     if (ref > 0)
         return;
     ossl_provider_free(keymgmt->prov);
+    OPENSSL_free(keymgmt->name);
     CRYPTO_THREAD_lock_free(keymgmt->lock);
     OPENSSL_free(keymgmt);
 }
diff --git a/crypto/include/internal/evp_int.h b/crypto/include/internal/evp_int.h
index 50ed933..9d87898 100644
--- a/crypto/include/internal/evp_int.h
+++ b/crypto/include/internal/evp_int.h
@@ -201,6 +201,7 @@ struct evp_md_st {
 
     /* New structure members */
     /* TODO(3.0): Remove above comment when legacy has gone */
+    char *name;
     OSSL_PROVIDER *prov;
     CRYPTO_REF_COUNT refcnt;
     CRYPTO_RWLOCK *lock;
@@ -251,6 +252,7 @@ struct evp_cipher_st {
 
     /* New structure members */
     /* TODO(3.0): Remove above comment when legacy has gone */
+    char *name;
     OSSL_PROVIDER *prov;
     CRYPTO_REF_COUNT refcnt;
     CRYPTO_RWLOCK *lock;
diff --git a/crypto/provider.c b/crypto/provider.c
index 4e21bfe..8c9c6da 100644
--- a/crypto/provider.c
+++ b/crypto/provider.c
@@ -68,3 +68,8 @@ int OSSL_PROVIDER_add_builtin(OPENSSL_CTX *libctx, const char *name,
 
     return 1;
 }
+
+const char *OSSL_PROVIDER_name(const OSSL_PROVIDER *prov)
+{
+    return ossl_provider_name(prov);
+}
diff --git a/doc/internal/man3/ossl_algorithm_do_all.pod b/doc/internal/man3/ossl_algorithm_do_all.pod
new file mode 100644
index 0000000..6ef85a7
--- /dev/null
+++ b/doc/internal/man3/ossl_algorithm_do_all.pod
@@ -0,0 +1,63 @@
+=pod
+
+=head1 NAME
+
+ossl_algorithm_do_all - generic algorithm implementation iterator
+
+=head1 SYNOPSIS
+
+ void ossl_algorithm_do_all(OPENSSL_CTX *libctx, int operation_id,
+                            OSSL_PROVIDER *provider,
+                            void (*fn)(OSSL_PROVIDER *provider,
+                                       const OSSL_ALGORITHM *algo,
+                                       int no_store, void *data),
+                            void *data)
+
+=head1 DESCRIPTION
+
+ossl_algorithm_do_all() looks up every algorithm it can find, given a
+library context I<libctx>, an operation identity I<operation_id> and a
+provider I<provider>.
+I<libctx> may be NULL to signify that the default library context should
+be used.
+I<operation_id> may be zero to signify that all kinds of operations
+will be looked up.
+I<provider> may be NULL to signify that all loaded providers will be
+queried.
+
+For each implementation found, the function I<fn> is called with the
+I<provider> for the implementation, the algorithm descriptor I<algo>,
+the flag I<no_store> indicating whether the algorithm descriptor may
+be remembered or not, and the caller I<data> that was passed to
+ossl_algorithm_do_all().
+
+=head1 RETURN VALUES
+
+ossl_algorithm_do_all() doesn't return any value.
+
+=head1 NOTES
+
+The function described here are mainly useful for discovery, and
+possibly display of what has been discovered, for example an
+application that wants to display the loaded providers and what they
+may offer, but also for constructors, such as
+L<ossl_construct_method(3)>.
+
+=head1 SEE ALSO
+
+L<ossl_construct_method(3)>, L<EVP_MAC_do_all(3)>
+
+=head1 HISTORY
+
+This functionality was added to OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License").  You may not use this
+file except in compliance with the License.  You can obtain a copy in the file
+LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man1/list.pod b/doc/man1/list.pod
index 901a266..1e4d7cd 100644
--- a/doc/man1/list.pod
+++ b/doc/man1/list.pod
@@ -53,6 +53,8 @@ as input to the L<dgst(1)> or L<speed(1)> commands.
 Display a list of message digest algorithms.
 If a line is of the form C<foo =E<gt> bar> then B<foo> is an alias for the
 official algorithm name, B<bar>.
+If a line is of the form C<foo @ bar>, then B<foo> is provided by the provider
+B<bar>.
 
 =item B<-mac-algorithms>
 
@@ -70,6 +72,8 @@ to the L<dgst(1)> or L<speed(1)> commands.
 Display a list of cipher algorithms.
 If a line is of the form C<foo =E<gt> bar> then B<foo> is an alias for the
 official algorithm name, B<bar>.
+If a line is of the form C<foo @ bar>, then B<foo> is provided by the provider
+B<bar>.
 
 =item B<-public-key-algorithms>
 
diff --git a/doc/man3/EVP_DigestInit.pod b/doc/man3/EVP_DigestInit.pod
index 6f36f0a..226bc46 100644
--- a/doc/man3/EVP_DigestInit.pod
+++ b/doc/man3/EVP_DigestInit.pod
@@ -8,12 +8,16 @@ EVP_MD_CTX_copy_ex, EVP_MD_CTX_ctrl, EVP_MD_CTX_set_params, EVP_MD_CTX_get_param
 EVP_MD_CTX_set_flags, EVP_MD_CTX_clear_flags, EVP_MD_CTX_test_flags,
 EVP_Digest, EVP_DigestInit_ex, EVP_DigestInit, EVP_DigestUpdate,
 EVP_DigestFinal_ex, EVP_DigestFinalXOF, EVP_DigestFinal,
+EVP_MD_name, EVP_MD_provider,
 EVP_MD_type, EVP_MD_pkey_type, EVP_MD_size, EVP_MD_block_size, EVP_MD_flags,
+EVP_MD_CTX_name,
 EVP_MD_CTX_md, EVP_MD_CTX_type, EVP_MD_CTX_size, EVP_MD_CTX_block_size,
 EVP_MD_CTX_md_data, EVP_MD_CTX_update_fn, EVP_MD_CTX_set_update_fn,
 EVP_md_null,
 EVP_get_digestbyname, EVP_get_digestbynid, EVP_get_digestbyobj,
-EVP_MD_CTX_pkey_ctx, EVP_MD_CTX_set_pkey_ctx - EVP digest routines
+EVP_MD_CTX_pkey_ctx, EVP_MD_CTX_set_pkey_ctx,
+EVP_MD_do_all_ex
+- EVP digest routines
 
 =head1 SYNOPSIS
 
@@ -45,6 +49,8 @@ EVP_MD_CTX_pkey_ctx, EVP_MD_CTX_set_pkey_ctx - EVP digest routines
 
  int EVP_MD_CTX_copy(EVP_MD_CTX *out, EVP_MD_CTX *in);
 
+ const char *EVP_MD_name(const EVP_MD *md);
+ const OSSL_PROVIDER *EVP_MD_provider(const EVP_MD *md);
  int EVP_MD_type(const EVP_MD *md);
  int EVP_MD_pkey_type(const EVP_MD *md);
  int EVP_MD_size(const EVP_MD *md);
@@ -52,6 +58,7 @@ EVP_MD_CTX_pkey_ctx, EVP_MD_CTX_set_pkey_ctx - EVP digest routines
  unsigned long EVP_MD_flags(const EVP_MD *md);
 
  const EVP_MD *EVP_MD_CTX_md(const EVP_MD_CTX *ctx);
+ const char *EVP_MD_CTX_name(const EVP_MD_CTX *ctx);
  int EVP_MD_CTX_size(const EVP_MD *ctx);
  int EVP_MD_CTX_block_size(const EVP_MD *ctx);
  int EVP_MD_CTX_type(const EVP_MD *ctx);
@@ -71,6 +78,10 @@ EVP_MD_CTX_pkey_ctx, EVP_MD_CTX_set_pkey_ctx - EVP digest routines
  EVP_PKEY_CTX *EVP_MD_CTX_pkey_ctx(const EVP_MD_CTX *ctx);
  void EVP_MD_CTX_set_pkey_ctx(EVP_MD_CTX *ctx, EVP_PKEY_CTX *pctx);
 
+ void EVP_MD_do_all_ex(OPENSSL_CTX *libctx,
+                       void (*fn)(EVP_MD *mac, void *arg),
+                       void *arg);
+
 =head1 DESCRIPTION
 
 The EVP digest routines are a high level interface to message digests,
@@ -184,6 +195,16 @@ automatically cleaned up.
 Similar to EVP_MD_CTX_copy_ex() except the destination B<out> does not have to
 be initialized.
 
+=item EVP_MD_name(),
+EVP_MD_CTX_name()
+
+Return the name of the given message digest.
+
+=item EVP_MD_provider()
+
+Returns an B<OSSL_PROVIDER> pointer to the provider that implements the given
+B<EVP_MD>.
+
 =item EVP_MD_size(),
 EVP_MD_CTX_size()
 
@@ -266,6 +287,13 @@ by the caller. A NULL B<pctx> pointer is also allowed to clear the B<EVP_PKEY_CT
 assigned to B<ctx>. In such case, freeing the cleared B<EVP_PKEY_CTX> or not
 depends on how the B<EVP_PKEY_CTX> is created.
 
+=item EVP_MD_do_all_ex()
+
+Traverses all messages digests implemented by all activated providers
+in the given library context I<libctx>, and for each of the implementations,
+calls the given function I<fn> with the implementation method and the given
+I<arg> as argument.
+
 =back
 
 =head1 PARAMS
@@ -433,9 +461,9 @@ implementations of digests to be specified.
 If digest contexts are not cleaned up after use,
 memory leaks will occur.
 
-EVP_MD_CTX_size(), EVP_MD_CTX_block_size(), EVP_MD_CTX_type(),
-EVP_get_digestbynid() and EVP_get_digestbyobj() are defined as
-macros.
+EVP_MD_CTX_name(), EVP_MD_CTX_size(), EVP_MD_CTX_block_size(),
+EVP_MD_CTX_type(), EVP_get_digestbynid() and EVP_get_digestbyobj() are defined
+as macros.
 
 EVP_MD_CTX_ctrl() sends commands to message digests for additional configuration
 or control.
diff --git a/doc/man3/EVP_EncryptInit.pod b/doc/man3/EVP_EncryptInit.pod
index e4fb0c4..43ed7f9 100644
--- a/doc/man3/EVP_EncryptInit.pod
+++ b/doc/man3/EVP_EncryptInit.pod
@@ -26,6 +26,8 @@ EVP_CipherFinal,
 EVP_get_cipherbyname,
 EVP_get_cipherbynid,
 EVP_get_cipherbyobj,
+EVP_CIPHER_name,
+EVP_CIPHER_provider,
 EVP_CIPHER_nid,
 EVP_CIPHER_block_size,
 EVP_CIPHER_key_length,
@@ -34,6 +36,7 @@ EVP_CIPHER_flags,
 EVP_CIPHER_mode,
 EVP_CIPHER_type,
 EVP_CIPHER_CTX_cipher,
+EVP_CIPHER_CTX_name,
 EVP_CIPHER_CTX_nid,
 EVP_CIPHER_CTX_block_size,
 EVP_CIPHER_CTX_key_length,
@@ -46,7 +49,8 @@ EVP_CIPHER_CTX_mode,
 EVP_CIPHER_param_to_asn1,
 EVP_CIPHER_asn1_to_param,
 EVP_CIPHER_CTX_set_padding,
-EVP_enc_null
+EVP_enc_null,
+EVP_CIPHER_do_all_ex
 - EVP cipher routines
 
 =head1 SYNOPSIS
@@ -101,6 +105,8 @@ EVP_enc_null
  const EVP_CIPHER *EVP_get_cipherbyobj(const ASN1_OBJECT *a);
 
  int EVP_CIPHER_nid(const EVP_CIPHER *e);
+ const char *EVP_CIPHER_name(const EVP_CIPHER *cipher);
+ const OSSL_PROVIDER *EVP_CIPHER_provider(const EVP_CIPHER *cipher);
  int EVP_CIPHER_block_size(const EVP_CIPHER *e);
  int EVP_CIPHER_key_length(const EVP_CIPHER *e);
  int EVP_CIPHER_iv_length(const EVP_CIPHER *e);
@@ -110,6 +116,7 @@ EVP_enc_null
 
  const EVP_CIPHER *EVP_CIPHER_CTX_cipher(const EVP_CIPHER_CTX *ctx);
  int EVP_CIPHER_CTX_nid(const EVP_CIPHER_CTX *ctx);
+ const char *EVP_CIPHER_CTX_name(const EVP_CIPHER_CTX *ctx);
  int EVP_CIPHER_CTX_block_size(const EVP_CIPHER_CTX *ctx);
  int EVP_CIPHER_CTX_key_length(const EVP_CIPHER_CTX *ctx);
  int EVP_CIPHER_CTX_iv_length(const EVP_CIPHER_CTX *ctx);
@@ -121,6 +128,10 @@ EVP_enc_null
  int EVP_CIPHER_param_to_asn1(EVP_CIPHER_CTX *c, ASN1_TYPE *type);
  int EVP_CIPHER_asn1_to_param(EVP_CIPHER_CTX *c, ASN1_TYPE *type);
 
+ void EVP_CIPHER_do_all_ex(OPENSSL_CTX *libctx,
+                           void (*fn)(EVP_CIPHER *cipher, void *arg),
+                           void *arg);
+
 =head1 DESCRIPTION
 
 The EVP cipher routines are a high level interface to certain
@@ -255,6 +266,12 @@ IDENTIFIER as such it ignores the cipher parameters and 40 bit RC2 and
 identifier or does not have ASN1 support this function will return
 B<NID_undef>.
 
+EVP_CIPHER_name() and EVP_CIPHER_CTX_name() return the name of the passed
+cipher or context.
+
+EVP_CIPHER_provider() returns an B<OSSL_PROVIDER> pointer to the provider
+that implements the given B<EVP_CIPHER>.
+
 EVP_CIPHER_CTX_cipher() returns the B<EVP_CIPHER> structure when passed
 an B<EVP_CIPHER_CTX> structure.
 
@@ -290,6 +307,11 @@ based on the cipher context. The EVP_CIPHER can provide its own random key
 generation routine to support keys of a specific form. B<Key> must point to a
 buffer at least as big as the value returned by EVP_CIPHER_CTX_key_length().
 
+EVP_CIPHER_do_all_ex() traverses all ciphers implemented by all activated
+providers in the given library context I<libctx>, and for each of the
+implementations, calls the given function I<fn> with the implementation method
+and the given I<arg> as argument.
+
 =head1 RETURN VALUES
 
 EVP_CIPHER_fetch() returns a pointer to a B<EVP_CIPHER> for success
diff --git a/doc/man3/OSSL_PROVIDER.pod b/doc/man3/OSSL_PROVIDER.pod
index 9fe2e18..fec6706 100644
--- a/doc/man3/OSSL_PROVIDER.pod
+++ b/doc/man3/OSSL_PROVIDER.pod
@@ -4,7 +4,7 @@
 
 OSSL_PROVIDER, OSSL_PROVIDER_load, OSSL_PROVIDER_unload,
 OSSL_PROVIDER_get_param_types, OSSL_PROVIDER_get_params,
-OSSL_PROVIDER_add_builtin - provider routines
+OSSL_PROVIDER_add_builtin, OSSL_PROVIDER_name - provider routines
 
 =head1 SYNOPSIS
 
@@ -21,6 +21,8 @@ OSSL_PROVIDER_add_builtin - provider routines
  int OSSL_PROVIDER_add_builtin(OPENSSL_CTX *, const char *name,
                                ossl_provider_init_fn *init_fn);
 
+ const char *OSSL_PROVIDER_name(const OSSL_PROVIDER *prov);
+
 =head1 DESCRIPTION
 
 B<OSSL_PROVIDER> is a type that holds internal information about
@@ -59,6 +61,8 @@ The caller must prepare the B<OSSL_PARAM> array before calling this
 function, and the variables acting as buffers for this parameter array
 should be filled with data when it returns successfully.
 
+OSSL_PROVIDER_name() returns the name of the given provider.
+
 =head1 RETURN VALUES
 
 OSSL_PROVIDER_add() returns 1 on success, or 0 on error.
diff --git a/include/internal/core.h b/include/internal/core.h
index 3f0cdfa..bd2f9a0 100644
--- a/include/internal/core.h
+++ b/include/internal/core.h
@@ -51,4 +51,11 @@ void *ossl_method_construct(OPENSSL_CTX *ctx, int operation_id,
                             int force_cache,
                             OSSL_METHOD_CONSTRUCT_METHOD *mcm, void *mcm_data);
 
+void ossl_algorithm_do_all(OPENSSL_CTX *libctx, int operation_id,
+                           OSSL_PROVIDER *provider,
+                           void (*fn)(OSSL_PROVIDER *provider,
+                                      const OSSL_ALGORITHM *algo,
+                                      int no_store, void *data),
+                           void *data);
+
 #endif
diff --git a/include/openssl/core_numbers.h b/include/openssl/core_numbers.h
index f45b8f1..905094d 100644
--- a/include/openssl/core_numbers.h
+++ b/include/openssl/core_numbers.h
@@ -324,6 +324,9 @@ OSSL_CORE_MAKE_FUNC(void *, OP_keyexch_dupctx, (void *ctx))
 OSSL_CORE_MAKE_FUNC(int, OP_keyexch_set_params, (void *ctx,
                                                  OSSL_PARAM params[]))
 
+/* Highest known operation number */
+# define OSSL_OP__HIGHEST                            3
+
 # ifdef __cplusplus
 }
 # endif
diff --git a/include/openssl/evp.h b/include/openssl/evp.h
index d014a2e..24ad23f 100644
--- a/include/openssl/evp.h
+++ b/include/openssl/evp.h
@@ -449,7 +449,8 @@ typedef int (EVP_PBE_KEYGEN) (EVP_CIPHER_CTX *ctx, const char *pass,
 
 int EVP_MD_type(const EVP_MD *md);
 # define EVP_MD_nid(e)                   EVP_MD_type(e)
-# define EVP_MD_name(e)                  OBJ_nid2sn(EVP_MD_nid(e))
+const char *EVP_MD_name(const EVP_MD *md);
+const OSSL_PROVIDER *EVP_MD_provider(const EVP_MD *md);
 int EVP_MD_pkey_type(const EVP_MD *md);
 int EVP_MD_size(const EVP_MD *md);
 int EVP_MD_block_size(const EVP_MD *md);
@@ -461,6 +462,7 @@ int (*EVP_MD_CTX_update_fn(EVP_MD_CTX *ctx))(EVP_MD_CTX *ctx,
 void EVP_MD_CTX_set_update_fn(EVP_MD_CTX *ctx,
                               int (*update) (EVP_MD_CTX *ctx,
                                              const void *data, size_t count));
+# define EVP_MD_CTX_name(e)              EVP_MD_name(EVP_MD_CTX_md(e))
 # define EVP_MD_CTX_size(e)              EVP_MD_size(EVP_MD_CTX_md(e))
 # define EVP_MD_CTX_block_size(e)        EVP_MD_block_size(EVP_MD_CTX_md(e))
 # define EVP_MD_CTX_type(e)              EVP_MD_type(EVP_MD_CTX_md(e))
@@ -469,7 +471,8 @@ void EVP_MD_CTX_set_pkey_ctx(EVP_MD_CTX *ctx, EVP_PKEY_CTX *pctx);
 void *EVP_MD_CTX_md_data(const EVP_MD_CTX *ctx);
 
 int EVP_CIPHER_nid(const EVP_CIPHER *cipher);
-# define EVP_CIPHER_name(e)              OBJ_nid2sn(EVP_CIPHER_nid(e))
+const char *EVP_CIPHER_name(const EVP_CIPHER *cipher);
+const OSSL_PROVIDER *EVP_CIPHER_provider(const EVP_CIPHER *cipher);
 int EVP_CIPHER_block_size(const EVP_CIPHER *cipher);
 int EVP_CIPHER_impl_ctx_size(const EVP_CIPHER *cipher);
 int EVP_CIPHER_key_length(const EVP_CIPHER *cipher);
@@ -496,6 +499,7 @@ void *EVP_CIPHER_CTX_get_app_data(const EVP_CIPHER_CTX *ctx);
 void EVP_CIPHER_CTX_set_app_data(EVP_CIPHER_CTX *ctx, void *data);
 void *EVP_CIPHER_CTX_get_cipher_data(const EVP_CIPHER_CTX *ctx);
 void *EVP_CIPHER_CTX_set_cipher_data(EVP_CIPHER_CTX *ctx, void *cipher_data);
+# define EVP_CIPHER_CTX_name(c)         EVP_CIPHER_name(EVP_CIPHER_CTX_cipher(c))
 # define EVP_CIPHER_CTX_type(c)         EVP_CIPHER_type(EVP_CIPHER_CTX_cipher(c))
 # if !OPENSSL_API_1_1_0
 #  define EVP_CIPHER_CTX_flags(c)       EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(c))
@@ -991,6 +995,9 @@ void EVP_CIPHER_do_all(void (*fn) (const EVP_CIPHER *ciph,
 void EVP_CIPHER_do_all_sorted(void (*fn)
                                (const EVP_CIPHER *ciph, const char *from,
                                 const char *to, void *x), void *arg);
+void EVP_CIPHER_do_all_ex(OPENSSL_CTX *libctx,
+                          void (*fn)(EVP_CIPHER *cipher, void *arg),
+                          void *arg);
 
 void EVP_MD_do_all(void (*fn) (const EVP_MD *ciph,
                                const char *from, const char *to, void *x),
@@ -998,6 +1005,9 @@ void EVP_MD_do_all(void (*fn) (const EVP_MD *ciph,
 void EVP_MD_do_all_sorted(void (*fn)
                            (const EVP_MD *ciph, const char *from,
                             const char *to, void *x), void *arg);
+void EVP_MD_do_all_ex(OPENSSL_CTX *libctx,
+                      void (*fn)(EVP_MD *md, void *arg),
+                      void *arg);
 
 /* MAC stuff */
 
diff --git a/include/openssl/provider.h b/include/openssl/provider.h
index c7f6664..722e83b 100644
--- a/include/openssl/provider.h
+++ b/include/openssl/provider.h
@@ -27,6 +27,9 @@ int OSSL_PROVIDER_get_params(const OSSL_PROVIDER *prov, OSSL_PARAM params[]);
 int OSSL_PROVIDER_add_builtin(OPENSSL_CTX *, const char *name,
                               OSSL_provider_init_fn *init_fn);
 
+/* Information */
+const char *OSSL_PROVIDER_name(const OSSL_PROVIDER *prov);
+
 # ifdef __cplusplus
 }
 # endif
diff --git a/util/libcrypto.num b/util/libcrypto.num
index e18fdca..b0a7f81 100644
--- a/util/libcrypto.num
+++ b/util/libcrypto.num
@@ -4691,3 +4691,10 @@ EVP_KEYMGMT_free                        4796	3_0_0	EXIST::FUNCTION:
 EVP_KEYMGMT_provider                    4797	3_0_0	EXIST::FUNCTION:
 X509_PUBKEY_dup                         4798	3_0_0	EXIST::FUNCTION:
 ERR_put_func_error                      4799	3_0_0	EXIST::FUNCTION:
+EVP_MD_name                             4800	3_0_0	EXIST::FUNCTION:
+EVP_CIPHER_name                         4801	3_0_0	EXIST::FUNCTION:
+EVP_MD_provider                         4802	3_0_0	EXIST::FUNCTION:
+EVP_CIPHER_provider                     4803	3_0_0	EXIST::FUNCTION:
+OSSL_PROVIDER_name                      4804	3_0_0	EXIST::FUNCTION:
+EVP_CIPHER_do_all_ex                    4805	3_0_0	EXIST::FUNCTION:
+EVP_MD_do_all_ex                        4806	3_0_0	EXIST::FUNCTION:
diff --git a/util/private.num b/util/private.num
index 3307e3e..1e76dfb 100644
--- a/util/private.num
+++ b/util/private.num
@@ -201,6 +201,7 @@ EVP_DigestVerifyUpdate                  define
 EVP_KDF_name                            define
 EVP_MAC_name                            define
 EVP_MD_CTX_block_size                   define
+EVP_MD_CTX_name                         define
 EVP_MD_CTX_size                         define
 EVP_MD_CTX_type                         define
 EVP_OpenUpdate                          define


More information about the openssl-commits mailing list