[openssl] master update

Dr. Paul Dale pauli at openssl.org
Tue Feb 1 05:17:44 UTC 2022


The branch master has been updated
       via  1751356267f64d5db8824cf4ff5b3496e15972da (commit)
       via  b9d8ad3f157fa816c423bec6f7b4328ef894577c (commit)
       via  d3aaf4e9e71944d869ae47821d7b5a8402234ee8 (commit)
       via  43332e405bea83a2d553e0519fdb04170879bc96 (commit)
       via  769cd46540b2ec2a2d91ee3886b9e4f9d78e9a51 (commit)
       via  2722eeceaa993f4488b295a22d2e1178f5ba1ce1 (commit)
       via  59558f9d8824747024b6ab756f3798a577ecae48 (commit)
       via  cdcdcf5c6fa382c879cb3503609519d56fa62e81 (commit)
       via  fe01052f775d1b5dff86ff9b405b6b0df5efd3cf (commit)
       via  4c1a841c3de645674ed2af92da25f7f5736fae1c (commit)
       via  d54c52c28ebb780e2ffc5b7752d35359215cf0a6 (commit)
       via  95bd5ff65985e992827f7178deda84d95b1e6f66 (commit)
       via  0a10f71d3071bae0183cd4277da64d100f6b48eb (commit)
       via  6585d3aa7638c8cea2d4bb9f10e7298002f652e5 (commit)
       via  c8adf19d2da318cd7b007753d6c8a7f9dc94d4ed (commit)
       via  5b030ec0800d4ad6022ecd00e18a19f77ada0b04 (commit)
      from  a841d450a443efccf4df02922ebe02e4c2f11a2b (commit)


- Log -----------------------------------------------------------------
commit 1751356267f64d5db8824cf4ff5b3496e15972da
Author: Pauli <pauli at openssl.org>
Date:   Wed Jan 26 12:01:57 2022 +1100

    indentation fix
    
    Reviewed-by: Shane Lontis <shane.lontis at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/17572)

commit b9d8ad3f157fa816c423bec6f7b4328ef894577c
Author: Pauli <pauli at openssl.org>
Date:   Tue Jan 25 11:54:56 2022 +1100

    tls1 prf: implement ctx dup operation
    
    Reviewed-by: Shane Lontis <shane.lontis at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/17572)

commit d3aaf4e9e71944d869ae47821d7b5a8402234ee8
Author: Pauli <pauli at openssl.org>
Date:   Tue Jan 25 11:54:42 2022 +1100

    pkcs12 kdf: implement ctx dup operation
    
    Reviewed-by: Shane Lontis <shane.lontis at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/17572)

commit 43332e405bea83a2d553e0519fdb04170879bc96
Author: Pauli <pauli at openssl.org>
Date:   Tue Jan 25 11:47:23 2022 +1100

    test: change pkey kdf dup fail test to a pkey kdf dup success test
    
    Reviewed-by: Shane Lontis <shane.lontis at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/17572)

commit 769cd46540b2ec2a2d91ee3886b9e4f9d78e9a51
Author: Pauli <pauli at openssl.org>
Date:   Mon Jan 24 17:38:57 2022 +1100

    k942 kdf: implement ctx dup operation
    
    Reviewed-by: Shane Lontis <shane.lontis at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/17572)

commit 2722eeceaa993f4488b295a22d2e1178f5ba1ce1
Author: Pauli <pauli at openssl.org>
Date:   Mon Jan 24 17:32:16 2022 +1100

    ss KDF: implement ctx dup operation
    
    Reviewed-by: Shane Lontis <shane.lontis at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/17572)

commit 59558f9d8824747024b6ab756f3798a577ecae48
Author: Pauli <pauli at openssl.org>
Date:   Mon Jan 24 17:22:37 2022 +1100

    ssh kdf: implement ctx dup operation
    
    Reviewed-by: Shane Lontis <shane.lontis at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/17572)

commit cdcdcf5c6fa382c879cb3503609519d56fa62e81
Author: Pauli <pauli at openssl.org>
Date:   Mon Jan 24 17:17:58 2022 +1100

    scrypt: implement ctx dup operation
    
    Reviewed-by: Shane Lontis <shane.lontis at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/17572)

commit fe01052f775d1b5dff86ff9b405b6b0df5efd3cf
Author: Pauli <pauli at openssl.org>
Date:   Mon Jan 24 17:08:58 2022 +1100

    pvk kdf: implement ctx dup operation
    
    Reviewed-by: Shane Lontis <shane.lontis at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/17572)

commit 4c1a841c3de645674ed2af92da25f7f5736fae1c
Author: Pauli <pauli at openssl.org>
Date:   Mon Jan 24 17:02:29 2022 +1100

    krb5kdf: implement ctx dup operation
    
    Reviewed-by: Shane Lontis <shane.lontis at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/17572)

commit d54c52c28ebb780e2ffc5b7752d35359215cf0a6
Author: Pauli <pauli at openssl.org>
Date:   Mon Jan 24 16:58:54 2022 +1100

    kbkdf: implement ctx dup operation
    
    Reviewed-by: Shane Lontis <shane.lontis at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/17572)

commit 95bd5ff65985e992827f7178deda84d95b1e6f66
Author: Pauli <pauli at openssl.org>
Date:   Mon Jan 24 16:51:24 2022 +1100

    hkdf: implement ctx dup operation
    
    Reviewed-by: Shane Lontis <shane.lontis at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/17572)

commit 0a10f71d3071bae0183cd4277da64d100f6b48eb
Author: Pauli <pauli at openssl.org>
Date:   Mon Jan 24 16:22:54 2022 +1100

    pbkdf2: implement ctx dup operation
    
    Reviewed-by: Shane Lontis <shane.lontis at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/17572)

commit 6585d3aa7638c8cea2d4bb9f10e7298002f652e5
Author: Pauli <pauli at openssl.org>
Date:   Mon Jan 24 16:17:44 2022 +1100

    pbkdf1: implement ctx dup operation
    
    Reviewed-by: Shane Lontis <shane.lontis at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/17572)

commit c8adf19d2da318cd7b007753d6c8a7f9dc94d4ed
Author: Pauli <pauli at openssl.org>
Date:   Mon Jan 24 16:17:25 2022 +1100

    evp_test: add a ctx dup operation to the KDF tests
    
    Reviewed-by: Shane Lontis <shane.lontis at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/17572)

commit 5b030ec0800d4ad6022ecd00e18a19f77ada0b04
Author: Pauli <pauli at openssl.org>
Date:   Wed Jan 26 15:21:51 2022 +1100

    prov: add a safe memdup function for context cloning
    
    Reviewed-by: Shane Lontis <shane.lontis at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/17572)

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

Summary of changes:
 providers/common/include/prov/provider_util.h |  4 +++
 providers/common/provider_util.c              | 19 +++++++++++++-
 providers/implementations/kdfs/hkdf.c         | 33 +++++++++++++++++++++++
 providers/implementations/kdfs/kbkdf.c        | 32 ++++++++++++++++++++++
 providers/implementations/kdfs/krb5kdf.c      | 23 ++++++++++++++++
 providers/implementations/kdfs/pbkdf1.c       | 24 +++++++++++++++++
 providers/implementations/kdfs/pbkdf2.c       | 38 +++++++++++++++++++++++++--
 providers/implementations/kdfs/pkcs12kdf.c    | 25 ++++++++++++++++++
 providers/implementations/kdfs/pvkkdf.c       | 22 ++++++++++++++++
 providers/implementations/kdfs/scrypt.c       | 35 ++++++++++++++++++++++++
 providers/implementations/kdfs/sshkdf.c       | 26 ++++++++++++++++++
 providers/implementations/kdfs/sskdf.c        | 32 ++++++++++++++++++++++
 providers/implementations/kdfs/tls1_prf.c     | 27 +++++++++++++++++++
 providers/implementations/kdfs/x942kdf.c      | 37 ++++++++++++++++++++++++++
 test/evp_pkey_provided_test.c                 | 15 ++++++-----
 test/evp_test.c                               |  5 ++++
 16 files changed, 387 insertions(+), 10 deletions(-)

diff --git a/providers/common/include/prov/provider_util.h b/providers/common/include/prov/provider_util.h
index dfe91f29bc..0bf7f9c3b1 100644
--- a/providers/common/include/prov/provider_util.h
+++ b/providers/common/include/prov/provider_util.h
@@ -136,3 +136,7 @@ typedef struct ag_capable_st {
  */
 void ossl_prov_cache_exported_algorithms(const OSSL_ALGORITHM_CAPABLE *in,
                                          OSSL_ALGORITHM *out);
+
+/* Duplicate a lump of memory safely */
+int ossl_prov_memdup(const void *src, size_t src_len,
+                     unsigned char **dest, size_t *dest_len);
diff --git a/providers/common/provider_util.c b/providers/common/provider_util.c
index 58d4db3379..c934cfc59b 100644
--- a/providers/common/provider_util.c
+++ b/providers/common/provider_util.c
@@ -165,7 +165,7 @@ int ossl_prov_digest_copy(PROV_DIGEST *dst, const PROV_DIGEST *src)
 }
 
 const EVP_MD *ossl_prov_digest_fetch(PROV_DIGEST *pd, OSSL_LIB_CTX *libctx,
-                           const char *mdname, const char *propquery)
+                                     const char *mdname, const char *propquery)
 {
     EVP_MD_free(pd->alloc_md);
     pd->md = pd->alloc_md = EVP_MD_fetch(libctx, mdname, propquery);
@@ -351,3 +351,20 @@ void ossl_prov_cache_exported_algorithms(const OSSL_ALGORITHM_CAPABLE *in,
         out[j++] = in[i].alg;
     }
 }
+
+/* Duplicate a lump of memory safely */
+int ossl_prov_memdup(const void *src, size_t src_len,
+                     unsigned char **dest, size_t *dest_len)
+{
+    if (src != NULL) {
+        if ((*dest = OPENSSL_memdup(src, src_len)) == NULL) {
+            ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+            return 0;
+        }
+        *dest_len = src_len;
+    } else {
+        *dest = NULL;
+        *dest_len = 0;
+    }
+    return 1;
+}
diff --git a/providers/implementations/kdfs/hkdf.c b/providers/implementations/kdfs/hkdf.c
index 667d5e9619..e014e32d5b 100644
--- a/providers/implementations/kdfs/hkdf.c
+++ b/providers/implementations/kdfs/hkdf.c
@@ -34,6 +34,7 @@
 #define HKDF_MAXBUF 2048
 
 static OSSL_FUNC_kdf_newctx_fn kdf_hkdf_new;
+static OSSL_FUNC_kdf_dupctx_fn kdf_hkdf_dup;
 static OSSL_FUNC_kdf_freectx_fn kdf_hkdf_free;
 static OSSL_FUNC_kdf_reset_fn kdf_hkdf_reset;
 static OSSL_FUNC_kdf_derive_fn kdf_hkdf_derive;
@@ -126,6 +127,36 @@ static void kdf_hkdf_reset(void *vctx)
     ctx->provctx = provctx;
 }
 
+static void *kdf_hkdf_dup(void *vctx)
+{
+    const KDF_HKDF *src = (const KDF_HKDF *)vctx;
+    KDF_HKDF *dest;
+
+    dest = kdf_hkdf_new(src->provctx);
+    if (dest != NULL) {
+        if (!ossl_prov_memdup(src->salt, src->salt_len, &dest->salt,
+                              &dest->salt_len)
+                || !ossl_prov_memdup(src->key, src->key_len,
+                                     &dest->key , &dest->key_len)
+                || !ossl_prov_memdup(src->prefix, src->prefix_len,
+                                     &dest->prefix, &dest->prefix_len)
+                || !ossl_prov_memdup(src->label, src->label_len,
+                                     &dest->label, &dest->label_len)
+                || !ossl_prov_memdup(src->data, src->data_len,
+                                     &dest->data, &dest->data_len)
+                || !ossl_prov_digest_copy(&dest->digest, &src->digest))
+            goto err;
+        memcpy(dest->info, src->info, sizeof(dest->info));
+        dest->info_len = src->info_len;
+        dest->mode = src->mode;
+    }
+    return dest;
+
+ err:
+    kdf_hkdf_free(dest);
+    return NULL;
+}
+
 static size_t kdf_hkdf_size(KDF_HKDF *ctx)
 {
     int sz;
@@ -313,6 +344,7 @@ static const OSSL_PARAM *kdf_hkdf_gettable_ctx_params(ossl_unused void *ctx,
 
 const OSSL_DISPATCH ossl_kdf_hkdf_functions[] = {
     { OSSL_FUNC_KDF_NEWCTX, (void(*)(void))kdf_hkdf_new },
+    { OSSL_FUNC_KDF_DUPCTX, (void(*)(void))kdf_hkdf_dup },
     { OSSL_FUNC_KDF_FREECTX, (void(*)(void))kdf_hkdf_free },
     { OSSL_FUNC_KDF_RESET, (void(*)(void))kdf_hkdf_reset },
     { OSSL_FUNC_KDF_DERIVE, (void(*)(void))kdf_hkdf_derive },
@@ -728,6 +760,7 @@ static const OSSL_PARAM *kdf_tls1_3_settable_ctx_params(ossl_unused void *ctx,
 
 const OSSL_DISPATCH ossl_kdf_tls1_3_kdf_functions[] = {
     { OSSL_FUNC_KDF_NEWCTX, (void(*)(void))kdf_hkdf_new },
+    { OSSL_FUNC_KDF_DUPCTX, (void(*)(void))kdf_hkdf_dup },
     { OSSL_FUNC_KDF_FREECTX, (void(*)(void))kdf_hkdf_free },
     { OSSL_FUNC_KDF_RESET, (void(*)(void))kdf_hkdf_reset },
     { OSSL_FUNC_KDF_DERIVE, (void(*)(void))kdf_tls1_3_derive },
diff --git a/providers/implementations/kdfs/kbkdf.c b/providers/implementations/kdfs/kbkdf.c
index 22fc7b86ad..fb5c1c022e 100644
--- a/providers/implementations/kdfs/kbkdf.c
+++ b/providers/implementations/kdfs/kbkdf.c
@@ -75,6 +75,7 @@ typedef struct {
 
 /* Definitions needed for typechecking. */
 static OSSL_FUNC_kdf_newctx_fn kbkdf_new;
+static OSSL_FUNC_kdf_newctx_fn kbkdf_dup;
 static OSSL_FUNC_kdf_freectx_fn kbkdf_free;
 static OSSL_FUNC_kdf_reset_fn kbkdf_reset;
 static OSSL_FUNC_kdf_derive_fn kbkdf_derive;
@@ -149,6 +150,36 @@ static void kbkdf_reset(void *vctx)
     init(ctx);
 }
 
+static void *kbkdf_dup(void *vctx)
+{
+    const KBKDF *src = (const KBKDF *)vctx;
+    KBKDF *dest;
+
+    dest = kbkdf_new(src->provctx);
+    if (dest != NULL) {
+        dest->ctx_init = EVP_MAC_CTX_dup(src->ctx_init);
+        if (dest->ctx_init == NULL
+                || !ossl_prov_memdup(src->ki, src->ki_len,
+                                     &dest->ki, &dest->ki_len)
+                || !ossl_prov_memdup(src->label, src->label_len,
+                                     &dest->label, &dest->label_len)
+                || !ossl_prov_memdup(src->context, src->context_len,
+                                     &dest->context, &dest->context_len)
+                || !ossl_prov_memdup(src->iv, src->iv_len,
+                                     &dest->iv, &dest->iv_len))
+            goto err;
+        dest->mode = src->mode;
+        dest->r = src->r;
+        dest->use_l = src->use_l;
+        dest->use_separator = src->use_separator;
+    }
+    return dest;
+
+ err:
+    kbkdf_free(dest);
+    return NULL;
+}
+
 /* SP800-108 section 5.1 or section 5.2 depending on mode. */
 static int derive(EVP_MAC_CTX *ctx_init, kbkdf_mode mode, unsigned char *iv,
                   size_t iv_len, unsigned char *label, size_t label_len,
@@ -405,6 +436,7 @@ static const OSSL_PARAM *kbkdf_gettable_ctx_params(ossl_unused void *ctx,
 
 const OSSL_DISPATCH ossl_kdf_kbkdf_functions[] = {
     { OSSL_FUNC_KDF_NEWCTX, (void(*)(void))kbkdf_new },
+    { OSSL_FUNC_KDF_DUPCTX, (void(*)(void))kbkdf_dup },
     { OSSL_FUNC_KDF_FREECTX, (void(*)(void))kbkdf_free },
     { OSSL_FUNC_KDF_RESET, (void(*)(void))kbkdf_reset },
     { OSSL_FUNC_KDF_DERIVE, (void(*)(void))kbkdf_derive },
diff --git a/providers/implementations/kdfs/krb5kdf.c b/providers/implementations/kdfs/krb5kdf.c
index 2c887f0eb9..1e86f9a6d7 100644
--- a/providers/implementations/kdfs/krb5kdf.c
+++ b/providers/implementations/kdfs/krb5kdf.c
@@ -34,6 +34,7 @@
 /* KRB5 KDF defined in RFC 3961, Section 5.1 */
 
 static OSSL_FUNC_kdf_newctx_fn krb5kdf_new;
+static OSSL_FUNC_kdf_dupctx_fn krb5kdf_dup;
 static OSSL_FUNC_kdf_freectx_fn krb5kdf_free;
 static OSSL_FUNC_kdf_reset_fn krb5kdf_reset;
 static OSSL_FUNC_kdf_derive_fn krb5kdf_derive;
@@ -102,6 +103,27 @@ static int krb5kdf_set_membuf(unsigned char **dst, size_t *dst_len,
     return OSSL_PARAM_get_octet_string(p, (void **)dst, 0, dst_len);
 }
 
+static void *krb5kdf_dup(void *vctx)
+{
+    const KRB5KDF_CTX *src = (const KRB5KDF_CTX *)vctx;
+    KRB5KDF_CTX *dest;
+
+    dest = krb5kdf_new(src->provctx);
+    if (dest != NULL) {
+        if (!ossl_prov_memdup(src->key, src->key_len,
+                              &dest->key, &dest->key_len)
+                || !ossl_prov_memdup(src->constant, src->constant_len,
+                                     &dest->constant , &dest->constant_len)
+                || !ossl_prov_cipher_copy(&dest->cipher, &src->cipher))
+            goto err;
+    }
+    return dest;
+
+ err:
+    krb5kdf_free(dest);
+    return NULL;
+}
+
 static int krb5kdf_derive(void *vctx, unsigned char *key, size_t keylen,
                           const OSSL_PARAM params[])
 {
@@ -198,6 +220,7 @@ static const OSSL_PARAM *krb5kdf_gettable_ctx_params(ossl_unused void *ctx,
 
 const OSSL_DISPATCH ossl_kdf_krb5kdf_functions[] = {
     { OSSL_FUNC_KDF_NEWCTX, (void(*)(void))krb5kdf_new },
+    { OSSL_FUNC_KDF_DUPCTX, (void(*)(void))krb5kdf_dup },
     { OSSL_FUNC_KDF_FREECTX, (void(*)(void))krb5kdf_free },
     { OSSL_FUNC_KDF_RESET, (void(*)(void))krb5kdf_reset },
     { OSSL_FUNC_KDF_DERIVE, (void(*)(void))krb5kdf_derive },
diff --git a/providers/implementations/kdfs/pbkdf1.c b/providers/implementations/kdfs/pbkdf1.c
index b9b164c4e2..986dd25ee3 100644
--- a/providers/implementations/kdfs/pbkdf1.c
+++ b/providers/implementations/kdfs/pbkdf1.c
@@ -24,6 +24,7 @@
 #include "prov/provider_util.h"
 
 static OSSL_FUNC_kdf_newctx_fn kdf_pbkdf1_new;
+static OSSL_FUNC_kdf_dupctx_fn kdf_pbkdf1_dup;
 static OSSL_FUNC_kdf_freectx_fn kdf_pbkdf1_free;
 static OSSL_FUNC_kdf_reset_fn kdf_pbkdf1_reset;
 static OSSL_FUNC_kdf_derive_fn kdf_pbkdf1_derive;
@@ -130,6 +131,28 @@ static void kdf_pbkdf1_reset(void *vctx)
     ctx->provctx = provctx;
 }
 
+static void *kdf_pbkdf1_dup(void *vctx)
+{
+    const KDF_PBKDF1 *src = (const KDF_PBKDF1 *)vctx;
+    KDF_PBKDF1 *dest;
+
+    dest = kdf_pbkdf1_new(src->provctx);
+    if (dest != NULL) {
+        if (!ossl_prov_memdup(src->salt, src->salt_len,
+                              &dest->salt, &dest->salt_len)
+                || !ossl_prov_memdup(src->pass, src->pass_len,
+                                     &dest->pass , &dest->pass_len)
+                || !ossl_prov_digest_copy(&dest->digest, &src->digest))
+            goto err;
+        dest->iter = src->iter;
+    }
+    return dest;
+
+ err:
+    kdf_pbkdf1_free(dest);
+    return NULL;
+}
+
 static int kdf_pbkdf1_set_membuf(unsigned char **buffer, size_t *buflen,
                              const OSSL_PARAM *p)
 {
@@ -231,6 +254,7 @@ static const OSSL_PARAM *kdf_pbkdf1_gettable_ctx_params(ossl_unused void *ctx,
 
 const OSSL_DISPATCH ossl_kdf_pbkdf1_functions[] = {
     { OSSL_FUNC_KDF_NEWCTX, (void(*)(void))kdf_pbkdf1_new },
+    { OSSL_FUNC_KDF_DUPCTX, (void(*)(void))kdf_pbkdf1_dup },
     { OSSL_FUNC_KDF_FREECTX, (void(*)(void))kdf_pbkdf1_free },
     { OSSL_FUNC_KDF_RESET, (void(*)(void))kdf_pbkdf1_reset },
     { OSSL_FUNC_KDF_DERIVE, (void(*)(void))kdf_pbkdf1_derive },
diff --git a/providers/implementations/kdfs/pbkdf2.c b/providers/implementations/kdfs/pbkdf2.c
index 4c829a6d1f..79578fb77d 100644
--- a/providers/implementations/kdfs/pbkdf2.c
+++ b/providers/implementations/kdfs/pbkdf2.c
@@ -37,6 +37,7 @@
 #define KDF_PBKDF2_MIN_SALT_LEN   (128 / 8)
 
 static OSSL_FUNC_kdf_newctx_fn kdf_pbkdf2_new;
+static OSSL_FUNC_kdf_dupctx_fn kdf_pbkdf2_dup;
 static OSSL_FUNC_kdf_freectx_fn kdf_pbkdf2_free;
 static OSSL_FUNC_kdf_reset_fn kdf_pbkdf2_reset;
 static OSSL_FUNC_kdf_derive_fn kdf_pbkdf2_derive;
@@ -63,7 +64,7 @@ typedef struct {
 
 static void kdf_pbkdf2_init(KDF_PBKDF2 *ctx);
 
-static void *kdf_pbkdf2_new(void *provctx)
+static void *kdf_pbkdf2_new_no_init(void *provctx)
 {
     KDF_PBKDF2 *ctx;
 
@@ -76,7 +77,15 @@ static void *kdf_pbkdf2_new(void *provctx)
         return NULL;
     }
     ctx->provctx = provctx;
-    kdf_pbkdf2_init(ctx);
+    return ctx;
+}
+
+static void *kdf_pbkdf2_new(void *provctx)
+{
+    KDF_PBKDF2 *ctx = kdf_pbkdf2_new_no_init(provctx);
+
+    if (ctx != NULL)
+        kdf_pbkdf2_init(ctx);
     return ctx;
 }
 
@@ -108,6 +117,30 @@ static void kdf_pbkdf2_reset(void *vctx)
     kdf_pbkdf2_init(ctx);
 }
 
+static void *kdf_pbkdf2_dup(void *vctx)
+{
+    const KDF_PBKDF2 *src = (const KDF_PBKDF2 *)vctx;
+    KDF_PBKDF2 *dest;
+
+    /* We need a new PBKDF2 object but uninitialised since we're filling it */
+    dest = kdf_pbkdf2_new_no_init(src->provctx);
+    if (dest != NULL) {
+        if (!ossl_prov_memdup(src->salt, src->salt_len,
+                              &dest->salt, &dest->salt_len)
+                || !ossl_prov_memdup(src->pass, src->pass_len,
+                                     &dest->pass, &dest->pass_len)
+                || !ossl_prov_digest_copy(&dest->digest, &src->digest))
+            goto err;
+        dest->iter = src->iter;
+        dest->lower_bound_checks = src->lower_bound_checks;
+    }
+    return dest;
+
+ err:
+    kdf_pbkdf2_free(dest);
+    return NULL;
+}
+
 static void kdf_pbkdf2_init(KDF_PBKDF2 *ctx)
 {
     OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END };
@@ -249,6 +282,7 @@ static const OSSL_PARAM *kdf_pbkdf2_gettable_ctx_params(ossl_unused void *ctx,
 
 const OSSL_DISPATCH ossl_kdf_pbkdf2_functions[] = {
     { OSSL_FUNC_KDF_NEWCTX, (void(*)(void))kdf_pbkdf2_new },
+    { OSSL_FUNC_KDF_DUPCTX, (void(*)(void))kdf_pbkdf2_dup },
     { OSSL_FUNC_KDF_FREECTX, (void(*)(void))kdf_pbkdf2_free },
     { OSSL_FUNC_KDF_RESET, (void(*)(void))kdf_pbkdf2_reset },
     { OSSL_FUNC_KDF_DERIVE, (void(*)(void))kdf_pbkdf2_derive },
diff --git a/providers/implementations/kdfs/pkcs12kdf.c b/providers/implementations/kdfs/pkcs12kdf.c
index a29a618ee8..5f8905de13 100644
--- a/providers/implementations/kdfs/pkcs12kdf.c
+++ b/providers/implementations/kdfs/pkcs12kdf.c
@@ -24,6 +24,7 @@
 #include "prov/provider_util.h"
 
 static OSSL_FUNC_kdf_newctx_fn kdf_pkcs12_new;
+static OSSL_FUNC_kdf_dupctx_fn kdf_pkcs12_dup;
 static OSSL_FUNC_kdf_freectx_fn kdf_pkcs12_free;
 static OSSL_FUNC_kdf_reset_fn kdf_pkcs12_reset;
 static OSSL_FUNC_kdf_derive_fn kdf_pkcs12_derive;
@@ -178,6 +179,29 @@ static void kdf_pkcs12_reset(void *vctx)
     ctx->provctx = provctx;
 }
 
+static void *kdf_pkcs12_dup(void *vctx)
+{
+    const KDF_PKCS12 *src = (const KDF_PKCS12 *)vctx;
+    KDF_PKCS12 *dest;
+
+    dest = kdf_pkcs12_new(src->provctx);
+    if (dest != NULL) {
+        if (!ossl_prov_memdup(src->salt, src->salt_len,
+                              &dest->salt, &dest->salt_len)
+                || !ossl_prov_memdup(src->pass, src->pass_len,
+                                     &dest->pass , &dest->pass_len)
+                || !ossl_prov_digest_copy(&dest->digest, &src->digest))
+            goto err;
+        dest->iter = src->iter;
+        dest->id = src->id;
+    }
+    return dest;
+
+ err:
+    kdf_pkcs12_free(dest);
+    return NULL;
+}
+
 static int pkcs12kdf_set_membuf(unsigned char **buffer, size_t *buflen,
                              const OSSL_PARAM *p)
 {
@@ -287,6 +311,7 @@ static const OSSL_PARAM *kdf_pkcs12_gettable_ctx_params(
 
 const OSSL_DISPATCH ossl_kdf_pkcs12_functions[] = {
     { OSSL_FUNC_KDF_NEWCTX, (void(*)(void))kdf_pkcs12_new },
+    { OSSL_FUNC_KDF_DUPCTX, (void(*)(void))kdf_pkcs12_dup },
     { OSSL_FUNC_KDF_FREECTX, (void(*)(void))kdf_pkcs12_free },
     { OSSL_FUNC_KDF_RESET, (void(*)(void))kdf_pkcs12_reset },
     { OSSL_FUNC_KDF_DERIVE, (void(*)(void))kdf_pkcs12_derive },
diff --git a/providers/implementations/kdfs/pvkkdf.c b/providers/implementations/kdfs/pvkkdf.c
index e953911c83..e96ff29b3b 100644
--- a/providers/implementations/kdfs/pvkkdf.c
+++ b/providers/implementations/kdfs/pvkkdf.c
@@ -17,6 +17,7 @@
 #include "prov/provider_util.h"
 
 static OSSL_FUNC_kdf_newctx_fn kdf_pvk_new;
+static OSSL_FUNC_kdf_dupctx_fn kdf_pvk_dup;
 static OSSL_FUNC_kdf_freectx_fn kdf_pvk_free;
 static OSSL_FUNC_kdf_reset_fn kdf_pvk_reset;
 static OSSL_FUNC_kdf_derive_fn kdf_pvk_derive;
@@ -71,6 +72,26 @@ static void kdf_pvk_free(void *vctx)
     }
 }
 
+static void *kdf_pvk_dup(void *vctx)
+{
+    const KDF_PVK *src = (const KDF_PVK *)vctx;
+    KDF_PVK *dest;
+
+    dest = kdf_pvk_new(src->provctx);
+    if (dest != NULL)
+        if (!ossl_prov_memdup(src->salt, src->salt_len,
+                              &dest->salt, &dest->salt_len)
+                || !ossl_prov_memdup(src->pass, src->pass_len,
+                                     &dest->pass , &dest->pass_len)
+                || !ossl_prov_digest_copy(&dest->digest, &src->digest))
+            goto err;
+    return dest;
+
+ err:
+    kdf_pvk_free(dest);
+    return NULL;
+}
+
 static void kdf_pvk_reset(void *vctx)
 {
     KDF_PVK *ctx = (KDF_PVK *)vctx;
@@ -216,6 +237,7 @@ static const OSSL_PARAM *kdf_pvk_gettable_ctx_params(ossl_unused void *ctx,
 
 const OSSL_DISPATCH ossl_kdf_pvk_functions[] = {
     { OSSL_FUNC_KDF_NEWCTX, (void(*)(void))kdf_pvk_new },
+    { OSSL_FUNC_KDF_DUPCTX, (void(*)(void))kdf_pvk_dup },
     { OSSL_FUNC_KDF_FREECTX, (void(*)(void))kdf_pvk_free },
     { OSSL_FUNC_KDF_RESET, (void(*)(void))kdf_pvk_reset },
     { OSSL_FUNC_KDF_DERIVE, (void(*)(void))kdf_pvk_derive },
diff --git a/providers/implementations/kdfs/scrypt.c b/providers/implementations/kdfs/scrypt.c
index a7072f785f..744f87847b 100644
--- a/providers/implementations/kdfs/scrypt.c
+++ b/providers/implementations/kdfs/scrypt.c
@@ -21,10 +21,12 @@
 #include "prov/provider_ctx.h"
 #include "prov/providercommon.h"
 #include "prov/implementations.h"
+#include "prov/provider_util.h"
 
 #ifndef OPENSSL_NO_SCRYPT
 
 static OSSL_FUNC_kdf_newctx_fn kdf_scrypt_new;
+static OSSL_FUNC_kdf_dupctx_fn kdf_scrypt_dup;
 static OSSL_FUNC_kdf_freectx_fn kdf_scrypt_free;
 static OSSL_FUNC_kdf_reset_fn kdf_scrypt_reset;
 static OSSL_FUNC_kdf_derive_fn kdf_scrypt_derive;
@@ -92,6 +94,38 @@ static void kdf_scrypt_reset(void *vctx)
     kdf_scrypt_init(ctx);
 }
 
+static void *kdf_scrypt_dup(void *vctx)
+{
+    const KDF_SCRYPT *src = (const KDF_SCRYPT *)vctx;
+    KDF_SCRYPT *dest;
+
+    dest = kdf_scrypt_new(src->libctx);
+    if (dest != NULL) {
+        if (src->sha256 != NULL && !EVP_MD_up_ref(src->sha256))
+            goto err;
+        if (src->propq != NULL) {
+            dest->propq = OPENSSL_strdup(src->propq);
+            if (dest->propq == NULL)
+                goto err;
+        }
+        if (!ossl_prov_memdup(src->salt, src->salt_len,
+                              &dest->salt, &dest->salt_len)
+                || !ossl_prov_memdup(src->pass, src->pass_len,
+                                     &dest->pass , &dest->pass_len))
+            goto err;
+        dest->N = src->N;
+        dest->r = src->r;
+        dest->p = src->p;
+        dest->maxmem_bytes = src->maxmem_bytes;
+        dest->sha256 = src->sha256;
+    }
+    return dest;
+
+ err:
+    kdf_scrypt_free(dest);
+    return NULL;
+}
+
 static void kdf_scrypt_init(KDF_SCRYPT *ctx)
 {
     /* Default values are the most conservative recommendation given in the
@@ -275,6 +309,7 @@ static const OSSL_PARAM *kdf_scrypt_gettable_ctx_params(ossl_unused void *ctx,
 
 const OSSL_DISPATCH ossl_kdf_scrypt_functions[] = {
     { OSSL_FUNC_KDF_NEWCTX, (void(*)(void))kdf_scrypt_new },
+    { OSSL_FUNC_KDF_DUPCTX, (void(*)(void))kdf_scrypt_dup },
     { OSSL_FUNC_KDF_FREECTX, (void(*)(void))kdf_scrypt_free },
     { OSSL_FUNC_KDF_RESET, (void(*)(void))kdf_scrypt_reset },
     { OSSL_FUNC_KDF_DERIVE, (void(*)(void))kdf_scrypt_derive },
diff --git a/providers/implementations/kdfs/sshkdf.c b/providers/implementations/kdfs/sshkdf.c
index be23c2143d..6c1cf7e615 100644
--- a/providers/implementations/kdfs/sshkdf.c
+++ b/providers/implementations/kdfs/sshkdf.c
@@ -24,6 +24,7 @@
 
 /* See RFC 4253, Section 7.2 */
 static OSSL_FUNC_kdf_newctx_fn kdf_sshkdf_new;
+static OSSL_FUNC_kdf_dupctx_fn kdf_sshkdf_dup;
 static OSSL_FUNC_kdf_freectx_fn kdf_sshkdf_free;
 static OSSL_FUNC_kdf_reset_fn kdf_sshkdf_reset;
 static OSSL_FUNC_kdf_derive_fn kdf_sshkdf_derive;
@@ -86,6 +87,30 @@ static void kdf_sshkdf_reset(void *vctx)
     ctx->provctx = provctx;
 }
 
+static void *kdf_sshkdf_dup(void *vctx)
+{
+    const KDF_SSHKDF *src = (const KDF_SSHKDF *)vctx;
+    KDF_SSHKDF *dest;
+
+    dest = kdf_sshkdf_new(src->provctx);
+    if (dest != NULL) {
+        if (!ossl_prov_memdup(src->key, src->key_len,
+                              &dest->key, &dest->key_len)
+                || !ossl_prov_memdup(src->xcghash, src->xcghash_len,
+                                     &dest->xcghash , &dest->xcghash_len)
+                || !ossl_prov_memdup(src->session_id, src->session_id_len,
+                                     &dest->session_id , &dest->session_id_len)
+                || !ossl_prov_digest_copy(&dest->digest, &src->digest))
+            goto err;
+        dest->type = src->type;
+    }
+    return dest;
+
+ err:
+    kdf_sshkdf_free(dest);
+    return NULL;
+}
+
 static int sshkdf_set_membuf(unsigned char **dst, size_t *dst_len,
                              const OSSL_PARAM *p)
 {
@@ -211,6 +236,7 @@ static const OSSL_PARAM *kdf_sshkdf_gettable_ctx_params(ossl_unused void *ctx,
 
 const OSSL_DISPATCH ossl_kdf_sshkdf_functions[] = {
     { OSSL_FUNC_KDF_NEWCTX, (void(*)(void))kdf_sshkdf_new },
+    { OSSL_FUNC_KDF_DUPCTX, (void(*)(void))kdf_sshkdf_dup },
     { OSSL_FUNC_KDF_FREECTX, (void(*)(void))kdf_sshkdf_free },
     { OSSL_FUNC_KDF_RESET, (void(*)(void))kdf_sshkdf_reset },
     { OSSL_FUNC_KDF_DERIVE, (void(*)(void))kdf_sshkdf_derive },
diff --git a/providers/implementations/kdfs/sskdf.c b/providers/implementations/kdfs/sskdf.c
index 297ddcdc2d..e7f1727ba5 100644
--- a/providers/implementations/kdfs/sskdf.c
+++ b/providers/implementations/kdfs/sskdf.c
@@ -72,6 +72,7 @@ typedef struct {
 static const unsigned char kmac_custom_str[] = { 0x4B, 0x44, 0x46 };
 
 static OSSL_FUNC_kdf_newctx_fn sskdf_new;
+static OSSL_FUNC_kdf_dupctx_fn sskdf_dup;
 static OSSL_FUNC_kdf_freectx_fn sskdf_free;
 static OSSL_FUNC_kdf_reset_fn sskdf_reset;
 static OSSL_FUNC_kdf_derive_fn sskdf_derive;
@@ -319,6 +320,35 @@ static void sskdf_free(void *vctx)
     }
 }
 
+static void *sskdf_dup(void *vctx)
+{
+    const KDF_SSKDF *src = (const KDF_SSKDF *)vctx;
+    KDF_SSKDF *dest;
+
+    dest = sskdf_new(src->provctx);
+    if (dest != NULL) {
+        if (src->macctx != NULL) {
+            dest->macctx = EVP_MAC_CTX_dup(src->macctx);
+            if (dest->macctx == NULL)
+                goto err;
+        }
+        if (!ossl_prov_memdup(src->info, src->info_len,
+                              &dest->info, &dest->info_len)
+                || !ossl_prov_memdup(src->salt, src->salt_len,
+                                     &dest->salt , &dest->salt_len)
+                || !ossl_prov_memdup(src->secret, src->secret_len,
+                                     &dest->secret, &dest->secret_len)
+                || !ossl_prov_digest_copy(&dest->digest, &src->digest))
+            goto err;
+        dest->out_len = src->out_len;
+    }
+    return dest;
+
+ err:
+    sskdf_free(dest);
+    return NULL;
+}
+
 static int sskdf_set_buffer(unsigned char **out, size_t *out_len,
                             const OSSL_PARAM *p)
 {
@@ -520,6 +550,7 @@ static const OSSL_PARAM *sskdf_gettable_ctx_params(ossl_unused void *ctx,
 
 const OSSL_DISPATCH ossl_kdf_sskdf_functions[] = {
     { OSSL_FUNC_KDF_NEWCTX, (void(*)(void))sskdf_new },
+    { OSSL_FUNC_KDF_DUPCTX, (void(*)(void))sskdf_dup },
     { OSSL_FUNC_KDF_FREECTX, (void(*)(void))sskdf_free },
     { OSSL_FUNC_KDF_RESET, (void(*)(void))sskdf_reset },
     { OSSL_FUNC_KDF_DERIVE, (void(*)(void))sskdf_derive },
@@ -534,6 +565,7 @@ const OSSL_DISPATCH ossl_kdf_sskdf_functions[] = {
 
 const OSSL_DISPATCH ossl_kdf_x963_kdf_functions[] = {
     { OSSL_FUNC_KDF_NEWCTX, (void(*)(void))sskdf_new },
+    { OSSL_FUNC_KDF_DUPCTX, (void(*)(void))sskdf_dup },
     { OSSL_FUNC_KDF_FREECTX, (void(*)(void))sskdf_free },
     { OSSL_FUNC_KDF_RESET, (void(*)(void))sskdf_reset },
     { OSSL_FUNC_KDF_DERIVE, (void(*)(void))x963kdf_derive },
diff --git a/providers/implementations/kdfs/tls1_prf.c b/providers/implementations/kdfs/tls1_prf.c
index 74a0f7e1f3..23436cf241 100644
--- a/providers/implementations/kdfs/tls1_prf.c
+++ b/providers/implementations/kdfs/tls1_prf.c
@@ -63,6 +63,7 @@
 #include "e_os.h"
 
 static OSSL_FUNC_kdf_newctx_fn kdf_tls1_prf_new;
+static OSSL_FUNC_kdf_dupctx_fn kdf_tls1_prf_dup;
 static OSSL_FUNC_kdf_freectx_fn kdf_tls1_prf_free;
 static OSSL_FUNC_kdf_reset_fn kdf_tls1_prf_reset;
 static OSSL_FUNC_kdf_derive_fn kdf_tls1_prf_derive;
@@ -131,6 +132,31 @@ static void kdf_tls1_prf_reset(void *vctx)
     ctx->provctx = provctx;
 }
 
+static void *kdf_tls1_prf_dup(void *vctx)
+{
+    const TLS1_PRF *src = (const TLS1_PRF *)vctx;
+    TLS1_PRF *dest;
+
+    dest = kdf_tls1_prf_new(src->provctx);
+    if (dest != NULL) {
+        if (src->P_hash != NULL
+                    && (dest->P_hash = EVP_MAC_CTX_dup(src->P_hash)) == NULL)
+            goto err;
+        if (src->P_sha1 != NULL
+                    && (dest->P_sha1 = EVP_MAC_CTX_dup(src->P_sha1)) == NULL)
+            goto err;
+        if (!ossl_prov_memdup(src->sec, src->seclen, &dest->sec, &dest->seclen))
+            goto err;
+        memcpy(dest->seed, src->seed, src->seedlen);
+        dest->seedlen = src->seedlen;
+    }
+    return dest;
+
+ err:
+    kdf_tls1_prf_free(dest);
+    return NULL;
+}
+
 static int kdf_tls1_prf_derive(void *vctx, unsigned char *key, size_t keylen,
                                const OSSL_PARAM params[])
 {
@@ -248,6 +274,7 @@ static const OSSL_PARAM *kdf_tls1_prf_gettable_ctx_params(
 
 const OSSL_DISPATCH ossl_kdf_tls1_prf_functions[] = {
     { OSSL_FUNC_KDF_NEWCTX, (void(*)(void))kdf_tls1_prf_new },
+    { OSSL_FUNC_KDF_DUPCTX, (void(*)(void))kdf_tls1_prf_dup },
     { OSSL_FUNC_KDF_FREECTX, (void(*)(void))kdf_tls1_prf_free },
     { OSSL_FUNC_KDF_RESET, (void(*)(void))kdf_tls1_prf_reset },
     { OSSL_FUNC_KDF_DERIVE, (void(*)(void))kdf_tls1_prf_derive },
diff --git a/providers/implementations/kdfs/x942kdf.c b/providers/implementations/kdfs/x942kdf.c
index c2cc94a192..4fb71835a2 100644
--- a/providers/implementations/kdfs/x942kdf.c
+++ b/providers/implementations/kdfs/x942kdf.c
@@ -26,6 +26,7 @@
 #define X942KDF_MAX_INLEN (1 << 30)
 
 static OSSL_FUNC_kdf_newctx_fn x942kdf_new;
+static OSSL_FUNC_kdf_dupctx_fn x942kdf_dup;
 static OSSL_FUNC_kdf_freectx_fn x942kdf_free;
 static OSSL_FUNC_kdf_reset_fn x942kdf_reset;
 static OSSL_FUNC_kdf_derive_fn x942kdf_derive;
@@ -368,6 +369,41 @@ static void x942kdf_free(void *vctx)
     }
 }
 
+static void *x942kdf_dup(void *vctx)
+{
+    const KDF_X942 *src = (const KDF_X942 *)vctx;
+    KDF_X942 *dest;
+
+    dest = x942kdf_new(src->provctx);
+    if (dest != NULL) {
+        if (!ossl_prov_memdup(src->secret, src->secret_len,
+                              &dest->secret , &dest->secret_len)
+                || !ossl_prov_memdup(src->acvpinfo, src->acvpinfo_len,
+                                     &dest->acvpinfo , &dest->acvpinfo_len)
+                || !ossl_prov_memdup(src->partyuinfo, src->partyuinfo_len,
+                                     &dest->partyuinfo , &dest->partyuinfo_len)
+                || !ossl_prov_memdup(src->partyvinfo, src->partyvinfo_len,
+                                     &dest->partyvinfo , &dest->partyvinfo_len)
+                || !ossl_prov_memdup(src->supp_pubinfo, src->supp_pubinfo_len,
+                                     &dest->supp_pubinfo,
+                                     &dest->supp_pubinfo_len)
+                || !ossl_prov_memdup(src->supp_privinfo, src->supp_privinfo_len,
+                                     &dest->supp_privinfo,
+                                     &dest->supp_privinfo_len)
+                || !ossl_prov_digest_copy(&dest->digest, &src->digest))
+            goto err;
+        dest->cek_oid = src->cek_oid;
+        dest->cek_oid_len = src->cek_oid_len;
+        dest->dkm_len = src->dkm_len;
+        dest->use_keybits = src->use_keybits;
+    }
+    return dest;
+
+ err:
+    x942kdf_free(dest);
+    return NULL;
+}
+
 static int x942kdf_set_buffer(unsigned char **out, size_t *out_len,
                               const OSSL_PARAM *p)
 {
@@ -579,6 +615,7 @@ static const OSSL_PARAM *x942kdf_gettable_ctx_params(ossl_unused void *ctx,
 
 const OSSL_DISPATCH ossl_kdf_x942_kdf_functions[] = {
     { OSSL_FUNC_KDF_NEWCTX, (void(*)(void))x942kdf_new },
+    { OSSL_FUNC_KDF_DUPCTX, (void(*)(void))x942kdf_dup },
     { OSSL_FUNC_KDF_FREECTX, (void(*)(void))x942kdf_free },
     { OSSL_FUNC_KDF_RESET, (void(*)(void))x942kdf_reset },
     { OSSL_FUNC_KDF_DERIVE, (void(*)(void))x942kdf_derive },
diff --git a/test/evp_pkey_provided_test.c b/test/evp_pkey_provided_test.c
index b4a77f8500..ebd09544df 100644
--- a/test/evp_pkey_provided_test.c
+++ b/test/evp_pkey_provided_test.c
@@ -1693,11 +1693,10 @@ static OSSL_PARAM *do_construct_hkdf_params(char *digest, char *key,
     return params;
 }
 
-/* Test that EVP_PKEY_CTX_dup() fails gracefully for a KDF */
-static int test_evp_pkey_ctx_dup_kdf_fail(void)
+static int test_evp_pkey_ctx_dup_kdf(void)
 {
     int ret = 0;
-    size_t len = 0;
+    size_t len = 0, dlen = 0;
     EVP_PKEY_CTX *pctx = NULL, *dctx = NULL;
     OSSL_PARAM *params = NULL;
 
@@ -1708,10 +1707,12 @@ static int test_evp_pkey_ctx_dup_kdf_fail(void)
         goto err;
     if (!TEST_int_eq(EVP_PKEY_derive_init_ex(pctx, params), 1))
         goto err;
-    if (!TEST_int_eq(EVP_PKEY_derive(pctx, NULL, &len), 1)
-        || !TEST_size_t_eq(len, SHA256_DIGEST_LENGTH))
+    if (!TEST_ptr(dctx = EVP_PKEY_CTX_dup(pctx)))
         goto err;
-    if (!TEST_ptr_null(dctx = EVP_PKEY_CTX_dup(pctx)))
+    if (!TEST_int_eq(EVP_PKEY_derive(pctx, NULL, &len), 1)
+        || !TEST_size_t_eq(len, SHA256_DIGEST_LENGTH)
+        || !TEST_int_eq(EVP_PKEY_derive(dctx, NULL, &dlen), 1)
+        || !TEST_size_t_eq(dlen, SHA256_DIGEST_LENGTH))
         goto err;
     ret = 1;
 err:
@@ -1731,7 +1732,7 @@ int setup_tests(void)
     if (!TEST_ptr(datadir = test_get_argument(0)))
         return 0;
 
-    ADD_TEST(test_evp_pkey_ctx_dup_kdf_fail);
+    ADD_TEST(test_evp_pkey_ctx_dup_kdf);
     ADD_TEST(test_evp_pkey_get_bn_param_large);
     ADD_TEST(test_fromdata_rsa);
 #ifndef OPENSSL_NO_DH
diff --git a/test/evp_test.c b/test/evp_test.c
index 34caec2c5d..5e106c64f0 100644
--- a/test/evp_test.c
+++ b/test/evp_test.c
@@ -2690,6 +2690,7 @@ static int kdf_test_run(EVP_TEST *t)
     KDF_DATA *expected = t->data;
     unsigned char *got = NULL;
     size_t got_len = expected->output_len;
+    EVP_KDF_CTX *ctx;
 
     if (!EVP_KDF_CTX_set_params(expected->ctx, expected->params)) {
         t->err = "KDF_CTRL_ERROR";
@@ -2699,6 +2700,10 @@ static int kdf_test_run(EVP_TEST *t)
         t->err = "INTERNAL_ERROR";
         goto err;
     }
+    if ((ctx = EVP_KDF_CTX_dup(expected->ctx)) != NULL) {
+        EVP_KDF_CTX_free(expected->ctx);
+        expected->ctx = ctx;
+    }
     if (EVP_KDF_derive(expected->ctx, got, got_len, NULL) <= 0) {
         t->err = "KDF_DERIVE_ERROR";
         goto err;


More information about the openssl-commits mailing list