Hi,
 The attached patch set introduces new APIs to access the TLS 1.0 and
1.2 PRFs as well as the HKDF (rfc5869) function used in TLS 1.3.

There are few other updates to .gitlab-ci.yml (to use a more recent
asan and ubsan versions), and a comment in .bootstrap for the
testsuite/.test-rules.make which I always seem to forget and spend an
hour figuring out what is going on. Ideally .test-rules.make should
depend on Makefile.in so that one wouldn't need to manually run test-
rules.

I'd also suggest to rename the .bootstrap to bootstrap.sh as the latter
is quite a convention to find in projects (.bootstrap is not even
listed in ls).

regards,
Nikos
From f198ab5ac4c246945d44ea54f6e218a33658c334 Mon Sep 17 00:00:00 2001
From: Nikos Mavrogiannopoulos <[email protected]>
Date: Tue, 16 May 2017 14:30:41 +0200
Subject: [PATCH 6/6] Added the HKDF key derivation function and test vectors

Signed-off-by: Nikos Mavrogiannopoulos <[email protected]>
---
 Makefile.in                |   4 +-
 hkdf.c                     | 100 ++++++++++++++++++++++++++++++++++
 hkdf.h                     |  71 ++++++++++++++++++++++++
 testsuite/.test-rules.make |   3 ++
 testsuite/Makefile.in      |   2 +-
 testsuite/hkdf-test.c      | 131 +++++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 308 insertions(+), 3 deletions(-)
 create mode 100644 hkdf.c
 create mode 100644 hkdf.h
 create mode 100644 testsuite/hkdf-test.c

diff --git a/Makefile.in b/Makefile.in
index 5f07bee..2e80772 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -106,7 +106,7 @@ nettle_SOURCES = aes-decrypt-internal.c aes-decrypt.c \
 		 gosthash94.c gosthash94-meta.c \
 		 hmac.c hmac-md5.c hmac-ripemd160.c hmac-sha1.c \
 		 hmac-sha224.c hmac-sha256.c hmac-sha384.c hmac-sha512.c \
-		 knuth-lfib.c tls1-prf.c \
+		 knuth-lfib.c tls1-prf.c hkdf.c \
 		 md2.c md2-meta.c md4.c md4-meta.c \
 		 md5.c md5-compress.c md5-compat.c md5-meta.c \
 		 memeql-sec.c memxor.c memxor3.c \
@@ -191,7 +191,7 @@ HEADERS = aes.h arcfour.h arctwo.h asn1.h blowfish.h \
 	  cbc.h ccm.h chacha.h chacha-poly1305.h ctr.h \
 	  curve25519.h des.h des-compat.h dsa.h dsa-compat.h eax.h \
 	  ecc-curve.h ecc.h ecdsa.h eddsa.h \
-	  gcm.h gosthash94.h hmac.h tls1-prf.h \
+	  gcm.h gosthash94.h hmac.h tls1-prf.h hkdf.h \
 	  knuth-lfib.h \
 	  macros.h \
 	  md2.h md4.h \
diff --git a/hkdf.c b/hkdf.c
new file mode 100644
index 0000000..beb0468
--- /dev/null
+++ b/hkdf.c
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2017 Red Hat, Inc.
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GnuTLS.
+ *
+ * The GnuTLS is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+/* Functions for the HKDF handling.
+ */
+
+#if HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <assert.h>
+/* Needed for alloca on freebsd */
+#include <stdlib.h>
+#include <string.h>
+
+#include "hmac.h"
+
+#include "memxor.h"
+#include "nettle-internal.h"
+#include "hkdf.h"
+
+/* hkdf_extract: Outputs a PRK of digest_size
+ */
+void
+hkdf_extract(void *mac_ctx,
+	     nettle_hmac_set_key_func *set_key,
+	     nettle_hash_update_func *update,
+	     nettle_hash_digest_func *digest,
+	     size_t digest_size,
+	     size_t salt_size, const uint8_t *salt,
+	     size_t secret_size, const uint8_t *secret,
+	     uint8_t *dst)
+{
+	set_key(mac_ctx, salt_size, salt);
+
+	update(mac_ctx, secret_size, secret);
+	digest(mac_ctx, digest_size, dst);
+}
+
+void
+hkdf_expand(void *mac_ctx,
+	     nettle_hmac_set_key_func *set_key,
+	     nettle_hash_update_func *update,
+	     nettle_hash_digest_func *digest,
+	     size_t digest_size,
+	     size_t prk_size, const uint8_t *prk,
+	     size_t info_size, const uint8_t *info,
+	     size_t length, uint8_t *dst)
+{
+	uint8_t *Ttmp;
+	ssize_t left;
+	uint8_t i = 1;
+	unsigned started = 0;
+
+	left = length;
+
+	while(left > 0) {
+		/* T(i) */
+		set_key(mac_ctx, prk_size, prk);
+		if (started != 0) {
+			update(mac_ctx, digest_size, Ttmp);
+		} else {
+			started = 1;
+		}
+		if (info_size)
+			update(mac_ctx, info_size, info);
+		update(mac_ctx, 1, &i);
+
+		if (left < digest_size)
+			digest_size = left;
+
+		digest(mac_ctx, digest_size, dst);
+		Ttmp = dst;
+
+		left -= digest_size;
+		dst += digest_size;
+		i++;
+	}
+
+	return;
+}
diff --git a/hkdf.h b/hkdf.h
new file mode 100644
index 0000000..12bc449
--- /dev/null
+++ b/hkdf.h
@@ -0,0 +1,71 @@
+/* hmac.h
+
+   TLS PRF code (RFC-5246, RFC-2246).
+
+   Copyright (C) 2017 Red Hat, Inc.
+
+   This file is part of GNU Nettle.
+
+   GNU Nettle is free software: you can redistribute it and/or
+   modify it under the terms of either:
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at your
+       option) any later version.
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at your
+       option) any later version.
+
+   or both in parallel, as here.
+
+   GNU Nettle is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see http://www.gnu.org/licenses/.
+*/
+
+#ifndef NETTLE_HKDF_H_INCLUDED
+#define NETTLE_HKDF_H_INCLUDED
+
+#include "nettle-meta.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Namespace mangling */
+#define hkdf_extract nettle_hkdf_extract
+#define hkdf_expand nettle_hkdf_expand
+
+void
+hkdf_extract(void *mac_ctx,
+	     nettle_hmac_set_key_func *set_key,
+	     nettle_hash_update_func *update,
+	     nettle_hash_digest_func *digest,
+	     size_t digest_size,
+	     size_t salt_size, const uint8_t *salt,
+	     size_t secret_size, const uint8_t *secret,
+	     uint8_t *dst);
+
+void
+hkdf_expand(void *mac_ctx,
+	     nettle_hmac_set_key_func *set_key,
+	     nettle_hash_update_func *update,
+	     nettle_hash_digest_func *digest,
+	     size_t digest_size,
+	     size_t prk_size, const uint8_t *prk,
+	     size_t info_size, const uint8_t *info,
+	     size_t length, uint8_t *dst);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* NETTLE_HKDF_H_INCLUDED */
diff --git a/testsuite/.test-rules.make b/testsuite/.test-rules.make
index d09a68b..a419a09 100644
--- a/testsuite/.test-rules.make
+++ b/testsuite/.test-rules.make
@@ -58,6 +58,9 @@ gosthash94-test$(EXEEXT): gosthash94-test.$(OBJEXT)
 ripemd160-test$(EXEEXT): ripemd160-test.$(OBJEXT)
 	$(LINK) ripemd160-test.$(OBJEXT) $(TEST_OBJS) -o ripemd160-test$(EXEEXT)
 
+hkdf-test$(EXEEXT): hkdf-test.$(OBJEXT)
+	$(LINK) hkdf-test.$(OBJEXT) $(TEST_OBJS) -o hkdf-test$(EXEEXT)
+
 salsa20-test$(EXEEXT): salsa20-test.$(OBJEXT)
 	$(LINK) salsa20-test.$(OBJEXT) $(TEST_OBJS) -o salsa20-test$(EXEEXT)
 
diff --git a/testsuite/Makefile.in b/testsuite/Makefile.in
index 9344e7f..d1a97ef 100644
--- a/testsuite/Makefile.in
+++ b/testsuite/Makefile.in
@@ -17,7 +17,7 @@ TS_NETTLE_SOURCES = aes-test.c arcfour-test.c arctwo-test.c \
 		    des-test.c des3-test.c des-compat-test.c \
 		    md2-test.c md4-test.c md5-test.c md5-compat-test.c \
 		    memeql-test.c memxor-test.c gosthash94-test.c \
-		    ripemd160-test.c \
+		    ripemd160-test.c hkdf-test.c \
 		    salsa20-test.c tls10-prf-test.c tls12-prf-test.c \
 		    sha1-test.c sha224-test.c sha256-test.c \
 		    sha384-test.c sha512-test.c sha512-224-test.c sha512-256-test.c \
diff --git a/testsuite/hkdf-test.c b/testsuite/hkdf-test.c
new file mode 100644
index 0000000..e55d6ba
--- /dev/null
+++ b/testsuite/hkdf-test.c
@@ -0,0 +1,131 @@
+#include "testutils.h"
+#include "hkdf.h"
+#include "hmac.h"
+
+static
+void test_hkdf_sha256(const struct tstring *ikm, const struct tstring *salt,
+	const struct tstring *info, const struct tstring *extract_output,
+	const struct tstring *expand_output)
+{
+	struct hmac_sha256_ctx ctx;
+	uint8_t prk[SHA256_DIGEST_SIZE];
+	uint8_t *buffer = xalloc(expand_output->length);
+
+	hkdf_extract(&ctx, (nettle_hmac_set_key_func*)hmac_sha256_set_key,
+		  (nettle_hash_update_func*)hmac_sha256_update,
+		  (nettle_hash_digest_func*)hmac_sha256_digest, SHA256_DIGEST_SIZE,
+		  salt->length, salt->data, ikm->length, ikm->data,
+		  prk);
+
+	if (MEMEQ(SHA256_DIGEST_SIZE, prk, extract_output->data) == 0) {
+		fprintf(stdout, "\nGot:\n");
+		print_hex(SHA256_DIGEST_SIZE, prk);
+		fprintf(stdout, "\nExpected:\n");
+		print_hex(extract_output->length, extract_output->data);
+		abort();
+	}
+
+	hkdf_expand(&ctx, (nettle_hmac_set_key_func*)hmac_sha256_set_key,
+		  (nettle_hash_update_func*)hmac_sha256_update,
+		  (nettle_hash_digest_func*)hmac_sha256_digest, SHA256_DIGEST_SIZE,
+		  SHA256_DIGEST_SIZE, prk,
+		  info->length, info->data,
+		  expand_output->length, buffer);
+
+	if (MEMEQ(expand_output->length, expand_output->data, buffer) == 0) {
+		fprintf(stdout, "\nGot:\n");
+		print_hex(expand_output->length, buffer);
+		fprintf(stdout, "\nExpected:\n");
+		print_hex(expand_output->length, expand_output->data);
+		abort();
+	}
+	free(buffer);
+}
+
+static
+void test_hkdf_sha1(const struct tstring *ikm, const struct tstring *salt,
+	const struct tstring *info, const struct tstring *extract_output,
+	const struct tstring *expand_output)
+{
+	struct hmac_sha1_ctx ctx;
+	uint8_t prk[SHA1_DIGEST_SIZE];
+	uint8_t *buffer = xalloc(expand_output->length);
+
+	hkdf_extract(&ctx, (nettle_hmac_set_key_func*)hmac_sha1_set_key,
+		  (nettle_hash_update_func*)hmac_sha1_update,
+		  (nettle_hash_digest_func*)hmac_sha1_digest, SHA1_DIGEST_SIZE,
+		  salt->length, salt->data, ikm->length, ikm->data,
+		  prk);
+
+	if (MEMEQ(SHA1_DIGEST_SIZE, prk, extract_output->data) == 0) {
+		fprintf(stdout, "\nGot:\n");
+		print_hex(SHA1_DIGEST_SIZE, prk);
+		fprintf(stdout, "\nExpected:\n");
+		print_hex(extract_output->length, extract_output->data);
+		abort();
+	}
+
+	hkdf_expand(&ctx, (nettle_hmac_set_key_func*)hmac_sha1_set_key,
+		  (nettle_hash_update_func*)hmac_sha1_update,
+		  (nettle_hash_digest_func*)hmac_sha1_digest, SHA1_DIGEST_SIZE,
+		  SHA1_DIGEST_SIZE, prk,
+		  info->length, info->data,
+		  expand_output->length, buffer);
+
+	if (MEMEQ(expand_output->length, expand_output->data, buffer) == 0) {
+		fprintf(stdout, "\nGot:\n");
+		print_hex(expand_output->length, buffer);
+		fprintf(stdout, "\nExpected:\n");
+		print_hex(expand_output->length, expand_output->data);
+		abort();
+	}
+	free(buffer);
+}
+
+void
+test_main(void)
+{
+  /* HKDF test vectors from RFC5869 */
+  test_hkdf_sha256(SHEX("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"),
+  	SHEX("000102030405060708090a0b0c"),
+  	SHEX("f0f1f2f3f4f5f6f7f8f9"),
+  	SHEX("077709362c2e32df0ddc3f0dc47bba6390b6c73bb50f9c3122ec844ad7c2b3e5"),
+  	SHEX("3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865"));
+
+  test_hkdf_sha256(SHEX("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f"),
+  	SHEX("606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeaf"),
+  	SHEX("b0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"),
+  	SHEX("06a6b88c5853361a06104c9ceb35b45cef760014904671014a193f40c15fc244"),
+  	SHEX("b11e398dc80327a1c8e7f78c596a49344f012eda2d4efad8a050cc4c19afa97c59045a99cac7827271cb41c65e590e09da3275600c2f09b8367793a9aca3db71cc30c58179ec3e87c14c01d5c1f3434f1d87"));
+
+  test_hkdf_sha256(SHEX("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"),
+  	SDATA(""),
+  	SDATA(""),
+  	SHEX("19ef24a32c717b167f33a91d6f648bdf96596776afdb6377ac434c1c293ccb04"),
+  	SHEX("8da4e775a563c18f715f802a063c5a31b8a11f5c5ee1879ec3454e5f3c738d2d9d201395faa4b61a96c8"));
+
+  test_hkdf_sha1(SHEX("0b0b0b0b0b0b0b0b0b0b0b"),
+  	SHEX("000102030405060708090a0b0c"),
+  	SHEX("f0f1f2f3f4f5f6f7f8f9"),
+  	SHEX("9b6c18c432a7bf8f0e71c8eb88f4b30baa2ba243"),
+  	SHEX("085a01ea1b10f36933068b56efa5ad81a4f14b822f5b091568a9cdd4f155fda2c22e422478d305f3f896"));
+
+  test_hkdf_sha1(SHEX("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f"),
+  	SHEX("606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeaf"),
+  	SHEX("b0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"),
+  	SHEX("8adae09a2a307059478d309b26c4115a224cfaf6"),
+  	SHEX("0bd770a74d1160f7c9f12cd5912a06ebff6adcae899d92191fe4305673ba2ffe8fa3f1a4e5ad79f3f334b3b202b2173c486ea37ce3d397ed034c7f9dfeb15c5e927336d0441f4c4300e2cff0d0900b52d3b4"));
+
+  test_hkdf_sha1(SHEX("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"),
+  	SDATA(""),
+  	SDATA(""),
+  	SHEX("da8c8a73c7fa77288ec6f5e7c297786aa0d32d01"),
+  	SHEX("0ac1af7002b3d761d1e55298da9d0506b9ae52057220a306e07b6b87e8df21d0ea00033de03984d34918"));
+
+  test_hkdf_sha1(SHEX("0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c"),
+  	SHEX(""),
+  	SHEX(""),
+  	SHEX("2adccada18779e7c2077ad2eb19d3f3e731385dd"),
+  	SHEX("2c91117204d745f3500d636a62f64f0ab3bae548aa53d423b0d1f27ebba6f5e5673a081d70cce7acfc48"));
+}
+
-- 
2.9.3

From 86c1bd5a1c64322243247364de44e087585d15af Mon Sep 17 00:00:00 2001
From: Nikos Mavrogiannopoulos <[email protected]>
Date: Tue, 16 May 2017 13:11:29 +0200
Subject: [PATCH 5/6] Added the TLS 1.2 PRF and test vectors

Signed-off-by: Nikos Mavrogiannopoulos <[email protected]>
---
 testsuite/.test-rules.make |  3 +++
 testsuite/Makefile.in      |  2 +-
 testsuite/tls12-prf-test.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++
 tls1-prf.c                 | 49 ++++++++++++++++++++++++++++++++++++++++++++++
 tls1-prf.h                 | 11 +++++++++++
 5 files changed, 113 insertions(+), 1 deletion(-)
 create mode 100644 testsuite/tls12-prf-test.c

diff --git a/testsuite/.test-rules.make b/testsuite/.test-rules.make
index dbeb7a1..d09a68b 100644
--- a/testsuite/.test-rules.make
+++ b/testsuite/.test-rules.make
@@ -64,6 +64,9 @@ salsa20-test$(EXEEXT): salsa20-test.$(OBJEXT)
 tls10-prf-test$(EXEEXT): tls10-prf-test.$(OBJEXT)
 	$(LINK) tls10-prf-test.$(OBJEXT) $(TEST_OBJS) -o tls10-prf-test$(EXEEXT)
 
+tls12-prf-test$(EXEEXT): tls12-prf-test.$(OBJEXT)
+	$(LINK) tls12-prf-test.$(OBJEXT) $(TEST_OBJS) -o tls12-prf-test$(EXEEXT)
+
 sha1-test$(EXEEXT): sha1-test.$(OBJEXT)
 	$(LINK) sha1-test.$(OBJEXT) $(TEST_OBJS) -o sha1-test$(EXEEXT)
 
diff --git a/testsuite/Makefile.in b/testsuite/Makefile.in
index 9e85c9f..9344e7f 100644
--- a/testsuite/Makefile.in
+++ b/testsuite/Makefile.in
@@ -18,7 +18,7 @@ TS_NETTLE_SOURCES = aes-test.c arcfour-test.c arctwo-test.c \
 		    md2-test.c md4-test.c md5-test.c md5-compat-test.c \
 		    memeql-test.c memxor-test.c gosthash94-test.c \
 		    ripemd160-test.c \
-		    salsa20-test.c tls10-prf-test.c \
+		    salsa20-test.c tls10-prf-test.c tls12-prf-test.c \
 		    sha1-test.c sha224-test.c sha256-test.c \
 		    sha384-test.c sha512-test.c sha512-224-test.c sha512-256-test.c \
 		    sha3-permute-test.c sha3-224-test.c sha3-256-test.c \
diff --git a/testsuite/tls12-prf-test.c b/testsuite/tls12-prf-test.c
new file mode 100644
index 0000000..4744877
--- /dev/null
+++ b/testsuite/tls12-prf-test.c
@@ -0,0 +1,49 @@
+#include "testutils.h"
+#include "tls1-prf.h"
+#include "hmac.h"
+
+static
+void test_tls12_sha256_prf(const struct tstring *secret, const struct tstring *seed,
+	const struct tstring *label, const struct tstring *output)
+{
+	struct hmac_sha256_ctx ctx;
+	uint8_t *buffer = xalloc(output->length);
+
+	tls12_prf(&ctx, (nettle_hmac_set_key_func*)hmac_sha256_set_key,
+		  (nettle_hash_update_func*)hmac_sha256_update,
+		  (nettle_hash_digest_func*)hmac_sha256_digest, SHA256_DIGEST_SIZE,
+		  secret->length, secret->data, label->length, (char*)label->data,
+		  seed->length, seed->data, output->length, buffer);
+
+	if (MEMEQ(output->length, output->data, buffer) == 0) {
+		fprintf(stdout, "\nGot:\n");
+		print_hex(output->length, buffer);
+		fprintf(stdout, "\nExpected:\n");
+		print_hex(output->length, output->data);
+		abort();
+	}
+	free(buffer);
+}
+
+void
+test_main(void)
+{
+  /* TLS 1.2 SHA256-PRF vectors generated by _gnutls_prf_raw() */
+  test_tls12_sha256_prf(SHEX("0450b0ea9ecd3602ee0d76c5c3c86f4a"),
+  	SHEX("207acc0254b867f5b925b45a33601d8b"),
+  	SDATA("test label"), SHEX("ae679e0e714f5975763768b166979e1d"));
+
+  test_tls12_sha256_prf(SHEX("34204a9df0be6eb4e925a8027cf6c602"),
+  	SHEX("98b2c40bcd664c83bb920c18201a6395"),
+  	SDATA("test label"), SHEX("afa9312453c22fa83d2b511b372d73a402a2a62873239a51fade45082faf3fd2bb7ffb3e9bf36e28b3141aaba484005332a9f9e388a4d329f1587a4b317da07708ea1ba95a53f8786724bd83ce4b03af"));
+
+  test_tls12_sha256_prf(SHEX("a3691aa1f6814b80592bf1cf2acf1697"),
+  	SHEX("5523d41e320e694d0c1ff5734d830b933e46927071c92621"),
+  	SDATA("test label"), SHEX("6ad0984fa06f78fe161bd46d7c261de43340d728dddc3d0ff0dd7e0d"));
+
+  test_tls12_sha256_prf(SHEX("210ec937069707e5465bc46bf779e104108b18fdb793be7b218dbf145c8641f3"), SHEX("1e351a0baf35c79945924394b881cfe31dae8f1c1ed54d3b"),
+  	SDATA("test label"), SHEX("7653fa809cde3b553c4a17e2cdbcc918f36527f22219a7d7f95d97243ff2d5dee8265ef0af03"));
+
+
+}
+
diff --git a/tls1-prf.c b/tls1-prf.c
index f825b69..b986d09 100644
--- a/tls1-prf.c
+++ b/tls1-prf.c
@@ -149,3 +149,52 @@ tls10_prf(size_t secret_size, const uint8_t *secret,
 
 	return;
 }
+
+/*-
+ * tls12_prf:
+ * @mac_ctx: a MAC context
+ * @set_key: a MAC set key function
+ * @update: a MAC update function
+ * @digest: a MAC digest function
+ * @digest_size: the MAC output size
+ * @secret_size: the size of secret
+ * @secret: the secret data
+ * @label_size: the size of the label
+ * @label: the label to apply
+ * @seed_size: the seed size
+ * @seed: the seed
+ * @length: size of desired PRF output
+ * @dst: the location to store output
+ *
+ * The TLS 1.2 Pseudo-Random-Function (PRF).
+ *
+ * Returns: zero on failure, non zero on success.
+ -*/
+void
+tls12_prf(void *mac_ctx,
+	  nettle_hmac_set_key_func *set_key,
+	  nettle_hash_update_func *update,
+	  nettle_hash_digest_func *digest,
+	  size_t digest_size,
+	  size_t secret_size, const uint8_t *secret,
+	  size_t label_size, const char *label,
+	  size_t seed_size, const uint8_t *seed,
+	  size_t length, uint8_t *dst)
+{
+	size_t cseed_size;
+
+	TMP_DECL(cseed, uint8_t, MAX_SEED_SIZE);
+
+	/* label+seed = cseed */
+	cseed_size = seed_size + label_size;
+
+	TMP_ALLOC (cseed, cseed_size);
+
+	memcpy(cseed, label, label_size);
+	memcpy(&cseed[label_size], seed, seed_size);
+
+	P_hash(mac_ctx, set_key, update, digest, digest_size,
+		secret_size, secret, cseed_size, cseed, length, dst);
+
+	return;
+}
diff --git a/tls1-prf.h b/tls1-prf.h
index fdcef1d..69008cc 100644
--- a/tls1-prf.h
+++ b/tls1-prf.h
@@ -42,6 +42,7 @@ extern "C" {
 
 /* Namespace mangling */
 #define tls10_prf nettle_tls10_prf
+#define tls12_prf nettle_tls12_prf
 
 void
 tls10_prf(size_t secret_size, const uint8_t *secret,
@@ -49,6 +50,16 @@ tls10_prf(size_t secret_size, const uint8_t *secret,
 	  size_t seed_size, const uint8_t *seed,
 	  size_t length, uint8_t *dst);
 
+void
+tls12_prf(void *mac_ctx,
+	  nettle_hmac_set_key_func *set_key,
+	  nettle_hash_update_func *update,
+	  nettle_hash_digest_func *digest,
+	  size_t digest_size,
+	  size_t secret_size, const uint8_t *secret,
+	  size_t label_size, const char *label,
+	  size_t seed_size, const uint8_t *seed,
+	  size_t length, uint8_t *dst);
 
 #ifdef __cplusplus
 }
-- 
2.9.3

From 7f908ffbb7375a0f1da25c9f5f0affb58dcf5e7f Mon Sep 17 00:00:00 2001
From: Nikos Mavrogiannopoulos <[email protected]>
Date: Tue, 16 May 2017 12:57:12 +0200
Subject: [PATCH 4/6] Added the TLS 1.0 PRF and test vectors

Signed-off-by: Nikos Mavrogiannopoulos <[email protected]>
---
 Makefile.in                |   4 +-
 nettle-types.h             |   3 +
 testsuite/.test-rules.make |   3 +
 testsuite/Makefile.in      |   2 +-
 testsuite/tls10-prf-test.c |  42 +++++++++++++
 tls1-prf.c                 | 151 +++++++++++++++++++++++++++++++++++++++++++++
 tls1-prf.h                 |  57 +++++++++++++++++
 7 files changed, 259 insertions(+), 3 deletions(-)
 create mode 100644 testsuite/tls10-prf-test.c
 create mode 100644 tls1-prf.c
 create mode 100644 tls1-prf.h

diff --git a/Makefile.in b/Makefile.in
index 7e8f29c..5f07bee 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -106,7 +106,7 @@ nettle_SOURCES = aes-decrypt-internal.c aes-decrypt.c \
 		 gosthash94.c gosthash94-meta.c \
 		 hmac.c hmac-md5.c hmac-ripemd160.c hmac-sha1.c \
 		 hmac-sha224.c hmac-sha256.c hmac-sha384.c hmac-sha512.c \
-		 knuth-lfib.c \
+		 knuth-lfib.c tls1-prf.c \
 		 md2.c md2-meta.c md4.c md4-meta.c \
 		 md5.c md5-compress.c md5-compat.c md5-meta.c \
 		 memeql-sec.c memxor.c memxor3.c \
@@ -191,7 +191,7 @@ HEADERS = aes.h arcfour.h arctwo.h asn1.h blowfish.h \
 	  cbc.h ccm.h chacha.h chacha-poly1305.h ctr.h \
 	  curve25519.h des.h des-compat.h dsa.h dsa-compat.h eax.h \
 	  ecc-curve.h ecc.h ecdsa.h eddsa.h \
-	  gcm.h gosthash94.h hmac.h \
+	  gcm.h gosthash94.h hmac.h tls1-prf.h \
 	  knuth-lfib.h \
 	  macros.h \
 	  md2.h md4.h \
diff --git a/nettle-types.h b/nettle-types.h
index 475937d..32fb302 100644
--- a/nettle-types.h
+++ b/nettle-types.h
@@ -63,6 +63,9 @@ typedef void *nettle_realloc_func(void *ctx, void *p, size_t length);
 /* Ciphers */
 typedef void nettle_set_key_func(void *ctx, const uint8_t *key);
 
+/* MACs */
+typedef void nettle_hmac_set_key_func(void *ctx, size_t length, const uint8_t *key);
+
 /* For block ciphers, const context. */
 typedef void nettle_cipher_func(const void *ctx,
 				size_t length, uint8_t *dst,
diff --git a/testsuite/.test-rules.make b/testsuite/.test-rules.make
index 1b9c3fa..dbeb7a1 100644
--- a/testsuite/.test-rules.make
+++ b/testsuite/.test-rules.make
@@ -61,6 +61,9 @@ ripemd160-test$(EXEEXT): ripemd160-test.$(OBJEXT)
 salsa20-test$(EXEEXT): salsa20-test.$(OBJEXT)
 	$(LINK) salsa20-test.$(OBJEXT) $(TEST_OBJS) -o salsa20-test$(EXEEXT)
 
+tls10-prf-test$(EXEEXT): tls10-prf-test.$(OBJEXT)
+	$(LINK) tls10-prf-test.$(OBJEXT) $(TEST_OBJS) -o tls10-prf-test$(EXEEXT)
+
 sha1-test$(EXEEXT): sha1-test.$(OBJEXT)
 	$(LINK) sha1-test.$(OBJEXT) $(TEST_OBJS) -o sha1-test$(EXEEXT)
 
diff --git a/testsuite/Makefile.in b/testsuite/Makefile.in
index 590691c..9e85c9f 100644
--- a/testsuite/Makefile.in
+++ b/testsuite/Makefile.in
@@ -18,7 +18,7 @@ TS_NETTLE_SOURCES = aes-test.c arcfour-test.c arctwo-test.c \
 		    md2-test.c md4-test.c md5-test.c md5-compat-test.c \
 		    memeql-test.c memxor-test.c gosthash94-test.c \
 		    ripemd160-test.c \
-		    salsa20-test.c \
+		    salsa20-test.c tls10-prf-test.c \
 		    sha1-test.c sha224-test.c sha256-test.c \
 		    sha384-test.c sha512-test.c sha512-224-test.c sha512-256-test.c \
 		    sha3-permute-test.c sha3-224-test.c sha3-256-test.c \
diff --git a/testsuite/tls10-prf-test.c b/testsuite/tls10-prf-test.c
new file mode 100644
index 0000000..1d763ae
--- /dev/null
+++ b/testsuite/tls10-prf-test.c
@@ -0,0 +1,42 @@
+#include "testutils.h"
+#include "tls1-prf.h"
+
+static
+void test_tls10_prf(const struct tstring *secret, const struct tstring *seed,
+	const struct tstring *label, const struct tstring *output)
+{
+	uint8_t *buffer = xalloc(output->length);
+
+	tls10_prf(secret->length, secret->data, label->length, (char*)label->data,
+		  seed->length, seed->data, output->length, buffer);
+
+	if (MEMEQ(output->length, output->data, buffer) == 0) {
+		fprintf(stdout, "\nGot:\n");
+		print_hex(output->length, buffer);
+		fprintf(stdout, "\nExpected:\n");
+		print_hex(output->length, output->data);
+		abort();
+	}
+	free(buffer);
+}
+
+void
+test_main(void)
+{
+  /* TLS 1.0 PRF vectors generated by _gnutls_prf_raw() */
+  test_tls10_prf(SHEX("263bdbbb6f6d4c664e058d0aa9d321be"), SHEX("b920573b199601024f04d6dc61966e65"),
+  	SDATA("test label"), SHEX("6617993765fa6ca703d19ec70dd5dd160ffcc07725fafb714a9f815a2a30bfb7e3bbfb7eee574b3b613eb7fe80eec9691d8c1b0e2d9b3c8b4b02b6b6d6db88e2094623ef6240607eda7abe3c846e82a3"));
+
+  test_tls10_prf(SHEX("bf31fe6c78ebf0ff9ce8bb5dd9d1f83d"), SHEX("7fc4583d19871d962760f358a18696c8"),
+  	SDATA("test label"), SHEX("8318f382c49fd5af7d6fdb4cbb31dfef"));
+
+  test_tls10_prf(SHEX("0addfc84435b9ac1ef523ef44791a784bf55757dea17837c1a72beec1bdb1850"),
+  	SHEX("74e849d11ad8a98d9bc2291dbceec26ff9"),
+  	SDATA("test label"), SHEX("3c221520c48bcb3a0eb3734a"));
+
+  test_tls10_prf(SHEX("4074939b440a08a285bc7208485c531f0bbd4c101d71bdba33ec066791e4678c"),
+  	SHEX("8aff0c770c1d60455ee48f220c9adb471e5fee27c88c1f33"),
+  	SDATA("test label"), SHEX("3a9aee040bbf3cf7009210e64bbdad1775ccf1b46b3a965d5f15168e9ddaa7cc6a7c0c117848"));
+
+}
+
diff --git a/tls1-prf.c b/tls1-prf.c
new file mode 100644
index 0000000..f825b69
--- /dev/null
+++ b/tls1-prf.c
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2002-2017 Free Software Foundation, Inc.
+ * Copyright (C) 2014-2017 Nikos Mavrogiannopoulos
+ * Copyright (C) 2017 Red Hat, Inc.
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GnuTLS.
+ *
+ * The GnuTLS is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+/* Functions for the TLS PRF handling.
+ */
+
+#if HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <assert.h>
+/* Needed for alloca on freebsd */
+#include <stdlib.h>
+#include <string.h>
+
+#include "hmac.h"
+
+#include "memxor.h"
+#include "nettle-internal.h"
+#include "tls1-prf.h"
+#include "sha1.h"
+#include "md5.h"
+
+/* The RFC2246 P_hash() function.
+ */
+static void
+P_hash( void *mac_ctx,
+	nettle_hmac_set_key_func *set_key,
+	nettle_hash_update_func *update,
+	nettle_hash_digest_func *digest,
+	size_t digest_size,
+	size_t secret_size, const uint8_t *secret,
+	size_t seed_size, const uint8_t *seed,
+	size_t dst_length,
+	uint8_t *dst)
+{
+	uint8_t Atmp[NETTLE_MAX_HASH_DIGEST_SIZE];
+	ssize_t left;
+	unsigned started = 0;
+
+	/* round up */
+	left = dst_length;
+
+	while(left > 0) {
+		set_key(mac_ctx, secret_size, secret);
+		if (started == 0) { /* A(0) */
+			update(mac_ctx, seed_size, seed);
+			started = 1;
+		} else {
+			update(mac_ctx, digest_size, Atmp);
+		}
+		digest(mac_ctx, digest_size, Atmp); /* store A(i) */
+
+		set_key(mac_ctx, secret_size, secret);
+		update(mac_ctx, digest_size, Atmp); /* hash A(i) */
+		update(mac_ctx, seed_size, seed); /* hash seed */
+
+		if (left < (ssize_t)digest_size)
+			digest_size = left;
+
+		digest(mac_ctx, digest_size, dst);
+
+		left -= digest_size;
+		dst += digest_size;
+	}
+
+	return;
+}
+
+/*-
+ * tls10_prf:
+ * @secret_size: the size of secret
+ * @secret: the secret data
+ * @label_size: the size of the label
+ * @label: the label to apply
+ * @seed_size: the seed size
+ * @seed: the seed
+ * @length: size of desired PRF output
+ * @dst: the location to store output
+ *
+ * The TLS 1.0 Pseudo-Random-Function (PRF).
+ *
+ * Returns: zero on failure, non zero on success.
+ -*/
+void
+tls10_prf(size_t secret_size, const uint8_t *secret,
+	  size_t label_size, const char *label,
+	  size_t seed_size, const uint8_t *seed,
+	  size_t length, uint8_t *dst)
+{
+	int l_s, cseed_size;
+	const uint8_t *s1, *s2;
+	struct hmac_md5_ctx md5_ctx;
+	struct hmac_sha1_ctx sha1_ctx;
+
+	TMP_DECL(o1, uint8_t, MAX_PRF_BYTES);
+	TMP_DECL(cseed, uint8_t, MAX_SEED_SIZE);
+
+	/* label+seed = cseed */
+	cseed_size = seed_size + label_size;
+
+	TMP_ALLOC (o1, length);
+	TMP_ALLOC (cseed, cseed_size);
+
+	memcpy(cseed, label, label_size);
+	memcpy(&cseed[label_size], seed, seed_size);
+
+	l_s = secret_size / 2;
+	s1 = &secret[0];
+	s2 = &secret[l_s];
+	if (secret_size % 2 != 0) {
+		l_s++;
+	}
+
+	P_hash(&md5_ctx, (nettle_hmac_set_key_func*)hmac_md5_set_key,
+		(nettle_hash_update_func*)hmac_md5_update,
+		(nettle_hash_digest_func*)hmac_md5_digest,
+		MD5_DIGEST_SIZE,
+		l_s, s1, cseed_size, cseed, length, o1);
+
+	P_hash(&sha1_ctx, (nettle_hmac_set_key_func*)hmac_sha1_set_key,
+		(nettle_hash_update_func*)hmac_sha1_update,
+		(nettle_hash_digest_func*)hmac_sha1_digest,
+		SHA1_DIGEST_SIZE,
+		l_s, s2, cseed_size, cseed, length, dst);
+
+	memxor(dst, o1, length);
+
+	return;
+}
diff --git a/tls1-prf.h b/tls1-prf.h
new file mode 100644
index 0000000..fdcef1d
--- /dev/null
+++ b/tls1-prf.h
@@ -0,0 +1,57 @@
+/* hmac.h
+
+   TLS PRF code (RFC-5246, RFC-2246).
+
+   Copyright (C) 2017 Nikos Mavrogiannopoulos
+
+   This file is part of GNU Nettle.
+
+   GNU Nettle is free software: you can redistribute it and/or
+   modify it under the terms of either:
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at your
+       option) any later version.
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at your
+       option) any later version.
+
+   or both in parallel, as here.
+
+   GNU Nettle is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see http://www.gnu.org/licenses/.
+*/
+
+#ifndef NETTLE_PRF_H_INCLUDED
+#define NETTLE_PRF_H_INCLUDED
+
+#include "nettle-meta.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Namespace mangling */
+#define tls10_prf nettle_tls10_prf
+
+void
+tls10_prf(size_t secret_size, const uint8_t *secret,
+	  size_t label_size, const char *label,
+	  size_t seed_size, const uint8_t *seed,
+	  size_t length, uint8_t *dst);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* NETTLE_PRF_H_INCLUDED */
-- 
2.9.3

From 6b0197a8f031891ec70309d710038eea96daa64c Mon Sep 17 00:00:00 2001
From: Nikos Mavrogiannopoulos <[email protected]>
Date: Tue, 16 May 2017 13:23:13 +0200
Subject: [PATCH 3/6] .gitlab-ci.yml: use asan from fedora25 instead of centos7

The former provides a much newer version.

Signed-off-by: Nikos Mavrogiannopoulos <[email protected]>
---
 .gitlab-ci.yml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index e1b71ad..6fa9898 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -45,6 +45,7 @@ Build and Check with ubsan:
   except:
   - tags
 Build and Check with asan:
+  image: fedora:25
   script:
   - yum install -y gmp-devel
   - ./.bootstrap && 
-- 
2.9.3

From bfc9b0fee5360b5a1403663c132121862a42571c Mon Sep 17 00:00:00 2001
From: Nikos Mavrogiannopoulos <[email protected]>
Date: Tue, 16 May 2017 13:14:46 +0200
Subject: [PATCH 2/6] .gitlab-ci.yml: ubsan use fedora25

---
 .gitlab-ci.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index f839416..e1b71ad 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -34,7 +34,7 @@ Build and Check with mini-gmp:
   except:
   - tags
 Build and Check with ubsan:
-  image: fedora:24
+  image: fedora:25
   script:
   - yum install -y gmp-devel libubsan-static libubsan
   - ./.bootstrap && 
-- 
2.9.3

From a04030028dbf9a9f22470ceb6e956907dd93e424 Mon Sep 17 00:00:00 2001
From: Nikos Mavrogiannopoulos <[email protected]>
Date: Tue, 16 May 2017 11:40:08 +0200
Subject: [PATCH 1/6] .bootstrap: delete the .test-rules.make

Delete this obscure file when .bootstrap is run. This is a file with
build rules that prevents modifying the testsuite/Makefile.in
without rewriting it. It always gets me spending hours prior to
understanding that this needs to be deleted.

Signed-off-by: Nikos Mavrogiannopoulos <[email protected]>
---
 .bootstrap | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/.bootstrap b/.bootstrap
index d85e2e2..94c7132 100755
--- a/.bootstrap
+++ b/.bootstrap
@@ -1,3 +1,7 @@
 #! /bin/sh
 
 autoconf && autoheader
+
+echo "************************************************************************"
+echo "You need to run 'make test-rules' after modifying anything in testsuite/"
+echo "************************************************************************"
-- 
2.9.3

_______________________________________________
nettle-bugs mailing list
[email protected]
http://lists.lysator.liu.se/mailman/listinfo/nettle-bugs

Reply via email to