commit 080af499b026af99818dcd4c8da17be6582a2b95 Author: CentOS Sources Date: Thu Apr 30 12:25:43 2020 -0400 import gnutls-3.6.8-10.el8_2 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..190b97a --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +SOURCES/gnutls-3.6.8.tar.xz +SOURCES/gpgkey-1F42418905D8206AA754CCDC29EE58B996865171.gpg diff --git a/.gnutls.metadata b/.gnutls.metadata new file mode 100644 index 0000000..af466d6 --- /dev/null +++ b/.gnutls.metadata @@ -0,0 +1,2 @@ +e1243188791af409bca118d31faf3ec3d5f0a5ab SOURCES/gnutls-3.6.8.tar.xz +e6f8a1400839ce7b4021cdd0f8d08d71b0693486 SOURCES/gpgkey-1F42418905D8206AA754CCDC29EE58B996865171.gpg diff --git a/SOURCES/gnutls-3.2.7-rpath.patch b/SOURCES/gnutls-3.2.7-rpath.patch new file mode 100644 index 0000000..4e6aed3 --- /dev/null +++ b/SOURCES/gnutls-3.2.7-rpath.patch @@ -0,0 +1,12 @@ +diff -ur gnutls-3.2.7.orig/configure gnutls-3.2.7/configure +--- gnutls-3.2.7.orig/configure 2013-11-23 11:09:49.000000000 +0100 ++++ gnutls-3.2.7/configure 2013-11-25 16:53:05.559440656 +0100 +@@ -39652,7 +39652,7 @@ + shlibpath_overrides_runpath=unknown + version_type=none + dynamic_linker="$host_os ld.so" +-sys_lib_dlsearch_path_spec="/lib /usr/lib" ++sys_lib_dlsearch_path_spec="/lib /usr/lib /lib64 /usr/lib64" + need_lib_prefix=unknown + hardcode_into_libs=no + diff --git a/SOURCES/gnutls-3.6.12-dtls-random.patch b/SOURCES/gnutls-3.6.12-dtls-random.patch new file mode 100644 index 0000000..b308af7 --- /dev/null +++ b/SOURCES/gnutls-3.6.12-dtls-random.patch @@ -0,0 +1,29 @@ +From c01011c2d8533dbbbe754e49e256c109cb848d0d Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Stefan=20B=C3=BChler?= +Date: Fri, 27 Mar 2020 17:17:57 +0100 +Subject: [PATCH] dtls client hello: fix zeroed random (fixes #960) +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This broke with bcf4de03 "handshake: treat reply to HRR as a reply to +hello verify request", which failed to "De Morgan" properly. + +Signed-off-by: Stefan Bühler +--- + lib/handshake.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +Index: gnutls-3.6.8/lib/handshake.c +=================================================================== +--- gnutls-3.6.8.orig/lib/handshake.c ++++ gnutls-3.6.8/lib/handshake.c +@@ -2164,7 +2164,7 @@ static int send_client_hello(gnutls_sess + /* Generate random data + */ + if (!(session->internals.hsk_flags & HSK_HRR_RECEIVED) && +- !(IS_DTLS(session) && session->internals.dtls.hsk_hello_verify_requests == 0)) { ++ !(IS_DTLS(session) && session->internals.dtls.hsk_hello_verify_requests != 0)) { + ret = _gnutls_gen_client_random(session); + if (ret < 0) { + gnutls_assert(); diff --git a/SOURCES/gnutls-3.6.4-no-now-guile.patch b/SOURCES/gnutls-3.6.4-no-now-guile.patch new file mode 100644 index 0000000..1da536b --- /dev/null +++ b/SOURCES/gnutls-3.6.4-no-now-guile.patch @@ -0,0 +1,13 @@ +diff --git a/guile/src/Makefile.in b/guile/src/Makefile.in +index 95e1e9c..1dfc88e 100644 +--- a/guile/src/Makefile.in ++++ b/guile/src/Makefile.in +@@ -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 + # . +-guile_gnutls_v_2_la_LDFLAGS = -module -no-undefined ++guile_gnutls_v_2_la_LDFLAGS = -module -no-undefined -Wl,-z,lazy + + # Linking against GnuTLS. + GNUTLS_CORE_LIBS = $(top_builddir)/lib/libgnutls.la 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 +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 +--- + 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 +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 +--- + 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 +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 +--- + 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 +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 +--- + 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 +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 +--- + 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 +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 +--- + 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.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 +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 +--- + .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 ++ * ++ */ ++ ++#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 ++ * ++ */ ++ ++#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 ++ */ ++ ++#ifdef HAVE_CONFIG_H ++#include ++#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 +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 +--- + 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 + #include + #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 +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 +--- + .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 ++ */ ++ ++#ifdef HAVE_CONFIG_H ++#include ++#endif ++ ++#include ++ ++#include ++#include ++#include ++#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-decr-len.patch b/SOURCES/gnutls-3.6.8-decr-len.patch new file mode 100644 index 0000000..30272a1 --- /dev/null +++ b/SOURCES/gnutls-3.6.8-decr-len.patch @@ -0,0 +1,687 @@ +From e0fe31f1fc2ba13ada1d6bc35231847b75be4ee9 Mon Sep 17 00:00:00 2001 +From: Daiki Ueno +Date: Thu, 8 Aug 2019 18:02:08 +0200 +Subject: [PATCH 1/2] gnutls_int.h: make DECR_LEN neutral to signedness + +DECR_LEN was previously implemented in a way that it first decrements +the given length and then checks whether the result is negative. This +requires the caller to properly coerce the length argument to a signed +integer, before invoking the macro. + +Signed-off-by: Daiki Ueno +--- + lib/gnutls_int.h | 11 ++++++----- + 1 file changed, 6 insertions(+), 5 deletions(-) + +diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h +index 179d71b4a..7f7b6a7c9 100644 +--- a/lib/gnutls_int.h ++++ b/lib/gnutls_int.h +@@ -256,14 +256,15 @@ typedef enum record_send_state_t { + + #define MEMSUB(x,y) ((ssize_t)((ptrdiff_t)x-(ptrdiff_t)y)) + +-#define DECR_LEN(len, x) do { len-=x; if (len<0) {gnutls_assert(); return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;} } while (0) ++#define DECR_LEN(len, x) DECR_LENGTH_RET(len, x, GNUTLS_E_UNEXPECTED_PACKET_LENGTH) + #define DECR_LEN_FINAL(len, x) do { \ +- len-=x; \ +- if (len != 0) \ ++ if (len != x) \ + return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH); \ ++ else \ ++ len = 0; \ + } while (0) +-#define DECR_LENGTH_RET(len, x, RET) do { len-=x; if (len<0) {gnutls_assert(); return RET;} } while (0) +-#define DECR_LENGTH_COM(len, x, COM) do { len-=x; if (len<0) {gnutls_assert(); COM;} } while (0) ++#define DECR_LENGTH_RET(len, x, RET) DECR_LENGTH_COM(len, x, return RET) ++#define DECR_LENGTH_COM(len, x, COM) do { if (len +Date: Thu, 8 Aug 2019 18:04:18 +0200 +Subject: [PATCH 2/2] lib/*: remove unnecessary cast to ssize_t + +Signed-off-by: Daiki Ueno +--- + lib/crypto-api.c | 10 +++++----- + lib/ext/alpn.c | 3 +-- + lib/ext/client_cert_type.c | 9 ++++----- + lib/ext/cookie.c | 5 ++--- + lib/ext/ec_point_formats.c | 7 +++---- + lib/ext/key_share.c | 5 ++--- + lib/ext/max_record.c | 3 +-- + lib/ext/psk_ke_modes.c | 3 +-- + lib/ext/record_size_limit.c | 3 +-- + lib/ext/safe_renegotiation.c | 3 +-- + lib/ext/server_cert_type.c | 9 ++++----- + lib/ext/server_name.c | 3 +-- + lib/ext/session_ticket.c | 5 ++--- + lib/ext/signature.c | 3 +-- + lib/ext/srp.c | 3 +-- + lib/ext/srtp.c | 5 ++--- + lib/ext/status_request.c | 3 +-- + lib/ext/supported_groups.c | 3 +-- + lib/ext/supported_versions.c | 5 ++--- + lib/extv.c | 8 ++++---- + lib/sslv2_compat.c | 3 +-- + lib/supplemental.c | 4 ++-- + lib/tls13/certificate.c | 21 +++++++++++---------- + lib/tls13/psk_ext_parser.c | 4 +--- + lib/tls13/psk_ext_parser.h | 4 ++-- + lib/tls13/session_ticket.c | 2 +- + 26 files changed, 58 insertions(+), 78 deletions(-) + +diff --git a/lib/crypto-api.c b/lib/crypto-api.c +index 2834c0199..09b3d7bfc 100644 +--- a/lib/crypto-api.c ++++ b/lib/crypto-api.c +@@ -990,9 +990,9 @@ gnutls_aead_cipher_encryptv(gnutls_aead_cipher_hd_t handle, + api_aead_cipher_hd_st *h = handle; + ssize_t ret; + uint8_t *dst; +- ssize_t dst_size, total = 0; ++ size_t dst_size, total = 0; + uint8_t *p; +- ssize_t blocksize = handle->ctx_enc.e->blocksize; ++ size_t blocksize = handle->ctx_enc.e->blocksize; + struct iov_iter_st iter; + size_t blocks; + +@@ -1071,7 +1071,7 @@ gnutls_aead_cipher_encryptv(gnutls_aead_cipher_hd_t handle, + if (ret == 0) + break; + blocks = ret; +- if (unlikely((size_t) dst_size < blocksize * blocks)) ++ if (unlikely(dst_size < blocksize * blocks)) + return gnutls_assert_val(GNUTLS_E_SHORT_MEMORY_BUFFER); + ret = _gnutls_cipher_encrypt2(&handle->ctx_enc, p, + blocksize * blocks, +@@ -1083,7 +1083,7 @@ gnutls_aead_cipher_encryptv(gnutls_aead_cipher_hd_t handle, + total += blocksize * blocks; + } + if (iter.block_offset > 0) { +- if (unlikely((size_t) dst_size < iter.block_offset)) ++ if (unlikely(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, +@@ -1095,7 +1095,7 @@ gnutls_aead_cipher_encryptv(gnutls_aead_cipher_hd_t handle, + total += iter.block_offset; + } + +- if ((size_t)dst_size < tag_size) ++ if (dst_size < tag_size) + return gnutls_assert_val(GNUTLS_E_SHORT_MEMORY_BUFFER); + + _gnutls_cipher_tag(&handle->ctx_enc, dst, tag_size); +diff --git a/lib/ext/alpn.c b/lib/ext/alpn.c +index 34f6ce09d..b9991f0a1 100644 +--- a/lib/ext/alpn.c ++++ b/lib/ext/alpn.c +@@ -51,13 +51,12 @@ const hello_ext_entry_st ext_mod_alpn = { + + static int + _gnutls_alpn_recv_params(gnutls_session_t session, +- const uint8_t * data, size_t _data_size) ++ const uint8_t * data, size_t data_size) + { + unsigned int i; + int ret; + const uint8_t *p = data; + unsigned len1, len; +- ssize_t data_size = _data_size; + alpn_ext_st *priv; + gnutls_ext_priv_data_t epriv; + int selected_protocol_index; +diff --git a/lib/ext/client_cert_type.c b/lib/ext/client_cert_type.c +index 471d42c5f..b627b71f9 100644 +--- a/lib/ext/client_cert_type.c ++++ b/lib/ext/client_cert_type.c +@@ -73,7 +73,6 @@ static int _gnutls_client_cert_type_recv_params(gnutls_session_t session, + gnutls_certificate_type_t cert_type; + + uint8_t i, found = 0; +- ssize_t len = data_size; + const uint8_t* pdata = data; + + /* Only activate this extension if we have cert credentials set +@@ -86,7 +85,7 @@ static int _gnutls_client_cert_type_recv_params(gnutls_session_t session, + + /* Compare packet length with expected packet length. For the + * client this is a single byte. */ +- if (len != 1) { ++ if (data_size != 1) { + return + gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH); + } +@@ -136,8 +135,8 @@ static int _gnutls_client_cert_type_recv_params(gnutls_session_t session, + + } else { // server mode + // Compare packet length with expected packet length. +- DECR_LEN(len, 1); +- if (data[0] != len) { ++ DECR_LEN(data_size, 1); ++ if (data[0] != data_size) { + return + gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH); + } +@@ -145,7 +144,7 @@ static int _gnutls_client_cert_type_recv_params(gnutls_session_t session, + + // Assign the contents of our data buffer to a gnutls_datum_t + cert_types.data = (uint8_t*)pdata; // Need casting to get rid of 'discards const qualifier' warning +- cert_types.size = len; ++ cert_types.size = data_size; + + // Store the client certificate types in our session + _gnutls_hello_ext_set_datum(session, +diff --git a/lib/ext/cookie.c b/lib/ext/cookie.c +index 1e66c3d49..0feb2f0e5 100644 +--- a/lib/ext/cookie.c ++++ b/lib/ext/cookie.c +@@ -53,10 +53,9 @@ const hello_ext_entry_st ext_mod_cookie = { + /* Only client sends this extension. */ + static int + cookie_recv_params(gnutls_session_t session, +- const uint8_t * data, size_t _data_size) ++ const uint8_t * data, size_t data_size) + { +- ssize_t data_size = _data_size; +- ssize_t csize; ++ size_t csize; + int ret; + gnutls_datum_t tmp; + +diff --git a/lib/ext/ec_point_formats.c b/lib/ext/ec_point_formats.c +index eb59ec139..c702d434c 100644 +--- a/lib/ext/ec_point_formats.c ++++ b/lib/ext/ec_point_formats.c +@@ -57,11 +57,10 @@ const hello_ext_entry_st ext_mod_supported_ec_point_formats = { + static int + _gnutls_supported_ec_point_formats_recv_params(gnutls_session_t session, + const uint8_t * data, +- size_t _data_size) ++ size_t data_size) + { +- int len, i; ++ size_t len, i; + int uncompressed = 0; +- int data_size = _data_size; + + if (session->security_parameters.entity == GNUTLS_CLIENT) { + if (data_size < 1) +@@ -91,7 +90,7 @@ _gnutls_supported_ec_point_formats_recv_params(gnutls_session_t session, + /* only sanity check here. We only support uncompressed points + * and a client must support it thus nothing to check. + */ +- if (_data_size < 1) ++ if (data_size < 1) + return + gnutls_assert_val + (GNUTLS_E_RECEIVED_ILLEGAL_EXTENSION); +diff --git a/lib/ext/key_share.c b/lib/ext/key_share.c +index 599eff8fb..8f0912e69 100644 +--- a/lib/ext/key_share.c ++++ b/lib/ext/key_share.c +@@ -504,11 +504,10 @@ client_use_key_share(gnutls_session_t session, const gnutls_group_entry_st *grou + + static int + key_share_recv_params(gnutls_session_t session, +- const uint8_t * data, size_t _data_size) ++ const uint8_t * data, size_t data_size) + { + int ret; +- ssize_t data_size = _data_size; +- ssize_t size; ++ size_t size; + unsigned gid; + const version_entry_st *ver; + const gnutls_group_entry_st *group; +diff --git a/lib/ext/max_record.c b/lib/ext/max_record.c +index dbb98cf62..3cada69be 100644 +--- a/lib/ext/max_record.c ++++ b/lib/ext/max_record.c +@@ -65,10 +65,9 @@ const hello_ext_entry_st ext_mod_max_record_size = { + + static int + _gnutls_max_record_recv_params(gnutls_session_t session, +- const uint8_t * data, size_t _data_size) ++ const uint8_t * data, size_t data_size) + { + ssize_t new_size; +- ssize_t data_size = _data_size; + + if (session->internals.hsk_flags & HSK_RECORD_SIZE_LIMIT_NEGOTIATED) + return 0; +diff --git a/lib/ext/psk_ke_modes.c b/lib/ext/psk_ke_modes.c +index da7a55098..8d8effb43 100644 +--- a/lib/ext/psk_ke_modes.c ++++ b/lib/ext/psk_ke_modes.c +@@ -106,10 +106,9 @@ psk_ke_modes_send_params(gnutls_session_t session, + */ + static int + psk_ke_modes_recv_params(gnutls_session_t session, +- const unsigned char *data, size_t _len) ++ const unsigned char *data, size_t len) + { + uint8_t ke_modes_len; +- ssize_t len = _len; + const version_entry_st *vers = get_version(session); + gnutls_psk_server_credentials_t cred; + int dhpsk_pos = MAX_POS; +diff --git a/lib/ext/record_size_limit.c b/lib/ext/record_size_limit.c +index e9fe6a1d8..0e94fece3 100644 +--- a/lib/ext/record_size_limit.c ++++ b/lib/ext/record_size_limit.c +@@ -48,10 +48,9 @@ const hello_ext_entry_st ext_mod_record_size_limit = { + + static int + _gnutls_record_size_limit_recv_params(gnutls_session_t session, +- const uint8_t * data, size_t _data_size) ++ const uint8_t * data, size_t data_size) + { + ssize_t new_size; +- ssize_t data_size = _data_size; + const version_entry_st *vers; + + DECR_LEN(data_size, 2); +diff --git a/lib/ext/safe_renegotiation.c b/lib/ext/safe_renegotiation.c +index 6424f45b5..bb4a57e45 100644 +--- a/lib/ext/safe_renegotiation.c ++++ b/lib/ext/safe_renegotiation.c +@@ -265,10 +265,9 @@ int _gnutls_ext_sr_send_cs(gnutls_session_t session) + + static int + _gnutls_sr_recv_params(gnutls_session_t session, +- const uint8_t * data, size_t _data_size) ++ const uint8_t * data, size_t data_size) + { + unsigned int len; +- ssize_t data_size = _data_size; + sr_ext_st *priv; + gnutls_ext_priv_data_t epriv; + int set = 0, ret; +diff --git a/lib/ext/server_cert_type.c b/lib/ext/server_cert_type.c +index dbcb3971b..864a44bbc 100644 +--- a/lib/ext/server_cert_type.c ++++ b/lib/ext/server_cert_type.c +@@ -73,7 +73,6 @@ static int _gnutls_server_cert_type_recv_params(gnutls_session_t session, + gnutls_certificate_type_t cert_type; + + uint8_t i, found = 0; +- ssize_t len = data_size; + const uint8_t* pdata = data; + + /* Only activate this extension if we have cert credentials set +@@ -86,7 +85,7 @@ static int _gnutls_server_cert_type_recv_params(gnutls_session_t session, + + /* Compare packet length with expected packet length. For the + * client this is a single byte. */ +- if (len != 1) { ++ if (data_size != 1) { + return + gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH); + } +@@ -135,8 +134,8 @@ static int _gnutls_server_cert_type_recv_params(gnutls_session_t session, + + } else { // server mode + // Compare packet length with expected packet length. +- DECR_LEN(len, 1); +- if (data[0] != len) { ++ DECR_LEN(data_size, 1); ++ if (data[0] != data_size) { + return + gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH); + } +@@ -144,7 +143,7 @@ static int _gnutls_server_cert_type_recv_params(gnutls_session_t session, + + // Assign the contents of our data buffer to a gnutls_datum_t + cert_types.data = (uint8_t*)pdata; // Need casting to get rid of 'discards const qualifier' warning +- cert_types.size = len; ++ cert_types.size = data_size; + + // Store the server certificate types in our session + _gnutls_hello_ext_set_datum(session, +diff --git a/lib/ext/server_name.c b/lib/ext/server_name.c +index 259dc998e..0c6331569 100644 +--- a/lib/ext/server_name.c ++++ b/lib/ext/server_name.c +@@ -66,11 +66,10 @@ const hello_ext_entry_st ext_mod_server_name = { + */ + static int + _gnutls_server_name_recv_params(gnutls_session_t session, +- const uint8_t * data, size_t _data_size) ++ const uint8_t * data, size_t data_size) + { + const unsigned char *p; + uint16_t len, type; +- ssize_t data_size = _data_size; + gnutls_datum_t name; + + if (session->security_parameters.entity == GNUTLS_SERVER) { +diff --git a/lib/ext/session_ticket.c b/lib/ext/session_ticket.c +index 98db39ff8..263273fa2 100644 +--- a/lib/ext/session_ticket.c ++++ b/lib/ext/session_ticket.c +@@ -78,7 +78,7 @@ static int + unpack_ticket(const gnutls_datum_t *ticket_data, struct ticket_st *ticket) + { + const uint8_t * data = ticket_data->data; +- ssize_t data_size = ticket_data->size; ++ size_t data_size = ticket_data->size; + const uint8_t *encrypted_state; + + /* Format: +@@ -371,11 +371,10 @@ unpack_session(gnutls_session_t session, const gnutls_datum_t *state) + + static int + session_ticket_recv_params(gnutls_session_t session, +- const uint8_t * data, size_t _data_size) ++ const uint8_t * data, size_t data_size) + { + gnutls_datum_t ticket_data; + gnutls_datum_t state; +- ssize_t data_size = _data_size; + int ret; + + if (session->internals.flags & GNUTLS_NO_TICKETS) +diff --git a/lib/ext/signature.c b/lib/ext/signature.c +index e734d2c7d..a90f58d53 100644 +--- a/lib/ext/signature.c ++++ b/lib/ext/signature.c +@@ -187,9 +187,8 @@ _gnutls_sign_algorithm_parse_data(gnutls_session_t session, + static int + _gnutls_signature_algorithm_recv_params(gnutls_session_t session, + const uint8_t * data, +- size_t _data_size) ++ size_t data_size) + { +- ssize_t data_size = _data_size; + int ret; + + if (session->security_parameters.entity == GNUTLS_CLIENT) { +diff --git a/lib/ext/srp.c b/lib/ext/srp.c +index 8b58222e0..07f6e6883 100644 +--- a/lib/ext/srp.c ++++ b/lib/ext/srp.c +@@ -59,10 +59,9 @@ const hello_ext_entry_st ext_mod_srp = { + + static int + _gnutls_srp_recv_params(gnutls_session_t session, const uint8_t * data, +- size_t _data_size) ++ size_t data_size) + { + uint8_t len; +- ssize_t data_size = _data_size; + gnutls_ext_priv_data_t epriv; + srp_ext_st *priv; + +diff --git a/lib/ext/srtp.c b/lib/ext/srtp.c +index 3fc7ed35a..412e26d45 100644 +--- a/lib/ext/srtp.c ++++ b/lib/ext/srtp.c +@@ -162,13 +162,12 @@ const char *gnutls_srtp_get_profile_name(gnutls_srtp_profile_t profile) + + static int + _gnutls_srtp_recv_params(gnutls_session_t session, +- const uint8_t * data, size_t _data_size) ++ const uint8_t * data, size_t data_size) + { + unsigned int i; + int ret; + const uint8_t *p = data; +- int len; +- ssize_t data_size = _data_size; ++ size_t len; + srtp_ext_st *priv; + gnutls_ext_priv_data_t epriv; + uint16_t profile; +diff --git a/lib/ext/status_request.c b/lib/ext/status_request.c +index d8779e8cf..cf9d5bd03 100644 +--- a/lib/ext/status_request.c ++++ b/lib/ext/status_request.c +@@ -86,9 +86,8 @@ client_send(gnutls_session_t session, + static int + server_recv(gnutls_session_t session, + status_request_ext_st * priv, +- const uint8_t * data, size_t size) ++ const uint8_t * data, size_t data_size) + { +- ssize_t data_size = size; + unsigned rid_bytes = 0; + + /* minimum message is type (1) + responder_id_list (2) + +diff --git a/lib/ext/supported_groups.c b/lib/ext/supported_groups.c +index 952d3bb0c..ef7859f73 100644 +--- a/lib/ext/supported_groups.c ++++ b/lib/ext/supported_groups.c +@@ -93,10 +93,9 @@ static unsigned get_min_dh(gnutls_session_t session) + */ + static int + _gnutls_supported_groups_recv_params(gnutls_session_t session, +- const uint8_t * data, size_t _data_size) ++ const uint8_t * data, size_t data_size) + { + int i; +- ssize_t data_size = _data_size; + uint16_t len; + const uint8_t *p = data; + const gnutls_group_entry_st *group = NULL; +diff --git a/lib/ext/supported_versions.c b/lib/ext/supported_versions.c +index 52828ee37..8d52fad5c 100644 +--- a/lib/ext/supported_versions.c ++++ b/lib/ext/supported_versions.c +@@ -54,12 +54,11 @@ const hello_ext_entry_st ext_mod_supported_versions = { + + static int + supported_versions_recv_params(gnutls_session_t session, +- const uint8_t * data, size_t _data_size) ++ const uint8_t * data, size_t data_size) + { + const version_entry_st *vers; +- ssize_t data_size = _data_size; + uint8_t major, minor; +- ssize_t bytes; ++ size_t bytes; + int ret; + + if (session->security_parameters.entity == GNUTLS_SERVER) { +diff --git a/lib/extv.c b/lib/extv.c +index bfdfdf974..0c0c46f32 100644 +--- a/lib/extv.c ++++ b/lib/extv.c +@@ -105,7 +105,7 @@ int gnutls_ext_raw_parse(void *ctx, gnutls_ext_raw_process_func cb, + const gnutls_datum_t *data, unsigned int flags) + { + if (flags & GNUTLS_EXT_RAW_FLAG_TLS_CLIENT_HELLO) { +- ssize_t size = data->size; ++ size_t size = data->size; + size_t len; + uint8_t *p = data->data; + +@@ -137,12 +137,12 @@ int gnutls_ext_raw_parse(void *ctx, gnutls_ext_raw_process_func cb, + DECR_LEN(size, len); + p += len; + +- if (size <= 0) ++ if (size == 0) + return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE); + + return _gnutls_extv_parse(ctx, cb, p, size); + } else if (flags & GNUTLS_EXT_RAW_FLAG_DTLS_CLIENT_HELLO) { +- ssize_t size = data->size; ++ size_t size = data->size; + size_t len; + uint8_t *p = data->data; + +@@ -181,7 +181,7 @@ int gnutls_ext_raw_parse(void *ctx, gnutls_ext_raw_process_func cb, + DECR_LEN(size, len); + p += len; + +- if (size <= 0) ++ if (size == 0) + return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE); + + return _gnutls_extv_parse(ctx, cb, p, size); +diff --git a/lib/sslv2_compat.c b/lib/sslv2_compat.c +index 6122d1098..9d247ba4c 100644 +--- a/lib/sslv2_compat.c ++++ b/lib/sslv2_compat.c +@@ -87,14 +87,13 @@ _gnutls_handshake_select_v2_suite(gnutls_session_t session, + */ + int + _gnutls_read_client_hello_v2(gnutls_session_t session, uint8_t * data, +- unsigned int datalen) ++ unsigned int len) + { + uint16_t session_id_len = 0; + int pos = 0; + int ret = 0, sret = 0; + uint16_t sizeOfSuites; + uint8_t rnd[GNUTLS_RANDOM_SIZE], major, minor; +- int len = datalen; + int neg_version; + const version_entry_st *vers; + uint16_t challenge; +diff --git a/lib/supplemental.c b/lib/supplemental.c +index cd90fa1fb..07b38cc93 100644 +--- a/lib/supplemental.c ++++ b/lib/supplemental.c +@@ -192,14 +192,14 @@ _gnutls_parse_supplemental(gnutls_session_t session, + const uint8_t * data, int datalen) + { + const uint8_t *p = data; +- ssize_t dsize = datalen; ++ size_t dsize = datalen; + size_t total_size; + + DECR_LEN(dsize, 3); + total_size = _gnutls_read_uint24(p); + p += 3; + +- if (dsize != (ssize_t) total_size) { ++ if (dsize != total_size) { + gnutls_assert(); + return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER; + } +diff --git a/lib/tls13/certificate.c b/lib/tls13/certificate.c +index bd257237f..8a1a11872 100644 +--- a/lib/tls13/certificate.c ++++ b/lib/tls13/certificate.c +@@ -360,11 +360,12 @@ static int parse_cert_extension(void *_ctx, unsigned tls_id, const uint8_t *data + static int + parse_cert_list(gnutls_session_t session, uint8_t * data, size_t data_size) + { +- int len, ret; ++ int ret; ++ size_t len; + uint8_t *p = data; + cert_auth_info_t info; + gnutls_certificate_credentials_t cred; +- ssize_t dsize = data_size, size; ++ size_t size; + int i; + unsigned npeer_certs, npeer_ocsp, j; + crt_cert_ctx_st ctx; +@@ -395,31 +396,31 @@ parse_cert_list(gnutls_session_t session, uint8_t * data, size_t data_size) + if (info == NULL) + return gnutls_assert_val(GNUTLS_E_INSUFFICIENT_CREDENTIALS); + +- DECR_LEN(dsize, 3); ++ DECR_LEN(data_size, 3); + size = _gnutls_read_uint24(p); + p += 3; + +- if (size != dsize) ++ if (size != data_size) + return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH); + + if (size == 0) + return gnutls_assert_val(GNUTLS_E_NO_CERTIFICATE_FOUND); + +- i = dsize; ++ i = data_size; + + while (i > 0) { +- DECR_LEN(dsize, 3); ++ DECR_LEN(data_size, 3); + len = _gnutls_read_uint24(p); + if (len == 0) + return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH); + +- DECR_LEN(dsize, len); ++ DECR_LEN(data_size, len); + p += len + 3; + i -= len + 3; + +- DECR_LEN(dsize, 2); ++ DECR_LEN(data_size, 2); + len = _gnutls_read_uint16(p); +- DECR_LEN(dsize, len); ++ DECR_LEN(data_size, len); + + i -= len + 2; + p += len + 2; +@@ -427,7 +428,7 @@ parse_cert_list(gnutls_session_t session, uint8_t * data, size_t data_size) + nentries++; + } + +- if (dsize != 0) ++ if (data_size != 0) + return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH); + + /* this is unnecessary - keeping to avoid a regression due to a re-org +diff --git a/lib/tls13/psk_ext_parser.c b/lib/tls13/psk_ext_parser.c +index 6e3a12f90..33ebc0461 100644 +--- a/lib/tls13/psk_ext_parser.c ++++ b/lib/tls13/psk_ext_parser.c +@@ -28,10 +28,8 @@ + * are present, or 0, on success. + */ + int _gnutls13_psk_ext_parser_init(psk_ext_parser_st *p, +- const unsigned char *data, size_t _len) ++ const unsigned char *data, size_t len) + { +- ssize_t len = _len; +- + if (!p || !data || !len) + return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); + +diff --git a/lib/tls13/psk_ext_parser.h b/lib/tls13/psk_ext_parser.h +index 30b47e904..f46b211e0 100644 +--- a/lib/tls13/psk_ext_parser.h ++++ b/lib/tls13/psk_ext_parser.h +@@ -25,10 +25,10 @@ + + struct psk_ext_parser_st { + const unsigned char *identities_data; +- ssize_t identities_len; ++ size_t identities_len; + + const unsigned char *binders_data; +- ssize_t binders_len; ++ size_t binders_len; + }; + + typedef struct psk_ext_parser_st psk_ext_parser_st; +diff --git a/lib/tls13/session_ticket.c b/lib/tls13/session_ticket.c +index 146aee9b1..072a56d9c 100644 +--- a/lib/tls13/session_ticket.c ++++ b/lib/tls13/session_ticket.c +@@ -105,7 +105,7 @@ unpack_ticket(gnutls_session_t session, gnutls_datum_t *packed, tls13_ticket_st + gnutls_mac_algorithm_t kdf; + const mac_entry_st *prf; + uint8_t *p; +- ssize_t len; ++ size_t len; + uint64_t v; + int ret; + +-- +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 +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 +--- + 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 +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 +--- + 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 ++ * ++ */ ++ ++#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 ++ ++#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 ++ * ++ */ ++ ++#ifndef GNUTLS_LIB_NETTLE_INT_DSA_COMPUTE_K_H ++#define GNUTLS_LIB_NETTLE_INT_DSA_COMPUTE_K_H ++ ++#include ++#include /* 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 ++ * ++ */ ++ ++#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 ++ * ++ */ ++ ++#ifndef GNUTLS_LIB_NETTLE_INT_ECDSA_COMPUTE_K_H ++#define GNUTLS_LIB_NETTLE_INT_ECDSA_COMPUTE_K_H ++ ++#include ++#include /* 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 ++ ++/* 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 +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 +--- + 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 +Date: Wed, 7 Aug 2019 14:37:00 +0200 +Subject: [PATCH 3/6] privkey_sign_prehashed: remove unused argument + +Signed-off-by: Daiki Ueno +--- + 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, ¶ms, flags); ++ return privkey_sign_prehashed(signer, se, hash_data, signature, ¶ms); + } + + 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, ¶ms, flags); ++ hash_data, signature, ¶ms); + } + + 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 +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 +--- + .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 + #include + +@@ -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, ¶ms); + } + +@@ -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, ¶ms); + } + +@@ -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, ¶ms); + } + +@@ -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, ¶ms); + } +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, ¶ms); + 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, ¶ms); + 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, ¶ms); + } 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 ++#endif ++ ++#include ++#include ++#include ++#include ++#ifndef _WIN32 ++# include ++# include ++# include ++#endif ++#include ++#include ++#include ++#include ++#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 +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 +--- + 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 +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 +--- + 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 +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 +--- + 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 +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 +--- + 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 +-#include +-#include ++#include + #include + #include + ++/* 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 +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 +--- + 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-fix-aead-cipher-encryptv2.patch b/SOURCES/gnutls-3.6.8-fix-aead-cipher-encryptv2.patch new file mode 100644 index 0000000..0194c6c --- /dev/null +++ b/SOURCES/gnutls-3.6.8-fix-aead-cipher-encryptv2.patch @@ -0,0 +1,767 @@ +From bbb312749780928cc10b45662c6d7eadcaa98f0b Mon Sep 17 00:00:00 2001 +From: Daiki Ueno +Date: Thu, 3 Oct 2019 10:34:18 +0200 +Subject: [PATCH 1/3] iov: _gnutls_iov_iter_next: return bytes instead of + blocks + +This eliminates the need of special handling of final block. Also +adds more tests in exceptional cases. + +Signed-off-by: Daiki Ueno +--- + lib/crypto-api.c | 82 +++++------------------------- + lib/iov.c | 31 +++++++++--- + tests/iov.c | 126 ++++++++++++++++++++++++++++++++--------------- + 3 files changed, 121 insertions(+), 118 deletions(-) + +diff --git a/lib/crypto-api.c b/lib/crypto-api.c +index 09b3d7bfc..41e759b74 100644 +--- a/lib/crypto-api.c ++++ b/lib/crypto-api.c +@@ -992,9 +992,9 @@ gnutls_aead_cipher_encryptv(gnutls_aead_cipher_hd_t handle, + uint8_t *dst; + size_t dst_size, total = 0; + uint8_t *p; ++ size_t len; + size_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(), +@@ -1045,15 +1045,7 @@ gnutls_aead_cipher_encryptv(gnutls_aead_cipher_hd_t handle, + 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); ++ ret = _gnutls_cipher_auth(&handle->ctx_enc, p, ret); + if (unlikely(ret < 0)) + return gnutls_assert_val(ret); + } +@@ -1070,29 +1062,15 @@ gnutls_aead_cipher_encryptv(gnutls_aead_cipher_hd_t handle, + return gnutls_assert_val(ret); + if (ret == 0) + break; +- blocks = ret; +- if (unlikely(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(dst_size < iter.block_offset)) +- return gnutls_assert_val(GNUTLS_E_SHORT_MEMORY_BUFFER); ++ len = ret; + ret = _gnutls_cipher_encrypt2(&handle->ctx_enc, +- iter.block, iter.block_offset, ++ p, len, + 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; ++ DECR_LEN(dst_size, len); ++ dst += len; ++ total += len; + } + + if (dst_size < tag_size) +@@ -1137,7 +1115,6 @@ gnutls_aead_cipher_encryptv2(gnutls_aead_cipher_hd_t handle, + 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) +@@ -1220,15 +1197,7 @@ gnutls_aead_cipher_encryptv2(gnutls_aead_cipher_hd_t handle, + 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); ++ ret = _gnutls_cipher_auth(&handle->ctx_enc, p, ret); + if (unlikely(ret < 0)) + return gnutls_assert_val(ret); + } +@@ -1242,17 +1211,7 @@ gnutls_aead_cipher_encryptv2(gnutls_aead_cipher_hd_t handle, + 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); ++ ret = _gnutls_cipher_encrypt2(&handle->ctx_enc, p, ret, p, ret); + if (unlikely(ret < 0)) + return gnutls_assert_val(ret); + } +@@ -1296,7 +1255,6 @@ gnutls_aead_cipher_decryptv2(gnutls_aead_cipher_hd_t handle, + 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) +@@ -1370,15 +1328,7 @@ gnutls_aead_cipher_decryptv2(gnutls_aead_cipher_hd_t handle, + 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); ++ ret = _gnutls_cipher_auth(&handle->ctx_enc, p, ret); + if (unlikely(ret < 0)) + return gnutls_assert_val(ret); + } +@@ -1392,17 +1342,7 @@ gnutls_aead_cipher_decryptv2(gnutls_aead_cipher_hd_t handle, + 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); ++ ret = _gnutls_cipher_decrypt2(&handle->ctx_enc, p, ret, p, ret); + if (unlikely(ret < 0)) + return gnutls_assert_val(ret); + } +diff --git a/lib/iov.c b/lib/iov.c +index 5dc29c54b..17272886c 100644 +--- a/lib/iov.c ++++ b/lib/iov.c +@@ -58,8 +58,8 @@ _gnutls_iov_iter_init(struct iov_iter_st *iter, + * @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. ++ * position. It returns the number of bytes 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 +@@ -88,25 +88,30 @@ _gnutls_iov_iter_next(struct iov_iter_st *iter, uint8_t **data) + if ((len % iter->block_size) == 0) { + iter->iov_index++; + iter->iov_offset = 0; +- } else +- iter->iov_offset += +- len - (len % iter->block_size); ++ } else { ++ len -= (len % iter->block_size); ++ iter->iov_offset += len; ++ } + + /* Return the blocks. */ + *data = p; +- return len / iter->block_size; ++ return len; + } + + /* 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; ++ if (len == block_left) { ++ iter->iov_index++; ++ iter->iov_offset = 0; ++ } else ++ iter->iov_offset += block_left; + iter->block_offset = 0; + + /* Return the filled block. */ + *data = iter->block; +- return 1; ++ return iter->block_size; + } + + /* Not enough data for a full block, store in temp +@@ -116,5 +121,15 @@ _gnutls_iov_iter_next(struct iov_iter_st *iter, uint8_t **data) + iter->iov_index++; + iter->iov_offset = 0; + } ++ ++ if (iter->block_offset > 0) { ++ size_t len = iter->block_offset; ++ ++ /* Return the incomplete block. */ ++ *data = iter->block; ++ iter->block_offset = 0; ++ return len; ++ } ++ + return 0; + } +diff --git a/tests/iov.c b/tests/iov.c +index eda5583a7..3d116b471 100644 +--- a/tests/iov.c ++++ b/tests/iov.c +@@ -32,7 +32,6 @@ struct exp_st { + ssize_t ret; + size_t iov_index; + size_t iov_offset; +- size_t block_offset; + }; + + struct test_st { +@@ -42,7 +41,6 @@ struct test_st { + size_t block_size; + const struct exp_st *exp; + size_t expcnt; +- size_t remaining; + }; + + static const giovec_t iov16[] = { +@@ -53,40 +51,41 @@ static const giovec_t iov16[] = { + }; + + static const struct exp_st exp16_64[] = { +- {1, 3, 16, 0}, +- {0, 0, 0, 0} ++ {64, 4, 0}, ++ {0, 0, 0} + }; + + static const struct exp_st exp16_32[] = { +- {1, 1, 16, 0}, +- {1, 3, 16, 0}, +- {0, 0, 0, 0} ++ {32, 2, 0}, ++ {32, 4, 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} ++ {16, 1, 0}, ++ {16, 2, 0}, ++ {16, 3, 0}, ++ {16, 4, 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} ++ {16, 1, 0}, ++ {16, 2, 0}, ++ {16, 3, 0}, ++ {16, 4, 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} ++ {15, 0, 15}, ++ {3, 1, 2}, ++ {12, 1, 14}, ++ {3, 2, 1}, ++ {15, 3, 0}, ++ {15, 3, 15}, ++ {1, 4, 0}, ++ {0, 0, 0} + }; + + static const giovec_t iov8[] = { +@@ -97,22 +96,74 @@ static const giovec_t iov8[] = { + }; + + static const struct exp_st exp8_64[] = { +- {0, 0, 0, 32} ++ {32, 4, 0}, ++ {0, 0, 0} ++}; ++ ++static const giovec_t iov_odd[] = { ++ {(void *) "0", 1}, ++ {(void *) "012", 3}, ++ {(void *) "01234", 5}, ++ {(void *) "0123456", 7}, ++ {(void *) "012345678", 9}, ++ {(void *) "01234567890", 11}, ++ {(void *) "0123456789012", 13}, ++ {(void *) "012345678901234", 15} ++}; ++ ++static const struct exp_st exp_odd_16[] = { ++ {16, 4, 0}, ++ {16, 5, 7}, ++ {16, 6, 12}, ++ {16, 8, 0}, ++ {0, 0, 0} ++}; ++ ++static const giovec_t iov_skip[] = { ++ {(void *) "0123456789012345", 16}, ++ {(void *) "01234567", 8}, ++ {(void *) "", 0}, ++ {(void *) "", 0}, ++ {(void *) "0123456789012345", 16} ++}; ++ ++static const struct exp_st exp_skip_16[] = { ++ {16, 1, 0}, ++ {16, 4, 8}, ++ {8, 5, 0}, ++ {0, 0, 0} ++}; ++ ++static const giovec_t iov_empty[] = { ++ {(void *) "", 0}, ++ {(void *) "", 0}, ++ {(void *) "", 0}, ++ {(void *) "", 0} ++}; ++ ++static const struct exp_st exp_empty_16[] = { ++ {0, 0, 0} + }; + + 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 }, ++ exp16_64, sizeof(exp16_64)/sizeof(exp16_64[0]) }, + { "16/32", iov16, sizeof(iov16)/sizeof(iov16[0]), 32, +- exp16_32, sizeof(exp16_32)/sizeof(exp16_32[0]), 0 }, ++ exp16_32, sizeof(exp16_32)/sizeof(exp16_32[0]) }, + { "16/16", iov16, sizeof(iov16)/sizeof(iov16[0]), 16, +- exp16_16, sizeof(exp16_16)/sizeof(exp16_16[0]), 0 }, ++ exp16_16, sizeof(exp16_16)/sizeof(exp16_16[0]) }, + { "16/4", iov16, sizeof(iov16)/sizeof(iov16[0]), 4, +- exp16_4, sizeof(exp16_4)/sizeof(exp16_4[0]), 0 }, ++ exp16_4, sizeof(exp16_4)/sizeof(exp16_4[0]) }, + { "16/3", iov16, sizeof(iov16)/sizeof(iov16[0]), 3, +- exp16_3, sizeof(exp16_3)/sizeof(exp16_3[0]), 1 }, ++ exp16_3, sizeof(exp16_3)/sizeof(exp16_3[0]) }, + { "8/64", iov8, sizeof(iov8)/sizeof(iov8[0]), 64, +- exp8_64, sizeof(exp8_64)/sizeof(exp8_64[0]), 32 } ++ exp8_64, sizeof(exp8_64)/sizeof(exp8_64[0]) }, ++ { "odd/16", iov_odd, sizeof(iov_odd)/sizeof(iov_odd[0]), 16, ++ exp_odd_16, sizeof(exp_odd_16)/sizeof(exp_odd_16[0]) }, ++ { "skip/16", iov_skip, sizeof(iov_skip)/sizeof(iov_skip[0]), 16, ++ exp_skip_16, sizeof(exp_skip_16)/sizeof(exp_skip_16[0]) }, ++ { "empty/16", iov_empty, sizeof(iov_empty)/sizeof(iov_empty[0]), 16, ++ exp_empty_16, sizeof(exp_empty_16)/sizeof(exp_empty_16[0]) }, + }; + + void +@@ -155,16 +206,13 @@ doit (void) + 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); ++ if (iter.block_offset != 0) ++ fail("iter.block_offset: %u != 0\n", ++ (unsigned) iter.block_offset); + else if (debug) +- success("iter.block_offset: %u == %u\n", +- (unsigned) iter.block_offset, (unsigned) exp[j].block_offset); ++ success("iter.block_offset: %u == 0\n", ++ (unsigned) iter.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 c684814cc456a9792a9183ce77d32d435f29e6b7 Mon Sep 17 00:00:00 2001 +From: Daiki Ueno +Date: Tue, 1 Oct 2019 18:14:48 +0200 +Subject: [PATCH 2/3] iov: add _gnutls_iov_iter_sync to write back cached data + to iov + +Signed-off-by: Daiki Ueno +--- + lib/iov.c | 59 +++++++++++++++++++++++++++++++++++++++++++++ + lib/iov.h | 4 +++- + lib/libgnutls.map | 1 + + tests/iov.c | 61 +++++++++++++++++++++++++++++++++++++++++++---- + 4 files changed, 119 insertions(+), 6 deletions(-) + +diff --git a/lib/iov.c b/lib/iov.c +index 17272886c..1cd8d46dd 100644 +--- a/lib/iov.c ++++ b/lib/iov.c +@@ -133,3 +133,62 @@ _gnutls_iov_iter_next(struct iov_iter_st *iter, uint8_t **data) + + return 0; + } ++ ++/** ++ * _gnutls_iov_iter_sync: ++ * @iter: the iterator ++ * @data: data returned by _gnutls_iov_iter_next ++ * @data_size: size of @data ++ * ++ * Flush the content of temp buffer (if any) to the data buffer. ++ */ ++int ++_gnutls_iov_iter_sync(struct iov_iter_st *iter, const uint8_t *data, ++ size_t data_size) ++{ ++ size_t iov_index; ++ size_t iov_offset; ++ ++ /* We didn't return the cached block. */ ++ if (data != iter->block) ++ return 0; ++ ++ iov_index = iter->iov_index; ++ iov_offset = iter->iov_offset; ++ ++ /* When syncing a cache block we walk backwards because we only have a ++ * pointer to were the block ends in the iovec, walking backwards is ++ * fine as we are always writing a full block, so the whole content ++ * is written in the right places: ++ * iovec: |--0--|---1---|--2--|-3-| ++ * block: |-----------------------| ++ * 1st write |---| ++ * 2nd write |----- ++ * 3rd write |------- ++ * last write |----- ++ */ ++ while (data_size > 0) { ++ const giovec_t *iov; ++ uint8_t *p; ++ size_t to_write; ++ ++ while (iov_offset == 0) { ++ if (unlikely(iov_index == 0)) ++ return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); ++ ++ iov_index--; ++ iov_offset = iter->iov[iov_index].iov_len; ++ } ++ ++ iov = &iter->iov[iov_index]; ++ p = iov->iov_base; ++ to_write = MIN(data_size, iov_offset); ++ ++ iov_offset -= to_write; ++ data_size -= to_write; ++ ++ memcpy(p + iov_offset, &iter->block[data_size], to_write); ++ } ++ ++ return 0; ++} +diff --git a/lib/iov.h b/lib/iov.h +index 47fba559a..5b9903460 100644 +--- a/lib/iov.h ++++ b/lib/iov.h +@@ -34,7 +34,6 @@ struct iov_iter_st { + 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, +@@ -43,4 +42,7 @@ int _gnutls_iov_iter_init(struct iov_iter_st *iter, + + ssize_t _gnutls_iov_iter_next(struct iov_iter_st *iter, uint8_t **data); + ++int _gnutls_iov_iter_sync(struct iov_iter_st *iter, const uint8_t *data, ++ size_t data_size); ++ + #endif /* GNUTLS_LIB_IOV_H */ +diff --git a/lib/libgnutls.map b/lib/libgnutls.map +index f83a21e9b..d6973f72e 100644 +--- a/lib/libgnutls.map ++++ b/lib/libgnutls.map +@@ -1394,4 +1394,5 @@ GNUTLS_PRIVATE_3_4 { + # needed by tests/iov: + _gnutls_iov_iter_init; + _gnutls_iov_iter_next; ++ _gnutls_iov_iter_sync; + } GNUTLS_3_4; +diff --git a/tests/iov.c b/tests/iov.c +index 3d116b471..2acd2b5f5 100644 +--- a/tests/iov.c ++++ b/tests/iov.c +@@ -44,10 +44,10 @@ struct test_st { + }; + + static const giovec_t iov16[] = { +- {(void *) "0123456789abcdef", 16}, +- {(void *) "0123456789abcdef", 16}, +- {(void *) "0123456789abcdef", 16}, +- {(void *) "0123456789abcdef", 16} ++ {(void *) "0123456789012345", 16}, ++ {(void *) "0123456789012345", 16}, ++ {(void *) "0123456789012345", 16}, ++ {(void *) "0123456789012345", 16} + }; + + static const struct exp_st exp16_64[] = { +@@ -166,20 +166,53 @@ static const struct test_st tests[] = { + exp_empty_16, sizeof(exp_empty_16)/sizeof(exp_empty_16[0]) }, + }; + ++static void ++copy(giovec_t *dst, uint8_t *buffer, const giovec_t *src, size_t iovcnt) ++{ ++ uint8_t *p = buffer; ++ size_t i; ++ ++ for (i = 0; i < iovcnt; i++) { ++ dst[i].iov_base = p; ++ dst[i].iov_len = src[i].iov_len; ++ memcpy(dst[i].iov_base, src[i].iov_base, src[i].iov_len); ++ p += src[i].iov_len; ++ } ++} ++ ++static void ++translate(uint8_t *data, size_t len) ++{ ++ for (; len > 0; len--) { ++ uint8_t *p = &data[len - 1]; ++ if (*p >= '0' && *p <= '9') ++ *p = 'A' + *p - '0'; ++ else if (*p >= 'A' && *p <= 'Z') ++ *p = '0' + *p - 'A'; ++ } ++} ++ ++#define MAX_BUF 1024 ++#define MAX_IOV 16 ++ + void + doit (void) + { ++ uint8_t buffer[MAX_BUF]; + size_t i; + + for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++) { ++ giovec_t iov[MAX_IOV]; + struct iov_iter_st iter; + const struct exp_st *exp = tests[i].exp; + uint8_t *data; + size_t j; + ++ copy(iov, buffer, tests[i].iov, tests[i].iovcnt); ++ + success("%s\n", tests[i].name); + assert(_gnutls_iov_iter_init(&iter, +- tests[i].iov, tests[i].iovcnt, ++ iov, tests[i].iovcnt, + tests[i].block_size) == 0); + for (j = 0; j < tests[i].expcnt; j++) { + ssize_t ret; +@@ -212,7 +245,25 @@ doit (void) + else if (debug) + success("iter.block_offset: %u == 0\n", + (unsigned) iter.block_offset); ++ ++ translate(data, ret); ++ ++ ret = _gnutls_iov_iter_sync(&iter, data, ret); ++ if (ret < 0) ++ fail("sync failed\n"); + } + } ++ ++ for (j = 0; j < tests[i].iovcnt; j++) { ++ translate(iov[j].iov_base, iov[j].iov_len); ++ ++ if (memcmp(iov[j].iov_base, tests[i].iov[j].iov_base, ++ iov[j].iov_len) != 0) ++ fail("iov doesn't match: %*s != %*s\n", ++ (int)iov[j].iov_len, ++ (char *)iov[j].iov_base, ++ (int)tests[i].iov[j].iov_len, ++ (char *)tests[i].iov[j].iov_len); ++ } + } + } +-- +2.21.0 + + +From 6df0cf1c0ec727fc237a9b429684c8f2ef5d34b7 Mon Sep 17 00:00:00 2001 +From: Daiki Ueno +Date: Tue, 1 Oct 2019 18:15:19 +0200 +Subject: [PATCH 3/3] gnutls_aead_cipher_{en,de}cryptv2: write back cached data + to buffers + +Previously, those functions failed to write the output to the buffers +if the buffer length is not multiple of cipher block size. This makes +sure that the cached data is always flushed. + +Signed-off-by: Daiki Ueno +--- + lib/crypto-api.c | 18 ++++++++++++++++-- + tests/aead-cipher-vec.c | 14 ++++++++------ + 2 files changed, 24 insertions(+), 8 deletions(-) + +diff --git a/lib/crypto-api.c b/lib/crypto-api.c +index 41e759b74..7308d7e7b 100644 +--- a/lib/crypto-api.c ++++ b/lib/crypto-api.c +@@ -1113,6 +1113,7 @@ gnutls_aead_cipher_encryptv2(gnutls_aead_cipher_hd_t handle, + api_aead_cipher_hd_st *h = handle; + ssize_t ret; + uint8_t *p; ++ size_t len; + ssize_t blocksize = handle->ctx_enc.e->blocksize; + struct iov_iter_st iter; + size_t _tag_size; +@@ -1211,7 +1212,13 @@ gnutls_aead_cipher_encryptv2(gnutls_aead_cipher_hd_t handle, + return gnutls_assert_val(ret); + if (ret == 0) + break; +- ret = _gnutls_cipher_encrypt2(&handle->ctx_enc, p, ret, p, ret); ++ ++ len = ret; ++ ret = _gnutls_cipher_encrypt2(&handle->ctx_enc, p, len, p, len); ++ if (unlikely(ret < 0)) ++ return gnutls_assert_val(ret); ++ ++ ret = _gnutls_iov_iter_sync(&iter, p, len); + if (unlikely(ret < 0)) + return gnutls_assert_val(ret); + } +@@ -1253,6 +1260,7 @@ gnutls_aead_cipher_decryptv2(gnutls_aead_cipher_hd_t handle, + api_aead_cipher_hd_st *h = handle; + ssize_t ret; + uint8_t *p; ++ size_t len; + ssize_t blocksize = handle->ctx_enc.e->blocksize; + struct iov_iter_st iter; + uint8_t _tag[MAX_HASH_SIZE]; +@@ -1342,7 +1350,13 @@ gnutls_aead_cipher_decryptv2(gnutls_aead_cipher_hd_t handle, + return gnutls_assert_val(ret); + if (ret == 0) + break; +- ret = _gnutls_cipher_decrypt2(&handle->ctx_enc, p, ret, p, ret); ++ ++ len = ret; ++ ret = _gnutls_cipher_decrypt2(&handle->ctx_enc, p, len, p, len); ++ if (unlikely(ret < 0)) ++ return gnutls_assert_val(ret); ++ ++ ret = _gnutls_iov_iter_sync(&iter, p, len); + if (unlikely(ret < 0)) + return gnutls_assert_val(ret); + } +diff --git a/tests/aead-cipher-vec.c b/tests/aead-cipher-vec.c +index 6c2542cf1..10e3db862 100644 +--- a/tests/aead-cipher-vec.c ++++ b/tests/aead-cipher-vec.c +@@ -43,9 +43,9 @@ static void start(const char *name, int algo) + uint8_t key16[64]; + uint8_t iv16[32]; + uint8_t auth[128]; +- uint8_t data[128+64]; ++ uint8_t data[64+56+36]; + gnutls_datum_t key, iv; +- giovec_t iov[2]; ++ giovec_t iov[3]; + giovec_t auth_iov[2]; + uint8_t tag[64]; + size_t tag_size = 0; +@@ -60,13 +60,15 @@ static void start(const char *name, int algo) + + memset(iv.data, 0xff, iv.size); + memset(key.data, 0xfe, key.size); +- memset(data, 0xfa, 128); ++ memset(data, 0xfa, sizeof(data)); + 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; ++ iov[1].iov_len = 56; ++ iov[2].iov_base = data + 64 + 56; ++ iov[2].iov_len = 36; + + auth_iov[0].iov_base = auth; + auth_iov[0].iov_len = 64; +@@ -83,7 +85,7 @@ static void start(const char *name, int algo) + ret = gnutls_aead_cipher_encryptv2(ch, + iv.data, iv.size, + auth_iov, 2, +- iov, 2, ++ iov, 3, + tag, &tag_size); + if (ret < 0) + fail("could not encrypt data: %s\n", gnutls_strerror(ret)); +@@ -91,7 +93,7 @@ static void start(const char *name, int algo) + ret = gnutls_aead_cipher_decryptv2(ch, + iv.data, iv.size, + auth_iov, 2, +- iov, 2, ++ iov, 3, + tag, tag_size); + if (ret < 0) + fail("could not decrypt data: %s\n", gnutls_strerror(ret)); +-- +2.21.0 + diff --git a/SOURCES/gnutls-3.6.8-fix-cfb8-decrypt.patch b/SOURCES/gnutls-3.6.8-fix-cfb8-decrypt.patch new file mode 100644 index 0000000..738069b --- /dev/null +++ b/SOURCES/gnutls-3.6.8-fix-cfb8-decrypt.patch @@ -0,0 +1,204 @@ +From 1c2135506825ae80966fe2797613806916b7e3c0 Mon Sep 17 00:00:00 2001 +From: Daiki Ueno +Date: Wed, 6 Nov 2019 12:07:24 +0100 +Subject: [PATCH 1/2] nettle: backport fixes to cfb8_decrypt + +cfb8: don't truncate output IV if input is shorter than block size: +https://git.lysator.liu.se/nettle/nettle/commit/f4a9c842621baf5d71aa9cc3989851f44dc46861 + +Signed-off-by: Daiki Ueno +--- + lib/nettle/backport/cfb8.c | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +diff --git a/lib/nettle/backport/cfb8.c b/lib/nettle/backport/cfb8.c +index e9816feb7..1762192f4 100644 +--- a/lib/nettle/backport/cfb8.c ++++ b/lib/nettle/backport/cfb8.c +@@ -110,10 +110,12 @@ cfb8_decrypt(const void *ctx, nettle_cipher_func *f, + src += i; + dst += i; + +- memcpy(buffer, buffer + block_size, block_size); +- memcpy(buffer + block_size, src, +- length < block_size ? length : block_size); +- ++ if (i == block_size) ++ { ++ memcpy(buffer, buffer + block_size, block_size); ++ memcpy(buffer + block_size, src, ++ length < block_size ? length : block_size); ++ } + } + + memcpy(iv, buffer + i, block_size); +-- +2.21.0 + + +From cc01347302678719f0bcfb4f3383fe0f1e905ed8 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?G=C3=BCnther=20Deschner?= +Date: Wed, 6 Nov 2019 13:17:57 +0100 +Subject: [PATCH 2/2] crypto-selftests: test CFB8 ciphers with different + chunksizes + +Signed-off-by: Guenther Deschner +Signed-off-by: Daiki Ueno +--- + lib/crypto-selftests.c | 124 +++++++++++++++++++++++++++++++++++++++-- + 1 file changed, 118 insertions(+), 6 deletions(-) + +diff --git a/lib/crypto-selftests.c b/lib/crypto-selftests.c +index 6caf817e8..5f0a4ec8b 100644 +--- a/lib/crypto-selftests.c ++++ b/lib/crypto-selftests.c +@@ -710,6 +710,107 @@ static int test_cipher(gnutls_cipher_algorithm_t cipher, + return 0; + } + ++static int test_cipher_all_block_sizes(gnutls_cipher_algorithm_t cipher, ++ const struct cipher_vectors_st *vectors, ++ size_t vectors_size, unsigned flags) ++{ ++ gnutls_cipher_hd_t hd; ++ int ret; ++ unsigned int i; ++ uint8_t tmp[384]; ++ gnutls_datum_t key, iv = {NULL, 0}; ++ size_t block; ++ size_t offset; ++ ++ for (i = 0; i < vectors_size; i++) { ++ for (block = 1; block <= vectors[i].plaintext_size; block++) { ++ key.data = (void *) vectors[i].key; ++ key.size = vectors[i].key_size; ++ ++ iv.data = (void *) vectors[i].iv; ++ iv.size = gnutls_cipher_get_iv_size(cipher); ++ ++ if (iv.size != vectors[i].iv_size) ++ return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR); ++ ++ ret = gnutls_cipher_init(&hd, cipher, &key, &iv); ++ if (ret < 0) { ++ _gnutls_debug_log("error initializing: %s\n", ++ gnutls_cipher_get_name(cipher)); ++ return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR); ++ } ++ ++ for (offset = 0; ++ offset < vectors[i].plaintext_size; ++ offset += block) { ++ ret = ++ gnutls_cipher_encrypt2(hd, ++ vectors[i].plaintext + offset, ++ MIN(block, vectors[i].plaintext_size - offset), ++ tmp + offset, ++ sizeof(tmp) - offset); ++ if (ret < 0) ++ return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR); ++ } ++ ++ if (memcmp ++ (tmp, vectors[i].ciphertext, ++ vectors[i].plaintext_size) != 0) { ++ _gnutls_debug_log("%s encryption of test vector %d failed with block size %d/%d!\n", ++ gnutls_cipher_get_name(cipher), ++ i, (int)block, (int)vectors[i].plaintext_size); ++ return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR); ++ } ++ ++ gnutls_cipher_deinit(hd); ++ } ++ } ++ ++ for (i = 0; i < vectors_size; i++) { ++ for (block = 1; block <= vectors[i].plaintext_size; block++) { ++ key.data = (void *) vectors[i].key; ++ key.size = vectors[i].key_size; ++ ++ iv.data = (void *) vectors[i].iv; ++ iv.size = gnutls_cipher_get_iv_size(cipher); ++ ++ ret = gnutls_cipher_init(&hd, cipher, &key, &iv); ++ if (ret < 0) ++ return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR); ++ ++ for (offset = 0; ++ offset + block <= vectors[i].plaintext_size; ++ offset += block) { ++ ret = ++ gnutls_cipher_decrypt2(hd, ++ vectors[i].ciphertext + offset, ++ MIN(block, vectors[i].plaintext_size - offset), ++ tmp + offset, ++ sizeof(tmp) - offset); ++ if (ret < 0) ++ return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR); ++ } ++ ++ if (memcmp ++ (tmp, vectors[i].plaintext, ++ vectors[i].plaintext_size) != 0) { ++ _gnutls_debug_log("%s decryption of test vector %d failed with block size %d!\n", ++ gnutls_cipher_get_name(cipher), ++ i, (int)block); ++ return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR); ++ } ++ ++ gnutls_cipher_deinit(hd); ++ } ++ } ++ ++ _gnutls_debug_log ++ ("%s self check succeeded\n", ++ gnutls_cipher_get_name(cipher)); ++ ++ return 0; ++} ++ + /* AEAD modes (compat APIs) */ + static int test_cipher_aead_compat(gnutls_cipher_algorithm_t cipher, + const struct cipher_aead_vectors_st *vectors, +@@ -1721,6 +1822,14 @@ static int test_mac(gnutls_mac_algorithm_t mac, + if (!(flags & GNUTLS_SELF_TEST_FLAG_ALL) || ret < 0) \ + return ret + ++#define CASE2(x, func, func2, vectors) case x: \ ++ ret = func(x, V(vectors), flags); \ ++ if (!(flags & GNUTLS_SELF_TEST_FLAG_ALL) || ret < 0) \ ++ return ret; \ ++ ret = func2(x, V(vectors), flags); \ ++ if (!(flags & GNUTLS_SELF_TEST_FLAG_ALL) || ret < 0) \ ++ return ret ++ + #define NON_FIPS_CASE(x, func, vectors) case x: \ + if (_gnutls_fips_mode_enabled() == 0) { \ + ret = func(x, V(vectors), flags); \ +@@ -1786,14 +1895,17 @@ int gnutls_cipher_self_test(unsigned flags, gnutls_cipher_algorithm_t cipher) + NON_FIPS_CASE(GNUTLS_CIPHER_CHACHA20_POLY1305, test_cipher_aead, + chacha_poly1305_vectors); + FALLTHROUGH; +- CASE(GNUTLS_CIPHER_AES_128_CFB8, test_cipher, +- aes128_cfb8_vectors); ++ CASE2(GNUTLS_CIPHER_AES_128_CFB8, test_cipher, ++ test_cipher_all_block_sizes, ++ aes128_cfb8_vectors); + FALLTHROUGH; +- CASE(GNUTLS_CIPHER_AES_192_CFB8, test_cipher, +- aes192_cfb8_vectors); ++ CASE2(GNUTLS_CIPHER_AES_192_CFB8, test_cipher, ++ test_cipher_all_block_sizes, ++ aes192_cfb8_vectors); + FALLTHROUGH; +- CASE(GNUTLS_CIPHER_AES_256_CFB8, test_cipher, +- aes256_cfb8_vectors); ++ CASE2(GNUTLS_CIPHER_AES_256_CFB8, test_cipher, ++ test_cipher_all_block_sizes, ++ aes256_cfb8_vectors); + FALLTHROUGH; + CASE(GNUTLS_CIPHER_AES_128_XTS, test_cipher, + aes128_xts_vectors); +-- +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 +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 +--- + .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 ++ */ ++ ++#ifdef HAVE_CONFIG_H ++#include ++#endif ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#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 +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 +--- + .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 ++ */ ++ ++#ifdef HAVE_CONFIG_H ++#include ++#endif ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#define P11_KIT_FUTURE_UNSTABLE_API ++#include ++#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 +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 +--- + 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 new file mode 100644 index 0000000..ea01f2b --- /dev/null +++ b/SPECS/gnutls.spec @@ -0,0 +1,1012 @@ +Version: 3.6.8 +Release: 10%{?dist} +Patch1: gnutls-3.2.7-rpath.patch +Patch2: gnutls-3.6.4-no-now-guile.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 +Patch12: gnutls-3.6.8-decr-len.patch +Patch13: gnutls-3.6.8-fix-aead-cipher-encryptv2.patch +Patch14: gnutls-3.6.8-fix-cfb8-decrypt.patch +Patch15: gnutls-3.6.12-dtls-random.patch +%bcond_without dane +%if 0%{?rhel} +%bcond_with guile +%bcond_without fips +%else +%bcond_without guile +%bcond_without fips +%endif + +Summary: A TLS protocol implementation +Name: gnutls +# The libraries are LGPLv2.1+, utilities are GPLv3+ +License: GPLv3+ and LGPLv2+ +Group: System Environment/Libraries +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.4.1 +BuildRequires: trousers-devel >= 0.3.11.2 +BuildRequires: libidn2-devel +BuildRequires: libunistring-devel +BuildRequires: gperf, net-tools, datefudge, softhsm, gcc, gcc-c++ +BuildRequires: gnupg2 +%if %{with fips} +BuildRequires: fipscheck +%endif + +# for a sanity check on cert loading +BuildRequires: p11-kit-trust, ca-certificates +Requires: crypto-policies +Requires: p11-kit-trust +Requires: libtasn1 >= 4.3 +Requires: nettle >= 3.4.1 +Recommends: trousers >= 0.3.11.2 + +%if %{with dane} +BuildRequires: unbound-devel unbound-libs +%endif +%if %{with guile} +BuildRequires: guile-devel +%endif +URL: http://www.gnutls.org/ +Source0: ftp://ftp.gnutls.org/gcrypt/gnutls/v3.6/%{name}-%{version}.tar.xz +Source1: ftp://ftp.gnutls.org/gcrypt/gnutls/v3.6/%{name}-%{version}.tar.xz.sig +Source2: gpgkey-1F42418905D8206AA754CCDC29EE58B996865171.gpg + +# Wildcard bundling exception https://fedorahosted.org/fpc/ticket/174 +Provides: bundled(gnulib) = 20130424 + +%package c++ +Summary: The C++ interface to GnuTLS +Requires: %{name}%{?_isa} = %{version}-%{release} + +%package devel +Summary: Development files for the %{name} package +Group: Development/Libraries +Requires: %{name}%{?_isa} = %{version}-%{release} +Requires: %{name}-c++%{?_isa} = %{version}-%{release} +%if %{with dane} +Requires: %{name}-dane%{?_isa} = %{version}-%{release} +%endif +Requires: pkgconfig +Requires(post): /sbin/install-info +Requires(preun): /sbin/install-info + +%package utils +License: GPLv3+ +Summary: Command line tools for TLS protocol +Group: Applications/System +Requires: %{name}%{?_isa} = %{version}-%{release} +%if %{with dane} +Requires: %{name}-dane%{?_isa} = %{version}-%{release} +%endif + +%if %{with dane} +%package dane +Summary: A DANE protocol implementation for GnuTLS +Requires: %{name}%{?_isa} = %{version}-%{release} +%endif + +%if %{with guile} +%package guile +Summary: Guile bindings for the GNUTLS library +Group: Development/Libraries +Requires: %{name}%{?_isa} = %{version}-%{release} +Requires: guile +%endif + +%description +GnuTLS is a secure communications library implementing the SSL, TLS and DTLS +protocols and technologies around them. It provides a simple C language +application programming interface (API) to access the secure communications +protocols as well as APIs to parse and write X.509, PKCS #12, OpenPGP and +other required structures. + +%description c++ +GnuTLS is a secure communications library implementing the SSL, TLS and DTLS +protocols and technologies around them. It provides a simple C language +application programming interface (API) to access the secure communications +protocols as well as APIs to parse and write X.509, PKCS #12, OpenPGP and +other required structures. + +%description devel +GnuTLS is a secure communications library implementing the SSL, TLS and DTLS +protocols and technologies around them. It provides a simple C language +application programming interface (API) to access the secure communications +protocols as well as APIs to parse and write X.509, PKCS #12, OpenPGP and +other required structures. +This package contains files needed for developing applications with +the GnuTLS library. + +%description utils +GnuTLS is a secure communications library implementing the SSL, TLS and DTLS +protocols and technologies around them. It provides a simple C language +application programming interface (API) to access the secure communications +protocols as well as APIs to parse and write X.509, PKCS #12, OpenPGP and +other required structures. +This package contains command line TLS client and server and certificate +manipulation tools. + +%if %{with dane} +%description dane +GnuTLS is a secure communications library implementing the SSL, TLS and DTLS +protocols and technologies around them. It provides a simple C language +application programming interface (API) to access the secure communications +protocols as well as APIs to parse and write X.509, PKCS #12, OpenPGP and +other required structures. +This package contains library that implements the DANE protocol for verifying +TLS certificates through DNSSEC. +%endif + +%if %{with guile} +%description guile +GnuTLS is a secure communications library implementing the SSL, TLS and DTLS +protocols and technologies around them. It provides a simple C language +application programming interface (API) to access the secure communications +protocols as well as APIs to parse and write X.509, PKCS #12, OpenPGP and +other required structures. +This package contains Guile bindings for the library. +%endif + +%prep +gpgv2 --keyring %{SOURCE2} %{SOURCE1} %{SOURCE0} + +%autosetup -p1 + +sed -i -e 's|sys_lib_dlsearch_path_spec="/lib /usr/lib|sys_lib_dlsearch_path_spec="/lib /usr/lib %{_libdir}|g' configure +rm -f lib/minitasn1/*.c lib/minitasn1/*.h +rm -f src/libopts/*.c src/libopts/*.h src/libopts/compat/*.c src/libopts/compat/*.h + +echo "SYSTEM=NORMAL" >> tests/system.prio + +# Note that we explicitly enable SHA1, as SHA1 deprecation is handled +# via the crypto policies + +%build +CCASFLAGS="$CCASFLAGS -Wa,--generate-missing-build-notes=yes" +export CCASFLAGS +%configure --with-libtasn1-prefix=%{_prefix} \ +%if %{with fips} + --enable-fips140-mode \ +%endif + --enable-tls13-support \ + --enable-sha1-support \ + --disable-static \ + --disable-openssl-compatibility \ + --disable-non-suiteb-curves \ + --with-system-priority-file=%{_sysconfdir}/crypto-policies/back-ends/gnutls.config \ + --with-default-trust-store-pkcs11="pkcs11:" \ + --with-trousers-lib=%{_libdir}/libtspi.so.1 \ + --htmldir=%{_docdir}/manual \ +%if %{with guile} + --enable-guile \ +%else + --disable-guile \ +%endif +%if %{with dane} + --with-unbound-root-key-file=/var/lib/unbound/root.key \ + --enable-dane \ +%else + --disable-dane \ +%endif + --disable-rpath \ + --with-default-priority-string="@SYSTEM" + +make %{?_smp_mflags} V=1 + +%if %{with fips} +%define __spec_install_post \ + %{?__debug_package:%{__debug_install_post}} \ + %{__arch_install_post} \ + %{__os_install_post} \ + fipshmac -d $RPM_BUILD_ROOT%{_libdir} $RPM_BUILD_ROOT%{_libdir}/libgnutls.so.30.*.* \ + file=`basename $RPM_BUILD_ROOT%{_libdir}/libgnutls.so.30.*.hmac` && mv $RPM_BUILD_ROOT%{_libdir}/$file $RPM_BUILD_ROOT%{_libdir}/.$file && ln -s .$file $RPM_BUILD_ROOT%{_libdir}/.libgnutls.so.30.hmac \ +%{nil} +%endif + +%install +make install DESTDIR=$RPM_BUILD_ROOT +make -C doc install-html DESTDIR=$RPM_BUILD_ROOT +rm -f $RPM_BUILD_ROOT%{_infodir}/dir +rm -f $RPM_BUILD_ROOT%{_libdir}/*.la +rm -f $RPM_BUILD_ROOT%{_libdir}/guile/2.0/guile-gnutls*.a +rm -f $RPM_BUILD_ROOT%{_libdir}/guile/2.0/guile-gnutls*.la +rm -f $RPM_BUILD_ROOT%{_libdir}/gnutls/libpkcs11mock1.* +%if %{without dane} +rm -f $RPM_BUILD_ROOT%{_libdir}/pkgconfig/gnutls-dane.pc +%endif + +%find_lang gnutls + +%check +make check %{?_smp_mflags} + +%post devel +if [ -f %{_infodir}/gnutls.info.gz ]; then + /sbin/install-info %{_infodir}/gnutls.info.gz %{_infodir}/dir || : +fi + +%preun devel +if [ $1 = 0 -a -f %{_infodir}/gnutls.info.gz ]; then + /sbin/install-info --delete %{_infodir}/gnutls.info.gz %{_infodir}/dir || : +fi + +%files -f gnutls.lang +%defattr(-,root,root,-) +%{_libdir}/libgnutls.so.30* +%if %{with fips} +%{_libdir}/.libgnutls.so.30*.hmac +%endif +%doc README.md AUTHORS NEWS THANKS +%license LICENSE doc/COPYING doc/COPYING.LESSER + +%files c++ +%{_libdir}/libgnutlsxx.so.* + +%files devel +%defattr(-,root,root,-) +%{_includedir}/* +%{_libdir}/libgnutls*.so +%if %{with fips} +%{_libdir}/.libgnutls.so.*.hmac +%endif + +%{_libdir}/pkgconfig/*.pc +%{_mandir}/man3/* +%{_infodir}/gnutls* +%{_infodir}/pkcs11-vision* +%{_docdir}/manual/* + +%files utils +%defattr(-,root,root,-) +%{_bindir}/certtool +%{_bindir}/tpmtool +%{_bindir}/ocsptool +%{_bindir}/psktool +%{_bindir}/p11tool +%{_bindir}/srptool +%if %{with dane} +%{_bindir}/danetool +%endif +%{_bindir}/gnutls* +%{_mandir}/man1/* +%doc doc/certtool.cfg + +%if %{with dane} +%files dane +%defattr(-,root,root,-) +%{_libdir}/libgnutls-dane.so.* +%endif + +%if %{with guile} +%files guile +%defattr(-,root,root,-) +%{_libdir}/guile/2.0/guile-gnutls*.so* +%{_libdir}/guile/2.0/site-ccache/gnutls.go +%{_libdir}/guile/2.0/site-ccache/gnutls/extra.go +%{_datadir}/guile/site/2.0/gnutls.scm +%{_datadir}/guile/site/2.0/gnutls/extra.scm +%endif + +%changelog +* Tue Apr 21 2020 Daiki Ueno - 3.6.8-10 +- Fix CVE-2020-11501 (#1826176) + +* Wed Nov 6 2019 Daiki Ueno - 3.6.8-9 +- Fix CFB8 decryption when repeatedly called (#1757848) +- Fix gnutls_aead_cipher_{en,de}cryptv2 with input not multiple of block size (#1757856) + +* Fri Aug 16 2019 Daiki Ueno - 3.6.8-8 +- Use fallback random function for RSA blinding in FIPS selftests + +* Fri Aug 16 2019 Daiki Ueno - 3.6.8-7 +- Fix deterministic signature creation in selftests + +* Fri Aug 16 2019 Daiki Ueno - 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 - 3.6.8-5 +- Avoid UB when encrypting session tickets + +* Tue Jul 2 2019 Daiki Ueno - 3.6.8-4 +- Add RNG continuous test under FIPS + +* Fri Jun 14 2019 Daiki Ueno - 3.6.8-3 +- Follow-up fix on multiple key updates handling (#1673975) + +* Thu Jun 13 2019 Daiki Ueno - 3.6.8-2 +- Run FIPS AES self-tests over overridden algorithms + +* Wed May 29 2019 Daiki Ueno - 3.6.8-1 +- Update to upstream 3.6.8 release + +* Fri May 24 2019 Anderson Sasaki - 3.6.5-4 +- Fixed FIPS signatures self tests (#1680509) + +* Wed Mar 27 2019 Anderson Sasaki - 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 - 3.6.5-2 +- Fixed FIPS integrity self tests (#1665061) + +* Mon Dec 17 2018 Anderson Sasaki - 3.6.5-1 +- Update to upstream 3.6.5 release +- Fixes CVE-2018-16868 (#1655395) +- Removed ldconfig scriptlet +- Added explicit Requires for nettle >= 3.4.1 + +* Mon Nov 26 2018 Anderson Sasaki - 3.6.4-7 +- Fix incorrect certificate type returned in TLS1.3 resumption (#1649786) + +* Mon Nov 12 2018 Anderson Sasaki - 3.6.4-6 +- Add support for record_size_limit extension in TLS1.2 (#1644850) + +* Tue Oct 30 2018 Nikos Mavrogiannopoulos - 3.6.4-5 +- Fix issue with GOST ciphers (#1644193) +- Made gnutls-serv use the default priorities if none is specified (#1644243) + +* Wed Oct 24 2018 Nikos Mavrogiannopoulos - 3.6.4-3 +- Fix issue with rehandshake affecting glib-networking (#1641072) + +* Tue Oct 16 2018 Tomáš Mráz - 3.6.4-2 +- Add missing annobin notes for assembler sources + +* Tue Sep 25 2018 Nikos Mavrogiannopoulos - 3.6.4-1 +- Updated to upstream 3.6.4 release +- Added support for the latest version of the TLS1.3 protocol + +* Thu Aug 16 2018 Nikos Mavrogiannopoulos - 3.6.3-4 +- Fixed support for ECDSA public keys (backported from Fedora) +- Ensure that we do not cause issues with version rollback detection + and TLS1.3. + +* Thu Jul 26 2018 Nikos Mavrogiannopoulos - 3.6.3-4 +- Updated to upstream 3.6.3 release + +* Wed Jun 06 2018 Nikos Mavrogiannopoulos - 3.6.2-3 +- Include FIPS mode +- Add missing BuildRequires: gnupg2 for gpgv2 in %%prep + +* Fri Feb 16 2018 Nikos Mavrogiannopoulos - 3.6.2-1 +- Updated to upstream 3.6.2 release + +* Wed Feb 07 2018 Fedora Release Engineering - 3.6.1-5 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_28_Mass_Rebuild + +* Fri Feb 2 2018 Nikos Mavrogiannopoulos - 3.6.1-4 +- Rebuilt to address incompatibility with new nettle + +* Thu Nov 30 2017 Nikos Mavrogiannopoulos - 3.6.1-3 +- Corrected regression from 3.6.1-2 which prevented the loading of + arbitrary p11-kit modules (#1507402) + +* Mon Nov 6 2017 Nikos Mavrogiannopoulos - 3.6.1-2 +- Prevent the loading of all PKCS#11 modules on certificate verification + but only restrict to p11-kit trust module (#1507402) + +* Sat Oct 21 2017 Nikos Mavrogiannopoulos - 3.6.1-1 +- Update to upstream 3.6.1 release + +* Mon Aug 21 2017 Nikos Mavrogiannopoulos - 3.6.0-1 +- Update to upstream 3.6.0 release + +* Wed Aug 02 2017 Fedora Release Engineering - 3.5.14-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Binutils_Mass_Rebuild + +* Wed Jul 26 2017 Fedora Release Engineering - 3.5.14-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Mass_Rebuild + +* Tue Jul 04 2017 Nikos Mavrogiannopoulos - 3.5.14-1 +- Update to upstream 3.5.14 release + +* Wed Jun 07 2017 Nikos Mavrogiannopoulos - 3.5.13-1 +- Update to upstream 3.5.13 release + +* Thu May 11 2017 Nikos Mavrogiannopoulos - 3.5.12-2 +- Fix issue with p11-kit-trust arch dependency + +* Thu May 11 2017 Nikos Mavrogiannopoulos - 3.5.12-1 +- Update to upstream 3.5.12 release + +* Fri Apr 07 2017 Nikos Mavrogiannopoulos - 3.5.11-1 +- Update to upstream 3.5.11 release + +* Mon Mar 06 2017 Nikos Mavrogiannopoulos - 3.5.10-1 +- Update to upstream 3.5.10 release + +* Wed Feb 15 2017 Nikos Mavrogiannopoulos - 3.5.9-2 +- Work around missing pkg-config file (#1422256) + +* Tue Feb 14 2017 Nikos Mavrogiannopoulos - 3.5.9-1 +- Update to upstream 3.5.9 release + +* Fri Feb 10 2017 Fedora Release Engineering - 3.5.8-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_26_Mass_Rebuild + +* Sat Feb 4 2017 Nikos Mavrogiannopoulos 3.5.8-2 +- Added patch fix initialization issue in gnutls_pkcs11_obj_list_import_url4 + +* Mon Jan 9 2017 Nikos Mavrogiannopoulos 3.5.8-1 +- New upstream release + +* Tue Dec 13 2016 Nikos Mavrogiannopoulos 3.5.7-3 +- Fix PKCS#8 file loading (#1404084) + +* Thu Dec 8 2016 Nikos Mavrogiannopoulos 3.5.7-1 +- New upstream release + +* Fri Nov 4 2016 Nikos Mavrogiannopoulos 3.5.6-1 +- New upstream release + +* Tue Oct 11 2016 walters@redhat.com - 3.5.5-2 +- Apply patch to fix compatibility with ostree (#1383708) + +* Mon Oct 10 2016 Nikos Mavrogiannopoulos 3.5.5-1 +- New upstream release + +* Thu Sep 8 2016 Nikos Mavrogiannopoulos 3.5.4-1 +- New upstream release + +* Mon Aug 29 2016 Nikos Mavrogiannopoulos 3.5.3-2 +- Work around #1371082 for x86 +- Fixed issue with DTLS sliding window implementation (#1370881) + +* Tue Aug 9 2016 Nikos Mavrogiannopoulos 3.5.3-1 +- New upstream release + +* Wed Jul 6 2016 Nikos Mavrogiannopoulos 3.5.2-1 +- New upstream release + +* Wed Jun 15 2016 Nikos Mavrogiannopoulos 3.5.1-1 +- New upstream release + +* Tue Jun 7 2016 Nikos Mavrogiannopoulos 3.4.13-1 +- New upstream release (#1343258) +- Addresses issue with setuid programs introduced in 3.4.12 (#1343342) + +* Fri May 20 2016 Nikos Mavrogiannopoulos 3.4.12-1 +- New upstream release + +* Mon Apr 11 2016 Nikos Mavrogiannopoulos 3.4.11-1 +- New upstream release + +* Fri Mar 4 2016 Nikos Mavrogiannopoulos 3.4.10-1 +- New upstream release (#1314576) + +* Wed Feb 3 2016 Nikos Mavrogiannopoulos 3.4.9-1 +- Fix broken key usage flags introduced in 3.4.8 (#1303355) + +* Mon Jan 11 2016 Nikos Mavrogiannopoulos 3.4.8-1 +- New upstream release (#1297079) + +* Mon Nov 23 2015 Nikos Mavrogiannopoulos 3.4.7-1 +- New upstream release (#1284300) +- Documentation updates (#1282864) +- Adds interface to set unique IDs in certificates (#1281343) +- Allow arbitrary key sizes with ARCFOUR (#1284401) + +* Wed Oct 21 2015 Nikos Mavrogiannopoulos 3.4.6-1 +- New upstream release (#1273672) +- Enhances p11tool to write CKA_ISSUER and CKA_SERIAL_NUMBER (#1272178) + +* Tue Oct 20 2015 Adam Williamson - 3.4.5-2 +- fix interaction with Chrome 45+ (master secret extension) (#1273102) + +* Mon Sep 14 2015 Nikos Mavrogiannopoulos 3.4.5-1 +- New upstream release (#1252192) +- Eliminates hard limits on CRL parsing of certtool. + +* Mon Aug 10 2015 Nikos Mavrogiannopoulos 3.4.4-1 +- new upstream release +- no longer requires trousers patch +- fixes issue in gnutls_x509_privkey_import (#1250020) + +* Mon Jul 13 2015 Nikos Mavrogiannopoulos 3.4.3-2 +- Don't link against trousers but rather dlopen() it when available. + That avoids a dependency on openssl by the main library. + +* Mon Jul 13 2015 Nikos Mavrogiannopoulos 3.4.3-1 +- new upstream release + +* Thu Jul 02 2015 Adam Jackson 3.4.2-3 +- Only disable -z now for the guile modules + +* Thu Jun 18 2015 Nikos Mavrogiannopoulos 3.4.2-2 +- rename the symbol version for internal symbols to avoid clashes + with 3.3.x. + +* Wed Jun 17 2015 Nikos Mavrogiannopoulos 3.4.2-1 +- new upstream release + +* Tue May 5 2015 Nikos Mavrogiannopoulos 3.4.1-2 +- Provide missing GNUTLS_SUPPLEMENTAL_USER_MAPPING_DATA definition + +* Mon May 4 2015 Nikos Mavrogiannopoulos 3.4.1-1 +- new upstream release + +* Sat May 02 2015 Kalev Lember - 3.3.14-2 +- Rebuilt for GCC 5 C++11 ABI change + +* Mon Mar 30 2015 Nikos Mavrogiannopoulos 3.3.14-1 +- new upstream release +- improved BER decoding of PKCS #12 structures (#1131461) + +* Fri Mar 6 2015 Nikos Mavrogiannopoulos 3.3.13-3 +- Build with hardened flags +- Removed -Wl,--no-add-needed linker flag + +* Fri Feb 27 2015 Till Maas - 3.3.13-2 +- Do not build with hardened flags + +* Thu Feb 26 2015 Nikos Mavrogiannopoulos 3.3.13-1 +- new upstream release + +* Sat Feb 21 2015 Till Maas - 3.3.12-3 +- Make build verbose +- Use %%license + +* Sat Feb 21 2015 Till Maas - 3.3.12-2 +- Rebuilt for Fedora 23 Change + https://fedoraproject.org/wiki/Changes/Harden_all_packages_with_position-independent_code + +* Mon Jan 19 2015 Nikos Mavrogiannopoulos 3.3.12-1 +- new upstream release + +* Mon Jan 5 2015 Nikos Mavrogiannopoulos 3.3.11-2 +- enabled guile bindings (#1177847) + +* Thu Dec 11 2014 Nikos Mavrogiannopoulos 3.3.11-1 +- new upstream release + +* Mon Nov 10 2014 Nikos Mavrogiannopoulos 3.3.10-1 +- new upstream release + +* Thu Oct 23 2014 Nikos Mavrogiannopoulos 3.3.9-2 +- applied fix for issue in get-issuer (#1155901) + +* Mon Oct 13 2014 Nikos Mavrogiannopoulos 3.3.9-1 +- new upstream release + +* Fri Sep 19 2014 Nikos Mavrogiannopoulos 3.3.8-2 +- strip rpath from library + +* Thu Sep 18 2014 Nikos Mavrogiannopoulos 3.3.8-1 +- new upstream release + +* Mon Aug 25 2014 Nikos Mavrogiannopoulos 3.3.7-1 +- new upstream release + +* Sat Aug 16 2014 Fedora Release Engineering - 3.3.6-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_22_Mass_Rebuild + +* Wed Jul 23 2014 Nikos Mavrogiannopoulos 3.3.6-1 +- new upstream release + +* Tue Jul 01 2014 Nikos Mavrogiannopoulos 3.3.5-2 +- Added work-around for s390 builds with gcc 4.9 (#1102324) + +* Mon Jun 30 2014 Nikos Mavrogiannopoulos 3.3.5-1 +- new upstream release + +* Tue Jun 17 2014 Nikos Mavrogiannopoulos 3.3.4-3 +- explicitly depend on p11-kit-trust + +* Sat Jun 07 2014 Fedora Release Engineering - 3.3.4-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_Mass_Rebuild + +* Mon Jun 02 2014 Nikos Mavrogiannopoulos 3.3.4-1 +- new upstream release + +* Fri May 30 2014 Nikos Mavrogiannopoulos 3.3.3-1 +- new upstream release + +* Wed May 21 2014 Nikos Mavrogiannopoulos 3.3.2-2 +- Require crypto-policies + +* Fri May 09 2014 Nikos Mavrogiannopoulos 3.3.2-1 +- new upstream release + +* Mon May 05 2014 Nikos Mavrogiannopoulos 3.3.1-4 +- Replaced /etc/crypto-profiles/apps with /etc/crypto-policies/back-ends. +- Added support for "very weak" profile. + +* Mon Apr 28 2014 Nikos Mavrogiannopoulos 3.3.1-2 +- gnutls_global_deinit() will not do anything if the previous + initialization has failed (#1091053) + +* Mon Apr 28 2014 Nikos Mavrogiannopoulos 3.3.1-1 +- new upstream release + +* Mon Apr 14 2014 Nikos Mavrogiannopoulos 3.3.0-1 +- new upstream release + +* Tue Apr 08 2014 Nikos Mavrogiannopoulos 3.2.13-1 +- new upstream release + +* Wed Mar 05 2014 Nikos Mavrogiannopoulos 3.2.12.1-1 +- new upstream release + +* Mon Mar 03 2014 Nikos Mavrogiannopoulos 3.2.12-1 +- new upstream release + +* Mon Feb 03 2014 Nikos Mavrogiannopoulos 3.2.10-2 +- use p11-kit trust store for certificate verification + +* Mon Feb 03 2014 Nikos Mavrogiannopoulos 3.2.10-1 +- new upstream release + +* Tue Jan 14 2014 Tomáš Mráz 3.2.8-2 +- build the crywrap tool + +* Mon Dec 23 2013 Nikos Mavrogiannopoulos 3.2.8-1 +- new upstream release + +* Wed Dec 4 2013 Nikos Mavrogiannopoulos 3.2.7-2 +- Use the correct root key for unbound /var/lib/unbound/root.key (#1012494) +- Pull asm fixes from upstream (#973210) + +* Mon Nov 25 2013 Nikos Mavrogiannopoulos 3.2.7-1 +- new upstream release +- added dependency to autogen-libopts-devel to use the system's + libopts library +- added dependency to trousers-devel to enable TPM support + +* Mon Nov 4 2013 Tomáš Mráz 3.1.16-1 +- new upstream release +- fixes CVE-2013-4466 off-by-one in dane_query_tlsa() + +* Fri Oct 25 2013 Tomáš Mráz 3.1.15-1 +- new upstream release +- fixes CVE-2013-4466 buffer overflow in handling DANE entries + +* Wed Oct 16 2013 Tomáš Mráz 3.1.13-3 +- enable ECC NIST Suite B curves + +* Sat Aug 03 2013 Fedora Release Engineering - 3.1.13-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_20_Mass_Rebuild + +* Mon Jul 15 2013 Tomáš Mráz 3.1.13-1 +- new upstream release + +* Mon May 13 2013 Tomáš Mráz 3.1.11-1 +- new upstream release + +* Mon Mar 25 2013 Tomas Mraz 3.1.10-1 +- new upstream release +- license of the library is back to LGPLv2.1+ + +* Fri Mar 15 2013 Tomas Mraz 3.1.9-1 +- new upstream release + +* Thu Mar 7 2013 Tomas Mraz 3.1.8-3 +- drop the temporary old library + +* Tue Feb 26 2013 Tomas Mraz 3.1.8-2 +- don't send ECC algos as supported (#913797) + +* Thu Feb 21 2013 Tomas Mraz 3.1.8-1 +- new upstream version + +* Wed Feb 6 2013 Tomas Mraz 3.1.7-1 +- new upstream version, requires rebuild of dependencies +- this release temporarily includes old compatibility .so + +* Tue Feb 5 2013 Tomas Mraz 2.12.22-2 +- rebuilt with new libtasn1 +- make guile bindings optional - breaks i686 build and there is + no dependent package + +* Tue Jan 8 2013 Tomas Mraz 2.12.22-1 +- new upstream version + +* Wed Nov 28 2012 Tomas Mraz 2.12.21-2 +- use RSA bit sizes supported by libgcrypt in FIPS mode for security + levels (#879643) + +* Fri Nov 9 2012 Tomas Mraz 2.12.21-1 +- new upstream version + +* Thu Nov 1 2012 Tomas Mraz 2.12.20-4 +- negotiate only FIPS approved algorithms in the FIPS mode (#871826) + +* Wed Aug 8 2012 Tomas Mraz 2.12.20-3 +- fix the gnutls-cli-debug manpage - patch by Peter Schiffer + +* Thu Jul 19 2012 Fedora Release Engineering - 2.12.20-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_18_Mass_Rebuild + +* Mon Jun 18 2012 Tomas Mraz 2.12.20-1 +- new upstream version + +* Fri May 18 2012 Tomas Mraz 2.12.19-1 +- new upstream version + +* Thu Mar 29 2012 Tomas Mraz 2.12.18-1 +- new upstream version + +* Thu Mar 8 2012 Tomas Mraz 2.12.17-1 +- new upstream version +- fix leaks in key generation (#796302) + +* Fri Feb 03 2012 Kevin Fenzi - 2.12.14-3 +- Disable largefile on arm arch. (#787287) + +* Fri Jan 13 2012 Fedora Release Engineering - 2.12.14-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_17_Mass_Rebuild + +* Tue Nov 8 2011 Tomas Mraz 2.12.14-1 +- new upstream version + +* Mon Oct 24 2011 Tomas Mraz 2.12.12-1 +- new upstream version + +* Thu Sep 29 2011 Tomas Mraz 2.12.11-1 +- new upstream version + +* Fri Aug 26 2011 Tomas Mraz 2.12.9-1 +- new upstream version + +* Tue Aug 16 2011 Tomas Mraz 2.12.8-1 +- new upstream version + +* Mon Jul 25 2011 Tomas Mraz 2.12.7-2 +- fix problem when using new libgcrypt +- split libgnutlsxx to a subpackage (#455146) +- drop libgnutls-openssl (#460310) + +* Tue Jun 21 2011 Tomas Mraz 2.12.7-1 +- new upstream version + +* Mon May 9 2011 Tomas Mraz 2.12.4-1 +- new upstream version + +* Tue Apr 26 2011 Tomas Mraz 2.12.3-1 +- new upstream version + +* Mon Apr 18 2011 Tomas Mraz 2.12.2-1 +- new upstream version + +* Thu Mar 3 2011 Tomas Mraz 2.10.5-1 +- new upstream version + +* Tue Feb 08 2011 Fedora Release Engineering - 2.10.4-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_15_Mass_Rebuild + +* Wed Dec 8 2010 Tomas Mraz 2.10.4-1 +- new upstream version + +* Thu Dec 2 2010 Tomas Mraz 2.10.3-2 +- fix buffer overflow in gnutls-serv (#659259) + +* Fri Nov 19 2010 Tomas Mraz 2.10.3-1 +- new upstream version + +* Thu Sep 30 2010 Tomas Mraz 2.10.2-1 +- new upstream version + +* Wed Sep 29 2010 jkeating - 2.10.1-4 +- Rebuilt for gcc bug 634757 + +* Thu Sep 23 2010 Tomas Mraz 2.10.1-3 +- more patching for internal errors regression (#629858) + patch by Vivek Dasmohapatra + +* Tue Sep 21 2010 Tomas Mraz 2.10.1-2 +- backported patch from upstream git hopefully fixing internal errors + (#629858) + +* Wed Aug 4 2010 Tomas Mraz 2.10.1-1 +- new upstream version + +* Wed Jun 2 2010 Tomas Mraz 2.8.6-2 +- add support for safe renegotiation CVE-2009-3555 (#533125) + +* Wed May 12 2010 Tomas Mraz 2.8.6-1 +- upgrade to a new upstream version + +* Mon Feb 15 2010 Rex Dieter 2.8.5-4 +- FTBFS gnutls-2.8.5-3.fc13: ImplicitDSOLinking (#564624) + +* Thu Jan 28 2010 Tomas Mraz 2.8.5-3 +- drop superfluous rpath from binaries +- do not call autoreconf during build +- specify the license on utils subpackage + +* Mon Jan 18 2010 Tomas Mraz 2.8.5-2 +- do not create static libraries (#556052) + +* Mon Nov 2 2009 Tomas Mraz 2.8.5-1 +- upgrade to a new upstream version + +* Wed Sep 23 2009 Tomas Mraz 2.8.4-1 +- upgrade to a new upstream version + +* Fri Aug 14 2009 Tomas Mraz 2.8.3-1 +- upgrade to a new upstream version + +* Fri Jul 24 2009 Fedora Release Engineering - 2.8.1-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_12_Mass_Rebuild + +* Wed Jun 10 2009 Tomas Mraz 2.8.1-1 +- upgrade to a new upstream version + +* Wed Jun 3 2009 Tomas Mraz 2.8.0-1 +- upgrade to a new upstream version + +* Mon May 4 2009 Tomas Mraz 2.6.6-1 +- upgrade to a new upstream version - security fixes + +* Tue Apr 14 2009 Tomas Mraz 2.6.5-1 +- upgrade to a new upstream version, minor bugfixes only + +* Fri Mar 6 2009 Tomas Mraz 2.6.4-1 +- upgrade to a new upstream version + +* Tue Feb 24 2009 Fedora Release Engineering - 2.6.3-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_11_Mass_Rebuild + +* Mon Dec 15 2008 Tomas Mraz 2.6.3-1 +- upgrade to a new upstream version + +* Thu Dec 4 2008 Tomas Mraz 2.6.2-1 +- upgrade to a new upstream version + +* Tue Nov 11 2008 Tomas Mraz 2.4.2-3 +- fix chain verification issue CVE-2008-4989 (#470079) + +* Thu Sep 25 2008 Tomas Mraz 2.4.2-2 +- add guile subpackage (#463735) +- force new libtool through autoreconf to drop unnecessary rpaths + +* Tue Sep 23 2008 Tomas Mraz 2.4.2-1 +- new upstream version + +* Tue Jul 1 2008 Tomas Mraz 2.4.1-1 +- new upstream version +- correct the license tag +- explicit --with-included-opencdk not needed +- use external lzo library, internal not included anymore + +* Tue Jun 24 2008 Tomas Mraz 2.4.0-1 +- upgrade to latest upstream + +* Tue May 20 2008 Tomas Mraz 2.0.4-3 +- fix three security issues in gnutls handshake - GNUTLS-SA-2008-1 + (#447461, #447462, #447463) + +* Mon Feb 4 2008 Joe Orton 2.0.4-2 +- use system libtasn1 + +* Tue Dec 4 2007 Tomas Mraz 2.0.4-1 +- upgrade to latest upstream + +* Tue Aug 21 2007 Tomas Mraz 1.6.3-2 +- license tag fix + +* Wed Jun 6 2007 Tomas Mraz 1.6.3-1 +- upgrade to latest upstream (#232445) + +* Tue Apr 10 2007 Tomas Mraz 1.4.5-2 +- properly require install-info (patch by Ville Skyttä) +- standard buildroot and use dist tag +- add COPYING and README to doc + +* Wed Feb 7 2007 Tomas Mraz 1.4.5-1 +- new upstream version +- drop libtermcap-devel from buildrequires + +* Thu Sep 14 2006 Tomas Mraz 1.4.1-2 +- detect forged signatures - CVE-2006-4790 (#206411), patch + from upstream + +* Tue Jul 18 2006 Tomas Mraz - 1.4.1-1 +- upgrade to new upstream version, only minor changes + +* Wed Jul 12 2006 Jesse Keating - 1.4.0-1.1 +- rebuild + +* Wed Jun 14 2006 Tomas Mraz - 1.4.0-1 +- upgrade to new upstream version (#192070), rebuild + of dependent packages required + +* Tue May 16 2006 Tomas Mraz - 1.2.10-2 +- added missing buildrequires + +* Mon Feb 13 2006 Tomas Mraz - 1.2.10-1 +- updated to new version (fixes CVE-2006-0645) + +* Fri Feb 10 2006 Jesse Keating - 1.2.9-3.2 +- bump again for double-long bug on ppc(64) + +* Tue Feb 07 2006 Jesse Keating - 1.2.9-3.1 +- rebuilt for new gcc4.1 snapshot and glibc changes + +* Tue Jan 3 2006 Jesse Keating 1.2.9-3 +- rebuilt + +* Fri Dec 9 2005 Tomas Mraz 1.2.9-2 +- replaced *-config scripts with calls to pkg-config to + solve multilib conflicts + +* Wed Nov 23 2005 Tomas Mraz 1.2.9-1 +- upgrade to newest upstream +- removed .la files (#172635) + +* Sun Aug 7 2005 Tomas Mraz 1.2.6-1 +- upgrade to newest upstream (rebuild of dependencies necessary) + +* Mon Jul 4 2005 Tomas Mraz 1.0.25-2 +- split the command line tools to utils subpackage + +* Sat Apr 30 2005 Tomas Mraz 1.0.25-1 +- new upstream version fixes potential DOS attack + +* Sat Apr 23 2005 Tomas Mraz 1.0.24-2 +- readd the version script dropped by upstream + +* Fri Apr 22 2005 Tomas Mraz 1.0.24-1 +- update to the latest upstream version on the 1.0 branch + +* Wed Mar 2 2005 Warren Togami 1.0.20-6 +- gcc4 rebuild + +* Tue Jan 4 2005 Ivana Varekova 1.0.20-5 +- add gnutls Requires zlib-devel (#144069) + +* Mon Nov 08 2004 Colin Walters 1.0.20-4 +- Make gnutls-devel Require libgcrypt-devel + +* Tue Sep 21 2004 Jeff Johnson 1.0.20-3 +- rebuild with release++, otherwise unchanged. + +* Tue Sep 7 2004 Jeff Johnson 1.0.20-2 +- patent tainted SRP code removed. + +* Sun Sep 5 2004 Jeff Johnson 1.0.20-1 +- update to 1.0.20. +- add --with-included-opencdk --with-included-libtasn1 +- add --with-included-libcfg --with-included-lzo +- add --disable-srp-authentication. +- do "make check" after build. + +* Fri Mar 21 2003 Jeff Johnson 0.9.2-1 +- upgrade to 0.9.2 + +* Tue Jun 25 2002 Jeff Johnson 0.4.4-1 +- update to 0.4.4. + +* Fri Jun 21 2002 Tim Powers +- automated rebuild + +* Sat May 25 2002 Jeff Johnson 0.4.3-1 +- update to 0.4.3. + +* Tue May 21 2002 Jeff Johnson 0.4.2-1 +- update to 0.4.2. +- change license to LGPL. +- include splint annotations patch. + +* Tue Apr 2 2002 Nalin Dahyabhai 0.4.0-1 +- update to 0.4.0 + +* Thu Jan 17 2002 Nalin Dahyabhai 0.3.2-1 +- update to 0.3.2 + +* Thu Jan 10 2002 Nalin Dahyabhai 0.3.0-1 +- add a URL + +* Thu Dec 20 2001 Nalin Dahyabhai +- initial package