[openssl-commits] [openssl] master update

Dr. Stephen Henson steve at openssl.org
Tue Jan 19 14:17:06 UTC 2016


The branch master has been updated
       via  6ada465fb258ae2c29668c59f3ec9b69dc38f8b3 (commit)
       via  53a3a545c3c1ce35a2e9af50e0f868c6878603b5 (commit)
       via  44a284d292d7bc76edd6a7e3acbd70889daa25cf (commit)
       via  b7d60e7662f903fc2e5a137bf1fce9a6b431776a (commit)
       via  1eff3485b63f84956b5f212aa4d853783bf6c8b5 (commit)
      from  8957728772824c1efd1c5e479d8b60fe6f88e6f5 (commit)


- Log -----------------------------------------------------------------
commit 6ada465fb258ae2c29668c59f3ec9b69dc38f8b3
Author: Dr. Stephen Henson <steve at openssl.org>
Date:   Tue Jan 19 13:59:09 2016 +0000

    Add documentation for EVP_PKEY_TLS1_PRF
    
    Reviewed-by: Matt Caswell <matt at openssl.org>

commit 53a3a545c3c1ce35a2e9af50e0f868c6878603b5
Author: Dr. Stephen Henson <steve at openssl.org>
Date:   Tue Jan 19 13:59:05 2016 +0000

    add TLS1-PRF tests
    
    Reviewed-by: Matt Caswell <matt at openssl.org>

commit 44a284d292d7bc76edd6a7e3acbd70889daa25cf
Author: Dr. Stephen Henson <steve at openssl.org>
Date:   Tue Jan 19 13:59:00 2016 +0000

    Add TLS1-PRF test support to evp_test
    
    Reviewed-by: Matt Caswell <matt at openssl.org>

commit b7d60e7662f903fc2e5a137bf1fce9a6b431776a
Author: Dr. Stephen Henson <steve at openssl.org>
Date:   Tue Jan 19 13:58:51 2016 +0000

    use TLS PRF
    
    Modify libssl to use EVP_PKEY TLS PRF.
    
    Reviewed-by: Matt Caswell <matt at openssl.org>

commit 1eff3485b63f84956b5f212aa4d853783bf6c8b5
Author: Dr. Stephen Henson <steve at openssl.org>
Date:   Tue Jan 19 13:57:19 2016 +0000

    Add TLS PRF method.
    
    Add EVP_PKEY algorithm for TLS1 PRF.
    
    Reviewed-by: Matt Caswell <matt at openssl.org>

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

Summary of changes:
 Makefile.in                       |   2 +-
 crypto/evp/pmeth_lib.c            |   3 +-
 crypto/include/internal/evp_int.h |   1 +
 crypto/{cmac => kdf}/Makefile.in  |  18 ++-
 crypto/kdf/tls1_prf.c             | 283 ++++++++++++++++++++++++++++++++++++++
 crypto/objects/obj_dat.h          |   9 +-
 crypto/objects/obj_mac.num        |   1 +
 crypto/objects/objects.txt        |   3 +
 doc/crypto/EVP_PKEY_TLS1_PRF.pod  |  87 ++++++++++++
 include/openssl/evp.h             |   1 +
 include/openssl/{cmac.h => kdf.h} |  33 +++--
 include/openssl/obj_mac.h         |   4 +
 ssl/t1_enc.c                      | 188 ++++++-------------------
 test/evp_test.c                   | 115 ++++++++++++++++
 test/evptests.txt                 |  48 +++++++
 15 files changed, 625 insertions(+), 171 deletions(-)
 copy crypto/{cmac => kdf}/Makefile.in (81%)
 create mode 100644 crypto/kdf/tls1_prf.c
 create mode 100644 doc/crypto/EVP_PKEY_TLS1_PRF.pod
 copy include/openssl/{cmac.h => kdf.h} (74%)

diff --git a/Makefile.in b/Makefile.in
index 496f118..8dd7f1a 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -144,7 +144,7 @@ SDIRS=  \
 	bn ec rsa dsa dh dso engine \
 	buffer bio stack lhash rand err \
 	evp asn1 pem x509 x509v3 conf txt_db pkcs7 pkcs12 comp ocsp ui \
-	cms pqueue ts jpake srp store cmac ct async
+	cms pqueue ts jpake srp store cmac ct async kdf
 # keep in mind that the above list is adjusted by ./Configure
 # according to no-xxx arguments...
 
diff --git a/crypto/evp/pmeth_lib.c b/crypto/evp/pmeth_lib.c
index f5d558f..1d7d576 100644
--- a/crypto/evp/pmeth_lib.c
+++ b/crypto/evp/pmeth_lib.c
@@ -87,8 +87,9 @@ static const EVP_PKEY_METHOD *standard_methods[] = {
     &hmac_pkey_meth,
     &cmac_pkey_meth,
 #ifndef OPENSSL_NO_DH
-    &dhx_pkey_meth
+    &dhx_pkey_meth,
 #endif
+    &tls1_prf_pkey_meth
 };
 
 DECLARE_OBJ_BSEARCH_CMP_FN(const EVP_PKEY_METHOD *, const EVP_PKEY_METHOD *,
diff --git a/crypto/include/internal/evp_int.h b/crypto/include/internal/evp_int.h
index e6be432..da73e70 100644
--- a/crypto/include/internal/evp_int.h
+++ b/crypto/include/internal/evp_int.h
@@ -131,6 +131,7 @@ extern const EVP_PKEY_METHOD dsa_pkey_meth;
 extern const EVP_PKEY_METHOD ec_pkey_meth;
 extern const EVP_PKEY_METHOD hmac_pkey_meth;
 extern const EVP_PKEY_METHOD rsa_pkey_meth;
+extern const EVP_PKEY_METHOD tls1_prf_pkey_meth;
 
 struct evp_md_st {
     int type;
diff --git a/crypto/cmac/Makefile.in b/crypto/kdf/Makefile.in
similarity index 81%
copy from crypto/cmac/Makefile.in
copy to crypto/kdf/Makefile.in
index d9cc9c5..25798af 100644
--- a/crypto/cmac/Makefile.in
+++ b/crypto/kdf/Makefile.in
@@ -1,8 +1,8 @@
 #
-# OpenSSL/crypto/cmac/Makefile
+# OpenSSL/crypto/kdf/Makefile
 #
 
-DIR=	cmac
+DIR=	kdf
 TOP=	../..
 CC=	cc
 INCLUDES=
@@ -15,12 +15,12 @@ CFLAGS= $(INCLUDES) $(CFLAG)
 GENERAL=Makefile
 
 LIB=$(TOP)/libcrypto.a
-LIBSRC=cmac.c cm_ameth.c cm_pmeth.c
-LIBOBJ=cmac.o cm_ameth.o cm_pmeth.o
+LIBSRC=tls1_prf.c
+LIBOBJ=tls1_prf.o
 
 SRC= $(LIBSRC)
 
-HEADER=	
+HEADER=
 
 ALL=    $(GENERAL) $(SRC) $(HEADER)
 
@@ -37,6 +37,14 @@ lib:	$(LIBOBJ)
 files:
 	$(PERL) $(TOP)/util/files.pl Makefile >> $(TOP)/MINFO
 
+tags:
+	ctags $(SRC)
+
+tests:
+
+lint:
+	lint -DLINT $(INCLUDES) $(SRC)>fluff
+
 update: depend
 
 depend:
diff --git a/crypto/kdf/tls1_prf.c b/crypto/kdf/tls1_prf.c
new file mode 100644
index 0000000..3c14b90
--- /dev/null
+++ b/crypto/kdf/tls1_prf.c
@@ -0,0 +1,283 @@
+/*
+ * Written by Dr Stephen N Henson (steve at openssl.org) for the OpenSSL project
+ * 2016.
+ */
+/* ====================================================================
+ * Copyright (c) 2015 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing at OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay at cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh at cryptsoft.com).
+ *
+ */
+
+#include <stdio.h>
+#include "internal/cryptlib.h"
+#include <openssl/kdf.h>
+#include <openssl/evp.h>
+#include "internal/evp_int.h"
+
+static int tls1_prf_alg(const EVP_MD *md,
+                        const unsigned char *sec, size_t slen,
+                        const unsigned char *seed, size_t seed_len,
+                        unsigned char *out, size_t olen);
+
+#define TLS1_PRF_MAXBUF 1024
+
+/* TLS KDF pkey context structure */
+
+typedef struct {
+    /* Digest to use for PRF */
+    const EVP_MD *md;
+    /* Secret value to use for PRF */
+    unsigned char *sec;
+    size_t seclen;
+    /* 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)
+{
+    TLS1_PRF_PKEY_CTX *kctx;
+
+    kctx = OPENSSL_zalloc(sizeof(*kctx));
+    if (kctx == NULL)
+        return 0;
+    ctx->data = kctx;
+
+    return 1;
+}
+
+static void pkey_tls1_prf_cleanup(EVP_PKEY_CTX *ctx)
+{
+    TLS1_PRF_PKEY_CTX *kctx = ctx->data;
+    OPENSSL_clear_free(kctx->sec, kctx->seclen);
+    OPENSSL_cleanse(kctx->seed, kctx->seedlen);
+    OPENSSL_free(kctx);
+}
+
+static int pkey_tls1_prf_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
+{
+    TLS1_PRF_PKEY_CTX *kctx = ctx->data;
+    switch (type) {
+    case EVP_PKEY_CTRL_TLS_MD:
+        kctx->md = p2;
+        return 1;
+
+    case EVP_PKEY_CTRL_TLS_SECRET:
+        if (p1 < 0)
+            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)
+            return 0;
+        kctx->seclen  = p1;
+        return 1;
+
+    case EVP_PKEY_CTRL_TLS_SEED:
+        if (p1 == 0 || p2 == NULL)
+            return 1;
+        if (p1 < 0 || p1 > (int)(TLS1_PRF_MAXBUF - kctx->seedlen))
+            return 0;
+        memcpy(kctx->seed + kctx->seedlen, p2, p1);
+        kctx->seedlen += p1;
+        return 1;
+
+    default:
+        return -2;
+
+    }
+}
+
+static int pkey_tls1_prf_derive(EVP_PKEY_CTX *ctx, unsigned char *key,
+                                size_t *keylen)
+{
+    TLS1_PRF_PKEY_CTX *kctx = ctx->data;
+    if (kctx->md == NULL || kctx->sec == NULL || kctx->seed == NULL)
+        return 0;
+    return tls1_prf_alg(kctx->md, kctx->sec, kctx->seclen,
+                        kctx->seed, kctx->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,
+    0
+};
+
+static int tls1_prf_P_hash(const EVP_MD *md,
+                           const unsigned char *sec, size_t sec_len,
+                           const unsigned char *seed, size_t seed_len,
+                           unsigned char *out, size_t olen)
+{
+    int chunk;
+    EVP_MD_CTX *ctx = NULL, *ctx_tmp = NULL, *ctx_init = NULL;
+    EVP_PKEY *mac_key = NULL;
+    unsigned char A1[EVP_MAX_MD_SIZE];
+    size_t A1_len;
+    int ret = 0;
+
+    chunk = EVP_MD_size(md);
+    OPENSSL_assert(chunk >= 0);
+
+    ctx = EVP_MD_CTX_new();
+    ctx_tmp = EVP_MD_CTX_new();
+    ctx_init = EVP_MD_CTX_new();
+    if (ctx == NULL || ctx_tmp == NULL || ctx_init == NULL)
+        goto err;
+    EVP_MD_CTX_set_flags(ctx_init, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
+    mac_key = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL, sec, sec_len);
+    if (mac_key == NULL)
+        goto err;
+    if (!EVP_DigestSignInit(ctx_init, NULL, md, NULL, mac_key))
+        goto err;
+    if (!EVP_MD_CTX_copy_ex(ctx, ctx_init))
+        goto err;
+    if (seed != NULL && !EVP_DigestSignUpdate(ctx, seed, seed_len))
+        goto err;
+    if (!EVP_DigestSignFinal(ctx, A1, &A1_len))
+        goto err;
+
+    for (;;) {
+        /* Reinit mac contexts */
+        if (!EVP_MD_CTX_copy_ex(ctx, ctx_init))
+            goto err;
+        if (!EVP_DigestSignUpdate(ctx, A1, A1_len))
+            goto err;
+        if (olen > (size_t)chunk && !EVP_MD_CTX_copy_ex(ctx_tmp, ctx))
+            goto err;
+        if (seed && !EVP_DigestSignUpdate(ctx, seed, seed_len))
+            goto err;
+
+        if (olen > (size_t)chunk) {
+            size_t mac_len;
+            if (!EVP_DigestSignFinal(ctx, out, &mac_len))
+                goto err;
+            out += mac_len;
+            olen -= mac_len;
+            /* calc the next A1 value */
+            if (!EVP_DigestSignFinal(ctx_tmp, A1, &A1_len))
+                goto err;
+        } else {                /* last one */
+
+            if (!EVP_DigestSignFinal(ctx, A1, &A1_len))
+                goto err;
+            memcpy(out, A1, olen);
+            break;
+        }
+    }
+    ret = 1;
+ err:
+    EVP_PKEY_free(mac_key);
+    EVP_MD_CTX_free(ctx);
+    EVP_MD_CTX_free(ctx_tmp);
+    EVP_MD_CTX_free(ctx_init);
+    OPENSSL_cleanse(A1, sizeof(A1));
+    return ret;
+}
+
+static int tls1_prf_alg(const EVP_MD *md,
+                        const unsigned char *sec, size_t slen,
+                        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))
+            return 0;
+
+        tmp = OPENSSL_malloc(olen);
+        if (tmp == NULL)
+            return 0;
+        if (!tls1_prf_P_hash(EVP_sha1(), sec + slen/2, slen/2 + (slen & 1),
+                         seed, seed_len, tmp, olen)) {
+            OPENSSL_clear_free(tmp, olen);
+            return 0;
+        }
+        for (i = 0; i < olen; i++)
+            out[i] ^= tmp[i];
+        OPENSSL_clear_free(tmp, olen);
+        return 1;
+    }
+    if (!tls1_prf_P_hash(md, sec, slen, seed, seed_len, out, olen))
+        return 0;
+
+    return 1;
+}
diff --git a/crypto/objects/obj_dat.h b/crypto/objects/obj_dat.h
index debf8cc..1f13992 100644
--- a/crypto/objects/obj_dat.h
+++ b/crypto/objects/obj_dat.h
@@ -62,9 +62,9 @@
  * [including the GNU Public Licence.]
  */
 
-#define NUM_NID 1021
-#define NUM_SN 1014
-#define NUM_LN 1014
+#define NUM_NID 1022
+#define NUM_SN 1015
+#define NUM_LN 1015
 #define NUM_OBJ 937
 
 static const unsigned char lvalues[6612]={
@@ -2671,6 +2671,7 @@ static const ASN1_OBJECT nid_objs[NUM_NID]={
 {"ChaCha20-Poly1305","chacha20-poly1305",NID_chacha20_poly1305,0,NULL,0},
 {"ChaCha20","chacha20",NID_chacha20,0,NULL,0},
 {"tlsfeature","TLS Feature",NID_tlsfeature,8,&(lvalues[6603]),0},
+{"TLS1-PRF","tls1-prf",NID_tls1_prf,0,NULL,0},
 };
 
 static const unsigned int sn_objs[NUM_SN]={
@@ -2878,6 +2879,7 @@ static const unsigned int sn_objs[NUM_SN]={
 1006,	/* "SNILS" */
 16,	/* "ST" */
 143,	/* "SXNetID" */
+1021,	/* "TLS1-PRF" */
 458,	/* "UID" */
  0,	/* "UNDEF" */
 11,	/* "X500" */
@@ -4674,6 +4676,7 @@ static const unsigned int ln_objs[NUM_LN]={
 459,	/* "textEncodedORAddress" */
 293,	/* "textNotice" */
 106,	/* "title" */
+1021,	/* "tls1-prf" */
 682,	/* "tpBasis" */
 436,	/* "ucl" */
  0,	/* "undefined" */
diff --git a/crypto/objects/obj_mac.num b/crypto/objects/obj_mac.num
index 5c6ffd4..663e86c 100644
--- a/crypto/objects/obj_mac.num
+++ b/crypto/objects/obj_mac.num
@@ -1018,3 +1018,4 @@ grasshopper_mac		1017
 chacha20_poly1305		1018
 chacha20		1019
 tlsfeature		1020
+tls1_prf		1021
diff --git a/crypto/objects/objects.txt b/crypto/objects/objects.txt
index f34609d..1de8e79 100644
--- a/crypto/objects/objects.txt
+++ b/crypto/objects/objects.txt
@@ -1428,3 +1428,6 @@ secg-scheme 14 3 : dhSinglePass-cofactorDH-sha512kdf-scheme
 
 # SCRYPT algorithm
 1 3 6 1 4 1 11591 4 11		: id-scrypt
+
+# NID for TLS1 PRF
+                            : TLS1-PRF          : tls1-prf
diff --git a/doc/crypto/EVP_PKEY_TLS1_PRF.pod b/doc/crypto/EVP_PKEY_TLS1_PRF.pod
new file mode 100644
index 0000000..8e9ff5a
--- /dev/null
+++ b/doc/crypto/EVP_PKEY_TLS1_PRF.pod
@@ -0,0 +1,87 @@
+=pod
+
+=head1 NAME
+
+EVP_PKEY_TLS1_PRF, EVP_PKEY_CTX_set_tls1_prf_md,
+EVP_PKEY_CTX_set1_tls1_prf_secret, EVP_PKEY_CTX_add1_tls1_prf_seed -
+TLS PRF key derivation algorithm
+
+=head1 SYNOPSIS
+
+ #include <openssl/kdf.h>
+
+ int EVP_PKEY_CTX_set_tls1_prf_md(EVP_PKEY_CTX *pctx, const EVP_MD *md);
+ int EVP_PKEY_CTX_set1_tls1_prf_secret(EVP_PKEY_CTX *pctx,
+                                       unsigned char *sec, int seclen);
+ int EVP_PKEY_CTX_add1_tls1_prf_seed(EVP_PKEY_CTX *pctx, seed, seedlen)
+                                     unsigned char *seed, int seedlen);
+
+=head1 DESCRIPTION
+
+The EVP_PKEY_TLS1_PRF algorithm implements the PRF key derivation function for
+TLS. It has no associated private key and only implements key derivation
+using EVP_PKEY_derive().
+
+EVP_PKEY_set_tls1_prf_md() sets 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.
+
+EVP_PKEY_CTX_set_tls1_prf_secret() sets the secret value of the TLS PRF
+to B<seclen> bytes of the buffer B<sec>. Any existing secret value is replaced
+and any seed is reset.
+
+EVP_PKEY_CTX_add1_tls1_prf_seed() sets the seed to B<seedlen> bytes of B<seed>.
+If a seed is already set it is appended to the existing value.
+
+=head1 NOTES
+
+All these functions are implemented as macros.
+
+A context for the TLS PRF can be obtained by calling:
+
+ EVP_PKEY_CTX *pctx = EVP_PKEY_new_id(EVP_PKEY_TLS1_PRF, NULL);
+
+The digest, secret value and seed must be set before a key is derived or an
+error occurs.
+
+The total length of all seeds cannot exceed 1024 bytes in length: this should
+be more than enough for any normal use of the TLS PRF.
+
+The output length of the PRF is specified by the length parameter in the
+EVP_PKEY_derive() function. Since the output length is variable, setting
+the buffer to B<NULL> is not meaningful for the TLS PRF.
+
+Optimised versions of the TLS PRF can be implemented in an ENGINE.
+
+=head1 RETURN VALUES
+
+All these 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 public key algorithm.
+
+=head1 EXAMPLE
+
+This example derives 10 bytes using SHA-256 with the secret key "secret"
+and seed value "seed":
+
+ EVP_PKEY_CTX *pctx;
+ unsigned char out[10];
+ size_t outlen = sizeof(out);
+ pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_TLS1_PRF, NULL);
+ if (EVP_PKEY_derive_init(pctx) <= 0)
+    /* Error */
+ if (EVP_PKEY_CTX_set_tls1_prf_md(pctx, EVP_sha256()) <= 0)
+    /* Error */
+ if (EVP_PKEY_CTX_set1_tls1_prf_secret(pctx, "secret", 6) <= 0)
+    /* Error */
+ if (EVP_PKEY_CTX_add1_tls1_prf_seed(pctx, "seed", 4) <= 0)
+    /* Error */
+ if (EVP_PKEY_derive(pctx, out, &outlen) <= 0)
+    /* Error */
+
+=head1 SEE ALSO
+
+L<EVP_PKEY_CTX_new(3)>,
+L<EVP_PKEY_derive(3)>,
+
+=cut
diff --git a/include/openssl/evp.h b/include/openssl/evp.h
index 8001182..2ed9faa 100644
--- a/include/openssl/evp.h
+++ b/include/openssl/evp.h
@@ -108,6 +108,7 @@
 # define EVP_PKEY_EC     NID_X9_62_id_ecPublicKey
 # define EVP_PKEY_HMAC   NID_hmac
 # define EVP_PKEY_CMAC   NID_cmac
+# define EVP_PKEY_TLS1_PRF NID_tls1_prf
 
 #ifdef  __cplusplus
 extern "C" {
diff --git a/include/openssl/cmac.h b/include/openssl/kdf.h
similarity index 74%
copy from include/openssl/cmac.h
copy to include/openssl/kdf.h
index 175be83..96ccf92 100644
--- a/include/openssl/cmac.h
+++ b/include/openssl/kdf.h
@@ -1,10 +1,10 @@
-/* crypto/cmac/cmac.h */
+/* kdf.h */
 /*
  * Written by Dr Stephen N Henson (steve at openssl.org) for the OpenSSL
  * project.
  */
 /* ====================================================================
- * Copyright (c) 2010 The OpenSSL Project.  All rights reserved.
+ * Copyright (c) 2016 The OpenSSL Project.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -52,29 +52,28 @@
  * ====================================================================
  */
 
-#ifndef HEADER_CMAC_H
-# define HEADER_CMAC_H
+#ifndef HEADER_KDF_H
+# define HEADER_KDF_H
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
-# include <openssl/evp.h>
+# define EVP_PKEY_CTRL_TLS_MD       (EVP_PKEY_ALG_CTRL)
+# define EVP_PKEY_CTRL_TLS_SECRET   (EVP_PKEY_ALG_CTRL + 1)
+# define EVP_PKEY_CTRL_TLS_SEED     (EVP_PKEY_ALG_CTRL + 2)
 
-/* Opaque */
-typedef struct CMAC_CTX_st CMAC_CTX;
+# define EVP_PKEY_CTX_set_tls1_prf_md(pctx, md) \
+            EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_DERIVE, \
+                              EVP_PKEY_CTRL_TLS_MD, 0, (void *)md)
 
-CMAC_CTX *CMAC_CTX_new(void);
-void CMAC_CTX_cleanup(CMAC_CTX *ctx);
-void CMAC_CTX_free(CMAC_CTX *ctx);
-EVP_CIPHER_CTX *CMAC_CTX_get0_cipher_ctx(CMAC_CTX *ctx);
-int CMAC_CTX_copy(CMAC_CTX *out, const CMAC_CTX *in);
+# define EVP_PKEY_CTX_set1_tls1_prf_secret(pctx, sec, seclen) \
+            EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_DERIVE, \
+                              EVP_PKEY_CTRL_TLS_SECRET, seclen, (void *)sec)
 
-int CMAC_Init(CMAC_CTX *ctx, const void *key, size_t keylen,
-              const EVP_CIPHER *cipher, ENGINE *impl);
-int CMAC_Update(CMAC_CTX *ctx, const void *data, size_t dlen);
-int CMAC_Final(CMAC_CTX *ctx, unsigned char *out, size_t *poutlen);
-int CMAC_resume(CMAC_CTX *ctx);
+# define EVP_PKEY_CTX_add1_tls1_prf_seed(pctx, seed, seedlen) \
+            EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_DERIVE, \
+                              EVP_PKEY_CTRL_TLS_SEED, seedlen, (void *)seed)
 
 #ifdef  __cplusplus
 }
diff --git a/include/openssl/obj_mac.h b/include/openssl/obj_mac.h
index 5f21fd5..04605e0 100644
--- a/include/openssl/obj_mac.h
+++ b/include/openssl/obj_mac.h
@@ -4463,3 +4463,7 @@
 #define SN_id_scrypt            "id-scrypt"
 #define NID_id_scrypt           973
 #define OBJ_id_scrypt           1L,3L,6L,1L,4L,1L,11591L,4L,11L
+
+#define SN_tls1_prf             "TLS1-PRF"
+#define LN_tls1_prf             "tls1-prf"
+#define NID_tls1_prf            1021
diff --git a/ssl/t1_enc.c b/ssl/t1_enc.c
index 9885f24..23b3640 100644
--- a/ssl/t1_enc.c
+++ b/ssl/t1_enc.c
@@ -141,103 +141,10 @@
 # include <openssl/comp.h>
 #endif
 #include <openssl/evp.h>
-#include <openssl/hmac.h>
-#include <openssl/md5.h>
+#include <openssl/kdf.h>
 #include <openssl/rand.h>
 
-/* seed1 through seed5 are virtually concatenated */
-static int tls1_P_hash(const EVP_MD *md, const unsigned char *sec,
-                       int sec_len,
-                       const void *seed1, int seed1_len,
-                       const void *seed2, int seed2_len,
-                       const void *seed3, int seed3_len,
-                       const void *seed4, int seed4_len,
-                       const void *seed5, int seed5_len,
-                       unsigned char *out, int olen)
-{
-    int chunk;
-    size_t j;
-    EVP_MD_CTX *ctx = NULL, *ctx_tmp = NULL, *ctx_init = NULL;
-    EVP_PKEY *mac_key = NULL;
-    unsigned char A1[EVP_MAX_MD_SIZE];
-    size_t A1_len;
-    int ret = 0;
-
-    chunk = EVP_MD_size(md);
-    OPENSSL_assert(chunk >= 0);
-
-    ctx = EVP_MD_CTX_new();
-    ctx_tmp = EVP_MD_CTX_new();
-    ctx_init = EVP_MD_CTX_new();
-    if (ctx == NULL || ctx_tmp == NULL || ctx_init == NULL)
-        goto err;
-    EVP_MD_CTX_set_flags(ctx_init, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
-    mac_key = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL, sec, sec_len);
-    if (!mac_key)
-        goto err;
-    if (!EVP_DigestSignInit(ctx_init, NULL, md, NULL, mac_key))
-        goto err;
-    if (!EVP_MD_CTX_copy_ex(ctx, ctx_init))
-        goto err;
-    if (seed1 && !EVP_DigestSignUpdate(ctx, seed1, seed1_len))
-        goto err;
-    if (seed2 && !EVP_DigestSignUpdate(ctx, seed2, seed2_len))
-        goto err;
-    if (seed3 && !EVP_DigestSignUpdate(ctx, seed3, seed3_len))
-        goto err;
-    if (seed4 && !EVP_DigestSignUpdate(ctx, seed4, seed4_len))
-        goto err;
-    if (seed5 && !EVP_DigestSignUpdate(ctx, seed5, seed5_len))
-        goto err;
-    if (!EVP_DigestSignFinal(ctx, A1, &A1_len))
-        goto err;
-
-    for (;;) {
-        /* Reinit mac contexts */
-        if (!EVP_MD_CTX_copy_ex(ctx, ctx_init))
-            goto err;
-        if (!EVP_DigestSignUpdate(ctx, A1, A1_len))
-            goto err;
-        if (olen > chunk && !EVP_MD_CTX_copy_ex(ctx_tmp, ctx))
-            goto err;
-        if (seed1 && !EVP_DigestSignUpdate(ctx, seed1, seed1_len))
-            goto err;
-        if (seed2 && !EVP_DigestSignUpdate(ctx, seed2, seed2_len))
-            goto err;
-        if (seed3 && !EVP_DigestSignUpdate(ctx, seed3, seed3_len))
-            goto err;
-        if (seed4 && !EVP_DigestSignUpdate(ctx, seed4, seed4_len))
-            goto err;
-        if (seed5 && !EVP_DigestSignUpdate(ctx, seed5, seed5_len))
-            goto err;
-
-        if (olen > chunk) {
-            if (!EVP_DigestSignFinal(ctx, out, &j))
-                goto err;
-            out += j;
-            olen -= j;
-            /* calc the next A1 value */
-            if (!EVP_DigestSignFinal(ctx_tmp, A1, &A1_len))
-                goto err;
-        } else {                /* last one */
-
-            if (!EVP_DigestSignFinal(ctx, A1, &A1_len))
-                goto err;
-            memcpy(out, A1, olen);
-            break;
-        }
-    }
-    ret = 1;
- err:
-    EVP_PKEY_free(mac_key);
-    EVP_MD_CTX_free(ctx);
-    EVP_MD_CTX_free(ctx_tmp);
-    EVP_MD_CTX_free(ctx_init);
-    OPENSSL_cleanse(A1, sizeof(A1));
-    return ret;
-}
-
-/* seed1 through seed5 are virtually concatenated */
+/* seed1 through seed5 are concatenated */
 static int tls1_PRF(SSL *s,
                     const void *seed1, int seed1_len,
                     const void *seed2, int seed2_len,
@@ -245,43 +152,46 @@ static int tls1_PRF(SSL *s,
                     const void *seed4, int seed4_len,
                     const void *seed5, int seed5_len,
                     const unsigned char *sec, int slen,
-                    unsigned char *out1, unsigned char *out2, int olen)
+                    unsigned char *out, int olen)
 {
     const EVP_MD *md = ssl_prf_md(s);
+    EVP_PKEY_CTX *pctx = NULL;
+
+    int ret = 0;
+    size_t outlen = olen;
 
     if (md == NULL) {
         /* Should never happen */
         SSLerr(SSL_F_TLS1_PRF, ERR_R_INTERNAL_ERROR);
         return 0;
     }
-    if (EVP_MD_type(md) == NID_md5_sha1) {
-        int i;
-        if (!tls1_P_hash(EVP_md5(), sec, slen/2 + (slen & 1),
-                         seed1, seed1_len, seed2, seed2_len, seed3,
-                         seed3_len, seed4, seed4_len, seed5, seed5_len,
-                         out1, olen))
-            return 0;
-        if (!tls1_P_hash(EVP_sha1(), sec + slen/2, slen/2 + (slen & 1),
-                         seed1, seed1_len, seed2, seed2_len, seed3,
-                         seed3_len, seed4, seed4_len, seed5, seed5_len,
-                         out2, olen))
-            return 0;
-        for (i = 0; i < olen; i++)
-            out1[i] ^= out2[i];
-        return 1;
-    }
-    memset(out2, 0, olen);
-    if (!tls1_P_hash(md, sec, slen,
-                     seed1, seed1_len, seed2, seed2_len, seed3,
-                     seed3_len, seed4, seed4_len, seed5, seed5_len,
-                     out1, olen))
-        return 0;
+    pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_TLS1_PRF, NULL);
+    if (pctx == NULL || EVP_PKEY_derive_init(pctx) <= 0
+        || EVP_PKEY_CTX_set_tls1_prf_md(pctx, md) <= 0
+        || EVP_PKEY_CTX_set1_tls1_prf_secret(pctx, sec, slen) <= 0)
+        goto err;
 
-    return 1;
+    if (EVP_PKEY_CTX_add1_tls1_prf_seed(pctx, seed1, seed1_len) <= 0)
+        goto err;
+    if (EVP_PKEY_CTX_add1_tls1_prf_seed(pctx, seed2, seed2_len) <= 0)
+        goto err;
+    if (EVP_PKEY_CTX_add1_tls1_prf_seed(pctx, seed3, seed3_len) <= 0)
+        goto err;
+    if (EVP_PKEY_CTX_add1_tls1_prf_seed(pctx, seed4, seed4_len) <= 0)
+        goto err;
+    if (EVP_PKEY_CTX_add1_tls1_prf_seed(pctx, seed5, seed5_len) <= 0)
+        goto err;
+
+    if (EVP_PKEY_derive(pctx, out, &outlen) <= 0)
+        goto err;
+    ret = 1;
+
+    err:
+    EVP_PKEY_CTX_free(pctx);
+    return ret;
 }
 
-static int tls1_generate_key_block(SSL *s, unsigned char *km,
-                                   unsigned char *tmp, int num)
+static int tls1_generate_key_block(SSL *s, unsigned char *km, int num)
 {
     int ret;
     ret = tls1_PRF(s,
@@ -289,7 +199,7 @@ static int tls1_generate_key_block(SSL *s, unsigned char *km,
                    TLS_MD_KEY_EXPANSION_CONST_SIZE, s->s3->server_random,
                    SSL3_RANDOM_SIZE, s->s3->client_random, SSL3_RANDOM_SIZE,
                    NULL, 0, NULL, 0, s->session->master_key,
-                   s->session->master_key_length, km, tmp, num);
+                   s->session->master_key_length, km, num);
 
     return ret;
 }
@@ -550,7 +460,7 @@ int tls1_change_cipher_state(SSL *s, int which)
 
 int tls1_setup_key_block(SSL *s)
 {
-    unsigned char *p1, *p2 = NULL;
+    unsigned char *p;
     const EVP_CIPHER *c;
     const EVP_MD *hash;
     int num;
@@ -578,19 +488,14 @@ int tls1_setup_key_block(SSL *s)
 
     ssl3_cleanup_key_block(s);
 
-    if ((p1 = OPENSSL_malloc(num)) == NULL) {
+    if ((p = OPENSSL_malloc(num)) == NULL) {
         SSLerr(SSL_F_TLS1_SETUP_KEY_BLOCK, ERR_R_MALLOC_FAILURE);
         goto err;
     }
 
     s->s3->tmp.key_block_length = num;
-    s->s3->tmp.key_block = p1;
+    s->s3->tmp.key_block = p;
 
-    if ((p2 = OPENSSL_malloc(num)) == NULL) {
-        SSLerr(SSL_F_TLS1_SETUP_KEY_BLOCK, ERR_R_MALLOC_FAILURE);
-        OPENSSL_free(p1);
-        goto err;
-    }
 #ifdef TLS_DEBUG
     printf("client random\n");
     {
@@ -614,7 +519,7 @@ int tls1_setup_key_block(SSL *s)
                    ((z + 1) % 16) ? ' ' : '\n');
     }
 #endif
-    if (!tls1_generate_key_block(s, p1, p2, num))
+    if (!tls1_generate_key_block(s, p, num))
         goto err;
 #ifdef TLS_DEBUG
     printf("\nkey block\n");
@@ -646,7 +551,6 @@ int tls1_setup_key_block(SSL *s)
 
     ret = 1;
  err:
-    OPENSSL_clear_free(p2, num);
     return (ret);
 }
 
@@ -655,7 +559,6 @@ int tls1_final_finish_mac(SSL *s, const char *str, int slen,
 {
     int hashlen;
     unsigned char hash[EVP_MAX_MD_SIZE];
-    unsigned char buf2[12];
 
     if (!ssl3_digest_cached_records(s, 0))
         return 0;
@@ -665,21 +568,17 @@ int tls1_final_finish_mac(SSL *s, const char *str, int slen,
     if (hashlen == 0)
         return 0;
 
-    if (!tls1_PRF(s,
-                  str, slen, hash, hashlen, NULL, 0, NULL, 0, NULL, 0,
+    if (!tls1_PRF(s, str, slen, hash, hashlen, NULL, 0, NULL, 0, NULL, 0,
                   s->session->master_key, s->session->master_key_length,
-                  out, buf2, sizeof buf2))
+                  out, TLS1_FINISH_MAC_LENGTH))
         return 0;
     OPENSSL_cleanse(hash, hashlen);
-    OPENSSL_cleanse(buf2, sizeof(buf2));
-    return sizeof(buf2);
+    return TLS1_FINISH_MAC_LENGTH;
 }
 
 int tls1_generate_master_secret(SSL *s, unsigned char *out, unsigned char *p,
                                 int len)
 {
-    unsigned char buff[SSL_MAX_MASTER_KEY_LENGTH];
-
     if (s->session->flags & SSL_SESS_FLAG_EXTMS) {
         unsigned char hash[EVP_MAX_MD_SIZE * 2];
         int hashlen;
@@ -701,7 +600,8 @@ int tls1_generate_master_secret(SSL *s, unsigned char *out, unsigned char *p,
                  hash, hashlen,
                  NULL, 0,
                  NULL, 0,
-                 NULL, 0, p, len, s->session->master_key, buff, sizeof buff);
+                 NULL, 0, p, len, s->session->master_key,
+                 SSL3_MASTER_SECRET_SIZE);
         OPENSSL_cleanse(hash, hashlen);
     } else {
         tls1_PRF(s,
@@ -710,9 +610,9 @@ int tls1_generate_master_secret(SSL *s, unsigned char *out, unsigned char *p,
                  s->s3->client_random, SSL3_RANDOM_SIZE,
                  NULL, 0,
                  s->s3->server_random, SSL3_RANDOM_SIZE,
-                 NULL, 0, p, len, s->session->master_key, buff, sizeof buff);
+                 NULL, 0, p, len, s->session->master_key,
+                 SSL3_MASTER_SECRET_SIZE);
     }
-    OPENSSL_cleanse(buff, sizeof buff);
 #ifdef SSL_DEBUG
     fprintf(stderr, "Premaster Secret:\n");
     BIO_dump_fp(stderr, (char *)p, len);
@@ -817,7 +717,7 @@ int tls1_export_keying_material(SSL *s, unsigned char *out, size_t olen,
                   NULL, 0,
                   NULL, 0,
                   s->session->master_key, s->session->master_key_length,
-                  out, buff, olen);
+                  out, olen);
 
     goto ret;
  err1:
diff --git a/test/evp_test.c b/test/evp_test.c
index c8d1f60..bc3e6dd 100644
--- a/test/evp_test.c
+++ b/test/evp_test.c
@@ -61,6 +61,7 @@
 #include <openssl/err.h>
 #include <openssl/x509v3.h>
 #include <openssl/pkcs12.h>
+#include <openssl/kdf.h>
 #include "internal/numbers.h"
 
 /* Remove spaces from beginning and end of a string */
@@ -293,6 +294,7 @@ static const struct evp_test_method pdecrypt_test_method;
 static const struct evp_test_method pverify_recover_test_method;
 static const struct evp_test_method pbe_test_method;
 static const struct evp_test_method encode_test_method;
+static const struct evp_test_method kdf_test_method;
 
 static const struct evp_test_method *evp_test_list[] = {
     &digest_test_method,
@@ -304,6 +306,7 @@ static const struct evp_test_method *evp_test_list[] = {
     &pverify_recover_test_method,
     &pbe_test_method,
     &encode_test_method,
+    &kdf_test_method,
     NULL
 };
 
@@ -1664,3 +1667,115 @@ static const struct evp_test_method encode_test_method = {
     encode_test_parse,
     encode_test_run,
 };
+
+/*
+ * KDF operations: initially just TLS1 PRF but can be adapted.
+ */
+
+struct kdf_data {
+    /* Context for this operation */
+    EVP_PKEY_CTX *ctx;
+    /* Expected output */
+    unsigned char *output;
+    size_t output_len;
+};
+
+/*
+ * Perform public key operation setup: lookup key, allocated ctx and call
+ * the appropriate initialisation function
+ */
+static int kdf_test_init(struct evp_test *t, const char *name)
+{
+    struct kdf_data *kdata;
+
+    kdata = OPENSSL_malloc(sizeof(*kdata));
+    if (kdata == NULL)
+        return 0;
+    kdata->ctx = NULL;
+    kdata->output = NULL;
+    t->data = kdata;
+    kdata->ctx = EVP_PKEY_CTX_new_id(OBJ_sn2nid(name), NULL);
+    if (kdata->ctx == NULL)
+        return 0;
+    if (EVP_PKEY_derive_init(kdata->ctx) <= 0)
+        return 0;
+    return 1;
+}
+
+static void kdf_test_cleanup(struct evp_test *t)
+{
+    struct kdf_data *kdata = t->data;
+    OPENSSL_free(kdata->output);
+    EVP_PKEY_CTX_free(kdata->ctx);
+}
+
+static int kdf_ctrl(EVP_PKEY_CTX *ctx, int op, const char *value)
+{
+    unsigned char *buf = NULL;
+    size_t buf_len;
+    int rv = 0;
+    if (test_bin(value, &buf, &buf_len) == 0)
+        return 0;
+    if (EVP_PKEY_CTX_ctrl(ctx, -1, -1, op, buf_len, buf) <= 0)
+        goto err;
+    rv = 1;
+    err:
+    OPENSSL_free(buf);
+    return rv;
+}
+
+static int kdf_test_parse(struct evp_test *t,
+                          const char *keyword, const char *value)
+{
+    struct kdf_data *kdata = t->data;
+    if (strcmp(keyword, "Output") == 0)
+        return test_bin(value, &kdata->output, &kdata->output_len);
+    else if (strcmp(keyword, "MD") == 0) {
+        const EVP_MD *md = EVP_get_digestbyname(value);
+        if (md == NULL)
+            return 0;
+        if (EVP_PKEY_CTX_set_tls1_prf_md(kdata->ctx, md) <= 0)
+            return 0;
+        return 1;
+    } else if (strcmp(keyword, "Secret") == 0) {
+        return kdf_ctrl(kdata->ctx, EVP_PKEY_CTRL_TLS_SECRET, value);
+    } else if (strncmp("Seed", keyword, 4) == 0) {
+        return kdf_ctrl(kdata->ctx, EVP_PKEY_CTRL_TLS_SEED, value);
+    }
+    return 0;
+}
+
+static int kdf_test_run(struct evp_test *t)
+{
+    struct kdf_data *kdata = t->data;
+    unsigned char *out = NULL;
+    size_t out_len = kdata->output_len;
+    const char *err = "INTERNAL_ERROR";
+    out = OPENSSL_malloc(out_len);
+    if (!out) {
+        fprintf(stderr, "Error allocating output buffer!\n");
+        exit(1);
+    }
+    err = "KDF_DERIVE_ERROR";
+    if (EVP_PKEY_derive(kdata->ctx, out, &out_len) <= 0)
+        goto err;
+    err = "KDF_LENGTH_MISMATCH";
+    if (out_len != kdata->output_len)
+        goto err;
+    err = "KDF_MISMATCH";
+    if (check_output(t, kdata->output, out, out_len))
+        goto err;
+    err = NULL;
+ err:
+    OPENSSL_free(out);
+    t->err = err;
+    return 1;
+}
+
+static const struct evp_test_method kdf_test_method = {
+    "KDF",
+    kdf_test_init,
+    kdf_test_cleanup,
+    kdf_test_parse,
+    kdf_test_run
+};
diff --git a/test/evptests.txt b/test/evptests.txt
index 99ffe60..83452b4 100644
--- a/test/evptests.txt
+++ b/test/evptests.txt
@@ -2908,3 +2908,51 @@ AAD = f33388860000000000004e91
 Tag = eead9d67890cbb22392336fea1851f38
 Plaintext = 496e7465726e65742d4472616674732061726520647261667420646f63756d656e74732076616c696420666f722061206d6178696d756d206f6620736978206d6f6e74687320616e64206d617920626520757064617465642c207265706c616365642c206f72206f62736f6c65746564206279206f7468657220646f63756d656e747320617420616e792074696d652e20497420697320696e617070726f70726961746520746f2075736520496e7465726e65742d447261667473206173207265666572656e6365206d6174657269616c206f7220746f2063697465207468656d206f74686572207468616e206173202fe2809c776f726b20696e2070726f67726573732e2fe2809d
 Ciphertext = 64a0861575861af460f062c79be643bd5e805cfd345cf389f108670ac76c8cb24c6cfc18755d43eea09ee94e382d26b0bdb7b73c321b0100d4f03b7f355894cf332f830e710b97ce98c8a84abd0b948114ad176e008d33bd60f982b1ff37c8559797a06ef4f0ef61c186324e2b3506383606907b6a7c02b0f9f6157b53c867e4b9166c767b804d46a59b5216cde7a4e99040c5a40433225ee282a1b0a06c523eaf4534d7f83fa1155b0047718cbc546a0d072b04b3564eea1b422273f548271a0bb2316053fa76991955ebd63159434ecebb4e466dae5a1073a6727627097a1049e617d91d361094fa68f0ff77987130305beaba2eda04df997b714d6c6f2c29a6ad5cb4022b02709b
+
+# TLS1 PRF tests, from NIST test vectors
+
+KDF=TLS1-PRF
+MD=MD5-SHA1
+Secret = bded7fa5c1699c010be23dd06ada3a48349f21e5f86263d512c0c5cc379f0e780ec55d9844b2f1db02a96453513568d0
+Seed.label = "master secret"
+Seed.client_random = e5acaf549cd25c22d964c0d930fa4b5261d2507fad84c33715b7b9a864020693
+Seed.server_random = 135e4d557fdf3aa6406d82975d5c606a9734c9334b42136e96990fbd5358cdb2
+Output = 2f6962dfbc744c4b2138bb6b3d33054c5ecc14f24851d9896395a44ab3964efc2090c5bf51a0891209f46c1e1e998f62
+
+KDF=TLS1-PRF
+MD=MD5-SHA1
+Secret = 2f6962dfbc744c4b2138bb6b3d33054c5ecc14f24851d9896395a44ab3964efc2090c5bf51a0891209f46c1e1e998f62
+Seed.label = "key expansion"
+Seed.server_random = 67267e650eb32444119d222a368c191af3082888dc35afe8368e638c828874be
+Seed.client_random = d58a7b1cd4fedaa232159df652ce188f9d997e061b9bf48e83b62990440931f6
+Output = 3088825988e77fce68d19f756e18e43eb7fe672433504feaf99b3c503d9091b164f166db301d70c9fc0870b4a94563907bee1a61fb786cb717576890bcc51cb9ead97e01d0a2fea99c953377b195205ff07b369589178796edc963fd80fdbe518a2fc1c35c18ae8d
+
+KDF=TLS1-PRF
+MD=SHA256
+Secret = f8938ecc9edebc5030c0c6a441e213cd24e6f770a50dda07876f8d55da062bcadb386b411fd4fe4313a604fce6c17fbc
+Seed.label = "master secret"
+Seed.client_random = 36c129d01a3200894b9179faac589d9835d58775f9b5ea3587cb8fd0364cae8c
+Seed.server_random = f6c9575ed7ddd73e1f7d16eca115415812a43c2b747daaaae043abfb50053fce
+Output = 202c88c00f84a17a20027079604787461176455539e705be730890602c289a5001e34eeb3a043e5d52a65e66125188bf
+
+KDF=TLS1-PRF
+MD=SHA256
+Secret = 202c88c00f84a17a20027079604787461176455539e705be730890602c289a5001e34eeb3a043e5d52a65e66125188bf
+Seed.label = "key expansion"
+Seed.server_random = ae6c806f8ad4d80784549dff28a4b58fd837681a51d928c3e30ee5ff14f39868
+Seed.client_random = 62e1fd91f23f558a605f28478c58cf72637b89784d959df7e946d3f07bd1b616
+Output = d06139889fffac1e3a71865f504aa5d0d2a2e89506c6f2279b670c3e1b74f531016a2530c51a3a0f7e1d6590d0f0566b2f387f8d11fd4f731cdd572d2eae927f6f2f81410b25e6960be68985add6c38445ad9f8c64bf8068bf9a6679485d966f1ad6f68b43495b10a683755ea2b858d70ccac7ec8b053c6bd41ca299d4e51928
+
+# Missing digest.
+KDF=TLS1-PRF
+Secret = 01
+Seed = 02
+Output = 03
+Result = KDF_DERIVE_ERROR
+
+# Missing secret.
+KDF=TLS1-PRF
+MD=MD5-SHA1
+Seed = 02
+Output = 03
+Result = KDF_DERIVE_ERROR


More information about the openssl-commits mailing list