[openssl-commits] [openssl] master update

Richard Levitte levitte at openssl.org
Wed Feb 13 11:12:12 UTC 2019


The branch master has been updated
       via  5a285addbf39f91d567f95f04b2b41764127950d (commit)
      from  e0ae0585bee898184cbbe8144d2fa8ce25e8ca72 (commit)


- Log -----------------------------------------------------------------
commit 5a285addbf39f91d567f95f04b2b41764127950d
Author: David Makepeace <david.p.makepeace at oracle.com>
Date:   Fri Jun 22 07:16:18 2018 +1000

    Added new EVP/KDF API.
    Changed PKEY/KDF API to call the new API.
    Added wrappers for PKCS5_PBKDF2_HMAC() and EVP_PBE_scrypt() to call the new EVP KDF APIs.
    Documentation updated.
    
    Reviewed-by: Paul Dale <paul.dale at oracle.com>
    Reviewed-by: Richard Levitte <levitte at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/6674)

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

Summary of changes:
 CHANGES                                            |   7 +
 crypto/err/openssl.txt                             |  25 ++
 crypto/evp/build.info                              |   3 +-
 crypto/evp/e_chacha20_poly1305.c                   |   2 +-
 crypto/evp/encode.c                                |   2 +-
 crypto/evp/evp_err.c                               |   9 +-
 crypto/evp/evp_locl.h                              |   5 +
 crypto/evp/evp_pbe.c                               |   1 +
 crypto/evp/kdf_lib.c                               | 165 ++++++++
 crypto/evp/p5_crpt2.c                              | 110 ++---
 crypto/evp/pbe_scrypt.c                            | 242 ++---------
 crypto/evp/pkey_kdf.c                              | 255 +++++++++++
 crypto/include/internal/evp_int.h                  |  18 +
 crypto/kdf/build.info                              |   2 +-
 crypto/kdf/hkdf.c                                  | 324 +++++++-------
 crypto/kdf/kdf_err.c                               |  28 +-
 crypto/kdf/kdf_local.h                             |  22 +
 crypto/kdf/kdf_util.c                              |  73 ++++
 crypto/kdf/pbkdf2.c                                | 264 ++++++++++++
 crypto/kdf/scrypt.c                                | 466 ++++++++++++++++-----
 crypto/kdf/tls1_prf.c                              | 193 +++++----
 doc/man3/EVP_KDF_CTX.pod                           | 217 ++++++++++
 doc/man7/EVP_KDF_HKDF.pod                          | 180 ++++++++
 doc/man7/EVP_KDF_PBKDF2.pod                        |  78 ++++
 doc/man7/{scrypt.pod => EVP_KDF_SCRYPT.pod}        | 100 +++--
 doc/man7/EVP_KDF_TLS1_PRF.pod                      | 142 +++++++
 include/openssl/evperr.h                           |   8 +-
 include/openssl/kdf.h                              |  55 ++-
 include/openssl/kdferr.h                           |  21 +-
 include/openssl/ossl_typ.h                         |   2 +
 test/build.info                                    |   7 +-
 test/evp_kdf_test.c                                | 237 +++++++++++
 test/evp_test.c                                    | 152 ++++++-
 test/pkey_meth_kdf_test.c                          |  80 ++--
 test/recipes/30-test_evp.t                         |   4 +-
 test/recipes/30-test_evp_data/evpkdf.txt           | 194 +++++++--
 .../{evpkdf.txt => evppkey_kdf.txt}                |  82 ++--
 test/recipes/30-test_evp_kdf.t                     |  13 +
 util/libcrypto.num                                 |   8 +
 util/private.num                                   |   1 +
 40 files changed, 2947 insertions(+), 850 deletions(-)
 create mode 100644 crypto/evp/kdf_lib.c
 create mode 100644 crypto/evp/pkey_kdf.c
 create mode 100644 crypto/kdf/kdf_local.h
 create mode 100644 crypto/kdf/kdf_util.c
 create mode 100644 crypto/kdf/pbkdf2.c
 create mode 100644 doc/man3/EVP_KDF_CTX.pod
 create mode 100644 doc/man7/EVP_KDF_HKDF.pod
 create mode 100644 doc/man7/EVP_KDF_PBKDF2.pod
 rename doc/man7/{scrypt.pod => EVP_KDF_SCRYPT.pod} (53%)
 create mode 100644 doc/man7/EVP_KDF_TLS1_PRF.pod
 create mode 100644 test/evp_kdf_test.c
 copy test/recipes/30-test_evp_data/{evpkdf.txt => evppkey_kdf.txt} (94%)
 create mode 100644 test/recipes/30-test_evp_kdf.t

diff --git a/CHANGES b/CHANGES
index 02258ce..d9a2e1b 100644
--- a/CHANGES
+++ b/CHANGES
@@ -9,6 +9,13 @@
 
  Changes between 1.1.1 and 3.0.0 [xx XXX xxxx]
 
+  *) Added EVP_KDF, an EVP layer KDF API, to simplify adding KDF and PRF
+     implementations.  This includes an EVP_PKEY to EVP_KDF bridge for
+     those algorithms that were already supported through the EVP_PKEY API
+     (scrypt, TLS1 PRF and HKDF).  The low-level KDF functions for PBKDF2
+     and scrypt are now wrappers that call EVP_KDF.
+     [David Makepeace]
+
   *) Build devcrypto engine as a dynamic engine.
      [Eneas U de Queiroz]
 
diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt
index aaea598..a269ac6 100644
--- a/crypto/err/openssl.txt
+++ b/crypto/err/openssl.txt
@@ -753,6 +753,9 @@ EVP_F_EVP_DIGESTINIT_EX:128:EVP_DigestInit_ex
 EVP_F_EVP_ENCRYPTDECRYPTUPDATE:219:evp_EncryptDecryptUpdate
 EVP_F_EVP_ENCRYPTFINAL_EX:127:EVP_EncryptFinal_ex
 EVP_F_EVP_ENCRYPTUPDATE:167:EVP_EncryptUpdate
+EVP_F_EVP_KDF_CTRL:224:EVP_KDF_ctrl
+EVP_F_EVP_KDF_CTRL_STR:225:EVP_KDF_ctrl_str
+EVP_F_EVP_KDF_CTX_NEW_ID:226:EVP_KDF_CTX_new_id
 EVP_F_EVP_MAC_CTRL:209:EVP_MAC_ctrl
 EVP_F_EVP_MAC_CTRL_STR:210:EVP_MAC_ctrl_str
 EVP_F_EVP_MAC_CTX_COPY:211:EVP_MAC_CTX_copy
@@ -823,6 +826,7 @@ EVP_F_PKCS5_PBE_KEYIVGEN:117:PKCS5_PBE_keyivgen
 EVP_F_PKCS5_V2_PBE_KEYIVGEN:118:PKCS5_v2_PBE_keyivgen
 EVP_F_PKCS5_V2_PBKDF2_KEYIVGEN:164:PKCS5_v2_PBKDF2_keyivgen
 EVP_F_PKCS5_V2_SCRYPT_KEYIVGEN:180:PKCS5_v2_scrypt_keyivgen
+EVP_F_PKEY_KDF_CTRL:227:pkey_kdf_ctrl
 EVP_F_PKEY_MAC_INIT:214:pkey_mac_init
 EVP_F_PKEY_SET_TYPE:158:pkey_set_type
 EVP_F_POLY1305_CTRL:216:poly1305_ctrl
@@ -830,7 +834,25 @@ EVP_F_RC2_MAGIC_TO_METH:109:rc2_magic_to_meth
 EVP_F_RC5_CTRL:125:rc5_ctrl
 EVP_F_S390X_AES_GCM_CTRL:201:s390x_aes_gcm_ctrl
 EVP_F_S390X_AES_GCM_TLS_CIPHER:208:s390x_aes_gcm_tls_cipher
+EVP_F_SCRYPT_ALG:228:scrypt_alg
 EVP_F_UPDATE:173:update
+KDF_F_HKDF_EXTRACT:112:HKDF_Extract
+KDF_F_KDF_HKDF_DERIVE:113:kdf_hkdf_derive
+KDF_F_KDF_HKDF_NEW:114:kdf_hkdf_new
+KDF_F_KDF_HKDF_SIZE:115:kdf_hkdf_size
+KDF_F_KDF_MD2CTRL:116:kdf_md2ctrl
+KDF_F_KDF_PBKDF2_CTRL_STR:117:kdf_pbkdf2_ctrl_str
+KDF_F_KDF_PBKDF2_DERIVE:118:kdf_pbkdf2_derive
+KDF_F_KDF_PBKDF2_NEW:119:kdf_pbkdf2_new
+KDF_F_KDF_SCRYPT_CTRL_STR:120:kdf_scrypt_ctrl_str
+KDF_F_KDF_SCRYPT_CTRL_UINT32:121:kdf_scrypt_ctrl_uint32
+KDF_F_KDF_SCRYPT_CTRL_UINT64:122:kdf_scrypt_ctrl_uint64
+KDF_F_KDF_SCRYPT_DERIVE:123:kdf_scrypt_derive
+KDF_F_KDF_SCRYPT_NEW:124:kdf_scrypt_new
+KDF_F_KDF_TLS1_PRF_CTRL_STR:125:kdf_tls1_prf_ctrl_str
+KDF_F_KDF_TLS1_PRF_DERIVE:126:kdf_tls1_prf_derive
+KDF_F_KDF_TLS1_PRF_NEW:127:kdf_tls1_prf_new
+KDF_F_PBKDF2_SET_MEMBUF:128:pbkdf2_set_membuf
 KDF_F_PKEY_HKDF_CTRL_STR:103:pkey_hkdf_ctrl_str
 KDF_F_PKEY_HKDF_DERIVE:102:pkey_hkdf_derive
 KDF_F_PKEY_HKDF_INIT:108:pkey_hkdf_init
@@ -842,6 +864,7 @@ KDF_F_PKEY_SCRYPT_SET_MEMBUF:107:pkey_scrypt_set_membuf
 KDF_F_PKEY_TLS1_PRF_CTRL_STR:100:pkey_tls1_prf_ctrl_str
 KDF_F_PKEY_TLS1_PRF_DERIVE:101:pkey_tls1_prf_derive
 KDF_F_PKEY_TLS1_PRF_INIT:110:pkey_tls1_prf_init
+KDF_F_SCRYPT_SET_MEMBUF:129:scrypt_set_membuf
 KDF_F_TLS1_PRF_ALG:111:tls1_prf_alg
 OBJ_F_OBJ_ADD_OBJECT:105:OBJ_add_object
 OBJ_F_OBJ_ADD_SIGID:107:OBJ_add_sigid
@@ -2284,6 +2307,7 @@ EVP_R_ONLY_ONESHOT_SUPPORTED:177:only oneshot supported
 EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE:150:\
 	operation not supported for this keytype
 EVP_R_OPERATON_NOT_INITIALIZED:151:operaton not initialized
+EVP_R_PARAMETER_TOO_LARGE:187:parameter too large
 EVP_R_PARTIALLY_OVERLAPPING:162:partially overlapping buffers
 EVP_R_PBKDF2_ERROR:181:pbkdf2 error
 EVP_R_PKEY_APPLICATION_ASN1_METHOD_ALREADY_REGISTERED:179:\
@@ -2320,6 +2344,7 @@ KDF_R_MISSING_SEED:106:missing seed
 KDF_R_UNKNOWN_PARAMETER_TYPE:103:unknown parameter type
 KDF_R_VALUE_ERROR:108:value error
 KDF_R_VALUE_MISSING:102:value missing
+KDF_R_WRONG_OUTPUT_BUFFER_SIZE:112:wrong output buffer size
 OBJ_R_OID_EXISTS:102:oid exists
 OBJ_R_UNKNOWN_NID:101:unknown nid
 OCSP_R_CERTIFICATE_VERIFY_ERROR:101:certificate verify error
diff --git a/crypto/evp/build.info b/crypto/evp/build.info
index 84193b0..862afa8 100644
--- a/crypto/evp/build.info
+++ b/crypto/evp/build.info
@@ -9,7 +9,8 @@ SOURCE[../../libcrypto]=\
         p_open.c p_seal.c p_sign.c p_verify.c p_lib.c p_enc.c p_dec.c \
         bio_md.c bio_b64.c bio_enc.c evp_err.c e_null.c \
         c_allc.c c_alld.c evp_lib.c bio_ok.c \
-        evp_pkey.c evp_pbe.c p5_crpt.c p5_crpt2.c pbe_scrypt.c \
+        evp_pkey.c kdf_lib.c evp_pbe.c p5_crpt.c p5_crpt2.c pbe_scrypt.c \
+        pkey_kdf.c \
         e_old.c pmeth_lib.c pmeth_fn.c pmeth_gn.c m_sigver.c \
         e_aes_cbc_hmac_sha1.c e_aes_cbc_hmac_sha256.c e_rc4_hmac_md5.c \
         e_chacha20_poly1305.c cmeth_lib.c \
diff --git a/crypto/evp/e_chacha20_poly1305.c b/crypto/evp/e_chacha20_poly1305.c
index 0d4612f..e8a323f 100644
--- a/crypto/evp/e_chacha20_poly1305.c
+++ b/crypto/evp/e_chacha20_poly1305.c
@@ -14,8 +14,8 @@
 
 # include <openssl/evp.h>
 # include <openssl/objects.h>
-# include "evp_locl.h"
 # include "internal/evp_int.h"
+# include "evp_locl.h"
 # include "internal/chacha.h"
 
 typedef struct {
diff --git a/crypto/evp/encode.c b/crypto/evp/encode.c
index 5a54a9f..3519e3b 100644
--- a/crypto/evp/encode.c
+++ b/crypto/evp/encode.c
@@ -11,8 +11,8 @@
 #include <limits.h>
 #include "internal/cryptlib.h"
 #include <openssl/evp.h>
-#include "evp_locl.h"
 #include "internal/evp_int.h"
+#include "evp_locl.h"
 
 static unsigned char conv_ascii2bin(unsigned char a,
                                     const unsigned char *table);
diff --git a/crypto/evp/evp_err.c b/crypto/evp/evp_err.c
index a4dd97b..ef889b0 100644
--- a/crypto/evp/evp_err.c
+++ b/crypto/evp/evp_err.c
@@ -1,6 +1,6 @@
 /*
  * Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -60,6 +60,9 @@ static const ERR_STRING_DATA EVP_str_functs[] = {
     {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_ENCRYPTFINAL_EX, 0),
      "EVP_EncryptFinal_ex"},
     {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_ENCRYPTUPDATE, 0), "EVP_EncryptUpdate"},
+    {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_KDF_CTRL, 0), "EVP_KDF_ctrl"},
+    {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_KDF_CTRL_STR, 0), "EVP_KDF_ctrl_str"},
+    {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_KDF_CTX_NEW_ID, 0), "EVP_KDF_CTX_new_id"},
     {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_MAC_CTRL, 0), "EVP_MAC_ctrl"},
     {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_MAC_CTRL_STR, 0), "EVP_MAC_ctrl_str"},
     {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_MAC_CTX_COPY, 0), "EVP_MAC_CTX_copy"},
@@ -159,6 +162,7 @@ static const ERR_STRING_DATA EVP_str_functs[] = {
      "PKCS5_v2_PBKDF2_keyivgen"},
     {ERR_PACK(ERR_LIB_EVP, EVP_F_PKCS5_V2_SCRYPT_KEYIVGEN, 0),
      "PKCS5_v2_scrypt_keyivgen"},
+    {ERR_PACK(ERR_LIB_EVP, EVP_F_PKEY_KDF_CTRL, 0), "pkey_kdf_ctrl"},
     {ERR_PACK(ERR_LIB_EVP, EVP_F_PKEY_MAC_INIT, 0), "pkey_mac_init"},
     {ERR_PACK(ERR_LIB_EVP, EVP_F_PKEY_SET_TYPE, 0), "pkey_set_type"},
     {ERR_PACK(ERR_LIB_EVP, EVP_F_POLY1305_CTRL, 0), "poly1305_ctrl"},
@@ -167,6 +171,7 @@ static const ERR_STRING_DATA EVP_str_functs[] = {
     {ERR_PACK(ERR_LIB_EVP, EVP_F_S390X_AES_GCM_CTRL, 0), "s390x_aes_gcm_ctrl"},
     {ERR_PACK(ERR_LIB_EVP, EVP_F_S390X_AES_GCM_TLS_CIPHER, 0),
      "s390x_aes_gcm_tls_cipher"},
+    {ERR_PACK(ERR_LIB_EVP, EVP_F_SCRYPT_ALG, 0), "scrypt_alg"},
     {ERR_PACK(ERR_LIB_EVP, EVP_F_UPDATE, 0), "update"},
     {0, NULL}
 };
@@ -254,6 +259,8 @@ static const ERR_STRING_DATA EVP_str_reasons[] = {
     "operation not supported for this keytype"},
     {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_OPERATON_NOT_INITIALIZED),
     "operaton not initialized"},
+    {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_PARAMETER_TOO_LARGE),
+    "parameter too large"},
     {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_PARTIALLY_OVERLAPPING),
     "partially overlapping buffers"},
     {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_PBKDF2_ERROR), "pbkdf2 error"},
diff --git a/crypto/evp/evp_locl.h b/crypto/evp/evp_locl.h
index fe69067..95a9d5c 100644
--- a/crypto/evp/evp_locl.h
+++ b/crypto/evp/evp_locl.h
@@ -46,6 +46,11 @@ struct evp_mac_ctx_st {
     void *data;                  /* Individual method data */
 } /* EVP_MAC_CTX */;
 
+struct evp_kdf_ctx_st {
+    const EVP_KDF_METHOD *kmeth;
+    EVP_KDF_IMPL *impl;          /* Algorithm-specific data */
+} /* EVP_KDF_CTX */ ;
+
 int PKCS5_v2_PBKDF2_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass,
                              int passlen, ASN1_TYPE *param,
                              const EVP_CIPHER *c, const EVP_MD *md,
diff --git a/crypto/evp/evp_pbe.c b/crypto/evp/evp_pbe.c
index eb099ab..8162a5e 100644
--- a/crypto/evp/evp_pbe.c
+++ b/crypto/evp/evp_pbe.c
@@ -12,6 +12,7 @@
 #include <openssl/evp.h>
 #include <openssl/pkcs12.h>
 #include <openssl/x509.h>
+#include "internal/evp_int.h"
 #include "evp_locl.h"
 
 /* Password based encryption (PBE) functions */
diff --git a/crypto/evp/kdf_lib.c b/crypto/evp/kdf_lib.c
new file mode 100644
index 0000000..05f5cec
--- /dev/null
+++ b/crypto/evp/kdf_lib.c
@@ -0,0 +1,165 @@
+/*
+ * Copyright 2018 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 <stdio.h>
+#include <stdlib.h>
+#include "internal/cryptlib.h"
+#include <openssl/engine.h>
+#include <openssl/evp.h>
+#include <openssl/x509v3.h>
+#include <openssl/kdf.h>
+#include "internal/asn1_int.h"
+#include "internal/evp_int.h"
+#include "internal/numbers.h"
+#include "evp_locl.h"
+
+typedef int sk_cmp_fn_type(const char *const *a, const char *const *b);
+
+/* This array needs to be in order of NIDs */
+static const EVP_KDF_METHOD *standard_methods[] = {
+    &pbkdf2_kdf_meth,
+#ifndef OPENSSL_NO_SCRYPT
+    &scrypt_kdf_meth,
+#endif
+    &tls1_prf_kdf_meth,
+    &hkdf_kdf_meth
+};
+
+DECLARE_OBJ_BSEARCH_CMP_FN(const EVP_KDF_METHOD *, const EVP_KDF_METHOD *,
+                           kmeth);
+
+static int kmeth_cmp(const EVP_KDF_METHOD *const *a,
+                     const EVP_KDF_METHOD *const *b)
+{
+    return ((*a)->type - (*b)->type);
+}
+
+IMPLEMENT_OBJ_BSEARCH_CMP_FN(const EVP_KDF_METHOD *, const EVP_KDF_METHOD *,
+                             kmeth);
+
+static const EVP_KDF_METHOD *kdf_meth_find(int type)
+{
+    EVP_KDF_METHOD tmp;
+    const EVP_KDF_METHOD *t = &tmp, **ret;
+
+    tmp.type = type;
+    ret = OBJ_bsearch_kmeth(&t, standard_methods,
+                            OSSL_NELEM(standard_methods));
+    if (ret == NULL || *ret == NULL)
+        return NULL;
+
+    return *ret;
+}
+
+EVP_KDF_CTX *EVP_KDF_CTX_new_id(int id)
+{
+    EVP_KDF_CTX *ret;
+    const EVP_KDF_METHOD *kmeth;
+
+    kmeth = kdf_meth_find(id);
+    if (kmeth == NULL) {
+        EVPerr(EVP_F_EVP_KDF_CTX_NEW_ID, EVP_R_UNSUPPORTED_ALGORITHM);
+        return NULL;
+    }
+
+    ret = OPENSSL_zalloc(sizeof(*ret));
+    if (ret == NULL) {
+        EVPerr(EVP_F_EVP_KDF_CTX_NEW_ID, ERR_R_MALLOC_FAILURE);
+        return NULL;
+    }
+
+    if (kmeth->new != NULL && (ret->impl = kmeth->new()) == NULL) {
+        EVP_KDF_CTX_free(ret);
+        return NULL;
+    }
+
+    ret->kmeth = kmeth;
+    return ret;
+}
+
+void EVP_KDF_CTX_free(EVP_KDF_CTX *ctx)
+{
+    if (ctx == NULL)
+        return;
+
+    ctx->kmeth->free(ctx->impl);
+    OPENSSL_free(ctx);
+}
+
+void EVP_KDF_reset(EVP_KDF_CTX *ctx)
+{
+    if (ctx == NULL)
+        return;
+
+    if (ctx->kmeth->reset != NULL)
+        ctx->kmeth->reset(ctx->impl);
+}
+
+int EVP_KDF_ctrl(EVP_KDF_CTX *ctx, int cmd, ...)
+{
+    int ret;
+    va_list args;
+
+    va_start(args, cmd);
+    ret = EVP_KDF_vctrl(ctx, cmd, args);
+    va_end(args);
+
+    if (ret == -2)
+        EVPerr(EVP_F_EVP_KDF_CTRL, EVP_R_COMMAND_NOT_SUPPORTED);
+
+    return ret;
+}
+
+int EVP_KDF_vctrl(EVP_KDF_CTX *ctx, int cmd, va_list args)
+{
+    if (ctx == NULL)
+        return 0;
+
+    return ctx->kmeth->ctrl(ctx->impl, cmd, args);
+}
+
+int EVP_KDF_ctrl_str(EVP_KDF_CTX *ctx, const char *type, const char *value)
+{
+    int ret;
+
+    if (ctx == NULL)
+        return 0;
+
+    if (ctx->kmeth->ctrl_str == NULL) {
+        EVPerr(EVP_F_EVP_KDF_CTRL_STR, EVP_R_COMMAND_NOT_SUPPORTED);
+        return -2;
+    }
+
+    ret = ctx->kmeth->ctrl_str(ctx->impl, type, value);
+    if (ret == -2)
+        EVPerr(EVP_F_EVP_KDF_CTRL_STR, EVP_R_COMMAND_NOT_SUPPORTED);
+
+    return ret;
+}
+
+size_t EVP_KDF_size(EVP_KDF_CTX *ctx)
+{
+    if (ctx == NULL)
+        return 0;
+
+    if (ctx->kmeth->size == NULL)
+        return SIZE_MAX;
+
+    return ctx->kmeth->size(ctx->impl);
+}
+
+int EVP_KDF_derive(EVP_KDF_CTX *ctx, unsigned char *key, size_t keylen)
+{
+    if (ctx == NULL)
+        return 0;
+
+    return ctx->kmeth->derive(ctx->impl, key, keylen);
+}
+
diff --git a/crypto/evp/p5_crpt2.c b/crypto/evp/p5_crpt2.c
index a5a1559..4210e51 100644
--- a/crypto/evp/p5_crpt2.c
+++ b/crypto/evp/p5_crpt2.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1999-2018 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
@@ -10,105 +10,51 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include "internal/cryptlib.h"
-# include <openssl/x509.h>
-# include <openssl/evp.h>
-# include <openssl/hmac.h>
-# include "evp_locl.h"
+#include <openssl/x509.h>
+#include <openssl/evp.h>
+#include <openssl/kdf.h>
+#include <openssl/hmac.h>
+#include "internal/evp_int.h"
+#include "evp_locl.h"
 
 /* set this to print out info about the keygen algorithm */
 /* #define OPENSSL_DEBUG_PKCS5V2 */
 
-# ifdef OPENSSL_DEBUG_PKCS5V2
+#ifdef OPENSSL_DEBUG_PKCS5V2
 static void h__dump(const unsigned char *p, int len);
-# endif
-
-/*
- * This is an implementation of PKCS#5 v2.0 password based encryption key
- * derivation function PBKDF2. SHA1 version verified against test vectors
- * posted by Peter Gutmann to the PKCS-TNG mailing list.
- */
+#endif
 
 int PKCS5_PBKDF2_HMAC(const char *pass, int passlen,
                       const unsigned char *salt, int saltlen, int iter,
                       const EVP_MD *digest, int keylen, unsigned char *out)
 {
     const char *empty = "";
-    unsigned char digtmp[EVP_MAX_MD_SIZE], *p, itmp[4];
-    int cplen, j, k, tkeylen, mdlen;
-    unsigned long i = 1;
-    HMAC_CTX *hctx_tpl = NULL, *hctx = NULL;
-
-    mdlen = EVP_MD_size(digest);
-    if (mdlen < 0)
-        return 0;
+    int rv = 1;
+    EVP_KDF_CTX *kctx;
 
-    hctx_tpl = HMAC_CTX_new();
-    if (hctx_tpl == NULL)
-        return 0;
-    p = out;
-    tkeylen = keylen;
+    /* Keep documented behaviour. */
     if (pass == NULL) {
         pass = empty;
         passlen = 0;
     } else if (passlen == -1) {
         passlen = strlen(pass);
     }
-    if (!HMAC_Init_ex(hctx_tpl, pass, passlen, digest, NULL)) {
-        HMAC_CTX_free(hctx_tpl);
-        return 0;
-    }
-    hctx = HMAC_CTX_new();
-    if (hctx == NULL) {
-        HMAC_CTX_free(hctx_tpl);
+    if (salt == NULL && saltlen == 0)
+        salt = (unsigned char *)empty;
+
+    kctx = EVP_KDF_CTX_new_id(EVP_KDF_PBKDF2);
+    if (kctx == NULL)
         return 0;
-    }
-    while (tkeylen) {
-        if (tkeylen > mdlen)
-            cplen = mdlen;
-        else
-            cplen = tkeylen;
-        /*
-         * We are unlikely to ever use more than 256 blocks (5120 bits!) but
-         * just in case...
-         */
-        itmp[0] = (unsigned char)((i >> 24) & 0xff);
-        itmp[1] = (unsigned char)((i >> 16) & 0xff);
-        itmp[2] = (unsigned char)((i >> 8) & 0xff);
-        itmp[3] = (unsigned char)(i & 0xff);
-        if (!HMAC_CTX_copy(hctx, hctx_tpl)) {
-            HMAC_CTX_free(hctx);
-            HMAC_CTX_free(hctx_tpl);
-            return 0;
-        }
-        if (!HMAC_Update(hctx, salt, saltlen)
-            || !HMAC_Update(hctx, itmp, 4)
-            || !HMAC_Final(hctx, digtmp, NULL)) {
-            HMAC_CTX_free(hctx);
-            HMAC_CTX_free(hctx_tpl);
-            return 0;
-        }
-        memcpy(p, digtmp, cplen);
-        for (j = 1; j < iter; j++) {
-            if (!HMAC_CTX_copy(hctx, hctx_tpl)) {
-                HMAC_CTX_free(hctx);
-                HMAC_CTX_free(hctx_tpl);
-                return 0;
-            }
-            if (!HMAC_Update(hctx, digtmp, mdlen)
-                || !HMAC_Final(hctx, digtmp, NULL)) {
-                HMAC_CTX_free(hctx);
-                HMAC_CTX_free(hctx_tpl);
-                return 0;
-            }
-            for (k = 0; k < cplen; k++)
-                p[k] ^= digtmp[k];
-        }
-        tkeylen -= cplen;
-        i++;
-        p += cplen;
-    }
-    HMAC_CTX_free(hctx);
-    HMAC_CTX_free(hctx_tpl);
+    if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_PASS, pass, (size_t)passlen) != 1
+            || EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_SALT,
+                            salt, (size_t)saltlen) != 1
+            || EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_ITER, iter) != 1
+            || EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_MD, digest) != 1
+            || EVP_KDF_derive(kctx, out, keylen) != 1)
+        rv = 0;
+
+    EVP_KDF_CTX_free(kctx);
+
 # ifdef OPENSSL_DEBUG_PKCS5V2
     fprintf(stderr, "Password:\n");
     h__dump(pass, passlen);
@@ -118,7 +64,7 @@ int PKCS5_PBKDF2_HMAC(const char *pass, int passlen,
     fprintf(stderr, "Key:\n");
     h__dump(out, keylen);
 # endif
-    return 1;
+    return rv;
 }
 
 int PKCS5_PBKDF2_HMAC_SHA1(const char *pass, int passlen,
diff --git a/crypto/evp/pbe_scrypt.c b/crypto/evp/pbe_scrypt.c
index 0a39432..f8ea1fa 100644
--- a/crypto/evp/pbe_scrypt.c
+++ b/crypto/evp/pbe_scrypt.c
@@ -7,135 +7,12 @@
  * https://www.openssl.org/source/license.html
  */
 
-#include <stddef.h>
-#include <stdio.h>
-#include <string.h>
 #include <openssl/evp.h>
 #include <openssl/err.h>
-#include "internal/numbers.h"
+#include <openssl/kdf.h>
 
 #ifndef OPENSSL_NO_SCRYPT
 
-#define R(a,b) (((a) << (b)) | ((a) >> (32 - (b))))
-static void salsa208_word_specification(uint32_t inout[16])
-{
-    int i;
-    uint32_t x[16];
-    memcpy(x, inout, sizeof(x));
-    for (i = 8; i > 0; i -= 2) {
-        x[4] ^= R(x[0] + x[12], 7);
-        x[8] ^= R(x[4] + x[0], 9);
-        x[12] ^= R(x[8] + x[4], 13);
-        x[0] ^= R(x[12] + x[8], 18);
-        x[9] ^= R(x[5] + x[1], 7);
-        x[13] ^= R(x[9] + x[5], 9);
-        x[1] ^= R(x[13] + x[9], 13);
-        x[5] ^= R(x[1] + x[13], 18);
-        x[14] ^= R(x[10] + x[6], 7);
-        x[2] ^= R(x[14] + x[10], 9);
-        x[6] ^= R(x[2] + x[14], 13);
-        x[10] ^= R(x[6] + x[2], 18);
-        x[3] ^= R(x[15] + x[11], 7);
-        x[7] ^= R(x[3] + x[15], 9);
-        x[11] ^= R(x[7] + x[3], 13);
-        x[15] ^= R(x[11] + x[7], 18);
-        x[1] ^= R(x[0] + x[3], 7);
-        x[2] ^= R(x[1] + x[0], 9);
-        x[3] ^= R(x[2] + x[1], 13);
-        x[0] ^= R(x[3] + x[2], 18);
-        x[6] ^= R(x[5] + x[4], 7);
-        x[7] ^= R(x[6] + x[5], 9);
-        x[4] ^= R(x[7] + x[6], 13);
-        x[5] ^= R(x[4] + x[7], 18);
-        x[11] ^= R(x[10] + x[9], 7);
-        x[8] ^= R(x[11] + x[10], 9);
-        x[9] ^= R(x[8] + x[11], 13);
-        x[10] ^= R(x[9] + x[8], 18);
-        x[12] ^= R(x[15] + x[14], 7);
-        x[13] ^= R(x[12] + x[15], 9);
-        x[14] ^= R(x[13] + x[12], 13);
-        x[15] ^= R(x[14] + x[13], 18);
-    }
-    for (i = 0; i < 16; ++i)
-        inout[i] += x[i];
-    OPENSSL_cleanse(x, sizeof(x));
-}
-
-static void scryptBlockMix(uint32_t *B_, uint32_t *B, uint64_t r)
-{
-    uint64_t i, j;
-    uint32_t X[16], *pB;
-
-    memcpy(X, B + (r * 2 - 1) * 16, sizeof(X));
-    pB = B;
-    for (i = 0; i < r * 2; i++) {
-        for (j = 0; j < 16; j++)
-            X[j] ^= *pB++;
-        salsa208_word_specification(X);
-        memcpy(B_ + (i / 2 + (i & 1) * r) * 16, X, sizeof(X));
-    }
-    OPENSSL_cleanse(X, sizeof(X));
-}
-
-static void scryptROMix(unsigned char *B, uint64_t r, uint64_t N,
-                        uint32_t *X, uint32_t *T, uint32_t *V)
-{
-    unsigned char *pB;
-    uint32_t *pV;
-    uint64_t i, k;
-
-    /* Convert from little endian input */
-    for (pV = V, i = 0, pB = B; i < 32 * r; i++, pV++) {
-        *pV = *pB++;
-        *pV |= *pB++ << 8;
-        *pV |= *pB++ << 16;
-        *pV |= (uint32_t)*pB++ << 24;
-    }
-
-    for (i = 1; i < N; i++, pV += 32 * r)
-        scryptBlockMix(pV, pV - 32 * r, r);
-
-    scryptBlockMix(X, V + (N - 1) * 32 * r, r);
-
-    for (i = 0; i < N; i++) {
-        uint32_t j;
-        j = X[16 * (2 * r - 1)] % N;
-        pV = V + 32 * r * j;
-        for (k = 0; k < 32 * r; k++)
-            T[k] = X[k] ^ *pV++;
-        scryptBlockMix(X, T, r);
-    }
-    /* Convert output to little endian */
-    for (i = 0, pB = B; i < 32 * r; i++) {
-        uint32_t xtmp = X[i];
-        *pB++ = xtmp & 0xff;
-        *pB++ = (xtmp >> 8) & 0xff;
-        *pB++ = (xtmp >> 16) & 0xff;
-        *pB++ = (xtmp >> 24) & 0xff;
-    }
-}
-
-#ifndef SIZE_MAX
-# define SIZE_MAX    ((size_t)-1)
-#endif
-
-/*
- * Maximum power of two that will fit in uint64_t: this should work on
- * most (all?) platforms.
- */
-
-#define LOG2_UINT64_MAX         (sizeof(uint64_t) * 8 - 1)
-
-/*
- * Maximum value of p * r:
- * p <= ((2^32-1) * hLen) / MFLen =>
- * p <= ((2^32-1) * 32) / (128 * r) =>
- * p * r <= (2^30-1)
- *
- */
-
-#define SCRYPT_PR_MAX   ((1 << 30) - 1)
-
 /*
  * Maximum permitted memory allow this to be overridden with Configuration
  * option: e.g. -DSCRYPT_MAX_MEM=0 for maximum possible.
@@ -160,107 +37,38 @@ int EVP_PBE_scrypt(const char *pass, size_t passlen,
                    uint64_t N, uint64_t r, uint64_t p, uint64_t maxmem,
                    unsigned char *key, size_t keylen)
 {
-    int rv = 0;
-    unsigned char *B;
-    uint32_t *X, *V, *T;
-    uint64_t i, Blen, Vlen;
-
-    /* Sanity check parameters */
-    /* initial check, r,p must be non zero, N >= 2 and a power of 2 */
-    if (r == 0 || p == 0 || N < 2 || (N & (N - 1)))
-        return 0;
-    /* Check p * r < SCRYPT_PR_MAX avoiding overflow */
-    if (p > SCRYPT_PR_MAX / r) {
-        EVPerr(EVP_F_EVP_PBE_SCRYPT, EVP_R_MEMORY_LIMIT_EXCEEDED);
-        return 0;
-    }
-
-    /*
-     * Need to check N: if 2^(128 * r / 8) overflows limit this is
-     * automatically satisfied since N <= UINT64_MAX.
-     */
-
-    if (16 * r <= LOG2_UINT64_MAX) {
-        if (N >= (((uint64_t)1) << (16 * r))) {
-            EVPerr(EVP_F_EVP_PBE_SCRYPT, EVP_R_MEMORY_LIMIT_EXCEEDED);
-            return 0;
-        }
+    const char *empty = "";
+    int rv = 1;
+    EVP_KDF_CTX *kctx;
+
+    /* Maintain existing behaviour. */
+    if (pass == NULL) {
+        pass = empty;
+        passlen = 0;
     }
-
-    /* Memory checks: check total allocated buffer size fits in uint64_t */
-
-    /*
-     * B size in section 5 step 1.S
-     * Note: we know p * 128 * r < UINT64_MAX because we already checked
-     * p * r < SCRYPT_PR_MAX
-     */
-    Blen = p * 128 * r;
-    /*
-     * Yet we pass it as integer to PKCS5_PBKDF2_HMAC... [This would
-     * have to be revised when/if PKCS5_PBKDF2_HMAC accepts size_t.]
-     */
-    if (Blen > INT_MAX) {
-        EVPerr(EVP_F_EVP_PBE_SCRYPT, EVP_R_MEMORY_LIMIT_EXCEEDED);
-        return 0;
-    }
-
-    /*
-     * Check 32 * r * (N + 2) * sizeof(uint32_t) fits in uint64_t
-     * This is combined size V, X and T (section 4)
-     */
-    i = UINT64_MAX / (32 * sizeof(uint32_t));
-    if (N + 2 > i / r) {
-        EVPerr(EVP_F_EVP_PBE_SCRYPT, EVP_R_MEMORY_LIMIT_EXCEEDED);
-        return 0;
-    }
-    Vlen = 32 * r * (N + 2) * sizeof(uint32_t);
-
-    /* check total allocated size fits in uint64_t */
-    if (Blen > UINT64_MAX - Vlen) {
-        EVPerr(EVP_F_EVP_PBE_SCRYPT, EVP_R_MEMORY_LIMIT_EXCEEDED);
-        return 0;
-    }
-
     if (maxmem == 0)
         maxmem = SCRYPT_MAX_MEM;
 
-    /* Check that the maximum memory doesn't exceed a size_t limits */
-    if (maxmem > SIZE_MAX)
-        maxmem = SIZE_MAX;
-
-    if (Blen + Vlen > maxmem) {
-        EVPerr(EVP_F_EVP_PBE_SCRYPT, EVP_R_MEMORY_LIMIT_EXCEEDED);
+    kctx = EVP_KDF_CTX_new_id(EVP_KDF_SCRYPT);
+    if (kctx == NULL)
         return 0;
-    }
-
-    /* If no key return to indicate parameters are OK */
-    if (key == NULL)
-        return 1;
 
-    B = OPENSSL_malloc((size_t)(Blen + Vlen));
-    if (B == NULL) {
-        EVPerr(EVP_F_EVP_PBE_SCRYPT, ERR_R_MALLOC_FAILURE);
+    if (r > UINT32_MAX || p > UINT32_MAX) {
+        EVPerr(EVP_F_EVP_PBE_SCRYPT, EVP_R_PARAMETER_TOO_LARGE);
         return 0;
     }
-    X = (uint32_t *)(B + Blen);
-    T = X + 32 * r;
-    V = T + 32 * r;
-    if (PKCS5_PBKDF2_HMAC(pass, passlen, salt, saltlen, 1, EVP_sha256(),
-                          (int)Blen, B) == 0)
-        goto err;
-
-    for (i = 0; i < p; i++)
-        scryptROMix(B + 128 * r * i, r, N, X, T, V);
-
-    if (PKCS5_PBKDF2_HMAC(pass, passlen, B, (int)Blen, 1, EVP_sha256(),
-                          keylen, key) == 0)
-        goto err;
-    rv = 1;
- err:
-    if (rv == 0)
-        EVPerr(EVP_F_EVP_PBE_SCRYPT, EVP_R_PBKDF2_ERROR);
-
-    OPENSSL_clear_free(B, (size_t)(Blen + Vlen));
+    if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_PASS, pass, (size_t)passlen) != 1
+            || EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_SALT,
+                            salt, (size_t)saltlen) != 1
+            || EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_SCRYPT_N, N) != 1
+            || EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_SCRYPT_R, (uint32_t)r) != 1
+            || EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_SCRYPT_P, (uint32_t)p) != 1
+            || EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_MAXMEM_BYTES, maxmem) != 1
+            || EVP_KDF_derive(kctx, key, keylen) != 1)
+        rv = 0;
+
+    EVP_KDF_CTX_free(kctx);
     return rv;
 }
+
 #endif
diff --git a/crypto/evp/pkey_kdf.c b/crypto/evp/pkey_kdf.c
new file mode 100644
index 0000000..ddb682c
--- /dev/null
+++ b/crypto/evp/pkey_kdf.c
@@ -0,0 +1,255 @@
+/*
+ * Copyright 2018 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/kdf.h>
+#include "internal/evp_int.h"
+
+static int pkey_kdf_init(EVP_PKEY_CTX *ctx)
+{
+    EVP_KDF_CTX *kctx;
+
+    kctx = EVP_KDF_CTX_new_id(ctx->pmeth->pkey_id);
+    if (kctx == NULL)
+        return 0;
+
+    ctx->data = kctx;
+    return 1;
+}
+
+static void pkey_kdf_cleanup(EVP_PKEY_CTX *ctx)
+{
+    EVP_KDF_CTX *kctx = ctx->data;
+
+    EVP_KDF_CTX_free(kctx);
+}
+
+static int pkey_kdf_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
+{
+    EVP_KDF_CTX *kctx = ctx->data;
+    uint64_t u64_value;
+    int cmd;
+    int ret;
+
+    switch (type) {
+    case EVP_PKEY_CTRL_PASS:
+        cmd = EVP_KDF_CTRL_SET_PASS;
+        break;
+    case EVP_PKEY_CTRL_HKDF_SALT:
+    case EVP_PKEY_CTRL_SCRYPT_SALT:
+        cmd = EVP_KDF_CTRL_SET_SALT;
+        break;
+    case EVP_PKEY_CTRL_TLS_MD:
+    case EVP_PKEY_CTRL_HKDF_MD:
+        cmd = EVP_KDF_CTRL_SET_MD;
+        break;
+    case EVP_PKEY_CTRL_TLS_SECRET:
+        cmd = EVP_KDF_CTRL_SET_TLS_SECRET;
+        ret = EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_RESET_TLS_SEED);
+        if (ret < 1)
+            return ret;
+        break;
+    case EVP_PKEY_CTRL_TLS_SEED:
+        cmd = EVP_KDF_CTRL_ADD_TLS_SEED;
+        break;
+    case EVP_PKEY_CTRL_HKDF_KEY:
+        cmd = EVP_KDF_CTRL_SET_KEY;
+        break;
+    case EVP_PKEY_CTRL_HKDF_INFO:
+        cmd = EVP_KDF_CTRL_ADD_HKDF_INFO;
+        break;
+    case EVP_PKEY_CTRL_HKDF_MODE:
+        cmd = EVP_KDF_CTRL_SET_HKDF_MODE;
+        break;
+    case EVP_PKEY_CTRL_SCRYPT_N:
+        cmd = EVP_KDF_CTRL_SET_SCRYPT_N;
+        break;
+    case EVP_PKEY_CTRL_SCRYPT_R:
+        cmd = EVP_KDF_CTRL_SET_SCRYPT_R;
+        break;
+    case EVP_PKEY_CTRL_SCRYPT_P:
+        cmd = EVP_KDF_CTRL_SET_SCRYPT_P;
+        break;
+    case EVP_PKEY_CTRL_SCRYPT_MAXMEM_BYTES:
+        cmd = EVP_KDF_CTRL_SET_MAXMEM_BYTES;
+        break;
+    default:
+        return -2;
+    }
+
+    switch (cmd) {
+    case EVP_KDF_CTRL_SET_PASS:
+    case EVP_KDF_CTRL_SET_SALT:
+    case EVP_KDF_CTRL_SET_KEY:
+    case EVP_KDF_CTRL_SET_TLS_SECRET:
+    case EVP_KDF_CTRL_ADD_TLS_SEED:
+    case EVP_KDF_CTRL_ADD_HKDF_INFO:
+        return EVP_KDF_ctrl(kctx, cmd, (const unsigned char *)p2, (size_t)p1);
+
+    case EVP_KDF_CTRL_SET_MD:
+        return EVP_KDF_ctrl(kctx, cmd, (const EVP_MD *)p2);
+
+    case EVP_KDF_CTRL_SET_HKDF_MODE:
+        return EVP_KDF_ctrl(kctx, cmd, (int)p1);
+
+    case EVP_KDF_CTRL_SET_SCRYPT_R:
+    case EVP_KDF_CTRL_SET_SCRYPT_P:
+        u64_value = *(uint64_t *)p2;
+        if (u64_value > UINT32_MAX) {
+            EVPerr(EVP_F_PKEY_KDF_CTRL, EVP_R_PARAMETER_TOO_LARGE);
+            return 0;
+        }
+
+        return EVP_KDF_ctrl(kctx, cmd, (uint32_t)u64_value);
+
+    case EVP_KDF_CTRL_SET_SCRYPT_N:
+    case EVP_KDF_CTRL_SET_MAXMEM_BYTES:
+        return EVP_KDF_ctrl(kctx, cmd, *(uint64_t *)p2);
+
+    default:
+        return 0;
+    }
+}
+
+static int pkey_kdf_ctrl_str(EVP_PKEY_CTX *ctx, const char *type,
+                             const char *value)
+{
+    EVP_KDF_CTX *kctx = ctx->data;
+
+    if (strcmp(type, "md") == 0)
+        return EVP_KDF_ctrl_str(kctx, "digest", value);
+    return EVP_KDF_ctrl_str(kctx, type, value);
+}
+
+static int pkey_kdf_derive_init(EVP_PKEY_CTX *ctx)
+{
+    EVP_KDF_CTX *kctx = ctx->data;
+
+    EVP_KDF_reset(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_KDF_CTX *kctx = ctx->data;
+    size_t outlen = EVP_KDF_size(kctx);
+
+    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
+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
+};
+#endif
+
+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 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
+};
+
diff --git a/crypto/include/internal/evp_int.h b/crypto/include/internal/evp_int.h
index 189d8aa..b3dbbe2 100644
--- a/crypto/include/internal/evp_int.h
+++ b/crypto/include/internal/evp_int.h
@@ -151,6 +151,24 @@ const EVP_MD *evp_keccak_kmac256(void);
  */
 int EVP_add_mac(const EVP_MAC *mac);
 
+/* struct evp_kdf_impl_st is defined by the implementation */
+typedef struct evp_kdf_impl_st EVP_KDF_IMPL;
+typedef struct {
+    int type;
+    EVP_KDF_IMPL *(*new) (void);
+    void (*free) (EVP_KDF_IMPL *impl);
+    void (*reset) (EVP_KDF_IMPL *impl);
+    int (*ctrl) (EVP_KDF_IMPL *impl, int cmd, va_list args);
+    int (*ctrl_str) (EVP_KDF_IMPL *impl, const char *type, const char *value);
+    size_t (*size) (EVP_KDF_IMPL *impl);
+    int (*derive) (EVP_KDF_IMPL *impl, unsigned char *key, size_t keylen);
+} EVP_KDF_METHOD;
+
+extern const EVP_KDF_METHOD pbkdf2_kdf_meth;
+extern const EVP_KDF_METHOD scrypt_kdf_meth;
+extern const EVP_KDF_METHOD tls1_prf_kdf_meth;
+extern const EVP_KDF_METHOD hkdf_kdf_meth;
+
 struct evp_md_st {
     int type;
     int pkey_type;
diff --git a/crypto/kdf/build.info b/crypto/kdf/build.info
index c166399..dce960e 100644
--- a/crypto/kdf/build.info
+++ b/crypto/kdf/build.info
@@ -1,3 +1,3 @@
 LIBS=../../libcrypto
 SOURCE[../../libcrypto]=\
-        tls1_prf.c kdf_err.c hkdf.c scrypt.c
+        tls1_prf.c kdf_err.c kdf_util.c hkdf.c scrypt.c pbkdf2.c
diff --git a/crypto/kdf/hkdf.c b/crypto/kdf/hkdf.c
index dc2ead6..5540da3 100644
--- a/crypto/kdf/hkdf.c
+++ b/crypto/kdf/hkdf.c
@@ -8,32 +8,33 @@
  */
 
 #include <stdlib.h>
+#include <stdarg.h>
 #include <string.h>
 #include <openssl/hmac.h>
-#include <openssl/kdf.h>
 #include <openssl/evp.h>
+#include <openssl/kdf.h>
 #include "internal/cryptlib.h"
 #include "internal/evp_int.h"
+#include "kdf_local.h"
 
 #define HKDF_MAXBUF 1024
 
-static unsigned char *HKDF(const EVP_MD *evp_md,
-                           const unsigned char *salt, size_t salt_len,
-                           const unsigned char *key, size_t key_len,
-                           const unsigned char *info, size_t info_len,
-                           unsigned char *okm, size_t okm_len);
-
-static unsigned char *HKDF_Extract(const EVP_MD *evp_md,
-                                   const unsigned char *salt, size_t salt_len,
-                                   const unsigned char *key, size_t key_len,
-                                   unsigned char *prk, size_t *prk_len);
-
-static unsigned char *HKDF_Expand(const EVP_MD *evp_md,
-                                  const unsigned char *prk, size_t prk_len,
-                                  const unsigned char *info, size_t info_len,
-                                  unsigned char *okm, size_t okm_len);
-
-typedef struct {
+static void kdf_hkdf_reset(EVP_KDF_IMPL *impl);
+static int HKDF(const EVP_MD *evp_md,
+                const unsigned char *salt, size_t salt_len,
+                const unsigned char *key, size_t key_len,
+                const unsigned char *info, size_t info_len,
+                unsigned char *okm, size_t okm_len);
+static int HKDF_Extract(const EVP_MD *evp_md,
+                        const unsigned char *salt, size_t salt_len,
+                        const unsigned char *key, size_t key_len,
+                        unsigned char *prk, size_t prk_len);
+static int HKDF_Expand(const EVP_MD *evp_md,
+                       const unsigned char *prk, size_t prk_len,
+                       const unsigned char *info, size_t info_len,
+                       unsigned char *okm, size_t okm_len);
+
+struct evp_kdf_impl_st {
     int mode;
     const EVP_MD *md;
     unsigned char *salt;
@@ -42,230 +43,208 @@ typedef struct {
     size_t key_len;
     unsigned char info[HKDF_MAXBUF];
     size_t info_len;
-} HKDF_PKEY_CTX;
+};
 
-static int pkey_hkdf_init(EVP_PKEY_CTX *ctx)
+static EVP_KDF_IMPL *kdf_hkdf_new(void)
 {
-    HKDF_PKEY_CTX *kctx;
+    EVP_KDF_IMPL *impl;
 
-    if ((kctx = OPENSSL_zalloc(sizeof(*kctx))) == NULL) {
-        KDFerr(KDF_F_PKEY_HKDF_INIT, ERR_R_MALLOC_FAILURE);
-        return 0;
-    }
-
-    ctx->data = kctx;
+    if ((impl = OPENSSL_zalloc(sizeof(*impl))) == NULL)
+        KDFerr(KDF_F_KDF_HKDF_NEW, ERR_R_MALLOC_FAILURE);
+    return impl;
+}
 
-    return 1;
+static void kdf_hkdf_free(EVP_KDF_IMPL *impl)
+{
+    kdf_hkdf_reset(impl);
+    OPENSSL_free(impl);
 }
 
-static void pkey_hkdf_cleanup(EVP_PKEY_CTX *ctx)
+static void kdf_hkdf_reset(EVP_KDF_IMPL *impl)
 {
-    HKDF_PKEY_CTX *kctx = ctx->data;
-    OPENSSL_clear_free(kctx->salt, kctx->salt_len);
-    OPENSSL_clear_free(kctx->key, kctx->key_len);
-    OPENSSL_cleanse(kctx->info, kctx->info_len);
-    OPENSSL_free(kctx);
+    OPENSSL_free(impl->salt);
+    OPENSSL_clear_free(impl->key, impl->key_len);
+    OPENSSL_cleanse(impl->info, impl->info_len);
+    memset(impl, 0, sizeof(*impl));
 }
 
-static int pkey_hkdf_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
+static int kdf_hkdf_ctrl(EVP_KDF_IMPL *impl, int cmd, va_list args)
 {
-    HKDF_PKEY_CTX *kctx = ctx->data;
+    const unsigned char *p;
+    size_t len;
+    const EVP_MD *md;
 
-    switch (type) {
-    case EVP_PKEY_CTRL_HKDF_MD:
-        if (p2 == NULL)
+    switch (cmd) {
+    case EVP_KDF_CTRL_SET_MD:
+        md = va_arg(args, const EVP_MD *);
+        if (md == NULL)
             return 0;
 
-        kctx->md = p2;
+        impl->md = md;
         return 1;
 
-    case EVP_PKEY_CTRL_HKDF_MODE:
-        kctx->mode = p1;
+    case EVP_KDF_CTRL_SET_HKDF_MODE:
+        impl->mode = va_arg(args, int);
         return 1;
 
-    case EVP_PKEY_CTRL_HKDF_SALT:
-        if (p1 == 0 || p2 == NULL)
+    case EVP_KDF_CTRL_SET_SALT:
+        p = va_arg(args, const unsigned char *);
+        len = va_arg(args, size_t);
+        if (len == 0 || p == NULL)
             return 1;
 
-        if (p1 < 0)
+        OPENSSL_free(impl->salt);
+        impl->salt = OPENSSL_memdup(p, len);
+        if (impl->salt == NULL)
             return 0;
 
-        if (kctx->salt != NULL)
-            OPENSSL_clear_free(kctx->salt, kctx->salt_len);
-
-        kctx->salt = OPENSSL_memdup(p2, p1);
-        if (kctx->salt == NULL)
-            return 0;
-
-        kctx->salt_len = p1;
+        impl->salt_len = len;
         return 1;
 
-    case EVP_PKEY_CTRL_HKDF_KEY:
-        if (p1 < 0)
+    case EVP_KDF_CTRL_SET_KEY:
+        p = va_arg(args, const unsigned char *);
+        len = va_arg(args, size_t);
+        OPENSSL_clear_free(impl->key, impl->key_len);
+        impl->key = OPENSSL_memdup(p, len);
+        if (impl->key == NULL)
             return 0;
 
-        if (kctx->key != NULL)
-            OPENSSL_clear_free(kctx->key, kctx->key_len);
-
-        kctx->key = OPENSSL_memdup(p2, p1);
-        if (kctx->key == NULL)
-            return 0;
+        impl->key_len  = len;
+        return 1;
 
-        kctx->key_len  = p1;
+    case EVP_KDF_CTRL_RESET_HKDF_INFO:
+        OPENSSL_cleanse(impl->info, impl->info_len);
+        impl->info_len = 0;
         return 1;
 
-    case EVP_PKEY_CTRL_HKDF_INFO:
-        if (p1 == 0 || p2 == NULL)
+    case EVP_KDF_CTRL_ADD_HKDF_INFO:
+        p = va_arg(args, const unsigned char *);
+        len = va_arg(args, size_t);
+        if (len == 0 || p == NULL)
             return 1;
 
-        if (p1 < 0 || p1 > (int)(HKDF_MAXBUF - kctx->info_len))
+        if (len > (HKDF_MAXBUF - impl->info_len))
             return 0;
 
-        memcpy(kctx->info + kctx->info_len, p2, p1);
-        kctx->info_len += p1;
+        memcpy(impl->info + impl->info_len, p, len);
+        impl->info_len += len;
         return 1;
 
     default:
         return -2;
-
     }
 }
 
-static int pkey_hkdf_ctrl_str(EVP_PKEY_CTX *ctx, const char *type,
-                              const char *value)
+static int kdf_hkdf_ctrl_str(EVP_KDF_IMPL *impl, const char *type,
+                             const char *value)
 {
     if (strcmp(type, "mode") == 0) {
         int mode;
 
         if (strcmp(value, "EXTRACT_AND_EXPAND") == 0)
-            mode = EVP_PKEY_HKDEF_MODE_EXTRACT_AND_EXPAND;
+            mode = EVP_KDF_HKDF_MODE_EXTRACT_AND_EXPAND;
         else if (strcmp(value, "EXTRACT_ONLY") == 0)
-            mode = EVP_PKEY_HKDEF_MODE_EXTRACT_ONLY;
+            mode = EVP_KDF_HKDF_MODE_EXTRACT_ONLY;
         else if (strcmp(value, "EXPAND_ONLY") == 0)
-            mode = EVP_PKEY_HKDEF_MODE_EXPAND_ONLY;
+            mode = EVP_KDF_HKDF_MODE_EXPAND_ONLY;
         else
             return 0;
 
-        return EVP_PKEY_CTX_hkdf_mode(ctx, mode);
+        return call_ctrl(kdf_hkdf_ctrl, impl, EVP_KDF_CTRL_SET_HKDF_MODE, mode);
     }
 
-    if (strcmp(type, "md") == 0)
-        return EVP_PKEY_CTX_md(ctx, EVP_PKEY_OP_DERIVE,
-                               EVP_PKEY_CTRL_HKDF_MD, value);
+    if (strcmp(type, "digest") == 0)
+        return kdf_md2ctrl(impl, kdf_hkdf_ctrl, EVP_KDF_CTRL_SET_MD, value);
 
     if (strcmp(type, "salt") == 0)
-        return EVP_PKEY_CTX_str2ctrl(ctx, EVP_PKEY_CTRL_HKDF_SALT, value);
+        return kdf_str2ctrl(impl, kdf_hkdf_ctrl, EVP_KDF_CTRL_SET_SALT, value);
 
     if (strcmp(type, "hexsalt") == 0)
-        return EVP_PKEY_CTX_hex2ctrl(ctx, EVP_PKEY_CTRL_HKDF_SALT, value);
+        return kdf_hex2ctrl(impl, kdf_hkdf_ctrl, EVP_KDF_CTRL_SET_SALT, value);
 
     if (strcmp(type, "key") == 0)
-        return EVP_PKEY_CTX_str2ctrl(ctx, EVP_PKEY_CTRL_HKDF_KEY, value);
+        return kdf_str2ctrl(impl, kdf_hkdf_ctrl, EVP_KDF_CTRL_SET_KEY, value);
 
     if (strcmp(type, "hexkey") == 0)
-        return EVP_PKEY_CTX_hex2ctrl(ctx, EVP_PKEY_CTRL_HKDF_KEY, value);
+        return kdf_hex2ctrl(impl, kdf_hkdf_ctrl, EVP_KDF_CTRL_SET_KEY, value);
 
     if (strcmp(type, "info") == 0)
-        return EVP_PKEY_CTX_str2ctrl(ctx, EVP_PKEY_CTRL_HKDF_INFO, value);
+        return kdf_str2ctrl(impl, kdf_hkdf_ctrl, EVP_KDF_CTRL_ADD_HKDF_INFO,
+                            value);
 
     if (strcmp(type, "hexinfo") == 0)
-        return EVP_PKEY_CTX_hex2ctrl(ctx, EVP_PKEY_CTRL_HKDF_INFO, value);
+        return kdf_hex2ctrl(impl, kdf_hkdf_ctrl, EVP_KDF_CTRL_ADD_HKDF_INFO,
+                            value);
 
-    KDFerr(KDF_F_PKEY_HKDF_CTRL_STR, KDF_R_UNKNOWN_PARAMETER_TYPE);
     return -2;
 }
 
-static int pkey_hkdf_derive_init(EVP_PKEY_CTX *ctx)
+static size_t kdf_hkdf_size(EVP_KDF_IMPL *impl)
 {
-    HKDF_PKEY_CTX *kctx = ctx->data;
-
-    OPENSSL_clear_free(kctx->key, kctx->key_len);
-    OPENSSL_clear_free(kctx->salt, kctx->salt_len);
-    OPENSSL_cleanse(kctx->info, kctx->info_len);
-    memset(kctx, 0, sizeof(*kctx));
+    if (impl->mode != EVP_KDF_HKDF_MODE_EXTRACT_ONLY)
+        return SIZE_MAX;
 
-    return 1;
+    if (impl->md == NULL) {
+        KDFerr(KDF_F_KDF_HKDF_SIZE, KDF_R_MISSING_MESSAGE_DIGEST);
+        return 0;
+    }
+    return EVP_MD_size(impl->md);
 }
 
-static int pkey_hkdf_derive(EVP_PKEY_CTX *ctx, unsigned char *key,
-                            size_t *keylen)
+static int kdf_hkdf_derive(EVP_KDF_IMPL *impl, unsigned char *key,
+                           size_t keylen)
 {
-    HKDF_PKEY_CTX *kctx = ctx->data;
-
-    if (kctx->md == NULL) {
-        KDFerr(KDF_F_PKEY_HKDF_DERIVE, KDF_R_MISSING_MESSAGE_DIGEST);
+    if (impl->md == NULL) {
+        KDFerr(KDF_F_KDF_HKDF_DERIVE, KDF_R_MISSING_MESSAGE_DIGEST);
         return 0;
     }
-    if (kctx->key == NULL) {
-        KDFerr(KDF_F_PKEY_HKDF_DERIVE, KDF_R_MISSING_KEY);
+    if (impl->key == NULL) {
+        KDFerr(KDF_F_KDF_HKDF_DERIVE, KDF_R_MISSING_KEY);
         return 0;
     }
 
-    switch (kctx->mode) {
-    case EVP_PKEY_HKDEF_MODE_EXTRACT_AND_EXPAND:
-        return HKDF(kctx->md, kctx->salt, kctx->salt_len, kctx->key,
-                    kctx->key_len, kctx->info, kctx->info_len, key,
-                    *keylen) != NULL;
+    switch (impl->mode) {
+    case EVP_KDF_HKDF_MODE_EXTRACT_AND_EXPAND:
+        return HKDF(impl->md, impl->salt, impl->salt_len, impl->key,
+                    impl->key_len, impl->info, impl->info_len, key,
+                    keylen);
 
-    case EVP_PKEY_HKDEF_MODE_EXTRACT_ONLY:
-        if (key == NULL) {
-            *keylen = EVP_MD_size(kctx->md);
-            return 1;
-        }
-        return HKDF_Extract(kctx->md, kctx->salt, kctx->salt_len, kctx->key,
-                            kctx->key_len, key, keylen) != NULL;
+    case EVP_KDF_HKDF_MODE_EXTRACT_ONLY:
+        return HKDF_Extract(impl->md, impl->salt, impl->salt_len, impl->key,
+                            impl->key_len, key, keylen);
 
-    case EVP_PKEY_HKDEF_MODE_EXPAND_ONLY:
-        return HKDF_Expand(kctx->md, kctx->key, kctx->key_len, kctx->info,
-                           kctx->info_len, key, *keylen) != NULL;
+    case EVP_KDF_HKDF_MODE_EXPAND_ONLY:
+        return HKDF_Expand(impl->md, impl->key, impl->key_len, impl->info,
+                           impl->info_len, key, keylen);
 
     default:
         return 0;
     }
 }
 
-const EVP_PKEY_METHOD hkdf_pkey_meth = {
-    EVP_PKEY_HKDF,
-    0,
-    pkey_hkdf_init,
-    0,
-    pkey_hkdf_cleanup,
-
-    0, 0,
-    0, 0,
-
-    0,
-    0,
-
-    0,
-    0,
-
-    0, 0,
-
-    0, 0, 0, 0,
-
-    0, 0,
-
-    0, 0,
-
-    pkey_hkdf_derive_init,
-    pkey_hkdf_derive,
-    pkey_hkdf_ctrl,
-    pkey_hkdf_ctrl_str
+const EVP_KDF_METHOD hkdf_kdf_meth = {
+    EVP_KDF_HKDF,
+    kdf_hkdf_new,
+    kdf_hkdf_free,
+    kdf_hkdf_reset,
+    kdf_hkdf_ctrl,
+    kdf_hkdf_ctrl_str,
+    kdf_hkdf_size,
+    kdf_hkdf_derive
 };
 
-static unsigned char *HKDF(const EVP_MD *evp_md,
-                           const unsigned char *salt, size_t salt_len,
-                           const unsigned char *key, size_t key_len,
-                           const unsigned char *info, size_t info_len,
-                           unsigned char *okm, size_t okm_len)
+static int HKDF(const EVP_MD *evp_md,
+                const unsigned char *salt, size_t salt_len,
+                const unsigned char *key, size_t key_len,
+                const unsigned char *info, size_t info_len,
+                unsigned char *okm, size_t okm_len)
 {
     unsigned char prk[EVP_MAX_MD_SIZE];
-    unsigned char *ret;
-    size_t prk_len;
+    int ret;
+    size_t prk_len = EVP_MD_size(evp_md);
 
-    if (!HKDF_Extract(evp_md, salt, salt_len, key, key_len, prk, &prk_len))
-        return NULL;
+    if (!HKDF_Extract(evp_md, salt, salt_len, key, key_len, prk, prk_len))
+        return 0;
 
     ret = HKDF_Expand(evp_md, prk, prk_len, info, info_len, okm, okm_len);
     OPENSSL_cleanse(prk, sizeof(prk));
@@ -273,43 +252,38 @@ static unsigned char *HKDF(const EVP_MD *evp_md,
     return ret;
 }
 
-static unsigned char *HKDF_Extract(const EVP_MD *evp_md,
-                                   const unsigned char *salt, size_t salt_len,
-                                   const unsigned char *key, size_t key_len,
-                                   unsigned char *prk, size_t *prk_len)
+static int HKDF_Extract(const EVP_MD *evp_md,
+                        const unsigned char *salt, size_t salt_len,
+                        const unsigned char *key, size_t key_len,
+                        unsigned char *prk, size_t prk_len)
 {
-    unsigned int tmp_len;
-
-    if (!HMAC(evp_md, salt, salt_len, key, key_len, prk, &tmp_len))
-        return NULL;
-
-    *prk_len = tmp_len;
-    return prk;
+    if (prk_len != (size_t)EVP_MD_size(evp_md)) {
+        KDFerr(KDF_F_HKDF_EXTRACT, KDF_R_WRONG_OUTPUT_BUFFER_SIZE);
+        return 0;
+    }
+    return HMAC(evp_md, salt, salt_len, key, key_len, prk, NULL) != NULL;
 }
 
-static unsigned char *HKDF_Expand(const EVP_MD *evp_md,
-                                  const unsigned char *prk, size_t prk_len,
-                                  const unsigned char *info, size_t info_len,
-                                  unsigned char *okm, size_t okm_len)
+static int HKDF_Expand(const EVP_MD *evp_md,
+                       const unsigned char *prk, size_t prk_len,
+                       const unsigned char *info, size_t info_len,
+                       unsigned char *okm, size_t okm_len)
 {
     HMAC_CTX *hmac;
-    unsigned char *ret = NULL;
-
+    int ret = 0;
     unsigned int i;
-
     unsigned char prev[EVP_MAX_MD_SIZE];
-
     size_t done_len = 0, dig_len = EVP_MD_size(evp_md);
-
     size_t n = okm_len / dig_len;
+
     if (okm_len % dig_len)
         n++;
 
     if (n > 255 || okm == NULL)
-        return NULL;
+        return 0;
 
     if ((hmac = HMAC_CTX_new()) == NULL)
-        return NULL;
+        return 0;
 
     if (!HMAC_Init_ex(hmac, prk, prk_len, evp_md, NULL))
         goto err;
@@ -343,7 +317,7 @@ static unsigned char *HKDF_Expand(const EVP_MD *evp_md,
 
         done_len += copy_len;
     }
-    ret = okm;
+    ret = 1;
 
  err:
     OPENSSL_cleanse(prev, sizeof(prev));
diff --git a/crypto/kdf/kdf_err.c b/crypto/kdf/kdf_err.c
index 92e6a0c..b62c25f 100644
--- a/crypto/kdf/kdf_err.c
+++ b/crypto/kdf/kdf_err.c
@@ -1,6 +1,6 @@
 /*
  * Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -14,6 +14,29 @@
 #ifndef OPENSSL_NO_ERR
 
 static const ERR_STRING_DATA KDF_str_functs[] = {
+    {ERR_PACK(ERR_LIB_KDF, KDF_F_HKDF_EXTRACT, 0), "HKDF_Extract"},
+    {ERR_PACK(ERR_LIB_KDF, KDF_F_KDF_HKDF_DERIVE, 0), "kdf_hkdf_derive"},
+    {ERR_PACK(ERR_LIB_KDF, KDF_F_KDF_HKDF_NEW, 0), "kdf_hkdf_new"},
+    {ERR_PACK(ERR_LIB_KDF, KDF_F_KDF_HKDF_SIZE, 0), "kdf_hkdf_size"},
+    {ERR_PACK(ERR_LIB_KDF, KDF_F_KDF_MD2CTRL, 0), "kdf_md2ctrl"},
+    {ERR_PACK(ERR_LIB_KDF, KDF_F_KDF_PBKDF2_CTRL_STR, 0),
+     "kdf_pbkdf2_ctrl_str"},
+    {ERR_PACK(ERR_LIB_KDF, KDF_F_KDF_PBKDF2_DERIVE, 0), "kdf_pbkdf2_derive"},
+    {ERR_PACK(ERR_LIB_KDF, KDF_F_KDF_PBKDF2_NEW, 0), "kdf_pbkdf2_new"},
+    {ERR_PACK(ERR_LIB_KDF, KDF_F_KDF_SCRYPT_CTRL_STR, 0),
+     "kdf_scrypt_ctrl_str"},
+    {ERR_PACK(ERR_LIB_KDF, KDF_F_KDF_SCRYPT_CTRL_UINT32, 0),
+     "kdf_scrypt_ctrl_uint32"},
+    {ERR_PACK(ERR_LIB_KDF, KDF_F_KDF_SCRYPT_CTRL_UINT64, 0),
+     "kdf_scrypt_ctrl_uint64"},
+    {ERR_PACK(ERR_LIB_KDF, KDF_F_KDF_SCRYPT_DERIVE, 0), "kdf_scrypt_derive"},
+    {ERR_PACK(ERR_LIB_KDF, KDF_F_KDF_SCRYPT_NEW, 0), "kdf_scrypt_new"},
+    {ERR_PACK(ERR_LIB_KDF, KDF_F_KDF_TLS1_PRF_CTRL_STR, 0),
+     "kdf_tls1_prf_ctrl_str"},
+    {ERR_PACK(ERR_LIB_KDF, KDF_F_KDF_TLS1_PRF_DERIVE, 0),
+     "kdf_tls1_prf_derive"},
+    {ERR_PACK(ERR_LIB_KDF, KDF_F_KDF_TLS1_PRF_NEW, 0), "kdf_tls1_prf_new"},
+    {ERR_PACK(ERR_LIB_KDF, KDF_F_PBKDF2_SET_MEMBUF, 0), "pbkdf2_set_membuf"},
     {ERR_PACK(ERR_LIB_KDF, KDF_F_PKEY_HKDF_CTRL_STR, 0), "pkey_hkdf_ctrl_str"},
     {ERR_PACK(ERR_LIB_KDF, KDF_F_PKEY_HKDF_DERIVE, 0), "pkey_hkdf_derive"},
     {ERR_PACK(ERR_LIB_KDF, KDF_F_PKEY_HKDF_INIT, 0), "pkey_hkdf_init"},
@@ -30,6 +53,7 @@ static const ERR_STRING_DATA KDF_str_functs[] = {
     {ERR_PACK(ERR_LIB_KDF, KDF_F_PKEY_TLS1_PRF_DERIVE, 0),
      "pkey_tls1_prf_derive"},
     {ERR_PACK(ERR_LIB_KDF, KDF_F_PKEY_TLS1_PRF_INIT, 0), "pkey_tls1_prf_init"},
+    {ERR_PACK(ERR_LIB_KDF, KDF_F_SCRYPT_SET_MEMBUF, 0), "scrypt_set_membuf"},
     {ERR_PACK(ERR_LIB_KDF, KDF_F_TLS1_PRF_ALG, 0), "tls1_prf_alg"},
     {0, NULL}
 };
@@ -50,6 +74,8 @@ static const ERR_STRING_DATA KDF_str_reasons[] = {
     "unknown parameter type"},
     {ERR_PACK(ERR_LIB_KDF, 0, KDF_R_VALUE_ERROR), "value error"},
     {ERR_PACK(ERR_LIB_KDF, 0, KDF_R_VALUE_MISSING), "value missing"},
+    {ERR_PACK(ERR_LIB_KDF, 0, KDF_R_WRONG_OUTPUT_BUFFER_SIZE),
+    "wrong output buffer size"},
     {0, NULL}
 };
 
diff --git a/crypto/kdf/kdf_local.h b/crypto/kdf/kdf_local.h
new file mode 100644
index 0000000..4956dad
--- /dev/null
+++ b/crypto/kdf/kdf_local.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2018 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
+ */
+
+int call_ctrl(int (*ctrl)(EVP_KDF_IMPL *impl, int cmd, va_list args),
+              EVP_KDF_IMPL *impl, int cmd, ...);
+int kdf_str2ctrl(EVP_KDF_IMPL *impl,
+                 int (*ctrl)(EVP_KDF_IMPL *impl, int cmd, va_list args),
+                 int cmd, const char *str);
+int kdf_hex2ctrl(EVP_KDF_IMPL *impl,
+                 int (*ctrl)(EVP_KDF_IMPL *impl, int cmd, va_list args),
+                 int cmd, const char *hex);
+int kdf_md2ctrl(EVP_KDF_IMPL *impl,
+                int (*ctrl)(EVP_KDF_IMPL *impl, int cmd, va_list args),
+                int cmd, const char *md_name);
+
diff --git a/crypto/kdf/kdf_util.c b/crypto/kdf/kdf_util.c
new file mode 100644
index 0000000..8eb6d26
--- /dev/null
+++ b/crypto/kdf/kdf_util.c
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2018 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 <stdarg.h>
+#include <openssl/kdf.h>
+#include <openssl/evp.h>
+#include "internal/cryptlib.h"
+#include "internal/evp_int.h"
+#include "internal/numbers.h"
+#include "kdf_local.h"
+
+int call_ctrl(int (*ctrl)(EVP_KDF_IMPL *impl, int cmd, va_list args),
+              EVP_KDF_IMPL *impl, int cmd, ...)
+{
+    int ret;
+    va_list args;
+
+    va_start(args, cmd);
+    ret = ctrl(impl, cmd, args);
+    va_end(args);
+
+    return ret;
+}
+
+/* Utility functions to send a string or hex string to a ctrl */
+
+int kdf_str2ctrl(EVP_KDF_IMPL *impl,
+                 int (*ctrl)(EVP_KDF_IMPL *impl, int cmd, va_list args),
+                 int cmd, const char *str)
+{
+    return call_ctrl(ctrl, impl, cmd, (const unsigned char *)str, strlen(str));
+}
+
+int kdf_hex2ctrl(EVP_KDF_IMPL *impl,
+                 int (*ctrl)(EVP_KDF_IMPL *impl, int cmd, va_list args),
+                 int cmd, const char *hex)
+{
+    unsigned char *bin;
+    long binlen;
+    int ret = -1;
+
+    bin = OPENSSL_hexstr2buf(hex, &binlen);
+    if (bin == NULL)
+        return 0;
+
+    if (binlen <= INT_MAX)
+        ret = call_ctrl(ctrl, impl, cmd, bin, (size_t)binlen);
+    OPENSSL_free(bin);
+    return ret;
+}
+
+/* Pass a message digest to a ctrl */
+int kdf_md2ctrl(EVP_KDF_IMPL *impl,
+                int (*ctrl)(EVP_KDF_IMPL *impl, int cmd, va_list args),
+                int cmd, const char *md_name)
+{
+    const EVP_MD *md;
+
+    if (md_name == NULL || (md = EVP_get_digestbyname(md_name)) == NULL) {
+        KDFerr(KDF_F_KDF_MD2CTRL, KDF_R_INVALID_DIGEST);
+        return 0;
+    }
+    return call_ctrl(ctrl, impl, cmd, md);
+}
+
diff --git a/crypto/kdf/pbkdf2.c b/crypto/kdf/pbkdf2.c
new file mode 100644
index 0000000..bf1ac6d
--- /dev/null
+++ b/crypto/kdf/pbkdf2.c
@@ -0,0 +1,264 @@
+/*
+ * Copyright 2018 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 <stdarg.h>
+#include <string.h>
+#include <openssl/hmac.h>
+#include <openssl/evp.h>
+#include <openssl/kdf.h>
+#include "internal/cryptlib.h"
+#include "internal/evp_int.h"
+#include "kdf_local.h"
+
+static void kdf_pbkdf2_reset(EVP_KDF_IMPL *impl);
+static void kdf_pbkdf2_init(EVP_KDF_IMPL *impl);
+static int pkcs5_pbkdf2_alg(const char *pass, size_t passlen,
+                            const unsigned char *salt, int saltlen, int iter,
+                            const EVP_MD *digest, unsigned char *key,
+                            size_t keylen);
+
+struct evp_kdf_impl_st {
+    unsigned char *pass;
+    size_t pass_len;
+    unsigned char *salt;
+    size_t salt_len;
+    int iter;
+    const EVP_MD *md;
+};
+
+static EVP_KDF_IMPL *kdf_pbkdf2_new(void)
+{
+    EVP_KDF_IMPL *impl;
+
+    impl = OPENSSL_zalloc(sizeof(*impl));
+    if (impl == NULL) {
+        KDFerr(KDF_F_KDF_PBKDF2_NEW, ERR_R_MALLOC_FAILURE);
+        return NULL;
+    }
+    kdf_pbkdf2_init(impl);
+    return impl;
+}
+
+static void kdf_pbkdf2_free(EVP_KDF_IMPL *impl)
+{
+    kdf_pbkdf2_reset(impl);
+    OPENSSL_free(impl);
+}
+
+static void kdf_pbkdf2_reset(EVP_KDF_IMPL *impl)
+{
+    OPENSSL_free(impl->salt);
+    OPENSSL_clear_free(impl->pass, impl->pass_len);
+    memset(impl, 0, sizeof(*impl));
+    kdf_pbkdf2_init(impl);
+}
+
+static void kdf_pbkdf2_init(EVP_KDF_IMPL *impl)
+{
+    impl->iter = PKCS5_DEFAULT_ITER;
+    impl->md = EVP_sha1();
+}
+
+static int pbkdf2_set_membuf(unsigned char **buffer, size_t *buflen,
+                             const unsigned char *new_buffer,
+                             size_t new_buflen)
+{
+    if (new_buffer == NULL)
+        return 1;
+
+    OPENSSL_clear_free(*buffer, *buflen);
+
+    if (new_buflen > 0) {
+        *buffer = OPENSSL_memdup(new_buffer, new_buflen);
+    } else {
+        *buffer = OPENSSL_malloc(1);
+    }
+    if (*buffer == NULL) {
+        KDFerr(KDF_F_PBKDF2_SET_MEMBUF, ERR_R_MALLOC_FAILURE);
+        return 0;
+    }
+
+    *buflen = new_buflen;
+    return 1;
+}
+
+static int kdf_pbkdf2_ctrl(EVP_KDF_IMPL *impl, int cmd, va_list args)
+{
+    int iter;
+    const unsigned char *p;
+    size_t len;
+    const EVP_MD *md;
+
+    switch (cmd) {
+    case EVP_KDF_CTRL_SET_PASS:
+        p = va_arg(args, const unsigned char *);
+        len = va_arg(args, size_t);
+        return pbkdf2_set_membuf(&impl->pass, &impl->pass_len, p, len);
+
+    case EVP_KDF_CTRL_SET_SALT:
+        p = va_arg(args, const unsigned char *);
+        len = va_arg(args, size_t);
+        return pbkdf2_set_membuf(&impl->salt, &impl->salt_len, p, len);
+
+    case EVP_KDF_CTRL_SET_ITER:
+        iter = va_arg(args, int);
+        if (iter < 1)
+            return 0;
+
+        impl->iter = iter;
+        return 1;
+
+    case EVP_KDF_CTRL_SET_MD:
+        md = va_arg(args, const EVP_MD *);
+        if (md == NULL)
+            return 0;
+
+        impl->md = md;
+        return 1;
+
+    default:
+        return -2;
+    }
+}
+
+static int kdf_pbkdf2_ctrl_str(EVP_KDF_IMPL *impl, const char *type,
+                               const char *value)
+{
+    if (value == NULL) {
+        KDFerr(KDF_F_KDF_PBKDF2_CTRL_STR, KDF_R_VALUE_MISSING);
+        return 0;
+    }
+
+    if (strcmp(type, "pass") == 0)
+        return kdf_str2ctrl(impl, kdf_pbkdf2_ctrl, EVP_KDF_CTRL_SET_PASS,
+                            value);
+
+    if (strcmp(type, "hexpass") == 0)
+        return kdf_hex2ctrl(impl, kdf_pbkdf2_ctrl, EVP_KDF_CTRL_SET_PASS,
+                            value);
+
+    if (strcmp(type, "salt") == 0)
+        return kdf_str2ctrl(impl, kdf_pbkdf2_ctrl, EVP_KDF_CTRL_SET_SALT,
+                            value);
+
+    if (strcmp(type, "hexsalt") == 0)
+        return kdf_hex2ctrl(impl, kdf_pbkdf2_ctrl, EVP_KDF_CTRL_SET_SALT,
+                            value);
+
+    if (strcmp(type, "iter") == 0)
+        return call_ctrl(kdf_pbkdf2_ctrl, impl, EVP_KDF_CTRL_SET_ITER,
+                         atoi(value));
+
+    if (strcmp(type, "digest") == 0)
+        return kdf_md2ctrl(impl, kdf_pbkdf2_ctrl, EVP_KDF_CTRL_SET_MD, value);
+
+    return -2;
+}
+
+static int kdf_pbkdf2_derive(EVP_KDF_IMPL *impl, unsigned char *key,
+                             size_t keylen)
+{
+    if (impl->pass == NULL) {
+        KDFerr(KDF_F_KDF_PBKDF2_DERIVE, KDF_R_MISSING_PASS);
+        return 0;
+    }
+
+    if (impl->salt == NULL) {
+        KDFerr(KDF_F_KDF_PBKDF2_DERIVE, KDF_R_MISSING_SALT);
+        return 0;
+    }
+
+    return pkcs5_pbkdf2_alg((char *)impl->pass, impl->pass_len,
+                            impl->salt, impl->salt_len, impl->iter,
+                            impl->md, key, keylen);
+}
+
+const EVP_KDF_METHOD pbkdf2_kdf_meth = {
+    EVP_KDF_PBKDF2,
+    kdf_pbkdf2_new,
+    kdf_pbkdf2_free,
+    kdf_pbkdf2_reset,
+    kdf_pbkdf2_ctrl,
+    kdf_pbkdf2_ctrl_str,
+    NULL,
+    kdf_pbkdf2_derive
+};
+
+/*
+ * This is an implementation of PKCS#5 v2.0 password based encryption key
+ * derivation function PBKDF2. SHA1 version verified against test vectors
+ * posted by Peter Gutmann to the PKCS-TNG mailing list.
+ */
+
+static int pkcs5_pbkdf2_alg(const char *pass, size_t passlen,
+                            const unsigned char *salt, int saltlen, int iter,
+                            const EVP_MD *digest, unsigned char *key,
+                            size_t keylen)
+{
+    int ret = 0;
+    unsigned char digtmp[EVP_MAX_MD_SIZE], *p, itmp[4];
+    int cplen, j, k, tkeylen, mdlen;
+    unsigned long i = 1;
+    HMAC_CTX *hctx_tpl = NULL, *hctx = NULL;
+
+    mdlen = EVP_MD_size(digest);
+    if (mdlen < 0)
+        return 0;
+
+    hctx_tpl = HMAC_CTX_new();
+    if (hctx_tpl == NULL)
+        return 0;
+    p = key;
+    tkeylen = keylen;
+    if (!HMAC_Init_ex(hctx_tpl, pass, passlen, digest, NULL))
+        goto err;
+    hctx = HMAC_CTX_new();
+    if (hctx == NULL)
+        goto err;
+    while (tkeylen) {
+        if (tkeylen > mdlen)
+            cplen = mdlen;
+        else
+            cplen = tkeylen;
+        /*
+         * We are unlikely to ever use more than 256 blocks (5120 bits!) but
+         * just in case...
+         */
+        itmp[0] = (unsigned char)((i >> 24) & 0xff);
+        itmp[1] = (unsigned char)((i >> 16) & 0xff);
+        itmp[2] = (unsigned char)((i >> 8) & 0xff);
+        itmp[3] = (unsigned char)(i & 0xff);
+        if (!HMAC_CTX_copy(hctx, hctx_tpl))
+            goto err;
+        if (!HMAC_Update(hctx, salt, saltlen)
+                || !HMAC_Update(hctx, itmp, 4)
+                || !HMAC_Final(hctx, digtmp, NULL))
+            goto err;
+        memcpy(p, digtmp, cplen);
+        for (j = 1; j < iter; j++) {
+            if (!HMAC_CTX_copy(hctx, hctx_tpl))
+                goto err;
+            if (!HMAC_Update(hctx, digtmp, mdlen)
+                    || !HMAC_Final(hctx, digtmp, NULL))
+                goto err;
+            for (k = 0; k < cplen; k++)
+                p[k] ^= digtmp[k];
+        }
+        tkeylen -= cplen;
+        i++;
+        p += cplen;
+    }
+    ret = 1;
+
+err:
+    HMAC_CTX_free(hctx);
+    HMAC_CTX_free(hctx_tpl);
+    return ret;
+}
diff --git a/crypto/kdf/scrypt.c b/crypto/kdf/scrypt.c
index 6b35b77..ee77f1e 100644
--- a/crypto/kdf/scrypt.c
+++ b/crypto/kdf/scrypt.c
@@ -8,25 +8,34 @@
  */
 
 #include <stdlib.h>
+#include <stdarg.h>
 #include <string.h>
-#include <openssl/hmac.h>
-#include <openssl/kdf.h>
 #include <openssl/evp.h>
-#include "internal/cryptlib.h"
+#include <openssl/kdf.h>
+#include <openssl/err.h>
 #include "internal/evp_int.h"
+#include "internal/numbers.h"
+#include "kdf_local.h"
 
 #ifndef OPENSSL_NO_SCRYPT
 
+static void kdf_scrypt_reset(EVP_KDF_IMPL *impl);
+static void kdf_scrypt_init(EVP_KDF_IMPL *impl);
 static int atou64(const char *nptr, uint64_t *result);
+static int scrypt_alg(const char *pass, size_t passlen,
+                      const unsigned char *salt, size_t saltlen,
+                      uint64_t N, uint64_t r, uint64_t p, uint64_t maxmem,
+                      unsigned char *key, size_t keylen);
 
-typedef struct {
+struct evp_kdf_impl_st {
     unsigned char *pass;
     size_t pass_len;
     unsigned char *salt;
     size_t salt_len;
-    uint64_t N, r, p;
+    uint64_t N;
+    uint32_t r, p;
     uint64_t maxmem_bytes;
-} SCRYPT_PKEY_CTX;
+};
 
 /* Custom uint64_t parser since we do not have strtoull */
 static int atou64(const char *nptr, uint64_t *result)
@@ -53,51 +62,53 @@ static int atou64(const char *nptr, uint64_t *result)
     return 1;
 }
 
-static int pkey_scrypt_init(EVP_PKEY_CTX *ctx)
+static EVP_KDF_IMPL *kdf_scrypt_new(void)
 {
-    SCRYPT_PKEY_CTX *kctx;
+    EVP_KDF_IMPL *impl;
 
-    kctx = OPENSSL_zalloc(sizeof(*kctx));
-    if (kctx == NULL) {
-        KDFerr(KDF_F_PKEY_SCRYPT_INIT, ERR_R_MALLOC_FAILURE);
-        return 0;
+    impl = OPENSSL_zalloc(sizeof(*impl));
+    if (impl == NULL) {
+        KDFerr(KDF_F_KDF_SCRYPT_NEW, ERR_R_MALLOC_FAILURE);
+        return NULL;
     }
+    kdf_scrypt_init(impl);
+    return impl;
+}
 
-    /* Default values are the most conservative recommendation given in the
-     * original paper of C. Percival. Derivation uses roughly 1 GiB of memory
-     * for this parameter choice (approx. 128 * r * (N + p) bytes).
-     */
-    kctx->N = 1 << 20;
-    kctx->r = 8;
-    kctx->p = 1;
-    kctx->maxmem_bytes = 1025 * 1024 * 1024;
-
-    ctx->data = kctx;
-
-    return 1;
+static void kdf_scrypt_free(EVP_KDF_IMPL *impl)
+{
+    kdf_scrypt_reset(impl);
+    OPENSSL_free(impl);
 }
 
-static void pkey_scrypt_cleanup(EVP_PKEY_CTX *ctx)
+static void kdf_scrypt_reset(EVP_KDF_IMPL *impl)
 {
-    SCRYPT_PKEY_CTX *kctx = ctx->data;
+    OPENSSL_free(impl->salt);
+    OPENSSL_clear_free(impl->pass, impl->pass_len);
+    memset(impl, 0, sizeof(*impl));
+    kdf_scrypt_init(impl);
+}
 
-    OPENSSL_clear_free(kctx->salt, kctx->salt_len);
-    OPENSSL_clear_free(kctx->pass, kctx->pass_len);
-    OPENSSL_free(kctx);
+static void kdf_scrypt_init(EVP_KDF_IMPL *impl)
+{
+    /* Default values are the most conservative recommendation given in the
+     * original paper of C. Percival. Derivation uses roughly 1 GiB of memory
+     * for this parameter choice (approx. 128 * r * N * p bytes).
+     */
+    impl->N = 1 << 20;
+    impl->r = 8;
+    impl->p = 1;
+    impl->maxmem_bytes = 1025 * 1024 * 1024;
 }
 
-static int pkey_scrypt_set_membuf(unsigned char **buffer, size_t *buflen,
-                                  const unsigned char *new_buffer,
-                                  const int new_buflen)
+static int scrypt_set_membuf(unsigned char **buffer, size_t *buflen,
+                             const unsigned char *new_buffer,
+                             size_t new_buflen)
 {
     if (new_buffer == NULL)
         return 1;
 
-    if (new_buflen < 0)
-        return 0;
-
-    if (*buffer != NULL)
-        OPENSSL_clear_free(*buffer, *buflen);
+    OPENSSL_clear_free(*buffer, *buflen);
 
     if (new_buflen > 0) {
         *buffer = OPENSSL_memdup(new_buffer, new_buflen);
@@ -105,7 +116,7 @@ static int pkey_scrypt_set_membuf(unsigned char **buffer, size_t *buflen,
         *buffer = OPENSSL_malloc(1);
     }
     if (*buffer == NULL) {
-        KDFerr(KDF_F_PKEY_SCRYPT_SET_MEMBUF, ERR_R_MALLOC_FAILURE);
+        KDFerr(KDF_F_SCRYPT_SET_MEMBUF, ERR_R_MALLOC_FAILURE);
         return 0;
     }
 
@@ -118,149 +129,378 @@ static int is_power_of_two(uint64_t value)
     return (value != 0) && ((value & (value - 1)) == 0);
 }
 
-static int pkey_scrypt_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
+static int kdf_scrypt_ctrl(EVP_KDF_IMPL *impl, int cmd, va_list args)
 {
-    SCRYPT_PKEY_CTX *kctx = ctx->data;
     uint64_t u64_value;
-
-    switch (type) {
-    case EVP_PKEY_CTRL_PASS:
-        return pkey_scrypt_set_membuf(&kctx->pass, &kctx->pass_len, p2, p1);
-
-    case EVP_PKEY_CTRL_SCRYPT_SALT:
-        return pkey_scrypt_set_membuf(&kctx->salt, &kctx->salt_len, p2, p1);
-
-    case EVP_PKEY_CTRL_SCRYPT_N:
-        u64_value = *((uint64_t *)p2);
+    uint32_t value;
+    const unsigned char *p;
+    size_t len;
+
+    switch (cmd) {
+    case EVP_KDF_CTRL_SET_PASS:
+        p = va_arg(args, const unsigned char *);
+        len = va_arg(args, size_t);
+        return scrypt_set_membuf(&impl->pass, &impl->pass_len, p, len);
+
+    case EVP_KDF_CTRL_SET_SALT:
+        p = va_arg(args, const unsigned char *);
+        len = va_arg(args, size_t);
+        return scrypt_set_membuf(&impl->salt, &impl->salt_len, p, len);
+
+    case EVP_KDF_CTRL_SET_SCRYPT_N:
+        u64_value = va_arg(args, uint64_t);
         if ((u64_value <= 1) || !is_power_of_two(u64_value))
             return 0;
-        kctx->N = u64_value;
+
+        impl->N = u64_value;
         return 1;
 
-    case EVP_PKEY_CTRL_SCRYPT_R:
-        u64_value = *((uint64_t *)p2);
-        if (u64_value < 1)
+    case EVP_KDF_CTRL_SET_SCRYPT_R:
+        value = va_arg(args, uint32_t);
+        if (value < 1)
             return 0;
-        kctx->r = u64_value;
+
+        impl->r = value;
         return 1;
 
-    case EVP_PKEY_CTRL_SCRYPT_P:
-        u64_value = *((uint64_t *)p2);
-        if (u64_value < 1)
+    case EVP_KDF_CTRL_SET_SCRYPT_P:
+        value = va_arg(args, uint32_t);
+        if (value < 1)
             return 0;
-        kctx->p = u64_value;
+
+        impl->p = value;
         return 1;
 
-    case EVP_PKEY_CTRL_SCRYPT_MAXMEM_BYTES:
-        u64_value = *((uint64_t *)p2);
+    case EVP_KDF_CTRL_SET_MAXMEM_BYTES:
+        u64_value = va_arg(args, uint64_t);
         if (u64_value < 1)
             return 0;
-        kctx->maxmem_bytes = u64_value;
+
+        impl->maxmem_bytes = u64_value;
         return 1;
 
     default:
         return -2;
+    }
+}
+
+static int kdf_scrypt_ctrl_uint32(EVP_KDF_IMPL *impl, int cmd,
+                                  const char *value)
+{
+    int int_value = atoi(value);
 
+    if (int_value < 0 || (uint64_t)int_value > UINT32_MAX) {
+        KDFerr(KDF_F_KDF_SCRYPT_CTRL_UINT32, KDF_R_VALUE_ERROR);
+        return 0;
     }
+    return call_ctrl(kdf_scrypt_ctrl, impl, cmd, (uint32_t)int_value);
 }
 
-static int pkey_scrypt_ctrl_uint64(EVP_PKEY_CTX *ctx, int type,
-                                   const char *value)
+static int kdf_scrypt_ctrl_uint64(EVP_KDF_IMPL *impl, int cmd,
+                                  const char *value)
 {
-    uint64_t int_value;
+    uint64_t u64_value;
 
-    if (!atou64(value, &int_value)) {
-        KDFerr(KDF_F_PKEY_SCRYPT_CTRL_UINT64, KDF_R_VALUE_ERROR);
+    if (!atou64(value, &u64_value)) {
+        KDFerr(KDF_F_KDF_SCRYPT_CTRL_UINT64, KDF_R_VALUE_ERROR);
         return 0;
     }
-    return pkey_scrypt_ctrl(ctx, type, 0, &int_value);
+    return call_ctrl(kdf_scrypt_ctrl, impl, cmd, u64_value);
 }
 
-static int pkey_scrypt_ctrl_str(EVP_PKEY_CTX *ctx, const char *type,
-                                const char *value)
+static int kdf_scrypt_ctrl_str(EVP_KDF_IMPL *impl, const char *type,
+                               const char *value)
 {
     if (value == NULL) {
-        KDFerr(KDF_F_PKEY_SCRYPT_CTRL_STR, KDF_R_VALUE_MISSING);
+        KDFerr(KDF_F_KDF_SCRYPT_CTRL_STR, KDF_R_VALUE_MISSING);
         return 0;
     }
 
     if (strcmp(type, "pass") == 0)
-        return EVP_PKEY_CTX_str2ctrl(ctx, EVP_PKEY_CTRL_PASS, value);
+        return kdf_str2ctrl(impl, kdf_scrypt_ctrl, EVP_KDF_CTRL_SET_PASS,
+                            value);
 
     if (strcmp(type, "hexpass") == 0)
-        return EVP_PKEY_CTX_hex2ctrl(ctx, EVP_PKEY_CTRL_PASS, value);
+        return kdf_hex2ctrl(impl, kdf_scrypt_ctrl, EVP_KDF_CTRL_SET_PASS,
+                            value);
 
     if (strcmp(type, "salt") == 0)
-        return EVP_PKEY_CTX_str2ctrl(ctx, EVP_PKEY_CTRL_SCRYPT_SALT, value);
+        return kdf_str2ctrl(impl, kdf_scrypt_ctrl, EVP_KDF_CTRL_SET_SALT,
+                            value);
 
     if (strcmp(type, "hexsalt") == 0)
-        return EVP_PKEY_CTX_hex2ctrl(ctx, EVP_PKEY_CTRL_SCRYPT_SALT, value);
+        return kdf_hex2ctrl(impl, kdf_scrypt_ctrl, EVP_KDF_CTRL_SET_SALT,
+                            value);
 
     if (strcmp(type, "N") == 0)
-        return pkey_scrypt_ctrl_uint64(ctx, EVP_PKEY_CTRL_SCRYPT_N, value);
+        return kdf_scrypt_ctrl_uint64(impl, EVP_KDF_CTRL_SET_SCRYPT_N, value);
 
     if (strcmp(type, "r") == 0)
-        return pkey_scrypt_ctrl_uint64(ctx, EVP_PKEY_CTRL_SCRYPT_R, value);
+        return kdf_scrypt_ctrl_uint32(impl, EVP_KDF_CTRL_SET_SCRYPT_R, value);
 
     if (strcmp(type, "p") == 0)
-        return pkey_scrypt_ctrl_uint64(ctx, EVP_PKEY_CTRL_SCRYPT_P, value);
+        return kdf_scrypt_ctrl_uint32(impl, EVP_KDF_CTRL_SET_SCRYPT_P, value);
 
     if (strcmp(type, "maxmem_bytes") == 0)
-        return pkey_scrypt_ctrl_uint64(ctx, EVP_PKEY_CTRL_SCRYPT_MAXMEM_BYTES,
-                                       value);
+        return kdf_scrypt_ctrl_uint64(impl, EVP_KDF_CTRL_SET_MAXMEM_BYTES,
+                                      value);
 
-    KDFerr(KDF_F_PKEY_SCRYPT_CTRL_STR, KDF_R_UNKNOWN_PARAMETER_TYPE);
     return -2;
 }
 
-static int pkey_scrypt_derive(EVP_PKEY_CTX *ctx, unsigned char *key,
-                              size_t *keylen)
+static int kdf_scrypt_derive(EVP_KDF_IMPL *impl, unsigned char *key,
+                             size_t keylen)
 {
-    SCRYPT_PKEY_CTX *kctx = ctx->data;
-
-    if (kctx->pass == NULL) {
-        KDFerr(KDF_F_PKEY_SCRYPT_DERIVE, KDF_R_MISSING_PASS);
+    if (impl->pass == NULL) {
+        KDFerr(KDF_F_KDF_SCRYPT_DERIVE, KDF_R_MISSING_PASS);
         return 0;
     }
 
-    if (kctx->salt == NULL) {
-        KDFerr(KDF_F_PKEY_SCRYPT_DERIVE, KDF_R_MISSING_SALT);
+    if (impl->salt == NULL) {
+        KDFerr(KDF_F_KDF_SCRYPT_DERIVE, KDF_R_MISSING_SALT);
         return 0;
     }
 
-    return EVP_PBE_scrypt((char *)kctx->pass, kctx->pass_len, kctx->salt,
-                          kctx->salt_len, kctx->N, kctx->r, kctx->p,
-                          kctx->maxmem_bytes, key, *keylen);
+    return scrypt_alg((char *)impl->pass, impl->pass_len, impl->salt,
+                      impl->salt_len, impl->N, impl->r, impl->p,
+                      impl->maxmem_bytes, key, keylen);
+}
+
+const EVP_KDF_METHOD scrypt_kdf_meth = {
+    EVP_KDF_SCRYPT,
+    kdf_scrypt_new,
+    kdf_scrypt_free,
+    kdf_scrypt_reset,
+    kdf_scrypt_ctrl,
+    kdf_scrypt_ctrl_str,
+    NULL,
+    kdf_scrypt_derive
+};
+
+#define R(a,b) (((a) << (b)) | ((a) >> (32 - (b))))
+static void salsa208_word_specification(uint32_t inout[16])
+{
+    int i;
+    uint32_t x[16];
+
+    memcpy(x, inout, sizeof(x));
+    for (i = 8; i > 0; i -= 2) {
+        x[4] ^= R(x[0] + x[12], 7);
+        x[8] ^= R(x[4] + x[0], 9);
+        x[12] ^= R(x[8] + x[4], 13);
+        x[0] ^= R(x[12] + x[8], 18);
+        x[9] ^= R(x[5] + x[1], 7);
+        x[13] ^= R(x[9] + x[5], 9);
+        x[1] ^= R(x[13] + x[9], 13);
+        x[5] ^= R(x[1] + x[13], 18);
+        x[14] ^= R(x[10] + x[6], 7);
+        x[2] ^= R(x[14] + x[10], 9);
+        x[6] ^= R(x[2] + x[14], 13);
+        x[10] ^= R(x[6] + x[2], 18);
+        x[3] ^= R(x[15] + x[11], 7);
+        x[7] ^= R(x[3] + x[15], 9);
+        x[11] ^= R(x[7] + x[3], 13);
+        x[15] ^= R(x[11] + x[7], 18);
+        x[1] ^= R(x[0] + x[3], 7);
+        x[2] ^= R(x[1] + x[0], 9);
+        x[3] ^= R(x[2] + x[1], 13);
+        x[0] ^= R(x[3] + x[2], 18);
+        x[6] ^= R(x[5] + x[4], 7);
+        x[7] ^= R(x[6] + x[5], 9);
+        x[4] ^= R(x[7] + x[6], 13);
+        x[5] ^= R(x[4] + x[7], 18);
+        x[11] ^= R(x[10] + x[9], 7);
+        x[8] ^= R(x[11] + x[10], 9);
+        x[9] ^= R(x[8] + x[11], 13);
+        x[10] ^= R(x[9] + x[8], 18);
+        x[12] ^= R(x[15] + x[14], 7);
+        x[13] ^= R(x[12] + x[15], 9);
+        x[14] ^= R(x[13] + x[12], 13);
+        x[15] ^= R(x[14] + x[13], 18);
+    }
+    for (i = 0; i < 16; ++i)
+        inout[i] += x[i];
+    OPENSSL_cleanse(x, sizeof(x));
+}
+
+static void scryptBlockMix(uint32_t *B_, uint32_t *B, uint64_t r)
+{
+    uint64_t i, j;
+    uint32_t X[16], *pB;
+
+    memcpy(X, B + (r * 2 - 1) * 16, sizeof(X));
+    pB = B;
+    for (i = 0; i < r * 2; i++) {
+        for (j = 0; j < 16; j++)
+            X[j] ^= *pB++;
+        salsa208_word_specification(X);
+        memcpy(B_ + (i / 2 + (i & 1) * r) * 16, X, sizeof(X));
+    }
+    OPENSSL_cleanse(X, sizeof(X));
+}
+
+static void scryptROMix(unsigned char *B, uint64_t r, uint64_t N,
+                        uint32_t *X, uint32_t *T, uint32_t *V)
+{
+    unsigned char *pB;
+    uint32_t *pV;
+    uint64_t i, k;
+
+    /* Convert from little endian input */
+    for (pV = V, i = 0, pB = B; i < 32 * r; i++, pV++) {
+        *pV = *pB++;
+        *pV |= *pB++ << 8;
+        *pV |= *pB++ << 16;
+        *pV |= (uint32_t)*pB++ << 24;
+    }
+
+    for (i = 1; i < N; i++, pV += 32 * r)
+        scryptBlockMix(pV, pV - 32 * r, r);
+
+    scryptBlockMix(X, V + (N - 1) * 32 * r, r);
+
+    for (i = 0; i < N; i++) {
+        uint32_t j;
+        j = X[16 * (2 * r - 1)] % N;
+        pV = V + 32 * r * j;
+        for (k = 0; k < 32 * r; k++)
+            T[k] = X[k] ^ *pV++;
+        scryptBlockMix(X, T, r);
+    }
+    /* Convert output to little endian */
+    for (i = 0, pB = B; i < 32 * r; i++) {
+        uint32_t xtmp = X[i];
+        *pB++ = xtmp & 0xff;
+        *pB++ = (xtmp >> 8) & 0xff;
+        *pB++ = (xtmp >> 16) & 0xff;
+        *pB++ = (xtmp >> 24) & 0xff;
+    }
 }
 
-const EVP_PKEY_METHOD scrypt_pkey_meth = {
-    EVP_PKEY_SCRYPT,
-    0,
-    pkey_scrypt_init,
-    0,
-    pkey_scrypt_cleanup,
+#ifndef SIZE_MAX
+# define SIZE_MAX    ((size_t)-1)
+#endif
 
-    0, 0,
-    0, 0,
+/*
+ * Maximum power of two that will fit in uint64_t: this should work on
+ * most (all?) platforms.
+ */
 
-    0,
-    0,
+#define LOG2_UINT64_MAX         (sizeof(uint64_t) * 8 - 1)
 
-    0,
-    0,
+/*
+ * Maximum value of p * r:
+ * p <= ((2^32-1) * hLen) / MFLen =>
+ * p <= ((2^32-1) * 32) / (128 * r) =>
+ * p * r <= (2^30-1)
+ */
 
-    0, 0,
+#define SCRYPT_PR_MAX   ((1 << 30) - 1)
 
-    0, 0, 0, 0,
+static int scrypt_alg(const char *pass, size_t passlen,
+                      const unsigned char *salt, size_t saltlen,
+                      uint64_t N, uint64_t r, uint64_t p, uint64_t maxmem,
+                      unsigned char *key, size_t keylen)
+{
+    int rv = 0;
+    unsigned char *B;
+    uint32_t *X, *V, *T;
+    uint64_t i, Blen, Vlen;
+
+    /* Sanity check parameters */
+    /* initial check, r,p must be non zero, N >= 2 and a power of 2 */
+    if (r == 0 || p == 0 || N < 2 || (N & (N - 1)))
+        return 0;
+    /* Check p * r < SCRYPT_PR_MAX avoiding overflow */
+    if (p > SCRYPT_PR_MAX / r) {
+        EVPerr(EVP_F_SCRYPT_ALG, EVP_R_MEMORY_LIMIT_EXCEEDED);
+        return 0;
+    }
 
-    0, 0,
+    /*
+     * Need to check N: if 2^(128 * r / 8) overflows limit this is
+     * automatically satisfied since N <= UINT64_MAX.
+     */
 
-    0, 0,
+    if (16 * r <= LOG2_UINT64_MAX) {
+        if (N >= (((uint64_t)1) << (16 * r))) {
+            EVPerr(EVP_F_SCRYPT_ALG, EVP_R_MEMORY_LIMIT_EXCEEDED);
+            return 0;
+        }
+    }
 
-    0,
-    pkey_scrypt_derive,
-    pkey_scrypt_ctrl,
-    pkey_scrypt_ctrl_str
-};
+    /* Memory checks: check total allocated buffer size fits in uint64_t */
+
+    /*
+     * B size in section 5 step 1.S
+     * Note: we know p * 128 * r < UINT64_MAX because we already checked
+     * p * r < SCRYPT_PR_MAX
+     */
+    Blen = p * 128 * r;
+    /*
+     * Yet we pass it as integer to PKCS5_PBKDF2_HMAC... [This would
+     * have to be revised when/if PKCS5_PBKDF2_HMAC accepts size_t.]
+     */
+    if (Blen > INT_MAX) {
+        EVPerr(EVP_F_SCRYPT_ALG, EVP_R_MEMORY_LIMIT_EXCEEDED);
+        return 0;
+    }
+
+    /*
+     * Check 32 * r * (N + 2) * sizeof(uint32_t) fits in uint64_t
+     * This is combined size V, X and T (section 4)
+     */
+    i = UINT64_MAX / (32 * sizeof(uint32_t));
+    if (N + 2 > i / r) {
+        EVPerr(EVP_F_SCRYPT_ALG, EVP_R_MEMORY_LIMIT_EXCEEDED);
+        return 0;
+    }
+    Vlen = 32 * r * (N + 2) * sizeof(uint32_t);
+
+    /* check total allocated size fits in uint64_t */
+    if (Blen > UINT64_MAX - Vlen) {
+        EVPerr(EVP_F_SCRYPT_ALG, EVP_R_MEMORY_LIMIT_EXCEEDED);
+        return 0;
+    }
+
+    /* Check that the maximum memory doesn't exceed a size_t limits */
+    if (maxmem > SIZE_MAX)
+        maxmem = SIZE_MAX;
+
+    if (Blen + Vlen > maxmem) {
+        EVPerr(EVP_F_SCRYPT_ALG, EVP_R_MEMORY_LIMIT_EXCEEDED);
+        return 0;
+    }
+
+    /* If no key return to indicate parameters are OK */
+    if (key == NULL)
+        return 1;
+
+    B = OPENSSL_malloc((size_t)(Blen + Vlen));
+    if (B == NULL) {
+        EVPerr(EVP_F_SCRYPT_ALG, ERR_R_MALLOC_FAILURE);
+        return 0;
+    }
+    X = (uint32_t *)(B + Blen);
+    T = X + 32 * r;
+    V = T + 32 * r;
+    if (PKCS5_PBKDF2_HMAC(pass, passlen, salt, saltlen, 1, EVP_sha256(),
+                          (int)Blen, B) == 0)
+        goto err;
+
+    for (i = 0; i < p; i++)
+        scryptROMix(B + 128 * r * i, r, N, X, T, V);
+
+    if (PKCS5_PBKDF2_HMAC(pass, passlen, B, (int)Blen, 1, EVP_sha256(),
+                          keylen, key) == 0)
+        goto err;
+    rv = 1;
+ err:
+    if (rv == 0)
+        EVPerr(EVP_F_SCRYPT_ALG, EVP_R_PBKDF2_ERROR);
+
+    OPENSSL_clear_free(B, (size_t)(Blen + Vlen));
+    return rv;
+}
 
 #endif
diff --git a/crypto/kdf/tls1_prf.c b/crypto/kdf/tls1_prf.c
index 24ad59b..1f8374f 100644
--- a/crypto/kdf/tls1_prf.c
+++ b/crypto/kdf/tls1_prf.c
@@ -8,11 +8,15 @@
  */
 
 #include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
 #include "internal/cryptlib.h"
-#include <openssl/kdf.h>
 #include <openssl/evp.h>
+#include <openssl/kdf.h>
 #include "internal/evp_int.h"
+#include "kdf_local.h"
 
+static void kdf_tls1_prf_reset(EVP_KDF_IMPL *impl);
 static int tls1_prf_alg(const EVP_MD *md,
                         const unsigned char *sec, size_t slen,
                         const unsigned char *seed, size_t seed_len,
@@ -20,9 +24,9 @@ static int tls1_prf_alg(const EVP_MD *md,
 
 #define TLS1_PRF_MAXBUF 1024
 
-/* TLS KDF pkey context structure */
+/* TLS KDF kdf context structure */
 
-typedef struct {
+struct evp_kdf_impl_st {
     /* Digest to use for PRF */
     const EVP_MD *md;
     /* Secret value to use for PRF */
@@ -31,145 +35,137 @@ typedef struct {
     /* Buffer of concatenated seed data */
     unsigned char seed[TLS1_PRF_MAXBUF];
     size_t seedlen;
-} TLS1_PRF_PKEY_CTX;
+};
 
-static int pkey_tls1_prf_init(EVP_PKEY_CTX *ctx)
+static EVP_KDF_IMPL *kdf_tls1_prf_new(void)
 {
-    TLS1_PRF_PKEY_CTX *kctx;
+    EVP_KDF_IMPL *impl;
 
-    if ((kctx = OPENSSL_zalloc(sizeof(*kctx))) == NULL) {
-        KDFerr(KDF_F_PKEY_TLS1_PRF_INIT, ERR_R_MALLOC_FAILURE);
-        return 0;
-    }
-    ctx->data = kctx;
+    if ((impl = OPENSSL_zalloc(sizeof(*impl))) == NULL)
+        KDFerr(KDF_F_KDF_TLS1_PRF_NEW, ERR_R_MALLOC_FAILURE);
+    return impl;
+}
 
-    return 1;
+static void kdf_tls1_prf_free(EVP_KDF_IMPL *impl)
+{
+    kdf_tls1_prf_reset(impl);
+    OPENSSL_free(impl);
 }
 
-static void pkey_tls1_prf_cleanup(EVP_PKEY_CTX *ctx)
+static void kdf_tls1_prf_reset(EVP_KDF_IMPL *impl)
 {
-    TLS1_PRF_PKEY_CTX *kctx = ctx->data;
-    OPENSSL_clear_free(kctx->sec, kctx->seclen);
-    OPENSSL_cleanse(kctx->seed, kctx->seedlen);
-    OPENSSL_free(kctx);
+    OPENSSL_clear_free(impl->sec, impl->seclen);
+    OPENSSL_cleanse(impl->seed, impl->seedlen);
+    memset(impl, 0, sizeof(*impl));
 }
 
-static int pkey_tls1_prf_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
+static int kdf_tls1_prf_ctrl(EVP_KDF_IMPL *impl, int cmd, va_list args)
 {
-    TLS1_PRF_PKEY_CTX *kctx = ctx->data;
-    switch (type) {
-    case EVP_PKEY_CTRL_TLS_MD:
-        kctx->md = p2;
-        return 1;
+    const unsigned char *p;
+    size_t len;
+    const EVP_MD *md;
 
-    case EVP_PKEY_CTRL_TLS_SECRET:
-        if (p1 < 0)
+    switch (cmd) {
+    case EVP_KDF_CTRL_SET_MD:
+        md = va_arg(args, const EVP_MD *);
+        if (md == NULL)
             return 0;
-        if (kctx->sec != NULL)
-            OPENSSL_clear_free(kctx->sec, kctx->seclen);
-        OPENSSL_cleanse(kctx->seed, kctx->seedlen);
-        kctx->seedlen = 0;
-        kctx->sec = OPENSSL_memdup(p2, p1);
-        if (kctx->sec == NULL)
+
+        impl->md = md;
+        return 1;
+
+    case EVP_KDF_CTRL_SET_TLS_SECRET:
+        p = va_arg(args, const unsigned char *);
+        len = va_arg(args, size_t);
+        OPENSSL_clear_free(impl->sec, impl->seclen);
+        impl->sec = OPENSSL_memdup(p, len);
+        if (impl->sec == NULL)
             return 0;
-        kctx->seclen  = p1;
+
+        impl->seclen  = len;
         return 1;
 
-    case EVP_PKEY_CTRL_TLS_SEED:
-        if (p1 == 0 || p2 == NULL)
+    case EVP_KDF_CTRL_RESET_TLS_SEED:
+        OPENSSL_cleanse(impl->seed, impl->seedlen);
+        impl->seedlen = 0;
+        return 1;
+
+    case EVP_KDF_CTRL_ADD_TLS_SEED:
+        p = va_arg(args, const unsigned char *);
+        len = va_arg(args, size_t);
+        if (len == 0 || p == NULL)
             return 1;
-        if (p1 < 0 || p1 > (int)(TLS1_PRF_MAXBUF - kctx->seedlen))
+
+        if (len > (TLS1_PRF_MAXBUF - impl->seedlen))
             return 0;
-        memcpy(kctx->seed + kctx->seedlen, p2, p1);
-        kctx->seedlen += p1;
+
+        memcpy(impl->seed + impl->seedlen, p, len);
+        impl->seedlen += len;
         return 1;
 
     default:
         return -2;
-
     }
 }
 
-static int pkey_tls1_prf_ctrl_str(EVP_PKEY_CTX *ctx,
-                                  const char *type, const char *value)
+static int kdf_tls1_prf_ctrl_str(EVP_KDF_IMPL *impl,
+                                 const char *type, const char *value)
 {
     if (value == NULL) {
-        KDFerr(KDF_F_PKEY_TLS1_PRF_CTRL_STR, KDF_R_VALUE_MISSING);
+        KDFerr(KDF_F_KDF_TLS1_PRF_CTRL_STR, KDF_R_VALUE_MISSING);
         return 0;
     }
-    if (strcmp(type, "md") == 0) {
-        TLS1_PRF_PKEY_CTX *kctx = ctx->data;
+    if (strcmp(type, "digest") == 0)
+        return kdf_md2ctrl(impl, kdf_tls1_prf_ctrl, EVP_KDF_CTRL_SET_MD, value);
 
-        const EVP_MD *md = EVP_get_digestbyname(value);
-        if (md == NULL) {
-            KDFerr(KDF_F_PKEY_TLS1_PRF_CTRL_STR, KDF_R_INVALID_DIGEST);
-            return 0;
-        }
-        kctx->md = md;
-        return 1;
-    }
     if (strcmp(type, "secret") == 0)
-        return EVP_PKEY_CTX_str2ctrl(ctx, EVP_PKEY_CTRL_TLS_SECRET, value);
+        return kdf_str2ctrl(impl, kdf_tls1_prf_ctrl,
+                            EVP_KDF_CTRL_SET_TLS_SECRET, value);
+
     if (strcmp(type, "hexsecret") == 0)
-        return EVP_PKEY_CTX_hex2ctrl(ctx, EVP_PKEY_CTRL_TLS_SECRET, value);
+        return kdf_hex2ctrl(impl, kdf_tls1_prf_ctrl,
+                            EVP_KDF_CTRL_SET_TLS_SECRET, value);
+
     if (strcmp(type, "seed") == 0)
-        return EVP_PKEY_CTX_str2ctrl(ctx, EVP_PKEY_CTRL_TLS_SEED, value);
+        return kdf_str2ctrl(impl, kdf_tls1_prf_ctrl, EVP_KDF_CTRL_ADD_TLS_SEED,
+                            value);
+
     if (strcmp(type, "hexseed") == 0)
-        return EVP_PKEY_CTX_hex2ctrl(ctx, EVP_PKEY_CTRL_TLS_SEED, value);
+        return kdf_hex2ctrl(impl, kdf_tls1_prf_ctrl, EVP_KDF_CTRL_ADD_TLS_SEED,
+                            value);
 
-    KDFerr(KDF_F_PKEY_TLS1_PRF_CTRL_STR, KDF_R_UNKNOWN_PARAMETER_TYPE);
     return -2;
 }
 
-static int pkey_tls1_prf_derive(EVP_PKEY_CTX *ctx, unsigned char *key,
-                                size_t *keylen)
+static int kdf_tls1_prf_derive(EVP_KDF_IMPL *impl, unsigned char *key,
+                               size_t keylen)
 {
-    TLS1_PRF_PKEY_CTX *kctx = ctx->data;
-    if (kctx->md == NULL) {
-        KDFerr(KDF_F_PKEY_TLS1_PRF_DERIVE, KDF_R_MISSING_MESSAGE_DIGEST);
+    if (impl->md == NULL) {
+        KDFerr(KDF_F_KDF_TLS1_PRF_DERIVE, KDF_R_MISSING_MESSAGE_DIGEST);
         return 0;
     }
-    if (kctx->sec == NULL) {
-        KDFerr(KDF_F_PKEY_TLS1_PRF_DERIVE, KDF_R_MISSING_SECRET);
+    if (impl->sec == NULL) {
+        KDFerr(KDF_F_KDF_TLS1_PRF_DERIVE, KDF_R_MISSING_SECRET);
         return 0;
     }
-    if (kctx->seedlen == 0) {
-        KDFerr(KDF_F_PKEY_TLS1_PRF_DERIVE, KDF_R_MISSING_SEED);
+    if (impl->seedlen == 0) {
+        KDFerr(KDF_F_KDF_TLS1_PRF_DERIVE, KDF_R_MISSING_SEED);
         return 0;
     }
-    return tls1_prf_alg(kctx->md, kctx->sec, kctx->seclen,
-                        kctx->seed, kctx->seedlen,
-                        key, *keylen);
+    return tls1_prf_alg(impl->md, impl->sec, impl->seclen,
+                        impl->seed, impl->seedlen,
+                        key, keylen);
 }
 
-const EVP_PKEY_METHOD tls1_prf_pkey_meth = {
-    EVP_PKEY_TLS1_PRF,
-    0,
-    pkey_tls1_prf_init,
-    0,
-    pkey_tls1_prf_cleanup,
-
-    0, 0,
-    0, 0,
-
-    0,
-    0,
-
-    0,
-    0,
-
-    0, 0,
-
-    0, 0, 0, 0,
-
-    0, 0,
-
-    0, 0,
-
-    0,
-    pkey_tls1_prf_derive,
-    pkey_tls1_prf_ctrl,
-    pkey_tls1_prf_ctrl_str
+const EVP_KDF_METHOD tls1_prf_kdf_meth = {
+    EVP_KDF_TLS1_PRF,
+    kdf_tls1_prf_new,
+    kdf_tls1_prf_free,
+    kdf_tls1_prf_reset,
+    kdf_tls1_prf_ctrl,
+    kdf_tls1_prf_ctrl_str,
+    NULL,
+    kdf_tls1_prf_derive
 };
 
 static int tls1_prf_P_hash(const EVP_MD *md,
@@ -249,12 +245,11 @@ static int tls1_prf_alg(const EVP_MD *md,
                         const unsigned char *seed, size_t seed_len,
                         unsigned char *out, size_t olen)
 {
-
     if (EVP_MD_type(md) == NID_md5_sha1) {
         size_t i;
         unsigned char *tmp;
         if (!tls1_prf_P_hash(EVP_md5(), sec, slen/2 + (slen & 1),
-                         seed, seed_len, out, olen))
+                             seed, seed_len, out, olen))
             return 0;
 
         if ((tmp = OPENSSL_malloc(olen)) == NULL) {
@@ -262,7 +257,7 @@ static int tls1_prf_alg(const EVP_MD *md,
             return 0;
         }
         if (!tls1_prf_P_hash(EVP_sha1(), sec + slen/2, slen/2 + (slen & 1),
-                         seed, seed_len, tmp, olen)) {
+                             seed, seed_len, tmp, olen)) {
             OPENSSL_clear_free(tmp, olen);
             return 0;
         }
diff --git a/doc/man3/EVP_KDF_CTX.pod b/doc/man3/EVP_KDF_CTX.pod
new file mode 100644
index 0000000..b01c719
--- /dev/null
+++ b/doc/man3/EVP_KDF_CTX.pod
@@ -0,0 +1,217 @@
+=pod
+
+=head1 NAME
+
+EVP_KDF_CTX, EVP_KDF_CTX_new_id, EVP_KDF_CTX_free, EVP_KDF_reset,
+EVP_KDF_ctrl, EVP_KDF_vctrl, EVP_KDF_ctrl_str, EVP_KDF_size,
+EVP_KDF_derive - EVP KDF routines
+
+=head1 SYNOPSIS
+
+ #include <openssl/kdf.h>
+
+ typedef struct evp_kdf_ctx_st EVP_KDF_CTX;
+
+ EVP_KDF_CTX *EVP_KDF_CTX_new_id(int id);
+ void EVP_KDF_CTX_free(EVP_KDF_CTX *ctx);
+ void EVP_KDF_reset(EVP_KDF_CTX *ctx);
+ int EVP_KDF_ctrl(EVP_KDF_CTX *ctx, int cmd, ...);
+ int EVP_KDF_vctrl(EVP_KDF_CTX *ctx, int cmd, va_list args);
+ int EVP_KDF_ctrl_str(EVP_KDF_CTX *ctx, const char *type, const char *value);
+ size_t EVP_KDF_size(EVP_KDF_CTX *ctx);
+ int EVP_KDF_derive(EVP_KDF_CTX *ctx, unsigned char *key, size_t keylen);
+
+=head1 DESCRIPTION
+
+The EVP KDF routines are a high level interface to Key Derivation Function
+algorithms and should be used instead of algorithm-specific functions.
+
+After creating a C<EVP_KDF_CTX> for the required algorithm using
+EVP_KDF_CTX_new_id(), inputs to the algorithm are supplied using calls to
+EVP_KDF_ctrl(), EVP_KDF_vctrl() or EVP_KDF_ctrl_str() before calling
+EVP_KDF_derive() to derive the key.
+
+=head2 Types
+
+B<EVP_KDF_CTX> is a context type that holds the algorithm inputs.
+
+=head2 Context manipulation functions
+
+EVP_KDF_CTX_new_id() creates a KDF context for the algorithm identified by the
+specified NID.
+
+EVP_KDF_CTX_free() frees up the context C<ctx>.  If C<ctx> is C<NULL>, nothing
+is done.
+
+=head2 Computing functions
+
+EVP_KDF_reset() resets the context to the default state as if the context
+had just been created.
+
+EVP_KDF_ctrl() is used to provide inputs to the KDF algorithm prior to
+EVP_KDF_derive() being called.  The inputs that may be provided will vary
+depending on the KDF algorithm or its implementation.  This functions takes
+variable arguments, the exact expected arguments depend on C<cmd>.
+See L</CONTROLS> below for a description of standard controls.
+
+EVP_KDF_vctrl() is the variant of EVP_KDF_ctrl() that takes a C<va_list>
+argument instead of variadic arguments.
+
+EVP_KDF_ctrl_str() allows an application to send an algorithm specific control
+operation to a context C<ctx> in string form.  This is intended to be used for
+options specified on the command line or in text files.
+
+EVP_KDF_size() returns the output size if the algorithm produces a fixed amount
+of output and C<SIZE_MAX> otherwise.  If an error occurs then 0 is returned.
+For some algorithms an error may result if input parameters necessary to
+calculate a fixed output size have not yet been supplied.
+
+EVP_KDF_derive() derives C<keylen> bytes of key material and places it in the
+C<key> buffer.  If the algorithm produces a fixed amount of output then an
+error will occur unless the C<keylen> parameter is equal to that output size,
+as returned by EVP_KDF_size().
+
+=head1 CONTROLS
+
+The standard controls are:
+
+=over 4
+
+=item B<EVP_KDF_CTRL_SET_PASS>
+
+This control expects two arguments: C<unsigned char *pass>, C<size_t passlen>
+
+Some KDF implementations require a password.  For those KDF implementations
+that support it, this control sets the password.
+
+EVP_KDF_ctrl_str() takes two type strings for this control:
+
+=over 4
+
+=item "pass"
+
+The value string is used as is.
+
+=item "hexpass"
+
+The value string is expected to be a hexadecimal number, which will be
+decoded before being passed on as the control value.
+
+=back
+
+=item B<EVP_KDF_CTRL_SET_SALT>
+
+This control expects two arguments: C<unsigned char *salt>, C<size_t saltlen>
+
+Some KDF implementations can take a salt.  For those KDF implementations that
+support it, this control sets the salt.
+
+The default value, if any, is implementation dependent.
+
+EVP_KDF_ctrl_str() takes two type strings for this control:
+
+=over 4
+
+=item "salt"
+
+The value string is used as is.
+
+=item "hexsalt"
+
+The value string is expected to be a hexadecimal number, which will be
+decoded before being passed on as the control value.
+
+=back
+
+=item B<EVP_KDF_CTRL_SET_ITER>
+
+This control expects one argument: C<int iter>
+
+Some KDF implementations require an iteration count. For those KDF implementations that support it, this control sets the iteration count.
+
+The default value, if any, is implementation dependent.
+
+EVP_KDF_ctrl_str() type string: "iter"
+
+The value string is expected to be a decimal number.
+
+=item B<EVP_KDF_CTRL_SET_MD>
+
+This control expects one argument: C<EVP_MD *md>
+
+For MAC implementations that use a message digest as an underlying computation
+algorithm, this control set what the digest algorithm should be.
+
+EVP_KDF_ctrl_str() type string: "md"
+
+The value string is expected to be the name of a digest.
+
+=item B<EVP_KDF_CTRL_SET_KEY>
+
+This control expects two arguments: C<unsigned char *key>, C<size_t keylen>
+
+Some KDF implementations require a key.  For those KDF implementations that
+support it, this control sets the key.
+
+EVP_KDF_ctrl_str() takes two type strings for this control:
+
+=over 4
+
+=item "key"
+
+The value string is used as is.
+
+=item "hexkey"
+
+The value string is expected to be a hexadecimal number, which will be
+decoded before being passed on as the control value.
+
+=back
+
+=item B<EVP_KDF_CTRL_SET_MAXMEM_BYTES>
+
+This control expects one argument: C<uint64_t maxmem_bytes>
+
+Memory-hard password-based KDF algorithms, such as scrypt, use an amount of
+memory that depends on the load factors provided as input.  For those KDF
+implementations that support it, this control sets an upper limit on the amount
+of memory that may be consumed while performing a key derivation.  If this
+memory usage limit is exceeded because the load factors are chosen too high,
+the key derivation will fail.
+
+The default value is implementation dependent.
+
+EVP_KDF_ctrl_str() type string: "maxmem_bytes"
+
+The value string is expected to be a decimal number.
+
+=back
+
+=head1 RETURN VALUES
+
+EVP_KDF_CTX_new_id() returns either the newly allocated C<EVP_KDF_CTX>
+structure or C<NULL> if an error occurred.
+
+EVP_KDF_CTX_free() and EVP_KDF_reset() do not return a value.
+
+EVP_KDF_size() returns the output size.  C<SIZE_MAX> is returned to indicate
+that the algorithm produces a variable amount of output; 0 to indicate failure.
+
+The remaining functions return 1 for success and 0 or a negative value for
+failure.  In particular, a return value of -2 indicates the operation is not
+supported by the KDF algorithm.
+
+=head1 SEE ALSO
+
+L<EVP_KDF_SCRYPT(7)>
+
+=head1 COPYRIGHT
+
+Copyright 2018 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License").  You may not use
+this file except in compliance with the License.  You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/EVP_KDF_HKDF.pod b/doc/man7/EVP_KDF_HKDF.pod
new file mode 100644
index 0000000..2188b13
--- /dev/null
+++ b/doc/man7/EVP_KDF_HKDF.pod
@@ -0,0 +1,180 @@
+=pod
+
+=head1 NAME
+
+EVP_KDF_HKDF - The HKDF EVP_KDF implementation
+
+=head1 DESCRIPTION
+
+Support for computing the B<HKDF> KDF through the B<EVP_KDF> API.
+
+The EVP_KDF_HKDF algorithm implements the HKDF key derivation function.
+HKDF follows the "extract-then-expand" paradigm, where the KDF logically
+consists of two modules. The first stage takes the input keying material
+and "extracts" from it a fixed-length pseudorandom key K. The second stage
+"expands" the key K into several additional pseudorandom keys (the output
+of the KDF).
+
+=head2 Numeric identity
+
+B<EVP_KDF_HKDF> is the numeric identity for this implementation; it
+can be used with the EVP_KDF_CTX_new_id() function.
+
+=head2 Supported controls
+
+The supported controls are:
+
+=over 4
+
+=item B<EVP_KDF_CTRL_SET_SALT>
+
+=item B<EVP_KDF_CTRL_SET_MD>
+
+=item B<EVP_KDF_CTRL_SET_KEY>
+
+These controls work as described in L<EVP_KDF_CTX(3)/CONTROLS>.
+
+=item B<EVP_KDF_CTRL_RESET_HKDF_INFO>
+
+This control does not expect any arguments.
+
+Resets the context info buffer to zero length.
+
+=item B<EVP_KDF_CTRL_ADD_HKDF_INFO>
+
+This control expects two arguments: C<unsigned char *info>, C<size_t infolen>
+
+Sets the info value to the first B<infolen> bytes of the buffer B<info>.  If a
+value is already set, the contents of the buffer are appended to the existing
+value.
+
+The total length of the context info buffer cannot exceed 1024 bytes;
+this should be more than enough for any normal use of HKDF.
+
+EVP_KDF_ctrl_str() takes two type strings for this control:
+
+=over 4
+
+=item "info"
+
+The value string is used as is.
+
+=item "hexinfo"
+
+The value string is expected to be a hexadecimal number, which will be
+decoded before being passed on as the control value.
+
+=back
+
+=item B<EVP_KDF_CTRL_SET_HKDF_MODE>
+
+This control expects one argument: C<int mode>
+
+Sets the mode for the HKDF operation. There are three modes that are currently
+defined:
+
+=over 4
+
+=item EVP_KDF_HKDF_MODE_EXTRACT_AND_EXPAND
+
+This is the default mode.  Calling L<EVP_KDF_derive(3)> on an EVP_KDF_CTX set
+up for HKDF will perform an extract followed by an expand operation in one go.
+The derived key returned will be the result after the expand operation. The
+intermediate fixed-length pseudorandom key K is not returned.
+
+In this mode the digest, key, salt and info values must be set before a key is
+derived otherwise an error will occur.
+
+=item EVP_KDF_HKDF_MODE_EXTRACT_ONLY
+
+In this mode calling L<EVP_KDF_derive(3)> will just perform the extract
+operation. The value returned will be the intermediate fixed-length pseudorandom
+key K.  The C<keylen> parameter must match the size of K, which can be looked
+up by calling EVP_KDF_size() after setting the mode and digest.
+
+The digest, key and salt values must be set before a key is derived otherwise
+an error will occur.
+
+=item EVP_KDF_HKDF_MODE_EXPAND_ONLY
+
+In this mode calling L<EVP_KDF_derive(3)> will just perform the expand
+operation. The input key should be set to the intermediate fixed-length
+pseudorandom key K returned from a previous extract operation.
+
+The digest, key and info values must be set before a key is derived otherwise
+an error will occur.
+
+=back
+
+EVP_KDF_ctrl_str() type string: "mode"
+
+The value string is expected to be one of: "EXTRACT_AND_EXPAND", "EXTRACT_ONLY"
+or "EXPAND_ONLY".
+
+=back
+
+=head1 NOTES
+
+A context for HKDF can be obtained by calling:
+
+ EVP_KDF_CTX *kctx = EVP_KDF_CTX_new_id(EVP_KDF_HKDF);
+
+The output length of an HKDF expand operation is specified via the C<keylen>
+parameter to the L<EVP_KDF_derive(3)> function.  When using
+EVP_KDF_HKDF_MODE_EXTRACT_ONLY the C<keylen> parameter must equal the size of
+the intermediate fixed-length pseudorandom key otherwise an error will occur.
+For that mode, the fixed output size can be looked up by calling EVP_KDF_size()
+after setting the mode and digest on the C<EVP_KDF_CTX>.
+
+=head1 EXAMPLE
+
+This example derives 10 bytes using SHA-256 with the secret key "secret",
+salt value "salt" and info value "label":
+
+ EVP_KDF_CTX *kctx;
+ unsigned char out[10];
+
+ kctx = EVP_KDF_CTX_new_id(EVP_KDF_HKDF);
+
+ if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_MD, EVP_sha256()) <= 0) {
+     error("EVP_KDF_CTRL_SET_MD");
+ }
+ if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_SALT, "salt", (size_t)4) <= 0) {
+     error("EVP_KDF_CTRL_SET_SALT");
+ }
+ if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_KEY, "secret", (size_t)6) <= 0) {
+     error("EVP_KDF_CTRL_SET_KEY");
+ }
+ if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_ADD_HKDF_INFO, "label", (size_t)5) <= 0) {
+     error("EVP_KDF_CTRL_ADD_HKDF_INFO");
+ }
+ if (EVP_KDF_derive(kctx, out, sizeof(out)) <= 0) {
+     error("EVP_KDF_derive");
+ }
+
+ EVP_KDF_CTX_free(kctx);
+
+=head1 CONFORMING TO
+
+RFC 5869
+
+=head1 SEE ALSO
+
+L<EVP_KDF_CTX>,
+L<EVP_KDF_CTX_new_id(3)>,
+L<EVP_KDF_CTX_free(3)>,
+L<EVP_KDF_ctrl(3)>,
+L<EVP_KDF_size(3)>,
+L<EVP_KDF_derive(3)>,
+L<EVP_KDF_CTX(3)/CONTROLS>
+
+=head1 COPYRIGHT
+
+Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License").  You may not use
+this file except in compliance with the License.  You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/EVP_KDF_PBKDF2.pod b/doc/man7/EVP_KDF_PBKDF2.pod
new file mode 100644
index 0000000..ba322d4
--- /dev/null
+++ b/doc/man7/EVP_KDF_PBKDF2.pod
@@ -0,0 +1,78 @@
+=pod
+
+=head1 NAME
+
+EVP_KDF_PBKDF2 - The PBKDF2 EVP_KDF implementation
+
+=head1 DESCRIPTION
+
+Support for computing the B<PBKDF2> password-based KDF through the B<EVP_KDF>
+API.
+
+The EVP_KDF_PBKDF2 algorithm implements the PBKDF2 password-based key
+derivation function, as described in RFC 2898; it derives a key from a password
+using a salt and iteration count.
+
+=head2 Numeric identity
+
+B<EVP_KDF_PBKDF2> is the numeric identity for this implementation; it
+can be used with the EVP_KDF_CTX_new_id() function.
+
+=head2 Supported controls
+
+The supported controls are:
+
+=over 4
+
+=item B<EVP_KDF_CTRL_SET_PASS>
+
+=item B<EVP_KDF_CTRL_SET_SALT>
+
+=item B<EVP_KDF_CTRL_SET_ITER>
+
+=item B<EVP_KDF_CTRL_SET_MD>
+
+These controls work as described in L<EVP_KDF_CTX(3)/CONTROLS>.
+
+B<iter> is the iteration count and its value should be greater than or equal to
+1. RFC 2898 suggests an iteration count of at least 1000.  The default value is
+2048.  Any B<iter> less than 1 is treated as a single iteration.
+
+=back
+
+=head1 NOTES
+
+A typical application of this algorithm is to derive keying material for an
+encryption algorithm from a password in the B<pass>, a salt in B<salt>,
+and an iteration count.
+
+Increasing the B<iter> parameter slows down the algorithm which makes it
+harder for an attacker to perform a brute force attack using a large number
+of candidate passwords.
+
+No assumption is made regarding the given password; it is simply treated as a
+byte sequence.
+
+=head1 CONFORMING TO
+
+RFC 2898
+
+=head1 SEE ALSO
+
+L<EVP_KDF_CTX>,
+L<EVP_KDF_CTX_new_id(3)>,
+L<EVP_KDF_CTX_free(3)>,
+L<EVP_KDF_ctrl(3)>,
+L<EVP_KDF_derive(3)>,
+L<EVP_KDF_CTX(3)/CONTROLS>
+
+=head1 COPYRIGHT
+
+Copyright 2018 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License").  You may not use
+this file except in compliance with the License.  You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/scrypt.pod b/doc/man7/EVP_KDF_SCRYPT.pod
similarity index 53%
rename from doc/man7/scrypt.pod
rename to doc/man7/EVP_KDF_SCRYPT.pod
index eabad5b..a44dc63 100644
--- a/doc/man7/scrypt.pod
+++ b/doc/man7/EVP_KDF_SCRYPT.pod
@@ -2,11 +2,14 @@
 
 =head1 NAME
 
-scrypt - EVP_PKEY scrypt KDF support
+EVP_KDF_SCRYPT - The scrypt EVP_KDF implementation
 
 =head1 DESCRIPTION
 
-The EVP_PKEY_SCRYPT algorithm implements the scrypt password based key
+Support for computing the B<scrypt> password-based KDF through the B<EVP_KDF>
+API.
+
+The EVP_KDF_SCRYPT algorithm implements the scrypt password-based key
 derivation function, as described in RFC 7914.  It is memory-hard in the sense
 that it deliberately requires a significant amount of RAM for efficient
 computation. The intention of this is to render brute forcing of passwords on
@@ -26,49 +29,82 @@ computation time of less than 5 seconds on a 2.5 GHz Intel Core 2 Duo are N =
 2^20 = 1048576, r = 8, p = 1. Consequently, the required amount of memory for
 this computation is roughly 1 GiB. On a more recent CPU (Intel i7-5930K at 3.5
 GHz), this computation takes about 3 seconds. When N, r or p are not specified,
-they default to 1048576, 8, and 1, respectively. The default amount of RAM that
+they default to 1048576, 8, and 1, respectively. The maximum amount of RAM that
 may be used by scrypt defaults to 1025 MiB.
 
+=head2 Numeric identity
+
+B<EVP_KDF_SCRYPT> is the numeric identity for this implementation; it
+can be used with the EVP_KDF_CTX_new_id() function.
+
+=head2 Supported controls
+
+The supported controls are:
+
+=over 4
+
+=item B<EVP_KDF_CTRL_SET_PASS>
+
+=item B<EVP_KDF_CTRL_SET_SALT>
+
+These controls work as described in L<EVP_KDF_CTX(3)/CONTROLS>.
+
+=item B<EVP_KDF_CTRL_SET_SCRYPT_N>
+
+=item B<EVP_KDF_CTRL_SET_SCRYPT_R>
+
+=item B<EVP_KDF_CTRL_SET_SCRYPT_P>
+
+B<EVP_KDF_CTRL_SET_SCRYPT_N> expects one argument: C<uint64_t N>
+
+B<EVP_KDF_CTRL_SET_SCRYPT_R> expects one argument: C<uint32_t r>
+
+B<EVP_KDF_CTRL_SET_SCRYPT_P> expects one argument: C<uint32_t p>
+
+These controls configure the scrypt work factors N, r and p.
+
+EVP_KDF_ctrl_str() type strings: "N", "r" and "p", respectively.
+
+The corresponding value strings are expected to be decimal numbers.
+
+=back
+
 =head1 NOTES
 
 A context for scrypt can be obtained by calling:
 
- EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_SCRYPT, NULL);
+ EVP_KDF_CTX *kctx = EVP_KDF_CTX_new_id(EVP_KDF_SCRYPT);
 
 The output length of an scrypt key derivation is specified via the
-length parameter to the L<EVP_PKEY_derive(3)> function.
+B<keylen> parameter to the L<EVP_KDF_derive(3)> function.
 
 =head1 EXAMPLE
 
-This example derives a 64-byte long test vector using scrypt using the password
+This example derives a 64-byte long test vector using scrypt with the password
 "password", salt "NaCl" and N = 1024, r = 8, p = 16.
 
- EVP_PKEY_CTX *pctx;
+ EVP_KDF_CTX *kctx;
  unsigned char out[64];
 
- size_t outlen = sizeof(out);
- pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_SCRYPT, NULL);
+ kctx = EVP_KDF_CTX_new_id(EVP_KDF_SCRYPT);
 
- if (EVP_PKEY_derive_init(pctx) <= 0) {
-     error("EVP_PKEY_derive_init");
- }
- if (EVP_PKEY_CTX_set1_pbe_pass(pctx, "password", 8) <= 0) {
-     error("EVP_PKEY_CTX_set1_pbe_pass");
+ if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_PASS, "password", (size_t)8) <= 0) {
+     error("EVP_KDF_CTRL_SET_PASS");
  }
- if (EVP_PKEY_CTX_set1_scrypt_salt(pctx, "NaCl", 4) <= 0) {
-     error("EVP_PKEY_CTX_set1_scrypt_salt");
+ if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_SALT, "NaCl", (size_t)4) <= 0) {
+     error("EVP_KDF_CTRL_SET_SALT");
  }
- if (EVP_PKEY_CTX_set_scrypt_N(pctx, 1024) <= 0) {
-     error("EVP_PKEY_CTX_set_scrypt_N");
+ if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_SCRYPT_N, (uint64_t)1024) <= 0) {
+     error("EVP_KDF_CTRL_SET_SCRYPT_N");
  }
- if (EVP_PKEY_CTX_set_scrypt_r(pctx, 8) <= 0) {
-     error("EVP_PKEY_CTX_set_scrypt_r");
+ if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_SCRYPT_R, (uint32_t)8) <= 0) {
+     error("EVP_KDF_CTRL_SET_SCRYPT_R");
  }
- if (EVP_PKEY_CTX_set_scrypt_p(pctx, 16) <= 0) {
-     error("EVP_PKEY_CTX_set_scrypt_p");
+ if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_SCRYPT_P, (uint32_t)16) <= 0) {
+     error("EVP_KDF_CTRL_SET_SCRYPT_P");
  }
- if (EVP_PKEY_derive(pctx, out, &outlen) <= 0) {
-     error("EVP_PKEY_derive");
+ if (EVP_KDF_derive(kctx, out, sizeof(out)) <= 0) {
+     error("EVP_KDF_derive");
  }
 
  {
@@ -86,7 +122,7 @@ This example derives a 64-byte long test vector using scrypt using the password
      assert(!memcmp(out, expected, sizeof(out)));
  }
 
- EVP_PKEY_CTX_free(pctx);
+ EVP_KDF_CTX_free(kctx);
 
 =head1 CONFORMING TO
 
@@ -94,14 +130,12 @@ RFC 7914
 
 =head1 SEE ALSO
 
-L<EVP_PKEY_CTX_set1_scrypt_salt(3)>,
-L<EVP_PKEY_CTX_set_scrypt_N(3)>,
-L<EVP_PKEY_CTX_set_scrypt_r(3)>,
-L<EVP_PKEY_CTX_set_scrypt_p(3)>,
-L<EVP_PKEY_CTX_set_scrypt_maxmem_bytes(3)>,
-L<EVP_PKEY_CTX_new(3)>,
-L<EVP_PKEY_CTX_ctrl_str(3)>,
-L<EVP_PKEY_derive(3)>
+L<EVP_KDF_CTX>,
+L<EVP_KDF_CTX_new_id(3)>,
+L<EVP_KDF_CTX_free(3)>,
+L<EVP_KDF_ctrl(3)>,
+L<EVP_KDF_derive(3)>,
+L<EVP_KDF_CTX(3)/CONTROLS>
 
 =head1 COPYRIGHT
 
diff --git a/doc/man7/EVP_KDF_TLS1_PRF.pod b/doc/man7/EVP_KDF_TLS1_PRF.pod
new file mode 100644
index 0000000..e6cbe09
--- /dev/null
+++ b/doc/man7/EVP_KDF_TLS1_PRF.pod
@@ -0,0 +1,142 @@
+=pod
+
+=head1 NAME
+
+EVP_KDF_TLS1_PRF - The TLS1 PRF EVP_KDF implementation
+
+=head1 DESCRIPTION
+
+Support for computing the B<TLS1> PRF through the B<EVP_KDF> API.
+
+The EVP_KDF_TLS1_PRF algorithm implements the PRF used by TLS versions up to
+and including TLS 1.2.
+
+=head2 Numeric identity
+
+B<EVP_KDF_TLS1_PRF> is the numeric identity for this implementation; it
+can be used with the EVP_KDF_CTX_new_id() function.
+
+=head2 Supported controls
+
+The supported controls are:
+
+=over 4
+
+=item B<EVP_KDF_CTRL_SET_MD>
+
+This control works as described in L<EVP_KDF_CTX(3)/CONTROLS>.
+
+The C<EVP_KDF_CTRL_SET_MD> control is used to set the message digest associated
+with the TLS PRF.  EVP_md5_sha1() is treated as a special case which uses the
+PRF algorithm using both B<MD5> and B<SHA1> as used in TLS 1.0 and 1.1.
+
+=item B<EVP_KDF_CTRL_SET_TLS_SECRET>
+
+This control expects two arguments: C<unsigned char *sec>, C<size_t seclen>
+
+Sets the secret value of the TLS PRF to B<seclen> bytes of the buffer B<sec>.
+Any existing secret value is replaced.
+
+EVP_KDF_ctrl_str() takes two type strings for this control:
+
+=over 4
+
+=item "secret"
+
+The value string is used as is.
+
+=item "hexsecret"
+
+The value string is expected to be a hexadecimal number, which will be
+decoded before being passed on as the control value.
+
+=back
+
+=item B<EVP_KDF_CTRL_RESET_TLS_SEED>
+
+This control does not expect any arguments.
+
+Resets the context seed buffer to zero length.
+
+=item B<EVP_KDF_CTRL_ADD_TLS_SEED>
+
+This control expects two arguments: C<unsigned char *seed>, C<size_t seedlen>
+
+Sets the seed to B<seedlen> bytes of B<seed>.  If a seed is already set it is
+appended to the existing value.
+
+The total length of the context seed buffer cannot exceed 1024 bytes;
+this should be more than enough for any normal use of the TLS PRF.
+
+EVP_KDF_ctrl_str() takes two type strings for this control:
+
+=over 4
+
+=item "seed"
+
+The value string is used as is.
+
+=item "hexseed"
+
+The value string is expected to be a hexadecimal number, which will be
+decoded before being passed on as the control value.
+
+=back
+
+=back
+
+=head1 NOTES
+
+A context for the TLS PRF can be obtained by calling:
+
+ EVP_KDF_CTX *kctx = EVP_KDF_CTX_new_id(EVP_KDF_TLS1_PRF, NULL);
+
+The digest, secret value and seed must be set before a key is derived otherwise
+an error will occur.
+
+The output length of the PRF is specified by the C<keylen> parameter to the
+EVP_KDF_derive() function.
+
+=head1 EXAMPLE
+
+This example derives 10 bytes using SHA-256 with the secret key "secret"
+and seed value "seed":
+
+ EVP_KDF_CTX *kctx;
+ unsigned char out[10];
+
+ kctx = EVP_KDF_CTX_new_id(EVP_KDF_TLS1_PRF);
+ if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_MD, EVP_sha256()) <= 0) {
+     error("EVP_KDF_CTRL_SET_MD");
+ }
+ if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_TLS_SECRET,
+                  "secret", (size_t)6) <= 0) {
+     error("EVP_KDF_CTRL_SET_TLS_SECRET");
+ }
+ if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_ADD_TLS_SEED, "seed", (size_t)4) <= 0) {
+     error("EVP_KDF_CTRL_ADD_TLS_SEED");
+ }
+ if (EVP_KDF_derive(kctx, out, sizeof(out)) <= 0) {
+     error("EVP_KDF_derive");
+ }
+ EVP_KDF_CTX_free(kctx);
+
+=head1 SEE ALSO
+
+L<EVP_KDF_CTX>,
+L<EVP_KDF_CTX_new_id(3)>,
+L<EVP_KDF_CTX_free(3)>,
+L<EVP_KDF_ctrl(3)>,
+L<EVP_KDF_derive(3)>,
+L<EVP_KDF_CTX(3)/CONTROLS>
+
+=head1 COPYRIGHT
+
+Copyright 2018 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License").  You may not use
+this file except in compliance with the License.  You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/include/openssl/evperr.h b/include/openssl/evperr.h
index d3ed5b5..7da602d 100644
--- a/include/openssl/evperr.h
+++ b/include/openssl/evperr.h
@@ -1,6 +1,6 @@
 /*
  * Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -55,6 +55,9 @@ int ERR_load_EVP_strings(void);
 # define EVP_F_EVP_ENCRYPTDECRYPTUPDATE                   219
 # define EVP_F_EVP_ENCRYPTFINAL_EX                        127
 # define EVP_F_EVP_ENCRYPTUPDATE                          167
+# define EVP_F_EVP_KDF_CTRL                               224
+# define EVP_F_EVP_KDF_CTRL_STR                           225
+# define EVP_F_EVP_KDF_CTX_NEW_ID                         226
 # define EVP_F_EVP_MAC_CTRL                               209
 # define EVP_F_EVP_MAC_CTRL_STR                           210
 # define EVP_F_EVP_MAC_CTX_COPY                           211
@@ -125,6 +128,7 @@ int ERR_load_EVP_strings(void);
 # define EVP_F_PKCS5_V2_PBE_KEYIVGEN                      118
 # define EVP_F_PKCS5_V2_PBKDF2_KEYIVGEN                   164
 # define EVP_F_PKCS5_V2_SCRYPT_KEYIVGEN                   180
+# define EVP_F_PKEY_KDF_CTRL                              227
 # define EVP_F_PKEY_MAC_INIT                              214
 # define EVP_F_PKEY_SET_TYPE                              158
 # define EVP_F_POLY1305_CTRL                              216
@@ -132,6 +136,7 @@ int ERR_load_EVP_strings(void);
 # define EVP_F_RC5_CTRL                                   125
 # define EVP_F_S390X_AES_GCM_CTRL                         201
 # define EVP_F_S390X_AES_GCM_TLS_CIPHER                   208
+# define EVP_F_SCRYPT_ALG                                 228
 # define EVP_F_UPDATE                                     173
 
 /*
@@ -188,6 +193,7 @@ int ERR_load_EVP_strings(void);
 # define EVP_R_ONLY_ONESHOT_SUPPORTED                     177
 # define EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE   150
 # define EVP_R_OPERATON_NOT_INITIALIZED                   151
+# define EVP_R_PARAMETER_TOO_LARGE                        187
 # define EVP_R_PARTIALLY_OVERLAPPING                      162
 # define EVP_R_PBKDF2_ERROR                               181
 # define EVP_R_PKEY_APPLICATION_ASN1_METHOD_ALREADY_REGISTERED 179
diff --git a/include/openssl/kdf.h b/include/openssl/kdf.h
index b9e7824..0f39a14 100644
--- a/include/openssl/kdf.h
+++ b/include/openssl/kdf.h
@@ -10,10 +10,50 @@
 #ifndef HEADER_KDF_H
 # define HEADER_KDF_H
 
+# include <openssl/ossl_typ.h>
 # include <openssl/kdferr.h>
-#ifdef __cplusplus
+# ifdef __cplusplus
 extern "C" {
-#endif
+# endif
+
+# define EVP_KDF_PBKDF2     NID_id_pbkdf2
+# define EVP_KDF_SCRYPT     NID_id_scrypt
+# define EVP_KDF_TLS1_PRF   NID_tls1_prf
+# define EVP_KDF_HKDF       NID_hkdf
+
+EVP_KDF_CTX *EVP_KDF_CTX_new_id(int id);
+void EVP_KDF_CTX_free(EVP_KDF_CTX *ctx);
+
+void EVP_KDF_reset(EVP_KDF_CTX *ctx);
+int EVP_KDF_ctrl(EVP_KDF_CTX *ctx, int cmd, ...);
+int EVP_KDF_vctrl(EVP_KDF_CTX *ctx, int cmd, va_list args);
+int EVP_KDF_ctrl_str(EVP_KDF_CTX *ctx, const char *type, const char *value);
+size_t EVP_KDF_size(EVP_KDF_CTX *ctx);
+int EVP_KDF_derive(EVP_KDF_CTX *ctx, unsigned char *key, size_t keylen);
+
+
+# define EVP_KDF_CTRL_SET_PASS          0x01 /* unsigned char *, size_t */
+# define EVP_KDF_CTRL_SET_SALT          0x02 /* unsigned char *, size_t */
+# define EVP_KDF_CTRL_SET_ITER          0x03 /* int */
+# define EVP_KDF_CTRL_SET_MD            0x04 /* EVP_MD * */
+# define EVP_KDF_CTRL_SET_KEY           0x05 /* unsigned char *, size_t */
+# define EVP_KDF_CTRL_SET_MAXMEM_BYTES  0x06 /* uint64_t */
+# define EVP_KDF_CTRL_SET_TLS_SECRET    0x07 /* unsigned char *, size_t */
+# define EVP_KDF_CTRL_RESET_TLS_SEED    0x08
+# define EVP_KDF_CTRL_ADD_TLS_SEED      0x09 /* unsigned char *, size_t */
+# define EVP_KDF_CTRL_RESET_HKDF_INFO   0x0a
+# define EVP_KDF_CTRL_ADD_HKDF_INFO     0x0b /* unsigned char *, size_t */
+# define EVP_KDF_CTRL_SET_HKDF_MODE     0x0c /* int */
+# define EVP_KDF_CTRL_SET_SCRYPT_N      0x0d /* uint64_t */
+# define EVP_KDF_CTRL_SET_SCRYPT_R      0x0e /* uint32_t */
+# define EVP_KDF_CTRL_SET_SCRYPT_P      0x0f /* uint32_t */
+
+# define EVP_KDF_HKDF_MODE_EXTRACT_AND_EXPAND  0
+# define EVP_KDF_HKDF_MODE_EXTRACT_ONLY        1
+# define EVP_KDF_HKDF_MODE_EXPAND_ONLY         2
+
+
+/**** The legacy PKEY-based KDF API follows. ****/
 
 # define EVP_PKEY_CTRL_TLS_MD                   (EVP_PKEY_ALG_CTRL)
 # define EVP_PKEY_CTRL_TLS_SECRET               (EVP_PKEY_ALG_CTRL + 1)
@@ -30,9 +70,12 @@ extern "C" {
 # define EVP_PKEY_CTRL_SCRYPT_P                 (EVP_PKEY_ALG_CTRL + 12)
 # define EVP_PKEY_CTRL_SCRYPT_MAXMEM_BYTES      (EVP_PKEY_ALG_CTRL + 13)
 
-# define EVP_PKEY_HKDEF_MODE_EXTRACT_AND_EXPAND 0
-# define EVP_PKEY_HKDEF_MODE_EXTRACT_ONLY       1
-# define EVP_PKEY_HKDEF_MODE_EXPAND_ONLY        2
+# define EVP_PKEY_HKDEF_MODE_EXTRACT_AND_EXPAND \
+            EVP_KDF_HKDF_MODE_EXTRACT_AND_EXPAND
+# define EVP_PKEY_HKDEF_MODE_EXTRACT_ONLY       \
+            EVP_KDF_HKDF_MODE_EXTRACT_ONLY
+# 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, \
@@ -91,7 +134,7 @@ extern "C" {
                             EVP_PKEY_CTRL_SCRYPT_MAXMEM_BYTES, maxmem_bytes)
 
 
-# ifdef  __cplusplus
+# ifdef __cplusplus
 }
 # endif
 #endif
diff --git a/include/openssl/kdferr.h b/include/openssl/kdferr.h
index 0fddea0..a143959 100644
--- a/include/openssl/kdferr.h
+++ b/include/openssl/kdferr.h
@@ -1,6 +1,6 @@
 /*
  * Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -19,6 +19,23 @@ int ERR_load_KDF_strings(void);
 /*
  * KDF function codes.
  */
+# define KDF_F_HKDF_EXTRACT                               112
+# define KDF_F_KDF_HKDF_DERIVE                            113
+# define KDF_F_KDF_HKDF_NEW                               114
+# define KDF_F_KDF_HKDF_SIZE                              115
+# define KDF_F_KDF_MD2CTRL                                116
+# define KDF_F_KDF_PBKDF2_CTRL_STR                        117
+# define KDF_F_KDF_PBKDF2_DERIVE                          118
+# define KDF_F_KDF_PBKDF2_NEW                             119
+# define KDF_F_KDF_SCRYPT_CTRL_STR                        120
+# define KDF_F_KDF_SCRYPT_CTRL_UINT32                     121
+# define KDF_F_KDF_SCRYPT_CTRL_UINT64                     122
+# define KDF_F_KDF_SCRYPT_DERIVE                          123
+# define KDF_F_KDF_SCRYPT_NEW                             124
+# define KDF_F_KDF_TLS1_PRF_CTRL_STR                      125
+# define KDF_F_KDF_TLS1_PRF_DERIVE                        126
+# define KDF_F_KDF_TLS1_PRF_NEW                           127
+# define KDF_F_PBKDF2_SET_MEMBUF                          128
 # define KDF_F_PKEY_HKDF_CTRL_STR                         103
 # define KDF_F_PKEY_HKDF_DERIVE                           102
 # define KDF_F_PKEY_HKDF_INIT                             108
@@ -30,6 +47,7 @@ int ERR_load_KDF_strings(void);
 # define KDF_F_PKEY_TLS1_PRF_CTRL_STR                     100
 # define KDF_F_PKEY_TLS1_PRF_DERIVE                       101
 # define KDF_F_PKEY_TLS1_PRF_INIT                         110
+# define KDF_F_SCRYPT_SET_MEMBUF                          129
 # define KDF_F_TLS1_PRF_ALG                               111
 
 /*
@@ -47,5 +65,6 @@ int ERR_load_KDF_strings(void);
 # define KDF_R_UNKNOWN_PARAMETER_TYPE                     103
 # define KDF_R_VALUE_ERROR                                108
 # define KDF_R_VALUE_MISSING                              102
+# define KDF_R_WRONG_OUTPUT_BUFFER_SIZE                   112
 
 #endif
diff --git a/include/openssl/ossl_typ.h b/include/openssl/ossl_typ.h
index 51171d5..1c6acce 100644
--- a/include/openssl/ossl_typ.h
+++ b/include/openssl/ossl_typ.h
@@ -99,6 +99,8 @@ typedef struct evp_pkey_asn1_method_st EVP_PKEY_ASN1_METHOD;
 typedef struct evp_pkey_method_st EVP_PKEY_METHOD;
 typedef struct evp_pkey_ctx_st EVP_PKEY_CTX;
 
+typedef struct evp_kdf_ctx_st EVP_KDF_CTX;
+
 typedef struct evp_Encode_Ctx_st EVP_ENCODE_CTX;
 
 typedef struct hmac_ctx_st HMAC_CTX;
diff --git a/test/build.info b/test/build.info
index 7d4f953..5904267 100644
--- a/test/build.info
+++ b/test/build.info
@@ -38,7 +38,8 @@ IF[{- !$disabled{tests} -}]
           ssl_test_ctx_test ssl_test x509aux cipherlist_test asynciotest \
           bio_callback_test bio_memleak_test \
           bioprinttest sslapitest dtlstest sslcorrupttest bio_enc_test \
-          pkey_meth_test pkey_meth_kdf_test uitest cipherbytes_test \
+          pkey_meth_test pkey_meth_kdf_test evp_kdf_test uitest \
+          cipherbytes_test \
           asn1_encode_test asn1_decode_test asn1_string_table_test \
           x509_time_test x509_dup_cert_test x509_check_cert_pkey_test \
           recordlentest drbgtest sslbuffertest \
@@ -330,6 +331,10 @@ IF[{- !$disabled{tests} -}]
   INCLUDE[pkey_meth_kdf_test]=../include ../apps/include
   DEPEND[pkey_meth_kdf_test]=../libcrypto libtestutil.a
 
+  SOURCE[evp_kdf_test]=evp_kdf_test.c
+  INCLUDE[evp_kdf_test]=../include
+  DEPEND[evp_kdf_test]=../libcrypto libtestutil.a
+
   SOURCE[x509_time_test]=x509_time_test.c
   INCLUDE[x509_time_test]=../include ../apps/include
   DEPEND[x509_time_test]=../libcrypto libtestutil.a
diff --git a/test/evp_kdf_test.c b/test/evp_kdf_test.c
new file mode 100644
index 0000000..923e9ae
--- /dev/null
+++ b/test/evp_kdf_test.c
@@ -0,0 +1,237 @@
+/*
+ * Copyright 2018-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright (c) 2018-2019, 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
+ */
+
+/* Tests of the EVP_KDF_CTX APIs */
+
+#include <stdio.h>
+#include <string.h>
+
+#include <openssl/evp.h>
+#include <openssl/kdf.h>
+#include "testutil.h"
+
+static int test_kdf_tls1_prf(void)
+{
+    int ret = 0;
+    EVP_KDF_CTX *kctx;
+    unsigned char out[16];
+
+    if ((kctx = EVP_KDF_CTX_new_id(EVP_KDF_TLS1_PRF)) == NULL) {
+        TEST_error("EVP_KDF_TLS1_PRF");
+        goto err;
+    }
+    if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_MD, EVP_sha256()) <= 0) {
+        TEST_error("EVP_KDF_CTRL_SET_MD");
+        goto err;
+    }
+    if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_TLS_SECRET,
+                     "secret", (size_t)6) <= 0) {
+        TEST_error("EVP_KDF_CTRL_SET_TLS_SECRET");
+        goto err;
+    }
+    if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_ADD_TLS_SEED, "seed", (size_t)4) <= 0) {
+        TEST_error("EVP_KDF_CTRL_ADD_TLS_SEED");
+        goto err;
+    }
+    if (EVP_KDF_derive(kctx, out, sizeof(out)) <= 0) {
+        TEST_error("EVP_KDF_derive");
+        goto err;
+    }
+
+    {
+        const unsigned char expected[sizeof(out)] = {
+            0x8e, 0x4d, 0x93, 0x25, 0x30, 0xd7, 0x65, 0xa0,
+            0xaa, 0xe9, 0x74, 0xc3, 0x04, 0x73, 0x5e, 0xcc
+        };
+        if (!TEST_mem_eq(out, sizeof(out), expected, sizeof(expected))) {
+            goto err;
+        }
+    }
+    ret = 1;
+err:
+    EVP_KDF_CTX_free(kctx);
+    return ret;
+}
+
+static int test_kdf_hkdf(void)
+{
+    int ret = 0;
+    EVP_KDF_CTX *kctx;
+    unsigned char out[10];
+
+    if ((kctx = EVP_KDF_CTX_new_id(EVP_KDF_HKDF)) == NULL) {
+        TEST_error("EVP_KDF_HKDF");
+        goto err;
+    }
+    if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_MD, EVP_sha256()) <= 0) {
+        TEST_error("EVP_KDF_CTRL_SET_MD");
+        goto err;
+    }
+    if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_SALT, "salt", (size_t)4) <= 0) {
+        TEST_error("EVP_KDF_CTRL_SET_SALT");
+        goto err;
+    }
+    if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_KEY, "secret", (size_t)6) <= 0) {
+        TEST_error("EVP_KDF_CTRL_SET_KEY");
+        goto err;
+    }
+    if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_ADD_HKDF_INFO,
+                     "label", (size_t)5) <= 0) {
+        TEST_error("EVP_KDF_CTRL_ADD_HKDF_INFO");
+        goto err;
+    }
+    if (EVP_KDF_derive(kctx, out, sizeof(out)) <= 0) {
+        TEST_error("EVP_KDF_derive");
+        goto err;
+    }
+
+    {
+        const unsigned char expected[sizeof(out)] = {
+            0x2a, 0xc4, 0x36, 0x9f, 0x52, 0x59, 0x96, 0xf8, 0xde, 0x13
+        };
+        if (!TEST_mem_eq(out, sizeof(out), expected, sizeof(expected))) {
+            goto err;
+        }
+    }
+    ret = 1;
+err:
+    EVP_KDF_CTX_free(kctx);
+    return ret;
+}
+
+static int test_kdf_pbkdf2(void)
+{
+    int ret = 0;
+    EVP_KDF_CTX *kctx;
+    unsigned char out[32];
+
+    if ((kctx = EVP_KDF_CTX_new_id(EVP_KDF_PBKDF2)) == NULL) {
+        TEST_error("EVP_KDF_PBKDF2");
+        goto err;
+    }
+    if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_PASS, "password", (size_t)8) <= 0) {
+        TEST_error("EVP_KDF_CTRL_SET_PASS");
+        goto err;
+    }
+    if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_SALT, "salt", (size_t)4) <= 0) {
+        TEST_error("EVP_KDF_CTRL_SET_SALT");
+        goto err;
+    }
+    if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_ITER, 2) <= 0) {
+        TEST_error("EVP_KDF_CTRL_SET_ITER");
+        goto err;
+    }
+    if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_MD, EVP_sha256()) <= 0) {
+        TEST_error("EVP_KDF_CTRL_SET_MD");
+        goto err;
+    }
+    if (EVP_KDF_derive(kctx, out, sizeof(out)) <= 0) {
+        TEST_error("EVP_KDF_derive");
+        goto err;
+    }
+
+    {
+        const unsigned char expected[sizeof(out)] = {
+            0xae, 0x4d, 0x0c, 0x95, 0xaf, 0x6b, 0x46, 0xd3,
+            0x2d, 0x0a, 0xdf, 0xf9, 0x28, 0xf0, 0x6d, 0xd0,
+            0x2a, 0x30, 0x3f, 0x8e, 0xf3, 0xc2, 0x51, 0xdf,
+            0xd6, 0xe2, 0xd8, 0x5a, 0x95, 0x47, 0x4c, 0x43
+        };
+        if (!TEST_mem_eq(out, sizeof(out), expected, sizeof(expected))) {
+            goto err;
+        }
+    }
+    ret = 1;
+err:
+    EVP_KDF_CTX_free(kctx);
+    return ret;
+}
+
+#ifndef OPENSSL_NO_SCRYPT
+static int test_kdf_scrypt(void)
+{
+    int ret = 0;
+    EVP_KDF_CTX *kctx;
+    unsigned char out[64];
+
+    if ((kctx = EVP_KDF_CTX_new_id(EVP_KDF_SCRYPT)) == NULL) {
+        TEST_error("EVP_KDF_SCRYPT");
+        goto err;
+    }
+    if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_PASS, "password", (size_t)8) <= 0) {
+        TEST_error("EVP_KDF_CTRL_SET_PASS");
+        goto err;
+    }
+    if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_SALT, "NaCl", (size_t)4) <= 0) {
+        TEST_error("EVP_KDF_CTRL_SET_SALT");
+        goto err;
+    }
+    if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_SCRYPT_N, (uint64_t)1024) <= 0) {
+        TEST_error("EVP_KDF_CTRL_SET_SCRYPT_N");
+        goto err;
+    }
+    if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_SCRYPT_R, (uint32_t)8) <= 0) {
+        TEST_error("EVP_KDF_CTRL_SET_SCRYPT_R");
+        goto err;
+    }
+    if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_SCRYPT_P, (uint32_t)16) <= 0) {
+        TEST_error("EVP_KDF_CTRL_SET_SCRYPT_P");
+        goto err;
+    }
+    if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_MAXMEM_BYTES, (uint64_t)16) <= 0) {
+        TEST_error("EVP_KDF_CTRL_SET_MAXMEM_BYTES");
+        goto err;
+    }
+    if (EVP_KDF_derive(kctx, out, sizeof(out)) > 0) {
+        TEST_error("EVP_KDF_derive should have failed");
+        goto err;
+    }
+    if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_MAXMEM_BYTES,
+                     (uint64_t)(10 * 1024 * 1024)) <= 0) {
+        TEST_error("EVP_KDF_CTRL_SET_MAXMEM_BYTES");
+        goto err;
+    }
+    if (EVP_KDF_derive(kctx, out, sizeof(out)) <= 0) {
+        TEST_error("EVP_KDF_derive");
+        goto err;
+    }
+
+    {
+        const unsigned char expected[sizeof(out)] = {
+            0xfd, 0xba, 0xbe, 0x1c, 0x9d, 0x34, 0x72, 0x00,
+            0x78, 0x56, 0xe7, 0x19, 0x0d, 0x01, 0xe9, 0xfe,
+            0x7c, 0x6a, 0xd7, 0xcb, 0xc8, 0x23, 0x78, 0x30,
+            0xe7, 0x73, 0x76, 0x63, 0x4b, 0x37, 0x31, 0x62,
+            0x2e, 0xaf, 0x30, 0xd9, 0x2e, 0x22, 0xa3, 0x88,
+            0x6f, 0xf1, 0x09, 0x27, 0x9d, 0x98, 0x30, 0xda,
+            0xc7, 0x27, 0xaf, 0xb9, 0x4a, 0x83, 0xee, 0x6d,
+            0x83, 0x60, 0xcb, 0xdf, 0xa2, 0xcc, 0x06, 0x40
+        };
+        if (!TEST_mem_eq(out, sizeof(out), expected, sizeof(expected))) {
+            goto err;
+        }
+    }
+    ret = 1;
+err:
+    EVP_KDF_CTX_free(kctx);
+    return ret;
+}
+#endif
+
+int setup_tests(void)
+{
+    ADD_TEST(test_kdf_tls1_prf);
+    ADD_TEST(test_kdf_hkdf);
+    ADD_TEST(test_kdf_pbkdf2);
+#ifndef OPENSSL_NO_SCRYPT
+    ADD_TEST(test_kdf_scrypt);
+#endif
+    return 1;
+}
diff --git a/test/evp_test.c b/test/evp_test.c
index 49d254d..cad580e 100644
--- a/test/evp_test.c
+++ b/test/evp_test.c
@@ -1892,13 +1892,14 @@ static const EVP_TEST_METHOD encode_test_method = {
     encode_test_run,
 };
 
+
 /**
 ***  KDF TESTS
 **/
 
 typedef struct kdf_data_st {
     /* Context for this operation */
-    EVP_PKEY_CTX *ctx;
+    EVP_KDF_CTX *ctx;
     /* Expected output */
     unsigned char *output;
     size_t output_len;
@@ -1925,16 +1926,11 @@ static int kdf_test_init(EVP_TEST *t, const char *name)
 
     if (!TEST_ptr(kdata = OPENSSL_zalloc(sizeof(*kdata))))
         return 0;
-    kdata->ctx = EVP_PKEY_CTX_new_id(kdf_nid, NULL);
+    kdata->ctx = EVP_KDF_CTX_new_id(kdf_nid);
     if (kdata->ctx == NULL) {
         OPENSSL_free(kdata);
         return 0;
     }
-    if (EVP_PKEY_derive_init(kdata->ctx) <= 0) {
-        EVP_PKEY_CTX_free(kdata->ctx);
-        OPENSSL_free(kdata);
-        return 0;
-    }
     t->data = kdata;
     return 1;
 }
@@ -1943,7 +1939,42 @@ static void kdf_test_cleanup(EVP_TEST *t)
 {
     KDF_DATA *kdata = t->data;
     OPENSSL_free(kdata->output);
-    EVP_PKEY_CTX_free(kdata->ctx);
+    EVP_KDF_CTX_free(kdata->ctx);
+}
+
+static int kdf_test_ctrl(EVP_TEST *t, EVP_KDF_CTX *kctx,
+                         const char *value)
+{
+    int rv;
+    char *p, *tmpval;
+
+    if (!TEST_ptr(tmpval = OPENSSL_strdup(value)))
+        return 0;
+    p = strchr(tmpval, ':');
+    if (p != NULL)
+        *p++ = '\0';
+    rv = EVP_KDF_ctrl_str(kctx, tmpval, p);
+    if (rv == -2) {
+        t->err = "KDF_CTRL_INVALID";
+        rv = 1;
+    } else if (p != NULL && rv <= 0) {
+        /* If p has an OID and lookup fails assume disabled algorithm */
+        int nid = OBJ_sn2nid(p);
+
+        if (nid == NID_undef)
+             nid = OBJ_ln2nid(p);
+        if (nid != NID_undef
+                && EVP_get_digestbynid(nid) == NULL
+                && EVP_get_cipherbynid(nid) == NULL) {
+            t->skip = 1;
+            rv = 1;
+        } else {
+            t->err = "KDF_CTRL_ERROR";
+            rv = 1;
+        }
+    }
+    OPENSSL_free(tmpval);
+    return rv > 0;
 }
 
 static int kdf_test_parse(EVP_TEST *t,
@@ -1954,7 +1985,7 @@ static int kdf_test_parse(EVP_TEST *t,
     if (strcmp(keyword, "Output") == 0)
         return parse_bin(value, &kdata->output, &kdata->output_len);
     if (strncmp(keyword, "Ctrl", 4) == 0)
-        return pkey_test_ctrl(t, kdata->ctx, value);
+        return kdf_test_ctrl(t, kdata->ctx, value);
     return 0;
 }
 
@@ -1968,7 +1999,7 @@ static int kdf_test_run(EVP_TEST *t)
         t->err = "INTERNAL_ERROR";
         goto err;
     }
-    if (EVP_PKEY_derive(expected->ctx, got, &got_len) <= 0) {
+    if (EVP_KDF_derive(expected->ctx, got, got_len) <= 0) {
         t->err = "KDF_DERIVE_ERROR";
         goto err;
     }
@@ -1994,6 +2025,106 @@ static const EVP_TEST_METHOD kdf_test_method = {
 
 
 /**
+***  PKEY KDF TESTS
+**/
+
+typedef struct pkey_kdf_data_st {
+    /* Context for this operation */
+    EVP_PKEY_CTX *ctx;
+    /* Expected output */
+    unsigned char *output;
+    size_t output_len;
+} PKEY_KDF_DATA;
+
+/*
+ * Perform public key operation setup: lookup key, allocated ctx and call
+ * the appropriate initialisation function
+ */
+static int pkey_kdf_test_init(EVP_TEST *t, const char *name)
+{
+    PKEY_KDF_DATA *kdata;
+    int kdf_nid = OBJ_sn2nid(name);
+
+#ifdef OPENSSL_NO_SCRYPT
+    if (strcmp(name, "scrypt") == 0) {
+        t->skip = 1;
+        return 1;
+    }
+#endif
+
+    if (kdf_nid == NID_undef)
+        kdf_nid = OBJ_ln2nid(name);
+
+    if (!TEST_ptr(kdata = OPENSSL_zalloc(sizeof(*kdata))))
+        return 0;
+    kdata->ctx = EVP_PKEY_CTX_new_id(kdf_nid, NULL);
+    if (kdata->ctx == NULL) {
+        OPENSSL_free(kdata);
+        return 0;
+    }
+    if (EVP_PKEY_derive_init(kdata->ctx) <= 0) {
+        EVP_PKEY_CTX_free(kdata->ctx);
+        OPENSSL_free(kdata);
+        return 0;
+    }
+    t->data = kdata;
+    return 1;
+}
+
+static void pkey_kdf_test_cleanup(EVP_TEST *t)
+{
+    PKEY_KDF_DATA *kdata = t->data;
+    OPENSSL_free(kdata->output);
+    EVP_PKEY_CTX_free(kdata->ctx);
+}
+
+static int pkey_kdf_test_parse(EVP_TEST *t,
+                               const char *keyword, const char *value)
+{
+    PKEY_KDF_DATA *kdata = t->data;
+
+    if (strcmp(keyword, "Output") == 0)
+        return parse_bin(value, &kdata->output, &kdata->output_len);
+    if (strncmp(keyword, "Ctrl", 4) == 0)
+        return pkey_test_ctrl(t, kdata->ctx, value);
+    return 0;
+}
+
+static int pkey_kdf_test_run(EVP_TEST *t)
+{
+    PKEY_KDF_DATA *expected = t->data;
+    unsigned char *got = NULL;
+    size_t got_len = expected->output_len;
+
+    if (!TEST_ptr(got = OPENSSL_malloc(got_len))) {
+        t->err = "INTERNAL_ERROR";
+        goto err;
+    }
+    if (EVP_PKEY_derive(expected->ctx, got, &got_len) <= 0) {
+        t->err = "KDF_DERIVE_ERROR";
+        goto err;
+    }
+    if (!TEST_mem_eq(expected->output, expected->output_len, got, got_len)) {
+        t->err = "KDF_MISMATCH";
+        goto err;
+    }
+    t->err = NULL;
+
+ err:
+    OPENSSL_free(got);
+    return 1;
+}
+
+static const EVP_TEST_METHOD pkey_kdf_test_method = {
+    "PKEYKDF",
+    pkey_kdf_test_init,
+    pkey_kdf_test_cleanup,
+    pkey_kdf_test_parse,
+    pkey_kdf_test_run
+};
+
+
+/**
 ***  KEYPAIR TESTS
 **/
 
@@ -2497,6 +2628,7 @@ static const EVP_TEST_METHOD *evp_test_list[] = {
     &digestverify_test_method,
     &encode_test_method,
     &kdf_test_method,
+    &pkey_kdf_test_method,
     &keypair_test_method,
     &keygen_test_method,
     &mac_test_method,
diff --git a/test/pkey_meth_kdf_test.c b/test/pkey_meth_kdf_test.c
index ad75425..cdc3d9f 100644
--- a/test/pkey_meth_kdf_test.c
+++ b/test/pkey_meth_kdf_test.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2017-2019 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -18,30 +18,34 @@
 
 static int test_kdf_tls1_prf(void)
 {
+    int ret = 0;
     EVP_PKEY_CTX *pctx;
     unsigned char out[16];
     size_t outlen = sizeof(out);
-    pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_TLS1_PRF, NULL);
 
+    if ((pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_TLS1_PRF, NULL)) == NULL) {
+        TEST_error("EVP_PKEY_TLS1_PRF");
+        goto err;
+    }
     if (EVP_PKEY_derive_init(pctx) <= 0) {
         TEST_error("EVP_PKEY_derive_init");
-        return 0;
+        goto err;
     }
     if (EVP_PKEY_CTX_set_tls1_prf_md(pctx, EVP_sha256()) <= 0) {
         TEST_error("EVP_PKEY_CTX_set_tls1_prf_md");
-        return 0;
+        goto err;
     }
     if (EVP_PKEY_CTX_set1_tls1_prf_secret(pctx, "secret", 6) <= 0) {
         TEST_error("EVP_PKEY_CTX_set1_tls1_prf_secret");
-        return 0;
+        goto err;
     }
     if (EVP_PKEY_CTX_add1_tls1_prf_seed(pctx, "seed", 4) <= 0) {
         TEST_error("EVP_PKEY_CTX_add1_tls1_prf_seed");
-        return 0;
+        goto err;
     }
     if (EVP_PKEY_derive(pctx, out, &outlen) <= 0) {
         TEST_error("EVP_PKEY_derive");
-        return 0;
+        goto err;
     }
 
     {
@@ -50,43 +54,49 @@ static int test_kdf_tls1_prf(void)
             0xaa, 0xe9, 0x74, 0xc3, 0x04, 0x73, 0x5e, 0xcc
         };
         if (!TEST_mem_eq(out, sizeof(out), expected, sizeof(expected))) {
-            return 0;
+            goto err;
         }
     }
+    ret = 1;
+err:
     EVP_PKEY_CTX_free(pctx);
-    return 1;
+    return ret;
 }
 
 static int test_kdf_hkdf(void)
 {
+    int ret = 0;
     EVP_PKEY_CTX *pctx;
     unsigned char out[10];
     size_t outlen = sizeof(out);
-    pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_HKDF, NULL);
 
+    if ((pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_HKDF, NULL)) == NULL) {
+        TEST_error("EVP_PKEY_HKDF");
+        goto err;
+    }
     if (EVP_PKEY_derive_init(pctx) <= 0) {
         TEST_error("EVP_PKEY_derive_init");
-        return 0;
+        goto err;
     }
     if (EVP_PKEY_CTX_set_hkdf_md(pctx, EVP_sha256()) <= 0) {
         TEST_error("EVP_PKEY_CTX_set_hkdf_md");
-        return 0;
+        goto err;
     }
     if (EVP_PKEY_CTX_set1_hkdf_salt(pctx, "salt", 4) <= 0) {
         TEST_error("EVP_PKEY_CTX_set1_hkdf_salt");
-        return 0;
+        goto err;
     }
     if (EVP_PKEY_CTX_set1_hkdf_key(pctx, "secret", 6) <= 0) {
         TEST_error("EVP_PKEY_CTX_set1_hkdf_key");
-        return 0;
+        goto err;
     }
     if (EVP_PKEY_CTX_add1_hkdf_info(pctx, "label", 5) <= 0) {
         TEST_error("EVP_PKEY_CTX_set1_hkdf_info");
-        return 0;
+        goto err;
     }
     if (EVP_PKEY_derive(pctx, out, &outlen) <= 0) {
         TEST_error("EVP_PKEY_derive");
-        return 0;
+        goto err;
     }
 
     {
@@ -94,60 +104,66 @@ static int test_kdf_hkdf(void)
             0x2a, 0xc4, 0x36, 0x9f, 0x52, 0x59, 0x96, 0xf8, 0xde, 0x13
         };
         if (!TEST_mem_eq(out, sizeof(out), expected, sizeof(expected))) {
-            return 0;
+            goto err;
         }
     }
+    ret = 1;
+err:
     EVP_PKEY_CTX_free(pctx);
-    return 1;
+    return ret;
 }
 
 #ifndef OPENSSL_NO_SCRYPT
 static int test_kdf_scrypt(void)
 {
+    int ret = 0;
     EVP_PKEY_CTX *pctx;
     unsigned char out[64];
     size_t outlen = sizeof(out);
-    pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_SCRYPT, NULL);
 
+    if ((pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_SCRYPT, NULL)) == NULL) {
+        TEST_error("EVP_PKEY_SCRYPT");
+        goto err;
+    }
     if (EVP_PKEY_derive_init(pctx) <= 0) {
         TEST_error("EVP_PKEY_derive_init");
-        return 0;
+        goto err;
     }
     if (EVP_PKEY_CTX_set1_pbe_pass(pctx, "password", 8) <= 0) {
         TEST_error("EVP_PKEY_CTX_set1_pbe_pass");
-        return 0;
+        goto err;
     }
     if (EVP_PKEY_CTX_set1_scrypt_salt(pctx, "NaCl", 4) <= 0) {
         TEST_error("EVP_PKEY_CTX_set1_scrypt_salt");
-        return 0;
+        goto err;
     }
     if (EVP_PKEY_CTX_set_scrypt_N(pctx, 1024) <= 0) {
         TEST_error("EVP_PKEY_CTX_set_scrypt_N");
-        return 0;
+        goto err;
     }
     if (EVP_PKEY_CTX_set_scrypt_r(pctx, 8) <= 0) {
         TEST_error("EVP_PKEY_CTX_set_scrypt_r");
-        return 0;
+        goto err;
     }
     if (EVP_PKEY_CTX_set_scrypt_p(pctx, 16) <= 0) {
         TEST_error("EVP_PKEY_CTX_set_scrypt_p");
-        return 0;
+        goto err;
     }
     if (EVP_PKEY_CTX_set_scrypt_maxmem_bytes(pctx, 16) <= 0) {
         TEST_error("EVP_PKEY_CTX_set_maxmem_bytes");
-        return 0;
+        goto err;
     }
     if (EVP_PKEY_derive(pctx, out, &outlen) > 0) {
         TEST_error("EVP_PKEY_derive should have failed");
-        return 0;
+        goto err;
     }
     if (EVP_PKEY_CTX_set_scrypt_maxmem_bytes(pctx, 10 * 1024 * 1024) <= 0) {
         TEST_error("EVP_PKEY_CTX_set_maxmem_bytes");
-        return 0;
+        goto err;
     }
     if (EVP_PKEY_derive(pctx, out, &outlen) <= 0) {
         TEST_error("EVP_PKEY_derive");
-        return 0;
+        goto err;
     }
 
     {
@@ -162,11 +178,13 @@ static int test_kdf_scrypt(void)
             0x83, 0x60, 0xcb, 0xdf, 0xa2, 0xcc, 0x06, 0x40
         };
         if (!TEST_mem_eq(out, sizeof(out), expected, sizeof(expected))) {
-            return 0;
+            goto err;
         }
     }
+    ret = 1;
+err:
     EVP_PKEY_CTX_free(pctx);
-    return 1;
+    return ret;
 }
 #endif
 
diff --git a/test/recipes/30-test_evp.t b/test/recipes/30-test_evp.t
index c2079bd..24aa3a3 100644
--- a/test/recipes/30-test_evp.t
+++ b/test/recipes/30-test_evp.t
@@ -15,8 +15,8 @@ use OpenSSL::Test qw/:DEFAULT data_file/;
 setup("test_evp");
 
 my @files = ( "evpciph.txt", "evpdigest.txt", "evpencod.txt", "evpkdf.txt",
-    "evpmac.txt", "evppbe.txt", "evppkey.txt", "evppkey_ecc.txt",
-    "evpcase.txt", "evpaessiv.txt" );
+    "evppkey_kdf.txt", "evpmac.txt", "evppbe.txt", "evppkey.txt",
+    "evppkey_ecc.txt", "evpcase.txt", "evpaessiv.txt" );
 
 plan tests => scalar(@files);
 
diff --git a/test/recipes/30-test_evp_data/evpkdf.txt b/test/recipes/30-test_evp_data/evpkdf.txt
index 16f439f..6e34d38 100644
--- a/test/recipes/30-test_evp_data/evpkdf.txt
+++ b/test/recipes/30-test_evp_data/evpkdf.txt
@@ -1,5 +1,5 @@
 #
-# Copyright 2001-2017 The OpenSSL Project Authors. All Rights Reserved.
+# Copyright 2001-2018 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
@@ -15,7 +15,7 @@
 Title = TLS1 PRF tests (from NIST test vectors)
 
 KDF=TLS1-PRF
-Ctrl.md = md:MD5-SHA1
+Ctrl.digest = digest:MD5-SHA1
 Ctrl.Secret = hexsecret:bded7fa5c1699c010be23dd06ada3a48349f21e5f86263d512c0c5cc379f0e780ec55d9844b2f1db02a96453513568d0
 Ctrl.label = seed:master secret
 Ctrl.client_random = hexseed:e5acaf549cd25c22d964c0d930fa4b5261d2507fad84c33715b7b9a864020693
@@ -23,7 +23,7 @@ Ctrl.server_random = hexseed:135e4d557fdf3aa6406d82975d5c606a9734c9334b42136e969
 Output = 2f6962dfbc744c4b2138bb6b3d33054c5ecc14f24851d9896395a44ab3964efc2090c5bf51a0891209f46c1e1e998f62
 
 KDF=TLS1-PRF
-Ctrl.md = md:MD5-SHA1
+Ctrl.digest = digest:MD5-SHA1
 Ctrl.Secret = hexsecret:2f6962dfbc744c4b2138bb6b3d33054c5ecc14f24851d9896395a44ab3964efc2090c5bf51a0891209f46c1e1e998f62
 Ctrl.label = seed:key expansion
 Ctrl.server_random = hexseed:67267e650eb32444119d222a368c191af3082888dc35afe8368e638c828874be
@@ -31,7 +31,7 @@ Ctrl.client_random = hexseed:d58a7b1cd4fedaa232159df652ce188f9d997e061b9bf48e83b
 Output = 3088825988e77fce68d19f756e18e43eb7fe672433504feaf99b3c503d9091b164f166db301d70c9fc0870b4a94563907bee1a61fb786cb717576890bcc51cb9ead97e01d0a2fea99c953377b195205ff07b369589178796edc963fd80fdbe518a2fc1c35c18ae8d
 
 KDF=TLS1-PRF
-Ctrl.md = md:SHA256
+Ctrl.digest = digest:SHA256
 Ctrl.Secret = hexsecret:f8938ecc9edebc5030c0c6a441e213cd24e6f770a50dda07876f8d55da062bcadb386b411fd4fe4313a604fce6c17fbc
 Ctrl.label = seed:master secret
 Ctrl.client_random = hexseed:36c129d01a3200894b9179faac589d9835d58775f9b5ea3587cb8fd0364cae8c
@@ -39,7 +39,7 @@ Ctrl.server_random = hexseed:f6c9575ed7ddd73e1f7d16eca115415812a43c2b747daaaae04
 Output = 202c88c00f84a17a20027079604787461176455539e705be730890602c289a5001e34eeb3a043e5d52a65e66125188bf
 
 KDF=TLS1-PRF
-Ctrl.md = md:SHA256
+Ctrl.digest = digest:SHA256
 Ctrl.Secret = hexsecret:202c88c00f84a17a20027079604787461176455539e705be730890602c289a5001e34eeb3a043e5d52a65e66125188bf
 Ctrl.label = seed:key expansion
 Ctrl.server_random = hexseed:ae6c806f8ad4d80784549dff28a4b58fd837681a51d928c3e30ee5ff14f39868
@@ -48,7 +48,7 @@ Output = d06139889fffac1e3a71865f504aa5d0d2a2e89506c6f2279b670c3e1b74f531016a253
 
 # As above but use long name for KDF
 KDF=tls1-prf
-Ctrl.md = md:SHA256
+Ctrl.digest = digest:SHA256
 Ctrl.Secret = hexsecret:202c88c00f84a17a20027079604787461176455539e705be730890602c289a5001e34eeb3a043e5d52a65e66125188bf
 Ctrl.label = seed:key expansion
 Ctrl.server_random = hexseed:ae6c806f8ad4d80784549dff28a4b58fd837681a51d928c3e30ee5ff14f39868
@@ -64,7 +64,7 @@ Result = KDF_DERIVE_ERROR
 
 # Missing secret.
 KDF=TLS1-PRF
-Ctrl.md = md:MD5-SHA1
+Ctrl.digest = digest:MD5-SHA1
 Ctrl.Seed = hexseed:02
 Output = 03
 Result = KDF_DERIVE_ERROR
@@ -72,7 +72,7 @@ Result = KDF_DERIVE_ERROR
 Title = HKDF tests (from RFC5869 test vectors)
 
 KDF = HKDF
-Ctrl.md = md:SHA256
+Ctrl.digest = digest:SHA256
 Ctrl.IKM = hexkey:0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b
 Ctrl.salt = hexsalt:000102030405060708090a0b0c
 Ctrl.info = hexinfo:f0f1f2f3f4f5f6f7f8f9
@@ -80,20 +80,20 @@ Output = 3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf3400720
 
 KDF = HKDF
 Ctrl.mode = mode:EXTRACT_ONLY
-Ctrl.md = md:SHA256
+Ctrl.digest = digest:SHA256
 Ctrl.IKM = hexkey:0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b
 Ctrl.salt = hexsalt:000102030405060708090a0b0c
 Output = 077709362c2e32df0ddc3f0dc47bba6390b6c73bb50f9c3122ec844ad7c2b3e5
 
 KDF = HKDF
 Ctrl.mode = mode:EXPAND_ONLY
-Ctrl.md = md:SHA256
+Ctrl.digest = digest:SHA256
 Ctrl.IKM = hexkey:077709362c2e32df0ddc3f0dc47bba6390b6c73bb50f9c3122ec844ad7c2b3e5
 Ctrl.info = hexinfo:f0f1f2f3f4f5f6f7f8f9
 Output = 3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865
 
 KDF = HKDF
-Ctrl.md = md:SHA256
+Ctrl.digest = digest:SHA256
 Ctrl.IKM = hexkey:000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f
 Ctrl.salt = hexsalt:606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeaf
 Ctrl.info = hexinfo:b0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff
@@ -101,20 +101,20 @@ Output = b11e398dc80327a1c8e7f78c596a49344f012eda2d4efad8a050cc4c19afa97c59045a9
 
 KDF = HKDF
 Ctrl.mode = mode:EXTRACT_ONLY
-Ctrl.md = md:SHA256
+Ctrl.digest = digest:SHA256
 Ctrl.IKM = hexkey:000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f
 Ctrl.salt = hexsalt:606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeaf
 Output = 06a6b88c5853361a06104c9ceb35b45cef760014904671014a193f40c15fc244
 
 KDF = HKDF
 Ctrl.mode = mode:EXPAND_ONLY
-Ctrl.md = md:SHA256
+Ctrl.digest = digest:SHA256
 Ctrl.IKM = hexkey:06a6b88c5853361a06104c9ceb35b45cef760014904671014a193f40c15fc244
 Ctrl.info = hexinfo:b0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff
 Output = b11e398dc80327a1c8e7f78c596a49344f012eda2d4efad8a050cc4c19afa97c59045a99cac7827271cb41c65e590e09da3275600c2f09b8367793a9aca3db71cc30c58179ec3e87c14c01d5c1f3434f1d87
 
 KDF = HKDF
-Ctrl.md = md:SHA256
+Ctrl.digest = digest:SHA256
 Ctrl.IKM = hexkey:0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b
 Ctrl.salt = salt:
 Ctrl.info = info:
@@ -122,7 +122,7 @@ Output = 8da4e775a563c18f715f802a063c5a31b8a11f5c5ee1879ec3454e5f3c738d2d9d20139
 
 KDF = HKDF
 Ctrl.mode = mode:EXTRACT_ONLY
-Ctrl.md = md:SHA256
+Ctrl.digest = digest:SHA256
 Ctrl.IKM = hexkey:0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b
 Ctrl.salt = salt:
 Ctrl.info = info:
@@ -130,13 +130,13 @@ Output = 19ef24a32c717b167f33a91d6f648bdf96596776afdb6377ac434c1c293ccb04
 
 KDF = HKDF
 Ctrl.mode = mode:EXPAND_ONLY
-Ctrl.md = md:SHA256
+Ctrl.digest = digest:SHA256
 Ctrl.IKM = hexkey:19ef24a32c717b167f33a91d6f648bdf96596776afdb6377ac434c1c293ccb04
 Ctrl.info = info:
 Output = 8da4e775a563c18f715f802a063c5a31b8a11f5c5ee1879ec3454e5f3c738d2d9d201395faa4b61a96c8
 
 KDF = HKDF
-Ctrl.md = md:SHA1
+Ctrl.digest = digest:SHA1
 Ctrl.IKM = hexkey:0b0b0b0b0b0b0b0b0b0b0b
 Ctrl.salt = hexsalt:000102030405060708090a0b0c
 Ctrl.info = hexinfo:f0f1f2f3f4f5f6f7f8f9
@@ -144,20 +144,20 @@ Output = 085a01ea1b10f36933068b56efa5ad81a4f14b822f5b091568a9cdd4f155fda2c22e422
 
 KDF = HKDF
 Ctrl.mode = mode:EXTRACT_ONLY
-Ctrl.md = md:SHA1
+Ctrl.digest = digest:SHA1
 Ctrl.IKM = hexkey:0b0b0b0b0b0b0b0b0b0b0b
 Ctrl.salt = hexsalt:000102030405060708090a0b0c
 Output = 9b6c18c432a7bf8f0e71c8eb88f4b30baa2ba243
 
 KDF = HKDF
 Ctrl.mode = mode:EXPAND_ONLY
-Ctrl.md = md:SHA1
+Ctrl.digest = digest:SHA1
 Ctrl.IKM = hexkey:9b6c18c432a7bf8f0e71c8eb88f4b30baa2ba243
 Ctrl.info = hexinfo:f0f1f2f3f4f5f6f7f8f9
 Output = 085a01ea1b10f36933068b56efa5ad81a4f14b822f5b091568a9cdd4f155fda2c22e422478d305f3f896
 
 KDF = HKDF
-Ctrl.md = md:SHA1
+Ctrl.digest = digest:SHA1
 Ctrl.IKM = hexkey:000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f
 Ctrl.salt = hexsalt:606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeaf
 Ctrl.info = hexinfo:b0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff
@@ -165,20 +165,20 @@ Output = 0bd770a74d1160f7c9f12cd5912a06ebff6adcae899d92191fe4305673ba2ffe8fa3f1a
 
 KDF = HKDF
 Ctrl.mode = mode:EXTRACT_ONLY
-Ctrl.md = md:SHA1
+Ctrl.digest = digest:SHA1
 Ctrl.IKM = hexkey:000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f
 Ctrl.salt = hexsalt:606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeaf
 Output = 8adae09a2a307059478d309b26c4115a224cfaf6
 
 KDF = HKDF
 Ctrl.mode = mode:EXPAND_ONLY
-Ctrl.md = md:SHA1
+Ctrl.digest = digest:SHA1
 Ctrl.IKM = hexkey:8adae09a2a307059478d309b26c4115a224cfaf6
 Ctrl.info = hexinfo:b0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff
 Output = 0bd770a74d1160f7c9f12cd5912a06ebff6adcae899d92191fe4305673ba2ffe8fa3f1a4e5ad79f3f334b3b202b2173c486ea37ce3d397ed034c7f9dfeb15c5e927336d0441f4c4300e2cff0d0900b52d3b4
 
 KDF = HKDF
-Ctrl.md = md:SHA1
+Ctrl.digest = digest:SHA1
 Ctrl.IKM = hexkey:0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b
 Ctrl.salt = salt:
 Ctrl.info = info:
@@ -186,20 +186,20 @@ Output = 0ac1af7002b3d761d1e55298da9d0506b9ae52057220a306e07b6b87e8df21d0ea00033
 
 KDF = HKDF
 Ctrl.mode = mode:EXTRACT_ONLY
-Ctrl.md = md:SHA1
+Ctrl.digest = digest:SHA1
 Ctrl.IKM = hexkey:0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b
 Ctrl.salt = salt:
 Output = da8c8a73c7fa77288ec6f5e7c297786aa0d32d01
 
 KDF = HKDF
 Ctrl.mode = mode:EXPAND_ONLY
-Ctrl.md = md:SHA1
+Ctrl.digest = digest:SHA1
 Ctrl.IKM = hexkey:da8c8a73c7fa77288ec6f5e7c297786aa0d32d01
 Ctrl.info = info:
 Output = 0ac1af7002b3d761d1e55298da9d0506b9ae52057220a306e07b6b87e8df21d0ea00033de03984d34918
 
 KDF = HKDF
-Ctrl.md = md:SHA1
+Ctrl.digest = digest:SHA1
 Ctrl.IKM = hexkey:0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c
 Ctrl.salt = salt:
 Ctrl.info = info:
@@ -207,14 +207,14 @@ Output = 2c91117204d745f3500d636a62f64f0ab3bae548aa53d423b0d1f27ebba6f5e5673a081
 
 KDF = HKDF
 Ctrl.mode = mode:EXTRACT_ONLY
-Ctrl.md = md:SHA1
+Ctrl.digest = digest:SHA1
 Ctrl.IKM = hexkey:0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c
 Ctrl.salt = salt:
 Output = 2adccada18779e7c2077ad2eb19d3f3e731385dd
 
 KDF = HKDF
 Ctrl.mode = mode:EXPAND_ONLY
-Ctrl.md = md:SHA1
+Ctrl.digest = digest:SHA1
 Ctrl.IKM = hexkey:2adccada18779e7c2077ad2eb19d3f3e731385dd
 Ctrl.info = info:
 Output = 2c91117204d745f3500d636a62f64f0ab3bae548aa53d423b0d1f27ebba6f5e5673a081d70cce7acfc48
@@ -227,27 +227,27 @@ Output = 00
 Result = KDF_DERIVE_ERROR
 
 KDF = HKDF
-Ctrl.md = md:SHA1
+Ctrl.digest = digest:SHA1
 Ctrl.salt = salt:
 Ctrl.info = info:
 Output = 00
 Result = KDF_DERIVE_ERROR
 
 KDF = HKDF
-Ctrl.md = md:SHA1
+Ctrl.digest = digest:SHA1
 Ctrl.IKM = hexkey:0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c
 Ctrl.info = info:
 Output = 2c91117204d745f3500d636a62f64f0ab3bae548aa53d423b0d1f27ebba6f5e5673a081d70cce7acfc48
 
 KDF = HKDF
-Ctrl.md = md:SHA1
+Ctrl.digest = digest:SHA1
 Ctrl.IKM = hexkey:0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c
 Ctrl.salt = salt:
 Output = 2c91117204d745f3500d636a62f64f0ab3bae548aa53d423b0d1f27ebba6f5e5673a081d70cce7acfc48
 
 KDF = HKDF
 Ctrl.mode = mode:EXTRACT_AND_EXPAND
-Ctrl.md = md:SHA1
+Ctrl.digest = digest:SHA1
 Ctrl.IKM = hexkey:0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c
 Ctrl.salt = salt:
 Output = 2c91117204d745f3500d636a62f64f0ab3bae548aa53d423b0d1f27ebba6f5e5673a081d70cce7acfc48
@@ -303,3 +303,133 @@ Ctrl.r = r:8
 Ctrl.p = p:1
 Result = INTERNAL_ERROR
 
+Title = PBKDF2 tests
+
+KDF = PBKDF2
+Ctrl.pass = pass:password
+Ctrl.salt = salt:salt
+Ctrl.iter = iter:1
+Ctrl.digest = digest:sha1
+Output = 0c60c80f961f0e71f3a9b524af6012062fe037a6
+
+KDF = PBKDF2
+Ctrl.pass = pass:password
+Ctrl.salt = salt:salt
+Ctrl.iter = iter:1
+Ctrl.digest = digest:sha256
+Output = 120fb6cffcf8b32c43e7225256c4f837a86548c92ccc35480805987cb70be17b
+
+KDF = PBKDF2
+Ctrl.pass = pass:password
+Ctrl.salt = salt:salt
+Ctrl.iter = iter:1
+Ctrl.digest = digest:sha512
+Output = 867f70cf1ade02cff3752599a3a53dc4af34c7a669815ae5d513554e1c8cf252c02d470a285a0501bad999bfe943c08f050235d7d68b1da55e63f73b60a57fce
+
+KDF = PBKDF2
+Ctrl.pass = pass:password
+Ctrl.salt = salt:salt
+Ctrl.iter = iter:2
+Ctrl.digest = digest:sha1
+Output = ea6c014dc72d6f8ccd1ed92ace1d41f0d8de8957
+
+KDF = PBKDF2
+Ctrl.pass = pass:password
+Ctrl.salt = salt:salt
+Ctrl.iter = iter:2
+Ctrl.digest = digest:sha256
+Output = ae4d0c95af6b46d32d0adff928f06dd02a303f8ef3c251dfd6e2d85a95474c43
+
+KDF = PBKDF2
+Ctrl.pass = pass:password
+Ctrl.salt = salt:salt
+Ctrl.iter = iter:2
+Ctrl.digest = digest:sha512
+Output = e1d9c16aa681708a45f5c7c4e215ceb66e011a2e9f0040713f18aefdb866d53cf76cab2868a39b9f7840edce4fef5a82be67335c77a6068e04112754f27ccf4e
+
+KDF = PBKDF2
+Ctrl.pass = pass:password
+Ctrl.salt = salt:salt
+Ctrl.iter = iter:4096
+Ctrl.digest = digest:sha1
+Output = 4b007901b765489abead49d926f721d065a429c1
+
+KDF = PBKDF2
+Ctrl.pass = pass:password
+Ctrl.salt = salt:salt
+Ctrl.iter = iter:4096
+Ctrl.digest = digest:sha256
+Output = c5e478d59288c841aa530db6845c4c8d962893a001ce4e11a4963873aa98134a
+
+KDF = PBKDF2
+Ctrl.pass = pass:password
+Ctrl.salt = salt:salt
+Ctrl.iter = iter:4096
+Ctrl.digest = digest:sha512
+Output = d197b1b33db0143e018b12f3d1d1479e6cdebdcc97c5c0f87f6902e072f457b5143f30602641b3d55cd335988cb36b84376060ecd532e039b742a239434af2d5
+
+KDF = PBKDF2
+Ctrl.pass = pass:passwordPASSWORDpassword
+Ctrl.salt = salt:saltSALTsaltSALTsaltSALTsaltSALTsalt
+Ctrl.iter = iter:4096
+Ctrl.digest = digest:sha1
+Output = 3d2eec4fe41c849b80c8d83662c0e44a8b291a964cf2f07038
+
+KDF = PBKDF2
+Ctrl.pass = pass:passwordPASSWORDpassword
+Ctrl.salt = salt:saltSALTsaltSALTsaltSALTsaltSALTsalt
+Ctrl.iter = iter:4096
+Ctrl.digest = digest:sha256
+Output = 348c89dbcbd32b2f32d814b8116e84cf2b17347ebc1800181c4e2a1fb8dd53e1c635518c7dac47e9
+
+KDF = PBKDF2
+Ctrl.pass = pass:passwordPASSWORDpassword
+Ctrl.salt = salt:saltSALTsaltSALTsaltSALTsaltSALTsalt
+Ctrl.iter = iter:4096
+Ctrl.digest = digest:sha512
+Output = 8c0511f4c6e597c6ac6315d8f0362e225f3c501495ba23b868c005174dc4ee71115b59f9e60cd9532fa33e0f75aefe30225c583a186cd82bd4daea9724a3d3b8
+
+KDF = PBKDF2
+Ctrl.hexpass = hexpass:7061737300776f7264
+Ctrl.hexsalt = hexsalt:7361006c74
+Ctrl.iter = iter:4096
+Ctrl.digest = digest:sha1
+Output = 56fa6aa75548099dcc37d7f03425e0c3
+
+KDF = PBKDF2
+Ctrl.hexpass = hexpass:7061737300776f7264
+Ctrl.hexsalt = hexsalt:7361006c74
+Ctrl.iter = iter:4096
+Ctrl.digest = digest:sha256
+Output = 89b69d0516f829893c696226650a8687
+
+KDF = PBKDF2
+Ctrl.hexpass = hexpass:7061737300776f7264
+Ctrl.hexsalt = hexsalt:7361006c74
+Ctrl.iter = iter:4096
+Ctrl.digest = digest:sha512
+Output = 9d9e9c4cd21fe4be24d5b8244c759665
+
+Title = PBKDF2 tests for empty inputs
+
+KDF = PBKDF2
+Ctrl.pass = pass:
+Ctrl.salt = salt:salt
+Ctrl.iter = iter:1
+Ctrl.digest = digest:sha1
+Output = a33dddc30478185515311f8752895d36ea4363a2
+
+KDF = PBKDF2
+Ctrl.pass = pass:
+Ctrl.salt = salt:salt
+Ctrl.iter = iter:1
+Ctrl.digest = digest:sha256
+Output = f135c27993baf98773c5cdb40a5706ce6a345cde
+
+KDF = PBKDF2
+Ctrl.pass = pass:
+Ctrl.salt = salt:salt
+Ctrl.iter = iter:1
+Ctrl.digest = digest:sha512
+Output = 00ef42cdbfc98d29db20976608e455567fdddf14
+
diff --git a/test/recipes/30-test_evp_data/evpkdf.txt b/test/recipes/30-test_evp_data/evppkey_kdf.txt
similarity index 94%
copy from test/recipes/30-test_evp_data/evpkdf.txt
copy to test/recipes/30-test_evp_data/evppkey_kdf.txt
index 16f439f..c619efd 100644
--- a/test/recipes/30-test_evp_data/evpkdf.txt
+++ b/test/recipes/30-test_evp_data/evppkey_kdf.txt
@@ -1,5 +1,5 @@
 #
-# Copyright 2001-2017 The OpenSSL Project Authors. All Rights Reserved.
+# Copyright 2001-2018 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
@@ -7,14 +7,14 @@
 # https://www.openssl.org/source/license.html
 
 # Tests start with one of these keywords
-#       Cipher Decrypt Derive Digest Encoding KDF MAC PBE
+#       Cipher Decrypt Derive Digest Encoding KDF PKEYKDF MAC PBE
 #       PrivPubKeyPair Sign Verify VerifyRecover
 # and continue until a blank line.  Lines starting with a pound sign,
 # like this prolog, are ignored.
 
 Title = TLS1 PRF tests (from NIST test vectors)
 
-KDF=TLS1-PRF
+PKEYKDF=TLS1-PRF
 Ctrl.md = md:MD5-SHA1
 Ctrl.Secret = hexsecret:bded7fa5c1699c010be23dd06ada3a48349f21e5f86263d512c0c5cc379f0e780ec55d9844b2f1db02a96453513568d0
 Ctrl.label = seed:master secret
@@ -22,7 +22,7 @@ Ctrl.client_random = hexseed:e5acaf549cd25c22d964c0d930fa4b5261d2507fad84c33715b
 Ctrl.server_random = hexseed:135e4d557fdf3aa6406d82975d5c606a9734c9334b42136e96990fbd5358cdb2
 Output = 2f6962dfbc744c4b2138bb6b3d33054c5ecc14f24851d9896395a44ab3964efc2090c5bf51a0891209f46c1e1e998f62
 
-KDF=TLS1-PRF
+PKEYKDF=TLS1-PRF
 Ctrl.md = md:MD5-SHA1
 Ctrl.Secret = hexsecret:2f6962dfbc744c4b2138bb6b3d33054c5ecc14f24851d9896395a44ab3964efc2090c5bf51a0891209f46c1e1e998f62
 Ctrl.label = seed:key expansion
@@ -30,7 +30,7 @@ Ctrl.server_random = hexseed:67267e650eb32444119d222a368c191af3082888dc35afe8368
 Ctrl.client_random = hexseed:d58a7b1cd4fedaa232159df652ce188f9d997e061b9bf48e83b62990440931f6
 Output = 3088825988e77fce68d19f756e18e43eb7fe672433504feaf99b3c503d9091b164f166db301d70c9fc0870b4a94563907bee1a61fb786cb717576890bcc51cb9ead97e01d0a2fea99c953377b195205ff07b369589178796edc963fd80fdbe518a2fc1c35c18ae8d
 
-KDF=TLS1-PRF
+PKEYKDF=TLS1-PRF
 Ctrl.md = md:SHA256
 Ctrl.Secret = hexsecret:f8938ecc9edebc5030c0c6a441e213cd24e6f770a50dda07876f8d55da062bcadb386b411fd4fe4313a604fce6c17fbc
 Ctrl.label = seed:master secret
@@ -38,7 +38,7 @@ Ctrl.client_random = hexseed:36c129d01a3200894b9179faac589d9835d58775f9b5ea3587c
 Ctrl.server_random = hexseed:f6c9575ed7ddd73e1f7d16eca115415812a43c2b747daaaae043abfb50053fce
 Output = 202c88c00f84a17a20027079604787461176455539e705be730890602c289a5001e34eeb3a043e5d52a65e66125188bf
 
-KDF=TLS1-PRF
+PKEYKDF=TLS1-PRF
 Ctrl.md = md:SHA256
 Ctrl.Secret = hexsecret:202c88c00f84a17a20027079604787461176455539e705be730890602c289a5001e34eeb3a043e5d52a65e66125188bf
 Ctrl.label = seed:key expansion
@@ -47,7 +47,7 @@ Ctrl.client_random = hexseed:62e1fd91f23f558a605f28478c58cf72637b89784d959df7e94
 Output = d06139889fffac1e3a71865f504aa5d0d2a2e89506c6f2279b670c3e1b74f531016a2530c51a3a0f7e1d6590d0f0566b2f387f8d11fd4f731cdd572d2eae927f6f2f81410b25e6960be68985add6c38445ad9f8c64bf8068bf9a6679485d966f1ad6f68b43495b10a683755ea2b858d70ccac7ec8b053c6bd41ca299d4e51928
 
 # As above but use long name for KDF
-KDF=tls1-prf
+PKEYKDF=tls1-prf
 Ctrl.md = md:SHA256
 Ctrl.Secret = hexsecret:202c88c00f84a17a20027079604787461176455539e705be730890602c289a5001e34eeb3a043e5d52a65e66125188bf
 Ctrl.label = seed:key expansion
@@ -56,14 +56,14 @@ Ctrl.client_random = hexseed:62e1fd91f23f558a605f28478c58cf72637b89784d959df7e94
 Output = d06139889fffac1e3a71865f504aa5d0d2a2e89506c6f2279b670c3e1b74f531016a2530c51a3a0f7e1d6590d0f0566b2f387f8d11fd4f731cdd572d2eae927f6f2f81410b25e6960be68985add6c38445ad9f8c64bf8068bf9a6679485d966f1ad6f68b43495b10a683755ea2b858d70ccac7ec8b053c6bd41ca299d4e51928
 
 # Missing digest.
-KDF=TLS1-PRF
+PKEYKDF=TLS1-PRF
 Ctrl.Secret = hexsecret:01
 Ctrl.Seed = hexseed:02
 Output = 03
 Result = KDF_DERIVE_ERROR
 
 # Missing secret.
-KDF=TLS1-PRF
+PKEYKDF=TLS1-PRF
 Ctrl.md = md:MD5-SHA1
 Ctrl.Seed = hexseed:02
 Output = 03
@@ -71,56 +71,56 @@ Result = KDF_DERIVE_ERROR
 
 Title = HKDF tests (from RFC5869 test vectors)
 
-KDF = HKDF
+PKEYKDF = HKDF
 Ctrl.md = md:SHA256
 Ctrl.IKM = hexkey:0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b
 Ctrl.salt = hexsalt:000102030405060708090a0b0c
 Ctrl.info = hexinfo:f0f1f2f3f4f5f6f7f8f9
 Output = 3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865
 
-KDF = HKDF
+PKEYKDF = HKDF
 Ctrl.mode = mode:EXTRACT_ONLY
 Ctrl.md = md:SHA256
 Ctrl.IKM = hexkey:0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b
 Ctrl.salt = hexsalt:000102030405060708090a0b0c
 Output = 077709362c2e32df0ddc3f0dc47bba6390b6c73bb50f9c3122ec844ad7c2b3e5
 
-KDF = HKDF
+PKEYKDF = HKDF
 Ctrl.mode = mode:EXPAND_ONLY
 Ctrl.md = md:SHA256
 Ctrl.IKM = hexkey:077709362c2e32df0ddc3f0dc47bba6390b6c73bb50f9c3122ec844ad7c2b3e5
 Ctrl.info = hexinfo:f0f1f2f3f4f5f6f7f8f9
 Output = 3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865
 
-KDF = HKDF
+PKEYKDF = HKDF
 Ctrl.md = md:SHA256
 Ctrl.IKM = hexkey:000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f
 Ctrl.salt = hexsalt:606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeaf
 Ctrl.info = hexinfo:b0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff
 Output = b11e398dc80327a1c8e7f78c596a49344f012eda2d4efad8a050cc4c19afa97c59045a99cac7827271cb41c65e590e09da3275600c2f09b8367793a9aca3db71cc30c58179ec3e87c14c01d5c1f3434f1d87
 
-KDF = HKDF
+PKEYKDF = HKDF
 Ctrl.mode = mode:EXTRACT_ONLY
 Ctrl.md = md:SHA256
 Ctrl.IKM = hexkey:000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f
 Ctrl.salt = hexsalt:606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeaf
 Output = 06a6b88c5853361a06104c9ceb35b45cef760014904671014a193f40c15fc244
 
-KDF = HKDF
+PKEYKDF = HKDF
 Ctrl.mode = mode:EXPAND_ONLY
 Ctrl.md = md:SHA256
 Ctrl.IKM = hexkey:06a6b88c5853361a06104c9ceb35b45cef760014904671014a193f40c15fc244
 Ctrl.info = hexinfo:b0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff
 Output = b11e398dc80327a1c8e7f78c596a49344f012eda2d4efad8a050cc4c19afa97c59045a99cac7827271cb41c65e590e09da3275600c2f09b8367793a9aca3db71cc30c58179ec3e87c14c01d5c1f3434f1d87
 
-KDF = HKDF
+PKEYKDF = HKDF
 Ctrl.md = md:SHA256
 Ctrl.IKM = hexkey:0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b
 Ctrl.salt = salt:
 Ctrl.info = info:
 Output = 8da4e775a563c18f715f802a063c5a31b8a11f5c5ee1879ec3454e5f3c738d2d9d201395faa4b61a96c8
 
-KDF = HKDF
+PKEYKDF = HKDF
 Ctrl.mode = mode:EXTRACT_ONLY
 Ctrl.md = md:SHA256
 Ctrl.IKM = hexkey:0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b
@@ -128,124 +128,124 @@ Ctrl.salt = salt:
 Ctrl.info = info:
 Output = 19ef24a32c717b167f33a91d6f648bdf96596776afdb6377ac434c1c293ccb04
 
-KDF = HKDF
+PKEYKDF = HKDF
 Ctrl.mode = mode:EXPAND_ONLY
 Ctrl.md = md:SHA256
 Ctrl.IKM = hexkey:19ef24a32c717b167f33a91d6f648bdf96596776afdb6377ac434c1c293ccb04
 Ctrl.info = info:
 Output = 8da4e775a563c18f715f802a063c5a31b8a11f5c5ee1879ec3454e5f3c738d2d9d201395faa4b61a96c8
 
-KDF = HKDF
+PKEYKDF = HKDF
 Ctrl.md = md:SHA1
 Ctrl.IKM = hexkey:0b0b0b0b0b0b0b0b0b0b0b
 Ctrl.salt = hexsalt:000102030405060708090a0b0c
 Ctrl.info = hexinfo:f0f1f2f3f4f5f6f7f8f9
 Output = 085a01ea1b10f36933068b56efa5ad81a4f14b822f5b091568a9cdd4f155fda2c22e422478d305f3f896
 
-KDF = HKDF
+PKEYKDF = HKDF
 Ctrl.mode = mode:EXTRACT_ONLY
 Ctrl.md = md:SHA1
 Ctrl.IKM = hexkey:0b0b0b0b0b0b0b0b0b0b0b
 Ctrl.salt = hexsalt:000102030405060708090a0b0c
 Output = 9b6c18c432a7bf8f0e71c8eb88f4b30baa2ba243
 
-KDF = HKDF
+PKEYKDF = HKDF
 Ctrl.mode = mode:EXPAND_ONLY
 Ctrl.md = md:SHA1
 Ctrl.IKM = hexkey:9b6c18c432a7bf8f0e71c8eb88f4b30baa2ba243
 Ctrl.info = hexinfo:f0f1f2f3f4f5f6f7f8f9
 Output = 085a01ea1b10f36933068b56efa5ad81a4f14b822f5b091568a9cdd4f155fda2c22e422478d305f3f896
 
-KDF = HKDF
+PKEYKDF = HKDF
 Ctrl.md = md:SHA1
 Ctrl.IKM = hexkey:000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f
 Ctrl.salt = hexsalt:606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeaf
 Ctrl.info = hexinfo:b0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff
 Output = 0bd770a74d1160f7c9f12cd5912a06ebff6adcae899d92191fe4305673ba2ffe8fa3f1a4e5ad79f3f334b3b202b2173c486ea37ce3d397ed034c7f9dfeb15c5e927336d0441f4c4300e2cff0d0900b52d3b4
 
-KDF = HKDF
+PKEYKDF = HKDF
 Ctrl.mode = mode:EXTRACT_ONLY
 Ctrl.md = md:SHA1
 Ctrl.IKM = hexkey:000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f
 Ctrl.salt = hexsalt:606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeaf
 Output = 8adae09a2a307059478d309b26c4115a224cfaf6
 
-KDF = HKDF
+PKEYKDF = HKDF
 Ctrl.mode = mode:EXPAND_ONLY
 Ctrl.md = md:SHA1
 Ctrl.IKM = hexkey:8adae09a2a307059478d309b26c4115a224cfaf6
 Ctrl.info = hexinfo:b0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff
 Output = 0bd770a74d1160f7c9f12cd5912a06ebff6adcae899d92191fe4305673ba2ffe8fa3f1a4e5ad79f3f334b3b202b2173c486ea37ce3d397ed034c7f9dfeb15c5e927336d0441f4c4300e2cff0d0900b52d3b4
 
-KDF = HKDF
+PKEYKDF = HKDF
 Ctrl.md = md:SHA1
 Ctrl.IKM = hexkey:0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b
 Ctrl.salt = salt:
 Ctrl.info = info:
 Output = 0ac1af7002b3d761d1e55298da9d0506b9ae52057220a306e07b6b87e8df21d0ea00033de03984d34918
 
-KDF = HKDF
+PKEYKDF = HKDF
 Ctrl.mode = mode:EXTRACT_ONLY
 Ctrl.md = md:SHA1
 Ctrl.IKM = hexkey:0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b
 Ctrl.salt = salt:
 Output = da8c8a73c7fa77288ec6f5e7c297786aa0d32d01
 
-KDF = HKDF
+PKEYKDF = HKDF
 Ctrl.mode = mode:EXPAND_ONLY
 Ctrl.md = md:SHA1
 Ctrl.IKM = hexkey:da8c8a73c7fa77288ec6f5e7c297786aa0d32d01
 Ctrl.info = info:
 Output = 0ac1af7002b3d761d1e55298da9d0506b9ae52057220a306e07b6b87e8df21d0ea00033de03984d34918
 
-KDF = HKDF
+PKEYKDF = HKDF
 Ctrl.md = md:SHA1
 Ctrl.IKM = hexkey:0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c
 Ctrl.salt = salt:
 Ctrl.info = info:
 Output = 2c91117204d745f3500d636a62f64f0ab3bae548aa53d423b0d1f27ebba6f5e5673a081d70cce7acfc48
 
-KDF = HKDF
+PKEYKDF = HKDF
 Ctrl.mode = mode:EXTRACT_ONLY
 Ctrl.md = md:SHA1
 Ctrl.IKM = hexkey:0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c
 Ctrl.salt = salt:
 Output = 2adccada18779e7c2077ad2eb19d3f3e731385dd
 
-KDF = HKDF
+PKEYKDF = HKDF
 Ctrl.mode = mode:EXPAND_ONLY
 Ctrl.md = md:SHA1
 Ctrl.IKM = hexkey:2adccada18779e7c2077ad2eb19d3f3e731385dd
 Ctrl.info = info:
 Output = 2c91117204d745f3500d636a62f64f0ab3bae548aa53d423b0d1f27ebba6f5e5673a081d70cce7acfc48
 
-KDF = HKDF
+PKEYKDF = HKDF
 Ctrl.IKM = hexkey:0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c
 Ctrl.salt = salt:
 Ctrl.info = info:
 Output = 00
 Result = KDF_DERIVE_ERROR
 
-KDF = HKDF
+PKEYKDF = HKDF
 Ctrl.md = md:SHA1
 Ctrl.salt = salt:
 Ctrl.info = info:
 Output = 00
 Result = KDF_DERIVE_ERROR
 
-KDF = HKDF
+PKEYKDF = HKDF
 Ctrl.md = md:SHA1
 Ctrl.IKM = hexkey:0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c
 Ctrl.info = info:
 Output = 2c91117204d745f3500d636a62f64f0ab3bae548aa53d423b0d1f27ebba6f5e5673a081d70cce7acfc48
 
-KDF = HKDF
+PKEYKDF = HKDF
 Ctrl.md = md:SHA1
 Ctrl.IKM = hexkey:0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c
 Ctrl.salt = salt:
 Output = 2c91117204d745f3500d636a62f64f0ab3bae548aa53d423b0d1f27ebba6f5e5673a081d70cce7acfc48
 
-KDF = HKDF
+PKEYKDF = HKDF
 Ctrl.mode = mode:EXTRACT_AND_EXPAND
 Ctrl.md = md:SHA1
 Ctrl.IKM = hexkey:0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c
@@ -254,7 +254,7 @@ Output = 2c91117204d745f3500d636a62f64f0ab3bae548aa53d423b0d1f27ebba6f5e5673a081
 
 Title = id-scrypt tests (from draft-josefsson-id-scrypt-kdf-03 and others)
 
-KDF = scrypt
+PKEYKDF = scrypt
 Ctrl.pass = pass:
 Ctrl.salt = salt:
 Ctrl.N = N:16
@@ -262,7 +262,7 @@ Ctrl.r = r:1
 Ctrl.p = p:1
 Output = 77d6576238657b203b19ca42c18a0497f16b4844e3074ae8dfdffa3fede21442fcd0069ded0948f8326a753a0fc81f17e8d3e0fb2e0d3628cf35e20c38d18906
 
-KDF = scrypt
+PKEYKDF = scrypt
 Ctrl.pass = pass:password
 Ctrl.salt = salt:NaCl
 Ctrl.N = N:1024
@@ -270,7 +270,7 @@ Ctrl.r = r:8
 Ctrl.p = p:16
 Output = fdbabe1c9d3472007856e7190d01e9fe7c6ad7cbc8237830e77376634b3731622eaf30d92e22a3886ff109279d9830dac727afb94a83ee6d8360cbdfa2cc0640
 
-KDF = scrypt
+PKEYKDF = scrypt
 Ctrl.hexpass = hexpass:70617373776f7264
 Ctrl.salt = salt:NaCl
 Ctrl.N = N:1024
@@ -278,7 +278,7 @@ Ctrl.r = r:8
 Ctrl.p = p:16
 Output = fdbabe1c9d3472007856e7190d01e9fe7c6ad7cbc8237830e77376634b3731622eaf30d92e22a3886ff109279d9830dac727afb94a83ee6d8360cbdfa2cc0640
 
-KDF = scrypt
+PKEYKDF = scrypt
 Ctrl.pass = pass:password
 Ctrl.hexsalt = hexsalt:4e61436c
 Ctrl.N = N:1024
@@ -286,7 +286,7 @@ Ctrl.r = r:8
 Ctrl.p = p:16
 Output = fdbabe1c9d3472007856e7190d01e9fe7c6ad7cbc8237830e77376634b3731622eaf30d92e22a3886ff109279d9830dac727afb94a83ee6d8360cbdfa2cc0640
 
-KDF = scrypt
+PKEYKDF = scrypt
 Ctrl.pass = pass:pleaseletmein
 Ctrl.salt = salt:SodiumChloride
 Ctrl.N = N:16384
@@ -295,7 +295,7 @@ Ctrl.p = p:1
 Output = 7023bdcb3afd7348461c06cd81fd38ebfda8fbba904f8e3ea9b543f6545da1f2d5432955613f0fcf62d49705242a9af9e61e85dc0d651e40dfcf017b45575887
 
 # Out of memory
-KDF = scrypt
+PKEYKDF = scrypt
 Ctrl.pass = pass:pleaseletmein
 Ctrl.salt = salt:SodiumChloride
 Ctrl.N = N:1048576
diff --git a/test/recipes/30-test_evp_kdf.t b/test/recipes/30-test_evp_kdf.t
new file mode 100644
index 0000000..9e43d6d
--- /dev/null
+++ b/test/recipes/30-test_evp_kdf.t
@@ -0,0 +1,13 @@
+#! /usr/bin/env perl
+# Copyright 2018 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
+
+
+use OpenSSL::Test::Simple;
+
+simple_test("test_evp_kdf", "evp_kdf_test");
diff --git a/util/libcrypto.num b/util/libcrypto.num
index cc88ac4..2b5365e 100644
--- a/util/libcrypto.num
+++ b/util/libcrypto.num
@@ -4631,3 +4631,11 @@ CMS_add1_signing_cert_v2                4586	3_0_0	EXIST::FUNCTION:CMS
 ESS_SIGNING_CERT_new_init               4587	3_0_0	EXIST::FUNCTION:
 ESS_SIGNING_CERT_V2_new_init            4588	3_0_0	EXIST::FUNCTION:
 ERR_load_ESS_strings                    4589	3_0_0	EXIST::FUNCTION:
+EVP_KDF_CTX_new_id                      4590	3_0_0	EXIST::FUNCTION:
+EVP_KDF_CTX_free                        4591	3_0_0	EXIST::FUNCTION:
+EVP_KDF_reset                           4592	3_0_0	EXIST::FUNCTION:
+EVP_KDF_ctrl                            4593	3_0_0	EXIST::FUNCTION:
+EVP_KDF_vctrl                           4594	3_0_0	EXIST::FUNCTION:
+EVP_KDF_ctrl_str                        4595	3_0_0	EXIST::FUNCTION:
+EVP_KDF_size                            4596	3_0_0	EXIST::FUNCTION:
+EVP_KDF_derive                          4597	3_0_0	EXIST::FUNCTION:
diff --git a/util/private.num b/util/private.num
index 6fe4392..3832841 100644
--- a/util/private.num
+++ b/util/private.num
@@ -22,6 +22,7 @@ CRYPTO_EX_dup                           datatype
 CRYPTO_EX_free                          datatype
 CRYPTO_EX_new                           datatype
 DTLS_timer_cb                           datatype
+EVP_KDF_CTX                             datatype
 EVP_MAC                                 datatype
 EVP_MAC_CTX                             datatype
 EVP_PKEY_gen_cb                         datatype


More information about the openssl-commits mailing list