diff --git a/.gitignore b/.gitignore
index 85138a9..190b97a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,2 @@
-SOURCES/gnutls-3.6.5.tar.xz
+SOURCES/gnutls-3.6.8.tar.xz
 SOURCES/gpgkey-1F42418905D8206AA754CCDC29EE58B996865171.gpg
diff --git a/.gnutls.metadata b/.gnutls.metadata
index b18298d..af466d6 100644
--- a/.gnutls.metadata
+++ b/.gnutls.metadata
@@ -1,2 +1,2 @@
-749fcaba23f63b523ec2ad262caeca6f1e62fc6f SOURCES/gnutls-3.6.5.tar.xz
+e1243188791af409bca118d31faf3ec3d5f0a5ab SOURCES/gnutls-3.6.8.tar.xz
 e6f8a1400839ce7b4021cdd0f8d08d71b0693486 SOURCES/gpgkey-1F42418905D8206AA754CCDC29EE58B996865171.gpg
diff --git a/SOURCES/gnutls-3.6.4-no-now-guile.patch b/SOURCES/gnutls-3.6.4-no-now-guile.patch
index d4edff0..1da536b 100644
--- a/SOURCES/gnutls-3.6.4-no-now-guile.patch
+++ b/SOURCES/gnutls-3.6.4-no-now-guile.patch
@@ -1,11 +1,11 @@
 diff --git a/guile/src/Makefile.in b/guile/src/Makefile.in
-index 3e4f547..6ffec0e 100644
+index 95e1e9c..1dfc88e 100644
 --- a/guile/src/Makefile.in
 +++ b/guile/src/Makefile.in
-@@ -1430,7 +1430,7 @@ guileextension_LTLIBRARIES = guile-gnutls-v-2.la
+@@ -1483,7 +1483,7 @@ guileextension_LTLIBRARIES = guile-gnutls-v-2.la
  # Use '-module' to build a "dlopenable module", in Libtool terms.
  # Use '-undefined' to placate Libtool on Windows; see
- # <http://lists.gnutls.org/pipermail/gnutls-devel/2014-December/007294.html>.
+ # <https://lists.gnutls.org/pipermail/gnutls-devel/2014-December/007294.html>.
 -guile_gnutls_v_2_la_LDFLAGS = -module -no-undefined
 +guile_gnutls_v_2_la_LDFLAGS = -module -no-undefined -Wl,-z,lazy
  
diff --git a/SOURCES/gnutls-3.6.5-fix-fips-self-tests.patch b/SOURCES/gnutls-3.6.5-fix-fips-self-tests.patch
deleted file mode 100644
index ff0d105..0000000
--- a/SOURCES/gnutls-3.6.5-fix-fips-self-tests.patch
+++ /dev/null
@@ -1,68 +0,0 @@
-From ccf8343aedd49b1250bee761f5c1ba8465b7dadb Mon Sep 17 00:00:00 2001
-From: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
-Date: Thu, 10 Jan 2019 14:04:02 +0100
-Subject: [PATCH 1/2] fips140: Fix the names of files used in integrity checks
-
-The names of the libraries haven't been updated when the soname version
-were bumped.
-
-Signed-off-by: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
----
- lib/fips.c | 6 +++---
- 1 file changed, 3 insertions(+), 3 deletions(-)
-
-diff --git a/lib/fips.c b/lib/fips.c
-index 2715af599..fb2d596c2 100644
---- a/lib/fips.c
-+++ b/lib/fips.c
-@@ -135,9 +135,9 @@ void _gnutls_fips_mode_reset_zombie(void)
- 	}
- }
- 
--#define GNUTLS_LIBRARY_NAME "libgnutls.so.28"
--#define NETTLE_LIBRARY_NAME "libnettle.so.4"
--#define HOGWEED_LIBRARY_NAME "libhogweed.so.2"
-+#define GNUTLS_LIBRARY_NAME "libgnutls.so.30"
-+#define NETTLE_LIBRARY_NAME "libnettle.so.6"
-+#define HOGWEED_LIBRARY_NAME "libhogweed.so.4"
- #define GMP_LIBRARY_NAME "libgmp.so.10"
- 
- #define HMAC_SUFFIX ".hmac"
--- 
-2.20.1
-
-
-From 8bac499469af3fb39a5ad59f1defe9f3824d5119 Mon Sep 17 00:00:00 2001
-From: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
-Date: Fri, 11 Jan 2019 11:23:21 +0100
-Subject: [PATCH 2/2] fips140: Ignore newlines read at the end of HMAC file
-
-This makes the integrity check to ignore newlines appended after the
-HMAC value.
-
-Signed-off-by: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
----
- lib/fips.c | 7 +++++++
- 1 file changed, 7 insertions(+)
-
-diff --git a/lib/fips.c b/lib/fips.c
-index fb2d596c2..0169ab171 100644
---- a/lib/fips.c
-+++ b/lib/fips.c
-@@ -250,6 +250,13 @@ static unsigned check_binary_integrity(const char* libname, const char* symbol)
- 	}
- 
- 	hmac_size = hex_data_size(data.size);
-+
-+	/* trim eventual newlines from the end of the data read from file */
-+	while ((data.size > 0) && (data.data[data.size - 1] == '\n')) {
-+		data.data[data.size - 1] = 0;
-+		data.size--;
-+	}
-+
- 	ret = gnutls_hex_decode(&data, hmac, &hmac_size);
- 	gnutls_free(data.data);
- 
--- 
-2.20.1
-
diff --git a/SOURCES/gnutls-3.6.5-fix-fips-signature-post.patch b/SOURCES/gnutls-3.6.5-fix-fips-signature-post.patch
new file mode 100644
index 0000000..ce51cad
--- /dev/null
+++ b/SOURCES/gnutls-3.6.5-fix-fips-signature-post.patch
@@ -0,0 +1,728 @@
+From 2c44e9f8b2e7a1ebc65caeb03f9f106d31e30822 Mon Sep 17 00:00:00 2001
+From: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
+Date: Wed, 3 Apr 2019 13:40:04 +0200
+Subject: [PATCH 1/7] crypto-selftests-pk.c: Move hardcoded values to the top
+
+The objective of moving these values to the top is to allow them to be
+used by other functions, in particular test_sig().
+
+Signed-off-by: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
+---
+ lib/crypto-selftests-pk.c | 224 +++++++++++++++++++-------------------
+ 1 file changed, 112 insertions(+), 112 deletions(-)
+
+diff --git a/lib/crypto-selftests-pk.c b/lib/crypto-selftests-pk.c
+index 1aa53ea29..4fadd4161 100644
+--- a/lib/crypto-selftests-pk.c
++++ b/lib/crypto-selftests-pk.c
+@@ -107,6 +107,118 @@ static const char gost12_512_key[] =
+  "KjL7CLBERDm7Yvlv\n"
+  "-----END PRIVATE KEY-----\n";
+ 
++/* A precomputed RSA-SHA256 signature using the rsa_key2048 */
++static const char rsa_sig[] =
++    "\x7a\xb3\xf8\xb0\xf9\xf0\x52\x88\x37\x17\x97\x9f\xbe\x61\xb4\xd2\x43\x78\x9f\x79\x92\xd0\xad\x08\xdb\xbd\x3c\x72\x7a\xb5\x51\x59\x63\xd6\x7d\xf1\x9c\x1e\x10\x7b\x27\xab\xf8\xd4\x9d\xcd\xc5\xf9\xae\xf7\x09\x6b\x40\x93\xc5\xe9\x1c\x0f\xb4\x82\xa1\x47\x86\x54\x63\xd2\x4d\x40\x9a\x80\xb9\x38\x45\x69\xa2\xd6\x92\xb6\x69\x7f\x3f\xf3\x5b\xa5\x1d\xac\x06\xad\xdf\x4e\xbb\xe6\xda\x68\x0d\xe5\xab\xef\xd2\xf0\xc5\xd8\xc0\xed\x80\xe2\xd4\x76\x98\xec\x44\xa2\xfc\x3f\xce\x2e\x8b\xc4\x4b\xab\xb0\x70\x24\x52\x85\x2a\x36\xcd\x9a\xb5\x05\x00\xea\x98\x7c\x72\x06\x68\xb1\x38\x44\x16\x80\x6a\x3b\x64\x72\xbb\xfd\x4b\xc9\xdd\xda\x2a\x68\xde\x7f\x6e\x48\x28\xc1\x63\x57\x2b\xde\x83\xa3\x27\x34\xd7\xa6\x87\x18\x35\x10\xff\x31\xd9\x47\xc9\x84\x35\xe1\xaa\xe2\xf7\x98\xfa\x19\xd3\xf1\x94\x25\x2a\x96\xe4\xa8\xa7\x05\x10\x93\x87\xde\x96\x85\xe5\x68\xb8\xe5\x4e\xbf\x66\x85\x91\xbd\x52\x5b\x3d\x9f\x1b\x79\xea\xe3\x8b\xef\x62\x18\x39\x7a\x50\x01\x46\x1b\xde\x8d\x37\xbc\x90\x6c\x07\xc0\x07\xed\x60\xce\x2e\x31\xd6\x8f\xe8\x75\xdb\x45\x21\xc6\xcb";
++
++/* ECDSA key and signature */
++static const char ecdsa_secp256r1_privkey[] =
++    "-----BEGIN EC PRIVATE KEY-----\n"
++    "MHcCAQEEIPAKWV7+pZe9c5EubMNfAEKWRQtP/MvlO9HehwHmJssNoAoGCCqGSM49\n"
++    "AwEHoUQDQgAE2CNONRio3ciuXtoomJKs3MdbzLbd44VPhtzJN30VLFm5gvnfiCj2\n"
++    "zzz7pl9Cv0ECHl6yedNI8QEKdcwCDgEmkQ==\n"
++    "-----END EC PRIVATE KEY-----\n";
++
++static const char ecdsa_secp256r1_sig[] =
++    "\x30\x45\x02\x21\x00\x9b\x8f\x60\xed\x9e\x40\x8d\x74\x82\x73\xab\x20\x1a\x69\xfc\xf9\xee\x3c\x41\x80\xc0\x39\xdd\x21\x1a\x64\xfd\xbf\x7e\xaa\x43\x70\x02\x20\x44\x28\x05\xdd\x30\x47\x58\x96\x18\x39\x94\x18\xba\xe7\x7a\xf6\x1e\x2d\xba\xb1\xe0\x7d\x73\x9e\x2f\x58\xee\x0c\x2a\x89\xe8\x35";
++
++#ifdef ENABLE_NON_SUITEB_CURVES
++/* sha256 */
++static const char ecdsa_secp192r1_privkey[] =
++    "-----BEGIN EC PRIVATE KEY-----"
++    "MF8CAQEEGLjezFcbgDMeApVrdtZHvu/k1a8/tVZ41KAKBggqhkjOPQMBAaE0AzIA"
++    "BO1lciKdgxeRH8k64vxcaV1OYIK9akVrW02Dw21MXhRLP0l0wzCw6LGSr5rS6AaL"
++    "Fg==" "-----END EC PRIVATE KEY-----";
++
++static const char ecdsa_secp192r1_sig[] =
++    "\x30\x34\x02\x18\x5f\xb3\x10\x4b\x4d\x44\x48\x29\x4b\xfd\xa7\x8e\xce\x57\xac\x36\x38\x54\xab\x73\xdb\xed\xb8\x5f\x02\x18\x0b\x8b\xf3\xae\x49\x50\x0e\x47\xca\x89\x1a\x00\xca\x23\xf5\x8d\xd6\xe3\xce\x9a\xff\x2e\x4f\x5c";
++
++static const char ecdsa_secp224r1_privkey[] =
++    "-----BEGIN EC PRIVATE KEY-----"
++    "MGgCAQEEHOKWJFdWdrR/CgVrUeTeawOrJ9GozE9KKx2a8PmgBwYFK4EEACGhPAM6"
++    "AAQKQj3YpenWT7lFR41SnBvmj/+Bj+kgzQnaF65qWAtPRJsZXFlLTu3/IUNqSRu9"
++    "DqPsk8xBHAB7pA==" "-----END EC PRIVATE KEY-----";
++
++static const char ecdsa_secp224r1_sig[] =
++    "\x30\x3d\x02\x1c\x76\x03\x8d\x74\xf4\xd3\x09\x2a\xb5\xdf\x6b\x5b\xf4\x4b\x86\xb8\x62\x81\x5d\x7b\x7a\xbb\x37\xfc\xf1\x46\x1c\x2b\x02\x1d\x00\xa0\x98\x5d\x80\x43\x89\xe5\xee\x1a\xec\x46\x08\x04\x55\xbc\x50\xfa\x2a\xd5\xa6\x18\x92\x19\xdb\x68\xa0\x2a\xda";
++#endif
++
++static const char ecdsa_secp384r1_privkey[] =
++    "-----BEGIN EC PRIVATE KEY-----"
++    "MIGkAgEBBDDevshD6gb+4rZpC9vwFcIwNs4KmGzdqCxyyN40a8uOWRbyf7aHdiSS"
++    "03oAyKtc4JCgBwYFK4EEACKhZANiAARO1KkPMno2tnNXx1S9EZkp8SOpDCZ4aobH"
++    "IYv8RHnSmKf8I3OKD6TaoeR+1MwJmNJUH90Bj45WXla68/vsPiFcfVKboxsZYe/n"
++    "pv8e4ugXagVQVBXNZJ859iYPdJR24vo=" "-----END EC PRIVATE KEY-----";
++
++static const char ecdsa_secp384r1_sig[] =
++    "\x30\x66\x02\x31\x00\xbb\x4d\x25\x30\x13\x1b\x3b\x75\x60\x07\xed\x53\x8b\x52\xee\xd8\x6e\xf1\x9d\xa8\x36\x0e\x2e\x20\x31\x51\x11\x48\x78\xdd\xaf\x24\x38\x64\x81\x71\x6b\xa6\xb7\x29\x58\x28\x82\x32\xba\x29\x29\xd9\x02\x31\x00\xeb\x70\x09\x87\xac\x7b\x78\x0d\x4c\x4f\x08\x2b\x86\x27\xe2\x60\x1f\xc9\x11\x9f\x1d\xf5\x82\x4c\xc7\x3d\xb0\x27\xc8\x93\x29\xc7\xd0\x0e\x88\x02\x09\x93\xc2\x72\xce\xa5\x74\x8c\x3d\xe0\x8c\xad";
++
++static const char ecdsa_secp521r1_privkey[] =
++    "-----BEGIN EC PRIVATE KEY-----"
++    "MIHbAgEBBEGO2n7NN363qSCvJVdlQtCvudtaW4o0fEufXRjE1AsCrle+VXX0Zh0w"
++    "Y1slSeDHMndpakoiF+XkQ+bhcB867UV6aKAHBgUrgQQAI6GBiQOBhgAEAQb6jDpo"
++    "byy1tF8Zucg0TMGUzIN2DK+RZJ3QQRdWdirO25OIC3FoFi1Yird6rpoB6HlNyJ7R"
++    "0bNG9Uv34bSHMn8yAFoiqxUCdJZQbEenMoZsi6COaePe3e0QqvDMr0hEWT23Sr3t"
++    "LpEV7eZGFfFIJw5wSUp2KOcs+O9WjmoukTWtDKNV"
++    "-----END EC PRIVATE KEY-----";
++
++static const char ecdsa_secp521r1_sig[] =
++    "\x30\x81\x87\x02\x42\x01\xb8\xcb\x52\x9e\x10\xa8\x49\x3f\xe1\x9e\x14\x0a\xcf\x96\xed\x7e\xab\x7d\x0c\xe1\x9b\xa4\x97\xdf\x01\xf5\x35\x42\x5f\x5b\x28\x15\x24\x33\x6e\x59\x6c\xaf\x10\x8b\x98\x8e\xe9\x4c\x23\x0d\x76\x92\x03\xdd\x6d\x8d\x08\x47\x15\x5b\xf8\x66\x75\x75\x40\xe8\xf4\xa0\x52\x02\x41\x15\x27\x7c\x5f\xa6\x33\xa6\x29\x68\x3f\x55\x8d\x7f\x1d\x4f\x88\xc6\x61\x6e\xac\x21\xdf\x2b\x7b\xde\x76\x9a\xdc\xe6\x3b\x94\x3f\x03\x9c\xa2\xa6\xa3\x63\x39\x48\xbd\x79\x70\x21\xf2\x6b\xff\x58\x66\xf1\x58\xc2\x58\xad\x4f\x84\x14\x5d\x05\x12\x83\xd0\x87\xbd\xf3";
++
++/* DSA key and signature */
++static const char dsa_privkey[] =
++ "-----BEGIN DSA PRIVATE KEY-----\n"
++ "MIIDTQIBAAKCAQEAh60B6yPMRIT7udq2kKuwnQDohvT1U0w+RJcSr23C05cM/Ovn\n"
++ "UP/8Rrj6T8K+uYhMbKgLaZiJJW9q04jaPQk0cfUphbLvRjzVHwE/0Bkb+Y1Rv7ni\n"
++ "Jot2IFMq5iuNraf889PC0WREvFCcIkSFY2Ac4WT7mCcBtfx/raGFXDUjcUrJ0HwZ\n"
++ "IOhjQDfcXUsztuyYsYA75ociEY8kyDZq/ixyr5++R1VjNf30Re8AbQlXOEGxEN5t\n"
++ "t+Tvpq8K5L3prQs2KNSzyOUmedjb/ojH4T4qe/RL9EVjjeuIGHDNUT6F197yZ91y\n"
++ "qLLTf1WjnUyZcKij5rryX0LJBBWawEZjNSHZawIdAMQlyycia4NigCdiDR+QptUn\n"
++ "2xrj9o14fXkIrXcCggEAXRZm1rbPhsjSTo6cpCVrmDzO1grv83EHiBH4MvRQQnP8\n"
++ "FpAREsBA5cYju97XvLaLhioZeMjLn08kU7TUbHRUB+ULTuVvE2dQbBpGuKiLRRt9\n"
++ "6U2T0eD3xGLoM+o8EY/kpqaWGEpZv7hzM9xuo4vy55+viAZgFWULqmltwfG/7w7V\n"
++ "NXUHNv5H4Ipw//fSDLTPqzUlNqSSswDLz6pCjWEs0rWAqNAMaOiLTz4id9pL48Oe\n"
++ "oAfpcQR9tgTEnwyXfZBnrJVclHhkHKGeXvU05IgCzpKO76Z5R+By50T0i/JV7vzM\n"
++ "l2yS9aAl/cprT6U7yI3oU/blldCVNpMcFAFb+fO8DAKCAQBVMo8xptyvQOJeSvbO\n"
++ "SSYdJ3IiI/0GdkcGWXblWg9z7mrPaWEnT7OquEm/+vYtWd3GHDtyNM+jzsN4Xgjc\n"
++ "TL3AEd2hLiozJQ1BFKw25VU08UHAYTzUxZhO4Vwtmp46Kwj8YLDQ3NHRWCBxpDQR\n"
++ "fbiFvyXP+qXap6plMfrydnUD1mae/JSOWOYgdB7tFIehstLxVXx/cAnjwgFU03Df\n"
++ "grjsad92zA1Hc9wIjbsgAQdTR5DWnFRkRt3UtayBwoyqm6QceZHsv1NAGvkQ4ion\n"
++ "bEjkHkjF9YCkR9/rspR8cLghRIXMjOpypuSbaRPeeWq0gP2UOxFL/d3iWH0ETr/L\n"
++ "kTlCAhxYGpVgtfB96qmJukyl9GOGvfkwFTgEyIDoV84M\n"
++ "-----END DSA PRIVATE KEY-----\n";
++
++static const char dsa_sig[] =
++    "\x30\x3d\x02\x1c\x2e\x40\x14\xb3\x7a\x3f\xc0\x4f\x06\x74\x4f\xa6\x5f\xc2\x0a\x46\x35\x38\x88\xb4\x1a\xcf\x94\x02\x40\x42\x7c\x7f\x02\x1d\x00\x98\xfc\xf1\x08\x66\xf1\x86\x28\xc9\x73\x9e\x2b\x5d\xce\x57\xe8\xb5\xeb\xcf\xa3\xf6\x60\xf6\x63\x16\x0e\xc0\x42";
++
++static const char gost01_privkey[] =
++ "-----BEGIN PRIVATE KEY-----\n"
++ "MEUCAQAwHAYGKoUDAgITMBIGByqFAwICIwEGByqFAwICHgEEIgQgdNfuHGmmTdPm\n"
++ "p5dAa3ea9UYxpdYQPP9lbDwzQwG2bJM=\n"
++ "-----END PRIVATE KEY-----\n";
++
++static const char gost01_sig[] =
++    "\xc5\xc8\xf8\xdc\x22\x51\xb0\x72\xe9\xa2\xbb\x84\x6c\xe2\x24\xd5\x72\x39\x2a\x5a\x0e\x7a\x43\xfc\x9c\xc3\x5d\x32\x92\xbb\xab\xc0\x4b\x99\xbd\xc8\x47\x24\x70\x06\x7e\xa1\xc6\xe3\xa0\xdc\x42\xed\xa0\x66\xf0\xcc\x50\x97\xe9\x5a\x7d\x3f\x65\x2d\x7b\x1b\x03\xcb";
++
++static const char gost12_256_privkey[] =
++ "-----BEGIN PRIVATE KEY-----\n"
++ "MEgCAQAwHwYIKoUDBwEBAQEwEwYHKoUDAgIjAQYIKoUDBwEBAgIEIgQgKOF96tom\n"
++ "D61rhSnzKjyrmO3fv0gdlHei+6ovrc8SnBk=\n"
++ "-----END PRIVATE KEY-----\n";
++
++static const char gost12_256_sig[] =
++    "\xb2\x51\x5a\x1a\xbd\x95\x4e\x71\x55\xad\x74\x74\x81\xa6\xca\x6c\x14\x01\xe0\x18\xda\xe4\x0d\x02\x4f\x14\xd2\x39\xd6\x3c\xb5\x85\xa8\x37\xfd\x7f\x2b\xfa\xe4\xf5\xbc\xbc\x15\x20\x8b\x83\x4b\x84\x0d\x5d\x02\x21\x8c\x0d\xb9\xc4\x2b\xc0\x3e\xfd\x42\x55\x1d\xb0";
++
++static const char gost12_512_privkey[] =
++ "-----BEGIN PRIVATE KEY-----\n"
++ "MGoCAQAwIQYIKoUDBwEBAQIwFQYJKoUDBwECAQIBBggqhQMHAQECAwRCBECjFpvp\n"
++ "B0vdc7u59b99TCNXhHiB69JJtUjvieNkGYJpoaaIvoKZTNCjpSZASsZcQZCHOTof\n"
++ "hsQ3JCCy4xnd5jWT\n"
++ "-----END PRIVATE KEY-----\n";
++
++static const char gost12_512_sig[] =
++    "\x52\x4f\xa2\x77\x51\xd2\xc5\xef\xd3\xa3\x99\x4e\xec\xff\xc6\xe9\xfc\x2f\xc0\x28\x42\x03\x95\x6c\x9a\x38\xee\xea\x89\x79\xae\x1a\xc3\x68\x5e\xe4\x15\x15\x4b\xec\x0f\xf1\x7e\x0f\xba\x01\xc7\x84\x16\xc7\xb5\xac\x9d\x0c\x22\xdd\x31\xf7\xb0\x9b\x59\x4b\xf0\x02\xa8\x7d\xfd\x6d\x02\x43\xc7\x4f\x65\xbd\x84\x5c\x54\x91\xba\x75\x9f\x5a\x61\x19\x5c\x9a\x10\x78\x34\xa0\xa6\xf6\xdc\xb6\xb0\x50\x22\x38\x5f\xb0\x16\x66\xf1\xd5\x46\x00\xd5\xe2\xa8\xe5\xd2\x11\x5f\xd1\xbe\x6e\xac\xb2\x9c\x14\x34\x96\xe7\x58\x94\xb8\xf4\x5f";
++
+ static int test_rsa_enc(gnutls_pk_algorithm_t pk,
+ 			unsigned bits, gnutls_digest_algorithm_t ign)
+ {
+@@ -302,118 +414,6 @@ static int test_sig(gnutls_pk_algorithm_t pk,
+ 	return ret;
+ }
+ 
+-/* A precomputed RSA-SHA1 signature using the rsa_key2048 */
+-static const char rsa_sig[] =
+-    "\x7a\xb3\xf8\xb0\xf9\xf0\x52\x88\x37\x17\x97\x9f\xbe\x61\xb4\xd2\x43\x78\x9f\x79\x92\xd0\xad\x08\xdb\xbd\x3c\x72\x7a\xb5\x51\x59\x63\xd6\x7d\xf1\x9c\x1e\x10\x7b\x27\xab\xf8\xd4\x9d\xcd\xc5\xf9\xae\xf7\x09\x6b\x40\x93\xc5\xe9\x1c\x0f\xb4\x82\xa1\x47\x86\x54\x63\xd2\x4d\x40\x9a\x80\xb9\x38\x45\x69\xa2\xd6\x92\xb6\x69\x7f\x3f\xf3\x5b\xa5\x1d\xac\x06\xad\xdf\x4e\xbb\xe6\xda\x68\x0d\xe5\xab\xef\xd2\xf0\xc5\xd8\xc0\xed\x80\xe2\xd4\x76\x98\xec\x44\xa2\xfc\x3f\xce\x2e\x8b\xc4\x4b\xab\xb0\x70\x24\x52\x85\x2a\x36\xcd\x9a\xb5\x05\x00\xea\x98\x7c\x72\x06\x68\xb1\x38\x44\x16\x80\x6a\x3b\x64\x72\xbb\xfd\x4b\xc9\xdd\xda\x2a\x68\xde\x7f\x6e\x48\x28\xc1\x63\x57\x2b\xde\x83\xa3\x27\x34\xd7\xa6\x87\x18\x35\x10\xff\x31\xd9\x47\xc9\x84\x35\xe1\xaa\xe2\xf7\x98\xfa\x19\xd3\xf1\x94\x25\x2a\x96\xe4\xa8\xa7\x05\x10\x93\x87\xde\x96\x85\xe5\x68\xb8\xe5\x4e\xbf\x66\x85\x91\xbd\x52\x5b\x3d\x9f\x1b\x79\xea\xe3\x8b\xef\x62\x18\x39\x7a\x50\x01\x46\x1b\xde\x8d\x37\xbc\x90\x6c\x07\xc0\x07\xed\x60\xce\x2e\x31\xd6\x8f\xe8\x75\xdb\x45\x21\xc6\xcb";
+-
+-/* ECDSA key and signature */
+-static const char ecdsa_secp256r1_privkey[] =
+-    "-----BEGIN EC PRIVATE KEY-----\n"
+-    "MHcCAQEEIPAKWV7+pZe9c5EubMNfAEKWRQtP/MvlO9HehwHmJssNoAoGCCqGSM49\n"
+-    "AwEHoUQDQgAE2CNONRio3ciuXtoomJKs3MdbzLbd44VPhtzJN30VLFm5gvnfiCj2\n"
+-    "zzz7pl9Cv0ECHl6yedNI8QEKdcwCDgEmkQ==\n"
+-    "-----END EC PRIVATE KEY-----\n";
+-
+-static const char ecdsa_secp256r1_sig[] =
+-    "\x30\x45\x02\x21\x00\x9b\x8f\x60\xed\x9e\x40\x8d\x74\x82\x73\xab\x20\x1a\x69\xfc\xf9\xee\x3c\x41\x80\xc0\x39\xdd\x21\x1a\x64\xfd\xbf\x7e\xaa\x43\x70\x02\x20\x44\x28\x05\xdd\x30\x47\x58\x96\x18\x39\x94\x18\xba\xe7\x7a\xf6\x1e\x2d\xba\xb1\xe0\x7d\x73\x9e\x2f\x58\xee\x0c\x2a\x89\xe8\x35";
+-
+-#ifdef ENABLE_NON_SUITEB_CURVES
+-/* sha256 */
+-static const char ecdsa_secp192r1_privkey[] =
+-    "-----BEGIN EC PRIVATE KEY-----"
+-    "MF8CAQEEGLjezFcbgDMeApVrdtZHvu/k1a8/tVZ41KAKBggqhkjOPQMBAaE0AzIA"
+-    "BO1lciKdgxeRH8k64vxcaV1OYIK9akVrW02Dw21MXhRLP0l0wzCw6LGSr5rS6AaL"
+-    "Fg==" "-----END EC PRIVATE KEY-----";
+-
+-static const char ecdsa_secp192r1_sig[] =
+-    "\x30\x34\x02\x18\x5f\xb3\x10\x4b\x4d\x44\x48\x29\x4b\xfd\xa7\x8e\xce\x57\xac\x36\x38\x54\xab\x73\xdb\xed\xb8\x5f\x02\x18\x0b\x8b\xf3\xae\x49\x50\x0e\x47\xca\x89\x1a\x00\xca\x23\xf5\x8d\xd6\xe3\xce\x9a\xff\x2e\x4f\x5c";
+-
+-static const char ecdsa_secp224r1_privkey[] =
+-    "-----BEGIN EC PRIVATE KEY-----"
+-    "MGgCAQEEHOKWJFdWdrR/CgVrUeTeawOrJ9GozE9KKx2a8PmgBwYFK4EEACGhPAM6"
+-    "AAQKQj3YpenWT7lFR41SnBvmj/+Bj+kgzQnaF65qWAtPRJsZXFlLTu3/IUNqSRu9"
+-    "DqPsk8xBHAB7pA==" "-----END EC PRIVATE KEY-----";
+-
+-static const char ecdsa_secp224r1_sig[] =
+-    "\x30\x3d\x02\x1c\x76\x03\x8d\x74\xf4\xd3\x09\x2a\xb5\xdf\x6b\x5b\xf4\x4b\x86\xb8\x62\x81\x5d\x7b\x7a\xbb\x37\xfc\xf1\x46\x1c\x2b\x02\x1d\x00\xa0\x98\x5d\x80\x43\x89\xe5\xee\x1a\xec\x46\x08\x04\x55\xbc\x50\xfa\x2a\xd5\xa6\x18\x92\x19\xdb\x68\xa0\x2a\xda";
+-#endif
+-
+-static const char ecdsa_secp384r1_privkey[] =
+-    "-----BEGIN EC PRIVATE KEY-----"
+-    "MIGkAgEBBDDevshD6gb+4rZpC9vwFcIwNs4KmGzdqCxyyN40a8uOWRbyf7aHdiSS"
+-    "03oAyKtc4JCgBwYFK4EEACKhZANiAARO1KkPMno2tnNXx1S9EZkp8SOpDCZ4aobH"
+-    "IYv8RHnSmKf8I3OKD6TaoeR+1MwJmNJUH90Bj45WXla68/vsPiFcfVKboxsZYe/n"
+-    "pv8e4ugXagVQVBXNZJ859iYPdJR24vo=" "-----END EC PRIVATE KEY-----";
+-
+-static const char ecdsa_secp384r1_sig[] =
+-    "\x30\x66\x02\x31\x00\xbb\x4d\x25\x30\x13\x1b\x3b\x75\x60\x07\xed\x53\x8b\x52\xee\xd8\x6e\xf1\x9d\xa8\x36\x0e\x2e\x20\x31\x51\x11\x48\x78\xdd\xaf\x24\x38\x64\x81\x71\x6b\xa6\xb7\x29\x58\x28\x82\x32\xba\x29\x29\xd9\x02\x31\x00\xeb\x70\x09\x87\xac\x7b\x78\x0d\x4c\x4f\x08\x2b\x86\x27\xe2\x60\x1f\xc9\x11\x9f\x1d\xf5\x82\x4c\xc7\x3d\xb0\x27\xc8\x93\x29\xc7\xd0\x0e\x88\x02\x09\x93\xc2\x72\xce\xa5\x74\x8c\x3d\xe0\x8c\xad";
+-
+-static const char ecdsa_secp521r1_privkey[] =
+-    "-----BEGIN EC PRIVATE KEY-----"
+-    "MIHbAgEBBEGO2n7NN363qSCvJVdlQtCvudtaW4o0fEufXRjE1AsCrle+VXX0Zh0w"
+-    "Y1slSeDHMndpakoiF+XkQ+bhcB867UV6aKAHBgUrgQQAI6GBiQOBhgAEAQb6jDpo"
+-    "byy1tF8Zucg0TMGUzIN2DK+RZJ3QQRdWdirO25OIC3FoFi1Yird6rpoB6HlNyJ7R"
+-    "0bNG9Uv34bSHMn8yAFoiqxUCdJZQbEenMoZsi6COaePe3e0QqvDMr0hEWT23Sr3t"
+-    "LpEV7eZGFfFIJw5wSUp2KOcs+O9WjmoukTWtDKNV"
+-    "-----END EC PRIVATE KEY-----";
+-
+-static const char ecdsa_secp521r1_sig[] =
+-    "\x30\x81\x87\x02\x42\x01\xb8\xcb\x52\x9e\x10\xa8\x49\x3f\xe1\x9e\x14\x0a\xcf\x96\xed\x7e\xab\x7d\x0c\xe1\x9b\xa4\x97\xdf\x01\xf5\x35\x42\x5f\x5b\x28\x15\x24\x33\x6e\x59\x6c\xaf\x10\x8b\x98\x8e\xe9\x4c\x23\x0d\x76\x92\x03\xdd\x6d\x8d\x08\x47\x15\x5b\xf8\x66\x75\x75\x40\xe8\xf4\xa0\x52\x02\x41\x15\x27\x7c\x5f\xa6\x33\xa6\x29\x68\x3f\x55\x8d\x7f\x1d\x4f\x88\xc6\x61\x6e\xac\x21\xdf\x2b\x7b\xde\x76\x9a\xdc\xe6\x3b\x94\x3f\x03\x9c\xa2\xa6\xa3\x63\x39\x48\xbd\x79\x70\x21\xf2\x6b\xff\x58\x66\xf1\x58\xc2\x58\xad\x4f\x84\x14\x5d\x05\x12\x83\xd0\x87\xbd\xf3";
+-
+-/* DSA key and signature */
+-static const char dsa_privkey[] =
+- "-----BEGIN DSA PRIVATE KEY-----\n"
+- "MIIDTQIBAAKCAQEAh60B6yPMRIT7udq2kKuwnQDohvT1U0w+RJcSr23C05cM/Ovn\n"
+- "UP/8Rrj6T8K+uYhMbKgLaZiJJW9q04jaPQk0cfUphbLvRjzVHwE/0Bkb+Y1Rv7ni\n"
+- "Jot2IFMq5iuNraf889PC0WREvFCcIkSFY2Ac4WT7mCcBtfx/raGFXDUjcUrJ0HwZ\n"
+- "IOhjQDfcXUsztuyYsYA75ociEY8kyDZq/ixyr5++R1VjNf30Re8AbQlXOEGxEN5t\n"
+- "t+Tvpq8K5L3prQs2KNSzyOUmedjb/ojH4T4qe/RL9EVjjeuIGHDNUT6F197yZ91y\n"
+- "qLLTf1WjnUyZcKij5rryX0LJBBWawEZjNSHZawIdAMQlyycia4NigCdiDR+QptUn\n"
+- "2xrj9o14fXkIrXcCggEAXRZm1rbPhsjSTo6cpCVrmDzO1grv83EHiBH4MvRQQnP8\n"
+- "FpAREsBA5cYju97XvLaLhioZeMjLn08kU7TUbHRUB+ULTuVvE2dQbBpGuKiLRRt9\n"
+- "6U2T0eD3xGLoM+o8EY/kpqaWGEpZv7hzM9xuo4vy55+viAZgFWULqmltwfG/7w7V\n"
+- "NXUHNv5H4Ipw//fSDLTPqzUlNqSSswDLz6pCjWEs0rWAqNAMaOiLTz4id9pL48Oe\n"
+- "oAfpcQR9tgTEnwyXfZBnrJVclHhkHKGeXvU05IgCzpKO76Z5R+By50T0i/JV7vzM\n"
+- "l2yS9aAl/cprT6U7yI3oU/blldCVNpMcFAFb+fO8DAKCAQBVMo8xptyvQOJeSvbO\n"
+- "SSYdJ3IiI/0GdkcGWXblWg9z7mrPaWEnT7OquEm/+vYtWd3GHDtyNM+jzsN4Xgjc\n"
+- "TL3AEd2hLiozJQ1BFKw25VU08UHAYTzUxZhO4Vwtmp46Kwj8YLDQ3NHRWCBxpDQR\n"
+- "fbiFvyXP+qXap6plMfrydnUD1mae/JSOWOYgdB7tFIehstLxVXx/cAnjwgFU03Df\n"
+- "grjsad92zA1Hc9wIjbsgAQdTR5DWnFRkRt3UtayBwoyqm6QceZHsv1NAGvkQ4ion\n"
+- "bEjkHkjF9YCkR9/rspR8cLghRIXMjOpypuSbaRPeeWq0gP2UOxFL/d3iWH0ETr/L\n"
+- "kTlCAhxYGpVgtfB96qmJukyl9GOGvfkwFTgEyIDoV84M\n"
+- "-----END DSA PRIVATE KEY-----\n";
+-
+-static const char dsa_sig[] =
+-    "\x30\x3d\x02\x1c\x2e\x40\x14\xb3\x7a\x3f\xc0\x4f\x06\x74\x4f\xa6\x5f\xc2\x0a\x46\x35\x38\x88\xb4\x1a\xcf\x94\x02\x40\x42\x7c\x7f\x02\x1d\x00\x98\xfc\xf1\x08\x66\xf1\x86\x28\xc9\x73\x9e\x2b\x5d\xce\x57\xe8\xb5\xeb\xcf\xa3\xf6\x60\xf6\x63\x16\x0e\xc0\x42";
+-
+-static const char gost01_privkey[] =
+- "-----BEGIN PRIVATE KEY-----\n"
+- "MEUCAQAwHAYGKoUDAgITMBIGByqFAwICIwEGByqFAwICHgEEIgQgdNfuHGmmTdPm\n"
+- "p5dAa3ea9UYxpdYQPP9lbDwzQwG2bJM=\n"
+- "-----END PRIVATE KEY-----\n";
+-
+-static const char gost01_sig[] =
+-    "\xc5\xc8\xf8\xdc\x22\x51\xb0\x72\xe9\xa2\xbb\x84\x6c\xe2\x24\xd5\x72\x39\x2a\x5a\x0e\x7a\x43\xfc\x9c\xc3\x5d\x32\x92\xbb\xab\xc0\x4b\x99\xbd\xc8\x47\x24\x70\x06\x7e\xa1\xc6\xe3\xa0\xdc\x42\xed\xa0\x66\xf0\xcc\x50\x97\xe9\x5a\x7d\x3f\x65\x2d\x7b\x1b\x03\xcb";
+-
+-static const char gost12_256_privkey[] =
+- "-----BEGIN PRIVATE KEY-----\n"
+- "MEgCAQAwHwYIKoUDBwEBAQEwEwYHKoUDAgIjAQYIKoUDBwEBAgIEIgQgKOF96tom\n"
+- "D61rhSnzKjyrmO3fv0gdlHei+6ovrc8SnBk=\n"
+- "-----END PRIVATE KEY-----\n";
+-
+-static const char gost12_256_sig[] =
+-    "\xb2\x51\x5a\x1a\xbd\x95\x4e\x71\x55\xad\x74\x74\x81\xa6\xca\x6c\x14\x01\xe0\x18\xda\xe4\x0d\x02\x4f\x14\xd2\x39\xd6\x3c\xb5\x85\xa8\x37\xfd\x7f\x2b\xfa\xe4\xf5\xbc\xbc\x15\x20\x8b\x83\x4b\x84\x0d\x5d\x02\x21\x8c\x0d\xb9\xc4\x2b\xc0\x3e\xfd\x42\x55\x1d\xb0";
+-
+-static const char gost12_512_privkey[] =
+- "-----BEGIN PRIVATE KEY-----\n"
+- "MGoCAQAwIQYIKoUDBwEBAQIwFQYJKoUDBwECAQIBBggqhQMHAQECAwRCBECjFpvp\n"
+- "B0vdc7u59b99TCNXhHiB69JJtUjvieNkGYJpoaaIvoKZTNCjpSZASsZcQZCHOTof\n"
+- "hsQ3JCCy4xnd5jWT\n"
+- "-----END PRIVATE KEY-----\n";
+-
+-static const char gost12_512_sig[] =
+-    "\x52\x4f\xa2\x77\x51\xd2\xc5\xef\xd3\xa3\x99\x4e\xec\xff\xc6\xe9\xfc\x2f\xc0\x28\x42\x03\x95\x6c\x9a\x38\xee\xea\x89\x79\xae\x1a\xc3\x68\x5e\xe4\x15\x15\x4b\xec\x0f\xf1\x7e\x0f\xba\x01\xc7\x84\x16\xc7\xb5\xac\x9d\x0c\x22\xdd\x31\xf7\xb0\x9b\x59\x4b\xf0\x02\xa8\x7d\xfd\x6d\x02\x43\xc7\x4f\x65\xbd\x84\x5c\x54\x91\xba\x75\x9f\x5a\x61\x19\x5c\x9a\x10\x78\x34\xa0\xa6\xf6\xdc\xb6\xb0\x50\x22\x38\x5f\xb0\x16\x66\xf1\xd5\x46\x00\xd5\xe2\xa8\xe5\xd2\x11\x5f\xd1\xbe\x6e\xac\xb2\x9c\x14\x34\x96\xe7\x58\x94\xb8\xf4\x5f";
+-
+ static int test_known_sig(gnutls_pk_algorithm_t pk, unsigned bits,
+ 			  gnutls_digest_algorithm_t dig,
+ 			  const void *privkey, size_t privkey_size,
+-- 
+2.20.1
+
+
+From 4b04d899849ea566ae33862289276d9b297cd493 Mon Sep 17 00:00:00 2001
+From: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
+Date: Wed, 3 Apr 2019 13:44:56 +0200
+Subject: [PATCH 2/7] crypto-selftests-pk.c: Add a comparison with a known
+ signature
+
+For RSA, compare the generated signature with a stored known value in
+test_sig().
+
+Signed-off-by: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
+---
+ lib/crypto-selftests-pk.c | 13 +++++++++++++
+ 1 file changed, 13 insertions(+)
+
+diff --git a/lib/crypto-selftests-pk.c b/lib/crypto-selftests-pk.c
+index 4fadd4161..0233e6b9f 100644
+--- a/lib/crypto-selftests-pk.c
++++ b/lib/crypto-selftests-pk.c
+@@ -313,6 +313,7 @@ static int test_sig(gnutls_pk_algorithm_t pk,
+ {
+ 	int ret;
+ 	gnutls_datum_t sig = { NULL, 0 };
++	gnutls_datum_t known_sig = { NULL, 0 };
+ 	gnutls_datum_t raw_rsa_key = { (void*)rsa_key2048, sizeof(rsa_key2048)-1 };
+ 	gnutls_datum_t raw_dsa_key = { (void*)dsa_key, sizeof(dsa_key)-1 };
+ 	gnutls_datum_t raw_ecc_key = { (void*)ecc_key, sizeof(ecc_key)-1 };
+@@ -343,6 +344,8 @@ static int test_sig(gnutls_pk_algorithm_t pk,
+ 	}
+ 
+ 	if (pk == GNUTLS_PK_RSA) {
++		known_sig.data = (void *)rsa_sig;
++		known_sig.size = sizeof(rsa_sig) - 1;
+ 		ret = gnutls_privkey_import_x509_raw(key, &raw_rsa_key, GNUTLS_X509_FMT_PEM, NULL, 0);
+ 	} else if (pk == GNUTLS_PK_RSA_PSS) {
+ 		ret = gnutls_privkey_import_x509_raw(key, &raw_rsa_key, GNUTLS_X509_FMT_PEM, NULL, 0);
+@@ -378,6 +381,16 @@ static int test_sig(gnutls_pk_algorithm_t pk,
+ 		goto cleanup;
+ 	}
+ 
++	/* Compare with a stored known signature */
++	if (known_sig.data != NULL) {
++		if (sig.size != known_sig.size
++			|| memcmp(sig.data, known_sig.data, sig.size) != 0) {
++			ret = GNUTLS_E_SELF_TEST_ERROR;
++			gnutls_assert();
++			goto cleanup;
++		}
++	}
++
+ 	ret =
+ 	    gnutls_pubkey_verify_data2(pub, sigalgo, 0,
+ 				       &signed_data, &sig);
+-- 
+2.20.1
+
+
+From db2b308fdbe98420b722eaf678c1a911bc51b0a5 Mon Sep 17 00:00:00 2001
+From: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
+Date: Thu, 18 Apr 2019 17:22:18 +0200
+Subject: [PATCH 4/7] tests: Run rng-no-onload test in FIPS mode
+
+This changes the function used in the test to override gnutls_rnd() to
+fill the given buffer with a different value each time it is called.
+This allows the test to run when FIPS mode is enabled.
+
+Previously the rng-no-onload test could get stuck if FIPS mode was
+enabled.  This happened if gnutls_rnd() function was called during
+global_init() in a loop that checks the generated value (e.g. if ECDSA
+signature generation is called during self tests).
+
+Signed-off-by: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
+---
+ tests/rng-no-onload.c | 12 +++++++-----
+ 1 file changed, 7 insertions(+), 5 deletions(-)
+
+diff --git a/tests/rng-no-onload.c b/tests/rng-no-onload.c
+index ac01be214..a485a440d 100644
+--- a/tests/rng-no-onload.c
++++ b/tests/rng-no-onload.c
+@@ -50,18 +50,20 @@ static int _rnd_called = 0;
+ int __attribute__ ((visibility ("protected")))
+ gnutls_rnd(gnutls_rnd_level_t level, void *data, size_t len)
+ {
++	static unsigned int value = 0;
++
+ 	_rnd_called = 1;
+ 
+-	memset(data, 0xff, len);
++	/* Increment 'value' in each call up to 255, then start again from 0 */
++	value = (value + 1) & 0xFF;
++
++	memset(data, value, len);
++
+ 	return 0;
+ }
+ 
+ void doit(void)
+ {
+-	if (gnutls_fips140_mode_enabled()) {
+-		exit(77);
+-	}
+-
+ 	global_init();
+ 
+ 	if (_rnd_called != 0)
+-- 
+2.20.1
+
+
+From fc926cd65f1de06f359315c6693c1a9c9899ba8c Mon Sep 17 00:00:00 2001
+From: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
+Date: Thu, 4 Apr 2019 15:45:02 +0200
+Subject: [PATCH 5/7] crypto-selftests-pk.c: Fix test_known_sig
+
+Previously a new signature was generated only for deterministic
+algorithms (i.e. only RSA).  With this, a new signature is always
+generated (and compared with a stored signature for deterministic
+algorithms).  The signature verification is tested for both generated
+and stored signatures.
+
+Signed-off-by: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
+---
+ lib/crypto-selftests-pk.c | 31 ++++++++++++++++++++-----------
+ 1 file changed, 20 insertions(+), 11 deletions(-)
+
+diff --git a/lib/crypto-selftests-pk.c b/lib/crypto-selftests-pk.c
+index 0233e6b9f..ba8f5e376 100644
+--- a/lib/crypto-selftests-pk.c
++++ b/lib/crypto-selftests-pk.c
+@@ -475,19 +475,17 @@ static int test_known_sig(gnutls_pk_algorithm_t pk, unsigned bits,
+ 		goto cleanup;
+ 	}
+ 
+-	/* Test if the signature we generate matches the stored */
++	ret = gnutls_privkey_sign_data(key, dig, 0, &signed_data, &sig);
++	if (ret < 0) {
++		gnutls_assert();
++		goto cleanup;
++	}
++
++	/* Test if the generated signature matches the stored */
+ 	ssig.data = (void *) stored_sig;
+ 	ssig.size = stored_sig_size;
+ 
+ 	if (deterministic_sigs != 0) {	/* do not compare against stored signature if not provided */
+-		ret =
+-		    gnutls_privkey_sign_data(key, dig, 0, &signed_data,
+-					     &sig);
+-		if (ret < 0) {
+-			gnutls_assert();
+-			goto cleanup;
+-		}
+-
+ 		if (sig.size != ssig.size
+ 		    || memcmp(sig.data, ssig.data, sig.size) != 0) {
+ 			ret = GNUTLS_E_SELF_TEST_ERROR;
+@@ -507,7 +505,7 @@ static int test_known_sig(gnutls_pk_algorithm_t pk, unsigned bits,
+ 		}
+ 	}
+ 
+-	/* Test if we can verify the signature */
++	/* Test if we can verify the generated signature */
+ 
+ 	ret = gnutls_pubkey_import_privkey(pub, key, 0, 0);
+ 	if (ret < 0) {
+@@ -515,6 +513,17 @@ static int test_known_sig(gnutls_pk_algorithm_t pk, unsigned bits,
+ 		goto cleanup;
+ 	}
+ 
++	ret =
++	    gnutls_pubkey_verify_data2(pub, gnutls_pk_to_sign(pk, dig), 0,
++				       &signed_data, &sig);
++	if (ret < 0) {
++		ret = GNUTLS_E_SELF_TEST_ERROR;
++		gnutls_assert();
++		goto cleanup;
++	}
++
++	/* Test if we can verify the stored signature */
++
+ 	ret =
+ 	    gnutls_pubkey_verify_data2(pub, gnutls_pk_to_sign(pk, dig), 0,
+ 				       &signed_data, &ssig);
+@@ -528,7 +537,7 @@ static int test_known_sig(gnutls_pk_algorithm_t pk, unsigned bits,
+ 
+ 	ret =
+ 	    gnutls_pubkey_verify_data2(pub, gnutls_pk_to_sign(pk, dig), 0,
+-				       &bad_data, &ssig);
++				       &bad_data, &sig);
+ 
+ 	if (ret != GNUTLS_E_PK_SIG_VERIFY_FAILED) {
+ 		ret = GNUTLS_E_SELF_TEST_ERROR;
+-- 
+2.20.1
+
+
+From 7e49999db264556ac73ff498bd8f7edce401cdd1 Mon Sep 17 00:00:00 2001
+From: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
+Date: Thu, 4 Apr 2019 17:22:04 +0200
+Subject: [PATCH 6/7] crypto-selftests-pk.c: Fix PK_KNOWN_TEST and PK_TEST
+
+Remove the flag check from the end of the macros.  This change allows
+more than one test to run in sequence when GNUTLS_SELF_TEST_FLAG_ALL is
+not set.  Move the flags checks to run the minimal set of tests required
+for FIPS and keep the previous behaviour for GOST (run the first test
+for each algorithm).
+
+Signed-off-by: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
+---
+ lib/crypto-selftests-pk.c | 37 ++++++++++++++++++++-----------------
+ 1 file changed, 20 insertions(+), 17 deletions(-)
+
+diff --git a/lib/crypto-selftests-pk.c b/lib/crypto-selftests-pk.c
+index ba8f5e376..fc8ee2525 100644
+--- a/lib/crypto-selftests-pk.c
++++ b/lib/crypto-selftests-pk.c
+@@ -568,18 +568,14 @@ static int test_known_sig(gnutls_pk_algorithm_t pk, unsigned bits,
+ 			if (ret < 0) { \
+ 				gnutls_assert(); \
+ 				goto cleanup; \
+-			} \
+-			if (!(flags & GNUTLS_SELF_TEST_FLAG_ALL)) \
+-				return 0
++			}
+ 
+ #define PK_KNOWN_TEST(pk, det, bits, dig, pkey, sig) \
+ 			ret = test_known_sig(pk, bits, dig, pkey, sizeof(pkey)-1, sig, sizeof(sig)-1, det); \
+ 			if (ret < 0) { \
+ 				gnutls_assert(); \
+ 				goto cleanup; \
+-			} \
+-			if (!(flags & GNUTLS_SELF_TEST_FLAG_ALL)) \
+-				return 0
++			}
+ 
+ 
+ /* This file is also included by the test app in tests/slow/cipher-test, so in that
+@@ -812,11 +808,12 @@ int gnutls_pk_self_test(unsigned flags, gnutls_pk_algorithm_t pk)
+ 		PK_KNOWN_TEST(GNUTLS_PK_RSA, 1, 2048, GNUTLS_DIG_SHA256,
+ 			      rsa_key2048, rsa_sig);
+ 		PK_TEST(GNUTLS_PK_RSA, test_rsa_enc, 2048, 0);
+-		PK_TEST(GNUTLS_PK_RSA, test_sig, 3072, GNUTLS_SIGN_RSA_SHA256);
+ 
+ 		if (!(flags & GNUTLS_SELF_TEST_FLAG_ALL))
+ 			return 0;
+ 
++		PK_TEST(GNUTLS_PK_RSA, test_sig, 3072, GNUTLS_SIGN_RSA_SHA256);
++
+ 		FALLTHROUGH;
+ 	case GNUTLS_PK_RSA_PSS:
+ 		PK_TEST(GNUTLS_PK_RSA_PSS, test_sig, 2048, GNUTLS_SIGN_RSA_PSS_RSAE_SHA256);
+@@ -828,11 +825,12 @@ int gnutls_pk_self_test(unsigned flags, gnutls_pk_algorithm_t pk)
+ 	case GNUTLS_PK_DSA:
+ 		PK_KNOWN_TEST(GNUTLS_PK_DSA, 0, 2048, GNUTLS_DIG_SHA256,
+ 			      dsa_privkey, dsa_sig);
+-		PK_TEST(GNUTLS_PK_DSA, test_sig, 3072, GNUTLS_SIGN_DSA_SHA256);
+ 
+ 		if (!(flags & GNUTLS_SELF_TEST_FLAG_ALL))
+ 			return 0;
+ 
++		PK_TEST(GNUTLS_PK_DSA, test_sig, 3072, GNUTLS_SIGN_DSA_SHA256);
++
+ 		FALLTHROUGH;
+ 	case GNUTLS_PK_EC:
+ 		/* Test ECDH and ECDSA */
+@@ -850,13 +848,14 @@ int gnutls_pk_self_test(unsigned flags, gnutls_pk_algorithm_t pk)
+ 			      (GNUTLS_ECC_CURVE_SECP256R1),
+ 			      GNUTLS_DIG_SHA256, ecdsa_secp256r1_privkey,
+ 			      ecdsa_secp256r1_sig);
+-		PK_TEST(GNUTLS_PK_EC, test_sig,
+-			GNUTLS_CURVE_TO_BITS(GNUTLS_ECC_CURVE_SECP256R1),
+-			GNUTLS_SIGN_ECDSA_SHA256);
+ 
+ 		if (!(flags & GNUTLS_SELF_TEST_FLAG_ALL))
+ 			return 0;
+ 
++		PK_TEST(GNUTLS_PK_EC, test_sig,
++			GNUTLS_CURVE_TO_BITS(GNUTLS_ECC_CURVE_SECP256R1),
++			GNUTLS_SIGN_ECDSA_SHA256);
++
+ 		PK_KNOWN_TEST(GNUTLS_PK_EC, 0,
+ 			      GNUTLS_CURVE_TO_BITS
+ 			      (GNUTLS_ECC_CURVE_SECP384R1),
+@@ -900,31 +899,35 @@ int gnutls_pk_self_test(unsigned flags, gnutls_pk_algorithm_t pk)
+ 	case GNUTLS_PK_GOST_01:
+ 		PK_KNOWN_TEST(GNUTLS_PK_GOST_01, 0, GNUTLS_ECC_CURVE_GOST256CPA, GNUTLS_DIG_GOSTR_94,
+ 			      gost01_privkey, gost01_sig);
+-		PK_TEST(GNUTLS_PK_GOST_01, test_sig, GNUTLS_CURVE_TO_BITS(GNUTLS_ECC_CURVE_GOST256CPA),
+-			GNUTLS_SIGN_GOST_94);
+ 
+ 		if (!(flags & GNUTLS_SELF_TEST_FLAG_ALL))
+ 			return 0;
+ 
++		PK_TEST(GNUTLS_PK_GOST_01, test_sig, GNUTLS_CURVE_TO_BITS(GNUTLS_ECC_CURVE_GOST256CPA),
++			GNUTLS_SIGN_GOST_94);
++
+ 		FALLTHROUGH;
+ 	case GNUTLS_PK_GOST_12_256:
+ 		PK_KNOWN_TEST(GNUTLS_PK_GOST_12_256, 0, GNUTLS_ECC_CURVE_GOST256CPA, GNUTLS_DIG_STREEBOG_256,
+ 			      gost12_256_privkey, gost12_256_sig);
+-		PK_TEST(GNUTLS_PK_GOST_12_256, test_sig, GNUTLS_CURVE_TO_BITS(GNUTLS_ECC_CURVE_GOST256CPA),
+-			GNUTLS_SIGN_GOST_256);
+ 
+ 		if (!(flags & GNUTLS_SELF_TEST_FLAG_ALL))
+ 			return 0;
+ 
++		PK_TEST(GNUTLS_PK_GOST_12_256, test_sig, GNUTLS_CURVE_TO_BITS(GNUTLS_ECC_CURVE_GOST256CPA),
++			GNUTLS_SIGN_GOST_256);
++
+ 		FALLTHROUGH;
+ 	case GNUTLS_PK_GOST_12_512:
+ 		PK_KNOWN_TEST(GNUTLS_PK_GOST_12_512, 0, GNUTLS_ECC_CURVE_GOST512A, GNUTLS_DIG_STREEBOG_512,
+ 			      gost12_512_privkey, gost12_512_sig);
+-		PK_TEST(GNUTLS_PK_GOST_12_512, test_sig, GNUTLS_CURVE_TO_BITS(GNUTLS_ECC_CURVE_GOST512A),
+-			GNUTLS_SIGN_GOST_512);
+ 
+ 		if (!(flags & GNUTLS_SELF_TEST_FLAG_ALL))
+ 			return 0;
++
++		PK_TEST(GNUTLS_PK_GOST_12_512, test_sig, GNUTLS_CURVE_TO_BITS(GNUTLS_ECC_CURVE_GOST512A),
++			GNUTLS_SIGN_GOST_512);
++
+ #endif
+ 
+ 		break;
+-- 
+2.20.1
+
+
+From c2e83d2110b98d93588f1b6187bc932feb958ca4 Mon Sep 17 00:00:00 2001
+From: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
+Date: Mon, 8 Apr 2019 14:21:57 +0200
+Subject: [PATCH 7/7] crypto-selftests-pk.c: Cleanup self tests
+
+test_sig() always uses the same key for RSA, DSA, and ECDSA regardless
+of the value provided in the "bits" parameter.  Therefore, avoid
+printing specific information (number of bits or name of the curve).
+
+Changes test_sig() to use 2048 bits key for DSA; deleted hardcoded 512
+bits DSA key;
+
+Avoid calling test_sig() multiple times for ECDSA: the same key is
+used regardless of the curve provided in the parameters.
+
+Signed-off-by: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
+---
+ lib/crypto-selftests-pk.c | 42 +++++++++------------------------------
+ 1 file changed, 9 insertions(+), 33 deletions(-)
+
+diff --git a/lib/crypto-selftests-pk.c b/lib/crypto-selftests-pk.c
+index fc8ee2525..3d665b723 100644
+--- a/lib/crypto-selftests-pk.c
++++ b/lib/crypto-selftests-pk.c
+@@ -78,16 +78,6 @@ static const char ecc_key[] =
+  "MSHpe5vd0TQz+/GAa1zxle8mB/Cdh0JaTrA=\n"
+  "-----END EC PRIVATE KEY-----\n";
+ 
+-static const char dsa_key[] =
+- "-----BEGIN DSA PRIVATE KEY-----\n"
+- "MIH4AgEAAkEA6KUOSXfFNcInFLPdOlLlKNCe79zJrkxnsQN+lllxuk1ifZrE07r2\n"
+- "3edTrc4riQNnZ2nZ372tYUAMJg+5jM6IIwIVAOa58exwZ+42Tl+p3b4Kbpyu2Ron\n"
+- "AkBocj7gkiBYHtv6HMIIzooaxn4vpGR0Ns6wBfroBUGvrnSAgfT3WyiNaHkIF28e\n"
+- "quWcEeOJjUgFvatcM8gcY288AkEAyKWlgzBurIYST8TM3j4PuQJDTvdHDaGoAUAa\n"
+- "EfjmOw2UXKwqTmwPiT5BYKgCo2ILS87ttlTpd8vndH37pmnmVQIUQIVuKpZ8y9Bw\n"
+- "VzO8qcrLCFvTOXY=\n"
+- "-----END DSA PRIVATE KEY-----\n";
+-
+ static const char gost01_key[] =
+  "-----BEGIN PRIVATE KEY-----\n"
+  "MEUCAQAwHAYGKoUDAgITMBIGByqFAwICJAAGByqFAwICHgEEIgQgR1lBLIr4WBpn\n"
+@@ -315,22 +305,20 @@ static int test_sig(gnutls_pk_algorithm_t pk,
+ 	gnutls_datum_t sig = { NULL, 0 };
+ 	gnutls_datum_t known_sig = { NULL, 0 };
+ 	gnutls_datum_t raw_rsa_key = { (void*)rsa_key2048, sizeof(rsa_key2048)-1 };
+-	gnutls_datum_t raw_dsa_key = { (void*)dsa_key, sizeof(dsa_key)-1 };
++	gnutls_datum_t raw_dsa_key = { (void*)dsa_privkey, sizeof(dsa_privkey)-1 };
+ 	gnutls_datum_t raw_ecc_key = { (void*)ecc_key, sizeof(ecc_key)-1 };
+ 	gnutls_datum_t raw_gost01_key = { (void*)gost01_key, sizeof(gost01_key)-1 };
+ 	gnutls_datum_t raw_gost12_256_key = { (void*)gost12_256_key, sizeof(gost12_256_key)-1 };
+ 	gnutls_datum_t raw_gost12_512_key = { (void*)gost12_512_key, sizeof(gost12_512_key)-1 };
+ 	gnutls_privkey_t key;
+ 	gnutls_pubkey_t pub = NULL;
+-	char param_name[32];
++	char param_name[32] = "";
+ 
+-	if (pk == GNUTLS_PK_EC || pk == GNUTLS_PK_GOST_01 ||
+-	    pk == GNUTLS_PK_GOST_12_256 || pk == GNUTLS_PK_GOST_12_512) {
+-		snprintf(param_name, sizeof(param_name), "%s",
++	if (pk == GNUTLS_PK_GOST_01 || pk == GNUTLS_PK_GOST_12_256 ||
++	    pk == GNUTLS_PK_GOST_12_512) {
++		snprintf(param_name, sizeof(param_name), "-%s",
+ 			 gnutls_ecc_curve_get_name(GNUTLS_BITS_TO_CURVE
+ 						   (bits)));
+-	} else {
+-		snprintf(param_name, sizeof(param_name), "%u", bits);
+ 	}
+ 
+ 	ret = gnutls_privkey_init(&key);
+@@ -418,10 +406,10 @@ static int test_sig(gnutls_pk_algorithm_t pk,
+ 	gnutls_free(sig.data);
+ 
+ 	if (ret == 0)
+-		_gnutls_debug_log("%s-%s-sig self test succeeded\n",
++		_gnutls_debug_log("%s%s-sig self test succeeded\n",
+ 				  gnutls_pk_get_name(pk), param_name);
+ 	else
+-		_gnutls_debug_log("%s-%s-sig self test failed\n",
++		_gnutls_debug_log("%s%s-sig self test failed\n",
+ 				  gnutls_pk_get_name(pk), param_name);
+ 
+ 	return ret;
+@@ -812,7 +800,7 @@ int gnutls_pk_self_test(unsigned flags, gnutls_pk_algorithm_t pk)
+ 		if (!(flags & GNUTLS_SELF_TEST_FLAG_ALL))
+ 			return 0;
+ 
+-		PK_TEST(GNUTLS_PK_RSA, test_sig, 3072, GNUTLS_SIGN_RSA_SHA256);
++		PK_TEST(GNUTLS_PK_RSA, test_sig, 2048, GNUTLS_SIGN_RSA_SHA256);
+ 
+ 		FALLTHROUGH;
+ 	case GNUTLS_PK_RSA_PSS:
+@@ -829,7 +817,7 @@ int gnutls_pk_self_test(unsigned flags, gnutls_pk_algorithm_t pk)
+ 		if (!(flags & GNUTLS_SELF_TEST_FLAG_ALL))
+ 			return 0;
+ 
+-		PK_TEST(GNUTLS_PK_DSA, test_sig, 3072, GNUTLS_SIGN_DSA_SHA256);
++		PK_TEST(GNUTLS_PK_DSA, test_sig, 2048, GNUTLS_SIGN_DSA_SHA256);
+ 
+ 		FALLTHROUGH;
+ 	case GNUTLS_PK_EC:
+@@ -861,18 +849,12 @@ int gnutls_pk_self_test(unsigned flags, gnutls_pk_algorithm_t pk)
+ 			      (GNUTLS_ECC_CURVE_SECP384R1),
+ 			      GNUTLS_DIG_SHA256, ecdsa_secp384r1_privkey,
+ 			      ecdsa_secp384r1_sig);
+-		PK_TEST(GNUTLS_PK_EC, test_sig,
+-			GNUTLS_CURVE_TO_BITS(GNUTLS_ECC_CURVE_SECP384R1),
+-			GNUTLS_SIGN_ECDSA_SHA384);
+ 
+ 		PK_KNOWN_TEST(GNUTLS_PK_EC, 0,
+ 			      GNUTLS_CURVE_TO_BITS
+ 			      (GNUTLS_ECC_CURVE_SECP521R1),
+ 			      GNUTLS_DIG_SHA512, ecdsa_secp521r1_privkey,
+ 			      ecdsa_secp521r1_sig);
+-		PK_TEST(GNUTLS_PK_EC, test_sig,
+-			GNUTLS_CURVE_TO_BITS(GNUTLS_ECC_CURVE_SECP521R1),
+-			GNUTLS_SIGN_ECDSA_SHA512);
+ 
+ #ifdef ENABLE_NON_SUITEB_CURVES
+ 		PK_KNOWN_TEST(GNUTLS_PK_EC, 0,
+@@ -880,18 +862,12 @@ int gnutls_pk_self_test(unsigned flags, gnutls_pk_algorithm_t pk)
+ 			      (GNUTLS_ECC_CURVE_SECP192R1),
+ 			      GNUTLS_DIG_SHA256, ecdsa_secp192r1_privkey,
+ 			      ecdsa_secp192r1_sig);
+-		PK_TEST(GNUTLS_PK_EC, test_sig,
+-			GNUTLS_CURVE_TO_BITS(GNUTLS_ECC_CURVE_SECP192R1),
+-			GNUTLS_SIGN_ECDSA_SHA256);
+ 
+ 		PK_KNOWN_TEST(GNUTLS_PK_EC, 0,
+ 			      GNUTLS_CURVE_TO_BITS
+ 			      (GNUTLS_ECC_CURVE_SECP224R1),
+ 			      GNUTLS_DIG_SHA256, ecdsa_secp224r1_privkey,
+ 			      ecdsa_secp224r1_sig);
+-		PK_TEST(GNUTLS_PK_EC, test_sig,
+-			GNUTLS_CURVE_TO_BITS(GNUTLS_ECC_CURVE_SECP224R1),
+-			GNUTLS_SIGN_ECDSA_SHA256);
+ #endif
+ 
+ #if ENABLE_GOST
+-- 
+2.20.1
diff --git a/SOURCES/gnutls-3.6.5.tar.xz.sig b/SOURCES/gnutls-3.6.5.tar.xz.sig
deleted file mode 100644
index fb9e343..0000000
Binary files a/SOURCES/gnutls-3.6.5.tar.xz.sig and /dev/null differ
diff --git a/SOURCES/gnutls-3.6.8-aead-cipher-encryptv2.patch b/SOURCES/gnutls-3.6.8-aead-cipher-encryptv2.patch
new file mode 100644
index 0000000..8ed9aa6
--- /dev/null
+++ b/SOURCES/gnutls-3.6.8-aead-cipher-encryptv2.patch
@@ -0,0 +1,1296 @@
+From 38c8dc4317296624cba5b2c8ddba6e9047048180 Mon Sep 17 00:00:00 2001
+From: Daiki Ueno <dueno@redhat.com>
+Date: Thu, 1 Aug 2019 17:41:45 +0200
+Subject: [PATCH 1/3] iov: add iterator interface for giovec_t
+
+This adds an iterator interface over giovec_t array, extracting a
+fixed sized block.
+
+Signed-off-by: Daiki Ueno <dueno@redhat.com>
+---
+ .gitignore        |   1 +
+ lib/Makefile.am   |   3 +-
+ lib/iov.c         | 120 ++++++++++++++++++++++++++++++++
+ lib/iov.h         |  46 +++++++++++++
+ lib/libgnutls.map |   3 +
+ tests/Makefile.am |   6 +-
+ tests/iov.c       | 170 ++++++++++++++++++++++++++++++++++++++++++++++
+ 7 files changed, 347 insertions(+), 2 deletions(-)
+ create mode 100644 lib/iov.c
+ create mode 100644 lib/iov.h
+ create mode 100644 tests/iov.c
+
+diff --git a/lib/Makefile.am b/lib/Makefile.am
+index ffc72e4c2..9fe78afbd 100644
+--- a/lib/Makefile.am
++++ b/lib/Makefile.am
+@@ -80,7 +80,8 @@ COBJECTS = range.c record.c compress.c debug.c cipher.c gthreads.h handshake-tls
+ 	system-keys.h urls.c urls.h prf.c auto-verify.c dh-session.c \
+ 	cert-session.c handshake-checks.c dtls-sw.c dh-primes.c openpgp_compat.c \
+ 	crypto-selftests.c crypto-selftests-pk.c secrets.c extv.c extv.h \
+-	hello_ext_lib.c hello_ext_lib.h ocsp-api.c stek.c cert-cred-rawpk.c
++	hello_ext_lib.c hello_ext_lib.h ocsp-api.c stek.c cert-cred-rawpk.c \
++	iov.c iov.h
+ 
+ if WINDOWS
+ COBJECTS += system/keys-win.c
+diff --git a/lib/iov.c b/lib/iov.c
+new file mode 100644
+index 000000000..5dc29c54b
+--- /dev/null
++++ b/lib/iov.c
+@@ -0,0 +1,120 @@
++/*
++ * Copyright (C) 2019 Red Hat, Inc.
++ *
++ * Author: Daiki Ueno
++ *
++ * 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 <https://www.gnu.org/licenses/>
++ *
++ */
++
++#include "gnutls_int.h"
++#include "iov.h"
++
++/**
++ * _gnutls_iov_iter_init:
++ * @iter: the iterator
++ * @iov: the data buffers
++ * @iov_count: the number of data buffers
++ * @block_size: block size to iterate
++ *
++ * Initialize the iterator.
++ *
++ * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise
++ *   an error code is returned
++ */
++int
++_gnutls_iov_iter_init(struct iov_iter_st *iter,
++		      const giovec_t *iov, size_t iov_count,
++		      size_t block_size)
++{
++	if (unlikely(block_size > MAX_CIPHER_BLOCK_SIZE))
++		return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
++
++	iter->iov = iov;
++	iter->iov_count = iov_count;
++	iter->iov_index = 0;
++	iter->iov_offset = 0;
++	iter->block_size = block_size;
++	iter->block_offset = 0;
++	return 0;
++}
++
++/**
++ * _gnutls_iov_iter_next:
++ * @iter: the iterator
++ * @data: the return location of extracted data
++ *
++ * Retrieve block(s) pointed by @iter and advance it to the next
++ * position.  It returns the number of consecutive blocks in @data.
++ * At the end of iteration, 0 is returned.
++ *
++ * If the data stored in @iter is not multiple of the block size, the
++ * remaining data is stored in the "block" field of @iter with the
++ * size stored in the "block_offset" field.
++ *
++ * Returns: On success, a value greater than or equal to zero is
++ *   returned, otherwise a negative error code is returned
++ */
++ssize_t
++_gnutls_iov_iter_next(struct iov_iter_st *iter, uint8_t **data)
++{
++	while (iter->iov_index < iter->iov_count) {
++		const giovec_t *iov = &iter->iov[iter->iov_index];
++		uint8_t *p = iov->iov_base;
++		size_t len = iov->iov_len;
++		size_t block_left;
++
++		if (unlikely(len < iter->iov_offset))
++			return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
++		len -= iter->iov_offset;
++		p += iter->iov_offset;
++
++		/* We have at least one full block, return a whole set
++		 * of full blocks immediately. */
++		if (iter->block_offset == 0 && len >= iter->block_size) {
++			if ((len % iter->block_size) == 0) {
++				iter->iov_index++;
++				iter->iov_offset = 0;
++			} else
++				iter->iov_offset +=
++					len - (len % iter->block_size);
++
++			/* Return the blocks. */
++			*data = p;
++			return len / iter->block_size;
++		}
++
++		/* We can complete one full block to return. */
++		block_left = iter->block_size - iter->block_offset;
++		if (len >= block_left) {
++			memcpy(iter->block + iter->block_offset, p, block_left);
++			iter->iov_offset += block_left;
++			iter->block_offset = 0;
++
++			/* Return the filled block. */
++			*data = iter->block;
++			return 1;
++		}
++
++		/* Not enough data for a full block, store in temp
++		 * memory and continue. */
++		memcpy(iter->block + iter->block_offset, p, len);
++		iter->block_offset += len;
++		iter->iov_index++;
++		iter->iov_offset = 0;
++	}
++	return 0;
++}
+diff --git a/lib/iov.h b/lib/iov.h
+new file mode 100644
+index 000000000..47fba559a
+--- /dev/null
++++ b/lib/iov.h
+@@ -0,0 +1,46 @@
++/*
++ * Copyright (C) 2019 Red Hat, Inc.
++ *
++ * Author: Daiki Ueno
++ *
++ * 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 <https://www.gnu.org/licenses/>
++ *
++ */
++
++#ifndef GNUTLS_LIB_IOV_H
++#define GNUTLS_LIB_IOV_H
++
++#include "gnutls_int.h"
++
++struct iov_iter_st {
++	const giovec_t *iov;
++	size_t iov_count;	/* the number of iov */
++	size_t iov_index;	/* index of the current buffer */
++	size_t iov_offset;	/* byte offset in the current buffer */
++
++	uint8_t block[MAX_CIPHER_BLOCK_SIZE]; /* incomplete block for reading */
++	size_t block_size;	/* actual block size of the cipher */
++	size_t block_offset;	/* offset in block */
++
++};
++
++int _gnutls_iov_iter_init(struct iov_iter_st *iter,
++			  const giovec_t *iov, size_t iov_count,
++			  size_t block_size);
++
++ssize_t _gnutls_iov_iter_next(struct iov_iter_st *iter, uint8_t **data);
++
++#endif /* GNUTLS_LIB_IOV_H */
+diff --git a/lib/libgnutls.map b/lib/libgnutls.map
+index 0f31f4aef..fc93c0857 100644
+--- a/lib/libgnutls.map
++++ b/lib/libgnutls.map
+@@ -1374,4 +1374,7 @@ GNUTLS_PRIVATE_3_4 {
+ 	_gnutls_global_set_gettime_function;
+ 	# Internal symbols needed by tests/tls13/anti_replay.c
+ 	_gnutls_anti_replay_check;
++	# needed by tests/iov:
++	_gnutls_iov_iter_init;
++	_gnutls_iov_iter_next;
+ } GNUTLS_3_4;
+diff --git a/tests/Makefile.am b/tests/Makefile.am
+index a8c2d152e..a2883570f 100644
+--- a/tests/Makefile.am
++++ b/tests/Makefile.am
+@@ -212,7 +212,7 @@ ctests += mini-record-2 simple gnutls_hm
+ 	 null_retrieve_function tls-record-size-limit tls-crt_type-neg \
+ 	 resume-with-stek-expiration resume-with-previous-stek rawpk-api \
+ 	 tls-record-size-limit-asym dh-compute ecdh-compute \
+-	 sign-verify-deterministic
++	 sign-verify-deterministic iov
+ 
+ if HAVE_SECCOMP_TESTS
+ ctests += dtls-with-seccomp tls-with-seccomp dtls-client-with-seccomp tls-client-with-seccomp
+@@ -460,6 +460,10 @@ tls13_anti_replay_CPPFLAGS = $(AM_CPPFLAGS) \
+ 	-I$(top_builddir)/gl	\
+ 	$(NETTLE_CFLAGS)
+ 
++iov_CPPFLAGS = $(AM_CPPFLAGS) \
++	-I$(top_srcdir)/gl	\
++	-I$(top_builddir)/gl
++
+ if ENABLE_PKCS11
+ if !WINDOWS
+ ctests += tls13/post-handshake-with-cert-pkcs11 pkcs11/tls-neg-pkcs11-no-key
+diff --git a/tests/iov.c b/tests/iov.c
+new file mode 100644
+index 000000000..eda5583a7
+--- /dev/null
++++ b/tests/iov.c
+@@ -0,0 +1,170 @@
++/*
++ * Copyright (C) 2019 Red Hat, Inc.
++ *
++ * Author: Daiki Ueno
++ *
++ * This file is part of GnuTLS.
++ *
++ * GnuTLS is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 3 of the License, or
++ * (at your option) any later version.
++ *
++ * GnuTLS 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 a copy of the GNU Lesser General Public License
++ * along with this program.  If not, see <https://www.gnu.org/licenses/>
++ */
++
++#ifdef HAVE_CONFIG_H
++#include <config.h>
++#endif
++
++#include "gnutls_int.h"
++#include "../lib/iov.h"
++
++#include "utils.h"
++
++struct exp_st {
++	ssize_t ret;
++	size_t iov_index;
++	size_t iov_offset;
++	size_t block_offset;
++};
++
++struct test_st {
++	const char *name;
++	const giovec_t *iov;
++	size_t iovcnt;
++	size_t block_size;
++	const struct exp_st *exp;
++	size_t expcnt;
++	size_t remaining;
++};
++
++static const giovec_t iov16[] = {
++	{(void *) "0123456789abcdef", 16},
++	{(void *) "0123456789abcdef", 16},
++	{(void *) "0123456789abcdef", 16},
++	{(void *) "0123456789abcdef", 16}
++};
++
++static const struct exp_st exp16_64[] = {
++	{1, 3, 16, 0},
++	{0, 0, 0, 0}
++};
++
++static const struct exp_st exp16_32[] = {
++	{1, 1, 16, 0},
++	{1, 3, 16, 0},
++	{0, 0, 0, 0}
++};
++
++static const struct exp_st exp16_16[] = {
++	{1, 1, 0, 0},
++	{1, 2, 0, 0},
++	{1, 3, 0, 0},
++	{1, 4, 0, 0},
++	{0, 0, 0, 0}
++};
++
++static const struct exp_st exp16_4[] = {
++	{4, 1, 0, 0},
++	{4, 2, 0, 0},
++	{4, 3, 0, 0},
++	{4, 4, 0, 0},
++	{0, 0, 0, 0}
++};
++
++static const struct exp_st exp16_3[] = {
++	{5, 0, 15, 0},
++	{1, 1, 2, 0},
++	{4, 1, 14, 0},
++	{1, 2, 1, 0},
++	{5, 3, 0, 0},
++	{5, 3, 15, 0},
++	{0, 0, 0, 1}
++};
++
++static const giovec_t iov8[] = {
++	{(void *) "01234567", 8},
++	{(void *) "01234567", 8},
++	{(void *) "01234567", 8},
++	{(void *) "01234567", 8}
++};
++
++static const struct exp_st exp8_64[] = {
++	{0, 0, 0, 32}
++};
++
++static const struct test_st tests[] = {
++	{ "16/64", iov16, sizeof(iov16)/sizeof(iov16[0]), 64,
++	  exp16_64, sizeof(exp16_64)/sizeof(exp16_64[0]), 0 },
++	{ "16/32", iov16, sizeof(iov16)/sizeof(iov16[0]), 32,
++	  exp16_32, sizeof(exp16_32)/sizeof(exp16_32[0]), 0 },
++	{ "16/16", iov16, sizeof(iov16)/sizeof(iov16[0]), 16,
++	  exp16_16, sizeof(exp16_16)/sizeof(exp16_16[0]), 0 },
++	{ "16/4", iov16, sizeof(iov16)/sizeof(iov16[0]), 4,
++	  exp16_4, sizeof(exp16_4)/sizeof(exp16_4[0]), 0 },
++	{ "16/3", iov16, sizeof(iov16)/sizeof(iov16[0]), 3,
++	  exp16_3, sizeof(exp16_3)/sizeof(exp16_3[0]), 1 },
++	{ "8/64", iov8, sizeof(iov8)/sizeof(iov8[0]), 64,
++	  exp8_64, sizeof(exp8_64)/sizeof(exp8_64[0]), 32 }
++};
++
++void
++doit (void)
++{
++	size_t i;
++
++	for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++) {
++		struct iov_iter_st iter;
++		const struct exp_st *exp = tests[i].exp;
++		uint8_t *data;
++		size_t j;
++
++		success("%s\n", tests[i].name);
++		assert(_gnutls_iov_iter_init(&iter,
++					     tests[i].iov, tests[i].iovcnt,
++					     tests[i].block_size) == 0);
++		for (j = 0; j < tests[i].expcnt; j++) {
++			ssize_t ret;
++
++			ret = _gnutls_iov_iter_next(&iter, &data);
++			if (ret != exp[j].ret)
++				fail("iov_iter_next: %d != %d\n",
++				     (int) ret, (int) exp[j].ret);
++			else if (debug)
++				success("iov_iter_next: %d == %d\n",
++					(int) ret, (int) exp[j].ret);
++			if (ret == 0)
++				break;
++			if (ret > 0) {
++				if (iter.iov_index != exp[j].iov_index)
++					fail("iter.iov_index: %u != %u\n",
++					     (unsigned) iter.iov_index, (unsigned) exp[j].iov_index);
++				else if (debug)
++					success("iter.iov_index: %u == %u\n",
++					     (unsigned) iter.iov_index, (unsigned) exp[j].iov_index);
++				if (iter.iov_offset != exp[j].iov_offset)
++					fail("iter.iov_offset: %u != %u\n",
++					     (unsigned) iter.iov_offset, (unsigned) exp[j].iov_offset);
++				else if (debug)
++					success("iter.iov_offset: %u == %u\n",
++					     (unsigned) iter.iov_offset, (unsigned) exp[j].iov_offset);
++				if (iter.block_offset != exp[j].block_offset)
++					fail("iter.block_offset: %u != %u\n",
++					     (unsigned) iter.block_offset, (unsigned) exp[j].block_offset);
++				else if (debug)
++					success("iter.block_offset: %u == %u\n",
++					     (unsigned) iter.block_offset, (unsigned) exp[j].block_offset);
++			}
++		}
++		if (iter.block_offset != tests[i].remaining)
++			fail("remaining: %u != %u\n",
++			     (unsigned) iter.block_offset, (unsigned) tests[i].remaining);
++	}
++}
+-- 
+2.21.0
+
+
+From 9ca7a2b42168d356126e306e25211d43ea3c2e7d Mon Sep 17 00:00:00 2001
+From: Daiki Ueno <dueno@redhat.com>
+Date: Thu, 1 Aug 2019 18:13:38 +0200
+Subject: [PATCH 2/3] crypto-api: use giovec_t iterator interface for
+ aead_encryptv
+
+This replaces the macros AUTH_UPDATE and ENCRYPT used in
+gnutls_aead_cipher_encryptv() with the iov_iter interface.
+
+Signed-off-by: Daiki Ueno <dueno@redhat.com>
+---
+ lib/crypto-api.c | 167 ++++++++++++++++-------------------------------
+ 1 file changed, 57 insertions(+), 110 deletions(-)
+
+diff --git a/lib/crypto-api.c b/lib/crypto-api.c
+index 8af3f3b7d..70107fed0 100644
+--- a/lib/crypto-api.c
++++ b/lib/crypto-api.c
+@@ -31,6 +31,7 @@
+ #include <crypto.h>
+ #include <fips.h>
+ #include "crypto-api.h"
++#include "iov.h"
+ 
+ typedef struct api_cipher_hd_st {
+ 	cipher_hd_st ctx_enc;
+@@ -916,98 +917,6 @@ static int copy_iov(struct iov_store_st *dst, const giovec_t *iov, int iovcnt)
+ 	}
+ }
+ 
+-#define AUTH_UPDATE_FINAL(ctx) do { \
+-	if (index) { \
+-		ret = _gnutls_cipher_auth(ctx, cache, index); \
+-		if (unlikely(ret < 0)) \
+-			return gnutls_assert_val(ret); \
+-	} \
+-	} while(0)
+-
+-#define AUTH_UPDATE(ctx, data, length) do { \
+-	if (index) { \
+-		ssize_t left = blocksize - index; \
+-		if (length < left) { \
+-			memcpy(cache+index, data, \
+-			       length); \
+-			index += length; \
+-			goto __update_done; \
+-		} else { \
+-			memcpy(cache+index, data, left); \
+-			ret = _gnutls_cipher_auth(ctx, cache, blocksize); \
+-			if (unlikely(ret < 0)) \
+-				return gnutls_assert_val(ret); \
+-			data += left; \
+-			length -= left; \
+-		} \
+-	} \
+-	if (length >= blocksize) { \
+-		ssize_t to_proc = (length/blocksize)*blocksize; \
+-		ret = _gnutls_cipher_auth(ctx, data, to_proc); \
+-		if (unlikely(ret < 0)) \
+-			return gnutls_assert_val(ret); \
+-		data += to_proc; \
+-		length -= to_proc; \
+-	} \
+-	if (length) \
+-		memcpy(cache, data, length); \
+-	index = length; \
+- __update_done: \
+-	; \
+-	} while(0)
+-
+-#define ENCRYPT_FINAL(ctx, dst, dst_size) do { \
+-	if (index) { \
+-		if (unlikely(dst_size < (ssize_t)index)) \
+-			return gnutls_assert_val(GNUTLS_E_SHORT_MEMORY_BUFFER); \
+-		ret = _gnutls_cipher_encrypt2(ctx, cache, index, dst, dst_size); \
+-		if (unlikely(ret < 0)) \
+-			return gnutls_assert_val(ret); \
+-		dst += index; \
+-		dst_size -= index; \
+-	} \
+-	} while(0)
+-
+-#define ENCRYPT(ctx, data, length, dst, dst_size) do { \
+-	if (index) { \
+-		ssize_t left = blocksize - index; \
+-		if (length < left) { \
+-			memcpy(cache+index, data, \
+-			       length); \
+-			index += length; \
+-			goto __encrypt_done; \
+-		} else { \
+-			if (unlikely(dst_size < blocksize)) \
+-				return gnutls_assert_val(GNUTLS_E_SHORT_MEMORY_BUFFER); \
+-			memcpy(cache+index, data, left); \
+-			ret = _gnutls_cipher_encrypt2(ctx, cache, blocksize, dst, dst_size); \
+-			if (unlikely(ret < 0)) \
+-				return gnutls_assert_val(ret); \
+-			data += left; \
+-			length -= left; \
+-			dst += blocksize; \
+-			dst_size -= blocksize; \
+-		} \
+-	} \
+-	if (length >= blocksize) { \
+-		ssize_t to_proc = (length/blocksize)*blocksize; \
+-		if (unlikely(dst_size < to_proc)) \
+-			return gnutls_assert_val(GNUTLS_E_SHORT_MEMORY_BUFFER); \
+-		ret = _gnutls_cipher_encrypt2(ctx, data, to_proc, dst, dst_size); \
+-		if (unlikely(ret < 0)) \
+-			return gnutls_assert_val(ret); \
+-		data += to_proc; \
+-		length -= to_proc; \
+-		dst += to_proc; \
+-		dst_size -= to_proc; \
+-	} \
+-	if (length) \
+-		memcpy(cache, data, length); \
+-	index = length; \
+- __encrypt_done: \
+-	; \
+-	} while(0)
+-
+ 
+ /**
+  * gnutls_aead_cipher_encryptv:
+@@ -1039,14 +948,13 @@ gnutls_aead_cipher_encryptv(gnutls_aead_cipher_hd_t handle,
+ 			    void *ctext, size_t *ctext_len)
+ {
+ 	api_aead_cipher_hd_st *h = handle;
+-	int ret;
++	ssize_t ret;
+ 	uint8_t *dst;
+-	ssize_t dst_size, total = 0, len;
++	ssize_t dst_size, total = 0;
+ 	uint8_t *p;
+-	unsigned i;
+-	uint8_t cache[MAX_CIPHER_BLOCK_SIZE];
+-	unsigned index;
+ 	ssize_t blocksize = handle->ctx_enc.e->blocksize;
++	struct iov_iter_st iter;
++	size_t blocks;
+ 
+ 	/* Limitation: this function provides an optimization under the internally registered
+ 	 * AEAD ciphers. When an AEAD cipher is used registered with gnutls_crypto_register_aead_cipher(),
+@@ -1088,25 +996,64 @@ gnutls_aead_cipher_encryptv(gnutls_aead_cipher_hd_t handle,
+ 	if (unlikely(ret < 0))
+ 		return gnutls_assert_val(ret);
+ 
+-	index = 0;
+-	for (i = 0; i < (unsigned)auth_iovcnt; i++) {
+-		p = auth_iov[i].iov_base;
+-		len = auth_iov[i].iov_len;
+-		AUTH_UPDATE(&handle->ctx_enc, p, len);
++	ret = _gnutls_iov_iter_init(&iter, auth_iov, auth_iovcnt, blocksize);
++	if (unlikely(ret < 0))
++		return gnutls_assert_val(ret);
++	while (1) {
++		ret = _gnutls_iov_iter_next(&iter, &p);
++		if (unlikely(ret < 0))
++			return gnutls_assert_val(ret);
++		if (ret == 0)
++			break;
++		blocks = ret;
++		ret = _gnutls_cipher_auth(&handle->ctx_enc, p,
++					  blocksize * blocks);
++		if (unlikely(ret < 0))
++			return gnutls_assert_val(ret);
++	}
++	if (iter.block_offset > 0) {
++		ret = _gnutls_cipher_auth(&handle->ctx_enc,
++					  iter.block, iter.block_offset);
++		if (unlikely(ret < 0))
++			return gnutls_assert_val(ret);
+ 	}
+-	AUTH_UPDATE_FINAL(&handle->ctx_enc);
+ 
+ 	dst = ctext;
+ 	dst_size = *ctext_len;
+ 
+-	index = 0;
+-	for (i = 0; i < (unsigned)iovcnt; i++) {
+-		p = iov[i].iov_base;
+-		len = iov[i].iov_len;
+-		ENCRYPT(&handle->ctx_enc, p, len, dst, dst_size);
+-		total += iov[i].iov_len;
++	ret = _gnutls_iov_iter_init(&iter, iov, iovcnt, blocksize);
++	if (unlikely(ret < 0))
++		return gnutls_assert_val(ret);
++	while (1) {
++		ret = _gnutls_iov_iter_next(&iter, &p);
++		if (unlikely(ret < 0))
++			return gnutls_assert_val(ret);
++		if (ret == 0)
++			break;
++		blocks = ret;
++		if (unlikely((size_t) dst_size < blocksize * blocks))
++			return gnutls_assert_val(GNUTLS_E_SHORT_MEMORY_BUFFER);
++		ret = _gnutls_cipher_encrypt2(&handle->ctx_enc, p,
++					      blocksize * blocks,
++					      dst, dst_size);
++		if (unlikely(ret < 0))
++			return gnutls_assert_val(ret);
++		DECR_LEN(dst_size, blocksize * blocks);
++		dst += blocksize * blocks;
++		total += blocksize * blocks;
++	}
++	if (iter.block_offset > 0) {
++		if (unlikely((size_t) dst_size < iter.block_offset))
++			return gnutls_assert_val(GNUTLS_E_SHORT_MEMORY_BUFFER);
++		ret = _gnutls_cipher_encrypt2(&handle->ctx_enc,
++					      iter.block, iter.block_offset,
++					      dst, dst_size);
++		if (unlikely(ret < 0))
++			return gnutls_assert_val(ret);
++		DECR_LEN(dst_size, iter.block_offset);
++		dst += iter.block_offset;
++		total += iter.block_offset;
+ 	}
+-	ENCRYPT_FINAL(&handle->ctx_enc, dst, dst_size);
+ 
+ 	if ((size_t)dst_size < tag_size)
+ 		return gnutls_assert_val(GNUTLS_E_SHORT_MEMORY_BUFFER);
+-- 
+2.21.0
+
+
+From d230011cdbbe55f429b43d818c75c8f6687cbc78 Mon Sep 17 00:00:00 2001
+From: Daiki Ueno <dueno@redhat.com>
+Date: Fri, 2 Aug 2019 07:40:44 +0200
+Subject: [PATCH 3/3] crypto-api: add gnutls_aead_cipher_{en,de}cryptv2
+
+This adds an in-place equivalent of gnutls_aead_cipher_encrypt() and
+gnutls_aead_cipher_decrypt(), that works on data buffers.
+
+Signed-off-by: Daiki Ueno <dueno@redhat.com>
+---
+ .gitignore                        |   1 +
+ NEWS                              |   7 +
+ devel/libgnutls-latest-x86_64.abi |  26 +++
+ devel/symbols.last                |   3 +
+ doc/Makefile.am                   |   4 +
+ doc/manpages/Makefile.am          |   2 +
+ lib/crypto-api.c                  | 356 +++++++++++++++++++++++++++++-
+ lib/includes/gnutls/crypto.h      |  14 ++
+ lib/libgnutls.map                 |   7 +
+ tests/Makefile.am                 |   2 +-
+ tests/aead-cipher-vec.c           | 123 +++++++++++
+ 11 files changed, 541 insertions(+), 4 deletions(-)
+ create mode 100644 tests/aead-cipher-vec.c
+
+diff --git a/doc/Makefile.am b/doc/Makefile.am
+index 6d21d7482..add63c23d 100644
+--- a/doc/Makefile.am
++++ b/doc/Makefile.am
+@@ -635,12 +635,16 @@ FUNCS += functions/dane_verify_session_crt
+ FUNCS += functions/dane_verify_session_crt.short
+ FUNCS += functions/gnutls_aead_cipher_decrypt
+ FUNCS += functions/gnutls_aead_cipher_decrypt.short
++FUNCS += functions/gnutls_aead_cipher_decryptv2
++FUNCS += functions/gnutls_aead_cipher_decryptv2.short
+ FUNCS += functions/gnutls_aead_cipher_deinit
+ FUNCS += functions/gnutls_aead_cipher_deinit.short
+ FUNCS += functions/gnutls_aead_cipher_encrypt
+ FUNCS += functions/gnutls_aead_cipher_encrypt.short
+ FUNCS += functions/gnutls_aead_cipher_encryptv
+ FUNCS += functions/gnutls_aead_cipher_encryptv.short
++FUNCS += functions/gnutls_aead_cipher_encryptv2
++FUNCS += functions/gnutls_aead_cipher_encryptv2.short
+ FUNCS += functions/gnutls_aead_cipher_init
+ FUNCS += functions/gnutls_aead_cipher_init.short
+ FUNCS += functions/gnutls_alert_get
+diff --git a/doc/manpages/Makefile.am b/doc/manpages/Makefile.am
+index d06c18013..ee855adf3 100644
+--- a/doc/manpages/Makefile.am
++++ b/doc/manpages/Makefile.am
+@@ -119,9 +119,11 @@ APIMANS += dane_verify_crt.3
+ APIMANS += dane_verify_crt_raw.3
+ APIMANS += dane_verify_session_crt.3
+ APIMANS += gnutls_aead_cipher_decrypt.3
++APIMANS += gnutls_aead_cipher_decryptv2.3
+ APIMANS += gnutls_aead_cipher_deinit.3
+ APIMANS += gnutls_aead_cipher_encrypt.3
+ APIMANS += gnutls_aead_cipher_encryptv.3
++APIMANS += gnutls_aead_cipher_encryptv2.3
+ APIMANS += gnutls_aead_cipher_init.3
+ APIMANS += gnutls_alert_get.3
+ APIMANS += gnutls_alert_get_name.3
+diff --git a/lib/crypto-api.c b/lib/crypto-api.c
+index 70107fed0..2834c0199 100644
+--- a/lib/crypto-api.c
++++ b/lib/crypto-api.c
+@@ -885,7 +885,26 @@ static void iov_store_free(struct iov_store_st *s)
+ 	}
+ }
+ 
+-static int copy_iov(struct iov_store_st *dst, const giovec_t *iov, int iovcnt)
++static int iov_store_grow(struct iov_store_st *s, size_t length)
++{
++	if (s->allocated || s->data == NULL) {
++		s->size += length;
++		s->data = gnutls_realloc(s->data, s->size);
++		if (s->data == NULL)
++			return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
++		s->allocated = 1;
++	} else {
++		void *data = s->data;
++		size_t size = s->size + length;
++		s->data = gnutls_malloc(size);
++		memcpy(s->data, data, s->size);
++		s->size += length;
++	}
++	return 0;
++}
++
++static int
++copy_from_iov(struct iov_store_st *dst, const giovec_t *iov, int iovcnt)
+ {
+ 	memset(dst, 0, sizeof(*dst));
+ 	if (iovcnt == 0) {
+@@ -917,6 +936,27 @@ static int copy_iov(struct iov_store_st *dst, const giovec_t *iov, int iovcnt)
+ 	}
+ }
+ 
++static int
++copy_to_iov(struct iov_store_st *src, size_t size,
++	    const giovec_t *iov, int iovcnt)
++{
++	size_t offset = 0;
++	int i;
++
++	if (unlikely(src->size < size))
++		return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
++
++	for (i = 0; i < iovcnt && size > 0; i++) {
++		size_t to_copy = MIN(size, iov[i].iov_len);
++		memcpy(iov[i].iov_base, (uint8_t *) src->data + offset, to_copy);
++		offset += to_copy;
++		size -= to_copy;
++	}
++	if (size > 0)
++		return gnutls_assert_val(GNUTLS_E_SHORT_MEMORY_BUFFER);
++	return 0;
++}
++
+ 
+ /**
+  * gnutls_aead_cipher_encryptv:
+@@ -971,11 +1011,11 @@ gnutls_aead_cipher_encryptv(gnutls_aead_cipher_hd_t handle,
+ 		struct iov_store_st auth;
+ 		struct iov_store_st ptext;
+ 
+-		ret = copy_iov(&auth, auth_iov, auth_iovcnt);
++		ret = copy_from_iov(&auth, auth_iov, auth_iovcnt);
+ 		if (ret < 0)
+ 			return gnutls_assert_val(ret);
+ 
+-		ret = copy_iov(&ptext, iov, iovcnt);
++		ret = copy_from_iov(&ptext, iov, iovcnt);
+ 		if (ret < 0) {
+ 			iov_store_free(&auth);
+ 			return gnutls_assert_val(ret);
+@@ -1066,6 +1106,316 @@ gnutls_aead_cipher_encryptv(gnutls_aead_cipher_hd_t handle,
+ 	return 0;
+ }
+ 
++/**
++ * gnutls_aead_cipher_encryptv2:
++ * @handle: is a #gnutls_aead_cipher_hd_t type.
++ * @nonce: the nonce to set
++ * @nonce_len: The length of the nonce
++ * @auth_iov: additional data to be authenticated
++ * @auth_iovcnt: The number of buffers in @auth_iov
++ * @iov: the data to be encrypted
++ * @iovcnt: The number of buffers in @iov
++ * @tag: The authentication tag
++ * @tag_size: The size of the tag to use (use zero for the default)
++ *
++ * This is similar to gnutls_aead_cipher_encrypt(), but it performs
++ * in-place encryption on the provided data buffers.
++ *
++ * Returns: Zero or a negative error code on error.
++ *
++ * Since: 3.6.10
++ **/
++int
++gnutls_aead_cipher_encryptv2(gnutls_aead_cipher_hd_t handle,
++			     const void *nonce, size_t nonce_len,
++			     const giovec_t *auth_iov, int auth_iovcnt,
++			     const giovec_t *iov, int iovcnt,
++			     void *tag, size_t *tag_size)
++{
++	api_aead_cipher_hd_st *h = handle;
++	ssize_t ret;
++	uint8_t *p;
++	ssize_t blocksize = handle->ctx_enc.e->blocksize;
++	struct iov_iter_st iter;
++	size_t blocks;
++	size_t _tag_size;
++
++	if (tag_size == NULL || *tag_size == 0)
++		_tag_size = _gnutls_cipher_get_tag_size(h->ctx_enc.e);
++	else
++		_tag_size = *tag_size;
++
++	if (_tag_size > (unsigned)_gnutls_cipher_get_tag_size(h->ctx_enc.e))
++		return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
++
++	/* Limitation: this function provides an optimization under the internally registered
++	 * AEAD ciphers. When an AEAD cipher is used registered with gnutls_crypto_register_aead_cipher(),
++	 * then this becomes a convenience function as it missed the lower-level primitives
++	 * necessary for piecemeal encryption. */
++	if (handle->ctx_enc.e->only_aead || handle->ctx_enc.encrypt == NULL) {
++		/* ciphertext cannot be produced in a piecemeal approach */
++		struct iov_store_st auth;
++		struct iov_store_st ptext;
++		size_t ptext_size;
++
++		ret = copy_from_iov(&auth, auth_iov, auth_iovcnt);
++		if (ret < 0)
++			return gnutls_assert_val(ret);
++
++		ret = copy_from_iov(&ptext, iov, iovcnt);
++		if (ret < 0) {
++			gnutls_assert();
++			goto fallback_fail;
++		}
++
++		ptext_size = ptext.size;
++
++		/* append space for tag */
++		ret = iov_store_grow(&ptext, _tag_size);
++		if (ret < 0) {
++			gnutls_assert();
++			goto fallback_fail;
++		}
++
++		ret = gnutls_aead_cipher_encrypt(handle, nonce, nonce_len,
++						 auth.data, auth.size,
++						 _tag_size,
++						 ptext.data, ptext_size,
++						 ptext.data, &ptext.size);
++		if (ret < 0) {
++			gnutls_assert();
++			goto fallback_fail;
++		}
++
++		ret = copy_to_iov(&ptext, ptext_size, iov, iovcnt);
++		if (ret < 0) {
++			gnutls_assert();
++			goto fallback_fail;
++		}
++
++		if (tag != NULL)
++			memcpy(tag,
++			       (uint8_t *) ptext.data + ptext_size,
++			       _tag_size);
++		if (tag_size != NULL)
++			*tag_size = _tag_size;
++
++	fallback_fail:
++		iov_store_free(&auth);
++		iov_store_free(&ptext);
++
++		return ret;
++	}
++
++	ret = _gnutls_cipher_setiv(&handle->ctx_enc, nonce, nonce_len);
++	if (unlikely(ret < 0))
++		return gnutls_assert_val(ret);
++
++	ret = _gnutls_iov_iter_init(&iter, auth_iov, auth_iovcnt, blocksize);
++	if (unlikely(ret < 0))
++		return gnutls_assert_val(ret);
++	while (1) {
++		ret = _gnutls_iov_iter_next(&iter, &p);
++		if (unlikely(ret < 0))
++			return gnutls_assert_val(ret);
++		if (ret == 0)
++			break;
++		blocks = ret;
++		ret = _gnutls_cipher_auth(&handle->ctx_enc, p,
++					  blocksize * blocks);
++		if (unlikely(ret < 0))
++			return gnutls_assert_val(ret);
++	}
++	if (iter.block_offset > 0) {
++		ret = _gnutls_cipher_auth(&handle->ctx_enc,
++					  iter.block, iter.block_offset);
++		if (unlikely(ret < 0))
++			return gnutls_assert_val(ret);
++	}
++
++	ret = _gnutls_iov_iter_init(&iter, iov, iovcnt, blocksize);
++	if (unlikely(ret < 0))
++		return gnutls_assert_val(ret);
++	while (1) {
++		ret = _gnutls_iov_iter_next(&iter, &p);
++		if (unlikely(ret < 0))
++			return gnutls_assert_val(ret);
++		if (ret == 0)
++			break;
++		blocks = ret;
++		ret = _gnutls_cipher_encrypt2(&handle->ctx_enc,
++					      p, blocksize * blocks,
++					      p, blocksize * blocks);
++		if (unlikely(ret < 0))
++			return gnutls_assert_val(ret);
++	}
++	if (iter.block_offset > 0) {
++		ret = _gnutls_cipher_encrypt2(&handle->ctx_enc,
++					      iter.block, iter.block_offset,
++					      iter.block, iter.block_offset);
++		if (unlikely(ret < 0))
++			return gnutls_assert_val(ret);
++	}
++
++	if (tag != NULL)
++		_gnutls_cipher_tag(&handle->ctx_enc, tag, _tag_size);
++	if (tag_size != NULL)
++		*tag_size = _tag_size;
++
++	return 0;
++}
++
++/**
++ * gnutls_aead_cipher_decryptv2:
++ * @handle: is a #gnutls_aead_cipher_hd_t type.
++ * @nonce: the nonce to set
++ * @nonce_len: The length of the nonce
++ * @auth_iov: additional data to be authenticated
++ * @auth_iovcnt: The number of buffers in @auth_iov
++ * @iov: the data to decrypt
++ * @iovcnt: The number of buffers in @iov
++ * @tag: The authentication tag
++ * @tag_size: The size of the tag to use (use zero for the default)
++ *
++ * This is similar to gnutls_aead_cipher_decrypt(), but it performs
++ * in-place encryption on the provided data buffers.
++ *
++ * Returns: Zero or a negative error code on error.
++ *
++ * Since: 3.6.10
++ **/
++int
++gnutls_aead_cipher_decryptv2(gnutls_aead_cipher_hd_t handle,
++			     const void *nonce, size_t nonce_len,
++			     const giovec_t *auth_iov, int auth_iovcnt,
++			     const giovec_t *iov, int iovcnt,
++			     void *tag, size_t tag_size)
++{
++	api_aead_cipher_hd_st *h = handle;
++	ssize_t ret;
++	uint8_t *p;
++	ssize_t blocksize = handle->ctx_enc.e->blocksize;
++	struct iov_iter_st iter;
++	size_t blocks;
++	uint8_t _tag[MAX_HASH_SIZE];
++
++	if (tag_size == 0)
++		tag_size = _gnutls_cipher_get_tag_size(h->ctx_enc.e);
++	else if (tag_size > (unsigned)_gnutls_cipher_get_tag_size(h->ctx_enc.e))
++		return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
++
++	/* Limitation: this function provides an optimization under the internally registered
++	 * AEAD ciphers. When an AEAD cipher is used registered with gnutls_crypto_register_aead_cipher(),
++	 * then this becomes a convenience function as it missed the lower-level primitives
++	 * necessary for piecemeal encryption. */
++	if (handle->ctx_enc.e->only_aead || handle->ctx_enc.encrypt == NULL) {
++		/* ciphertext cannot be produced in a piecemeal approach */
++		struct iov_store_st auth;
++		struct iov_store_st ctext;
++		size_t ctext_size;
++
++		ret = copy_from_iov(&auth, auth_iov, auth_iovcnt);
++		if (ret < 0)
++			return gnutls_assert_val(ret);
++
++		ret = copy_from_iov(&ctext, iov, iovcnt);
++		if (ret < 0) {
++			gnutls_assert();
++			goto fallback_fail;
++		}
++
++		ctext_size = ctext.size;
++
++		/* append tag */
++		ret = iov_store_grow(&ctext, tag_size);
++		if (ret < 0) {
++			gnutls_assert();
++			goto fallback_fail;
++		}
++		memcpy((uint8_t *) ctext.data + ctext_size, tag, tag_size);
++
++		ret = gnutls_aead_cipher_decrypt(handle, nonce, nonce_len,
++						 auth.data, auth.size,
++						 tag_size,
++						 ctext.data, ctext.size,
++						 ctext.data, &ctext_size);
++		if (ret < 0) {
++			gnutls_assert();
++			goto fallback_fail;
++		}
++
++		ret = copy_to_iov(&ctext, ctext_size, iov, iovcnt);
++		if (ret < 0) {
++			gnutls_assert();
++			goto fallback_fail;
++		}
++
++	fallback_fail:
++		iov_store_free(&auth);
++		iov_store_free(&ctext);
++
++		return ret;
++	}
++
++	ret = _gnutls_cipher_setiv(&handle->ctx_enc, nonce, nonce_len);
++	if (unlikely(ret < 0))
++		return gnutls_assert_val(ret);
++
++	ret = _gnutls_iov_iter_init(&iter, auth_iov, auth_iovcnt, blocksize);
++	if (unlikely(ret < 0))
++		return gnutls_assert_val(ret);
++	while (1) {
++		ret = _gnutls_iov_iter_next(&iter, &p);
++		if (unlikely(ret < 0))
++			return gnutls_assert_val(ret);
++		if (ret == 0)
++			break;
++		blocks = ret;
++		ret = _gnutls_cipher_auth(&handle->ctx_enc, p,
++					  blocksize * blocks);
++		if (unlikely(ret < 0))
++			return gnutls_assert_val(ret);
++	}
++	if (iter.block_offset > 0) {
++		ret = _gnutls_cipher_auth(&handle->ctx_enc,
++					  iter.block, iter.block_offset);
++		if (unlikely(ret < 0))
++			return gnutls_assert_val(ret);
++	}
++
++	ret = _gnutls_iov_iter_init(&iter, iov, iovcnt, blocksize);
++	if (unlikely(ret < 0))
++		return gnutls_assert_val(ret);
++	while (1) {
++		ret = _gnutls_iov_iter_next(&iter, &p);
++		if (unlikely(ret < 0))
++			return gnutls_assert_val(ret);
++		if (ret == 0)
++			break;
++		blocks = ret;
++		ret = _gnutls_cipher_decrypt2(&handle->ctx_enc,
++					      p, blocksize * blocks,
++					      p, blocksize * blocks);
++		if (unlikely(ret < 0))
++			return gnutls_assert_val(ret);
++	}
++	if (iter.block_offset > 0) {
++		ret = _gnutls_cipher_decrypt2(&handle->ctx_enc,
++					      iter.block, iter.block_offset,
++					      iter.block, iter.block_offset);
++		if (unlikely(ret < 0))
++			return gnutls_assert_val(ret);
++	}
++
++	if (tag != NULL) {
++		_gnutls_cipher_tag(&handle->ctx_enc, _tag, tag_size);
++		if (gnutls_memcmp(_tag, tag, tag_size) != 0)
++			return gnutls_assert_val(GNUTLS_E_DECRYPTION_FAILED);
++	}
++
++	return 0;
++}
++
+ /**
+  * gnutls_aead_cipher_deinit:
+  * @handle: is a #gnutls_aead_cipher_hd_t type.
+diff --git a/lib/includes/gnutls/crypto.h b/lib/includes/gnutls/crypto.h
+index d2b8cae8f..4d4926c86 100644
+--- a/lib/includes/gnutls/crypto.h
++++ b/lib/includes/gnutls/crypto.h
+@@ -92,6 +92,20 @@ gnutls_aead_cipher_encryptv(gnutls_aead_cipher_hd_t handle,
+ 			    const giovec_t *iov, int iovcnt,
+ 			    void *ctext, size_t *ctext_len);
+ 
++int
++gnutls_aead_cipher_encryptv2(gnutls_aead_cipher_hd_t handle,
++			     const void *nonce, size_t nonce_len,
++			     const giovec_t *auth_iov, int auth_iovcnt,
++			     const giovec_t *iov, int iovcnt,
++			     void *tag, size_t *tag_size);
++
++int
++gnutls_aead_cipher_decryptv2(gnutls_aead_cipher_hd_t handle,
++			     const void *nonce, size_t nonce_len,
++			     const giovec_t *auth_iov, int auth_iovcnt,
++			     const giovec_t *iov, int iovcnt,
++			     void *tag, size_t tag_size);
++
+ void gnutls_aead_cipher_deinit(gnutls_aead_cipher_hd_t handle);
+ 
+ /* Hash - MAC API */
+diff --git a/lib/libgnutls.map b/lib/libgnutls.map
+index fc93c0857..f83a21e9b 100644
+--- a/lib/libgnutls.map
++++ b/lib/libgnutls.map
+@@ -1286,6 +1286,13 @@ GNUTLS_3_6_8
+ 	gnutls_ffdhe_8192_group_q;
+ } GNUTLS_3_6_6;
+ 
++GNUTLS_3_6_10
++{
++ global:
++	gnutls_aead_cipher_encryptv2;
++	gnutls_aead_cipher_decryptv2;
++} GNUTLS_3_6_8;
++
+ GNUTLS_FIPS140_3_4 {
+   global:
+ 	gnutls_cipher_self_test;
+diff --git a/tests/Makefile.am b/tests/Makefile.am
+index a2883570f..075c2728f 100644
+--- a/tests/Makefile.am
++++ b/tests/Makefile.am
+@@ -212,7 +212,7 @@ ctests += mini-record-2 simple gnutls_hm
+ 	 null_retrieve_function tls-record-size-limit tls-crt_type-neg \
+ 	 resume-with-stek-expiration resume-with-previous-stek rawpk-api \
+ 	 tls-record-size-limit-asym dh-compute ecdh-compute \
+-	 sign-verify-deterministic iov
++	 sign-verify-deterministic iov aead-cipher-vec
+ 
+ if HAVE_SECCOMP_TESTS
+ ctests += dtls-with-seccomp tls-with-seccomp dtls-client-with-seccomp tls-client-with-seccomp
+diff --git a/tests/aead-cipher-vec.c b/tests/aead-cipher-vec.c
+new file mode 100644
+index 000000000..6c2542cf1
+--- /dev/null
++++ b/tests/aead-cipher-vec.c
+@@ -0,0 +1,123 @@
++/*
++ * Copyright (C) 2019 Red Hat, Inc.
++ *
++ * Author: Daiki Ueno
++ *
++ * This file is part of GnuTLS.
++ *
++ * GnuTLS is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 3 of the License, or
++ * (at your option) any later version.
++ *
++ * GnuTLS 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 a copy of the GNU Lesser General Public License
++ * along with this program.  If not, see <https://www.gnu.org/licenses/>
++ */
++
++#ifdef HAVE_CONFIG_H
++#include <config.h>
++#endif
++
++#include <gnutls/crypto.h>
++
++#include <assert.h>
++#include <stdint.h>
++#include <string.h>
++#include "utils.h"
++
++static void tls_log_func(int level, const char *str)
++{
++	fprintf(stderr, "<%d>| %s", level, str);
++}
++
++/* Test whether gnutls_aead_cipher_{en,de}crypt_vec works */
++static void start(const char *name, int algo)
++{
++	int ret;
++	gnutls_aead_cipher_hd_t ch;
++	uint8_t key16[64];
++	uint8_t iv16[32];
++	uint8_t auth[128];
++	uint8_t data[128+64];
++	gnutls_datum_t key, iv;
++	giovec_t iov[2];
++	giovec_t auth_iov[2];
++	uint8_t tag[64];
++	size_t tag_size = 0;
++
++	key.data = key16;
++	key.size = gnutls_cipher_get_key_size(algo);
++	assert(key.size <= sizeof(key16));
++
++	iv.data = iv16;
++	iv.size = gnutls_cipher_get_iv_size(algo);
++	assert(iv.size <= sizeof(iv16));
++
++	memset(iv.data, 0xff, iv.size);
++	memset(key.data, 0xfe, key.size);
++	memset(data, 0xfa, 128);
++	memset(auth, 0xaa, sizeof(auth));
++
++	iov[0].iov_base = data;
++	iov[0].iov_len = 64;
++	iov[1].iov_base = data + 64;
++	iov[1].iov_len = 64;
++
++	auth_iov[0].iov_base = auth;
++	auth_iov[0].iov_len = 64;
++	auth_iov[1].iov_base = auth + 64;
++	auth_iov[1].iov_len = 64;
++
++	success("trying %s\n", name);
++
++	ret =
++	    gnutls_aead_cipher_init(&ch, algo, &key);
++	if (ret < 0)
++		fail("gnutls_cipher_init: %s\n", gnutls_strerror(ret));
++
++	ret = gnutls_aead_cipher_encryptv2(ch,
++					   iv.data, iv.size,
++					   auth_iov, 2,
++					   iov, 2,
++					   tag, &tag_size);
++	if (ret < 0)
++		fail("could not encrypt data: %s\n", gnutls_strerror(ret));
++
++	ret = gnutls_aead_cipher_decryptv2(ch,
++					   iv.data, iv.size,
++					   auth_iov, 2,
++					   iov, 2,
++					   tag, tag_size);
++	if (ret < 0)
++		fail("could not decrypt data: %s\n", gnutls_strerror(ret));
++
++	gnutls_aead_cipher_deinit(ch);
++}
++
++void
++doit(void)
++{
++	int ret;
++
++	gnutls_global_set_log_function(tls_log_func);
++	if (debug)
++		gnutls_global_set_log_level(4711);
++
++	ret = global_init();
++	if (ret < 0) {
++		fail("Cannot initialize library\n"); /*errcode 1 */
++	}
++
++	start("aes-128-gcm", GNUTLS_CIPHER_AES_128_GCM);
++	start("aes-256-gcm", GNUTLS_CIPHER_AES_256_GCM);
++	start("aes-128-ccm", GNUTLS_CIPHER_AES_128_CCM);
++	if (!gnutls_fips140_mode_enabled())
++		start("chacha20-poly1305", GNUTLS_CIPHER_CHACHA20_POLY1305);
++
++	gnutls_global_deinit();
++}
+-- 
+2.21.0
+
diff --git a/SOURCES/gnutls-3.6.8-fips-aes-cbc-kat.patch b/SOURCES/gnutls-3.6.8-fips-aes-cbc-kat.patch
new file mode 100644
index 0000000..016a6bf
--- /dev/null
+++ b/SOURCES/gnutls-3.6.8-fips-aes-cbc-kat.patch
@@ -0,0 +1,36 @@
+From facea2b7659e11efce7014bda8800574d35dd05d Mon Sep 17 00:00:00 2001
+From: Daiki Ueno <dueno@redhat.com>
+Date: Wed, 12 Jun 2019 14:02:05 +0200
+Subject: [PATCH] fips: run selftests over overridden AES-CBC algorithm
+
+Previously, we only tested nettle's AES-CBC in
+_gnutls_fips_perform_self_checks1(), which is called before the
+implementation is overridden.  This adds an AES-CBC self-test in
+_gnutls_fips_perform_self_checks2() so it can test the actual
+implementation.
+
+Signed-off-by: Daiki Ueno <dueno@redhat.com>
+---
+ lib/fips.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/lib/fips.c b/lib/fips.c
+index b92edbbd7..902af5674 100644
+--- a/lib/fips.c
++++ b/lib/fips.c
+@@ -317,6 +317,12 @@ int _gnutls_fips_perform_self_checks2(void)
+ 		goto error;
+ 	}
+ 
++	ret = gnutls_cipher_self_test(0, GNUTLS_CIPHER_AES_256_CBC);
++	if (ret < 0) {
++		gnutls_assert();
++		goto error;
++	}
++
+ 	ret = gnutls_cipher_self_test(0, GNUTLS_CIPHER_AES_256_GCM);
+ 	if (ret < 0) {
+ 		gnutls_assert();
+-- 
+2.20.1
+
diff --git a/SOURCES/gnutls-3.6.8-fips-deterministic-ecdsa.patch b/SOURCES/gnutls-3.6.8-fips-deterministic-ecdsa.patch
new file mode 100644
index 0000000..5be6209
--- /dev/null
+++ b/SOURCES/gnutls-3.6.8-fips-deterministic-ecdsa.patch
@@ -0,0 +1,1352 @@
+From e94ab6b703ee50ea020565e1b8729a9b1d524d84 Mon Sep 17 00:00:00 2001
+From: Daiki Ueno <dueno@redhat.com>
+Date: Mon, 29 Jul 2019 14:00:30 +0200
+Subject: [PATCH 1/6] nettle: add functions for deterministic ECDSA/DSA
+
+This adds functions to perform deterministic ECDSA/DSA, namely
+_gnutls_{ecdsa,dsa}_compute_k(), which computes the k value according
+to RFC 6979.  The retrieved k value can be given to
+nettle_{ecdsa,dsa}_sign() through a wrapper random function.
+
+Signed-off-by: Daiki Ueno <dueno@redhat.com>
+---
+ lib/nettle/Makefile.am           |   5 +-
+ lib/nettle/int/dsa-compute-k.c   | 209 +++++++++++++++++++++++++++++++
+ lib/nettle/int/dsa-compute-k.h   |  37 ++++++
+ lib/nettle/int/ecdsa-compute-k.c |  95 ++++++++++++++
+ lib/nettle/int/ecdsa-compute-k.h |  37 ++++++
+ lib/nettle/int/mpn-base256.c     |  97 ++++++++++++++
+ lib/nettle/int/mpn-base256.h     |  48 +++++++
+ 7 files changed, 527 insertions(+), 1 deletion(-)
+ create mode 100644 lib/nettle/int/dsa-compute-k.c
+ create mode 100644 lib/nettle/int/dsa-compute-k.h
+ create mode 100644 lib/nettle/int/ecdsa-compute-k.c
+ create mode 100644 lib/nettle/int/ecdsa-compute-k.h
+ create mode 100644 lib/nettle/int/mpn-base256.c
+ create mode 100644 lib/nettle/int/mpn-base256.h
+
+diff --git a/lib/nettle/Makefile.am b/lib/nettle/Makefile.am
+index 1c60d3244..bd9dd753a 100644
+--- a/lib/nettle/Makefile.am
++++ b/lib/nettle/Makefile.am
+@@ -45,7 +45,10 @@ libcrypto_la_SOURCES = pk.c mpi.c mac.c cipher.c init.c \
+ 	backport/xts.c backport/xts.h \
+ 	rnd.c int/rsa-fips.h int/rsa-keygen-fips186.c int/provable-prime.c \
+ 	int/dsa-fips.h int/dsa-keygen-fips186.c int/dsa-validate.c \
+-	int/tls1-prf.c int/tls1-prf.h
++	int/tls1-prf.c int/tls1-prf.h \
++	int/dsa-compute-k.c int/dsa-compute-k.h \
++	int/ecdsa-compute-k.c int/ecdsa-compute-k.h \
++	int/mpn-base256.c int/mpn-base256.h
+ 
+ if WINDOWS
+ libcrypto_la_SOURCES += sysrng-windows.c
+diff --git a/lib/nettle/int/dsa-compute-k.c b/lib/nettle/int/dsa-compute-k.c
+new file mode 100644
+index 000000000..17d63318c
+--- /dev/null
++++ b/lib/nettle/int/dsa-compute-k.c
+@@ -0,0 +1,209 @@
++/*
++ * Copyright (C) 2019 Red Hat, Inc.
++ *
++ * Author: Daiki Ueno
++ *
++ * This file is part of GNUTLS.
++ *
++ * The GNUTLS library 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 <https://www.gnu.org/licenses/>
++ *
++ */
++
++#if HAVE_CONFIG_H
++# include "config.h"
++#endif
++
++#include "dsa-compute-k.h"
++
++#include "gnutls_int.h"
++#include "mem.h"
++#include "mpn-base256.h"
++#include <string.h>
++
++#define BITS_TO_LIMBS(bits) (((bits) + GMP_NUMB_BITS - 1) / GMP_NUMB_BITS)
++
++/* The maximum size of q, choosen from the fact that we support
++ * 521-bit elliptic curve generator and 512-bit DSA subgroup at
++ * maximum. */
++#define MAX_Q_BITS 521
++#define MAX_Q_SIZE ((MAX_Q_BITS + 7) / 8)
++#define MAX_Q_LIMBS BITS_TO_LIMBS(MAX_Q_BITS)
++
++#define MAX_HASH_BITS (MAX_HASH_SIZE * 8)
++#define MAX_HASH_LIMBS BITS_TO_LIMBS(MAX_HASH_BITS)
++
++int
++_gnutls_dsa_compute_k(mpz_t k,
++		      const mpz_t q,
++		      const mpz_t x,
++		      gnutls_mac_algorithm_t mac,
++		      const uint8_t *digest,
++		      size_t length)
++{
++	uint8_t V[MAX_HASH_SIZE];
++	uint8_t K[MAX_HASH_SIZE];
++	uint8_t xp[MAX_Q_SIZE];
++	uint8_t tp[MAX_Q_SIZE];
++	mp_limb_t h[MAX(MAX_Q_LIMBS, MAX_HASH_LIMBS)];
++	mp_bitcnt_t q_bits = mpz_sizeinbase (q, 2);
++	mp_size_t qn = mpz_size(q);
++	mp_bitcnt_t h_bits = length * 8;
++	mp_size_t hn = BITS_TO_LIMBS(h_bits);
++	size_t nbytes = (q_bits + 7) / 8;
++	const uint8_t c0 = 0x00;
++	const uint8_t c1 = 0x01;
++	mp_limb_t cy;
++	gnutls_hmac_hd_t hd;
++	int ret = 0;
++
++	if (unlikely(q_bits > MAX_Q_BITS))
++		return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
++	if (unlikely(length > MAX_HASH_SIZE))
++		return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
++
++	/* int2octets(x) */
++	mpn_get_base256(xp, nbytes, mpz_limbs_read(x), qn);
++
++	/* bits2octets(h) */
++	mpn_set_base256(h, hn, digest, length);
++
++	if (hn < qn)
++		/* qlen > blen: add zero bits to the left */
++		mpn_zero(&h[hn], qn - hn);
++	else if (h_bits > q_bits) {
++		/* qlen < blen: keep the leftmost qlen bits.  We do this in 2
++		 * steps because mpn_rshift only accepts shift count in the
++		 * range 1 to mp_bits_per_limb-1.
++		 */
++		mp_bitcnt_t shift = h_bits - q_bits;
++
++		if (shift / GMP_NUMB_BITS > 0) {
++			mpn_copyi(h, &h[shift / GMP_NUMB_BITS], qn);
++			hn -= shift / GMP_NUMB_BITS;
++		}
++
++		if (shift % GMP_NUMB_BITS > 0)
++			mpn_rshift(h, h, hn, shift % GMP_NUMB_BITS);
++	}
++
++	cy = mpn_sub_n(h, h, mpz_limbs_read(q), qn);
++	/* Fall back to addmul_1, if nettle is linked with mini-gmp. */
++#ifdef mpn_cnd_add_n
++	mpn_cnd_add_n(cy, h, h, mpz_limbs_read(q), qn);
++#else
++	mpn_addmul_1(h, mpz_limbs_read(q), qn, cy != 0);
++#endif
++	mpn_get_base256(tp, nbytes, h, qn);
++
++	/* Step b */
++	memset(V, c1, length);
++
++	/* Step c */
++	memset(K, c0, length);
++
++	/* Step d */
++	ret = gnutls_hmac_init(&hd, mac, K, length);
++	if (ret < 0)
++		goto out;
++	ret = gnutls_hmac(hd, V, length);
++	if (ret < 0)
++		goto out;
++	ret = gnutls_hmac(hd, &c0, 1);
++	if (ret < 0)
++		goto out;
++	ret = gnutls_hmac(hd, xp, nbytes);
++	if (ret < 0)
++		goto out;
++	ret = gnutls_hmac(hd, tp, nbytes);
++	if (ret < 0)
++		goto out;
++	gnutls_hmac_deinit(hd, K);
++
++	/* Step e */
++	ret = gnutls_hmac_fast(mac, K, length, V, length, V);
++	if (ret < 0)
++		goto out;
++
++	/* Step f */
++	ret = gnutls_hmac_init(&hd, mac, K, length);
++	if (ret < 0)
++		goto out;
++	ret = gnutls_hmac(hd, V, length);
++	if (ret < 0)
++		goto out;
++	ret = gnutls_hmac(hd, &c1, 1);
++	if (ret < 0)
++		goto out;
++	ret = gnutls_hmac(hd, xp, nbytes);
++	if (ret < 0)
++		goto out;
++	ret = gnutls_hmac(hd, tp, nbytes);
++	if (ret < 0)
++		goto out;
++	gnutls_hmac_deinit(hd, K);
++
++	/* Step g */
++	ret = gnutls_hmac_fast(mac, K, length, V, length, V);
++	if (ret < 0)
++		goto out;
++
++	/* Step h */
++	for (;;) {
++		/* Step 1 */
++		size_t tlen = 0;
++
++		/* Step 2 */
++		while (tlen < nbytes) {
++			size_t remaining = MIN(nbytes - tlen, length);
++			ret = gnutls_hmac_fast(mac, K, length, V, length, V);
++			if (ret < 0)
++				goto out;
++			memcpy (&tp[tlen], V, remaining);
++			tlen += remaining;
++		}
++
++		/* Step 3 */
++		mpn_set_base256 (h, qn, tp, tlen);
++		if (tlen * 8 > q_bits)
++			mpn_rshift (h, h, qn, tlen * 8 - q_bits);
++		/* Check if k is in [1,q-1] */
++		if (!mpn_zero_p (h, qn) &&
++		    mpn_cmp (h, mpz_limbs_read(q), qn) < 0) {
++			mpn_copyi(mpz_limbs_write(k, qn), h, qn);
++			mpz_limbs_finish(k, qn);
++			break;
++		}
++
++		ret = gnutls_hmac_init(&hd, mac, K, length);
++		if (ret < 0)
++			goto out;
++		ret = gnutls_hmac(hd, V, length);
++		if (ret < 0)
++			goto out;
++		ret = gnutls_hmac(hd, &c0, 1);
++		if (ret < 0)
++			goto out;
++		gnutls_hmac_deinit(hd, K);
++
++		ret = gnutls_hmac_fast(mac, K, length, V, length, V);
++		if (ret < 0)
++			goto out;
++	}
++
++ out:
++	zeroize_key(xp, sizeof(xp));
++	zeroize_key(tp, sizeof(tp));
++
++	return ret;
++}
+diff --git a/lib/nettle/int/dsa-compute-k.h b/lib/nettle/int/dsa-compute-k.h
+new file mode 100644
+index 000000000..64e90e0ca
+--- /dev/null
++++ b/lib/nettle/int/dsa-compute-k.h
+@@ -0,0 +1,37 @@
++/*
++ * Copyright (C) 2019 Red Hat, Inc.
++ *
++ * Author: Daiki Ueno
++ *
++ * 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/>
++ *
++ */
++
++#ifndef GNUTLS_LIB_NETTLE_INT_DSA_COMPUTE_K_H
++#define GNUTLS_LIB_NETTLE_INT_DSA_COMPUTE_K_H
++
++#include <gnutls/gnutls.h>
++#include <nettle/bignum.h> /* includes gmp.h */
++
++int
++_gnutls_dsa_compute_k(mpz_t k,
++		      const mpz_t q,
++		      const mpz_t x,
++		      gnutls_mac_algorithm_t mac,
++		      const uint8_t *digest,
++		      size_t length);
++
++#endif /* GNUTLS_LIB_NETTLE_INT_DSA_COMPUTE_K_H */
+diff --git a/lib/nettle/int/ecdsa-compute-k.c b/lib/nettle/int/ecdsa-compute-k.c
+new file mode 100644
+index 000000000..94914ebdf
+--- /dev/null
++++ b/lib/nettle/int/ecdsa-compute-k.c
+@@ -0,0 +1,95 @@
++/*
++ * Copyright (C) 2019 Red Hat, Inc.
++ *
++ * Author: Daiki Ueno
++ *
++ * This file is part of GNUTLS.
++ *
++ * The GNUTLS library 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 <https://www.gnu.org/licenses/>
++ *
++ */
++
++#if HAVE_CONFIG_H
++# include "config.h"
++#endif
++
++#include "ecdsa-compute-k.h"
++
++#include "dsa-compute-k.h"
++#include "gnutls_int.h"
++
++static inline int
++_gnutls_ecc_curve_to_dsa_q(mpz_t *q, gnutls_ecc_curve_t curve)
++{
++	switch (curve) {
++#ifdef ENABLE_NON_SUITEB_CURVES
++	case GNUTLS_ECC_CURVE_SECP192R1:
++		mpz_init_set_str(*q,
++				 "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836"
++				 "146BC9B1B4D22831",
++				 16);
++		return 0;
++	case GNUTLS_ECC_CURVE_SECP224R1:
++		mpz_init_set_str(*q,
++				 "FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2"
++				 "E0B8F03E13DD29455C5C2A3D",
++				 16);
++		return 0;
++#endif
++	case GNUTLS_ECC_CURVE_SECP256R1:
++		mpz_init_set_str(*q,
++				 "FFFFFFFF00000000FFFFFFFFFFFFFFFF"
++				 "BCE6FAADA7179E84F3B9CAC2FC632551",
++				 16);
++		return 0;
++	case GNUTLS_ECC_CURVE_SECP384R1:
++		mpz_init_set_str(*q,
++				 "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
++				 "FFFFFFFFFFFFFFFFC7634D81F4372DDF"
++				 "581A0DB248B0A77AECEC196ACCC52973",
++				 16);
++		return 0;
++	case GNUTLS_ECC_CURVE_SECP521R1:
++		mpz_init_set_str(*q,
++				 "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
++				 "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
++				 "FFA51868783BF2F966B7FCC0148F709A"
++				 "5D03BB5C9B8899C47AEBB6FB71E91386"
++				 "409",
++				 16);
++		return 0;
++	default:
++		return gnutls_assert_val(GNUTLS_E_UNSUPPORTED_SIGNATURE_ALGORITHM);
++	}
++}
++
++int
++_gnutls_ecdsa_compute_k (mpz_t k,
++			 gnutls_ecc_curve_t curve,
++			 const mpz_t x,
++			 gnutls_mac_algorithm_t mac,
++			 const uint8_t *digest,
++			 size_t length)
++{
++	mpz_t q;
++	int ret;
++
++	ret = _gnutls_ecc_curve_to_dsa_q(&q, curve);
++	if (ret < 0)
++		return gnutls_assert_val(ret);
++
++	ret = _gnutls_dsa_compute_k (k, q, x, mac, digest, length);
++	mpz_clear(q);
++	return ret;
++}
+diff --git a/lib/nettle/int/ecdsa-compute-k.h b/lib/nettle/int/ecdsa-compute-k.h
+new file mode 100644
+index 000000000..7ca401d6e
+--- /dev/null
++++ b/lib/nettle/int/ecdsa-compute-k.h
+@@ -0,0 +1,37 @@
++/*
++ * Copyright (C) 2019 Red Hat, Inc.
++ *
++ * Author: Daiki Ueno
++ *
++ * 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/>
++ *
++ */
++
++#ifndef GNUTLS_LIB_NETTLE_INT_ECDSA_COMPUTE_K_H
++#define GNUTLS_LIB_NETTLE_INT_ECDSA_COMPUTE_K_H
++
++#include <gnutls/gnutls.h>
++#include <nettle/bignum.h> /* includes gmp.h */
++
++int
++_gnutls_ecdsa_compute_k (mpz_t k,
++			 gnutls_ecc_curve_t curve,
++			 const mpz_t x,
++			 gnutls_mac_algorithm_t mac,
++			 const uint8_t *digest,
++			 size_t length);
++
++#endif /* GNUTLS_LIB_NETTLE_INT_ECDSA_COMPUTE_K_H */
+diff --git a/lib/nettle/int/mpn-base256.c b/lib/nettle/int/mpn-base256.c
+new file mode 100644
+index 000000000..88dd00bd2
+--- /dev/null
++++ b/lib/nettle/int/mpn-base256.c
+@@ -0,0 +1,97 @@
++/* gmp-glue.c
++
++   Copyright (C) 2013 Niels Möller
++   Copyright (C) 2013 Red Hat
++
++   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/.
++*/
++
++#if HAVE_CONFIG_H
++# include "config.h"
++#endif
++
++#include "mpn-base256.h"
++
++void
++mpn_set_base256 (mp_limb_t *rp, mp_size_t rn,
++		 const uint8_t *xp, size_t xn)
++{
++  size_t xi;
++  mp_limb_t out;
++  unsigned bits;
++  for (xi = xn, out = bits = 0; xi > 0 && rn > 0; )
++    {
++      mp_limb_t in = xp[--xi];
++      out |= (in << bits) & GMP_NUMB_MASK;
++      bits += 8;
++      if (bits >= GMP_NUMB_BITS)
++	{
++	  *rp++ = out;
++	  rn--;
++
++	  bits -= GMP_NUMB_BITS;
++	  out = in >> (8 - bits);
++	}
++    }
++  if (rn > 0)
++    {
++      *rp++ = out;
++      if (--rn > 0)
++	mpn_zero (rp, rn);
++    }
++}
++
++void
++mpn_get_base256 (uint8_t *rp, size_t rn,
++		 const mp_limb_t *xp, mp_size_t xn)
++{
++  unsigned bits;
++  mp_limb_t in;
++  for (bits = in = 0; xn > 0 && rn > 0; )
++    {
++      if (bits >= 8)
++	{
++	  rp[--rn] = in;
++	  in >>= 8;
++	  bits -= 8;
++	}
++      else
++	{
++	  uint8_t old = in;
++	  in = *xp++;
++	  xn--;
++	  rp[--rn] = old | (in << bits);
++	  in >>= (8 - bits);
++	  bits += GMP_NUMB_BITS - 8;
++	}
++    }
++  while (rn > 0)
++    {
++      rp[--rn] = in;
++      in >>= 8;
++    }
++}
+diff --git a/lib/nettle/int/mpn-base256.h b/lib/nettle/int/mpn-base256.h
+new file mode 100644
+index 000000000..b5ca4af03
+--- /dev/null
++++ b/lib/nettle/int/mpn-base256.h
+@@ -0,0 +1,48 @@
++/* gmp-glue.h
++
++   Copyright (C) 2013 Niels Möller
++   Copyright (C) 2013 Red Hat
++
++   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_GMP_GLUE_H_INCLUDED
++#define NETTLE_GMP_GLUE_H_INCLUDED
++
++#include <nettle/bignum.h>
++
++/* Like mpn_set_str, but always writes rn limbs. If input is larger,
++   higher bits are ignored. */
++void
++mpn_set_base256 (mp_limb_t *rp, mp_size_t rn,
++		 const uint8_t *xp, size_t xn);
++
++void
++mpn_get_base256 (uint8_t *rp, size_t rn,
++	         const mp_limb_t *xp, mp_size_t xn);
++
++#endif /* NETTLE_GMP_GLUE_H_INCLUDED */
+-- 
+2.21.0
+
+
+From f42d96451a654ccc3523b0a0086e18f19ba3fecc Mon Sep 17 00:00:00 2001
+From: Daiki Ueno <dueno@redhat.com>
+Date: Mon, 29 Jul 2019 15:10:51 +0200
+Subject: [PATCH 2/6] privkey_sign_raw_data: remove unnecessary local variable
+
+Signed-off-by: Daiki Ueno <dueno@redhat.com>
+---
+ lib/privkey.c | 4 +---
+ 1 file changed, 1 insertion(+), 3 deletions(-)
+
+diff --git a/lib/privkey.c b/lib/privkey.c
+index 8e353c5e5..2fee8777a 100644
+--- a/lib/privkey.c
++++ b/lib/privkey.c
+@@ -1492,8 +1492,6 @@ privkey_sign_raw_data(gnutls_privkey_t key,
+ 							   0,
+ 							   data, signature);
+ 		} else if (key->key.ext.sign_hash_func) {
+-			unsigned int flags = 0;
+-
+ 			if (se->pk == GNUTLS_PK_RSA) {
+ 				se = _gnutls_sign_to_entry(GNUTLS_SIGN_RSA_RAW);
+ 				assert(se != NULL);
+@@ -1502,7 +1500,7 @@ privkey_sign_raw_data(gnutls_privkey_t key,
+ 			/* se may not be set here if we are doing legacy RSA */
+ 			return key->key.ext.sign_hash_func(key, se->id,
+ 							   key->key.ext.userdata,
+-							   flags,
++							   0,
+ 							   data, signature);
+ 		} else {
+ 			if (!PK_IS_OK_FOR_EXT2(se->pk))
+-- 
+2.21.0
+
+
+From 3dd0df9e1a499c7b31bf7b4a315e797d2195c1ba Mon Sep 17 00:00:00 2001
+From: Daiki Ueno <dueno@redhat.com>
+Date: Wed, 7 Aug 2019 14:37:00 +0200
+Subject: [PATCH 3/6] privkey_sign_prehashed: remove unused argument
+
+Signed-off-by: Daiki Ueno <dueno@redhat.com>
+---
+ lib/privkey.c | 9 ++++-----
+ 1 file changed, 4 insertions(+), 5 deletions(-)
+
+diff --git a/lib/privkey.c b/lib/privkey.c
+index 2fee8777a..8683b4e20 100644
+--- a/lib/privkey.c
++++ b/lib/privkey.c
+@@ -43,7 +43,7 @@ privkey_sign_prehashed(gnutls_privkey_t signer,
+ 		       const gnutls_sign_entry_st *se,
+ 		       const gnutls_datum_t * hash_data,
+ 		       gnutls_datum_t * signature,
+-		       gnutls_x509_spki_st * params, unsigned flags);
++		       gnutls_x509_spki_st * params);
+ 
+ /**
+  * gnutls_privkey_get_type:
+@@ -1253,7 +1253,7 @@ gnutls_privkey_sign_hash2(gnutls_privkey_t signer,
+ 		return ret;
+ 	}
+ 
+-	return privkey_sign_prehashed(signer, se, hash_data, signature, &params, flags);
++	return privkey_sign_prehashed(signer, se, hash_data, signature, &params);
+ }
+ 
+ int
+@@ -1377,7 +1377,7 @@ gnutls_privkey_sign_hash(gnutls_privkey_t signer,
+ 		return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+ 
+ 	return privkey_sign_prehashed(signer, se,
+-				      hash_data, signature, &params, flags);
++				      hash_data, signature, &params);
+ }
+ 
+ static int
+@@ -1385,8 +1385,7 @@ privkey_sign_prehashed(gnutls_privkey_t signer,
+ 		       const gnutls_sign_entry_st *se,
+ 		       const gnutls_datum_t * hash_data,
+ 		       gnutls_datum_t * signature,
+-		       gnutls_x509_spki_st * params,
+-		       unsigned flags)
++		       gnutls_x509_spki_st * params)
+ {
+ 	int ret;
+ 	gnutls_datum_t digest;
+-- 
+2.21.0
+
+
+From 8eb3a29336ea11f6b417ce7e25d53513509bdd87 Mon Sep 17 00:00:00 2001
+From: Daiki Ueno <dueno@redhat.com>
+Date: Mon, 29 Jul 2019 14:01:11 +0200
+Subject: [PATCH 4/6] pk: implement deterministic ECDSA/DSA
+
+This exposes the deterministic ECDSA/DSA functionality through the
+GNUTLS_PRIVKEY_FLAG_REPRODUCIBLE flag.
+
+Signed-off-by: Daiki Ueno <dueno@redhat.com>
+---
+ .gitignore                        |   1 +
+ NEWS                              |   7 ++
+ lib/crypto-backend.h              |  16 ++-
+ lib/includes/gnutls/abstract.h    |   5 +-
+ lib/nettle/pk.c                   |  54 +++++++-
+ lib/privkey.c                     |   8 ++
+ lib/x509/crq.c                    |   2 +
+ lib/x509/pkcs7.c                  |   2 +
+ lib/x509/sign.c                   |   2 +
+ tests/Makefile.am                 |   2 +-
+ tests/sign-verify-deterministic.c | 196 ++++++++++++++++++++++++++++++
+ 11 files changed, 290 insertions(+), 5 deletions(-)
+ create mode 100644 tests/sign-verify-deterministic.c
+
+diff --git a/lib/crypto-backend.h b/lib/crypto-backend.h
+index 43124abaf..33eca6031 100644
+--- a/lib/crypto-backend.h
++++ b/lib/crypto-backend.h
+@@ -187,6 +187,13 @@ typedef struct gnutls_x509_spki_st {
+ 	/* if non-zero, the legacy value for PKCS#7 signatures will be
+ 	 * written for RSA signatures. */
+ 	unsigned int legacy;
++
++	/* the digest used by ECDSA/DSA */
++	gnutls_digest_algorithm_t dsa_dig;
++
++	/* flags may include GNUTLS_PK_FLAG_REPRODUCIBLE for
++	 * deterministic ECDSA/DSA */
++	unsigned int flags;
+ } gnutls_x509_spki_st;
+ 
+ #define GNUTLS_MAX_PK_PARAMS 16
+@@ -219,9 +226,16 @@ typedef struct {
+  */
+ typedef enum {
+ 	GNUTLS_PK_FLAG_NONE = 0,
+-	GNUTLS_PK_FLAG_PROVABLE = 1
++	GNUTLS_PK_FLAG_PROVABLE = 1,
++	GNUTLS_PK_FLAG_REPRODUCIBLE = 2
+ } gnutls_pk_flag_t;
+ 
++#define FIX_SIGN_PARAMS(params, flags, dig) do {		\
++	if ((flags) & GNUTLS_PRIVKEY_FLAG_REPRODUCIBLE) {	\
++		(params).flags |= GNUTLS_PK_FLAG_REPRODUCIBLE;	\
++		(params).dsa_dig = (dig);			\
++	}							\
++} while (0)
+ 
+ void gnutls_pk_params_release(gnutls_pk_params_st * p);
+ void gnutls_pk_params_clear(gnutls_pk_params_st * p);
+diff --git a/lib/includes/gnutls/abstract.h b/lib/includes/gnutls/abstract.h
+index d4b7da68b..d8805681a 100644
+--- a/lib/includes/gnutls/abstract.h
++++ b/lib/includes/gnutls/abstract.h
+@@ -371,7 +371,10 @@ int gnutls_privkey_status(gnutls_privkey_t key);
+  * gnutls_privkey_flags:
+  * @GNUTLS_PRIVKEY_SIGN_FLAG_TLS1_RSA: Make an RSA signature on the hashed data as in the TLS protocol.
+  * @GNUTLS_PRIVKEY_SIGN_FLAG_RSA_PSS: Make an RSA signature on the hashed data with the PSS padding.
+- * @GNUTLS_PRIVKEY_FLAG_REPRODUCIBLE: Make an RSA-PSS signature on the hashed data with reproducible parameters (zero salt).
++ * @GNUTLS_PRIVKEY_FLAG_REPRODUCIBLE: Make a signature on the hashed data with reproducible parameters.
++ *   For RSA-PSS, that means to use empty salt instead of random value. For ECDSA/DSA, it uses the deterministic
++ *   construction of random parameter according to RFC 6979. Note that
++ *   this only supports the NIST curves and DSA subgroup bits up to 512.
+  * @GNUTLS_PRIVKEY_IMPORT_AUTO_RELEASE: When importing a private key, automatically
+  *   release it when the structure it was imported is released.
+  * @GNUTLS_PRIVKEY_IMPORT_COPY: Copy required values during import.
+diff --git a/lib/nettle/pk.c b/lib/nettle/pk.c
+index 08117c2d8..ebd6481cf 100644
+--- a/lib/nettle/pk.c
++++ b/lib/nettle/pk.c
+@@ -54,6 +54,8 @@
+ #include "gost/gostdsa.h"
+ #include "gost/ecc-gost-curve.h"
+ #endif
++#include "int/ecdsa-compute-k.h"
++#include "int/dsa-compute-k.h"
+ #include <gnettle.h>
+ #include <fips.h>
+ 
+@@ -86,6 +88,12 @@ static void rnd_nonce_func(void *_ctx, size_t length, uint8_t * data)
+ 	}
+ }
+ 
++static void rnd_mpz_func(void *_ctx, size_t length, uint8_t * data)
++{
++	mpz_t *k = _ctx;
++	nettle_mpz_get_str_256 (length, data, *k);
++}
++
+ static void
+ ecc_scalar_zclear (struct ecc_scalar *s)
+ {
+@@ -782,6 +790,9 @@ _wrap_nettle_pk_sign(gnutls_pk_algorithm_t algo,
+ 			struct dsa_signature sig;
+ 			int curve_id = pk_params->curve;
+ 			const struct ecc_curve *curve;
++			mpz_t k;
++			void *random_ctx;
++			nettle_random_func *random_func;
+ 
+ 			curve = get_supported_nist_curve(curve_id);
+ 			if (curve == NULL)
+@@ -808,7 +819,23 @@ _wrap_nettle_pk_sign(gnutls_pk_algorithm_t algo,
+ 				hash_len = vdata->size;
+ 			}
+ 
+-			ecdsa_sign(&priv, NULL, rnd_nonce_func, hash_len,
++			mpz_init(k);
++			if (sign_params->flags & GNUTLS_PK_FLAG_REPRODUCIBLE) {
++				ret = _gnutls_ecdsa_compute_k(k,
++							      curve_id,
++							      pk_params->params[ECC_K],
++							      sign_params->dsa_dig,
++							      vdata->data,
++							      vdata->size);
++				if (ret < 0)
++					goto ecdsa_cleanup;
++				random_ctx = &k;
++				random_func = rnd_mpz_func;
++			} else {
++				random_ctx = NULL;
++				random_func = rnd_nonce_func;
++			}
++			ecdsa_sign(&priv, random_ctx, random_func, hash_len,
+ 				   vdata->data, &sig);
+ 
+ 			/* prevent memory leaks */
+@@ -824,6 +851,7 @@ _wrap_nettle_pk_sign(gnutls_pk_algorithm_t algo,
+  ecdsa_cleanup:
+ 			dsa_signature_clear(&sig);
+ 			ecc_scalar_zclear(&priv);
++			mpz_clear(k);
+ 
+ 			if (ret < 0) {
+ 				gnutls_assert();
+@@ -836,6 +864,9 @@ _wrap_nettle_pk_sign(gnutls_pk_algorithm_t algo,
+ 			struct dsa_params pub;
+ 			bigint_t priv;
+ 			struct dsa_signature sig;
++			mpz_t k;
++			void *random_ctx;
++			nettle_random_func *random_func;
+ 
+ 			memset(&priv, 0, sizeof(priv));
+ 			memset(&pub, 0, sizeof(pub));
+@@ -856,8 +887,26 @@ _wrap_nettle_pk_sign(gnutls_pk_algorithm_t algo,
+ 				hash_len = vdata->size;
+ 			}
+ 
++			mpz_init(k);
++			if (sign_params->flags & GNUTLS_PK_FLAG_REPRODUCIBLE) {
++				ret = _gnutls_dsa_compute_k(k,
++							    pub.q,
++							    TOMPZ(priv),
++							    sign_params->dsa_dig,
++							    vdata->data,
++							    vdata->size);
++				if (ret < 0)
++					goto dsa_fail;
++				/* cancel-out dsa_sign's addition of 1 to random data */
++				mpz_sub_ui (k, k, 1);
++				random_ctx = &k;
++				random_func = rnd_mpz_func;
++			} else {
++				random_ctx = NULL;
++				random_func = rnd_nonce_func;
++			}
+ 			ret =
+-			    dsa_sign(&pub, TOMPZ(priv), NULL, rnd_nonce_func,
++			    dsa_sign(&pub, TOMPZ(priv), random_ctx, random_func,
+ 				     hash_len, vdata->data, &sig);
+ 			if (ret == 0 || HAVE_LIB_ERROR()) {
+ 				gnutls_assert();
+@@ -871,6 +920,7 @@ _wrap_nettle_pk_sign(gnutls_pk_algorithm_t algo,
+ 
+  dsa_fail:
+ 			dsa_signature_clear(&sig);
++			mpz_clear(k);
+ 
+ 			if (ret < 0) {
+ 				gnutls_assert();
+diff --git a/lib/privkey.c b/lib/privkey.c
+index 8683b4e20..4ef07c8b0 100644
+--- a/lib/privkey.c
++++ b/lib/privkey.c
+@@ -1134,6 +1134,8 @@ gnutls_privkey_sign_data(gnutls_privkey_t signer,
+ 		return ret;
+ 	}
+ 
++	FIX_SIGN_PARAMS(params, flags, hash);
++
+ 	return privkey_sign_and_hash_data(signer, _gnutls_pk_to_sign_entry(params.pk, hash), data, signature, &params);
+ }
+ 
+@@ -1186,6 +1188,8 @@ gnutls_privkey_sign_data2(gnutls_privkey_t signer,
+ 		return ret;
+ 	}
+ 
++	FIX_SIGN_PARAMS(params, flags, se->hash);
++
+ 	return privkey_sign_and_hash_data(signer, se, data, signature, &params);
+ }
+ 
+@@ -1253,6 +1257,8 @@ gnutls_privkey_sign_hash2(gnutls_privkey_t signer,
+ 		return ret;
+ 	}
+ 
++	FIX_SIGN_PARAMS(params, flags, se->hash);
++
+ 	return privkey_sign_prehashed(signer, se, hash_data, signature, &params);
+ }
+ 
+@@ -1376,6 +1382,8 @@ gnutls_privkey_sign_hash(gnutls_privkey_t signer,
+ 	if (unlikely(se == NULL))
+ 		return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+ 
++	FIX_SIGN_PARAMS(params, flags, hash_algo);
++
+ 	return privkey_sign_prehashed(signer, se,
+ 				      hash_data, signature, &params);
+ }
+diff --git a/lib/x509/crq.c b/lib/x509/crq.c
+index c8899f81a..4ca67535d 100644
+--- a/lib/x509/crq.c
++++ b/lib/x509/crq.c
+@@ -2642,6 +2642,8 @@ gnutls_x509_crq_privkey_sign(gnutls_x509_crq_t crq, gnutls_privkey_t key,
+ 	if (se == NULL)
+ 		return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+ 
++	FIX_SIGN_PARAMS(params, flags, dig);
++
+ 	result = privkey_sign_and_hash_data(key, se,
+ 					    &tbs, &signature, &params);
+ 	gnutls_free(tbs.data);
+diff --git a/lib/x509/pkcs7.c b/lib/x509/pkcs7.c
+index 21fff7b07..98669e887 100644
+--- a/lib/x509/pkcs7.c
++++ b/lib/x509/pkcs7.c
+@@ -2532,6 +2532,8 @@ int gnutls_pkcs7_sign(gnutls_pkcs7_t pkcs7,
+ 		goto cleanup;
+ 	}
+ 
++	FIX_SIGN_PARAMS(params, flags, dig);
++
+ 	ret = privkey_sign_and_hash_data(signer_key, se,
+ 					 &sigdata, &signature, &params);
+ 	if (ret < 0) {
+diff --git a/lib/x509/sign.c b/lib/x509/sign.c
+index 8f7a96f21..461524f5b 100644
+--- a/lib/x509/sign.c
++++ b/lib/x509/sign.c
+@@ -175,6 +175,8 @@ _gnutls_x509_pkix_sign(ASN1_TYPE src, const char *src_name,
+ 		return result;
+ 	}
+ 
++	FIX_SIGN_PARAMS(params, flags, dig);
++
+ 	if (_gnutls_pk_is_not_prehashed(params.pk)) {
+ 		result = privkey_sign_raw_data(issuer_key, se, &tbs, &signature, &params);
+ 	} else {
+diff --git a/tests/Makefile.am b/tests/Makefile.am
+index 7970ad6b3..a8c2d152e 100644
+--- a/tests/Makefile.am
++++ b/tests/Makefile.am
+@@ -211,7 +211,8 @@ ctests += mini-record-2 simple gnutls_hm
+ 	 tls13-server-kx-neg gnutls_ext_raw_parse_dtls key-export-pkcs8 \
+ 	 null_retrieve_function tls-record-size-limit tls-crt_type-neg \
+ 	 resume-with-stek-expiration resume-with-previous-stek rawpk-api \
+-	 tls-record-size-limit-asym dh-compute ecdh-compute
++	 tls-record-size-limit-asym dh-compute ecdh-compute \
++	 sign-verify-deterministic
+ 
+ if HAVE_SECCOMP_TESTS
+ ctests += dtls-with-seccomp tls-with-seccomp dtls-client-with-seccomp tls-client-with-seccomp
+diff --git a/tests/sign-verify-deterministic.c b/tests/sign-verify-deterministic.c
+new file mode 100644
+index 000000000..fe4873fc8
+--- /dev/null
++++ b/tests/sign-verify-deterministic.c
+@@ -0,0 +1,196 @@
++/*
++ * Copyright (C) 2017-2019 Red Hat, Inc.
++ *
++ * Author: Nikos Mavrogiannopoulos, Daiki Ueno
++ *
++ * This file is part of GnuTLS.
++ *
++ * GnuTLS is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 3 of the License, or
++ * (at your option) any later version.
++ *
++ * GnuTLS 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 a copy of the GNU General Public License
++ * along with GnuTLS; if not, write to the Free Software Foundation,
++ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
++ */
++
++#ifdef HAVE_CONFIG_H
++#include <config.h>
++#endif
++
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++#include <sys/types.h>
++#ifndef _WIN32
++# include <netinet/in.h>
++# include <sys/socket.h>
++# include <arpa/inet.h>
++#endif
++#include <unistd.h>
++#include <gnutls/gnutls.h>
++#include <gnutls/x509.h>
++#include <gnutls/abstract.h>
++#include "utils.h"
++
++/* verifies whether the sign-data and verify-data APIs
++ * operate as expected with deterministic ECDSA/DSA (RFC 6979) */
++
++static void tls_log_func(int level, const char *str)
++{
++	fprintf(stderr, "<%d> %s", level, str);
++}
++
++struct _key_tests_st {
++	const char *name;
++	gnutls_datum_t key;
++	gnutls_datum_t msg;
++	gnutls_datum_t sig;
++	gnutls_pk_algorithm_t pk;
++	gnutls_digest_algorithm_t digest;
++	gnutls_sign_algorithm_t sigalgo;
++	unsigned int sign_flags;
++};
++
++/* Test vectors from RFC 6979 */
++static const char dsa_privkey_rfc6979[] =
++    "-----BEGIN DSA PRIVATE KEY-----\n"
++    "MIIBugIBAAKBgQCG9coD3P6yJQY/+DCgx2m53Z1hU62R184n94fEMni0R+ZTO4ax\n"
++    "i+1uiki3hKFMJSxb4Nv2C4bWOFvS8S+3Y+2Ic6v9P1ui4KjApZCC6sBWk15Sna98\n"
++    "YQRniZx3re38hGyIGHC3sZsrWPm+BSGhcALjvda4ZoXukLPZobAreCsXeQIVAJlv\n"
++    "ln9sjjiNnijQHiBfupV6VpixAoGAB7D5JUYVC2JRS7dx4qDAzjh/A72mxWtQUgn/\n"
++    "Jf08Ez2Ju82X6QTgkRTZp9796t/JB46lRNLkAa7sxAu5+794/YeZWhChwny3eJtZ\n"
++    "S6fvtcQyap/lmgcOE223cXVGStykF75dzi9A0QpGo6OUPyarf9nAOY/4x27gpWgm\n"
++    "qKiPHb0CgYBd9eAd7THQKX4nThaRwZL+WGj++eGahHdkVLEAzxb2U5IZWji5BSPi\n"
++    "VC7mGHHARAy4fDIvxLTS7F4efsdm4b6NTOk1Q33BHDyP1CYziTPr/nOcs0ZfTTZo\n"
++    "xeRzUIJTseaC9ly9xPrpPC6iEjkOVJBahuIiMXC0Tqp9pd2f/Pt/OwIUQRYCyxmm\n"
++    "zMNElNedmO8eftWvJfc=\n"
++    "-----END DSA PRIVATE KEY-----\n";
++
++static const char ecdsa_secp256r1_privkey_rfc6979[] =
++    "-----BEGIN EC PRIVATE KEY-----\n"
++    "MHgCAQEEIQDJr6nYRbp1FmtcIVdnsdaTTlDD2zbomxJ7imIrEg9nIaAKBggqhkjO\n"
++    "PQMBB6FEA0IABGD+1LolWp0xyWHrdMY1bWjASbiSO2H6bOZpYi5g8p+2eQP+EAi4\n"
++    "vJmkGunpVii8ZPLxsgwtfp9Rd6PClNRGIpk=\n"
++    "-----END EC PRIVATE KEY-----\n";
++
++static const char sample[] = "sample";
++
++static const
++struct _key_tests_st tests[] = {
++	{
++		.name = "dsa key",
++		.key = {(void *) dsa_privkey_rfc6979, sizeof(dsa_privkey_rfc6979)-1},
++		.msg = {(void *) sample, sizeof(sample)-1},
++		.sig = {(void *) "\x30\x2d\x02\x15\x00\x81\xf2\xf5\x85\x0b\xe5\xbc\x12\x3c\x43\xf7\x1a\x30\x33\xe9\x38\x46\x11\xc5\x45\x02\x14\x4c\xdd\x91\x4b\x65\xeb\x6c\x66\xa8\xaa\xad\x27\x29\x9b\xee\x6b\x03\x5f\x5e\x89", 47},
++		.pk = GNUTLS_PK_DSA,
++		.digest = GNUTLS_DIG_SHA256,
++		.sigalgo = GNUTLS_SIGN_DSA_SHA256,
++		.sign_flags = GNUTLS_PRIVKEY_FLAG_REPRODUCIBLE
++	},
++	{
++		.name = "ecdsa key",
++		.key = {(void *) ecdsa_secp256r1_privkey_rfc6979, sizeof(ecdsa_secp256r1_privkey_rfc6979)-1},
++		.msg = {(void *) sample, sizeof(sample)-1},
++		.sig = {(void *) "\x30\x46\x02\x21\x00\xef\xd4\x8b\x2a\xac\xb6\xa8\xfd\x11\x40\xdd\x9c\xd4\x5e\x81\xd6\x9d\x2c\x87\x7b\x56\xaa\xf9\x91\xc3\x4d\x0e\xa8\x4e\xaf\x37\x16\x02\x21\x00\xf7\xcb\x1c\x94\x2d\x65\x7c\x41\xd4\x36\xc7\xa1\xb6\xe2\x9f\x65\xf3\xe9\x00\xdb\xb9\xaf\xf4\x06\x4d\xc4\xab\x2f\x84\x3a\xcd\xa8", 72},
++		.pk = GNUTLS_PK_ECDSA,
++		.digest = GNUTLS_DIG_SHA256,
++		.sigalgo = GNUTLS_SIGN_ECDSA_SECP256R1_SHA256,
++		.sign_flags = GNUTLS_PRIVKEY_FLAG_REPRODUCIBLE
++	},
++	{
++		.name = "ecdsa key",
++		.key = {(void *) ecdsa_secp256r1_privkey_rfc6979, sizeof(ecdsa_secp256r1_privkey_rfc6979)-1},
++		.msg = {(void *) sample, sizeof(sample)-1},
++		.sig = {(void *) "\x30\x46\x02\x21\x00\xef\xd4\x8b\x2a\xac\xb6\xa8\xfd\x11\x40\xdd\x9c\xd4\x5e\x81\xd6\x9d\x2c\x87\x7b\x56\xaa\xf9\x91\xc3\x4d\x0e\xa8\x4e\xaf\x37\x16\x02\x21\x00\xf7\xcb\x1c\x94\x2d\x65\x7c\x41\xd4\x36\xc7\xa1\xb6\xe2\x9f\x65\xf3\xe9\x00\xdb\xb9\xaf\xf4\x06\x4d\xc4\xab\x2f\x84\x3a\xcd\xa8", 72},
++		.pk = GNUTLS_PK_ECDSA,
++		.digest = GNUTLS_DIG_SHA256,
++		.sigalgo = GNUTLS_SIGN_ECDSA_SHA256,
++		.sign_flags = GNUTLS_PRIVKEY_FLAG_REPRODUCIBLE
++	},
++	{
++		.name = "ecdsa key (q bits < h bits)",
++		.key = {(void *) ecdsa_secp256r1_privkey_rfc6979, sizeof(ecdsa_secp256r1_privkey_rfc6979)-1},
++		.msg = {(void *) sample, sizeof(sample)-1},
++		.sig = {(void *) "\x30\x44\x02\x20\x0e\xaf\xea\x03\x9b\x20\xe9\xb4\x23\x09\xfb\x1d\x89\xe2\x13\x05\x7c\xbf\x97\x3d\xc0\xcf\xc8\xf1\x29\xed\xdd\xc8\x00\xef\x77\x19\x02\x20\x48\x61\xf0\x49\x1e\x69\x98\xb9\x45\x51\x93\xe3\x4e\x7b\x0d\x28\x4d\xdd\x71\x49\xa7\x4b\x95\xb9\x26\x1f\x13\xab\xde\x94\x09\x54", 70},
++		.pk = GNUTLS_PK_ECDSA,
++		.digest = GNUTLS_DIG_SHA384,
++		.sigalgo = GNUTLS_SIGN_ECDSA_SHA384,
++		.sign_flags = GNUTLS_PRIVKEY_FLAG_REPRODUCIBLE
++	},
++	{
++		.name = "ecdsa key (q bits > h bits)",
++		.key = {(void *) ecdsa_secp256r1_privkey_rfc6979, sizeof(ecdsa_secp256r1_privkey_rfc6979)-1},
++		.msg = {(void *) sample, sizeof(sample)-1},
++		.sig = {(void *) "\x30\x45\x02\x20\x53\xb2\xff\xf5\xd1\x75\x2b\x2c\x68\x9d\xf2\x57\xc0\x4c\x40\xa5\x87\xfa\xba\xbb\x3f\x6f\xc2\x70\x2f\x13\x43\xaf\x7c\xa9\xaa\x3f\x02\x21\x00\xb9\xaf\xb6\x4f\xdc\x03\xdc\x1a\x13\x1c\x7d\x23\x86\xd1\x1e\x34\x9f\x07\x0a\xa4\x32\xa4\xac\xc9\x18\xbe\xa9\x88\xbf\x75\xc7\x4c", 71},
++		.pk = GNUTLS_PK_ECDSA,
++		.digest = GNUTLS_DIG_SHA224,
++		.sigalgo = GNUTLS_SIGN_ECDSA_SHA224,
++		.sign_flags = GNUTLS_PRIVKEY_FLAG_REPRODUCIBLE
++	}
++};
++
++#define testfail(fmt, ...) \
++	fail("%s: "fmt, tests[i].name, ##__VA_ARGS__)
++
++void doit(void)
++{
++	gnutls_pubkey_t pubkey;
++	gnutls_privkey_t privkey;
++	gnutls_datum_t signature;
++	int ret;
++	size_t i;
++
++	global_init();
++
++	gnutls_global_set_log_function(tls_log_func);
++	if (debug)
++		gnutls_global_set_log_level(6);
++
++	for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) {
++		success("testing: %s - %s\n", tests[i].name, gnutls_sign_algorithm_get_name(tests[i].sigalgo));
++
++		ret = gnutls_privkey_init(&privkey);
++		if (ret < 0)
++			testfail("gnutls_privkey_init\n");
++
++		ret = gnutls_privkey_import_x509_raw(privkey, &tests[i].key, GNUTLS_X509_FMT_PEM, NULL, 0);
++		if (ret < 0)
++			testfail("gnutls_privkey_import_x509_raw\n");
++
++		ret = gnutls_privkey_sign_data(privkey, tests[i].digest, tests[i].sign_flags,
++					       &tests[i].msg, &signature);
++		if (ret < 0)
++			testfail("gnutls_privkey_sign_data\n");
++
++		if (signature.size != tests[i].sig.size ||
++		    memcmp(signature.data, tests[i].sig.data, signature.size) != 0)
++			testfail("signature does not match");
++
++		ret = gnutls_pubkey_init(&pubkey);
++		if (ret < 0)
++			testfail("gnutls_pubkey_init\n");
++
++		ret = gnutls_pubkey_import_privkey(pubkey, privkey, 0, 0);
++		if (ret < 0)
++			testfail("gnutls_pubkey_import_privkey\n");
++
++		ret =
++		    gnutls_pubkey_verify_data2(pubkey, tests[i].sigalgo, 0, &tests[i].msg,
++					      &signature);
++		if (ret < 0)
++			testfail("gnutls_pubkey_verify_data2\n");
++
++		gnutls_free(signature.data);
++		gnutls_privkey_deinit(privkey);
++		gnutls_pubkey_deinit(pubkey);
++	}
++
++	gnutls_global_deinit();
++}
+-- 
+2.21.0
+
+
+From 1adee9e136176a8fe26bae036ebb275fe4c26f64 Mon Sep 17 00:00:00 2001
+From: Daiki Ueno <dueno@redhat.com>
+Date: Mon, 5 Aug 2019 15:21:55 +0200
+Subject: [PATCH 5/6] nettle: enable deterministic ECDSA/DSA during FIPS
+ selftests
+
+Signed-off-by: Daiki Ueno <dueno@redhat.com>
+---
+ lib/nettle/pk.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/lib/nettle/pk.c b/lib/nettle/pk.c
+index ebd6481cf..1f8e7f931 100644
+--- a/lib/nettle/pk.c
++++ b/lib/nettle/pk.c
+@@ -820,7 +820,8 @@ _wrap_nettle_pk_sign(gnutls_pk_algorithm_t algo,
+ 			}
+ 
+ 			mpz_init(k);
+-			if (sign_params->flags & GNUTLS_PK_FLAG_REPRODUCIBLE) {
++			if (_gnutls_get_lib_state() == LIB_STATE_SELFTEST ||
++			    (sign_params->flags & GNUTLS_PK_FLAG_REPRODUCIBLE)) {
+ 				ret = _gnutls_ecdsa_compute_k(k,
+ 							      curve_id,
+ 							      pk_params->params[ECC_K],
+@@ -888,7 +889,8 @@ _wrap_nettle_pk_sign(gnutls_pk_algorithm_t algo,
+ 			}
+ 
+ 			mpz_init(k);
+-			if (sign_params->flags & GNUTLS_PK_FLAG_REPRODUCIBLE) {
++			if (_gnutls_get_lib_state() == LIB_STATE_SELFTEST ||
++			    (sign_params->flags & GNUTLS_PK_FLAG_REPRODUCIBLE)) {
+ 				ret = _gnutls_dsa_compute_k(k,
+ 							    pub.q,
+ 							    TOMPZ(priv),
+-- 
+2.21.0
+
+
+From 3beaa23ef5852e2d8aaa610aac9cde9b46be4f77 Mon Sep 17 00:00:00 2001
+From: Daiki Ueno <dueno@redhat.com>
+Date: Wed, 7 Aug 2019 15:55:44 +0200
+Subject: [PATCH 6/6] nettle: prohibit deterministic ECDSA/DSA under FIPS
+ except selftests
+
+Signed-off-by: Daiki Ueno <dueno@redhat.com>
+---
+ lib/nettle/pk.c                   |  8 ++++++++
+ tests/sign-verify-deterministic.c | 27 ++++++++++++++++++++-------
+ 2 files changed, 28 insertions(+), 7 deletions(-)
+
+diff --git a/lib/nettle/pk.c b/lib/nettle/pk.c
+index 1f8e7f931..b2d27cf74 100644
+--- a/lib/nettle/pk.c
++++ b/lib/nettle/pk.c
+@@ -703,6 +703,14 @@ _wrap_nettle_pk_sign(gnutls_pk_algorithm_t algo,
+ 			return gnutls_assert_val(GNUTLS_E_ECC_UNSUPPORTED_CURVE);
+ 	}
+ 
++	/* deterministic ECDSA/DSA is prohibited under FIPS except in
++	 * the selftests */
++	if (_gnutls_fips_mode_enabled() &&
++	    _gnutls_get_lib_state() != LIB_STATE_SELFTEST &&
++	    (algo == GNUTLS_PK_DSA || algo == GNUTLS_PK_ECDSA) &&
++	    (sign_params->flags & GNUTLS_PK_FLAG_REPRODUCIBLE))
++		return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
++
+ 	switch (algo) {
+ 	case GNUTLS_PK_EDDSA_ED25519:	/* we do EdDSA */
+ 		{
+diff --git a/tests/sign-verify-deterministic.c b/tests/sign-verify-deterministic.c
+index fe4873fc8..6e907288e 100644
+--- a/tests/sign-verify-deterministic.c
++++ b/tests/sign-verify-deterministic.c
+@@ -154,29 +154,40 @@ void doit(void)
+ 		gnutls_global_set_log_level(6);
+ 
+ 	for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) {
+-		success("testing: %s - %s\n", tests[i].name, gnutls_sign_algorithm_get_name(tests[i].sigalgo));
++		success("testing: %s - %s", tests[i].name, gnutls_sign_algorithm_get_name(tests[i].sigalgo));
++
++		ret = gnutls_pubkey_init(&pubkey);
++		if (ret < 0)
++			testfail("gnutls_pubkey_init\n");
+ 
+ 		ret = gnutls_privkey_init(&privkey);
+ 		if (ret < 0)
+ 			testfail("gnutls_privkey_init\n");
+ 
++		signature.data = NULL;
++		signature.size = 0;
++
+ 		ret = gnutls_privkey_import_x509_raw(privkey, &tests[i].key, GNUTLS_X509_FMT_PEM, NULL, 0);
+ 		if (ret < 0)
+ 			testfail("gnutls_privkey_import_x509_raw\n");
+ 
+ 		ret = gnutls_privkey_sign_data(privkey, tests[i].digest, tests[i].sign_flags,
+ 					       &tests[i].msg, &signature);
+-		if (ret < 0)
+-			testfail("gnutls_privkey_sign_data\n");
++		if (gnutls_fips140_mode_enabled()) {
++			/* deterministic ECDSA/DSA is prohibited under FIPS */
++			if (ret != GNUTLS_E_INVALID_REQUEST)
++				testfail("gnutls_privkey_sign_data unexpectedly succeeds\n");
++			success(" - skipping\n");
++			goto next;
++		} else {
++			if (ret < 0)
++				testfail("gnutls_privkey_sign_data\n");
++		}
+ 
+ 		if (signature.size != tests[i].sig.size ||
+ 		    memcmp(signature.data, tests[i].sig.data, signature.size) != 0)
+ 			testfail("signature does not match");
+ 
+-		ret = gnutls_pubkey_init(&pubkey);
+-		if (ret < 0)
+-			testfail("gnutls_pubkey_init\n");
+-
+ 		ret = gnutls_pubkey_import_privkey(pubkey, privkey, 0, 0);
+ 		if (ret < 0)
+ 			testfail("gnutls_pubkey_import_privkey\n");
+@@ -186,7 +197,9 @@ void doit(void)
+ 					      &signature);
+ 		if (ret < 0)
+ 			testfail("gnutls_pubkey_verify_data2\n");
++		success(" - pass");
+ 
++	next:
+ 		gnutls_free(signature.data);
+ 		gnutls_privkey_deinit(privkey);
+ 		gnutls_pubkey_deinit(pubkey);
+-- 
+2.21.0
+
+From 6cb58f18280bedfec9d7c8ac411574b868b3d758 Mon Sep 17 00:00:00 2001
+From: Daiki Ueno <dueno@redhat.com>
+Date: Fri, 16 Aug 2019 14:59:03 +0200
+Subject: [PATCH] crypto-backend: always set sign_params.dsa_sig when ECDSA/DSA
+
+In FIPS selftests we create deterministic signature and the
+information about the digest algorithm is necessary.
+
+Signed-off-by: Daiki Ueno <dueno@redhat.com>
+---
+ lib/crypto-backend.h | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/lib/crypto-backend.h b/lib/crypto-backend.h
+index 33eca6031..664ba4377 100644
+--- a/lib/crypto-backend.h
++++ b/lib/crypto-backend.h
+@@ -233,6 +233,9 @@ typedef enum {
+ #define FIX_SIGN_PARAMS(params, flags, dig) do {		\
+ 	if ((flags) & GNUTLS_PRIVKEY_FLAG_REPRODUCIBLE) {	\
+ 		(params).flags |= GNUTLS_PK_FLAG_REPRODUCIBLE;	\
++	}							\
++	if ((params).pk == GNUTLS_PK_DSA ||			\
++	    (params).pk == GNUTLS_PK_ECDSA) {			\
+ 		(params).dsa_dig = (dig);			\
+ 	}							\
+ } while (0)
+-- 
+2.21.0
+
diff --git a/SOURCES/gnutls-3.6.8-fips-rng-continuous.patch b/SOURCES/gnutls-3.6.8-fips-rng-continuous.patch
new file mode 100644
index 0000000..6a88e65
--- /dev/null
+++ b/SOURCES/gnutls-3.6.8-fips-rng-continuous.patch
@@ -0,0 +1,203 @@
+From c7a419e7868fd9342c1799a04d21c2ff6292c405 Mon Sep 17 00:00:00 2001
+From: Daiki Ueno <dueno@redhat.com>
+Date: Fri, 21 Jun 2019 15:49:26 +0200
+Subject: [PATCH] nettle/rnd-fips: add FIPS 140-2 continuous RNG test
+
+This adds a continuous random number generator test as defined in FIPS
+140-2 4.9.2, by iteratively fetching fixed sized block from the system
+and comparing consecutive blocks.
+
+Signed-off-by: Daiki Ueno <dueno@redhat.com>
+---
+ lib/nettle/rnd-fips.c | 102 +++++++++++++++++++++++++++++++++---------
+ 1 file changed, 81 insertions(+), 21 deletions(-)
+
+diff --git a/lib/nettle/rnd-fips.c b/lib/nettle/rnd-fips.c
+index ee68cf68d..ccb92d25a 100644
+--- a/lib/nettle/rnd-fips.c
++++ b/lib/nettle/rnd-fips.c
+@@ -27,12 +27,13 @@
+ 
+ #include "gnutls_int.h"
+ #include "errors.h"
+-#include <nettle/aes.h>
+-#include <nettle/memxor.h>
+-#include <locks.h>
++#include <nettle/sha2.h>
+ #include <atfork.h>
+ #include <rnd-common.h>
+ 
++/* The block size is chosen arbitrarily */
++#define ENTROPY_BLOCK_SIZE SHA256_DIGEST_SIZE
++
+ /* This provides a random generator for gnutls. It uses
+  * two instances of the DRBG-AES-CTR generator, one for
+  * nonce level and another for the other levels of randomness.
+@@ -41,11 +42,13 @@ struct fips_ctx {
+ 	struct drbg_aes_ctx nonce_context;
+ 	struct drbg_aes_ctx normal_context;
+ 	unsigned int forkid;
++	uint8_t entropy_hash[SHA256_DIGEST_SIZE];
+ };
+ 
+ static int _rngfips_ctx_reinit(struct fips_ctx *fctx);
+ static int _rngfips_ctx_init(struct fips_ctx *fctx);
+-static int drbg_reseed(struct drbg_aes_ctx *ctx);
++static int drbg_reseed(struct fips_ctx *fctx, struct drbg_aes_ctx *ctx);
++static int get_entropy(struct fips_ctx *fctx, uint8_t *buffer, size_t length);
+ 
+ static int get_random(struct drbg_aes_ctx *ctx, struct fips_ctx *fctx,
+ 		      void *buffer, size_t length)
+@@ -59,7 +62,7 @@ static int get_random(struct drbg_aes_ctx *ctx, struct fips_ctx *fctx,
+ 	}
+ 
+ 	if (ctx->reseed_counter > DRBG_AES_RESEED_TIME) {
+-		ret = drbg_reseed(ctx);
++		ret = drbg_reseed(fctx, ctx);
+ 		if (ret < 0)
+ 			return gnutls_assert_val(ret);
+ 	}
+@@ -71,54 +74,111 @@ static int get_random(struct drbg_aes_ctx *ctx, struct fips_ctx *fctx,
+ 	return 0;
+ }
+ 
++static int get_entropy(struct fips_ctx *fctx, uint8_t *buffer, size_t length)
++{
++	int ret;
++	uint8_t block[ENTROPY_BLOCK_SIZE];
++	uint8_t hash[SHA256_DIGEST_SIZE];
++	struct sha256_ctx ctx;
++	size_t total = 0;
++
++	/* For FIPS 140-2 4.9.2 continuous random number generator
++	 * test, iteratively fetch fixed sized block from the system
++	 * RNG and compare consecutive blocks.
++	 *
++	 * Note that we store the hash of the entropy block rather
++	 * than the block itself for backward secrecy.
++	 */
++	while (total < length) {
++		ret = _rnd_get_system_entropy(block, ENTROPY_BLOCK_SIZE);
++		if (ret < 0)
++			return gnutls_assert_val(ret);
++
++		sha256_init(&ctx);
++		sha256_update(&ctx, sizeof(block), block);
++		sha256_digest(&ctx, sizeof(hash), hash);
++
++		if (memcmp(hash, fctx->entropy_hash, sizeof(hash)) == 0) {
++			_gnutls_switch_lib_state(LIB_STATE_ERROR);
++			return gnutls_assert_val(GNUTLS_E_RANDOM_FAILED);
++		}
++		memcpy(fctx->entropy_hash, hash, sizeof(hash));
++
++		memcpy(buffer, block, MIN(length - total, sizeof(block)));
++		total += sizeof(block);
++		buffer += sizeof(block);
++	}
++	zeroize_key(block, sizeof(block));
++
++	return 0;
++}
++
+ #define PSTRING "gnutls-rng"
+ #define PSTRING_SIZE (sizeof(PSTRING)-1)
+-static int drbg_init(struct drbg_aes_ctx *ctx)
++static int drbg_init(struct fips_ctx *fctx, struct drbg_aes_ctx *ctx)
+ {
+ 	uint8_t buffer[DRBG_AES_SEED_SIZE];
+ 	int ret;
+ 
+-	/* Get a key from the standard RNG or from the entropy source.  */
+-	ret = _rnd_get_system_entropy(buffer, sizeof(buffer));
++	ret = get_entropy(fctx, buffer, sizeof(buffer));
+ 	if (ret < 0)
+ 		return gnutls_assert_val(ret);
+ 
+-	ret = drbg_aes_init(ctx, sizeof(buffer), buffer, PSTRING_SIZE, (void*)PSTRING);
++	ret = drbg_aes_init(ctx, sizeof(buffer), buffer,
++			    PSTRING_SIZE, (void*)PSTRING);
++	zeroize_key(buffer, sizeof(buffer));
+ 	if (ret == 0)
+ 		return gnutls_assert_val(GNUTLS_E_RANDOM_FAILED);
+ 
+-	zeroize_key(buffer, sizeof(buffer));
+-
+-	return 0;
++	return GNUTLS_E_SUCCESS;
+ }
+ 
+ /* Reseed a generator. */
+-static int drbg_reseed(struct drbg_aes_ctx *ctx)
++static int drbg_reseed(struct fips_ctx *fctx, struct drbg_aes_ctx *ctx)
+ {
+ 	uint8_t buffer[DRBG_AES_SEED_SIZE];
+ 	int ret;
+ 
+-	/* The other two generators are seeded from /dev/random.  */
+-	ret = _rnd_get_system_entropy(buffer, sizeof(buffer));
++	ret = get_entropy(fctx, buffer, sizeof(buffer));
+ 	if (ret < 0)
+ 		return gnutls_assert_val(ret);
+ 
+-	drbg_aes_reseed(ctx, sizeof(buffer), buffer, 0, NULL);
++	ret = drbg_aes_reseed(ctx, sizeof(buffer), buffer, 0, NULL);
++	zeroize_key(buffer, sizeof(buffer));
++	if (ret == 0)
++		return gnutls_assert_val(GNUTLS_E_RANDOM_FAILED);
+ 
+-	return 0;
++	return GNUTLS_E_SUCCESS;
+ }
+ 
+ static int _rngfips_ctx_init(struct fips_ctx *fctx)
+ {
++	uint8_t block[ENTROPY_BLOCK_SIZE];
++	struct sha256_ctx ctx;
+ 	int ret;
+ 
++	/* For FIPS 140-2 4.9.2 continuous random number generator
++	 * test, get the initial entropy from the system RNG and keep
++	 * it for comparison.
++	 *
++	 * Note that we store the hash of the entropy block rather
++	 * than the block itself for backward secrecy.
++	 */
++	ret = _rnd_get_system_entropy(block, sizeof(block));
++	if (ret < 0)
++		return gnutls_assert_val(ret);
++	sha256_init(&ctx);
++	sha256_update(&ctx, sizeof(block), block);
++	zeroize_key(block, sizeof(block));
++	sha256_digest(&ctx, sizeof(fctx->entropy_hash), fctx->entropy_hash);
++
+ 	/* normal */
+-	ret = drbg_init(&fctx->normal_context);
++	ret = drbg_init(fctx, &fctx->normal_context);
+ 	if (ret < 0)
+ 		return gnutls_assert_val(ret);
+ 
+ 	/* nonce */
+-	ret = drbg_init(&fctx->nonce_context);
++	ret = drbg_init(fctx, &fctx->nonce_context);
+ 	if (ret < 0)
+ 		return gnutls_assert_val(ret);
+ 
+@@ -132,12 +192,12 @@ static int _rngfips_ctx_reinit(struct fips_ctx *fctx)
+ 	int ret;
+ 
+ 	/* normal */
+-	ret = drbg_reseed(&fctx->normal_context);
++	ret = drbg_reseed(fctx, &fctx->normal_context);
+ 	if (ret < 0)
+ 		return gnutls_assert_val(ret);
+ 
+ 	/* nonce */
+-	ret = drbg_reseed(&fctx->nonce_context);
++	ret = drbg_reseed(fctx, &fctx->nonce_context);
+ 	if (ret < 0)
+ 		return gnutls_assert_val(ret);
+ 
+-- 
+2.21.0
+
diff --git a/SOURCES/gnutls-3.6.8-fips-rsa-random-selftests.patch b/SOURCES/gnutls-3.6.8-fips-rsa-random-selftests.patch
new file mode 100644
index 0000000..93fdfe3
--- /dev/null
+++ b/SOURCES/gnutls-3.6.8-fips-rsa-random-selftests.patch
@@ -0,0 +1,124 @@
+From fbb6dd2a65c6fc7a2e9bd82fe66fde54f6cf2952 Mon Sep 17 00:00:00 2001
+From: Daiki Ueno <dueno@redhat.com>
+Date: Fri, 16 Aug 2019 17:01:05 +0200
+Subject: [PATCH] nettle: disable RSA blinding in FIPS selftests
+
+Nettle's RSA signing, encryption and decryption functions still
+require randomness for blinding, so fallback to use a fixed buffer in
+selftests where entropy might not be available.
+
+Signed-off-by: Daiki Ueno <dueno@redhat.com>
+---
+ lib/nettle/pk.c | 37 +++++++++++++++++++++++++++++++++----
+ 1 file changed, 33 insertions(+), 4 deletions(-)
+
+diff --git a/lib/nettle/pk.c b/lib/nettle/pk.c
+index b2d27cf74..772fcdc21 100644
+--- a/lib/nettle/pk.c
++++ b/lib/nettle/pk.c
+@@ -94,6 +94,15 @@ static void rnd_mpz_func(void *_ctx, size_t length, uint8_t * data)
+ 	nettle_mpz_get_str_256 (length, data, *k);
+ }
+ 
++static void rnd_nonce_func_fallback(void *_ctx, size_t length, uint8_t * data)
++{
++	if (unlikely(_gnutls_get_lib_state() != LIB_STATE_SELFTEST)) {
++		_gnutls_switch_lib_state(LIB_STATE_ERROR);
++	}
++
++	memset(data, 0xAA, length);
++}
++
+ static void
+ ecc_scalar_zclear (struct ecc_scalar *s)
+ {
+@@ -435,6 +444,7 @@ _wrap_nettle_pk_encrypt(gnutls_pk_algorithm_t algo,
+ 	case GNUTLS_PK_RSA:
+ 		{
+ 			struct rsa_public_key pub;
++			nettle_random_func *random_func;
+ 
+ 			ret = _rsa_params_to_pubkey(pk_params, &pub);
+ 			if (ret < 0) {
+@@ -442,8 +452,12 @@ _wrap_nettle_pk_encrypt(gnutls_pk_algorithm_t algo,
+ 				goto cleanup;
+ 			}
+ 
++			if (_gnutls_get_lib_state() == LIB_STATE_SELFTEST)
++				random_func = rnd_nonce_func_fallback;
++			else
++				random_func = rnd_nonce_func;
+ 			ret =
+-			    rsa_encrypt(&pub, NULL, rnd_nonce_func,
++			    rsa_encrypt(&pub, NULL, random_func,
+ 					plaintext->size, plaintext->data,
+ 					p);
+ 			if (ret == 0 || HAVE_LIB_ERROR()) {
+@@ -496,6 +510,7 @@ _wrap_nettle_pk_decrypt(gnutls_pk_algorithm_t algo,
+ 			struct rsa_public_key pub;
+ 			size_t length;
+ 			bigint_t c;
++			nettle_random_func *random_func;
+ 
+ 			_rsa_params_to_privkey(pk_params, &priv);
+ 			ret = _rsa_params_to_pubkey(pk_params, &pub);
+@@ -526,8 +541,12 @@ _wrap_nettle_pk_decrypt(gnutls_pk_algorithm_t algo,
+ 				goto cleanup;
+ 			}
+ 
++			if (_gnutls_get_lib_state() == LIB_STATE_SELFTEST)
++				random_func = rnd_nonce_func_fallback;
++			else
++				random_func = rnd_nonce_func;
+ 			ret =
+-			    rsa_decrypt_tr(&pub, &priv, NULL, rnd_nonce_func,
++			    rsa_decrypt_tr(&pub, &priv, NULL, random_func,
+ 					   &length, plaintext->data,
+ 					   TOMPZ(c));
+ 			_gnutls_mpi_release(&c);
+@@ -573,6 +592,7 @@ _wrap_nettle_pk_decrypt2(gnutls_pk_algorithm_t algo,
+ 	bigint_t c;
+ 	uint32_t is_err;
+ 	int ret;
++	nettle_random_func *random_func;
+ 
+ 	if (algo != GNUTLS_PK_RSA || plaintext == NULL) {
+ 		gnutls_assert();
+@@ -592,7 +612,11 @@ _wrap_nettle_pk_decrypt2(gnutls_pk_algorithm_t algo,
+ 		return gnutls_assert_val (GNUTLS_E_MPI_SCAN_FAILED);
+ 	}
+ 
+-	ret = rsa_sec_decrypt(&pub, &priv, NULL, rnd_nonce_func,
++	if (_gnutls_get_lib_state() == LIB_STATE_SELFTEST)
++		random_func = rnd_nonce_func_fallback;
++	else
++		random_func = rnd_nonce_func;
++	ret = rsa_sec_decrypt(&pub, &priv, NULL, random_func,
+ 			     plaintext_size, plaintext, TOMPZ(c));
+ 	/* after this point, any conditional on failure that cause differences
+ 	 * in execution may create a timing or cache access pattern side
+@@ -942,6 +966,7 @@ _wrap_nettle_pk_sign(gnutls_pk_algorithm_t algo,
+ 		{
+ 			struct rsa_private_key priv;
+ 			struct rsa_public_key pub;
++			nettle_random_func *random_func;
+ 			mpz_t s;
+ 
+ 			_rsa_params_to_privkey(pk_params, &priv);
+@@ -952,8 +977,12 @@ _wrap_nettle_pk_sign(gnutls_pk_algorithm_t algo,
+ 
+ 			mpz_init(s);
+ 
++			if (_gnutls_get_lib_state() == LIB_STATE_SELFTEST)
++				random_func = rnd_nonce_func_fallback;
++			else
++				random_func = rnd_nonce_func;
+ 			ret =
+-			    rsa_pkcs1_sign_tr(&pub, &priv, NULL, rnd_nonce_func,
++			    rsa_pkcs1_sign_tr(&pub, &priv, NULL, random_func,
+ 					      vdata->size, vdata->data, s);
+ 			if (ret == 0 || HAVE_LIB_ERROR()) {
+ 				gnutls_assert();
+-- 
+2.21.0
+
diff --git a/SOURCES/gnutls-3.6.8-multiple-key-updates.patch b/SOURCES/gnutls-3.6.8-multiple-key-updates.patch
new file mode 100644
index 0000000..720ada3
--- /dev/null
+++ b/SOURCES/gnutls-3.6.8-multiple-key-updates.patch
@@ -0,0 +1,286 @@
+From 6023c69c616d866e19ab1c0bb87931e5143c79d3 Mon Sep 17 00:00:00 2001
+From: Daiki Ueno <dueno@redhat.com>
+Date: Wed, 5 Jun 2019 16:48:39 +0200
+Subject: [PATCH] tls13/key_update: ignore multiple key updates instead of
+ error
+
+This fixes the multiple KeyUpdate messages handling in commit
+65e2aa80d114d4bef095d129c2eda475e473244a, where illegal_parameter is
+sent even if the limit doesn't exceed.
+
+Signed-off-by: Daiki Ueno <dueno@redhat.com>
+---
+ .gitignore                        |   1 +
+ lib/tls13/key_update.c            |   2 -
+ tests/Makefile.am                 |   2 +
+ tests/tls13/key_update_multiple.c | 232 ++++++++++++++++++++++++++++++
+ 4 files changed, 235 insertions(+), 2 deletions(-)
+ create mode 100644 tests/tls13/key_update_multiple.c
+
+diff --git a/lib/tls13/key_update.c b/lib/tls13/key_update.c
+index d542a214b..c6f6e0aa1 100644
+--- a/lib/tls13/key_update.c
++++ b/lib/tls13/key_update.c
+@@ -117,8 +117,6 @@ int _gnutls13_recv_key_update(gnutls_session_t session, gnutls_buffer_st *buf)
+ 			session->internals.rsend_state = RECORD_SEND_KEY_UPDATE_1;
+ 		else if (session->internals.rsend_state == RECORD_SEND_CORKED)
+ 			session->internals.rsend_state = RECORD_SEND_CORKED_TO_KU;
+-		else
+-			return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
+ 
+ 		break;
+ 	default:
+diff --git a/tests/Makefile.am b/tests/Makefile.am
+index ca0481879..4ffa69825 100644
+--- a/tests/Makefile.am
++++ b/tests/Makefile.am
+@@ -119,6 +119,8 @@ ctests += tls13/psk-ext
+ 
+ ctests += tls13/key_update
+ 
++ctests += tls13/key_update_multiple
++
+ ctests += tls13/key_limits
+ 
+ ctests += tls13/multi-ocsp
+diff --git a/tests/tls13/key_update_multiple.c b/tests/tls13/key_update_multiple.c
+new file mode 100644
+index 000000000..8b2c2db4b
+--- /dev/null
++++ b/tests/tls13/key_update_multiple.c
+@@ -0,0 +1,232 @@
++/*
++ * Copyright (C) 2017-2019 Red Hat, Inc.
++ *
++ * Author: Daiki Ueno
++ *
++ * This file is part of GnuTLS.
++ *
++ * GnuTLS is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 3 of the License, or
++ * (at your option) any later version.
++ *
++ * GnuTLS 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 a copy of the GNU Lesser General Public License
++ * along with this program.  If not, see <https://www.gnu.org/licenses/>
++ */
++
++#ifdef HAVE_CONFIG_H
++#include <config.h>
++#endif
++
++#include <stdbool.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++#include <errno.h>
++#include <gnutls/gnutls.h>
++#include <gnutls/crypto.h>
++#include <assert.h>
++#include "cert-common.h"
++
++#include "utils.h"
++#include "virt-time.h"
++#define RANDOMIZE
++#include "eagain-common.h"
++
++const char *side = "";
++
++/* This program tests whether multiple key update messages are handled
++ * properly with rate-limit. */
++
++static void tls_log_func(int level, const char *str)
++{
++	fprintf(stderr, "%s|<%d>| %s", side, level, str);
++}
++
++#define MAX_BUF 1024
++#define MSG "Hello TLS, and hi and how are you and more data here... and more... and even more and even more more data..."
++
++/* These must match the definitions in lib/tls13/key_update.c. */
++#define KEY_UPDATES_WINDOW 1000
++#define KEY_UPDATES_PER_WINDOW 8
++
++static unsigned key_update_msg_inc = 0;
++static unsigned key_update_msg_out = 0;
++
++static int hsk_callback(gnutls_session_t session, unsigned int htype,
++			unsigned post, unsigned int incoming, const gnutls_datum_t *msg)
++{
++	assert(post == GNUTLS_HOOK_PRE);
++
++	assert(msg->size == 1);
++
++	if (htype == GNUTLS_HANDSHAKE_KEY_UPDATE) {
++		if (incoming)
++			key_update_msg_inc++;
++		else
++			key_update_msg_out++;
++	}
++
++	return 0;
++}
++
++static void run(const char *name, bool exceed_limit)
++{
++	/* Server stuff. */
++	gnutls_certificate_credentials_t ccred;
++	gnutls_certificate_credentials_t scred;
++	gnutls_session_t server;
++	int sret, cret;
++	/* Client stuff. */
++	gnutls_session_t client;
++	/* Need to enable anonymous KX specifically. */
++	char buffer[MAX_BUF + 1];
++	int ret, transferred = 0;
++	size_t i;
++
++	success("%s\n", name);
++
++	/* General init. */
++	global_init();
++	gnutls_global_set_log_function(tls_log_func);
++	if (debug)
++		gnutls_global_set_log_level(9);
++
++	/* Init server */
++	assert(gnutls_certificate_allocate_credentials(&scred) >= 0);
++	assert(gnutls_certificate_set_x509_key_mem(scred,
++						   &server_ca3_localhost_cert,
++						   &server_ca3_key,
++						   GNUTLS_X509_FMT_PEM) >= 0);
++
++	assert(gnutls_init(&server, GNUTLS_SERVER) >= 0);
++	ret =
++	    gnutls_priority_set_direct(server,
++				       "NORMAL:-VERS-TLS-ALL:+VERS-TLS1.3",
++				       NULL);
++	if (ret < 0)
++		exit(1);
++
++	gnutls_credentials_set(server, GNUTLS_CRD_CERTIFICATE, scred);
++	gnutls_transport_set_push_function(server, server_push);
++	gnutls_transport_set_pull_function(server, server_pull);
++	gnutls_transport_set_ptr(server, server);
++
++	/* Init client */
++	assert(gnutls_certificate_allocate_credentials(&ccred) >= 0);
++	assert(gnutls_certificate_set_x509_trust_mem
++	       (ccred, &ca3_cert, GNUTLS_X509_FMT_PEM) >= 0);
++
++	gnutls_init(&client, GNUTLS_CLIENT);
++	ret =
++	    gnutls_priority_set_direct(client,
++				       "NORMAL:-VERS-TLS-ALL:+VERS-TLS1.3",
++				       NULL);
++	assert(ret >= 0);
++
++	ret = gnutls_credentials_set(client, GNUTLS_CRD_CERTIFICATE, ccred);
++	if (ret < 0)
++		exit(1);
++
++	gnutls_transport_set_push_function(client, client_push);
++	gnutls_transport_set_pull_function(client, client_pull);
++	gnutls_transport_set_ptr(client, client);
++
++
++	HANDSHAKE(client, server);
++	if (debug)
++		success("Handshake established\n");
++
++	key_update_msg_inc = 0;
++	key_update_msg_out = 0;
++
++	gnutls_handshake_set_hook_function(client, -1, GNUTLS_HOOK_PRE, hsk_callback);
++
++	/* schedule multiple key updates */
++	for (i = 0; i < KEY_UPDATES_PER_WINDOW; i++) {
++		do {
++			ret = gnutls_session_key_update(client, 1);
++		} while (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED);
++		if (ret < 0)
++			fail("error in key update: %s\n", gnutls_strerror(ret));
++	}
++
++	/* server receives the client key update and sends data */
++	TRANSFER(client, server, MSG, strlen(MSG), buffer, MAX_BUF);
++	TRANSFER(server, client, MSG, strlen(MSG), buffer, MAX_BUF);
++	EMPTY_BUF(server, client, buffer, MAX_BUF);
++
++	if (key_update_msg_out != KEY_UPDATES_PER_WINDOW)
++		fail("unexpected number of key updates are sent: %d\n",
++			key_update_msg_out);
++	else {
++		if (debug)
++			success("successfully sent %d key updates\n",
++				KEY_UPDATES_PER_WINDOW);
++	}
++	if (key_update_msg_inc != 1)
++		fail("unexpected number of key updates received: %d\n",
++			key_update_msg_inc);
++	else {
++		if (debug)
++			success("successfully received 1 key update\n");
++	}
++
++	if (exceed_limit) {
++		/* excessive key update in the same time window should
++		 * be rejected by the peer */
++		do {
++			ret = gnutls_session_key_update(client, 1);
++		} while (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED);
++
++		/* server receives the client key update and sends data */
++		ret = record_send_loop(client, MSG, strlen(MSG), 0);
++		assert(ret == strlen(MSG));
++		ret = gnutls_record_recv(server, buffer, MAX_BUF);
++		if (ret != GNUTLS_E_TOO_MANY_HANDSHAKE_PACKETS)
++			fail("server didn't reject excessive number of key updates\n");
++		else {
++			if (debug)
++				success("server rejected excessive number of key updates\n");
++		}
++	} else {
++		virt_sec_sleep(KEY_UPDATES_WINDOW / 1000 + 1);
++
++		/* the time window should be rolled over now */
++		do {
++			ret = gnutls_session_key_update(client, 1);
++		} while (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED);
++		if (ret < 0)
++			fail("error in key update: %s\n", gnutls_strerror(ret));
++
++		/* server receives the client key update and sends data */
++		TRANSFER(client, server, MSG, strlen(MSG), buffer, MAX_BUF);
++		TRANSFER(server, client, MSG, strlen(MSG), buffer, MAX_BUF);
++		EMPTY_BUF(server, client, buffer, MAX_BUF);
++	}
++
++	gnutls_bye(client, GNUTLS_SHUT_WR);
++	gnutls_bye(server, GNUTLS_SHUT_WR);
++
++	gnutls_deinit(client);
++	gnutls_deinit(server);
++
++	gnutls_certificate_free_credentials(scred);
++	gnutls_certificate_free_credentials(ccred);
++
++	gnutls_global_deinit();
++	reset_buffers();
++}
++
++void doit(void)
++{
++	virt_time_init();
++
++	run("not exceeding limit", 0);
++	run("exceeding limit", 1);
++}
+-- 
+2.20.1
+
diff --git a/SOURCES/gnutls-3.6.8-pkcs11-login-error.patch b/SOURCES/gnutls-3.6.8-pkcs11-login-error.patch
new file mode 100644
index 0000000..6135dca
--- /dev/null
+++ b/SOURCES/gnutls-3.6.8-pkcs11-login-error.patch
@@ -0,0 +1,265 @@
+From fa5147c86941512921282b84819b896a0d4f29bb Mon Sep 17 00:00:00 2001
+From: Daiki Ueno <dueno@redhat.com>
+Date: Wed, 19 Jun 2019 17:21:16 +0200
+Subject: [PATCH] pkcs11: ignore login error when traversing tokens
+
+If a token is a general access device, it is expected that login
+attempt to that token returns error:
+https://github.com/p11-glue/p11-kit/blob/master/trust/module.c#L852
+
+On the other hand, _pkcs11_traverse_tokens treats the error as fatal
+and stops iteration.  This behavior prevents object search without
+token specifier if such tokens are registered in the system.
+
+Reported by Stanislav Zidek in
+https://bugzilla.redhat.com/show_bug.cgi?id=1705478
+
+Signed-off-by: Daiki Ueno <dueno@redhat.com>
+---
+ .gitignore                  |   1 +
+ lib/pkcs11.c                |   8 +-
+ tests/Makefile.am           |   2 +-
+ tests/p11-kit-load.sh       |  23 ++++++
+ tests/pkcs11/list-objects.c | 150 ++++++++++++++++++++++++++++++++++++
+ 5 files changed, 182 insertions(+), 2 deletions(-)
+ create mode 100644 tests/pkcs11/list-objects.c
+
+diff --git a/lib/pkcs11.c b/lib/pkcs11.c
+index de5309b29..2ef0e3e02 100644
+--- a/lib/pkcs11.c
++++ b/lib/pkcs11.c
+@@ -1617,7 +1617,13 @@ _pkcs11_traverse_tokens(find_func_t find_func, void *input,
+ 					 info, flags);
+ 			if (ret < 0) {
+ 				gnutls_assert();
+-				return ret;
++				pkcs11_close_session(&sinfo);
++
++				/* treat the error as fatal only if
++				 * the token requires login */
++				if (l_tinfo.flags & CKF_LOGIN_REQUIRED)
++					return ret;
++				continue;
+ 			}
+ 
+ 			ret =
+diff --git a/tests/Makefile.am b/tests/Makefile.am
+index a67f1549c..7fe954f63 100644
+--- a/tests/Makefile.am
++++ b/tests/Makefile.am
+@@ -496,7 +496,7 @@ dist_check_SCRIPTS += p11-kit-trust.sh testpkcs11.sh certtool-pkcs11.sh
+ if HAVE_PKCS11_TRUST_STORE
+ if P11KIT_0_23_11_API
+ dist_check_SCRIPTS += p11-kit-load.sh
+-indirect_tests += pkcs11/list-tokens
++indirect_tests += pkcs11/list-tokens pkcs11/list-objects
+ endif
+ endif
+ 
+diff --git a/tests/p11-kit-load.sh b/tests/p11-kit-load.sh
+index 3201a2c5f..419900f6a 100755
+--- a/tests/p11-kit-load.sh
++++ b/tests/p11-kit-load.sh
+@@ -22,6 +22,7 @@
+ srcdir="${srcdir:-.}"
+ builddir="${builddir:-.}"
+ CERTTOOL="${CERTTOOL:-../src/certtool${EXEEXT}}"
++P11TOOL="${P11TOOL:-../src/p11tool${EXEEXT}}"
+ DIFF="${DIFF:-diff}"
+ PKGCONFIG="${PKG_CONFIG:-$(which pkg-config)}"
+ TMP_SOFTHSM_DIR="./softhsm-load.$$.tmp"
+@@ -90,6 +91,12 @@ if test $? != 0; then
+ 	exit 1
+ fi
+ 
++GNUTLS_PIN="${PIN}" ${P11TOOL} --login --label GnuTLS-Test-RSA --generate-privkey rsa --provider "${SOFTHSM_MODULE}" pkcs11: --outfile /dev/null
++if test $? != 0; then
++	echo "failed to generate privkey"
++	exit 1
++fi
++
+ FILTERTOKEN="sed s/token=.*//g"
+ 
+ # Check whether both are listed
+@@ -175,6 +182,22 @@ if test "$nr" != 2;then
+ 	exit 1
+ fi
+ 
++# Check whether public key and privkey are listed.
++nr=$(GNUTLS_PIN="${PIN}" ${builddir}/pkcs11/list-objects -o ${P11DIR} -t all pkcs11:token=GnuTLS-Test|sort -u|wc -l)
++if test "$nr" != 2;then
++	echo "Error in test 8: did not find all objects"
++	${builddir}/pkcs11/list-objects -o ${P11DIR} -t all pkcs11:token=GnuTLS-Test
++	exit 1
++fi
++
++# Check whether all privkeys are listed even if trust module is registered.
++nr=$(GNUTLS_PIN="${PIN}" ${builddir}/pkcs11/list-objects -o ${P11DIR} -t privkey pkcs11:|sort -u|wc -l)
++if test "$nr" != 1;then
++	echo "Error in test 9: did not find privkey objects"
++	${builddir}/pkcs11/list-objects -o ${P11DIR} -t privkey pkcs11:
++	exit 1
++fi
++
+ rm -f ${P11DIR}/*
+ rm -rf ${TMP_SOFTHSM_DIR}
+ 
+diff --git a/tests/pkcs11/list-objects.c b/tests/pkcs11/list-objects.c
+new file mode 100644
+index 000000000..ab30cd568
+--- /dev/null
++++ b/tests/pkcs11/list-objects.c
+@@ -0,0 +1,150 @@
++/*
++ * Copyright (C) 2016-2017 Red Hat, Inc.
++ *
++ * Author: Nikos Mavrogiannopoulos
++ *
++ * This file is part of GnuTLS.
++ *
++ * GnuTLS is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 3 of the License, or
++ * (at your option) any later version.
++ *
++ * GnuTLS 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 a copy of the GNU Lesser General Public License
++ * along with this program.  If not, see <https://www.gnu.org/licenses/>
++ */
++
++#ifdef HAVE_CONFIG_H
++#include <config.h>
++#endif
++
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++#include <unistd.h>
++#include <sys/types.h>
++#include <sys/wait.h>
++
++#include <gnutls/gnutls.h>
++#include <gnutls/x509.h>
++#include <gnutls/abstract.h>
++#include <getopt.h>
++#define P11_KIT_FUTURE_UNSTABLE_API
++#include <p11-kit/p11-kit.h>
++#include "cert-common.h"
++
++/* lists the registered PKCS#11 modules by p11-kit.
++ */
++
++static void tls_log_func(int level, const char *str)
++{
++	fprintf(stderr, "|<%d>| %s", level, str);
++}
++
++static const char *opt_pin;
++
++static
++int pin_func(void* userdata, int attempt, const char* url, const char *label,
++	     unsigned flags, char *pin, size_t pin_max)
++{
++	if (attempt == 0) {
++		strcpy(pin, opt_pin);
++		return 0;
++	}
++	return -1;
++}
++
++int main(int argc, char **argv)
++{
++	int ret;
++	unsigned i;
++	int opt;
++	char *url, *mod;
++	unsigned flags;
++	unsigned obj_flags = 0;
++	int attrs = GNUTLS_PKCS11_OBJ_ATTR_ALL;
++	gnutls_pkcs11_obj_t *crt_list;
++	unsigned int crt_list_size = 0;
++	const char *envvar;
++
++	ret = gnutls_global_init();
++	if (ret != 0) {
++		fprintf(stderr, "error at %d: %s\n", __LINE__, gnutls_strerror(ret));
++		exit(1);
++	}
++
++	gnutls_global_set_log_function(tls_log_func);
++
++	while((opt = getopt(argc, argv, "o:t:")) != -1) {
++		switch(opt) {
++			case 'o':
++				mod = strdup(optarg);
++				p11_kit_override_system_files(NULL, NULL, mod, mod, NULL);
++				break;
++			case 't':
++				/* specify the object type to list */
++				if (strcmp(optarg, "all") == 0)
++					attrs = GNUTLS_PKCS11_OBJ_ATTR_ALL;
++				else if (strcmp(optarg, "privkey") == 0)
++					attrs = GNUTLS_PKCS11_OBJ_ATTR_PRIVKEY;
++				else {
++					fprintf(stderr, "Unknown object type %s\n", optarg);
++					exit(1);
++				}
++				break;
++			default:
++				fprintf(stderr, "Unknown option %c\n", (char)opt);
++				exit(1);
++		}
++	}
++
++	if (optind == argc) {
++		fprintf(stderr, "specify URL\n");
++		exit(1);
++	}
++	url = argv[optind];
++
++	envvar = getenv("GNUTLS_PIN");
++	if (envvar && *envvar != '\0') {
++		opt_pin = envvar;
++		obj_flags |= GNUTLS_PKCS11_OBJ_FLAG_LOGIN;
++		gnutls_pkcs11_set_pin_function(pin_func, NULL);
++	}
++
++	ret = gnutls_pkcs11_token_get_flags(url, &flags);
++	if (ret < 0) {
++		flags = 0;
++	}
++
++	ret =
++	    gnutls_pkcs11_obj_list_import_url2(&crt_list, &crt_list_size,
++					       url, attrs, obj_flags);
++	if (ret != 0) {
++		fprintf(stderr, "error at %d: %s\n", __LINE__, gnutls_strerror(ret));
++		exit(1);
++	}
++
++	for (i = 0; i < crt_list_size; i++) {
++		char *output;
++
++		ret =
++		    gnutls_pkcs11_obj_export_url(crt_list[i], 0,
++						 &output);
++		if (ret != 0) {
++			fprintf(stderr, "error at %d: %s\n", __LINE__, gnutls_strerror(ret));
++			exit(1);
++		}
++
++		fprintf(stdout, "%s\n", output);
++		gnutls_free(output);
++		gnutls_pkcs11_obj_deinit(crt_list[i]);
++	}
++	gnutls_free(crt_list);
++
++	gnutls_global_deinit();
++}
+-- 
+2.21.0
+
diff --git a/SOURCES/gnutls-3.6.8-session-ticket-ub.patch b/SOURCES/gnutls-3.6.8-session-ticket-ub.patch
new file mode 100644
index 0000000..96e11f7
--- /dev/null
+++ b/SOURCES/gnutls-3.6.8-session-ticket-ub.patch
@@ -0,0 +1,51 @@
+From 1f6bbceeeeb613cf4d790874bdd1e917a7071159 Mon Sep 17 00:00:00 2001
+From: Daiki Ueno <dueno@redhat.com>
+Date: Mon, 8 Jul 2019 16:54:56 +0200
+Subject: [PATCH] ext/session_ticket: avoid calling memcpy on overlapping
+ memory areas
+
+In _gnutls_encrypt_session_ticket, ticket.encrypted_state is allocated
+from ticket_data->data, thus those memory areas may overlap.  Using
+memcpy here leads to undefined behavior.
+
+Spotted by valgrind run on ppc64le.
+
+==95231== Source and destination overlap in memcpy(0x47ce3a2, 0x47ce3a2, 160)
+==95231==    at 0x408A840: memcpy (vg_replace_strmem.c:1023)
+==95231==    by 0x424EE9F: pack_ticket (session_ticket.c:139)
+==95231==    by 0x424FA4F: _gnutls_encrypt_session_ticket (session_ticket.c:335)
+==95231==    by 0x4199E3B: generate_session_ticket (session_ticket.c:249)
+==95231==    by 0x419A333: _gnutls13_send_session_ticket (session_ticket.c:307)
+==95231==    by 0x40F8817: _gnutls13_handshake_server (handshake-tls13.c:511)
+==95231==    by 0x4110DEB: handshake_server (handshake.c:3331)
+==95231==    by 0x410C70B: gnutls_handshake (handshake.c:2727)
+==95231==    by 0x10009EBF: retry_handshake (serv.c:1306)
+==95231==    by 0x1000AB67: tcp_server (serv.c:1500)
+==95231==    by 0x10009E5B: main (serv.c:1297)
+==95231==
+
+Signed-off-by: Daiki Ueno <dueno@redhat.com>
+---
+ lib/ext/session_ticket.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/lib/ext/session_ticket.c b/lib/ext/session_ticket.c
+index 09e240c2d..98db39ff8 100644
+--- a/lib/ext/session_ticket.c
++++ b/lib/ext/session_ticket.c
+@@ -136,7 +136,11 @@ pack_ticket(const struct ticket_st *ticket, gnutls_datum_t *ticket_data)
+ 	_gnutls_write_uint16(ticket->encrypted_state_len, p);
+ 	p += 2;
+ 
+-	memcpy(p, ticket->encrypted_state, ticket->encrypted_state_len);
++	/* We use memmove instead of memcpy here because
++	 * ticket->encrypted_state is allocated from
++	 * ticket_data->data, and thus both memory areas may overlap.
++	 */
++	memmove(p, ticket->encrypted_state, ticket->encrypted_state_len);
+ 	p += ticket->encrypted_state_len;
+ 
+ 	memcpy(p, ticket->mac, TICKET_MAC_SIZE);
+-- 
+2.21.0
+
diff --git a/SOURCES/gnutls-3.6.8.tar.xz.sig b/SOURCES/gnutls-3.6.8.tar.xz.sig
new file mode 100644
index 0000000..d2f3862
Binary files /dev/null and b/SOURCES/gnutls-3.6.8.tar.xz.sig differ
diff --git a/SPECS/gnutls.spec b/SPECS/gnutls.spec
index ff01189..f71519b 100644
--- a/SPECS/gnutls.spec
+++ b/SPECS/gnutls.spec
@@ -1,8 +1,16 @@
-Version:	3.6.5
-Release: 2%{?dist}
+Version:	3.6.8
+Release: 8%{?dist}
 Patch1:	gnutls-3.2.7-rpath.patch
 Patch2:	gnutls-3.6.4-no-now-guile.patch
-Patch3:	gnutls-3.6.5-fix-fips-self-tests.patch
+Patch3:	gnutls-3.6.5-fix-fips-signature-post.patch
+Patch4: gnutls-3.6.8-fips-aes-cbc-kat.patch
+Patch5: gnutls-3.6.8-multiple-key-updates.patch
+Patch6: gnutls-3.6.8-fips-rng-continuous.patch
+Patch7: gnutls-3.6.8-session-ticket-ub.patch
+Patch8: gnutls-3.6.8-pkcs11-login-error.patch
+Patch9: gnutls-3.6.8-fips-deterministic-ecdsa.patch
+Patch10: gnutls-3.6.8-aead-cipher-encryptv2.patch
+Patch11: gnutls-3.6.8-fips-rsa-random-selftests.patch
 %bcond_without dane
 %if 0%{?rhel}
 %bcond_with guile
@@ -21,7 +29,7 @@ BuildRequires: p11-kit-devel >= 0.21.3, gettext-devel
 BuildRequires: zlib-devel, readline-devel, libtasn1-devel >= 4.3
 BuildRequires: libtool, automake, autoconf, texinfo
 BuildRequires: autogen-libopts-devel >= 5.18 autogen
-BuildRequires: nettle-devel >= 3.1.1
+BuildRequires: nettle-devel >= 3.4.1
 BuildRequires: trousers-devel >= 0.3.11.2
 BuildRequires: libidn2-devel
 BuildRequires: libunistring-devel
@@ -286,6 +294,40 @@ fi
 %endif
 
 %changelog
+* Fri Aug 16 2019 Daiki Ueno <dueno@redhat.com> - 3.6.8-8
+- Use fallback random function for RSA blinding in FIPS selftests
+
+* Fri Aug 16 2019 Daiki Ueno <dueno@redhat.com> - 3.6.8-7
+- Fix deterministic signature creation in selftests
+
+* Fri Aug 16 2019 Daiki Ueno <dueno@redhat.com> - 3.6.8-6
+- Treat login error more gracefully when enumerating PKCS#11 tokens (#1705478)
+- Use deterministic ECDSA/DSA in FIPS selftests (#1716560)
+- Add gnutls_aead_cipher_{encrypt,decrypt}v2 functions (#1684461)
+
+* Fri Aug  9 2019 Daiki Ueno <dueno@redhat.com> - 3.6.8-5
+- Avoid UB when encrypting session tickets
+
+* Tue Jul  2 2019 Daiki Ueno <dueno@redhat.com> - 3.6.8-4
+- Add RNG continuous test under FIPS
+
+* Fri Jun 14 2019 Daiki Ueno <dueno@redhat.com> - 3.6.8-3
+- Follow-up fix on multiple key updates handling (#1673975)
+
+* Thu Jun 13 2019 Daiki Ueno <dueno@redhat.com> - 3.6.8-2
+- Run FIPS AES self-tests over overridden algorithms
+
+* Wed May 29 2019 Daiki Ueno <dueno@redhat.com> - 3.6.8-1
+- Update to upstream 3.6.8 release
+
+* Fri May 24 2019 Anderson Sasaki <ansasaki@redhat.com> - 3.6.5-4
+- Fixed FIPS signatures self tests (#1680509)
+
+* Wed Mar 27 2019 Anderson Sasaki <ansasaki@redhat.com> - 3.6.5-3
+- Fixed CVE-2019-3829 (#1693285)
+- Fixed CVE-2019-3836 (#1693288)
+- Added explicit BuildRequires for nettle-devel >= 3.4.1
+
 * Fri Jan 11 2019 Anderson Sasaki <ansasaki@redhat.com> - 3.6.5-2
 - Fixed FIPS integrity self tests (#1665061)