[openssl] master update

Matt Caswell matt at openssl.org
Mon Aug 10 14:04:07 UTC 2020


The branch master has been updated
       via  711ae5d359d9fa89a9aef90ac197ba26c8de3330 (commit)
       via  cd0a4998a006f00d1e5c271cfcd8e1fd1f0b3c41 (commit)
       via  9d1ae03caaa690d96652a73888f091892ce115a2 (commit)
       via  74fc579a128f79dd3105b27de50d9e889b5bc9f3 (commit)
       via  1704752be6fc48ff2272c816df2c675e79aef4c0 (commit)
       via  194de849ccb269272b71994edf988dc1cdbafc0d (commit)
       via  05d2f72e79cdb1736681726dcd9a325491acf002 (commit)
       via  ac2d58c72b4dc4a8c74eef893000306bf78a30fd (commit)
      from  23f04372f45f8c9e3865c3bcfee3f77a9cc10673 (commit)


- Log -----------------------------------------------------------------
commit 711ae5d359d9fa89a9aef90ac197ba26c8de3330
Author: Matt Caswell <matt at openssl.org>
Date:   Fri Aug 7 12:23:07 2020 +0100

    Remove a TODO from evp_test
    
    Now that the EVP_PKEY KDF bridge is based on provider code a TODO item
    can be removed from evp_test.
    
    Reviewed-by: Paul Dale <paul.dale at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/12573)

commit cd0a4998a006f00d1e5c271cfcd8e1fd1f0b3c41
Author: Matt Caswell <matt at openssl.org>
Date:   Fri Aug 7 12:22:29 2020 +0100

    Extend the EVP_PKEY KDF to KDF provider bridge to the FIPS provider
    
    Reviewed-by: Paul Dale <paul.dale at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/12573)

commit 9d1ae03caaa690d96652a73888f091892ce115a2
Author: Matt Caswell <matt at openssl.org>
Date:   Tue Aug 4 14:43:11 2020 +0100

    Minimise the size of the macros in kdf_exch.c
    
    Use proper functions with just a macro wrapper around them to minimise
    the amount of code inside the macros. We also update the "settable"
    functions now that they take a "provctx" parameter.
    
    Reviewed-by: Paul Dale <paul.dale at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/12573)

commit 74fc579a128f79dd3105b27de50d9e889b5bc9f3
Author: Matt Caswell <matt at openssl.org>
Date:   Tue Aug 4 14:34:07 2020 +0100

    Update KDF documentation
    
    Following the previous commits where we moved the KDF bridge into
    provider side code, we need to update the documentation accordingly.
    
    Reviewed-by: Paul Dale <paul.dale at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/12573)

commit 1704752be6fc48ff2272c816df2c675e79aef4c0
Author: Matt Caswell <matt at openssl.org>
Date:   Fri Jul 31 16:43:04 2020 +0100

    Delete old KDF bridge EVP_PKEY_METHODS
    
    The KDF bridge is now done provider side so the old EVP_PKEY_METHODS for
    this are no longer required.
    
    Reviewed-by: Paul Dale <paul.dale at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/12573)

commit 194de849ccb269272b71994edf988dc1cdbafc0d
Author: Matt Caswell <matt at openssl.org>
Date:   Fri Jul 31 15:05:57 2020 +0100

    Extend the EVP_PKEY KDF to KDF provider bridge to also support Scrypt
    
    Reviewed-by: Paul Dale <paul.dale at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/12573)

commit 05d2f72e79cdb1736681726dcd9a325491acf002
Author: Matt Caswell <matt at openssl.org>
Date:   Mon Jul 20 18:06:55 2020 +0100

    Extend the EVP_PKEY KDF to KDF provider bridge to also support HKDF
    
    Reviewed-by: Paul Dale <paul.dale at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/12573)

commit ac2d58c72b4dc4a8c74eef893000306bf78a30fd
Author: Matt Caswell <matt at openssl.org>
Date:   Fri Jul 3 16:18:03 2020 +0100

    Implement a EVP_PKEY KDF to KDF provider bridge
    
    Some KDF implementations were available before the current EVP_KDF API.
    They were used via EVP_PKEY_derive. There exists a bridge between the old
    API and the EVP_KDF API however this bridge itself uses a legacy
    EVP_PKEY_METHOD. This commit implements a provider side bridge without
    having to use any legacy code.
    
    Reviewed-by: Paul Dale <paul.dale at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/12573)

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

Summary of changes:
 crypto/err/openssl.txt                             |   4 +
 crypto/evp/build.info                              |   2 +-
 crypto/evp/evp_err.c                               |   6 +
 crypto/evp/exchange.c                              |  26 +-
 crypto/evp/pkey_kdf.c                              | 413 ---------------------
 crypto/evp/pmeth_lib.c                             | 302 +++++++++++++--
 doc/man3/EVP_PKEY_CTX_set1_pbe_pass.pod            |   9 +-
 doc/man3/EVP_PKEY_CTX_set_hkdf_md.pod              |   7 +-
 doc/man3/EVP_PKEY_CTX_set_scrypt_N.pod             |   7 +-
 doc/man3/EVP_PKEY_CTX_set_tls1_prf_md.pod          |   7 +-
 include/crypto/evp.h                               |   3 -
 include/openssl/evperr.h                           |   4 +
 include/openssl/kdf.h                              |  64 ++--
 providers/defltprov.c                              |   6 +
 providers/fips/fipsprov.c                          |   4 +
 providers/implementations/exchange/build.info      |   3 +
 providers/implementations/exchange/kdf_exch.c      | 174 +++++++++
 .../implementations/include/prov/implementations.h |   4 +
 .../implementations/include/prov/kdfexchange.h     |  24 ++
 providers/implementations/kdfs/tls1_prf.c          |   3 -
 providers/implementations/keymgmt/build.info       |   3 +
 .../implementations/keymgmt/kdf_legacy_kmgmt.c     |  90 +++++
 test/evp_test.c                                    |  17 +-
 test/pkey_meth_kdf_test.c                          |  17 +-
 util/libcrypto.num                                 |  14 +
 25 files changed, 688 insertions(+), 525 deletions(-)
 delete mode 100644 crypto/evp/pkey_kdf.c
 create mode 100644 providers/implementations/exchange/kdf_exch.c
 create mode 100644 providers/implementations/include/prov/kdfexchange.h
 create mode 100644 providers/implementations/keymgmt/kdf_legacy_kmgmt.c

diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt
index af19ab26cd..cca13cc78f 100644
--- a/crypto/err/openssl.txt
+++ b/crypto/err/openssl.txt
@@ -2554,10 +2554,14 @@ EVP_R_INVALID_FIPS_MODE:168:invalid fips mode
 EVP_R_INVALID_IV_LENGTH:194:invalid iv length
 EVP_R_INVALID_KEY:163:invalid key
 EVP_R_INVALID_KEY_LENGTH:130:invalid key length
+EVP_R_INVALID_LENGTH:221:invalid length
 EVP_R_INVALID_NULL_ALGORITHM:218:invalid null algorithm
 EVP_R_INVALID_OPERATION:148:invalid operation
 EVP_R_INVALID_PROVIDER_FUNCTIONS:193:invalid provider functions
 EVP_R_INVALID_SALT_LENGTH:186:invalid salt length
+EVP_R_INVALID_SECRET_LENGTH:223:invalid secret length
+EVP_R_INVALID_SEED_LENGTH:220:invalid seed length
+EVP_R_INVALID_VALUE:222:invalid value
 EVP_R_KEYGEN_FAILURE:120:keygen failure
 EVP_R_KEYMGMT_EXPORT_FAILURE:205:keymgmt export failure
 EVP_R_KEY_SETUP_FAILED:180:key setup failed
diff --git a/crypto/evp/build.info b/crypto/evp/build.info
index ccd8357453..81c660051b 100644
--- a/crypto/evp/build.info
+++ b/crypto/evp/build.info
@@ -13,7 +13,7 @@ SOURCE[../../libcrypto]=$COMMON\
         bio_md.c bio_b64.c bio_enc.c evp_err.c e_null.c \
         c_allc.c c_alld.c bio_ok.c \
         evp_pkey.c evp_pbe.c p5_crpt.c p5_crpt2.c pbe_scrypt.c \
-        pkey_kdf.c pmeth_fn.c\
+        pmeth_fn.c\
         e_aes_cbc_hmac_sha1.c e_aes_cbc_hmac_sha256.c e_rc4_hmac_md5.c \
         e_chacha20_poly1305.c \
         pkey_mac.c \
diff --git a/crypto/evp/evp_err.c b/crypto/evp/evp_err.c
index d13cd05faa..09351f2434 100644
--- a/crypto/evp/evp_err.c
+++ b/crypto/evp/evp_err.c
@@ -90,6 +90,7 @@ static const ERR_STRING_DATA EVP_str_reasons[] = {
     {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INVALID_IV_LENGTH), "invalid iv length"},
     {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INVALID_KEY), "invalid key"},
     {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INVALID_KEY_LENGTH), "invalid key length"},
+    {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INVALID_LENGTH), "invalid length"},
     {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INVALID_NULL_ALGORITHM),
     "invalid null algorithm"},
     {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INVALID_OPERATION), "invalid operation"},
@@ -97,6 +98,11 @@ static const ERR_STRING_DATA EVP_str_reasons[] = {
     "invalid provider functions"},
     {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INVALID_SALT_LENGTH),
     "invalid salt length"},
+    {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INVALID_SECRET_LENGTH),
+    "invalid secret length"},
+    {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INVALID_SEED_LENGTH),
+    "invalid seed length"},
+    {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_INVALID_VALUE), "invalid value"},
     {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_KEYGEN_FAILURE), "keygen failure"},
     {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_KEYMGMT_EXPORT_FAILURE),
     "keymgmt export failure"},
diff --git a/crypto/evp/exchange.c b/crypto/evp/exchange.c
index 28e1f88db9..a47a0f0367 100644
--- a/crypto/evp/exchange.c
+++ b/crypto/evp/exchange.c
@@ -202,11 +202,31 @@ int EVP_PKEY_derive_init(EVP_PKEY_CTX *ctx)
 
     /*
      * Ensure that the key is provided, either natively, or as a cached export.
-     *  If not, go legacy
+     * If not, goto legacy
      */
     tmp_keymgmt = ctx->keymgmt;
-    provkey = evp_pkey_export_to_provider(ctx->pkey, ctx->libctx,
-                                          &tmp_keymgmt, ctx->propquery);
+    if (ctx->pkey == NULL) {
+        /*
+         * Some algorithms (e.g. legacy KDFs) don't have a pkey - so we create
+         * a blank one.
+         */
+        EVP_PKEY *pkey = EVP_PKEY_new();
+
+        if (pkey == NULL || !EVP_PKEY_set_type_by_keymgmt(pkey, tmp_keymgmt)) {
+            ERR_clear_last_mark();
+            EVP_PKEY_free(pkey);
+            ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
+            goto err;
+        }
+        provkey = pkey->keydata = evp_keymgmt_newdata(tmp_keymgmt);
+        if (provkey == NULL)
+            EVP_PKEY_free(pkey);
+        else
+            ctx->pkey = pkey;
+    } else {
+        provkey = evp_pkey_export_to_provider(ctx->pkey, ctx->libctx,
+                                            &tmp_keymgmt, ctx->propquery);
+    }
     if (provkey == NULL)
         goto legacy;
     if (!EVP_KEYMGMT_up_ref(tmp_keymgmt)) {
diff --git a/crypto/evp/pkey_kdf.c b/crypto/evp/pkey_kdf.c
deleted file mode 100644
index a2d25a925f..0000000000
--- a/crypto/evp/pkey_kdf.c
+++ /dev/null
@@ -1,413 +0,0 @@
-/*
- * Copyright 2018-2020 The OpenSSL Project Authors. All Rights Reserved.
- * Copyright (c) 2018, Oracle and/or its affiliates.  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 <string.h>
-#include <openssl/evp.h>
-#include <openssl/err.h>
-#include <openssl/buffer.h>
-#include <openssl/kdf.h>
-#include <openssl/core.h>
-#include <openssl/core_names.h>
-#include <openssl/params.h>
-#include "internal/numbers.h"
-#include "crypto/evp.h"
-
-#define MAX_PARAM   20
-
-typedef struct {
-    EVP_KDF_CTX *kctx;
-    /*
-     * EVP_PKEY implementations collect bits of certain data
-     */
-    BUF_MEM *collected_seed;
-    BUF_MEM *collected_info;
-} EVP_PKEY_KDF_CTX;
-
-static void pkey_kdf_free_collected(EVP_PKEY_KDF_CTX *pkctx)
-{
-    BUF_MEM_free(pkctx->collected_seed);
-    pkctx->collected_seed = NULL;
-    BUF_MEM_free(pkctx->collected_info);
-    pkctx->collected_info = NULL;
-}
-
-static int pkey_kdf_init(EVP_PKEY_CTX *ctx)
-{
-    EVP_PKEY_KDF_CTX *pkctx;
-    EVP_KDF_CTX *kctx;
-    const char *kdf_name = OBJ_nid2sn(ctx->pmeth->pkey_id);
-    EVP_KDF *kdf;
-
-    pkctx = OPENSSL_zalloc(sizeof(*pkctx));
-    if (pkctx == NULL)
-        return 0;
-
-    kdf = EVP_KDF_fetch(ctx->libctx, kdf_name, ctx->propquery);
-    kctx = EVP_KDF_CTX_new(kdf);
-    EVP_KDF_free(kdf);
-    if (kctx == NULL) {
-        OPENSSL_free(pkctx);
-        return 0;
-    }
-
-    pkctx->kctx = kctx;
-    ctx->data = pkctx;
-    return 1;
-}
-
-static void pkey_kdf_cleanup(EVP_PKEY_CTX *ctx)
-{
-    EVP_PKEY_KDF_CTX *pkctx = ctx->data;
-
-    EVP_KDF_CTX_free(pkctx->kctx);
-    pkey_kdf_free_collected(pkctx);
-    OPENSSL_free(pkctx);
-}
-
-static int collect(BUF_MEM **collector, void *data, size_t datalen)
-{
-    size_t i;
-
-    if (*collector == NULL)
-        *collector = BUF_MEM_new();
-    if (*collector == NULL) {
-        ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
-        return 0;
-    }
-
-    if (data != NULL && datalen > 0) {
-        i = (*collector)->length; /* BUF_MEM_grow() changes it! */
-
-        if (!BUF_MEM_grow(*collector, i + datalen))
-            return 0;
-        memcpy((*collector)->data + i, data, datalen);
-    }
-    return 1;
-}
-
-static int pkey_kdf_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
-{
-    EVP_PKEY_KDF_CTX *pkctx = ctx->data;
-    EVP_KDF_CTX *kctx = pkctx->kctx;
-    enum { T_OCTET_STRING, T_UINT64, T_DIGEST, T_INT } cmd;
-    const char *name, *mdname;
-    BUF_MEM **collector = NULL;
-    OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END };
-
-    switch (type) {
-    case EVP_PKEY_CTRL_PASS:
-        cmd = T_OCTET_STRING;
-        name = OSSL_KDF_PARAM_PASSWORD;
-        break;
-    case EVP_PKEY_CTRL_HKDF_SALT:
-    case EVP_PKEY_CTRL_SCRYPT_SALT:
-        cmd = T_OCTET_STRING;
-        name = OSSL_KDF_PARAM_SALT;
-        break;
-    case EVP_PKEY_CTRL_TLS_MD:
-    case EVP_PKEY_CTRL_HKDF_MD:
-        cmd = T_DIGEST;
-        name = OSSL_KDF_PARAM_DIGEST;
-        break;
-    case EVP_PKEY_CTRL_TLS_SECRET:
-        cmd = T_OCTET_STRING;
-        name = OSSL_KDF_PARAM_SECRET;
-        /*
-         * Perform the semantics described in
-         * EVP_PKEY_CTX_add1_tls1_prf_seed(3)
-         */
-        if (ctx->pmeth->pkey_id == NID_tls1_prf) {
-            BUF_MEM_free(pkctx->collected_seed);
-            pkctx->collected_seed = NULL;
-        }
-        break;
-    case EVP_PKEY_CTRL_TLS_SEED:
-        cmd = T_OCTET_STRING;
-        name = OSSL_KDF_PARAM_SEED;
-        collector = &pkctx->collected_seed;
-        break;
-    case EVP_PKEY_CTRL_HKDF_KEY:
-        cmd = T_OCTET_STRING;
-        name = OSSL_KDF_PARAM_KEY;
-        break;
-    case EVP_PKEY_CTRL_HKDF_INFO:
-        cmd = T_OCTET_STRING;
-        name = OSSL_KDF_PARAM_INFO;
-        collector = &pkctx->collected_info;
-        break;
-    case EVP_PKEY_CTRL_HKDF_MODE:
-        cmd = T_INT;
-        name = OSSL_KDF_PARAM_MODE;
-        break;
-    case EVP_PKEY_CTRL_SCRYPT_N:
-        cmd = T_UINT64;
-        name = OSSL_KDF_PARAM_SCRYPT_N;
-        break;
-    case EVP_PKEY_CTRL_SCRYPT_R:
-        cmd = T_UINT64; /* Range checking occurs on the provider side */
-        name = OSSL_KDF_PARAM_SCRYPT_R;
-        break;
-    case EVP_PKEY_CTRL_SCRYPT_P:
-        cmd = T_UINT64; /* Range checking occurs on the provider side */
-        name = OSSL_KDF_PARAM_SCRYPT_P;
-        break;
-    case EVP_PKEY_CTRL_SCRYPT_MAXMEM_BYTES:
-        cmd = T_UINT64;
-        name = OSSL_KDF_PARAM_SCRYPT_MAXMEM;
-        break;
-    default:
-        return -2;
-    }
-
-    if (collector != NULL) {
-        switch (cmd) {
-        case T_OCTET_STRING:
-            return collect(collector, p2, p1);
-        default:
-            OPENSSL_assert("You shouldn't be here");
-            break;
-        }
-        return 1;
-    }
-
-    switch (cmd) {
-    case T_OCTET_STRING:
-        params[0] =
-            OSSL_PARAM_construct_octet_string(name, (unsigned char *)p2,
-                                              (size_t)p1);
-        break;
-
-    case T_DIGEST:
-        mdname = EVP_MD_name((const EVP_MD *)p2);
-        params[0] = OSSL_PARAM_construct_utf8_string(name, (char *)mdname, 0);
-        break;
-
-        /*
-         * These are special because the helper macros pass a pointer to the
-         * stack, so a local copy is required.
-         */
-    case T_INT:
-        params[0] = OSSL_PARAM_construct_int(name, &p1);
-        break;
-
-    case T_UINT64:
-        params[0] = OSSL_PARAM_construct_uint64(name, (uint64_t *)p2);
-        break;
-    }
-
-    return EVP_KDF_CTX_set_params(kctx, params);
-}
-
-static int pkey_kdf_ctrl_str(EVP_PKEY_CTX *ctx, const char *type,
-                             const char *value)
-{
-    EVP_PKEY_KDF_CTX *pkctx = ctx->data;
-    EVP_KDF_CTX *kctx = pkctx->kctx;
-    const EVP_KDF *kdf = EVP_KDF_CTX_kdf(kctx);
-    BUF_MEM **collector = NULL;
-    const OSSL_PARAM *defs = EVP_KDF_settable_ctx_params(kdf);
-    OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END };
-    int ok = 0;
-
-    /* Deal with ctrl name aliasing */
-    if (strcmp(type, "md") == 0)
-        type = OSSL_KDF_PARAM_DIGEST;
-    /* scrypt uses 'N', params uses 'n' */
-    if (strcmp(type, "N") == 0)
-        type = OSSL_KDF_PARAM_SCRYPT_N;
-
-    if (!OSSL_PARAM_allocate_from_text(&params[0], defs, type,
-                                       value, strlen(value), NULL))
-        return 0;
-
-    /*
-     * We do the same special casing of seed and info here as in
-     * pkey_kdf_ctrl()
-     */
-    if (strcmp(params[0].key, OSSL_KDF_PARAM_SEED) == 0)
-        collector = &pkctx->collected_seed;
-    else if (strcmp(params[0].key, OSSL_KDF_PARAM_INFO) == 0)
-        collector = &pkctx->collected_info;
-
-    if (collector != NULL)
-        ok = collect(collector, params[0].data, params[0].data_size);
-    else
-        ok = EVP_KDF_CTX_set_params(kctx, params);
-    OPENSSL_free(params[0].data);
-    return ok;
-}
-
-static int pkey_kdf_derive_init(EVP_PKEY_CTX *ctx)
-{
-    EVP_PKEY_KDF_CTX *pkctx = ctx->data;
-
-    pkey_kdf_free_collected(pkctx);
-    if (pkctx->kctx != NULL)
-        EVP_KDF_reset(pkctx->kctx);
-    return 1;
-}
-
-/*
- * For fixed-output algorithms the keylen parameter is an "out" parameter
- * otherwise it is an "in" parameter.
- */
-static int pkey_kdf_derive(EVP_PKEY_CTX *ctx, unsigned char *key,
-                           size_t *keylen)
-{
-    EVP_PKEY_KDF_CTX *pkctx = ctx->data;
-    EVP_KDF_CTX *kctx = pkctx->kctx;
-    size_t outlen = EVP_KDF_size(kctx);
-    int r;
-
-    if (pkctx->collected_seed != NULL) {
-        OSSL_PARAM params[] = { OSSL_PARAM_END, OSSL_PARAM_END };
-
-        params[0] =
-            OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SEED,
-                                              pkctx->collected_seed->data,
-                                              pkctx->collected_seed->length);
-
-        r = EVP_KDF_CTX_set_params(kctx, params);
-        pkey_kdf_free_collected(pkctx);
-        if (!r)
-            return 0;
-    }
-    if (pkctx->collected_info != NULL) {
-        OSSL_PARAM params[] = { OSSL_PARAM_END, OSSL_PARAM_END };
-
-        params[0] =
-            OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_INFO,
-                                              pkctx->collected_info->data,
-                                              pkctx->collected_info->length);
-
-        r = EVP_KDF_CTX_set_params(kctx, params);
-        pkey_kdf_free_collected(pkctx);
-        if (!r)
-            return 0;
-    }
-    if (outlen == 0 || outlen == SIZE_MAX) {
-        /* Variable-output algorithm */
-        if (key == NULL)
-            return 0;
-    } else {
-        /* Fixed-output algorithm */
-        *keylen = outlen;
-        if (key == NULL)
-            return 1;
-    }
-    return EVP_KDF_derive(kctx, key, *keylen);
-}
-
-#ifndef OPENSSL_NO_SCRYPT
-static const EVP_PKEY_METHOD scrypt_pkey_meth = {
-    EVP_PKEY_SCRYPT,
-    0,
-    pkey_kdf_init,
-    0,
-    pkey_kdf_cleanup,
-
-    0, 0,
-    0, 0,
-
-    0,
-    0,
-
-    0,
-    0,
-
-    0, 0,
-
-    0, 0, 0, 0,
-
-    0, 0,
-
-    0, 0,
-
-    pkey_kdf_derive_init,
-    pkey_kdf_derive,
-    pkey_kdf_ctrl,
-    pkey_kdf_ctrl_str
-};
-
-const EVP_PKEY_METHOD *scrypt_pkey_method(void)
-{
-    return &scrypt_pkey_meth;
-}
-#endif
-
-static const EVP_PKEY_METHOD tls1_prf_pkey_meth = {
-    EVP_PKEY_TLS1_PRF,
-    0,
-    pkey_kdf_init,
-    0,
-    pkey_kdf_cleanup,
-
-    0, 0,
-    0, 0,
-
-    0,
-    0,
-
-    0,
-    0,
-
-    0, 0,
-
-    0, 0, 0, 0,
-
-    0, 0,
-
-    0, 0,
-
-    pkey_kdf_derive_init,
-    pkey_kdf_derive,
-    pkey_kdf_ctrl,
-    pkey_kdf_ctrl_str
-};
-
-const EVP_PKEY_METHOD *tls1_prf_pkey_method(void)
-{
-    return &tls1_prf_pkey_meth;
-}
-
-static const EVP_PKEY_METHOD hkdf_pkey_meth = {
-    EVP_PKEY_HKDF,
-    0,
-    pkey_kdf_init,
-    0,
-    pkey_kdf_cleanup,
-
-    0, 0,
-    0, 0,
-
-    0,
-    0,
-
-    0,
-    0,
-
-    0, 0,
-
-    0, 0, 0, 0,
-
-    0, 0,
-
-    0, 0,
-
-    pkey_kdf_derive_init,
-    pkey_kdf_derive,
-    pkey_kdf_ctrl,
-    pkey_kdf_ctrl_str
-};
-
-const EVP_PKEY_METHOD *hkdf_pkey_method(void)
-{
-    return &hkdf_pkey_meth;
-}
diff --git a/crypto/evp/pmeth_lib.c b/crypto/evp/pmeth_lib.c
index 17e73e05ba..6f2f52912b 100644
--- a/crypto/evp/pmeth_lib.c
+++ b/crypto/evp/pmeth_lib.c
@@ -21,6 +21,7 @@
 #include <openssl/core_names.h>
 #include <openssl/dh.h>
 #include <openssl/rsa.h>
+#include <openssl/kdf.h>
 #include "internal/cryptlib.h"
 #include "crypto/asn1.h"
 #include "crypto/evp.h"
@@ -61,15 +62,10 @@ static pmeth_fn standard_methods[] = {
 # ifndef OPENSSL_NO_DH
     dhx_pkey_method,
 # endif
-# ifndef OPENSSL_NO_SCRYPT
-    scrypt_pkey_method,
-# endif
-    tls1_prf_pkey_method,
 # ifndef OPENSSL_NO_EC
     ecx25519_pkey_method,
     ecx448_pkey_method,
 # endif
-    hkdf_pkey_method,
 # ifndef OPENSSL_NO_POLY1305
     poly1305_pkey_method,
 # endif
@@ -155,9 +151,6 @@ static int is_legacy_alg(int id, const char *keytype)
      */
     case EVP_PKEY_SM2:
     case EVP_PKEY_DHX:
-    case EVP_PKEY_SCRYPT:
-    case EVP_PKEY_TLS1_PRF:
-    case EVP_PKEY_HKDF:
     case EVP_PKEY_CMAC:
     case EVP_PKEY_HMAC:
     case EVP_PKEY_SIPHASH:
@@ -241,19 +234,25 @@ static EVP_PKEY_CTX *int_ctx_new(OPENSSL_CTX *libctx,
      * If an ENGINE handled this method look it up. Otherwise use internal
      * tables.
      */
-    if (e)
+    if (e != NULL) {
         pmeth = ENGINE_get_pkey_meth(e, id);
-    else
+        /*
+         * We are supposed to use an engine, so no point in looking for a
+         * provided implementation. If pmeth is NULL here we just fail.
+         */
+        if (pmeth == NULL) {
+            ENGINE_finish(e);
+            EVPerr(EVP_F_INT_CTX_NEW, EVP_R_UNSUPPORTED_ALGORITHM);
+            return NULL;
+        }
+    } else
 # endif
         pmeth = EVP_PKEY_meth_find(id);
+        /*
+         * if pmeth is NULL here we can keep trying to see if we have a provided
+         * implementation below.
+         */
 
-    if (pmeth == NULL) {
-# ifndef OPENSSL_NO_ENGINE
-        ENGINE_finish(e);
-# endif
-        EVPerr(EVP_F_INT_CTX_NEW, EVP_R_UNSUPPORTED_ALGORITHM);
-        return NULL;
-    }
     /* END legacy */
 #endif /* FIPS_MODULE */
  common:
@@ -759,7 +758,7 @@ int EVP_PKEY_CTX_set_dh_pad(EVP_PKEY_CTX *ctx, int pad)
 
 int EVP_PKEY_CTX_get_signature_md(EVP_PKEY_CTX *ctx, const EVP_MD **md)
 {
-    OSSL_PARAM sig_md_params[3], *p = sig_md_params;
+    OSSL_PARAM sig_md_params[2], *p = sig_md_params;
     /* 80 should be big enough */
     char name[80] = "";
     const EVP_MD *tmp;
@@ -778,7 +777,7 @@ int EVP_PKEY_CTX_get_signature_md(EVP_PKEY_CTX *ctx, const EVP_MD **md)
     *p++ = OSSL_PARAM_construct_utf8_string(OSSL_SIGNATURE_PARAM_DIGEST,
                                             name,
                                             sizeof(name));
-    *p++ = OSSL_PARAM_construct_end();
+    *p = OSSL_PARAM_construct_end();
 
     if (!EVP_PKEY_CTX_get_params(ctx, sig_md_params))
         return 0;
@@ -792,21 +791,22 @@ int EVP_PKEY_CTX_get_signature_md(EVP_PKEY_CTX *ctx, const EVP_MD **md)
     return 1;
 }
 
-int EVP_PKEY_CTX_set_signature_md(EVP_PKEY_CTX *ctx, const EVP_MD *md)
+static int evp_pkey_ctx_set_md(EVP_PKEY_CTX *ctx, const EVP_MD *md,
+                               int fallback, const char *param, int op,
+                               int ctrl)
 {
-    OSSL_PARAM sig_md_params[2], *p = sig_md_params;
+    OSSL_PARAM md_params[2], *p = md_params;
     const char *name;
 
-    if (ctx == NULL || !EVP_PKEY_CTX_IS_SIGNATURE_OP(ctx)) {
+    if (ctx == NULL || (ctx->operation & op) == 0) {
         ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
         /* Uses the same return values as EVP_PKEY_CTX_ctrl */
         return -2;
     }
 
     /* TODO(3.0): Remove this eventually when no more legacy */
-    if (ctx->op.sig.sigprovctx == NULL)
-        return EVP_PKEY_CTX_ctrl(ctx, -1, EVP_PKEY_OP_TYPE_SIG,
-                                 EVP_PKEY_CTRL_MD, 0, (void *)(md));
+    if (fallback)
+        return EVP_PKEY_CTX_ctrl(ctx, -1, op, ctrl, 0, (void *)(md));
 
     if (md == NULL) {
         name = "";
@@ -814,15 +814,218 @@ int EVP_PKEY_CTX_set_signature_md(EVP_PKEY_CTX *ctx, const EVP_MD *md)
         name = EVP_MD_name(md);
     }
 
-    *p++ = OSSL_PARAM_construct_utf8_string(OSSL_SIGNATURE_PARAM_DIGEST,
+    *p++ = OSSL_PARAM_construct_utf8_string(param,
                                             /*
                                              * Cast away the const. This is read
                                              * only so should be safe
                                              */
                                             (char *)name, 0);
-    *p++ = OSSL_PARAM_construct_end();
+    *p = OSSL_PARAM_construct_end();
+
+    return EVP_PKEY_CTX_set_params(ctx, md_params);
+}
 
-    return EVP_PKEY_CTX_set_params(ctx, sig_md_params);
+int EVP_PKEY_CTX_set_signature_md(EVP_PKEY_CTX *ctx, const EVP_MD *md)
+{
+    return evp_pkey_ctx_set_md(ctx, md, ctx->op.sig.sigprovctx == NULL,
+                               OSSL_SIGNATURE_PARAM_DIGEST,
+                               EVP_PKEY_OP_TYPE_SIG, EVP_PKEY_CTRL_MD);
+}
+
+int EVP_PKEY_CTX_set_tls1_prf_md(EVP_PKEY_CTX *ctx, const EVP_MD *md)
+{
+    return evp_pkey_ctx_set_md(ctx, md, ctx->op.kex.exchprovctx == NULL,
+                               OSSL_KDF_PARAM_DIGEST,
+                               EVP_PKEY_OP_DERIVE, EVP_PKEY_CTRL_TLS_MD);
+}
+
+static int evp_pkey_ctx_set1_octet_string(EVP_PKEY_CTX *ctx, int fallback,
+                                          const char *param, int op, int ctrl,
+                                          const unsigned char *data,
+                                          int datalen)
+{
+    OSSL_PARAM octet_string_params[2], *p = octet_string_params;
+
+    if (ctx == NULL || !EVP_PKEY_CTX_IS_DERIVE_OP(ctx)) {
+        ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
+        /* Uses the same return values as EVP_PKEY_CTX_ctrl */
+        return -2;
+    }
+
+    /* TODO(3.0): Remove this eventually when no more legacy */
+    if (fallback)
+        return EVP_PKEY_CTX_ctrl(ctx, -1, op, ctrl, datalen, (void *)(data));
+
+    if (datalen < 0) {
+        ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_LENGTH);
+        return 0;
+    }
+
+    *p++ = OSSL_PARAM_construct_octet_string(param,
+                                            /*
+                                             * Cast away the const. This is read
+                                             * only so should be safe
+                                             */
+                                            (unsigned char *)data,
+                                            (size_t)datalen);
+    *p = OSSL_PARAM_construct_end();
+
+    return EVP_PKEY_CTX_set_params(ctx, octet_string_params);
+}
+
+int EVP_PKEY_CTX_set1_tls1_prf_secret(EVP_PKEY_CTX *ctx,
+                                      const unsigned char *sec, int seclen)
+{
+    return evp_pkey_ctx_set1_octet_string(ctx, ctx->op.kex.exchprovctx == NULL,
+                                          OSSL_KDF_PARAM_SECRET,
+                                          EVP_PKEY_OP_DERIVE,
+                                          EVP_PKEY_CTRL_TLS_SECRET,
+                                          sec, seclen);
+}
+
+int EVP_PKEY_CTX_add1_tls1_prf_seed(EVP_PKEY_CTX *ctx,
+                                    const unsigned char *seed, int seedlen)
+{
+    return evp_pkey_ctx_set1_octet_string(ctx, ctx->op.kex.exchprovctx == NULL,
+                                          OSSL_KDF_PARAM_SEED,
+                                          EVP_PKEY_OP_DERIVE,
+                                          EVP_PKEY_CTRL_TLS_SEED,
+                                          seed, seedlen);
+}
+
+int EVP_PKEY_CTX_set_hkdf_md(EVP_PKEY_CTX *ctx, const EVP_MD *md)
+{
+    return evp_pkey_ctx_set_md(ctx, md, ctx->op.kex.exchprovctx == NULL,
+                               OSSL_KDF_PARAM_DIGEST,
+                               EVP_PKEY_OP_DERIVE, EVP_PKEY_CTRL_HKDF_MD);
+}
+
+int EVP_PKEY_CTX_set1_hkdf_salt(EVP_PKEY_CTX *ctx,
+                                const unsigned char *salt, int saltlen)
+{
+    return evp_pkey_ctx_set1_octet_string(ctx, ctx->op.kex.exchprovctx == NULL,
+                                          OSSL_KDF_PARAM_SALT,
+                                          EVP_PKEY_OP_DERIVE,
+                                          EVP_PKEY_CTRL_HKDF_SALT,
+                                          salt, saltlen);
+}
+
+int EVP_PKEY_CTX_set1_hkdf_key(EVP_PKEY_CTX *ctx,
+                                      const unsigned char *key, int keylen)
+{
+    return evp_pkey_ctx_set1_octet_string(ctx, ctx->op.kex.exchprovctx == NULL,
+                                          OSSL_KDF_PARAM_KEY,
+                                          EVP_PKEY_OP_DERIVE,
+                                          EVP_PKEY_CTRL_HKDF_KEY,
+                                          key, keylen);
+}
+
+int EVP_PKEY_CTX_add1_hkdf_info(EVP_PKEY_CTX *ctx,
+                                      const unsigned char *info, int infolen)
+{
+    return evp_pkey_ctx_set1_octet_string(ctx, ctx->op.kex.exchprovctx == NULL,
+                                          OSSL_KDF_PARAM_INFO,
+                                          EVP_PKEY_OP_DERIVE,
+                                          EVP_PKEY_CTRL_HKDF_INFO,
+                                          info, infolen);
+}
+
+int EVP_PKEY_CTX_hkdf_mode(EVP_PKEY_CTX *ctx, int mode)
+{
+    OSSL_PARAM int_params[2], *p = int_params;
+
+    if (ctx == NULL || !EVP_PKEY_CTX_IS_DERIVE_OP(ctx)) {
+        ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
+        /* Uses the same return values as EVP_PKEY_CTX_ctrl */
+        return -2;
+    }
+
+    /* TODO(3.0): Remove this eventually when no more legacy */
+    if (ctx->op.kex.exchprovctx == NULL)
+        return EVP_PKEY_CTX_ctrl(ctx, -1, EVP_PKEY_OP_DERIVE,
+                                 EVP_PKEY_CTRL_HKDF_MODE, mode, NULL);
+
+
+    if (mode < 0) {
+        ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_VALUE);
+        return 0;
+    }
+
+    *p++ = OSSL_PARAM_construct_int(OSSL_KDF_PARAM_MODE, &mode);
+    *p = OSSL_PARAM_construct_end();
+
+    return EVP_PKEY_CTX_set_params(ctx, int_params);
+}
+
+int EVP_PKEY_CTX_set1_pbe_pass(EVP_PKEY_CTX *ctx, const char *pass,
+                               int passlen)
+{
+    return evp_pkey_ctx_set1_octet_string(ctx, ctx->op.kex.exchprovctx == NULL,
+                                          OSSL_KDF_PARAM_PASSWORD,
+                                          EVP_PKEY_OP_DERIVE,
+                                          EVP_PKEY_CTRL_PASS,
+                                          (const unsigned char *)pass, passlen);
+}
+
+int EVP_PKEY_CTX_set1_scrypt_salt(EVP_PKEY_CTX *ctx,
+                                  const unsigned char *salt, int saltlen)
+{
+    return evp_pkey_ctx_set1_octet_string(ctx, ctx->op.kex.exchprovctx == NULL,
+                                          OSSL_KDF_PARAM_SALT,
+                                          EVP_PKEY_OP_DERIVE,
+                                          EVP_PKEY_CTRL_SCRYPT_SALT,
+                                          salt, saltlen);
+}
+
+static int evp_pkey_ctx_set_uint64(EVP_PKEY_CTX *ctx, const char *param,
+                                   int op, int ctrl, uint64_t val)
+{
+    OSSL_PARAM uint64_params[2], *p = uint64_params;
+
+    if (ctx == NULL || !EVP_PKEY_CTX_IS_DERIVE_OP(ctx)) {
+        ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
+        /* Uses the same return values as EVP_PKEY_CTX_ctrl */
+        return -2;
+    }
+
+    /* TODO(3.0): Remove this eventually when no more legacy */
+    if (ctx->op.kex.exchprovctx == NULL)
+        return EVP_PKEY_CTX_ctrl_uint64(ctx, -1, op, ctrl, val);
+
+    *p++ = OSSL_PARAM_construct_uint64(param, &val);
+    *p = OSSL_PARAM_construct_end();
+
+    return EVP_PKEY_CTX_set_params(ctx, uint64_params);
+}
+
+int EVP_PKEY_CTX_set_scrypt_N(EVP_PKEY_CTX *ctx, uint64_t n)
+{
+    return evp_pkey_ctx_set_uint64(ctx, OSSL_KDF_PARAM_SCRYPT_N,
+                                   EVP_PKEY_OP_DERIVE, EVP_PKEY_CTRL_SCRYPT_N,
+                                   n);
+}
+
+int EVP_PKEY_CTX_set_scrypt_r(EVP_PKEY_CTX *ctx, uint64_t r)
+{
+    return evp_pkey_ctx_set_uint64(ctx, OSSL_KDF_PARAM_SCRYPT_R,
+                                   EVP_PKEY_OP_DERIVE, EVP_PKEY_CTRL_SCRYPT_R,
+                                   r);
+}
+
+int EVP_PKEY_CTX_set_scrypt_p(EVP_PKEY_CTX *ctx, uint64_t p)
+{
+    return evp_pkey_ctx_set_uint64(ctx, OSSL_KDF_PARAM_SCRYPT_P,
+                                   EVP_PKEY_OP_DERIVE, EVP_PKEY_CTRL_SCRYPT_P,
+                                   p);
+}
+
+int EVP_PKEY_CTX_set_scrypt_maxmem_bytes(EVP_PKEY_CTX *ctx,
+                                         uint64_t maxmem_bytes)
+{
+    return evp_pkey_ctx_set_uint64(ctx, OSSL_KDF_PARAM_SCRYPT_MAXMEM,
+                                   EVP_PKEY_OP_DERIVE,
+                                   EVP_PKEY_CTRL_SCRYPT_MAXMEM_BYTES,
+                                   maxmem_bytes);
 }
 
 static int legacy_ctrl_to_param(EVP_PKEY_CTX *ctx, int keytype, int optype,
@@ -926,6 +1129,43 @@ static int legacy_ctrl_to_param(EVP_PKEY_CTX *ctx, int keytype, int optype,
      * or for generic controls that are the same across multiple key types.
      */
     if (keytype == -1) {
+        if (optype == EVP_PKEY_OP_DERIVE) {
+            switch (cmd) {
+            /* TLS1-PRF */
+            case EVP_PKEY_CTRL_TLS_MD:
+                return EVP_PKEY_CTX_set_tls1_prf_md(ctx, p2);
+            case EVP_PKEY_CTRL_TLS_SECRET:
+                return EVP_PKEY_CTX_set1_tls1_prf_secret(ctx, p2, p1);
+            case EVP_PKEY_CTRL_TLS_SEED:
+                return EVP_PKEY_CTX_add1_tls1_prf_seed(ctx, p2, p1);
+
+            /* HKDF */
+            case EVP_PKEY_CTRL_HKDF_MD:
+                return EVP_PKEY_CTX_set_hkdf_md(ctx, p2);
+            case EVP_PKEY_CTRL_HKDF_SALT :
+                return EVP_PKEY_CTX_set1_hkdf_salt(ctx, p2, p1);
+            case EVP_PKEY_CTRL_HKDF_KEY:
+                return EVP_PKEY_CTX_set1_hkdf_key(ctx, p2, p1);
+            case EVP_PKEY_CTRL_HKDF_INFO:
+                return EVP_PKEY_CTX_add1_hkdf_info(ctx, p2, p1);
+            case EVP_PKEY_CTRL_HKDF_MODE:
+                return EVP_PKEY_CTX_hkdf_mode(ctx, p1);
+
+            /* Scrypt */
+            case EVP_PKEY_CTRL_PASS:
+                return EVP_PKEY_CTX_set1_pbe_pass(ctx, p2, p1);
+            case EVP_PKEY_CTRL_SCRYPT_SALT:
+                return EVP_PKEY_CTX_set1_scrypt_salt(ctx, p2, p1);
+            case EVP_PKEY_CTRL_SCRYPT_N:
+                return EVP_PKEY_CTX_set_scrypt_N(ctx, p1);
+            case EVP_PKEY_CTRL_SCRYPT_R:
+                return EVP_PKEY_CTX_set_scrypt_r(ctx, p1);
+            case EVP_PKEY_CTRL_SCRYPT_P:
+                return EVP_PKEY_CTX_set_scrypt_p(ctx, p1);
+            case EVP_PKEY_CTRL_SCRYPT_MAXMEM_BYTES:
+                return EVP_PKEY_CTX_set_scrypt_maxmem_bytes(ctx, p1);
+            }
+        }
         switch (cmd) {
         case EVP_PKEY_CTRL_MD:
             return EVP_PKEY_CTX_set_signature_md(ctx, p2);
@@ -1034,7 +1274,9 @@ static int legacy_ctrl_str_to_param(EVP_PKEY_CTX *ctx, const char *name,
     }
 # endif
 
-    if (strcmp(name, "rsa_padding_mode") == 0)
+    if (strcmp(name, "md") == 0)
+        name = OSSL_ALG_PARAM_DIGEST;
+    else if (strcmp(name, "rsa_padding_mode") == 0)
         name = OSSL_ASYM_CIPHER_PARAM_PAD_MODE;
     else if (strcmp(name, "rsa_mgf1_md") == 0)
         name = OSSL_ASYM_CIPHER_PARAM_MGF1_DIGEST;
@@ -1090,6 +1332,8 @@ static int legacy_ctrl_str_to_param(EVP_PKEY_CTX *ctx, const char *name,
     else if (strcmp(name, "ecdh_kdf_md") == 0)
         name = OSSL_EXCHANGE_PARAM_KDF_DIGEST;
 # endif
+    else if (strcmp(name, "N") == 0)
+        name = OSSL_KDF_PARAM_SCRYPT_N;
 
     {
         /*
diff --git a/doc/man3/EVP_PKEY_CTX_set1_pbe_pass.pod b/doc/man3/EVP_PKEY_CTX_set1_pbe_pass.pod
index 959a95f810..d0c521adbf 100644
--- a/doc/man3/EVP_PKEY_CTX_set1_pbe_pass.pod
+++ b/doc/man3/EVP_PKEY_CTX_set1_pbe_pass.pod
@@ -42,10 +42,6 @@ supported by the algorithms that use them.
 
 =end comment
 
-=head1 NOTES
-
-All these functions are implemented as macros.
-
 =head1 RETURN VALUES
 
 All these functions return 1 for success and 0 or a negative value for failure.
@@ -58,6 +54,11 @@ L<EVP_PKEY_CTX_new(3)>,
 L<EVP_PKEY_CTX_ctrl_str(3)>,
 L<EVP_PKEY_derive(3)>
 
+=head1 HISTORY
+
+EVP_PKEY_CTX_set1_pbe_pass() was converted from a macro to a function in
+OpenSSL 3.0.
+
 =head1 COPYRIGHT
 
 Copyright 2018 The OpenSSL Project Authors. All Rights Reserved.
diff --git a/doc/man3/EVP_PKEY_CTX_set_hkdf_md.pod b/doc/man3/EVP_PKEY_CTX_set_hkdf_md.pod
index 7fc833e056..6fcecbe4f2 100644
--- a/doc/man3/EVP_PKEY_CTX_set_hkdf_md.pod
+++ b/doc/man3/EVP_PKEY_CTX_set_hkdf_md.pod
@@ -95,8 +95,6 @@ string which is converted to binary.
 
 =head1 NOTES
 
-All these functions are implemented as macros.
-
 A context for HKDF can be obtained by calling:
 
  EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_HKDF, NULL);
@@ -154,6 +152,11 @@ L<EVP_PKEY_CTX_new(3)>,
 L<EVP_PKEY_CTX_ctrl_str(3)>,
 L<EVP_PKEY_derive(3)>
 
+=head1 HISTORY
+
+All of the functions described here were converted from macros to functions in
+OpenSSL 3.0.
+
 =head1 COPYRIGHT
 
 Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved.
diff --git a/doc/man3/EVP_PKEY_CTX_set_scrypt_N.pod b/doc/man3/EVP_PKEY_CTX_set_scrypt_N.pod
index 70d5eb6d0c..1057f41e6a 100644
--- a/doc/man3/EVP_PKEY_CTX_set_scrypt_N.pod
+++ b/doc/man3/EVP_PKEY_CTX_set_scrypt_N.pod
@@ -61,8 +61,6 @@ The scrypt KDF also uses EVP_PKEY_CTX_set1_pbe_pass() as well as
 the value from the string controls "pass" and "hexpass".
 See L<EVP_PKEY_CTX_set1_pbe_pass(3)>.
 
-All the functions described here are implemented as macros.
-
 =head1 RETURN VALUES
 
 All these functions return 1 for success and 0 or a negative value for
@@ -77,6 +75,11 @@ L<EVP_PKEY_CTX_new(3)>,
 L<EVP_PKEY_CTX_ctrl_str(3)>,
 L<EVP_PKEY_derive(3)>
 
+=head1 HISTORY
+
+All of the functions described here were converted from macros to functions in
+OpenSSL 3.0.
+
 =head1 COPYRIGHT
 
 Copyright 2017-2020 The OpenSSL Project Authors. All Rights Reserved.
diff --git a/doc/man3/EVP_PKEY_CTX_set_tls1_prf_md.pod b/doc/man3/EVP_PKEY_CTX_set_tls1_prf_md.pod
index e0629accc7..4cc79886bc 100644
--- a/doc/man3/EVP_PKEY_CTX_set_tls1_prf_md.pod
+++ b/doc/man3/EVP_PKEY_CTX_set_tls1_prf_md.pod
@@ -46,8 +46,6 @@ which is converted to binary.
 
 =head1 NOTES
 
-All these functions are implemented as macros.
-
 A context for the TLS PRF can be obtained by calling:
 
  EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_TLS1_PRF, NULL);
@@ -97,6 +95,11 @@ L<EVP_PKEY_CTX_new(3)>,
 L<EVP_PKEY_CTX_ctrl_str(3)>,
 L<EVP_PKEY_derive(3)>
 
+=head1 HISTORY
+
+All of the functions described here were converted from macros to functions in
+OpenSSL 3.0.
+
 =head1 COPYRIGHT
 
 Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
diff --git a/include/crypto/evp.h b/include/crypto/evp.h
index 07e9ef4bb3..9ded000c10 100644
--- a/include/crypto/evp.h
+++ b/include/crypto/evp.h
@@ -144,9 +144,6 @@ const EVP_PKEY_METHOD *ed448_pkey_method(void);
 const EVP_PKEY_METHOD *hmac_pkey_method(void);
 const EVP_PKEY_METHOD *rsa_pkey_method(void);
 const EVP_PKEY_METHOD *rsa_pss_pkey_method(void);
-const EVP_PKEY_METHOD *scrypt_pkey_method(void);
-const EVP_PKEY_METHOD *tls1_prf_pkey_method(void);
-const EVP_PKEY_METHOD *hkdf_pkey_method(void);
 const EVP_PKEY_METHOD *poly1305_pkey_method(void);
 const EVP_PKEY_METHOD *siphash_pkey_method(void);
 
diff --git a/include/openssl/evperr.h b/include/openssl/evperr.h
index 5aa002815a..ef74c10243 100644
--- a/include/openssl/evperr.h
+++ b/include/openssl/evperr.h
@@ -206,10 +206,14 @@ int ERR_load_EVP_strings(void);
 # define EVP_R_INVALID_IV_LENGTH                          194
 # define EVP_R_INVALID_KEY                                163
 # define EVP_R_INVALID_KEY_LENGTH                         130
+# define EVP_R_INVALID_LENGTH                             221
 # define EVP_R_INVALID_NULL_ALGORITHM                     218
 # define EVP_R_INVALID_OPERATION                          148
 # define EVP_R_INVALID_PROVIDER_FUNCTIONS                 193
 # define EVP_R_INVALID_SALT_LENGTH                        186
+# define EVP_R_INVALID_SECRET_LENGTH                      223
+# define EVP_R_INVALID_SEED_LENGTH                        220
+# define EVP_R_INVALID_VALUE                              222
 # define EVP_R_KEYGEN_FAILURE                             120
 # define EVP_R_KEYMGMT_EXPORT_FAILURE                     205
 # define EVP_R_KEY_SETUP_FAILED                           180
diff --git a/include/openssl/kdf.h b/include/openssl/kdf.h
index b3dee525dc..b761113956 100644
--- a/include/openssl/kdf.h
+++ b/include/openssl/kdf.h
@@ -115,61 +115,41 @@ void EVP_KDF_names_do_all(const EVP_KDF *kdf,
 # define EVP_PKEY_HKDEF_MODE_EXPAND_ONLY        \
             EVP_KDF_HKDF_MODE_EXPAND_ONLY
 
-# define EVP_PKEY_CTX_set_tls1_prf_md(pctx, md) \
-            EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_DERIVE, \
-                              EVP_PKEY_CTRL_TLS_MD, 0, (void *)(md))
+int EVP_PKEY_CTX_set_tls1_prf_md(EVP_PKEY_CTX *ctx, const EVP_MD *md);
 
-# define EVP_PKEY_CTX_set1_tls1_prf_secret(pctx, sec, seclen) \
-            EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_DERIVE, \
-                              EVP_PKEY_CTRL_TLS_SECRET, seclen, (void *)(sec))
+int EVP_PKEY_CTX_set1_tls1_prf_secret(EVP_PKEY_CTX *pctx,
+                                      const unsigned char *sec, int seclen);
 
-# define EVP_PKEY_CTX_add1_tls1_prf_seed(pctx, seed, seedlen) \
-            EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_DERIVE, \
-                              EVP_PKEY_CTRL_TLS_SEED, seedlen, (void *)(seed))
+int EVP_PKEY_CTX_add1_tls1_prf_seed(EVP_PKEY_CTX *pctx,
+                                    const unsigned char *seed, int seedlen);
 
-# define EVP_PKEY_CTX_set_hkdf_md(pctx, md) \
-            EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_DERIVE, \
-                              EVP_PKEY_CTRL_HKDF_MD, 0, (void *)(md))
+int EVP_PKEY_CTX_set_hkdf_md(EVP_PKEY_CTX *ctx, const EVP_MD *md);
 
-# define EVP_PKEY_CTX_set1_hkdf_salt(pctx, salt, saltlen) \
-            EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_DERIVE, \
-                              EVP_PKEY_CTRL_HKDF_SALT, saltlen, (void *)(salt))
+int EVP_PKEY_CTX_set1_hkdf_salt(EVP_PKEY_CTX *ctx,
+                                const unsigned char *salt, int saltlen);
 
-# define EVP_PKEY_CTX_set1_hkdf_key(pctx, key, keylen) \
-            EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_DERIVE, \
-                              EVP_PKEY_CTRL_HKDF_KEY, keylen, (void *)(key))
+int EVP_PKEY_CTX_set1_hkdf_key(EVP_PKEY_CTX *ctx,
+                               const unsigned char *key, int keylen);
 
-# define EVP_PKEY_CTX_add1_hkdf_info(pctx, info, infolen) \
-            EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_DERIVE, \
-                              EVP_PKEY_CTRL_HKDF_INFO, infolen, (void *)(info))
+int EVP_PKEY_CTX_add1_hkdf_info(EVP_PKEY_CTX *ctx,
+                                const unsigned char *info, int infolen);
 
-# define EVP_PKEY_CTX_hkdf_mode(pctx, mode) \
-            EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_DERIVE, \
-                              EVP_PKEY_CTRL_HKDF_MODE, mode, NULL)
+int EVP_PKEY_CTX_hkdf_mode(EVP_PKEY_CTX *ctx, int mode);
 
-# define EVP_PKEY_CTX_set1_pbe_pass(pctx, pass, passlen) \
-            EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_DERIVE, \
-                            EVP_PKEY_CTRL_PASS, passlen, (void *)(pass))
+int EVP_PKEY_CTX_set1_pbe_pass(EVP_PKEY_CTX *ctx, const char *pass,
+                               int passlen);
 
-# define EVP_PKEY_CTX_set1_scrypt_salt(pctx, salt, saltlen) \
-            EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_DERIVE, \
-                            EVP_PKEY_CTRL_SCRYPT_SALT, saltlen, (void *)(salt))
+int EVP_PKEY_CTX_set1_scrypt_salt(EVP_PKEY_CTX *ctx,
+                                  const unsigned char *salt, int saltlen);
 
-# define EVP_PKEY_CTX_set_scrypt_N(pctx, n) \
-            EVP_PKEY_CTX_ctrl_uint64(pctx, -1, EVP_PKEY_OP_DERIVE, \
-                            EVP_PKEY_CTRL_SCRYPT_N, n)
+int EVP_PKEY_CTX_set_scrypt_N(EVP_PKEY_CTX *ctx, uint64_t n);
 
-# define EVP_PKEY_CTX_set_scrypt_r(pctx, r) \
-            EVP_PKEY_CTX_ctrl_uint64(pctx, -1, EVP_PKEY_OP_DERIVE, \
-                            EVP_PKEY_CTRL_SCRYPT_R, r)
+int EVP_PKEY_CTX_set_scrypt_r(EVP_PKEY_CTX *ctx, uint64_t r);
 
-# define EVP_PKEY_CTX_set_scrypt_p(pctx, p) \
-            EVP_PKEY_CTX_ctrl_uint64(pctx, -1, EVP_PKEY_OP_DERIVE, \
-                            EVP_PKEY_CTRL_SCRYPT_P, p)
+int EVP_PKEY_CTX_set_scrypt_p(EVP_PKEY_CTX *ctx, uint64_t p);
 
-# define EVP_PKEY_CTX_set_scrypt_maxmem_bytes(pctx, maxmem_bytes) \
-            EVP_PKEY_CTX_ctrl_uint64(pctx, -1, EVP_PKEY_OP_DERIVE, \
-                            EVP_PKEY_CTRL_SCRYPT_MAXMEM_BYTES, maxmem_bytes)
+int EVP_PKEY_CTX_set_scrypt_maxmem_bytes(EVP_PKEY_CTX *ctx,
+                                         uint64_t maxmem_bytes);
 
 
 # ifdef __cplusplus
diff --git a/providers/defltprov.c b/providers/defltprov.c
index 4ab39e6531..00d1800c24 100644
--- a/providers/defltprov.c
+++ b/providers/defltprov.c
@@ -339,6 +339,9 @@ static const OSSL_ALGORITHM deflt_keyexch[] = {
     { "X25519", "provider=default", x25519_keyexch_functions },
     { "X448", "provider=default", x448_keyexch_functions },
 #endif
+    { "TLS1-PRF", "provider=default", kdf_tls1_prf_keyexch_functions },
+    { "HKDF", "provider=default", kdf_hkdf_keyexch_functions },
+    { "SCRYPT:id-scrypt", "provider=default", kdf_scrypt_keyexch_functions },
     { NULL, NULL, NULL }
 };
 
@@ -384,6 +387,9 @@ static const OSSL_ALGORITHM deflt_keymgmt[] = {
     { "ED25519", "provider=default", ed25519_keymgmt_functions },
     { "ED448", "provider=default", ed448_keymgmt_functions },
 #endif
+    { "TLS1-PRF", "provider=default", kdf_keymgmt_functions },
+    { "HKDF", "provider=default", kdf_keymgmt_functions },
+    { "SCRYPT:id-scrypt", "provider=default", kdf_keymgmt_functions },
     { NULL, NULL, NULL }
 };
 
diff --git a/providers/fips/fipsprov.c b/providers/fips/fipsprov.c
index e39c306e48..4711a99b01 100644
--- a/providers/fips/fipsprov.c
+++ b/providers/fips/fipsprov.c
@@ -421,6 +421,8 @@ static const OSSL_ALGORITHM fips_keyexch[] = {
     { "X25519", FIPS_DEFAULT_PROPERTIES, x25519_keyexch_functions },
     { "X448", FIPS_DEFAULT_PROPERTIES, x448_keyexch_functions },
 #endif
+    { "TLS1-PRF", FIPS_DEFAULT_PROPERTIES, kdf_tls1_prf_keyexch_functions },
+    { "HKDF", FIPS_DEFAULT_PROPERTIES, kdf_hkdf_keyexch_functions },
     { NULL, NULL, NULL }
 };
 
@@ -459,6 +461,8 @@ static const OSSL_ALGORITHM fips_keymgmt[] = {
     { "ED25519", FIPS_DEFAULT_PROPERTIES, ed25519_keymgmt_functions },
     { "ED448", FIPS_DEFAULT_PROPERTIES, ed448_keymgmt_functions },
 #endif
+    { "TLS1-PRF", FIPS_DEFAULT_PROPERTIES, kdf_keymgmt_functions },
+    { "HKDF", FIPS_DEFAULT_PROPERTIES, kdf_keymgmt_functions },
     { NULL, NULL, NULL }
 };
 
diff --git a/providers/implementations/exchange/build.info b/providers/implementations/exchange/build.info
index 3127f9a3e7..92932b9d28 100644
--- a/providers/implementations/exchange/build.info
+++ b/providers/implementations/exchange/build.info
@@ -4,6 +4,7 @@
 $DH_GOAL=../../libimplementations.a
 $ECX_GOAL=../../libimplementations.a
 $ECDH_GOAL=../../libimplementations.a
+$KDF_GOAL=../../libimplementations.a
 
 IF[{- !$disabled{dh} -}]
   SOURCE[$DH_GOAL]=dh_exch.c
@@ -25,3 +26,5 @@ IF[{- !$disabled{ec} -}]
   SOURCE[../../libfips.a]=ecdh_exch.c
   SOURCE[../../libnonfips.a]=ecdh_exch.c
 ENDIF
+
+SOURCE[$KDF_GOAL]=kdf_exch.c
diff --git a/providers/implementations/exchange/kdf_exch.c b/providers/implementations/exchange/kdf_exch.c
new file mode 100644
index 0000000000..80164e10c6
--- /dev/null
+++ b/providers/implementations/exchange/kdf_exch.c
@@ -0,0 +1,174 @@
+/*
+ * Copyright 2020 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/crypto.h>
+#include <openssl/kdf.h>
+#include <openssl/core_dispatch.h>
+#include <openssl/core_names.h>
+#include <openssl/params.h>
+#include "prov/implementations.h"
+#include "prov/provider_ctx.h"
+#include "prov/kdfexchange.h"
+
+static OSSL_FUNC_keyexch_newctx_fn kdf_tls1_prf_newctx;
+static OSSL_FUNC_keyexch_newctx_fn kdf_hkdf_newctx;
+static OSSL_FUNC_keyexch_newctx_fn kdf_scrypt_newctx;
+static OSSL_FUNC_keyexch_init_fn kdf_init;
+static OSSL_FUNC_keyexch_derive_fn kdf_derive;
+static OSSL_FUNC_keyexch_freectx_fn kdf_freectx;
+static OSSL_FUNC_keyexch_dupctx_fn kdf_dupctx;
+static OSSL_FUNC_keyexch_set_ctx_params_fn kdf_set_ctx_params;
+static OSSL_FUNC_keyexch_settable_ctx_params_fn kdf_tls1_prf_settable_ctx_params;
+static OSSL_FUNC_keyexch_settable_ctx_params_fn kdf_hkdf_settable_ctx_params;
+static OSSL_FUNC_keyexch_settable_ctx_params_fn kdf_scrypt_settable_ctx_params;
+
+typedef struct {
+    void *provctx;
+    EVP_KDF_CTX *kdfctx;
+    KDF_DATA *kdfdata;
+} PROV_KDF_CTX;
+
+static void *kdf_newctx(const char *kdfname, void *provctx)
+{
+    PROV_KDF_CTX *kdfctx = OPENSSL_zalloc(sizeof(PROV_KDF_CTX));
+    EVP_KDF *kdf = NULL;
+
+    if (kdfctx == NULL)
+        return NULL;
+
+    kdfctx->provctx = provctx;
+
+    kdf = EVP_KDF_fetch(PROV_LIBRARY_CONTEXT_OF(provctx), kdfname, NULL);
+    if (kdf == NULL)
+        goto err;
+    kdfctx->kdfctx = EVP_KDF_CTX_new(kdf);
+    EVP_KDF_free(kdf);
+
+    if (kdfctx->kdfctx == NULL)
+        goto err;
+
+    return kdfctx;
+err:
+    OPENSSL_free(kdfctx);
+    return NULL;
+}
+
+#define KDF_NEWCTX(funcname, kdfname) \
+    static void *kdf_##funcname##_newctx(void *provctx) \
+    { \
+        return kdf_newctx(kdfname, provctx); \
+    }
+
+KDF_NEWCTX(tls1_prf, "TLS1-PRF")
+KDF_NEWCTX(hkdf, "HKDF")
+KDF_NEWCTX(scrypt, "SCRYPT")
+
+static int kdf_init(void *vpkdfctx, void *vkdf)
+{
+    PROV_KDF_CTX *pkdfctx = (PROV_KDF_CTX *)vpkdfctx;
+
+    if (pkdfctx == NULL || vkdf == NULL || !kdf_data_up_ref(vkdf))
+        return 0;
+    pkdfctx->kdfdata = vkdf;
+
+    return 1;
+}
+
+static int kdf_derive(void *vpkdfctx, unsigned char *secret, size_t *secretlen,
+                      size_t outlen)
+{
+    PROV_KDF_CTX *pkdfctx = (PROV_KDF_CTX *)vpkdfctx;
+
+    return EVP_KDF_derive(pkdfctx->kdfctx, secret, *secretlen);
+}
+
+static void kdf_freectx(void *vpkdfctx)
+{
+    PROV_KDF_CTX *pkdfctx = (PROV_KDF_CTX *)vpkdfctx;
+
+    EVP_KDF_CTX_free(pkdfctx->kdfctx);
+    kdf_data_free(pkdfctx->kdfdata);
+
+    OPENSSL_free(pkdfctx);
+}
+
+static void *kdf_dupctx(void *vpkdfctx)
+{
+    PROV_KDF_CTX *srcctx = (PROV_KDF_CTX *)vpkdfctx;
+    PROV_KDF_CTX *dstctx;
+
+    dstctx = OPENSSL_zalloc(sizeof(*srcctx));
+    if (dstctx == NULL)
+        return NULL;
+
+    *dstctx = *srcctx;
+
+    dstctx->kdfctx = EVP_KDF_CTX_dup(srcctx->kdfctx);
+    if (dstctx->kdfctx == NULL) {
+        OPENSSL_free(dstctx);
+        return NULL;
+    }
+    if (!kdf_data_up_ref(dstctx->kdfdata)) {
+        EVP_KDF_CTX_free(dstctx->kdfctx);
+        OPENSSL_free(dstctx);
+        return NULL;
+    }
+
+    return dstctx;
+}
+
+static int kdf_set_ctx_params(void *vpkdfctx, const OSSL_PARAM params[])
+{
+    PROV_KDF_CTX *pkdfctx = (PROV_KDF_CTX *)vpkdfctx;
+
+    return EVP_KDF_CTX_set_params(pkdfctx->kdfctx, params);
+}
+
+static const OSSL_PARAM *kdf_settable_ctx_params(void *provctx,
+                                                 const char *kdfname)
+{
+    EVP_KDF *kdf = EVP_KDF_fetch(PROV_LIBRARY_CONTEXT_OF(provctx), kdfname,
+                                 NULL);
+    const OSSL_PARAM *params;
+
+    if (kdf == NULL)
+        return NULL;
+
+    params = EVP_KDF_settable_ctx_params(kdf);
+    EVP_KDF_free(kdf);
+
+    return params;
+}
+
+#define KDF_SETTABLE_CTX_PARAMS(funcname, kdfname) \
+    static const OSSL_PARAM *kdf_##funcname##_settable_ctx_params(void *provctx) \
+    { \
+        return kdf_settable_ctx_params(provctx, kdfname); \
+    }
+
+KDF_SETTABLE_CTX_PARAMS(tls1_prf, "TLS1-PRF")
+KDF_SETTABLE_CTX_PARAMS(hkdf, "HKDF")
+KDF_SETTABLE_CTX_PARAMS(scrypt, "SCRYPT")
+
+#define KDF_KEYEXCH_FUNCTIONS(funcname) \
+    const OSSL_DISPATCH kdf_##funcname##_keyexch_functions[] = { \
+        { OSSL_FUNC_KEYEXCH_NEWCTX, (void (*)(void))kdf_##funcname##_newctx }, \
+        { OSSL_FUNC_KEYEXCH_INIT, (void (*)(void))kdf_init }, \
+        { OSSL_FUNC_KEYEXCH_DERIVE, (void (*)(void))kdf_derive }, \
+        { OSSL_FUNC_KEYEXCH_FREECTX, (void (*)(void))kdf_freectx }, \
+        { OSSL_FUNC_KEYEXCH_DUPCTX, (void (*)(void))kdf_dupctx }, \
+        { OSSL_FUNC_KEYEXCH_SET_CTX_PARAMS, (void (*)(void))kdf_set_ctx_params }, \
+        { OSSL_FUNC_KEYEXCH_SETTABLE_CTX_PARAMS, \
+        (void (*)(void))kdf_##funcname##_settable_ctx_params }, \
+        { 0, NULL } \
+    };
+
+KDF_KEYEXCH_FUNCTIONS(tls1_prf)
+KDF_KEYEXCH_FUNCTIONS(hkdf)
+KDF_KEYEXCH_FUNCTIONS(scrypt)
diff --git a/providers/implementations/include/prov/implementations.h b/providers/implementations/include/prov/implementations.h
index 7e470044cd..9e3ef4d79c 100644
--- a/providers/implementations/include/prov/implementations.h
+++ b/providers/implementations/include/prov/implementations.h
@@ -275,12 +275,16 @@ extern const OSSL_DISPATCH x448_keymgmt_functions[];
 extern const OSSL_DISPATCH ed25519_keymgmt_functions[];
 extern const OSSL_DISPATCH ed448_keymgmt_functions[];
 extern const OSSL_DISPATCH ec_keymgmt_functions[];
+extern const OSSL_DISPATCH kdf_keymgmt_functions[];
 
 /* Key Exchange */
 extern const OSSL_DISPATCH dh_keyexch_functions[];
 extern const OSSL_DISPATCH x25519_keyexch_functions[];
 extern const OSSL_DISPATCH x448_keyexch_functions[];
 extern const OSSL_DISPATCH ecdh_keyexch_functions[];
+extern const OSSL_DISPATCH kdf_tls1_prf_keyexch_functions[];
+extern const OSSL_DISPATCH kdf_hkdf_keyexch_functions[];
+extern const OSSL_DISPATCH kdf_scrypt_keyexch_functions[];
 
 /* Signature */
 extern const OSSL_DISPATCH dsa_signature_functions[];
diff --git a/providers/implementations/include/prov/kdfexchange.h b/providers/implementations/include/prov/kdfexchange.h
new file mode 100644
index 0000000000..5c817bb929
--- /dev/null
+++ b/providers/implementations/include/prov/kdfexchange.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2020 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 <stdlib.h>
+#include <openssl/crypto.h>
+#include "internal/refcount.h"
+
+struct kdf_data_st {
+    OPENSSL_CTX *libctx;
+    CRYPTO_REF_COUNT refcnt;
+    CRYPTO_RWLOCK *lock;
+};
+
+typedef struct kdf_data_st KDF_DATA;
+
+KDF_DATA *kdf_data_new(void *provctx);
+void kdf_data_free(KDF_DATA *kdfdata);
+int kdf_data_up_ref(KDF_DATA *kdfdata);
diff --git a/providers/implementations/kdfs/tls1_prf.c b/providers/implementations/kdfs/tls1_prf.c
index bc7d7fd721..46a1253ee8 100644
--- a/providers/implementations/kdfs/tls1_prf.c
+++ b/providers/implementations/kdfs/tls1_prf.c
@@ -183,9 +183,6 @@ static int kdf_tls1_prf_set_ctx_params(void *vctx, const OSSL_PARAM params[])
     }
     /* The seed fields concatenate, so process them all */
     if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SEED)) != NULL) {
-        OPENSSL_cleanse(ctx->seed, ctx->seedlen);
-        ctx->seedlen = 0;
-
         for (; p != NULL; p = OSSL_PARAM_locate_const(p + 1,
                                                       OSSL_KDF_PARAM_SEED)) {
             const void *q = ctx->seed + ctx->seedlen;
diff --git a/providers/implementations/keymgmt/build.info b/providers/implementations/keymgmt/build.info
index 73597c7cea..53c84ac3d4 100644
--- a/providers/implementations/keymgmt/build.info
+++ b/providers/implementations/keymgmt/build.info
@@ -5,6 +5,7 @@ $DH_GOAL=../../libimplementations.a
 $DSA_GOAL=../../libimplementations.a
 $EC_GOAL=../../libimplementations.a
 $ECX_GOAL=../../libimplementations.a
+$KDF_GOAL=../../libimplementations.a
 
 IF[{- !$disabled{dh} -}]
   SOURCE[$DH_GOAL]=dh_kmgmt.c
@@ -33,3 +34,5 @@ ENDIF
 
 SOURCE[../../libfips.a]=rsa_kmgmt.c
 SOURCE[../../libnonfips.a]=rsa_kmgmt.c
+
+SOURCE[$KDF_GOAL]=kdf_legacy_kmgmt.c
diff --git a/providers/implementations/keymgmt/kdf_legacy_kmgmt.c b/providers/implementations/keymgmt/kdf_legacy_kmgmt.c
new file mode 100644
index 0000000000..33cf87e350
--- /dev/null
+++ b/providers/implementations/keymgmt/kdf_legacy_kmgmt.c
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2019-2020 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
+ */
+
+/*
+ * This implemments a dummy key manager for legacy KDFs that still support the
+ * old way of performing a KDF via EVP_PKEY_derive(). New KDFs should not be
+ * implemented this way. In reality there is no key data for such KDFs, so this
+ * key manager does very little.
+ */
+
+#include <openssl/core_dispatch.h>
+#include <openssl/core_names.h>
+#include <openssl/err.h>
+#include "prov/implementations.h"
+#include "prov/providercommon.h"
+#include "prov/provider_ctx.h"
+#include "prov/kdfexchange.h"
+
+static OSSL_FUNC_keymgmt_new_fn kdf_newdata;
+static OSSL_FUNC_keymgmt_free_fn kdf_freedata;
+static OSSL_FUNC_keymgmt_has_fn kdf_has;
+
+KDF_DATA *kdf_data_new(void *provctx)
+{
+    KDF_DATA *kdfdata = OPENSSL_zalloc(sizeof(*kdfdata));
+
+    if (kdfdata == NULL)
+        return NULL;
+
+    kdfdata->lock = CRYPTO_THREAD_lock_new();
+    if (kdfdata->lock == NULL) {
+        OPENSSL_free(kdfdata);
+        return NULL;
+    }
+    kdfdata->libctx = PROV_LIBRARY_CONTEXT_OF(provctx);
+    kdfdata->refcnt = 1;
+
+    return kdfdata;
+}
+
+void kdf_data_free(KDF_DATA *kdfdata)
+{
+    int ref = 0;
+
+    if (kdfdata == NULL)
+        return;
+
+    CRYPTO_DOWN_REF(&kdfdata->refcnt, &ref, kdfdata->lock);
+    if (ref > 0)
+        return;
+
+    CRYPTO_THREAD_lock_free(kdfdata->lock);
+    OPENSSL_free(kdfdata);
+}
+
+int kdf_data_up_ref(KDF_DATA *kdfdata)
+{
+    int ref = 0;
+
+    CRYPTO_UP_REF(&kdfdata->refcnt, &ref, kdfdata->lock);
+    return 1;
+}
+
+static void *kdf_newdata(void *provctx)
+{
+    return kdf_data_new(provctx);
+}
+
+static void kdf_freedata(void *kdfdata)
+{
+    kdf_data_free(kdfdata);
+}
+
+static int kdf_has(void *keydata, int selection)
+{
+    return 0;
+}
+
+const OSSL_DISPATCH kdf_keymgmt_functions[] = {
+    { OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))kdf_newdata },
+    { OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))kdf_freedata },
+    { OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))kdf_has },
+    { 0, NULL }
+};
diff --git a/test/evp_test.c b/test/evp_test.c
index bff1ecb558..f384a8d863 100644
--- a/test/evp_test.c
+++ b/test/evp_test.c
@@ -2494,9 +2494,7 @@ typedef struct pkey_kdf_data_st {
  */
 static int pkey_kdf_test_init(EVP_TEST *t, const char *name)
 {
-    OPENSSL_CTX *save_libctx = NULL;
     PKEY_KDF_DATA *kdata = NULL;
-    int kdf_nid = OBJ_sn2nid(name);
 
     if (is_kdf_disabled(name)) {
         TEST_info("skipping, '%s' is disabled", name);
@@ -2504,28 +2502,17 @@ static int pkey_kdf_test_init(EVP_TEST *t, const char *name)
         return 1;
     }
 
-    if (kdf_nid == NID_undef)
-        kdf_nid = OBJ_ln2nid(name);
-
     if (!TEST_ptr(kdata = OPENSSL_zalloc(sizeof(*kdata))))
         return 0;
-    /*
-     * TODO(3.0): This should be using EVP_PKEY_CTX_new_from_name(),
-     * but it does not currently since the PKEY_KDF is using legacy paths.
-     * Internally it still uses fetches with the legacy path,
-     * So for now we hack in the library context.
-     */
-    save_libctx = OPENSSL_CTX_set0_default(libctx);
-    kdata->ctx = EVP_PKEY_CTX_new_id(kdf_nid, NULL);
+
+    kdata->ctx = EVP_PKEY_CTX_new_from_name(libctx, name, NULL);
     if (kdata->ctx == NULL
         || EVP_PKEY_derive_init(kdata->ctx) <= 0)
         goto err;
 
-    OPENSSL_CTX_set0_default(save_libctx);
     t->data = kdata;
     return 1;
 err:
-    OPENSSL_CTX_set0_default(save_libctx);
     EVP_PKEY_CTX_free(kdata->ctx);
     OPENSSL_free(kdata);
     return 0;
diff --git a/test/pkey_meth_kdf_test.c b/test/pkey_meth_kdf_test.c
index cdc3d9f61a..1d3e9eca3c 100644
--- a/test/pkey_meth_kdf_test.c
+++ b/test/pkey_meth_kdf_test.c
@@ -35,11 +35,13 @@ static int test_kdf_tls1_prf(void)
         TEST_error("EVP_PKEY_CTX_set_tls1_prf_md");
         goto err;
     }
-    if (EVP_PKEY_CTX_set1_tls1_prf_secret(pctx, "secret", 6) <= 0) {
+    if (EVP_PKEY_CTX_set1_tls1_prf_secret(pctx,
+                                          (unsigned char *)"secret", 6) <= 0) {
         TEST_error("EVP_PKEY_CTX_set1_tls1_prf_secret");
         goto err;
     }
-    if (EVP_PKEY_CTX_add1_tls1_prf_seed(pctx, "seed", 4) <= 0) {
+    if (EVP_PKEY_CTX_add1_tls1_prf_seed(pctx,
+                                        (unsigned char *)"seed", 4) <= 0) {
         TEST_error("EVP_PKEY_CTX_add1_tls1_prf_seed");
         goto err;
     }
@@ -82,15 +84,18 @@ static int test_kdf_hkdf(void)
         TEST_error("EVP_PKEY_CTX_set_hkdf_md");
         goto err;
     }
-    if (EVP_PKEY_CTX_set1_hkdf_salt(pctx, "salt", 4) <= 0) {
+    if (EVP_PKEY_CTX_set1_hkdf_salt(pctx, (const unsigned char *)"salt", 4)
+            <= 0) {
         TEST_error("EVP_PKEY_CTX_set1_hkdf_salt");
         goto err;
     }
-    if (EVP_PKEY_CTX_set1_hkdf_key(pctx, "secret", 6) <= 0) {
+    if (EVP_PKEY_CTX_set1_hkdf_key(pctx, (const unsigned char *)"secret", 6)
+            <= 0) {
         TEST_error("EVP_PKEY_CTX_set1_hkdf_key");
         goto err;
     }
-    if (EVP_PKEY_CTX_add1_hkdf_info(pctx, "label", 5) <= 0) {
+    if (EVP_PKEY_CTX_add1_hkdf_info(pctx, (const unsigned char *)"label", 5)
+            <= 0) {
         TEST_error("EVP_PKEY_CTX_set1_hkdf_info");
         goto err;
     }
@@ -133,7 +138,7 @@ static int test_kdf_scrypt(void)
         TEST_error("EVP_PKEY_CTX_set1_pbe_pass");
         goto err;
     }
-    if (EVP_PKEY_CTX_set1_scrypt_salt(pctx, "NaCl", 4) <= 0) {
+    if (EVP_PKEY_CTX_set1_scrypt_salt(pctx, (unsigned char *)"NaCl", 4) <= 0) {
         TEST_error("EVP_PKEY_CTX_set1_scrypt_salt");
         goto err;
     }
diff --git a/util/libcrypto.num b/util/libcrypto.num
index fe875f188d..a3fd0ddc31 100644
--- a/util/libcrypto.num
+++ b/util/libcrypto.num
@@ -5226,3 +5226,17 @@ PKCS7_sign_with_libctx                  ?	3_0_0	EXIST::FUNCTION:
 PKCS7_encrypt_with_libctx               ?	3_0_0	EXIST::FUNCTION:
 SMIME_read_PKCS7_ex                     ?	3_0_0	EXIST::FUNCTION:
 OSSL_PROVIDER_self_test                 ?	3_0_0	EXIST::FUNCTION:
+EVP_PKEY_CTX_set_tls1_prf_md            ?	3_0_0	EXIST::FUNCTION:
+EVP_PKEY_CTX_set1_tls1_prf_secret       ?	3_0_0	EXIST::FUNCTION:
+EVP_PKEY_CTX_add1_tls1_prf_seed         ?	3_0_0	EXIST::FUNCTION:
+EVP_PKEY_CTX_set_hkdf_md                ?	3_0_0	EXIST::FUNCTION:
+EVP_PKEY_CTX_set1_hkdf_salt             ?	3_0_0	EXIST::FUNCTION:
+EVP_PKEY_CTX_set1_hkdf_key              ?	3_0_0	EXIST::FUNCTION:
+EVP_PKEY_CTX_add1_hkdf_info             ?	3_0_0	EXIST::FUNCTION:
+EVP_PKEY_CTX_hkdf_mode                  ?	3_0_0	EXIST::FUNCTION:
+EVP_PKEY_CTX_set1_pbe_pass              ?	3_0_0	EXIST::FUNCTION:
+EVP_PKEY_CTX_set1_scrypt_salt           ?	3_0_0	EXIST::FUNCTION:
+EVP_PKEY_CTX_set_scrypt_N               ?	3_0_0	EXIST::FUNCTION:
+EVP_PKEY_CTX_set_scrypt_r               ?	3_0_0	EXIST::FUNCTION:
+EVP_PKEY_CTX_set_scrypt_p               ?	3_0_0	EXIST::FUNCTION:
+EVP_PKEY_CTX_set_scrypt_maxmem_bytes    ?	3_0_0	EXIST::FUNCTION:


More information about the openssl-commits mailing list