[openssl] master update

Dr. Paul Dale pauli at openssl.org
Sat Sep 7 06:07:27 UTC 2019


The branch master has been updated
       via  e97bab6929bbbc5b8364b25ca2ef4fcb02dd6e2a (commit)
       via  a1de4680fbf53b0feffd27baca3c6b4caf0c6c45 (commit)
       via  0f0db4dc2520777b889968c93e054693c5c58fdc (commit)
       via  7e149b39288fdfc8d57c881536b272fae78df038 (commit)
       via  e957226a0cf2150003b5b2d0b46ab9a89011f66f (commit)
       via  86f17ed64cb881a97801405906f4da7041a6edf8 (commit)
       via  cb74317b4f525feca9129944f82e74e23b2e381f (commit)
       via  c69561de00a032f85ec92d30c1e0bfa761b81dfd (commit)
       via  96d7e2733ef66e364f89aa394a6bdd49df48f2ae (commit)
       via  103d8b0be434c293c661861bda505f35f04d288f (commit)
       via  76497acf522578827f390891cf45c87280423d32 (commit)
       via  1dcc7ee6cf816e5fba8b99d278829031d71ee9df (commit)
       via  2f17cc493cfaa5c77a77d4f174dd2403188c41da (commit)
      from  4fe2ee3a449a8ca2886584e221f34ff0ef5de119 (commit)


- Log -----------------------------------------------------------------
commit e97bab6929bbbc5b8364b25ca2ef4fcb02dd6e2a
Author: Pauli <paul.dale at oracle.com>
Date:   Sat Sep 7 10:50:46 2019 +1000

    Use common digest getter for X942 KDF
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/9770)

commit a1de4680fbf53b0feffd27baca3c6b4caf0c6c45
Author: Pauli <paul.dale at oracle.com>
Date:   Sat Sep 7 10:50:14 2019 +1000

    Use common digest getter for SSH KDF
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/9770)

commit 0f0db4dc2520777b889968c93e054693c5c58fdc
Author: Pauli <paul.dale at oracle.com>
Date:   Sat Sep 7 10:49:53 2019 +1000

    Use common digest getter for TLS1 PRF
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/9770)

commit 7e149b39288fdfc8d57c881536b272fae78df038
Author: Pauli <paul.dale at oracle.com>
Date:   Sat Sep 7 10:49:36 2019 +1000

    Use common digest getter for single step KDF
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/9770)

commit e957226a0cf2150003b5b2d0b46ab9a89011f66f
Author: Pauli <paul.dale at oracle.com>
Date:   Sat Sep 7 10:49:18 2019 +1000

    Use common digest getter for PBKDF2
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/9770)

commit 86f17ed64cb881a97801405906f4da7041a6edf8
Author: Pauli <paul.dale at oracle.com>
Date:   Sat Sep 7 10:48:56 2019 +1000

    Use common digest getter for HKDF
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/9770)

commit cb74317b4f525feca9129944f82e74e23b2e381f
Author: Pauli <paul.dale at oracle.com>
Date:   Sat Sep 7 10:48:07 2019 +1000

    Use common define for properties, engine, cipher and digest params
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/9770)

commit c69561de00a032f85ec92d30c1e0bfa761b81dfd
Author: Pauli <paul.dale at oracle.com>
Date:   Sat Sep 7 10:47:37 2019 +1000

    Add 'engine' param to KDFs
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/9770)

commit 96d7e2733ef66e364f89aa394a6bdd49df48f2ae
Author: Pauli <paul.dale at oracle.com>
Date:   Thu Sep 5 13:55:04 2019 +1000

    KMAC using common digest get code
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/9770)

commit 103d8b0be434c293c661861bda505f35f04d288f
Author: Pauli <paul.dale at oracle.com>
Date:   Thu Sep 5 13:54:53 2019 +1000

    HMAC using common digest get code
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/9770)

commit 76497acf522578827f390891cf45c87280423d32
Author: Pauli <paul.dale at oracle.com>
Date:   Thu Sep 5 14:24:44 2019 +1000

    GMAC using common cipher get code
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/9770)

commit 1dcc7ee6cf816e5fba8b99d278829031d71ee9df
Author: Pauli <paul.dale at oracle.com>
Date:   Thu Sep 5 14:15:02 2019 +1000

    CMAC using common cipher get code
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/9770)

commit 2f17cc493cfaa5c77a77d4f174dd2403188c41da
Author: Pauli <paul.dale at oracle.com>
Date:   Thu Sep 5 13:53:20 2019 +1000

    Unify the digest getting code inside providers.
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/9770)

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

Summary of changes:
 doc/man3/EVP_KDF.pod                               |  20 +--
 include/openssl/core_names.h                       |  23 +++-
 providers/common/build.info                        |   5 +-
 providers/common/include/internal/provider_util.h  |  79 +++++++++++
 providers/common/include/internal/providercommon.h |   1 +
 providers/common/kdfs/hkdf.c                       |  44 ++----
 providers/common/kdfs/pbkdf2.c                     |  41 ++----
 providers/common/kdfs/sskdf.c                      |  50 +++----
 providers/common/kdfs/tls1_prf.c                   |  68 ++++------
 providers/common/macs/cmac_prov.c                  |  97 ++-----------
 providers/common/macs/gmac_prov.c                  |  92 +++----------
 providers/common/macs/hmac_prov.c                  |  98 +++----------
 providers/common/macs/kmac_prov.c                  |  80 +++++------
 providers/common/provider_util.c                   | 151 +++++++++++++++++++++
 providers/default/kdfs/sshkdf.c                    |  35 ++---
 providers/default/kdfs/x942kdf.c                   |  40 ++----
 16 files changed, 441 insertions(+), 483 deletions(-)
 create mode 100644 providers/common/include/internal/provider_util.h
 create mode 100644 providers/common/provider_util.c

diff --git a/doc/man3/EVP_KDF.pod b/doc/man3/EVP_KDF.pod
index fc09d5fad8..2069e7f0ee 100644
--- a/doc/man3/EVP_KDF.pod
+++ b/doc/man3/EVP_KDF.pod
@@ -166,18 +166,22 @@ The default value, if any, is implementation dependent.
 
 =item B<OSSL_KDF_PARAM_PROPERTIES> ("properties") <UTF8 string>
 
-Some KDF implementations use other cryptographic algorithms, this parameter
-sets what property query will be used to fetch the implementation.
-
 =item B<OSSL_KDF_PARAM_MAC> ("mac") <UTF8 string>
 
-Some KDF implementations use a MAC as an underlying computation
-algorithm, this parameter sets what the MAC algorithm should be.
-
 =item B<OSSL_KDF_PARAM_DIGEST> ("digest") <UTF8 string>
 
-For MAC implementations that use a message digest as an underlying computation
-algorithm, this parameter sets what the digest algorithm should be.
+=item B<OSSL_MAC_PARAM_ENGINE> ("engine") <utf8string>
+
+For KDF implementations that use an underlying computation MAC or
+digest, these parameters set what the algorithm should be, and the
+engine that implements the algorithm or the properties to fetch it
+by if needed.
+
+The value is always the name of the intended engine, algorithm,
+or the properties.
+
+Note that not all algorithms may support all possible underlying
+implementations.
 
 =item B<OSSL_KDF_PARAM_KEY> ("key") <octet string>
 
diff --git a/include/openssl/core_names.h b/include/openssl/core_names.h
index 1d8857295c..b78a0978fd 100644
--- a/include/openssl/core_names.h
+++ b/include/openssl/core_names.h
@@ -40,6 +40,16 @@ extern "C" {
  */
 #define OSSL_PROV_PARAM_MODULE_FILENAME "module-filename"
 
+/*
+ * Algorithm parameters
+ * If "engine" or "properties" are specified, they should always be paired
+ * with the algorithm type.
+ */
+#define OSSL_ALG_PARAM_DIGEST       "digest"    /* utf8_string */
+#define OSSL_ALG_PARAM_CIPHER       "cipher"    /* utf8_string */
+#define OSSL_ALG_PARAM_ENGINE       "engine"    /* utf8_string */
+#define OSSL_ALG_PARAM_PROPERTIES   "properties"/* utf8_string */
+
 /* cipher parameters */
 #define OSSL_CIPHER_PARAM_PADDING   "padding"    /* uint */
 #define OSSL_CIPHER_PARAM_MODE      "mode"       /* uint */
@@ -80,10 +90,10 @@ extern "C" {
  * If "engine" or "properties" are specified, they should always be paired
  * with "cipher" or "digest".
  */
-#define OSSL_MAC_PARAM_CIPHER       "cipher"     /* utf8 string */
-#define OSSL_MAC_PARAM_DIGEST       "digest"     /* utf8 string */
-#define OSSL_MAC_PARAM_ENGINE       "engine"     /* utf8 string */
-#define OSSL_MAC_PARAM_PROPERTIES   "properties" /* utf8 string */
+#define OSSL_MAC_PARAM_CIPHER       OSSL_ALG_PARAM_CIPHER     /* utf8 string */
+#define OSSL_MAC_PARAM_DIGEST       OSSL_ALG_PARAM_DIGEST     /* utf8 string */
+#define OSSL_MAC_PARAM_ENGINE       OSSL_ALG_PARAM_ENGINE     /* utf8 string */
+#define OSSL_MAC_PARAM_PROPERTIES   OSSL_ALG_PARAM_PROPERTIES /* utf8 string */
 #define OSSL_MAC_PARAM_SIZE         "size"       /* size_t */
 
 /* Known MAC names (not a complete list) */
@@ -97,10 +107,11 @@ extern "C" {
 #define OSSL_KDF_PARAM_KEY          "key"       /* octet string */
 #define OSSL_KDF_PARAM_SALT         "salt"      /* octet string */
 #define OSSL_KDF_PARAM_PASSWORD     "pass"      /* octet string */
-#define OSSL_KDF_PARAM_DIGEST       "digest"    /* utf8 string */
+#define OSSL_KDF_PARAM_DIGEST       OSSL_ALG_PARAM_DIGEST    /* utf8 string */
 #define OSSL_KDF_PARAM_MAC          "mac"       /* utf8 string */
 #define OSSL_KDF_PARAM_MAC_SIZE     "maclen"    /* size_t */
-#define OSSL_KDF_PARAM_PROPERTIES   "properties" /* utf8 string */
+#define OSSL_KDF_PARAM_ENGINE       OSSL_ALG_PARAM_ENGINE     /* utf8 string */
+#define OSSL_KDF_PARAM_PROPERTIES   OSSL_ALG_PARAM_PROPERTIES /* utf8 string */
 #define OSSL_KDF_PARAM_ITER         "iter"      /* unsigned int */
 #define OSSL_KDF_PARAM_MODE         "mode"      /* utf8 string or int */
 #define OSSL_KDF_PARAM_PKCS5        "pkcs5"     /* int */
diff --git a/providers/common/build.info b/providers/common/build.info
index 4d87b15e8d..b098ca6958 100644
--- a/providers/common/build.info
+++ b/providers/common/build.info
@@ -1,4 +1,5 @@
 SUBDIRS=digests ciphers macs kdfs exchange keymgmt
+$COMMON=provider_util.c
 
-SOURCE[../../libcrypto]=\
-        provider_err.c provlib.c
+SOURCE[../../libcrypto]=$COMMON provider_err.c provlib.c
+SOURCE[../fips]=$COMMON
diff --git a/providers/common/include/internal/provider_util.h b/providers/common/include/internal/provider_util.h
new file mode 100644
index 0000000000..c25c65886e
--- /dev/null
+++ b/providers/common/include/internal/provider_util.h
@@ -0,0 +1,79 @@
+/*
+ * 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/provider.h>
+#include <openssl/engine.h>
+
+typedef struct {
+    /*
+     * References to the underlying cipher implementation.  |cipher| caches
+     * the cipher, always.  |alloc_cipher| only holds a reference to an
+     * explicitly fetched cipher.
+     */
+    const EVP_CIPHER *cipher;   /* cipher */
+    EVP_CIPHER *alloc_cipher;   /* fetched cipher */
+
+    /* Conditions for legacy EVP_CIPHER uses */
+    ENGINE *engine;             /* cipher engine */
+} PROV_CIPHER;
+
+typedef struct {
+    /*
+     * References to the underlying digest implementation.  |md| caches
+     * the digest, always.  |alloc_md| only holds a reference to an explicitly
+     * fetched digest.
+     */
+    const EVP_MD *md;           /* digest */
+    EVP_MD *alloc_md;           /* fetched digest */
+
+    /* Conditions for legacy EVP_MD uses */
+    ENGINE *engine;             /* digest engine */
+} PROV_DIGEST;
+
+/* Cipher functions */
+/*
+ * Load a cipher from the specified parameters with the specified context.
+ * The params "properties", "engine" and "cipher" are used to determine the
+ * implementation used.  If a provider cannot be found, it falls back to trying
+ * non-provider based implementations.
+ */
+int ossl_prov_cipher_load_from_params(PROV_CIPHER *pd,
+                                      const OSSL_PARAM params[],
+                                      OPENSSL_CTX *ctx);
+
+/* Reset the PROV_CIPHER fields and free any allocated cipher reference */
+void ossl_prov_cipher_reset(PROV_CIPHER *pd);
+
+/* Clone a PROV_CIPHER structure into a second */
+int ossl_prov_cipher_copy(PROV_CIPHER *dst, const PROV_CIPHER *src);
+
+/* Query the cipher and associated engine (if any) */
+const EVP_CIPHER *ossl_prov_cipher_cipher(const PROV_CIPHER *pd);
+ENGINE *ossl_prov_cipher_engine(const PROV_CIPHER *pd);
+
+/* Digest functions */
+/*
+ * Load a digest from the specified parameters with the specified context.
+ * The params "properties", "engine" and "digest" are used to determine the
+ * implementation used.  If a provider cannot be found, it falls back to trying
+ * non-provider based implementations.
+ */
+int ossl_prov_digest_load_from_params(PROV_DIGEST *pd,
+                                      const OSSL_PARAM params[],
+                                      OPENSSL_CTX *ctx);
+
+/* Reset the PROV_DIGEST fields and free any allocated digest reference */
+void ossl_prov_digest_reset(PROV_DIGEST *pd);
+
+/* Clone a PROV_DIGEST structure into a second */
+int ossl_prov_digest_copy(PROV_DIGEST *dst, const PROV_DIGEST *src);
+
+/* Query the digest and associated engine (if any) */
+const EVP_MD *ossl_prov_digest_md(const PROV_DIGEST *pd);
+ENGINE *ossl_prov_digest_engine(const PROV_DIGEST *pd);
diff --git a/providers/common/include/internal/providercommon.h b/providers/common/include/internal/providercommon.h
index d54fafa971..569c08c0b1 100644
--- a/providers/common/include/internal/providercommon.h
+++ b/providers/common/include/internal/providercommon.h
@@ -12,3 +12,4 @@
 const OSSL_PROVIDER *FIPS_get_provider(OPENSSL_CTX *ctx);
 
 const char *ossl_prov_util_nid_to_name(int nid);
+
diff --git a/providers/common/kdfs/hkdf.c b/providers/common/kdfs/hkdf.c
index 30bda90f69..ac5cc34a21 100644
--- a/providers/common/kdfs/hkdf.c
+++ b/providers/common/kdfs/hkdf.c
@@ -20,6 +20,7 @@
 #include "internal/provider_ctx.h"
 #include "internal/providercommonerr.h"
 #include "internal/provider_algs.h"
+#include "internal/provider_util.h"
 #include "e_os.h"
 
 #define HKDF_MAXBUF 1024
@@ -50,7 +51,7 @@ static int HKDF_Expand(const EVP_MD *evp_md,
 typedef struct {
     void *provctx;
     int mode;
-    EVP_MD *md;
+    PROV_DIGEST digest;
     unsigned char *salt;
     size_t salt_len;
     unsigned char *key;
@@ -82,7 +83,7 @@ static void kdf_hkdf_reset(void *vctx)
 {
     KDF_HKDF *ctx = (KDF_HKDF *)vctx;
 
-    EVP_MD_meth_free(ctx->md);
+    ossl_prov_digest_reset(&ctx->digest);
     OPENSSL_free(ctx->salt);
     OPENSSL_clear_free(ctx->key, ctx->key_len);
     OPENSSL_cleanse(ctx->info, ctx->info_len);
@@ -92,15 +93,16 @@ static void kdf_hkdf_reset(void *vctx)
 static size_t kdf_hkdf_size(KDF_HKDF *ctx)
 {
     int sz;
+    const EVP_MD *md = ossl_prov_digest_md(&ctx->digest);
 
     if (ctx->mode != EVP_KDF_HKDF_MODE_EXTRACT_ONLY)
         return SIZE_MAX;
 
-    if (ctx->md == NULL) {
+    if (md == NULL) {
         ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_MESSAGE_DIGEST);
         return 0;
     }
-    sz = EVP_MD_size(ctx->md);
+    sz = EVP_MD_size(md);
     if (sz < 0)
         return 0;
 
@@ -110,8 +112,9 @@ static size_t kdf_hkdf_size(KDF_HKDF *ctx)
 static int kdf_hkdf_derive(void *vctx, unsigned char *key, size_t keylen)
 {
     KDF_HKDF *ctx = (KDF_HKDF *)vctx;
+    const EVP_MD *md = ossl_prov_digest_md(&ctx->digest);
 
-    if (ctx->md == NULL) {
+    if (md == NULL) {
         ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_MESSAGE_DIGEST);
         return 0;
     }
@@ -122,16 +125,16 @@ static int kdf_hkdf_derive(void *vctx, unsigned char *key, size_t keylen)
 
     switch (ctx->mode) {
     case EVP_KDF_HKDF_MODE_EXTRACT_AND_EXPAND:
-        return HKDF(ctx->md, ctx->salt, ctx->salt_len, ctx->key,
+        return HKDF(md, ctx->salt, ctx->salt_len, ctx->key,
                     ctx->key_len, ctx->info, ctx->info_len, key,
                     keylen);
 
     case EVP_KDF_HKDF_MODE_EXTRACT_ONLY:
-        return HKDF_Extract(ctx->md, ctx->salt, ctx->salt_len, ctx->key,
+        return HKDF_Extract(md, ctx->salt, ctx->salt_len, ctx->key,
                             ctx->key_len, key, keylen);
 
     case EVP_KDF_HKDF_MODE_EXPAND_ONLY:
-        return HKDF_Expand(ctx->md, ctx->key, ctx->key_len, ctx->info,
+        return HKDF_Expand(md, ctx->key, ctx->key_len, ctx->info,
                            ctx->info_len, key, keylen);
 
     default:
@@ -143,30 +146,11 @@ static int kdf_hkdf_set_ctx_params(void *vctx, const OSSL_PARAM params[])
 {
     const OSSL_PARAM *p;
     KDF_HKDF *ctx = vctx;
-    EVP_MD *md;
+    OPENSSL_CTX *provctx = PROV_LIBRARY_CONTEXT_OF(ctx->provctx);
     int n;
-    const char *properties = NULL;
 
-    /* Grab search properties, this should be before the digest lookup */
-    if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_PROPERTIES))
-        != NULL) {
-        if (p->data_type != OSSL_PARAM_UTF8_STRING)
-            return 0;
-        properties = p->data;
-    }
-    /* Handle aliasing of digest parameter names */
-    if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_DIGEST)) != NULL) {
-        if (p->data_type != OSSL_PARAM_UTF8_STRING)
-            return 0;
-        md = EVP_MD_fetch(PROV_LIBRARY_CONTEXT_OF(ctx->provctx), p->data,
-                          properties);
-        if (md == NULL) {
-            ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DIGEST);
-            return 0;
-        }
-        EVP_MD_meth_free(ctx->md);
-        ctx->md = md;
-    }
+    if (!ossl_prov_digest_load_from_params(&ctx->digest, params, provctx))
+        return 0;
 
     if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_MODE)) != NULL) {
         if (p->data_type == OSSL_PARAM_UTF8_STRING) {
diff --git a/providers/common/kdfs/pbkdf2.c b/providers/common/kdfs/pbkdf2.c
index e60f0126f7..ce395576dd 100644
--- a/providers/common/kdfs/pbkdf2.c
+++ b/providers/common/kdfs/pbkdf2.c
@@ -20,6 +20,7 @@
 #include "internal/provider_ctx.h"
 #include "internal/providercommonerr.h"
 #include "internal/provider_algs.h"
+#include "internal/provider_util.h"
 
 /* Constants specified in SP800-132 */
 #define KDF_PBKDF2_MIN_KEY_LEN_BITS  112
@@ -55,7 +56,7 @@ typedef struct {
     unsigned char *salt;
     size_t salt_len;
     uint64_t iter;
-    EVP_MD *md;
+    PROV_DIGEST digest;
     int lower_bound_checks;
 } KDF_PBKDF2;
 
@@ -77,7 +78,7 @@ static void *kdf_pbkdf2_new(void *provctx)
 
 static void kdf_pbkdf2_cleanup(KDF_PBKDF2 *ctx)
 {
-    EVP_MD_meth_free(ctx->md);
+    ossl_prov_digest_reset(&ctx->digest);
     OPENSSL_free(ctx->salt);
     OPENSSL_clear_free(ctx->pass, ctx->pass_len);
     memset(ctx, 0, sizeof(*ctx));
@@ -101,9 +102,13 @@ static void kdf_pbkdf2_reset(void *vctx)
 
 static void kdf_pbkdf2_init(KDF_PBKDF2 *ctx)
 {
+    OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END };
+    OPENSSL_CTX *provctx = PROV_LIBRARY_CONTEXT_OF(ctx->provctx);
+
+    params[0] = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST,
+                                                 SN_sha1, 0);
+    ossl_prov_digest_load_from_params(&ctx->digest, params, provctx);
     ctx->iter = PKCS5_DEFAULT_ITER;
-    ctx->md = EVP_MD_fetch(PROV_LIBRARY_CONTEXT_OF(ctx->provctx), SN_sha1,
-                           NULL);
     ctx->lower_bound_checks = KDF_PBKDF2_DEFAULT_CHECKS;
 }
 
@@ -128,6 +133,7 @@ static int kdf_pbkdf2_derive(void *vctx, unsigned char *key,
                              size_t keylen)
 {
     KDF_PBKDF2 *ctx = (KDF_PBKDF2 *)vctx;
+    const EVP_MD *md = ossl_prov_digest_md(&ctx->digest);
 
     if (ctx->pass == NULL) {
         ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_PASS);
@@ -141,38 +147,19 @@ static int kdf_pbkdf2_derive(void *vctx, unsigned char *key,
 
     return pbkdf2_derive((char *)ctx->pass, ctx->pass_len,
                          ctx->salt, ctx->salt_len, ctx->iter,
-                         ctx->md, key, keylen, ctx->lower_bound_checks);
+                         md, key, keylen, ctx->lower_bound_checks);
 }
 
 static int kdf_pbkdf2_set_ctx_params(void *vctx, const OSSL_PARAM params[])
 {
     const OSSL_PARAM *p;
     KDF_PBKDF2 *ctx = vctx;
-    EVP_MD *md;
+    OPENSSL_CTX *provctx = PROV_LIBRARY_CONTEXT_OF(ctx->provctx);
     int pkcs5;
     uint64_t iter, min_iter;
-    const char *properties = NULL;
 
-    /* Grab search properties, this should be before the digest lookup */
-    if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_PROPERTIES))
-        != NULL) {
-        if (p->data_type != OSSL_PARAM_UTF8_STRING)
-            return 0;
-        properties = p->data;
-    }
-    /* Handle aliasing of digest parameter names */
-    if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_DIGEST)) != NULL) {
-        if (p->data_type != OSSL_PARAM_UTF8_STRING)
-            return 0;
-        md = EVP_MD_fetch(PROV_LIBRARY_CONTEXT_OF(ctx->provctx), p->data,
-                          properties);
-        if (md == NULL) {
-            ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DIGEST);
-            return 0;
-        }
-        EVP_MD_meth_free(ctx->md);
-        ctx->md = md;
-    }
+    if (!ossl_prov_digest_load_from_params(&ctx->digest, params, provctx))
+        return 0;
 
     if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_PKCS5)) != NULL) {
         if (!OSSL_PARAM_get_int(p, &pkcs5))
diff --git a/providers/common/kdfs/sskdf.c b/providers/common/kdfs/sskdf.c
index b8a41fbbaa..e7921bac35 100644
--- a/providers/common/kdfs/sskdf.c
+++ b/providers/common/kdfs/sskdf.c
@@ -48,11 +48,12 @@
 #include "internal/provider_ctx.h"
 #include "internal/providercommonerr.h"
 #include "internal/provider_algs.h"
+#include "internal/provider_util.h"
 
 typedef struct {
     void *provctx;
     EVP_MAC *mac;       /* H(x) = HMAC_hash OR H(x) = KMAC */
-    EVP_MD *md;         /* H(x) = hash OR when H(x) = HMAC_hash */
+    PROV_DIGEST digest;
     unsigned char *secret;
     size_t secret_len;
     unsigned char *info;
@@ -315,7 +316,7 @@ static void sskdf_reset(void *vctx)
 {
     KDF_SSKDF *ctx = (KDF_SSKDF *)vctx;
 
-    EVP_MD_meth_free(ctx->md);
+    ossl_prov_digest_reset(&ctx->digest);
     EVP_MAC_free(ctx->mac);
     OPENSSL_clear_free(ctx->secret, ctx->secret_len);
     OPENSSL_clear_free(ctx->info, ctx->info_len);
@@ -344,18 +345,20 @@ static int sskdf_set_buffer(unsigned char **out, size_t *out_len,
 static size_t sskdf_size(KDF_SSKDF *ctx)
 {
     int len;
+    const EVP_MD *md = ossl_prov_digest_md(&ctx->digest);
 
-    if (ctx->md == NULL) {
+    if (md == NULL) {
         ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_MESSAGE_DIGEST);
         return 0;
     }
-    len = EVP_MD_size(ctx->md);
+    len = EVP_MD_size(md);
     return (len <= 0) ? 0 : (size_t)len;
 }
 
 static int sskdf_derive(void *vctx, unsigned char *key, size_t keylen)
 {
     KDF_SSKDF *ctx = (KDF_SSKDF *)vctx;
+    const EVP_MD *md = ossl_prov_digest_md(&ctx->digest);
 
     if (ctx->secret == NULL) {
         ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_SECRET);
@@ -378,11 +381,11 @@ static int sskdf_derive(void *vctx, unsigned char *key, size_t keylen)
         macname = EVP_MAC_name(ctx->mac);
         if (strcmp(macname, OSSL_MAC_NAME_HMAC) == 0) {
             /* H(x) = HMAC(x, salt, hash) */
-            if (ctx->md == NULL) {
+            if (md == NULL) {
                 ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_MESSAGE_DIGEST);
                 return 0;
             }
-            default_salt_len = EVP_MD_block_size(ctx->md);
+            default_salt_len = EVP_MD_block_size(md);
             if (default_salt_len <= 0)
                 return 0;
         } else if (strcmp(macname, OSSL_MAC_NAME_KMAC128) == 0
@@ -407,7 +410,7 @@ static int sskdf_derive(void *vctx, unsigned char *key, size_t keylen)
             }
             ctx->salt_len = default_salt_len;
         }
-        ret = SSKDF_mac_kdm(ctx->mac, ctx->md,
+        ret = SSKDF_mac_kdm(ctx->mac, md,
                             custom, custom_len, ctx->out_len,
                             ctx->salt, ctx->salt_len,
                             ctx->secret, ctx->secret_len,
@@ -415,11 +418,11 @@ static int sskdf_derive(void *vctx, unsigned char *key, size_t keylen)
         return ret;
     } else {
         /* H(x) = hash */
-        if (ctx->md == NULL) {
+        if (md == NULL) {
             ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_MESSAGE_DIGEST);
             return 0;
         }
-        return SSKDF_hash_kdm(ctx->md, ctx->secret, ctx->secret_len,
+        return SSKDF_hash_kdm(md, ctx->secret, ctx->secret_len,
                               ctx->info, ctx->info_len, 0, key, keylen);
     }
 }
@@ -427,6 +430,7 @@ static int sskdf_derive(void *vctx, unsigned char *key, size_t keylen)
 static int x963kdf_derive(void *vctx, unsigned char *key, size_t keylen)
 {
     KDF_SSKDF *ctx = (KDF_SSKDF *)vctx;
+    const EVP_MD *md = ossl_prov_digest_md(&ctx->digest);
 
     if (ctx->secret == NULL) {
         ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_SECRET);
@@ -438,11 +442,11 @@ static int x963kdf_derive(void *vctx, unsigned char *key, size_t keylen)
         return 0;
     } else {
         /* H(x) = hash */
-        if (ctx->md == NULL) {
+        if (md == NULL) {
             ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_MESSAGE_DIGEST);
             return 0;
         }
-        return SSKDF_hash_kdm(ctx->md, ctx->secret, ctx->secret_len,
+        return SSKDF_hash_kdm(md, ctx->secret, ctx->secret_len,
                               ctx->info, ctx->info_len, 1, key, keylen);
     }
 }
@@ -451,31 +455,13 @@ static int sskdf_set_ctx_params(void *vctx, const OSSL_PARAM params[])
 {
     const OSSL_PARAM *p;
     KDF_SSKDF *ctx = vctx;
-    EVP_MD *md;
+    OPENSSL_CTX *provctx = PROV_LIBRARY_CONTEXT_OF(ctx->provctx);
     EVP_MAC *mac;
     size_t sz;
     const char *properties = NULL;
 
-    /* Grab search properties, should be before the digest and mac lookups */
-    if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_PROPERTIES))
-        != NULL) {
-        if (p->data_type != OSSL_PARAM_UTF8_STRING)
-            return 0;
-        properties = p->data;
-    }
-    /* Handle aliasing of digest parameter names */
-    if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_DIGEST)) != NULL) {
-        if (p->data_type != OSSL_PARAM_UTF8_STRING)
-            return 0;
-        md = EVP_MD_fetch(PROV_LIBRARY_CONTEXT_OF(ctx->provctx), p->data,
-                          properties);
-        if (md == NULL) {
-            ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DIGEST);
-            return 0;
-        }
-        EVP_MD_meth_free(ctx->md);
-        ctx->md = md;
-    }
+    if (!ossl_prov_digest_load_from_params(&ctx->digest, params, provctx))
+        return 0;
 
     if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_MAC)) != NULL) {
         EVP_MAC_free(ctx->mac);
diff --git a/providers/common/kdfs/tls1_prf.c b/providers/common/kdfs/tls1_prf.c
index 38dbaddbf0..2c5e24b403 100644
--- a/providers/common/kdfs/tls1_prf.c
+++ b/providers/common/kdfs/tls1_prf.c
@@ -58,6 +58,7 @@
 #include "internal/provider_ctx.h"
 #include "internal/providercommonerr.h"
 #include "internal/provider_algs.h"
+#include "internal/provider_util.h"
 #include "e_os.h"
 
 static OSSL_OP_kdf_newctx_fn kdf_tls1_prf_new;
@@ -78,9 +79,9 @@ static int tls1_prf_alg(const EVP_MD *md, const EVP_MD *sha1,
 typedef struct {
     void *provctx;
     /* Digest to use for PRF */
-    EVP_MD *md;
+    PROV_DIGEST digest;
     /* Second digest for the MD5/SHA-1 combined PRF */
-    EVP_MD *sha1;
+    PROV_DIGEST sha1;
     /* Secret value to use for PRF */
     unsigned char *sec;
     size_t seclen;
@@ -111,8 +112,8 @@ static void kdf_tls1_prf_reset(void *vctx)
 {
     TLS1_PRF *ctx = (TLS1_PRF *)vctx;
 
-    EVP_MD_meth_free(ctx->sha1);
-    EVP_MD_meth_free(ctx->md);
+    ossl_prov_digest_reset(&ctx->sha1);
+    ossl_prov_digest_reset(&ctx->digest);
     OPENSSL_clear_free(ctx->sec, ctx->seclen);
     OPENSSL_cleanse(ctx->seed, ctx->seedlen);
     memset(ctx, 0, sizeof(*ctx));
@@ -122,8 +123,9 @@ static int kdf_tls1_prf_derive(void *vctx, unsigned char *key,
                                size_t keylen)
 {
     TLS1_PRF *ctx = (TLS1_PRF *)vctx;
+    const EVP_MD *md = ossl_prov_digest_md(&ctx->digest);
 
-    if (ctx->md == NULL) {
+    if (md == NULL) {
         ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_MESSAGE_DIGEST);
         return 0;
     }
@@ -135,7 +137,8 @@ static int kdf_tls1_prf_derive(void *vctx, unsigned char *key,
         ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_SEED);
         return 0;
     }
-    return tls1_prf_alg(ctx->md, ctx->sha1, ctx->sec, ctx->seclen,
+    return tls1_prf_alg(md, ossl_prov_digest_md(&ctx->sha1),
+                        ctx->sec, ctx->seclen,
                         ctx->seed, ctx->seedlen,
                         key, keylen);
 }
@@ -144,41 +147,28 @@ static int kdf_tls1_prf_set_ctx_params(void *vctx, const OSSL_PARAM params[])
 {
     const OSSL_PARAM *p;
     TLS1_PRF *ctx = vctx;
-    EVP_MD *md, *sha = NULL;
-    const char *properties = NULL, *name;
-
-    /* Grab search properties, this should be before the digest lookup */
-    if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_PROPERTIES))
-        != NULL) {
-        if (p->data_type != OSSL_PARAM_UTF8_STRING)
+    OPENSSL_CTX *provctx = PROV_LIBRARY_CONTEXT_OF(ctx->provctx);
+
+    if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_DIGEST)) != NULL
+        && p->data_type == OSSL_PARAM_UTF8_STRING
+        && strcasecmp(p->data, SN_md5_sha1) == 0) {
+        OSSL_PARAM qaram[4], *q = qaram;
+
+        /* Handle combined MD5 / SHA1 digest specially */
+        *q++ = OSSL_PARAM_construct_utf8_string("digest", SN_md5, 0);
+        if ((p = OSSL_PARAM_locate_const(params, "engine")) != NULL)
+            *q++ = *p;
+        if ((p = OSSL_PARAM_locate_const(params, "properties")) != NULL)
+            *q++ = *p;
+        *q = OSSL_PARAM_construct_end();
+        if (!ossl_prov_digest_load_from_params(&ctx->digest, qaram, provctx))
             return 0;
-        properties = p->data;
-    }
-    /* Handle aliasing of digest parameter names */
-    if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_DIGEST)) != NULL) {
-        if (p->data_type != OSSL_PARAM_UTF8_STRING)
+        qaram[0] = OSSL_PARAM_construct_utf8_string("digest", SN_sha1, 0);
+        if (!ossl_prov_digest_load_from_params(&ctx->sha1, qaram, provctx))
             return 0;
-        name = p->data;
-        if (strcasecmp(name, SN_md5_sha1) == 0) {
-            sha = EVP_MD_fetch(PROV_LIBRARY_CONTEXT_OF(ctx->provctx), SN_sha1,
-                               properties);
-            if (sha == NULL) {
-                ERR_raise(ERR_LIB_PROV, PROV_R_UNABLE_TO_LOAD_SHA1);
-                return 0;
-            }
-            name = SN_md5;
-        }
-        md = EVP_MD_fetch(PROV_LIBRARY_CONTEXT_OF(ctx->provctx), name,
-                          properties);
-        if (md == NULL) {
-            ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DIGEST);
-            EVP_MD_meth_free(sha);
-            return 0;
-        }
-        EVP_MD_meth_free(ctx->sha1);
-        EVP_MD_meth_free(ctx->md);
-        ctx->md = md;
-        ctx->sha1 = sha;
+    } else if (!ossl_prov_digest_load_from_params(&ctx->digest, params,
+                                                  provctx)) {
+        return 0;
     }
 
     if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SECRET)) != NULL) {
diff --git a/providers/common/macs/cmac_prov.c b/providers/common/macs/cmac_prov.c
index 7c15bc77b0..aee0b2bb0a 100644
--- a/providers/common/macs/cmac_prov.c
+++ b/providers/common/macs/cmac_prov.c
@@ -16,6 +16,7 @@
 
 #include "internal/provider_algs.h"
 #include "internal/provider_ctx.h"
+#include "internal/provider_util.h"
 
 /*
  * Forward declaration of everything implemented here.  This is not strictly
@@ -38,21 +39,7 @@ static OSSL_OP_mac_final_fn cmac_final;
 struct cmac_data_st {
     void *provctx;
     CMAC_CTX *ctx;
-
-    /*
-     * References to the underlying cipher implementation.  tmpcipher
-     * caches the cipher, always.  alloc_cipher only holds a reference
-     * to an explicitly fetched cipher.
-     * tmpcipher is cleared after a CMAC_Init call.
-     */
-    const EVP_CIPHER *tmpcipher; /* cached CMAC cipher */
-    EVP_CIPHER *alloc_cipher;    /* fetched CMAC cipher */
-
-    /*
-     * Conditions for legacy EVP_CIPHER uses.
-     * tmpengine is cleared after a CMAC_Init call.
-     */
-    ENGINE *tmpengine;           /* CMAC cipher engine (legacy) */
+    PROV_CIPHER cipher;
 };
 
 static void *cmac_new(void *provctx)
@@ -76,7 +63,7 @@ static void cmac_free(void *vmacctx)
 
     if (macctx != NULL) {
         CMAC_CTX_free(macctx->ctx);
-        EVP_CIPHER_free(macctx->alloc_cipher);
+        ossl_prov_cipher_reset(&macctx->cipher);
         OPENSSL_free(macctx);
     }
 }
@@ -86,19 +73,11 @@ static void *cmac_dup(void *vsrc)
     struct cmac_data_st *src = vsrc;
     struct cmac_data_st *dst = cmac_new(src->provctx);
 
-    if (!CMAC_CTX_copy(dst->ctx, src->ctx)) {
+    if (!CMAC_CTX_copy(dst->ctx, src->ctx)
+        || !ossl_prov_cipher_copy(&dst->cipher, &src->cipher)) {
         cmac_free(dst);
         return NULL;
     }
-
-    if (src->alloc_cipher != NULL && !EVP_CIPHER_up_ref(src->alloc_cipher)) {
-        cmac_free(dst);
-        return NULL;
-    }
-
-    dst->tmpengine = src->tmpengine;
-    dst->tmpcipher = src->tmpcipher;
-    dst->alloc_cipher = src->alloc_cipher;
     return dst;
 }
 
@@ -112,12 +91,11 @@ static size_t cmac_size(void *vmacctx)
 static int cmac_init(void *vmacctx)
 {
     struct cmac_data_st *macctx = vmacctx;
-    int rv = CMAC_Init(macctx->ctx, NULL, 0, macctx->tmpcipher,
-                       (ENGINE *)macctx->tmpengine);
-
-    macctx->tmpcipher = NULL;
-    macctx->tmpengine = NULL;
+    int rv = CMAC_Init(macctx->ctx, NULL, 0,
+                       ossl_prov_cipher_cipher(&macctx->cipher),
+                       ossl_prov_cipher_engine(&macctx->cipher));
 
+    ossl_prov_cipher_reset(&macctx->cipher);
     return rv;
 }
 
@@ -174,67 +152,22 @@ static const OSSL_PARAM *cmac_settable_ctx_params(void)
 static int cmac_set_ctx_params(void *vmacctx, const OSSL_PARAM params[])
 {
     struct cmac_data_st *macctx = vmacctx;
+    OPENSSL_CTX *ctx = PROV_LIBRARY_CONTEXT_OF(macctx->provctx);
     const OSSL_PARAM *p;
 
-    if ((p = OSSL_PARAM_locate_const(params, OSSL_MAC_PARAM_CIPHER)) != NULL) {
-        if (p->data_type != OSSL_PARAM_UTF8_STRING)
-            return 0;
-
-        {
-            const char *algoname = p->data;
-            const char *propquery = NULL;
-
-/* Inside the FIPS module, we don't support engines */
-#if !defined(FIPS_MODE) && !defined(OPENSSL_NO_ENGINE)
-            ENGINE_finish(macctx->tmpengine);
-            macctx->tmpengine = NULL;
-
-            if ((p = OSSL_PARAM_locate_const(params, OSSL_MAC_PARAM_ENGINE))
-                != NULL) {
-                if (p->data_type != OSSL_PARAM_UTF8_STRING)
-                    return 0;
-
-                macctx->tmpengine = ENGINE_by_id(p->data);
-                if (macctx->tmpengine == NULL)
-                    return 0;
-            }
-#endif
-            if ((p = OSSL_PARAM_locate_const(params,
-                                             OSSL_MAC_PARAM_PROPERTIES))
-                != NULL) {
-                if (p->data_type != OSSL_PARAM_UTF8_STRING)
-                    return 0;
-
-                propquery = p->data;
-            }
+    if (!ossl_prov_cipher_load_from_params(&macctx->cipher, params, ctx))
+        return 0;
 
-            EVP_CIPHER_free(macctx->alloc_cipher);
-
-            macctx->tmpcipher = macctx->alloc_cipher =
-                EVP_CIPHER_fetch(PROV_LIBRARY_CONTEXT_OF(macctx->provctx),
-                                 algoname, propquery);
-
-#ifndef FIPS_MODE /* Inside the FIPS module, we don't support legacy digests */
-            /* TODO(3.0) BEGIN legacy stuff, to be removed */
-            if (macctx->tmpcipher == NULL)
-                macctx->tmpcipher = EVP_get_cipherbyname(algoname);
-            /* TODO(3.0) END of legacy stuff */
-#endif
-
-            if (macctx->tmpcipher == NULL)
-                return 0;
-        }
-    }
     if ((p = OSSL_PARAM_locate_const(params, OSSL_MAC_PARAM_KEY)) != NULL) {
         if (p->data_type != OSSL_PARAM_OCTET_STRING)
             return 0;
 
         if (!CMAC_Init(macctx->ctx, p->data, p->data_size,
-                       macctx->tmpcipher, macctx->tmpengine))
+                       ossl_prov_cipher_cipher(&macctx->cipher),
+                       ossl_prov_cipher_engine(&macctx->cipher)))
             return 0;
 
-        macctx->tmpcipher = NULL;
-        macctx->tmpengine = NULL;
+        ossl_prov_cipher_reset(&macctx->cipher);
     }
     return 1;
 }
diff --git a/providers/common/macs/gmac_prov.c b/providers/common/macs/gmac_prov.c
index 22c8c95550..2da176d8b0 100644
--- a/providers/common/macs/gmac_prov.c
+++ b/providers/common/macs/gmac_prov.c
@@ -18,6 +18,7 @@
 #include "internal/providercommonerr.h"
 #include "internal/provider_algs.h"
 #include "internal/provider_ctx.h"
+#include "internal/provider_util.h"
 
 /*
  * Forward declaration of everything implemented here.  This is not strictly
@@ -40,20 +41,7 @@ static OSSL_OP_mac_final_fn gmac_final;
 struct gmac_data_st {
     void *provctx;
     EVP_CIPHER_CTX *ctx;         /* Cipher context */
-
-    /*
-     * References to the underlying cipher implementation.  |cipher| caches
-     * the cipher, always.  |alloc_cipher| only holds a reference to an
-     * explicitly fetched cipher.
-     * |cipher| is cleared after a CMAC_Init call.
-     */
-    const EVP_CIPHER *cipher;    /* Cache GCM cipher */
-    EVP_CIPHER *alloc_cipher;    /* Fetched cipher */
-
-    /*
-     * Conditions for legacy EVP_CIPHER uses.
-     */
-    ENGINE *engine;              /* Engine implementing the cipher */
+    PROV_CIPHER cipher;
 };
 
 static size_t gmac_size(void);
@@ -64,7 +52,7 @@ static void gmac_free(void *vmacctx)
 
     if (macctx != NULL) {
         EVP_CIPHER_CTX_free(macctx->ctx);
-        EVP_CIPHER_free(macctx->alloc_cipher);
+        ossl_prov_cipher_reset(&macctx->cipher);
         OPENSSL_free(macctx);
     }
 }
@@ -92,15 +80,10 @@ static void *gmac_dup(void *vsrc)
         return NULL;
 
     if (!EVP_CIPHER_CTX_copy(dst->ctx, src->ctx)
-        || (src->alloc_cipher != NULL
-            && !EVP_CIPHER_up_ref(src->alloc_cipher))) {
+        || !ossl_prov_cipher_copy(&dst->cipher, &src->cipher)) {
         gmac_free(dst);
         return NULL;
     }
-
-    dst->cipher = src->cipher;
-    dst->alloc_cipher = src->alloc_cipher;
-    dst->engine = src->engine;
     return dst;
 }
 
@@ -188,65 +171,22 @@ static int gmac_set_ctx_params(void *vmacctx, const OSSL_PARAM params[])
 {
     struct gmac_data_st *macctx = vmacctx;
     EVP_CIPHER_CTX *ctx = macctx->ctx;
+    OPENSSL_CTX *provctx = PROV_LIBRARY_CONTEXT_OF(macctx->provctx);
     const OSSL_PARAM *p;
 
-    if ((p = OSSL_PARAM_locate_const(params, OSSL_MAC_PARAM_CIPHER)) != NULL) {
-        if (p->data_type != OSSL_PARAM_UTF8_STRING)
-            return 0;
+   if (!ossl_prov_cipher_load_from_params(&macctx->cipher, params, provctx))
+        return 0;
 
-        {
-            const char *algoname = p->data;
-            const char *propquery = NULL;
-
-/* Inside the FIPS module, we don't support engines */
-#if !defined(FIPS_MODE) && !defined(OPENSSL_NO_ENGINE)
-            ENGINE_finish(macctx->engine);
-            macctx->engine = NULL;
-
-            if ((p = OSSL_PARAM_locate_const(params, OSSL_MAC_PARAM_ENGINE))
-                != NULL) {
-                if (p->data_type != OSSL_PARAM_UTF8_STRING)
-                    return 0;
-
-                macctx->engine = ENGINE_by_id(p->data);
-                if (macctx->engine == NULL)
-                    return 0;
-            }
-#endif
-            if ((p = OSSL_PARAM_locate_const(params,
-                                             OSSL_MAC_PARAM_PROPERTIES))
-                != NULL) {
-                if (p->data_type != OSSL_PARAM_UTF8_STRING)
-                    return 0;
-
-                propquery = p->data;
-            }
-
-            EVP_CIPHER_free(macctx->alloc_cipher);
-            macctx->cipher = macctx->alloc_cipher = NULL;
-
-            macctx->cipher = macctx->alloc_cipher =
-                EVP_CIPHER_fetch(PROV_LIBRARY_CONTEXT_OF(macctx->provctx),
-                                 algoname, propquery);
-#ifndef FIPS_MODE /* Inside the FIPS module, we don't support legacy ciphers */
-            /* TODO(3.0) BEGIN legacy stuff, to be removed */
-            if (macctx->cipher == NULL)
-                macctx->cipher = EVP_get_cipherbyname(algoname);
-            /* TODO(3.0) END of legacy stuff */
-#endif
-
-            if (macctx->cipher == NULL)
-                return 0;
-
-            if (EVP_CIPHER_mode(macctx->cipher) != EVP_CIPH_GCM_MODE) {
-                ERR_raise(ERR_LIB_PROV, EVP_R_CIPHER_NOT_GCM_MODE);
-                return 0;
-            }
-        }
-        if (!EVP_EncryptInit_ex(ctx, macctx->cipher, macctx->engine,
-                                NULL, NULL))
-            return 0;
+    if (EVP_CIPHER_mode(ossl_prov_cipher_cipher(&macctx->cipher))
+        != EVP_CIPH_GCM_MODE) {
+        ERR_raise(ERR_LIB_PROV, EVP_R_CIPHER_NOT_GCM_MODE);
+        return 0;
     }
+    if (!EVP_EncryptInit_ex(ctx, ossl_prov_cipher_cipher(&macctx->cipher),
+                            ossl_prov_cipher_engine(&macctx->cipher), NULL,
+                            NULL))
+        return 0;
+
     if ((p = OSSL_PARAM_locate_const(params, OSSL_MAC_PARAM_KEY)) != NULL) {
         if (p->data_type != OSSL_PARAM_OCTET_STRING)
             return 0;
diff --git a/providers/common/macs/hmac_prov.c b/providers/common/macs/hmac_prov.c
index d5f6db79de..64d6dd9dc9 100644
--- a/providers/common/macs/hmac_prov.c
+++ b/providers/common/macs/hmac_prov.c
@@ -16,6 +16,7 @@
 
 #include "internal/provider_algs.h"
 #include "internal/provider_ctx.h"
+#include "internal/provider_util.h"
 
 /*
  * Forward declaration of everything implemented here.  This is not strictly
@@ -39,21 +40,7 @@ static OSSL_OP_mac_final_fn hmac_final;
 struct hmac_data_st {
     void *provctx;
     HMAC_CTX *ctx;               /* HMAC context */
-
-    /*
-     * References to the underlying digest implementation.  tmpmd caches
-     * the md, always.  alloc_md only holds a reference to an explicitly
-     * fetched digest.
-     * tmpmd is cleared after a CMAC_Init call.
-     */
-    const EVP_MD *tmpmd;         /* HMAC digest */
-    EVP_MD *alloc_md;            /* fetched digest */
-
-    /*
-     * Conditions for legacy EVP_MD uses.
-     * tmpengine is cleared after a CMAC_Init call.
-     */
-    ENGINE *tmpengine;           /* HMAC digest engine */
+    PROV_DIGEST digest;
 };
 
 static size_t hmac_size(void *vmacctx);
@@ -79,7 +66,7 @@ static void hmac_free(void *vmacctx)
 
     if (macctx != NULL) {
         HMAC_CTX_free(macctx->ctx);
-        EVP_MD_free(macctx->alloc_md);
+        ossl_prov_digest_reset(&macctx->digest);
         OPENSSL_free(macctx);
     }
 }
@@ -92,19 +79,11 @@ static void *hmac_dup(void *vsrc)
     if (dst == NULL)
         return NULL;
 
-    if (!HMAC_CTX_copy(dst->ctx, src->ctx)) {
-        hmac_free(dst);
-        return NULL;
-    }
-
-    if (src->alloc_md != NULL && !EVP_MD_up_ref(src->alloc_md)) {
+    if (!HMAC_CTX_copy(dst->ctx, src->ctx)
+        || !ossl_prov_digest_copy(&dst->digest, &src->digest)) {
         hmac_free(dst);
         return NULL;
     }
-
-    dst->tmpengine = src->tmpengine;
-    dst->tmpmd = src->tmpmd;
-    dst->alloc_md = src->alloc_md;
     return dst;
 }
 
@@ -118,14 +97,14 @@ static size_t hmac_size(void *vmacctx)
 static int hmac_init(void *vmacctx)
 {
     struct hmac_data_st *macctx = vmacctx;
+    const EVP_MD *digest = ossl_prov_digest_md(&macctx->digest);
     int rv = 1;
 
     /* HMAC_Init_ex doesn't tolerate all zero params, so we must be careful */
-    if (macctx->tmpmd != NULL)
-        rv = HMAC_Init_ex(macctx->ctx, NULL, 0, macctx->tmpmd,
-                          (ENGINE * )macctx->tmpengine);
-    macctx->tmpengine = NULL;
-    macctx->tmpmd = NULL;
+    if (digest != NULL)
+        rv = HMAC_Init_ex(macctx->ctx, NULL, 0, digest,
+                          ossl_prov_digest_engine(&macctx->digest));
+    ossl_prov_digest_reset(&macctx->digest);
     return rv;
 }
 
@@ -188,57 +167,12 @@ static const OSSL_PARAM *hmac_settable_ctx_params(void)
 static int hmac_set_ctx_params(void *vmacctx, const OSSL_PARAM params[])
 {
     struct hmac_data_st *macctx = vmacctx;
+    OPENSSL_CTX *ctx = PROV_LIBRARY_CONTEXT_OF(macctx->provctx);
     const OSSL_PARAM *p;
 
-    if ((p = OSSL_PARAM_locate_const(params, OSSL_MAC_PARAM_DIGEST)) != NULL) {
-        if (p->data_type != OSSL_PARAM_UTF8_STRING)
-            return 0;
+    if (!ossl_prov_digest_load_from_params(&macctx->digest, params, ctx))
+        return 0;
 
-        {
-            const char *algoname = p->data;
-            const char *propquery = NULL;
-
-/* Inside the FIPS module, we don't support engines */
-#if !defined(FIPS_MODE) && !defined(OPENSSL_NO_ENGINE)
-            ENGINE_finish(macctx->tmpengine);
-            macctx->tmpengine = NULL;
-
-            if ((p = OSSL_PARAM_locate_const(params, OSSL_MAC_PARAM_ENGINE))
-                != NULL) {
-                if (p->data_type != OSSL_PARAM_UTF8_STRING)
-                    return 0;
-
-                macctx->tmpengine = ENGINE_by_id(p->data);
-                if (macctx->tmpengine == NULL)
-                    return 0;
-            }
-#endif
-            if ((p = OSSL_PARAM_locate_const(params,
-                                             OSSL_MAC_PARAM_PROPERTIES))
-                != NULL) {
-                if (p->data_type != OSSL_PARAM_UTF8_STRING)
-                    return 0;
-
-                propquery = p->data;
-            }
-
-            EVP_MD_free(macctx->alloc_md);
-
-            macctx->tmpmd = macctx->alloc_md =
-                EVP_MD_fetch(PROV_LIBRARY_CONTEXT_OF(macctx->provctx),
-                             algoname, propquery);
-
-#ifndef FIPS_MODE /* Inside the FIPS module, we don't support legacy digests */
-            /* TODO(3.0) BEGIN legacy stuff, to be removed */
-            if (macctx->tmpmd == NULL)
-                macctx->tmpmd = EVP_get_digestbyname(algoname);
-            /* TODO(3.0) END of legacy stuff */
-#endif
-
-            if (macctx->tmpmd == NULL)
-                    return 0;
-        }
-    }
     /* TODO(3.0) formalize the meaning of "flags", perhaps as other params */
     if ((p = OSSL_PARAM_locate_const(params,
                                      OSSL_MAC_PARAM_FLAGS)) != NULL) {
@@ -253,11 +187,11 @@ static int hmac_set_ctx_params(void *vmacctx, const OSSL_PARAM params[])
             return 0;
 
         if (!HMAC_Init_ex(macctx->ctx, p->data, p->data_size,
-                          macctx->tmpmd, NULL /* ENGINE */))
+                          ossl_prov_digest_md(&macctx->digest),
+                          NULL /* ENGINE */))
             return 0;
 
-        macctx->tmpmd = NULL;
-        macctx->tmpengine = NULL;
+        ossl_prov_digest_reset(&macctx->digest);
     }
     return 1;
 }
diff --git a/providers/common/macs/kmac_prov.c b/providers/common/macs/kmac_prov.c
index 9ffdbd5249..53598418db 100644
--- a/providers/common/macs/kmac_prov.c
+++ b/providers/common/macs/kmac_prov.c
@@ -57,6 +57,7 @@
 #include "internal/providercommonerr.h"
 #include "internal/provider_algs.h"
 #include "internal/provider_ctx.h"
+#include "internal/provider_util.h"
 
 /*
  * Forward declaration of everything implemented here.  This is not strictly
@@ -113,16 +114,7 @@ static const unsigned char kmac_string[] = {
 struct kmac_data_st {
     void  *provctx;
     EVP_MD_CTX *ctx;
-
-    /*
-     * References to the underlying keccak_kmac implementation.  |md|
-     * caches the digest, always.  |alloc_md| only holds a reference to an
-     * explicitly fetched digest.
-     * |md| is cleared after a EVP_DigestInit call.
-     */
-    const EVP_MD *md;            /* Cache KMAC digest */
-    EVP_MD *alloc_md;            /* Fetched digest */
-
+    PROV_DIGEST digest;
     size_t out_len;
     int key_len;
     int custom_len;
@@ -150,7 +142,7 @@ static void kmac_free(void *vmacctx)
 
     if (kctx != NULL) {
         EVP_MD_CTX_free(kctx->ctx);
-        EVP_MD_free(kctx->alloc_md);
+        ossl_prov_digest_reset(&kctx->digest);
         OPENSSL_cleanse(kctx->key, kctx->key_len);
         OPENSSL_cleanse(kctx->custom, kctx->custom_len);
         OPENSSL_free(kctx);
@@ -162,12 +154,9 @@ static void kmac_free(void *vmacctx)
  * reimplementing the EVP functionality with direct use of
  * keccak_mac_init() and friends.
  */
-static void *kmac_new(void *provctx, EVP_MD *fetched_md, const EVP_MD *md)
+static struct kmac_data_st *kmac_new(void *provctx)
 {
-    struct kmac_data_st *kctx = NULL;
-
-    if (md == NULL)
-        return NULL;
+    struct kmac_data_st *kctx;
 
     if ((kctx = OPENSSL_zalloc(sizeof(*kctx))) == NULL
             || (kctx->ctx = EVP_MD_CTX_new()) == NULL) {
@@ -175,58 +164,57 @@ static void *kmac_new(void *provctx, EVP_MD *fetched_md, const EVP_MD *md)
         return NULL;
     }
     kctx->provctx = provctx;
-    kctx->md = md;
-    kctx->alloc_md = fetched_md;
-    kctx->out_len = EVP_MD_size(md);
     return kctx;
 }
 
-static void *kmac_fetch_new(void *provctx, const char *mdname)
+static void *kmac_fetch_new(void *provctx, const OSSL_PARAM *params)
 {
-    EVP_MD *fetched_md = EVP_MD_fetch(PROV_LIBRARY_CONTEXT_OF(provctx),
-                                      mdname, NULL);
-    const EVP_MD *md = fetched_md;
-    void *ret = NULL;
-
-#ifndef FIPS_MODE /* Inside the FIPS module, we don't support legacy digests */
-    /* TODO(3.0) BEGIN legacy stuff, to be removed */
-    if (md == NULL)
-        md = EVP_get_digestbyname(mdname);
-    /* TODO(3.0) END of legacy stuff */
-#endif
-
-    ret = kmac_new(provctx, fetched_md, md);
-    if (ret == NULL)
-        EVP_MD_free(fetched_md);
-    return ret;
+    struct kmac_data_st *kctx = kmac_new(provctx);
+
+    if (kctx == NULL)
+        return 0;
+    if (!ossl_prov_digest_load_from_params(&kctx->digest, params,
+                                      PROV_LIBRARY_CONTEXT_OF(provctx)))
+        return 0;
+
+    kctx->out_len = EVP_MD_size(ossl_prov_digest_md(&kctx->digest));
+    return kctx;
 }
 
 static void *kmac128_new(void *provctx)
 {
-    return kmac_fetch_new(provctx, OSSL_DIGEST_NAME_KECCAK_KMAC128);
+    static const OSSL_PARAM kmac128_params[] = {
+        OSSL_PARAM_utf8_string("digest", OSSL_DIGEST_NAME_KECCAK_KMAC128,
+                               sizeof(OSSL_DIGEST_NAME_KECCAK_KMAC128)),
+        OSSL_PARAM_END
+    };
+    return kmac_fetch_new(provctx, kmac128_params);
 }
 
 static void *kmac256_new(void *provctx)
 {
-    return kmac_fetch_new(provctx, OSSL_DIGEST_NAME_KECCAK_KMAC256);
+    static const OSSL_PARAM kmac256_params[] = {
+        OSSL_PARAM_utf8_string("digest", OSSL_DIGEST_NAME_KECCAK_KMAC256,
+                               sizeof(OSSL_DIGEST_NAME_KECCAK_KMAC256)),
+        OSSL_PARAM_END
+    };
+    return kmac_fetch_new(provctx, kmac256_params);
 }
 
 static void *kmac_dup(void *vsrc)
 {
     struct kmac_data_st *src = vsrc;
-    struct kmac_data_st *dst = kmac_new(src->provctx, src->alloc_md, src->md);
+    struct kmac_data_st *dst = kmac_new(src->provctx);
 
     if (dst == NULL)
         return NULL;
 
     if (!EVP_MD_CTX_copy(dst->ctx, src->ctx)
-        || (src->alloc_md != NULL && !EVP_MD_up_ref(src->alloc_md))) {
+        || !ossl_prov_digest_copy(&dst->digest, &src->digest)) {
         kmac_free(dst);
         return NULL;
     }
 
-    dst->md = src->md;
-    dst->alloc_md = src->alloc_md;
     dst->out_len = src->out_len;
     dst->key_len = src->key_len;
     dst->custom_len = src->custom_len;
@@ -255,10 +243,11 @@ static int kmac_init(void *vmacctx)
         EVPerr(EVP_F_KMAC_INIT, EVP_R_NO_KEY_SET);
         return 0;
     }
-    if (!EVP_DigestInit_ex(kctx->ctx, kctx->md, NULL))
+    if (!EVP_DigestInit_ex(kctx->ctx, ossl_prov_digest_md(&kctx->digest),
+                           NULL))
         return 0;
 
-    block_len = EVP_MD_block_size(kctx->md);
+    block_len = EVP_MD_block_size(ossl_prov_digest_md(&kctx->digest));
 
     /* Set default custom string if it is not already set */
     if (kctx->custom_len == 0) {
@@ -354,6 +343,7 @@ static int kmac_set_ctx_params(void *vmacctx, const OSSL_PARAM *params)
 {
     struct kmac_data_st *kctx = vmacctx;
     const OSSL_PARAM *p;
+    const EVP_MD *digest = ossl_prov_digest_md(&kctx->digest);
 
     if ((p = OSSL_PARAM_locate_const(params, OSSL_MAC_PARAM_XOF)) != NULL
         && !OSSL_PARAM_get_int(p, &kctx->xof_mode))
@@ -368,7 +358,7 @@ static int kmac_set_ctx_params(void *vmacctx, const OSSL_PARAM *params)
         }
         if (!kmac_bytepad_encode_key(kctx->key, &kctx->key_len,
                                      p->data, p->data_size,
-                                     EVP_MD_block_size(kctx->md)))
+                                     EVP_MD_block_size(digest)))
             return 0;
     }
     if ((p = OSSL_PARAM_locate_const(params, OSSL_MAC_PARAM_CUSTOM))
diff --git a/providers/common/provider_util.c b/providers/common/provider_util.c
new file mode 100644
index 0000000000..babbfffd3d
--- /dev/null
+++ b/providers/common/provider_util.c
@@ -0,0 +1,151 @@
+/*
+ * 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/evp.h>
+#include <openssl/core_names.h>
+#include "internal/provider_util.h"
+
+void ossl_prov_cipher_reset(PROV_CIPHER *pc)
+{
+    EVP_CIPHER_free(pc->alloc_cipher);
+    pc->alloc_cipher = NULL;
+    pc->cipher = NULL;
+    pc->engine = NULL;
+}
+
+int ossl_prov_cipher_copy(PROV_CIPHER *dst, const PROV_CIPHER *src)
+{
+    if (src->alloc_cipher != NULL && !EVP_CIPHER_up_ref(src->alloc_cipher))
+        return 0;
+    dst->engine = src->engine;
+    dst->cipher = src->cipher;
+    dst->alloc_cipher = src->alloc_cipher;
+    return 1;
+}
+
+static int load_common(const OSSL_PARAM params[], const char **propquery,
+                       ENGINE **engine)
+{
+    const OSSL_PARAM *p;
+
+    *propquery = NULL;
+    p = OSSL_PARAM_locate_const(params, OSSL_ALG_PARAM_PROPERTIES);
+    if (p != NULL) {
+        if (p->data_type != OSSL_PARAM_UTF8_STRING)
+            return 0;
+        *propquery = p->data;
+    }
+
+    *engine = NULL;
+    /* TODO legacy stuff, to be removed */
+#ifndef FIPS_MODE /* Inside the FIPS module, we don't support legacy ciphers */
+    p = OSSL_PARAM_locate_const(params, OSSL_ALG_PARAM_ENGINE);
+    if (p != NULL) {
+        if (p->data_type != OSSL_PARAM_UTF8_STRING)
+            return 0;
+        ENGINE_finish(*engine);
+        *engine = ENGINE_by_id(p->data);
+        if (*engine == NULL)
+            return 0;
+    }
+#endif
+    return 1;
+}
+
+int ossl_prov_cipher_load_from_params(PROV_CIPHER *pc,
+                                      const OSSL_PARAM params[],
+                                      OPENSSL_CTX *ctx)
+{
+    const OSSL_PARAM *p;
+    const char *propquery;
+
+    if (!load_common(params, &propquery, &pc->engine))
+        return 0;
+
+    p = OSSL_PARAM_locate_const(params, OSSL_ALG_PARAM_CIPHER);
+    if (p == NULL)
+        return 1;
+    if (p->data_type != OSSL_PARAM_UTF8_STRING)
+        return 0;
+
+    EVP_CIPHER_free(pc->alloc_cipher);
+    pc->cipher = pc->alloc_cipher = EVP_CIPHER_fetch(ctx, p->data, propquery);
+    /* TODO legacy stuff, to be removed */
+#ifndef FIPS_MODE /* Inside the FIPS module, we don't support legacy ciphers */
+    if (pc->cipher == NULL)
+        pc->cipher = EVP_get_cipherbyname(p->data);
+#endif
+    return pc->cipher != NULL;
+}
+
+const EVP_CIPHER *ossl_prov_cipher_cipher(const PROV_CIPHER *pc)
+{
+    return pc->cipher;
+}
+
+ENGINE *ossl_prov_cipher_engine(const PROV_CIPHER *pc)
+{
+    return pc->engine;
+}
+
+void ossl_prov_digest_reset(PROV_DIGEST *pd)
+{
+    EVP_MD_free(pd->alloc_md);
+    pd->alloc_md = NULL;
+    pd->md = NULL;
+    pd->engine = NULL;
+}
+
+int ossl_prov_digest_copy(PROV_DIGEST *dst, const PROV_DIGEST *src)
+{
+    if (src->alloc_md != NULL && !EVP_MD_up_ref(src->alloc_md))
+        return 0;
+    dst->engine = src->engine;
+    dst->md = src->md;
+    dst->alloc_md = src->alloc_md;
+    return 1;
+}
+
+int ossl_prov_digest_load_from_params(PROV_DIGEST *pd,
+                                      const OSSL_PARAM params[],
+                                      OPENSSL_CTX *ctx)
+{
+    const OSSL_PARAM *p;
+    const char *propquery;
+
+    if (!load_common(params, &propquery, &pd->engine))
+        return 0;
+
+
+    p = OSSL_PARAM_locate_const(params, OSSL_ALG_PARAM_DIGEST);
+    if (p == NULL)
+        return 1;
+    if (p->data_type != OSSL_PARAM_UTF8_STRING)
+        return 0;
+
+    EVP_MD_free(pd->alloc_md);
+    pd->md = pd->alloc_md = EVP_MD_fetch(ctx, p->data, propquery);
+    /* TODO legacy stuff, to be removed */
+#ifndef FIPS_MODE /* Inside the FIPS module, we don't support legacy digests */
+    if (pd->md == NULL)
+        pd->md = EVP_get_digestbyname(p->data);
+#endif
+    return pd->md != NULL;
+}
+
+const EVP_MD *ossl_prov_digest_md(const PROV_DIGEST *pd)
+{
+    return pd->md;
+}
+
+ENGINE *ossl_prov_digest_engine(const PROV_DIGEST *pd)
+{
+    return pd->engine;
+}
+
diff --git a/providers/default/kdfs/sshkdf.c b/providers/default/kdfs/sshkdf.c
index da59aaf861..2db5397294 100644
--- a/providers/default/kdfs/sshkdf.c
+++ b/providers/default/kdfs/sshkdf.c
@@ -19,6 +19,7 @@
 #include "internal/provider_ctx.h"
 #include "internal/providercommonerr.h"
 #include "internal/provider_algs.h"
+# include "internal/provider_util.h"
 
 /* See RFC 4253, Section 7.2 */
 static OSSL_OP_kdf_newctx_fn kdf_sshkdf_new;
@@ -38,7 +39,7 @@ static int SSHKDF(const EVP_MD *evp_md,
 
 typedef struct {
     void *provctx;
-    EVP_MD *md;
+    PROV_DIGEST digest;
     unsigned char *key; /* K */
     size_t key_len;
     unsigned char *xcghash; /* H */
@@ -70,7 +71,7 @@ static void kdf_sshkdf_reset(void *vctx)
 {
     KDF_SSHKDF *ctx = (KDF_SSHKDF *)vctx;
 
-    EVP_MD_meth_free(ctx->md);
+    ossl_prov_digest_reset(&ctx->digest);
     OPENSSL_clear_free(ctx->key, ctx->key_len);
     OPENSSL_clear_free(ctx->xcghash, ctx->xcghash_len);
     OPENSSL_clear_free(ctx->session_id, ctx->session_id_len);
@@ -89,8 +90,9 @@ static int kdf_sshkdf_derive(void *vctx, unsigned char *key,
                              size_t keylen)
 {
     KDF_SSHKDF *ctx = (KDF_SSHKDF *)vctx;
+    const EVP_MD *md = ossl_prov_digest_md(&ctx->digest);
 
-    if (ctx->md == NULL) {
+    if (md == NULL) {
         ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_MESSAGE_DIGEST);
         return 0;
     }
@@ -110,7 +112,7 @@ static int kdf_sshkdf_derive(void *vctx, unsigned char *key,
         ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_TYPE);
         return 0;
     }
-    return SSHKDF(ctx->md, ctx->key, ctx->key_len,
+    return SSHKDF(md, ctx->key, ctx->key_len,
                   ctx->xcghash, ctx->xcghash_len,
                   ctx->session_id, ctx->session_id_len,
                   ctx->type, key, keylen);
@@ -120,30 +122,11 @@ static int kdf_sshkdf_set_ctx_params(void *vctx, const OSSL_PARAM params[])
 {
     const OSSL_PARAM *p;
     KDF_SSHKDF *ctx = vctx;
-    EVP_MD *md;
+    OPENSSL_CTX *provctx = PROV_LIBRARY_CONTEXT_OF(ctx->provctx);
     int t;
-    const char *properties = NULL;
 
-    /* Grab search properties, this should be before the digest lookup */
-    if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_PROPERTIES))
-        != NULL) {
-        if (p->data_type != OSSL_PARAM_UTF8_STRING)
-            return 0;
-        properties = p->data;
-    }
-    /* Handle aliasing of digest parameter names */
-    if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_DIGEST)) != NULL) {
-        if (p->data_type != OSSL_PARAM_UTF8_STRING)
-            return 0;
-        md = EVP_MD_fetch(PROV_LIBRARY_CONTEXT_OF(ctx->provctx), p->data,
-                          properties);
-        if (md == NULL) {
-            ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DIGEST);
-            return 0;
-        }
-        EVP_MD_meth_free(ctx->md);
-        ctx->md = md;
-    }
+    if (!ossl_prov_digest_load_from_params(&ctx->digest, params, provctx))
+        return 0;
 
     if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_KEY)) != NULL)
         if (!sshkdf_set_membuf(&ctx->key, &ctx->key_len, p))
diff --git a/providers/default/kdfs/x942kdf.c b/providers/default/kdfs/x942kdf.c
index af2b4a8db4..7c3afef911 100644
--- a/providers/default/kdfs/x942kdf.c
+++ b/providers/default/kdfs/x942kdf.c
@@ -28,6 +28,7 @@
 # include "internal/provider_ctx.h"
 # include "internal/providercommonerr.h"
 # include "internal/provider_algs.h"
+# include "internal/provider_util.h"
 
 # define X942KDF_MAX_INLEN (1 << 30)
 
@@ -42,7 +43,7 @@ static OSSL_OP_kdf_get_ctx_params_fn x942kdf_get_ctx_params;
 
 typedef struct {
     void *provctx;
-    EVP_MD *md;
+    PROV_DIGEST digest;
     unsigned char *secret;
     size_t secret_len;
     int cek_nid;
@@ -255,7 +256,7 @@ static void x942kdf_reset(void *vctx)
 {
     KDF_X942 *ctx = (KDF_X942 *)vctx;
 
-    EVP_MD_meth_free(ctx->md);
+    ossl_prov_digest_reset(&ctx->digest);
     OPENSSL_clear_free(ctx->secret, ctx->secret_len);
     OPENSSL_clear_free(ctx->ukm, ctx->ukm_len);
     memset(ctx, 0, sizeof(*ctx));
@@ -283,18 +284,20 @@ static int x942kdf_set_buffer(unsigned char **out, size_t *out_len,
 static size_t x942kdf_size(KDF_X942 *ctx)
 {
     int len;
+    const EVP_MD *md = ossl_prov_digest_md(&ctx->digest);
 
-    if (ctx->md == NULL) {
+    if (md == NULL) {
         ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_MESSAGE_DIGEST);
         return 0;
     }
-    len = EVP_MD_size(ctx->md);
+    len = EVP_MD_size(md);
     return (len <= 0) ? 0 : (size_t)len;
 }
 
 static int x942kdf_derive(void *vctx, unsigned char *key, size_t keylen)
 {
     KDF_X942 *ctx = (KDF_X942 *)vctx;
+    const EVP_MD *md = ossl_prov_digest_md(&ctx->digest);
     int ret = 0;
     unsigned char *ctr;
     unsigned char *der = NULL;
@@ -304,7 +307,7 @@ static int x942kdf_derive(void *vctx, unsigned char *key, size_t keylen)
         ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_SECRET);
         return 0;
     }
-    if (ctx->md == NULL) {
+    if (md == NULL) {
         ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_MESSAGE_DIGEST);
         return 0;
     }
@@ -331,7 +334,7 @@ static int x942kdf_derive(void *vctx, unsigned char *key, size_t keylen)
         ERR_raise(ERR_LIB_PROV, PROV_R_BAD_ENCODING);
         return 0;
     }
-    ret = x942kdf_hash_kdm(ctx->md, ctx->secret, ctx->secret_len,
+    ret = x942kdf_hash_kdm(md, ctx->secret, ctx->secret_len,
                            der, der_len, ctr, key, keylen);
     OPENSSL_free(der);
     return ret;
@@ -341,30 +344,11 @@ static int x942kdf_set_ctx_params(void *vctx, const OSSL_PARAM params[])
 {
     const OSSL_PARAM *p;
     KDF_X942 *ctx = vctx;
-    EVP_MD *md;
-    const char *properties = NULL;
+    OPENSSL_CTX *provctx = PROV_LIBRARY_CONTEXT_OF(ctx->provctx);
     size_t i;
 
-    /* Grab search properties, this should be before the digest lookup */
-    if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_PROPERTIES))
-        != NULL) {
-        if (p->data_type != OSSL_PARAM_UTF8_STRING)
-            return 0;
-        properties = p->data;
-    }
-    /* Handle aliasing of digest parameter names */
-    if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_DIGEST)) != NULL) {
-        if (p->data_type != OSSL_PARAM_UTF8_STRING)
-            return 0;
-        md = EVP_MD_fetch(PROV_LIBRARY_CONTEXT_OF(ctx->provctx), p->data,
-                          properties);
-        if (md == NULL) {
-            ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DIGEST);
-            return 0;
-        }
-        EVP_MD_meth_free(ctx->md);
-        ctx->md = md;
-    }
+    if (!ossl_prov_digest_load_from_params(&ctx->digest, params, provctx))
+        return 0;
 
     if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SECRET)) != NULL
         || (p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_KEY)) != NULL)


More information about the openssl-commits mailing list