]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
tls/prov: move the TLS 1.3 KDF code to providers
authorPauli <pauli@openssl.org>
Mon, 2 Aug 2021 06:16:35 +0000 (16:16 +1000)
committerPauli <pauli@openssl.org>
Thu, 5 Aug 2021 05:43:59 +0000 (15:43 +1000)
This function needs to be power up tested as part of the FIPS validation and
thus it needs to be inside the provider boundary.  This is realised by
introducing a new KDF "TLS13-KDF" which does the required massaging of
parameters but is otherwise functionally equivalent to HKDF.

Reviewed-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Shane Lontis <shane.lontis@oracle.com>
(Merged from https://github.com/openssl/openssl/pull/16203)

include/openssl/core_names.h
providers/implementations/include/prov/implementations.h
providers/implementations/include/prov/names.h
providers/implementations/kdfs/hkdf.c
ssl/tls13_enc.c

index f99497e22942009fd1e72cae5838a150b1eda1a1..b549dae9167cf398c107999ccc6def01ff607d7f 100644 (file)
@@ -190,6 +190,9 @@ extern "C" {
 #define OSSL_KDF_PARAM_KEY          "key"       /* octet string */
 #define OSSL_KDF_PARAM_SALT         "salt"      /* octet string */
 #define OSSL_KDF_PARAM_PASSWORD     "pass"      /* octet string */
+#define OSSL_KDF_PARAM_PREFIX       "prefix"    /* octet string */
+#define OSSL_KDF_PARAM_LABEL        "label"     /* octet string */
+#define OSSL_KDF_PARAM_DATA         "data"      /* octet string */
 #define OSSL_KDF_PARAM_DIGEST       OSSL_ALG_PARAM_DIGEST     /* utf8 string */
 #define OSSL_KDF_PARAM_CIPHER       OSSL_ALG_PARAM_CIPHER     /* utf8 string */
 #define OSSL_KDF_PARAM_MAC          OSSL_ALG_PARAM_MAC        /* utf8 string */
@@ -223,6 +226,7 @@ extern "C" {
 
 /* Known KDF names */
 #define OSSL_KDF_NAME_HKDF           "HKDF"
+#define OSSL_KDF_NAME_TLS1_3_KDF     "TLS13-KDF"
 #define OSSL_KDF_NAME_PBKDF1         "PBKDF1"
 #define OSSL_KDF_NAME_PBKDF2         "PBKDF2"
 #define OSSL_KDF_NAME_SCRYPT         "SCRYPT"
index 855bd90919c53e9efbdcf6089b8a438aed3fe414..c80b0dcfa37b72e78afdd922985ba0d0635ced24 100644 (file)
@@ -257,6 +257,7 @@ extern const OSSL_DISPATCH ossl_kdf_scrypt_functions[];
 #endif
 extern const OSSL_DISPATCH ossl_kdf_tls1_prf_functions[];
 extern const OSSL_DISPATCH ossl_kdf_hkdf_functions[];
+extern const OSSL_DISPATCH ossl_kdf_tls1_3_kdf_functions[];
 extern const OSSL_DISPATCH ossl_kdf_sshkdf_functions[];
 extern const OSSL_DISPATCH ossl_kdf_sskdf_functions[];
 extern const OSSL_DISPATCH ossl_kdf_x963_kdf_functions[];
index 5aec4a0934eab265a91b81b1612dba8d01adf795..b05776e4f62c079a3ec9295c78036f198a640d40 100644 (file)
  */
 #define PROV_NAMES_HKDF "HKDF"
 #define PROV_DESCS_HKDF_SIGN "OpenSSL HKDF via EVP_PKEY implementation"
+#define PROV_NAMES_TLS1_3_KDF "TLS13-KDF"
 #define PROV_NAMES_SSKDF "SSKDF"
 #define PROV_NAMES_PBKDF1 "PBKDF1"
 #define PROV_NAMES_PBKDF2 "PBKDF2:1.2.840.113549.1.5.12"
index 167b64f0b301b3515442fa209ef7be50993391d4..667d5e9619ff1521e1dd3d4f3fb65d57a7502a2f 100644 (file)
@@ -23,6 +23,7 @@
 #include <openssl/proverr.h>
 #include "internal/cryptlib.h"
 #include "internal/numbers.h"
+#include "internal/packet.h"
 #include "crypto/evp.h"
 #include "prov/provider_ctx.h"
 #include "prov/providercommon.h"
@@ -40,6 +41,9 @@ static OSSL_FUNC_kdf_settable_ctx_params_fn kdf_hkdf_settable_ctx_params;
 static OSSL_FUNC_kdf_set_ctx_params_fn kdf_hkdf_set_ctx_params;
 static OSSL_FUNC_kdf_gettable_ctx_params_fn kdf_hkdf_gettable_ctx_params;
 static OSSL_FUNC_kdf_get_ctx_params_fn kdf_hkdf_get_ctx_params;
+static OSSL_FUNC_kdf_derive_fn kdf_tls1_3_derive;
+static OSSL_FUNC_kdf_settable_ctx_params_fn kdf_tls1_3_settable_ctx_params;
+static OSSL_FUNC_kdf_set_ctx_params_fn kdf_tls1_3_set_ctx_params;
 
 static int HKDF(OSSL_LIB_CTX *libctx, const EVP_MD *evp_md,
                 const unsigned char *salt, size_t salt_len,
@@ -55,6 +59,15 @@ static int HKDF_Expand(const EVP_MD *evp_md,
                        const unsigned char *info, size_t info_len,
                        unsigned char *okm, size_t okm_len);
 
+/* Settable context parameters that are common across HKDF and the TLS KDF */
+#define HKDF_COMMON_SETTABLES                                           \
+        OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_MODE, NULL, 0),           \
+        OSSL_PARAM_int(OSSL_KDF_PARAM_MODE, NULL),                      \
+        OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_PROPERTIES, NULL, 0),     \
+        OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_DIGEST, NULL, 0),         \
+        OSSL_PARAM_octet_string(OSSL_KDF_PARAM_KEY, NULL, 0),           \
+        OSSL_PARAM_octet_string(OSSL_KDF_PARAM_SALT, NULL, 0)
+
 typedef struct {
     void *provctx;
     int mode;
@@ -63,6 +76,12 @@ typedef struct {
     size_t salt_len;
     unsigned char *key;
     size_t key_len;
+    unsigned char *prefix;
+    size_t prefix_len;
+    unsigned char *label;
+    size_t label_len;
+    unsigned char *data;
+    size_t data_len;
     unsigned char info[HKDF_MAXBUF];
     size_t info_len;
 } KDF_HKDF;
@@ -98,6 +117,9 @@ static void kdf_hkdf_reset(void *vctx)
 
     ossl_prov_digest_reset(&ctx->digest);
     OPENSSL_free(ctx->salt);
+    OPENSSL_free(ctx->prefix);
+    OPENSSL_free(ctx->label);
+    OPENSSL_clear_free(ctx->data, ctx->data_len);
     OPENSSL_clear_free(ctx->key, ctx->key_len);
     OPENSSL_cleanse(ctx->info, ctx->info_len);
     memset(ctx, 0, sizeof(*ctx));
@@ -163,11 +185,10 @@ static int kdf_hkdf_derive(void *vctx, unsigned char *key, size_t keylen,
     }
 }
 
-static int kdf_hkdf_set_ctx_params(void *vctx, const OSSL_PARAM params[])
+static int hkdf_common_set_ctx_params(KDF_HKDF *ctx, const OSSL_PARAM params[])
 {
-    const OSSL_PARAM *p;
-    KDF_HKDF *ctx = vctx;
     OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(ctx->provctx);
+    const OSSL_PARAM *p;
     int n;
 
     if (params == NULL)
@@ -219,6 +240,21 @@ static int kdf_hkdf_set_ctx_params(void *vctx, const OSSL_PARAM params[])
                 return 0;
         }
     }
+
+    return 1;
+}
+
+static int kdf_hkdf_set_ctx_params(void *vctx, const OSSL_PARAM params[])
+{
+    const OSSL_PARAM *p;
+    KDF_HKDF *ctx = vctx;
+
+    if (params == NULL)
+        return 1;
+
+    if (!hkdf_common_set_ctx_params(ctx, params))
+        return 0;
+
     /* The info fields concatenate, so process them all */
     if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_INFO)) != NULL) {
         ctx->info_len = 0;
@@ -243,12 +279,7 @@ static const OSSL_PARAM *kdf_hkdf_settable_ctx_params(ossl_unused void *ctx,
                                                       ossl_unused void *provctx)
 {
     static const OSSL_PARAM known_settable_ctx_params[] = {
-        OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_MODE, NULL, 0),
-        OSSL_PARAM_int(OSSL_KDF_PARAM_MODE, NULL),
-        OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_PROPERTIES, NULL, 0),
-        OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_DIGEST, NULL, 0),
-        OSSL_PARAM_octet_string(OSSL_KDF_PARAM_SALT, NULL, 0),
-        OSSL_PARAM_octet_string(OSSL_KDF_PARAM_KEY, NULL, 0),
+        HKDF_COMMON_SETTABLES,
         OSSL_PARAM_octet_string(OSSL_KDF_PARAM_INFO, NULL, 0),
         OSSL_PARAM_END
     };
@@ -496,3 +527,215 @@ static int HKDF_Expand(const EVP_MD *evp_md,
     HMAC_CTX_free(hmac);
     return ret;
 }
+
+/*
+ * TLS uses slight variations of the above and for FIPS validation purposes,
+ * they need to be present here.
+ * Refer to RFC 8446 section 7 for specific details.
+ */
+
+/*
+ * Given a |secret|; a |label| of length |labellen|; and |data| of length
+ * |datalen| (e.g. typically a hash of the handshake messages), derive a new
+ * secret |outlen| bytes long and store it in the location pointed to be |out|.
+ * The |data| value may be zero length. Returns 1 on success and 0 on failure.
+ */
+static int prov_tls13_hkdf_expand(const EVP_MD *md,
+                                  const unsigned char *key, size_t keylen,
+                                  const unsigned char *prefix, size_t prefixlen,
+                                  const unsigned char *label, size_t labellen,
+                                  const unsigned char *data, size_t datalen,
+                                  unsigned char *out, size_t outlen)
+{
+    size_t hkdflabellen;
+    unsigned char hkdflabel[HKDF_MAXBUF];
+    WPACKET pkt;
+
+    /*
+     * 2 bytes for length of derived secret + 1 byte for length of combined
+     * prefix and label + bytes for the label itself + 1 byte length of hash
+     * + bytes for the hash itself.  We've got the maximum the KDF can handle
+     * which should always be sufficient.
+     */
+    if (!WPACKET_init_static_len(&pkt, hkdflabel, sizeof(hkdflabel), 0)
+            || !WPACKET_put_bytes_u16(&pkt, outlen)
+            || !WPACKET_start_sub_packet_u8(&pkt)
+            || !WPACKET_memcpy(&pkt, prefix, prefixlen)
+            || !WPACKET_memcpy(&pkt, label, labellen)
+            || !WPACKET_close(&pkt)
+            || !WPACKET_sub_memcpy_u8(&pkt, data, (data == NULL) ? 0 : datalen)
+            || !WPACKET_get_total_written(&pkt, &hkdflabellen)
+            || !WPACKET_finish(&pkt)) {
+        WPACKET_cleanup(&pkt);
+        return 0;
+    }
+
+    return HKDF_Expand(md, key, keylen, hkdflabel, hkdflabellen,
+                       out, outlen);
+}
+
+static int prov_tls13_hkdf_generate_secret(OSSL_LIB_CTX *libctx,
+                                           const EVP_MD *md,
+                                           const unsigned char *prevsecret,
+                                           size_t prevsecretlen,
+                                           const unsigned char *insecret,
+                                           size_t insecretlen,
+                                           const unsigned char *prefix,
+                                           size_t prefixlen,
+                                           const unsigned char *label,
+                                           size_t labellen,
+                                           unsigned char *out, size_t outlen)
+{
+    size_t mdlen;
+    int ret;
+    unsigned char preextractsec[EVP_MAX_MD_SIZE];
+    /* Always filled with zeros */
+    static const unsigned char default_zeros[EVP_MAX_MD_SIZE];
+
+    ret = EVP_MD_get_size(md);
+    /* Ensure cast to size_t is safe */
+    if (ret <= 0)
+        return 0;
+    mdlen = (size_t)ret;
+
+    if (insecret == NULL) {
+        insecret = default_zeros;
+        insecretlen = mdlen;
+    }
+    if (prevsecret == NULL) {
+        prevsecret = default_zeros;
+        prevsecretlen = 0;
+    } else {
+        EVP_MD_CTX *mctx = EVP_MD_CTX_new();
+        unsigned char hash[EVP_MAX_MD_SIZE];
+
+        /* The pre-extract derive step uses a hash of no messages */
+        if (mctx == NULL
+                || EVP_DigestInit_ex(mctx, md, NULL) <= 0
+                || EVP_DigestFinal_ex(mctx, hash, NULL) <= 0) {
+            EVP_MD_CTX_free(mctx);
+            return 0;
+        }
+        EVP_MD_CTX_free(mctx);
+
+        /* Generate the pre-extract secret */
+        if (!prov_tls13_hkdf_expand(md, prevsecret, mdlen,
+                                    prefix, prefixlen, label, labellen,
+                                    hash, mdlen, preextractsec, mdlen))
+            return 0;
+        prevsecret = preextractsec;
+        prevsecretlen = mdlen;
+    }
+
+    ret = HKDF_Extract(libctx, md, prevsecret, prevsecretlen,
+                       insecret, insecretlen, out, outlen);
+
+    if (prevsecret == preextractsec)
+        OPENSSL_cleanse(preextractsec, mdlen);
+    return ret;
+}
+
+static int kdf_tls1_3_derive(void *vctx, unsigned char *key, size_t keylen,
+                             const OSSL_PARAM params[])
+{
+    KDF_HKDF *ctx = (KDF_HKDF *)vctx;
+    const EVP_MD *md;
+
+    if (!ossl_prov_is_running() || !kdf_tls1_3_set_ctx_params(ctx, params))
+        return 0;
+
+    md = ossl_prov_digest_md(&ctx->digest);
+    if (md == NULL) {
+        ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_MESSAGE_DIGEST);
+        return 0;
+    }
+
+    switch (ctx->mode) {
+    default:
+        return 0;
+
+    case EVP_KDF_HKDF_MODE_EXTRACT_ONLY:
+        return prov_tls13_hkdf_generate_secret(PROV_LIBCTX_OF(ctx->provctx),
+                                               md,
+                                               ctx->salt, ctx->salt_len,
+                                               ctx->key, ctx->key_len,
+                                               ctx->prefix, ctx->prefix_len,
+                                               ctx->label, ctx->label_len,
+                                               key, keylen);
+
+    case EVP_KDF_HKDF_MODE_EXPAND_ONLY:
+        return prov_tls13_hkdf_expand(md, ctx->key, ctx->key_len,
+                                      ctx->prefix, ctx->prefix_len,
+                                      ctx->label, ctx->label_len,
+                                      ctx->data, ctx->data_len,
+                                      key, keylen);
+    }
+}
+
+static int kdf_tls1_3_set_ctx_params(void *vctx, const OSSL_PARAM params[])
+{
+    const OSSL_PARAM *p;
+    KDF_HKDF *ctx = vctx;
+
+    if (params == NULL)
+        return 1;
+
+    if (!hkdf_common_set_ctx_params(ctx, params))
+        return 0;
+
+    if (ctx->mode == EVP_KDF_HKDF_MODE_EXTRACT_AND_EXPAND) {
+        ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_MODE);
+        return 0;
+    }
+
+    if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_PREFIX)) != NULL) {
+        OPENSSL_free(ctx->prefix);
+        ctx->prefix = NULL;
+        if (!OSSL_PARAM_get_octet_string(p, (void **)&ctx->prefix, 0,
+                                         &ctx->prefix_len))
+            return 0;
+    }
+
+    if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_LABEL)) != NULL) {
+        OPENSSL_free(ctx->label);
+        ctx->label = NULL;
+        if (!OSSL_PARAM_get_octet_string(p, (void **)&ctx->label, 0,
+                                         &ctx->label_len))
+            return 0;
+    }
+
+    OPENSSL_clear_free(ctx->data, ctx->data_len);
+    ctx->data = NULL;
+    if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_DATA)) != NULL
+            && !OSSL_PARAM_get_octet_string(p, (void **)&ctx->data, 0,
+                                            &ctx->data_len))
+        return 0;
+    return 1;
+}
+
+static const OSSL_PARAM *kdf_tls1_3_settable_ctx_params(ossl_unused void *ctx,
+                                                        ossl_unused void *provctx)
+{
+    static const OSSL_PARAM known_settable_ctx_params[] = {
+        HKDF_COMMON_SETTABLES,
+        OSSL_PARAM_octet_string(OSSL_KDF_PARAM_PREFIX, NULL, 0),
+        OSSL_PARAM_octet_string(OSSL_KDF_PARAM_LABEL, NULL, 0),
+        OSSL_PARAM_octet_string(OSSL_KDF_PARAM_DATA, NULL, 0),
+        OSSL_PARAM_END
+    };
+    return known_settable_ctx_params;
+}
+
+const OSSL_DISPATCH ossl_kdf_tls1_3_kdf_functions[] = {
+    { OSSL_FUNC_KDF_NEWCTX, (void(*)(void))kdf_hkdf_new },
+    { OSSL_FUNC_KDF_FREECTX, (void(*)(void))kdf_hkdf_free },
+    { OSSL_FUNC_KDF_RESET, (void(*)(void))kdf_hkdf_reset },
+    { OSSL_FUNC_KDF_DERIVE, (void(*)(void))kdf_tls1_3_derive },
+    { OSSL_FUNC_KDF_SETTABLE_CTX_PARAMS,
+      (void(*)(void))kdf_tls1_3_settable_ctx_params },
+    { OSSL_FUNC_KDF_SET_CTX_PARAMS, (void(*)(void))kdf_tls1_3_set_ctx_params },
+    { OSSL_FUNC_KDF_GETTABLE_CTX_PARAMS,
+      (void(*)(void))kdf_hkdf_gettable_ctx_params },
+    { OSSL_FUNC_KDF_GET_CTX_PARAMS, (void(*)(void))kdf_hkdf_get_ctx_params },
+    { 0, NULL }
+};
index 91c424811794c5b3856a69e22e75ce151a7e3e4f..7f6133f29c6b820cbf875b873c54aae38c022f3d 100644 (file)
 
 #define TLS13_MAX_LABEL_LEN     249
 
-/* Always filled with zeros */
-static const unsigned char default_zeros[EVP_MAX_MD_SIZE];
+#ifdef CHARSET_EBCDIC
+static const unsigned char label_prefix[] = { 0x74, 0x6C, 0x73, 0x31, 0x33, 0x20, 0x00 };
+#else
+static const unsigned char label_prefix[] = "tls13 ";
+#endif
 
 /*
  * Given a |secret|; a |label| of length |labellen|; and |data| of length
@@ -33,29 +36,14 @@ int tls13_hkdf_expand(SSL *s, const EVP_MD *md, const unsigned char *secret,
                              const unsigned char *data, size_t datalen,
                              unsigned char *out, size_t outlen, int fatal)
 {
-#ifdef CHARSET_EBCDIC
-    static const unsigned char label_prefix[] = { 0x74, 0x6C, 0x73, 0x31, 0x33, 0x20, 0x00 };
-#else
-    static const unsigned char label_prefix[] = "tls13 ";
-#endif
-    EVP_KDF *kdf = EVP_KDF_fetch(s->ctx->libctx, OSSL_KDF_NAME_HKDF,
+    EVP_KDF *kdf = EVP_KDF_fetch(s->ctx->libctx, OSSL_KDF_NAME_TLS1_3_KDF,
                                  s->ctx->propq);
     EVP_KDF_CTX *kctx;
-    OSSL_PARAM params[5], *p = params;
+    OSSL_PARAM params[7], *p = params;
     int mode = EVP_PKEY_HKDEF_MODE_EXPAND_ONLY;
     const char *mdname = EVP_MD_get0_name(md);
     int ret;
-    size_t hkdflabellen;
     size_t hashlen;
-    /*
-     * 2 bytes for length of derived secret + 1 byte for length of combined
-     * prefix and label + bytes for the label itself + 1 byte length of hash
-     * + bytes for the hash itself
-     */
-    unsigned char hkdflabel[sizeof(uint16_t) + sizeof(uint8_t)
-                            + (sizeof(label_prefix) - 1) + TLS13_MAX_LABEL_LEN
-                            + 1 + EVP_MAX_MD_SIZE];
-    WPACKET pkt;
 
     kctx = EVP_KDF_CTX_new(kdf);
     EVP_KDF_free(kdf);
@@ -76,37 +64,33 @@ int tls13_hkdf_expand(SSL *s, const EVP_MD *md, const unsigned char *secret,
         return 0;
     }
 
-    hashlen = EVP_MD_get_size(md);
-
-    if (!WPACKET_init_static_len(&pkt, hkdflabel, sizeof(hkdflabel), 0)
-            || !WPACKET_put_bytes_u16(&pkt, outlen)
-            || !WPACKET_start_sub_packet_u8(&pkt)
-            || !WPACKET_memcpy(&pkt, label_prefix, sizeof(label_prefix) - 1)
-            || !WPACKET_memcpy(&pkt, label, labellen)
-            || !WPACKET_close(&pkt)
-            || !WPACKET_sub_memcpy_u8(&pkt, data, (data == NULL) ? 0 : datalen)
-            || !WPACKET_get_total_written(&pkt, &hkdflabellen)
-            || !WPACKET_finish(&pkt)) {
+    if ((ret = EVP_MD_get_size(md)) <= 0) {
         EVP_KDF_CTX_free(kctx);
-        WPACKET_cleanup(&pkt);
         if (fatal)
             SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
         else
             ERR_raise(ERR_LIB_SSL, ERR_R_INTERNAL_ERROR);
         return 0;
     }
+    hashlen = (size_t)ret;
 
     *p++ = OSSL_PARAM_construct_int(OSSL_KDF_PARAM_MODE, &mode);
     *p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST,
                                             (char *)mdname, 0);
     *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_KEY,
                                              (unsigned char *)secret, hashlen);
-    *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_INFO,
-                                             hkdflabel, hkdflabellen);
+    *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_PREFIX,
+                                             (unsigned char *)label_prefix,
+                                             sizeof(label_prefix) - 1);
+    *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_LABEL,
+                                             (unsigned char *)label, labellen);
+    if (data != NULL)
+        *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_DATA,
+                                                 (unsigned char *)data,
+                                                 datalen);
     *p++ = OSSL_PARAM_construct_end();
 
     ret = EVP_KDF_derive(kctx, out, outlen, params) <= 0;
-
     EVP_KDF_CTX_free(kctx);
 
     if (ret != 0) {
@@ -178,12 +162,12 @@ int tls13_generate_secret(SSL *s, const EVP_MD *md,
                           size_t insecretlen,
                           unsigned char *outsecret)
 {
-    size_t mdlen, prevsecretlen;
+    size_t mdlen;
     int mdleni;
     int ret;
     EVP_KDF *kdf;
     EVP_KDF_CTX *kctx;
-    OSSL_PARAM params[5], *p = params;
+    OSSL_PARAM params[7], *p = params;
     int mode = EVP_PKEY_HKDEF_MODE_EXTRACT_ONLY;
     const char *mdname = EVP_MD_get0_name(md);
 #ifdef CHARSET_EBCDIC
@@ -191,9 +175,8 @@ int tls13_generate_secret(SSL *s, const EVP_MD *md,
 #else
     static const char derived_secret_label[] = "derived";
 #endif
-    unsigned char preextractsec[EVP_MAX_MD_SIZE];
 
-    kdf = EVP_KDF_fetch(s->ctx->libctx, OSSL_KDF_NAME_HKDF, s->ctx->propq);
+    kdf = EVP_KDF_fetch(s->ctx->libctx, OSSL_KDF_NAME_TLS1_3_KDF, s->ctx->propq);
     kctx = EVP_KDF_CTX_new(kdf);
     EVP_KDF_free(kdf);
     if (kctx == NULL) {
@@ -210,51 +193,22 @@ int tls13_generate_secret(SSL *s, const EVP_MD *md,
     }
     mdlen = (size_t)mdleni;
 
-    if (insecret == NULL) {
-        insecret = default_zeros;
-        insecretlen = mdlen;
-    }
-    if (prevsecret == NULL) {
-        prevsecret = default_zeros;
-        prevsecretlen = 0;
-    } else {
-        EVP_MD_CTX *mctx = EVP_MD_CTX_new();
-        unsigned char hash[EVP_MAX_MD_SIZE];
-
-        /* The pre-extract derive step uses a hash of no messages */
-        if (mctx == NULL
-                || EVP_DigestInit_ex(mctx, md, NULL) <= 0
-                || EVP_DigestFinal_ex(mctx, hash, NULL) <= 0) {
-            SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
-            EVP_MD_CTX_free(mctx);
-            EVP_KDF_CTX_free(kctx);
-            return 0;
-        }
-        EVP_MD_CTX_free(mctx);
-
-        /* Generate the pre-extract secret */
-        if (!tls13_hkdf_expand(s, md, prevsecret,
-                               (unsigned char *)derived_secret_label,
-                               sizeof(derived_secret_label) - 1, hash, mdlen,
-                               preextractsec, mdlen, 1)) {
-            /* SSLfatal() already called */
-            EVP_KDF_CTX_free(kctx);
-            return 0;
-        }
-
-        prevsecret = preextractsec;
-        prevsecretlen = mdlen;
-    }
-
     *p++ = OSSL_PARAM_construct_int(OSSL_KDF_PARAM_MODE, &mode);
     *p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST,
                                             (char *)mdname, 0);
-    *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_KEY,
-                                             (unsigned char *)insecret,
-                                             insecretlen);
-    *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SALT,
-                                             (unsigned char *)prevsecret,
-                                             prevsecretlen);
+    if (insecret != NULL)
+        *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_KEY,
+                                                 (unsigned char *)insecret,
+                                                 insecretlen);
+    if (prevsecret != NULL)
+        *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SALT,
+                                                 (unsigned char *)prevsecret, mdlen);
+    *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_PREFIX,
+                                             (unsigned char *)label_prefix,
+                                             sizeof(label_prefix) - 1);
+    *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_LABEL,
+                                             (unsigned char *)derived_secret_label,
+                                             sizeof(derived_secret_label) - 1);
     *p++ = OSSL_PARAM_construct_end();
 
     ret = EVP_KDF_derive(kctx, outsecret, mdlen, params) <= 0;
@@ -263,8 +217,6 @@ int tls13_generate_secret(SSL *s, const EVP_MD *md,
         SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
 
     EVP_KDF_CTX_free(kctx);
-    if (prevsecret == preextractsec)
-        OPENSSL_cleanse(preextractsec, mdlen);
     return ret == 0;
 }