diff --git a/SOURCES/gnutls-3.6.14-fips-dh-selftests.patch b/SOURCES/gnutls-3.6.14-fips-dh-selftests.patch new file mode 100644 index 0000000..adcb83c --- /dev/null +++ b/SOURCES/gnutls-3.6.14-fips-dh-selftests.patch @@ -0,0 +1,204 @@ +From f09b7627a63defb1c55e9965fb05e0bbddb90247 Mon Sep 17 00:00:00 2001 +From: Daiki Ueno +Date: Tue, 6 Oct 2020 11:54:21 +0200 +Subject: [PATCH] fips: use larger prime for DH self-tests + +According to FIPS140-2 IG 7.5, the minimum key size of FFC through +2030 is defined as 2048 bits. This updates the relevant self-test +using ffdhe3072 defined in RFC 7919. + +Signed-off-by: Daiki Ueno +--- + lib/crypto-selftests-pk.c | 142 ++++++++++++++++++++++++++++++++++---- + lib/dh-primes.c | 4 -- + 2 files changed, 130 insertions(+), 16 deletions(-) + +diff --git a/lib/crypto-selftests-pk.c b/lib/crypto-selftests-pk.c +index 70b0f618f..9b7c692a8 100644 +--- a/lib/crypto-selftests-pk.c ++++ b/lib/crypto-selftests-pk.c +@@ -620,32 +620,150 @@ static int test_dh(void) + gnutls_pk_params_st priv; + gnutls_pk_params_st pub; + gnutls_datum_t out = {NULL, 0}; ++ ++ /* FFDHE 3072 test vector provided by Stephan Mueller in: ++ * https://gitlab.com/gnutls/gnutls/-/merge_requests/1342#note_424430996 ++ */ + static const uint8_t known_dh_k[] = { +- 0x10, 0x25, 0x04, 0xb5, 0xc6, 0xc2, 0xcb, +- 0x0c, 0xe9, 0xc5, 0x58, 0x0d, 0x22, 0x62}; +- static const uint8_t test_p[] = { +- 0x24, 0x85, 0xdd, 0x3a, 0x74, 0x42, 0xe4, +- 0xb3, 0xf1, 0x0b, 0x13, 0xf9, 0x17, 0x4d }; +- static const uint8_t test_g[] = { 0x02 }; ++ 0xec, 0xb3, 0x85, 0x0c, 0x72, 0x55, 0x55, 0xc2, 0x98, 0x36, ++ 0xbe, 0x75, 0x9e, 0xc9, 0x9d, 0x8b, 0x16, 0xa6, 0xe6, 0x84, ++ 0x33, 0x12, 0x80, 0x1d, 0xac, 0xde, 0x6a, 0xd7, 0x3b, 0x1e, ++ 0x15, 0xca, 0x5d, 0x26, 0xb3, 0x0a, 0x35, 0xf4, 0xbb, 0xad, ++ 0x71, 0xcb, 0x03, 0x1a, 0xcb, 0xfb, 0x83, 0xf0, 0xa8, 0xde, ++ 0xed, 0x5e, 0x3d, 0x98, 0xd2, 0xb0, 0xef, 0xad, 0xdf, 0x32, ++ 0xa0, 0x16, 0x7d, 0x0e, 0x29, 0xd8, 0x85, 0xca, 0x12, 0x97, ++ 0x56, 0xab, 0x6a, 0x26, 0xa4, 0x46, 0x3d, 0x87, 0xd7, 0xe0, ++ 0xb4, 0x3e, 0x28, 0x75, 0xac, 0x59, 0xc5, 0x71, 0x3a, 0x24, ++ 0x15, 0x76, 0x98, 0x72, 0x94, 0x2d, 0xd0, 0x0e, 0xbc, 0x9a, ++ 0x77, 0xd4, 0xe2, 0xb2, 0x76, 0x54, 0x4a, 0x56, 0xbe, 0x0b, ++ 0x43, 0xf8, 0x21, 0x6f, 0x54, 0x32, 0xde, 0xb7, 0xd5, 0xb7, ++ 0x08, 0x00, 0xd2, 0x57, 0x8c, 0x0b, 0x8b, 0x02, 0x3e, 0xdb, ++ 0x72, 0x54, 0x3a, 0xc0, 0x50, 0x66, 0xbc, 0xc9, 0x67, 0xf5, ++ 0x22, 0x28, 0xf2, 0x3c, 0x51, 0x94, 0x61, 0x26, 0x9a, 0xc6, ++ 0x42, 0x0e, 0x8b, 0x42, 0xad, 0x79, 0x40, 0xa9, 0x0b, 0xdc, ++ 0x84, 0xd5, 0x71, 0x83, 0x94, 0xd9, 0x83, 0x2f, 0x08, 0x74, ++ 0xbc, 0x37, 0x6a, 0x3e, 0x1e, 0xbc, 0xcc, 0x09, 0x23, 0x30, ++ 0x79, 0x01, 0x39, 0xf6, 0xe3, 0xa8, 0xc0, 0xfa, 0x7e, 0xdb, ++ 0x0b, 0x71, 0x3e, 0x4f, 0x1f, 0x69, 0x84, 0xa6, 0x58, 0x6c, ++ 0x36, 0x2c, 0xcc, 0xb4, 0x7c, 0x94, 0xec, 0x06, 0x0b, 0x11, ++ 0x53, 0x95, 0xe6, 0x05, 0x43, 0xa4, 0xe4, 0xea, 0x1d, 0x4f, ++ 0xdc, 0xd0, 0x38, 0x0e, 0x32, 0xa1, 0xde, 0xd9, 0x8d, 0xd8, ++ 0x20, 0xac, 0x04, 0x83, 0xf8, 0x1b, 0x55, 0x52, 0x16, 0x20, ++ 0xe3, 0x2e, 0x6d, 0x11, 0x15, 0x29, 0x2f, 0x3a, 0x7c, 0x80, ++ 0x0a, 0x71, 0x3d, 0x31, 0x9c, 0x1b, 0x73, 0x59, 0xe1, 0x0d, ++ 0x27, 0xc5, 0xc0, 0x6a, 0x72, 0x3a, 0x5b, 0xd6, 0xf6, 0x50, ++ 0xe6, 0x69, 0x48, 0x1e, 0xfd, 0xeb, 0x4a, 0x47, 0x73, 0xfb, ++ 0x88, 0x14, 0xea, 0x6d, 0x36, 0xe1, 0x4c, 0x2c, 0xf9, 0x04, ++ 0xc1, 0xb7, 0x29, 0xfc, 0x5d, 0x02, 0x5d, 0x1c, 0x4d, 0x31, ++ 0x4a, 0x51, 0x3f, 0xa4, 0x45, 0x19, 0x29, 0xc4, 0x32, 0xa6, ++ 0x45, 0xdb, 0x94, 0x3a, 0xbd, 0x76, 0x2c, 0xd6, 0x1a, 0xb1, ++ 0xff, 0xe7, 0x62, 0x75, 0x16, 0xe5, 0x0b, 0xa3, 0x3a, 0x93, ++ 0x84, 0xd6, 0xad, 0xc2, 0x24, 0x68, 0x3d, 0xd6, 0x07, 0xe4, ++ 0xbe, 0x5a, 0x49, 0x31, 0x06, 0xad, 0x3f, 0x31, 0x4a, 0x1c, ++ 0xf7, 0x58, 0xdf, 0x34, 0xcb, 0xc8, 0xa9, 0x07, 0x24, 0x42, ++ 0x63, 0xa5, 0x8e, 0xdd, 0x37, 0x78, 0x92, 0x68, 0x3f, 0xd8, ++ 0x2f, 0xea, 0x8c, 0xf1, 0x8e, 0xd4, 0x8b, 0xa7, 0x3f, 0xa0, ++ 0xfa, 0xaf, 0xf0, 0x35, ++ }; + static const uint8_t test_x[] = { +- 0x06, 0x2c, 0x96, 0xae, 0x0e, 0x9e, 0x9b, +- 0xbb, 0x41, 0x51, 0x7a, 0xa7, 0xc5, 0xfe }; ++ 0x16, 0x5c, 0xa6, 0xe0, 0x9b, 0x87, 0xfa, 0x2d, 0xbc, 0x13, ++ 0x20, 0xcd, 0xac, 0x4e, 0xcc, 0x60, 0x1e, 0x48, 0xec, 0xbe, ++ 0x73, 0x0c, 0xa8, 0x6b, 0x6e, 0x2a, 0xee, 0xdd, 0xd8, 0xf3, ++ 0x2d, 0x5f, 0x75, 0xf3, 0x07, 0x94, 0x88, 0x3d, 0xb1, 0x38, ++ 0xcf, 0xae, 0x4a, 0xcc, 0xcb, 0x6a, 0x80, 0xbc, 0xeb, 0x3b, ++ 0xaa, 0x0b, 0x18, 0x74, 0x58, 0x7c, 0x3e, 0x74, 0xef, 0xb6, ++ 0xd3, 0x15, 0xee, 0x73, 0x29, 0x88, 0x7b, 0x65, 0x02, 0x39, ++ 0x33, 0xec, 0x22, 0x06, 0x8c, 0x5b, 0xd6, 0x2f, 0x4c, 0xf7, ++ 0xe0, 0x97, 0x6d, 0x2a, 0x90, 0x36, 0xfe, 0x1a, 0x44, 0x4d, ++ 0x9d, 0x41, 0x4b, 0xcb, 0xec, 0x25, 0xf4, 0xc3, 0xa5, 0x91, ++ 0xd0, 0x90, 0xc9, 0x34, 0x7b, 0xba, 0x27, 0x30, 0x5a, 0xa2, ++ 0x21, 0x58, 0xce, 0x88, 0x25, 0x39, 0xaf, 0xf1, 0x17, 0x02, ++ 0x12, 0xf8, 0x55, 0xdc, 0xd2, 0x08, 0x5b, 0xd3, 0xc7, 0x8e, ++ 0xcf, 0x29, 0x85, 0x85, 0xdb, 0x5c, 0x08, 0xc2, 0xd7, 0xb0, ++ 0x33, 0x0e, 0xe3, 0xb9, 0x2c, 0x1a, 0x1d, 0x4b, 0xe5, 0x76, ++ 0x8f, 0xd3, 0x14, 0xb6, 0x8c, 0xdc, 0x9a, 0xe8, 0x15, 0x60, ++ 0x60, 0x5e, 0xaa, 0xf9, 0xfa, 0xa6, 0xb2, 0x4f, 0xff, 0x46, ++ 0xc1, 0x5e, 0x93, 0x50, 0x90, 0x7e, 0x4c, 0x26, 0xd7, 0xbb, ++ 0x21, 0x05, 0x3d, 0x27, 0xc5, 0x9b, 0x0d, 0x46, 0x69, 0xe4, ++ 0x74, 0x87, 0x74, 0x55, 0xee, 0x5f, 0xe5, 0x72, 0x04, 0x46, ++ 0x1f, 0x2e, 0x55, 0xc7, 0xcc, 0x2b, 0x2b, 0x39, 0x6d, 0x90, ++ 0x60, 0x31, 0x37, 0x5b, 0x44, 0xde, 0xfd, 0xf2, 0xd1, 0xc6, ++ 0x9c, 0x12, 0x82, 0xcc, 0x7c, 0xb1, 0x0e, 0xa9, 0x95, 0x9d, ++ 0xe0, 0xa8, 0x3e, 0xc1, 0xa3, 0x4a, 0x6a, 0x37, 0x59, 0x17, ++ 0x93, 0x63, 0x1e, 0xbf, 0x04, 0xa3, 0xaa, 0xc0, 0x1d, 0xc4, ++ 0x6d, 0x7a, 0xdc, 0x69, 0x9c, 0xb0, 0x22, 0x56, 0xd9, 0x76, ++ 0x92, 0x2d, 0x1e, 0x62, 0xae, 0xfd, 0xd6, 0x9b, 0xfd, 0x08, ++ 0x2c, 0x95, 0xec, 0xe7, 0x02, 0x43, 0x62, 0x68, 0x1a, 0xaf, ++ 0x46, 0x59, 0xb7, 0xce, 0x8e, 0x42, 0x24, 0xae, 0xf7, 0x0e, ++ 0x9a, 0x3b, 0xf8, 0x77, 0xdf, 0x26, 0x85, 0x9f, 0x45, 0xad, ++ 0x8c, 0xa9, 0x54, 0x9c, 0x46, 0x44, 0xd5, 0x8a, 0xe9, 0xcc, ++ 0x34, 0x5e, 0xc5, 0xd1, 0x42, 0x6f, 0x44, 0xf3, 0x0f, 0x90, ++ 0x3a, 0x32, 0x1a, 0x9c, 0x2a, 0x63, 0xec, 0x21, 0xb4, 0xfc, ++ 0xfa, 0xa5, 0xcf, 0xe7, 0x9e, 0x43, 0xc7, 0x49, 0x56, 0xbc, ++ 0x50, 0xc5, 0x84, 0xf0, 0x42, 0xc8, 0x6a, 0xf1, 0x78, 0xe4, ++ 0xaa, 0x06, 0x37, 0xe1, 0x30, 0xf7, 0x65, 0x97, 0xca, 0xfd, ++ 0x35, 0xfa, 0xeb, 0x48, 0x6d, 0xaa, 0x45, 0x46, 0x9d, 0xbc, ++ 0x1d, 0x98, 0x17, 0x45, 0xa3, 0xee, 0x21, 0xa0, 0x97, 0x38, ++ 0x80, 0xc5, 0x28, 0x1f, ++ }; + static const uint8_t test_y[] = { /* y=g^x mod p */ +- 0x1e, 0xca, 0x23, 0x2a, 0xfd, 0x34, 0xe1, +- 0x10, 0x7a, 0xff, 0xaf, 0x2d, 0xaa, 0x53 }; ++ 0x93, 0xeb, 0x5c, 0x37, 0x1d, 0x3c, 0x06, 0x6f, 0xbf, 0xbe, ++ 0x96, 0x51, 0x26, 0x58, 0x81, 0x36, 0xc6, 0x4f, 0x9a, 0x34, ++ 0xc4, 0xc5, 0xa8, 0xa3, 0x2c, 0x41, 0x76, 0xa8, 0xc6, 0xc0, ++ 0xa0, 0xc8, 0x51, 0x36, 0xc4, 0x40, 0x4e, 0x2c, 0x69, 0xf7, ++ 0x51, 0xbb, 0xb0, 0xd6, 0xf5, 0xdb, 0x40, 0x29, 0x50, 0x3b, ++ 0x8a, 0xf9, 0xf3, 0x53, 0x78, 0xfc, 0x86, 0xe9, 0xf1, 0xe9, ++ 0xac, 0x85, 0x13, 0x65, 0x62, 0x22, 0x04, 0x1b, 0x14, 0x2a, ++ 0xf4, 0x8f, 0x2f, 0xf1, 0x2f, 0x81, 0xd6, 0x18, 0x0e, 0x76, ++ 0x91, 0x43, 0xb2, 0xfc, 0x7c, 0x6f, 0x0c, 0x45, 0x37, 0x31, ++ 0x31, 0x58, 0x5c, 0xdf, 0x42, 0x24, 0x7a, 0xba, 0x8b, 0x7f, ++ 0x79, 0x06, 0x07, 0xef, 0xd6, 0x06, 0xeb, 0xcb, 0x3c, 0xbd, ++ 0xbc, 0xe5, 0xff, 0xfd, 0x62, 0x15, 0x0c, 0x40, 0x46, 0x37, ++ 0xef, 0xd0, 0xa1, 0xde, 0x63, 0x4f, 0x20, 0x0b, 0x45, 0x7d, ++ 0x06, 0x77, 0xfd, 0x23, 0xc1, 0x32, 0x8a, 0x89, 0x65, 0x16, ++ 0xe8, 0x48, 0x12, 0x1c, 0x25, 0x33, 0x2d, 0xbd, 0xd8, 0x9f, ++ 0x1c, 0x9d, 0xbc, 0xe3, 0x08, 0x60, 0x87, 0x1a, 0xc6, 0x06, ++ 0x36, 0xd2, 0xac, 0x09, 0x6d, 0x99, 0x02, 0x89, 0xc6, 0x12, ++ 0x93, 0x8c, 0x4b, 0xd0, 0x7e, 0x36, 0x8a, 0xd6, 0xa0, 0x97, ++ 0x4f, 0x97, 0x3f, 0x97, 0x0b, 0xfe, 0x05, 0xfc, 0xc8, 0xef, ++ 0x21, 0x4d, 0x4a, 0x06, 0x6e, 0xb4, 0xa6, 0x4f, 0xe1, 0xdd, ++ 0x44, 0x06, 0xfa, 0xd5, 0x0e, 0x54, 0xf5, 0x54, 0x3e, 0x8c, ++ 0xb9, 0x85, 0x86, 0x00, 0x40, 0x98, 0xe7, 0x01, 0xdd, 0x93, ++ 0x9d, 0x95, 0xea, 0xf0, 0xd3, 0x99, 0x4b, 0xeb, 0xd5, 0x79, ++ 0x47, 0xa4, 0xad, 0x2a, 0xe0, 0x4d, 0x36, 0x3b, 0x46, 0x10, ++ 0x96, 0xbb, 0x48, 0xe9, 0xa1, 0x78, 0x01, 0x35, 0x0a, 0x5c, ++ 0x7b, 0x3f, 0xf5, 0xf7, 0xb1, 0xe3, 0x97, 0x17, 0x4d, 0x76, ++ 0x10, 0x8d, 0x68, 0x4c, 0x94, 0x7d, 0xee, 0x0e, 0x20, 0x8b, ++ 0xce, 0x7d, 0x0a, 0xa3, 0x51, 0xfb, 0xe6, 0xcf, 0xf0, 0x0e, ++ 0x7f, 0x3c, 0xd4, 0xef, 0x56, 0x31, 0xb2, 0x95, 0xf0, 0x5f, ++ 0x4b, 0x9c, 0x03, 0x9e, 0xae, 0xb1, 0xc1, 0x46, 0xd7, 0xc0, ++ 0x4f, 0xb0, 0xf6, 0x6c, 0xe1, 0xe9, 0x2a, 0x97, 0xe0, 0x3f, ++ 0x3a, 0x93, 0x04, 0xcd, 0x41, 0x7d, 0x45, 0x03, 0xb3, 0x40, ++ 0x20, 0xe6, 0xad, 0x2d, 0xd3, 0xf7, 0x32, 0x7b, 0xcc, 0x4f, ++ 0x81, 0x18, 0x4c, 0x50, 0x77, 0xc4, 0xb7, 0x6a, 0x4d, 0x05, ++ 0xd8, 0x6d, 0xbf, 0x6f, 0xba, 0x1d, 0x38, 0x78, 0x87, 0xd2, ++ 0x8e, 0xc2, 0x6d, 0xb6, 0xed, 0x66, 0x61, 0xa8, 0xb9, 0x19, ++ 0x0e, 0x93, 0xd1, 0xcd, 0x5b, 0xbe, 0x19, 0x05, 0x52, 0x43, ++ 0xd6, 0xc1, 0x07, 0x3c, 0x6a, 0x62, 0xbd, 0x33, 0x9b, 0x1b, ++ 0x02, 0x42, 0x61, 0x14, ++ }; + + gnutls_pk_params_init(&priv); + gnutls_pk_params_init(&pub); + + priv.algo = pub.algo = GNUTLS_PK_DH; + +- ret = _gnutls_mpi_init_scan(&priv.params[DH_P], test_p, sizeof(test_p)); ++ ret = _gnutls_mpi_init_scan(&priv.params[DH_P], ++ gnutls_ffdhe_3072_group_prime.data, ++ gnutls_ffdhe_3072_group_prime.size); + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } + +- ret = _gnutls_mpi_init_scan(&priv.params[DH_G], test_g, sizeof(test_g)); ++ ret = _gnutls_mpi_init_scan(&priv.params[DH_G], ++ gnutls_ffdhe_3072_group_generator.data, ++ gnutls_ffdhe_3072_group_generator.size); + if (ret < 0) { + gnutls_assert(); + goto cleanup; +diff --git a/lib/dh-primes.c b/lib/dh-primes.c +index a440b5b98..94b69e345 100644 +--- a/lib/dh-primes.c ++++ b/lib/dh-primes.c +@@ -23,8 +23,6 @@ + #include "gnutls_int.h" + #include + +-#if defined(ENABLE_DHE) || defined(ENABLE_ANON) +- + #include "dh.h" + + static const unsigned char ffdhe_generator = 0x02; +@@ -1934,5 +1932,3 @@ _gnutls_dh_prime_match_fips_approved(const uint8_t *prime, + + return 0; + } +- +-#endif +-- +2.26.2 + diff --git a/SOURCES/gnutls-3.6.14-fips-kdf-selftests.patch b/SOURCES/gnutls-3.6.14-fips-kdf-selftests.patch new file mode 100644 index 0000000..e6fdbb2 --- /dev/null +++ b/SOURCES/gnutls-3.6.14-fips-kdf-selftests.patch @@ -0,0 +1,713 @@ +From 93c0e3ba4d2cfee86b32f28f33303a2193c4133c Mon Sep 17 00:00:00 2001 +From: Daiki Ueno +Date: Mon, 5 Oct 2020 16:12:46 +0200 +Subject: [PATCH 1/4] fips: add self-tests for HKDF + +FIPS140-2 IG D.8 mandates self-test on approved KDF algorithms. As +the guidance only requires running a single instance of each KDF +mechanism, this only exercises HKDF-Extract and HKDF-Expand operations +with HMAC-SHA-256 as the underlying MAC. + +Although HKDF is non-approved, it would be sensible to do that as it +will be approved in FIPS140-3. + +Signed-off-by: Daiki Ueno +--- + devel/libgnutls-latest-x86_64.abi | 1 + + lib/crypto-selftests.c | 159 ++++++++++++++++++++++++++++++ + lib/fips.c | 7 ++ + lib/includes/gnutls/self-test.h | 1 + + lib/libgnutls.map | 1 + + 5 files changed, 169 insertions(+) + +diff --git a/lib/crypto-selftests.c b/lib/crypto-selftests.c +index 7a1c7729c..bd148b6af 100644 +--- a/lib/crypto-selftests.c ++++ b/lib/crypto-selftests.c +@@ -2917,3 +2917,162 @@ int gnutls_digest_self_test(unsigned flags, gnutls_digest_algorithm_t digest) + + return 0; + } ++ ++struct hkdf_vectors_st { ++ const uint8_t *ikm; ++ unsigned int ikm_size; ++ const uint8_t *salt; ++ unsigned int salt_size; ++ const uint8_t *prk; ++ unsigned int prk_size; ++ const uint8_t *info; ++ unsigned int info_size; ++ const uint8_t *okm; ++ unsigned int okm_size; ++}; ++ ++const struct hkdf_vectors_st hkdf_sha256_vectors[] = { ++ /* RFC 5869: A.1. Test Case 1: Basic test case with SHA-256 */ ++ { ++ STR(ikm, ikm_size, ++ "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" ++ "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"), ++ STR(salt, salt_size, ++ "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c"), ++ STR(prk, prk_size, ++ "\x07\x77\x09\x36\x2c\x2e\x32\xdf\x0d\xdc\x3f\x0d\xc4\x7b" ++ "\xba\x63\x90\xb6\xc7\x3b\xb5\x0f\x9c\x31\x22\xec\x84\x4a" ++ "\xd7\xc2\xb3\xe5"), ++ STR(info, info_size, ++ "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9"), ++ STR(okm, okm_size, ++ "\x3c\xb2\x5f\x25\xfa\xac\xd5\x7a\x90\x43\x4f\x64\xd0\x36" ++ "\x2f\x2a\x2d\x2d\x0a\x90\xcf\x1a\x5a\x4c\x5d\xb0\x2d\x56" ++ "\xec\xc4\xc5\xbf\x34\x00\x72\x08\xd5\xb8\x87\x18\x58\x65"), ++ }, ++ /* RFC 5869: A.2. Test Case 2: Test with SHA-256 and longer inputs/outputs */ ++ { ++ STR(ikm, ikm_size, ++ "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d" ++ "\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b" ++ "\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29" ++ "\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37" ++ "\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40\x41\x42\x43\x44\x45" ++ "\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f"), ++ STR(salt, salt_size, ++ "\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d" ++ "\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b" ++ "\x7c\x7d\x7e\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89" ++ "\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97" ++ "\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5" ++ "\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf"), ++ STR(prk, prk_size, ++ "\x06\xa6\xb8\x8c\x58\x53\x36\x1a\x06\x10\x4c\x9c\xeb\x35" ++ "\xb4\x5c\xef\x76\x00\x14\x90\x46\x71\x01\x4a\x19\x3f\x40" ++ "\xc1\x5f\xc2\x44"), ++ STR(info, info_size, ++ "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd" ++ "\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb" ++ "\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9" ++ "\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7" ++ "\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5" ++ "\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"), ++ STR(okm, okm_size, ++ "\xb1\x1e\x39\x8d\xc8\x03\x27\xa1\xc8\xe7\xf7\x8c\x59\x6a" ++ "\x49\x34\x4f\x01\x2e\xda\x2d\x4e\xfa\xd8\xa0\x50\xcc\x4c" ++ "\x19\xaf\xa9\x7c\x59\x04\x5a\x99\xca\xc7\x82\x72\x71\xcb" ++ "\x41\xc6\x5e\x59\x0e\x09\xda\x32\x75\x60\x0c\x2f\x09\xb8" ++ "\x36\x77\x93\xa9\xac\xa3\xdb\x71\xcc\x30\xc5\x81\x79\xec" ++ "\x3e\x87\xc1\x4c\x01\xd5\xc1\xf3\x43\x4f\x1d\x87"), ++ }, ++}; ++ ++static int test_hkdf(gnutls_mac_algorithm_t mac, ++ const struct hkdf_vectors_st *vectors, ++ size_t vectors_size, unsigned flags) ++{ ++ unsigned int i; ++ ++ for (i = 0; i < vectors_size; i++) { ++ gnutls_datum_t ikm, prk, salt, info; ++ uint8_t output[4096]; ++ int ret; ++ ++ ikm.data = (void *) vectors[i].ikm; ++ ikm.size = vectors[i].ikm_size; ++ salt.data = (void *) vectors[i].salt; ++ salt.size = vectors[i].salt_size; ++ ++ ret = gnutls_hkdf_extract(mac, &ikm, &salt, output); ++ if (ret < 0) { ++ _gnutls_debug_log("error extracting HKDF: MAC-%s\n", ++ gnutls_mac_get_name(mac)); ++ return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR); ++ } ++ ++ if (memcmp(output, vectors[i].prk, vectors[i].prk_size) != 0) { ++ _gnutls_debug_log ++ ("HKDF extract: MAC-%s test vector failed!\n", ++ gnutls_mac_get_name(mac)); ++ ++ return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR); ++ } ++ ++ prk.data = (void *) vectors[i].prk; ++ prk.size = vectors[i].prk_size; ++ info.data = (void *) vectors[i].info; ++ info.size = vectors[i].info_size; ++ ++ ret = gnutls_hkdf_expand(mac, &prk, &info, ++ output, vectors[i].okm_size); ++ if (ret < 0) { ++ _gnutls_debug_log("error extracting HKDF: MAC-%s\n", ++ gnutls_mac_get_name(mac)); ++ return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR); ++ } ++ ++ if (memcmp(output, vectors[i].okm, vectors[i].okm_size) != 0) { ++ _gnutls_debug_log ++ ("HKDF expand: MAC-%s test vector failed!\n", ++ gnutls_mac_get_name(mac)); ++ ++ return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR); ++ } ++ } ++ ++ _gnutls_debug_log ++ ("HKDF: MAC-%s self check succeeded\n", ++ gnutls_mac_get_name(mac)); ++ ++ return 0; ++} ++ ++/*- ++ * gnutls_hkdf_self_test: ++ * @flags: GNUTLS_SELF_TEST_FLAG flags ++ * @mac: the message authentication algorithm to use ++ * ++ * This function will run self tests on HKDF with the provided mac. ++ * ++ * Returns: Zero or a negative error code on error. ++ * ++ * Since: 3.3.0-FIPS140 ++ -*/ ++int gnutls_hkdf_self_test(unsigned flags, gnutls_mac_algorithm_t mac) ++{ ++ int ret; ++ ++ if (flags & GNUTLS_SELF_TEST_FLAG_ALL) ++ mac = GNUTLS_MAC_UNKNOWN; ++ ++ switch (mac) { ++ case GNUTLS_MAC_UNKNOWN: ++ CASE(GNUTLS_MAC_SHA256, test_hkdf, hkdf_sha256_vectors); ++ ++ break; ++ default: ++ return gnutls_assert_val(GNUTLS_E_NO_SELF_TEST); ++ } ++ ++ return 0; ++} +diff --git a/lib/fips.c b/lib/fips.c +index f8b10f750..48891ed57 100644 +--- a/lib/fips.c ++++ b/lib/fips.c +@@ -423,6 +423,13 @@ int _gnutls_fips_perform_self_checks2(void) + goto error; + } + ++ /* HKDF */ ++ ret = gnutls_hkdf_self_test(0, GNUTLS_MAC_SHA256); ++ if (ret < 0) { ++ gnutls_assert(); ++ goto error; ++ } ++ + if (_gnutls_rnd_ops.self_test == NULL) { + gnutls_assert(); + goto error; +diff --git a/lib/includes/gnutls/self-test.h b/lib/includes/gnutls/self-test.h +index aacbe94ca..9b7be8159 100644 +--- a/lib/includes/gnutls/self-test.h ++++ b/lib/includes/gnutls/self-test.h +@@ -34,5 +34,6 @@ int gnutls_cipher_self_test(unsigned flags, gnutls_cipher_algorithm_t cipher); + int gnutls_mac_self_test(unsigned flags, gnutls_mac_algorithm_t mac); + int gnutls_digest_self_test(unsigned flags, gnutls_digest_algorithm_t digest); + int gnutls_pk_self_test(unsigned flags, gnutls_pk_algorithm_t pk); ++int gnutls_hkdf_self_test(unsigned flags, gnutls_mac_algorithm_t mac); + + #endif +diff --git a/lib/libgnutls.map b/lib/libgnutls.map +index 61276e534..386b66f83 100644 +--- a/lib/libgnutls.map ++++ b/lib/libgnutls.map +@@ -1347,6 +1347,7 @@ GNUTLS_FIPS140_3_4 { + gnutls_pk_self_test; + gnutls_mac_self_test; + gnutls_digest_self_test; ++ gnutls_hkdf_self_test; + #for FIPS140-2 validation + drbg_aes_reseed; + drbg_aes_init; +-- +2.26.2 + + +From 31cc94275cd267f4e0db60999cc932fd76d43d5a Mon Sep 17 00:00:00 2001 +From: Daiki Ueno +Date: Mon, 5 Oct 2020 16:59:50 +0200 +Subject: [PATCH 2/4] fips: add self-tests for PBKDF2 + +FIPS140-2 IG D.8 mandates self-tests on approved KDF algorithms. As +the guidance only requires running a single instance of each KDF +mechanism, this only exercises PBKDF2 with HMAC-SHA-256 as the +underlying MAC algorithm. + +Signed-off-by: Daiki Ueno +--- + devel/libgnutls-latest-x86_64.abi | 1 + + lib/crypto-selftests.c | 107 ++++++++++++++++++++++++++++++ + lib/fips.c | 7 ++ + lib/includes/gnutls/self-test.h | 1 + + lib/libgnutls.map | 1 + + 5 files changed, 117 insertions(+) + +diff --git a/lib/crypto-selftests.c b/lib/crypto-selftests.c +index bd148b6af..c4b0bd207 100644 +--- a/lib/crypto-selftests.c ++++ b/lib/crypto-selftests.c +@@ -3076,3 +3076,110 @@ int gnutls_hkdf_self_test(unsigned flags, gnutls_mac_algorithm_t mac) + + return 0; + } ++ ++struct pbkdf2_vectors_st { ++ const uint8_t *key; ++ size_t key_size; ++ const uint8_t *salt; ++ size_t salt_size; ++ unsigned iter_count; ++ const uint8_t *output; ++ size_t output_size; ++}; ++ ++const struct pbkdf2_vectors_st pbkdf2_sha256_vectors[] = { ++ /* RFC 7914: 11. Test Vectors for PBKDF2 with HMAC-SHA-256 */ ++ { ++ STR(key, key_size, "passwd"), ++ STR(salt, salt_size, "salt"), ++ .iter_count = 1, ++ STR(output, output_size, ++ "\x55\xac\x04\x6e\x56\xe3\x08\x9f\xec\x16\x91\xc2\x25\x44" ++ "\xb6\x05\xf9\x41\x85\x21\x6d\xde\x04\x65\xe6\x8b\x9d\x57" ++ "\xc2\x0d\xac\xbc\x49\xca\x9c\xcc\xf1\x79\xb6\x45\x99\x16" ++ "\x64\xb3\x9d\x77\xef\x31\x7c\x71\xb8\x45\xb1\xe3\x0b\xd5" ++ "\x09\x11\x20\x41\xd3\xa1\x97\x83"), ++ }, ++ /* RFC 7914: 11. Test Vectors for PBKDF2 with HMAC-SHA-256 */ ++ { ++ STR(key, key_size, "Password"), ++ STR(salt, salt_size, "NaCl"), ++ .iter_count = 80000, ++ STR(output, output_size, ++ "\x4d\xdc\xd8\xf6\x0b\x98\xbe\x21\x83\x0c\xee\x5e\xf2\x27" ++ "\x01\xf9\x64\x1a\x44\x18\xd0\x4c\x04\x14\xae\xff\x08\x87" ++ "\x6b\x34\xab\x56\xa1\xd4\x25\xa1\x22\x58\x33\x54\x9a\xdb" ++ "\x84\x1b\x51\xc9\xb3\x17\x6a\x27\x2b\xde\xbb\xa1\xd0\x78" ++ "\x47\x8f\x62\xb3\x97\xf3\x3c\x8d"), ++ }, ++}; ++ ++static int test_pbkdf2(gnutls_mac_algorithm_t mac, ++ const struct pbkdf2_vectors_st *vectors, ++ size_t vectors_size, unsigned flags) ++{ ++ unsigned int i; ++ ++ for (i = 0; i < vectors_size; i++) { ++ gnutls_datum_t key, salt; ++ uint8_t output[4096]; ++ int ret; ++ ++ key.data = (void *) vectors[i].key; ++ key.size = vectors[i].key_size; ++ salt.data = (void *) vectors[i].salt; ++ salt.size = vectors[i].salt_size; ++ ++ ret = gnutls_pbkdf2(mac, &key, &salt, vectors[i].iter_count, ++ output, vectors[i].output_size); ++ if (ret < 0) { ++ _gnutls_debug_log("error calculating PBKDF2: MAC-%s\n", ++ gnutls_mac_get_name(mac)); ++ return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR); ++ } ++ ++ if (memcmp(output, vectors[i].output, vectors[i].output_size) != 0) { ++ _gnutls_debug_log ++ ("PBKDF2: MAC-%s test vector failed!\n", ++ gnutls_mac_get_name(mac)); ++ ++ return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR); ++ } ++ } ++ ++ _gnutls_debug_log ++ ("PBKDF2: MAC-%s self check succeeded\n", ++ gnutls_mac_get_name(mac)); ++ ++ return 0; ++} ++ ++/*- ++ * gnutls_pbkdf2_self_test: ++ * @flags: GNUTLS_SELF_TEST_FLAG flags ++ * @mac: the message authentication algorithm to use ++ * ++ * This function will run self tests on PBKDF2 with the provided mac. ++ * ++ * Returns: Zero or a negative error code on error. ++ * ++ * Since: 3.3.0-FIPS140 ++ -*/ ++int gnutls_pbkdf2_self_test(unsigned flags, gnutls_mac_algorithm_t mac) ++{ ++ int ret; ++ ++ if (flags & GNUTLS_SELF_TEST_FLAG_ALL) ++ mac = GNUTLS_MAC_UNKNOWN; ++ ++ switch (mac) { ++ case GNUTLS_MAC_UNKNOWN: ++ CASE(GNUTLS_MAC_SHA256, test_pbkdf2, pbkdf2_sha256_vectors); ++ ++ break; ++ default: ++ return gnutls_assert_val(GNUTLS_E_NO_SELF_TEST); ++ } ++ ++ return 0; ++} +diff --git a/lib/fips.c b/lib/fips.c +index 48891ed57..7cfab1049 100644 +--- a/lib/fips.c ++++ b/lib/fips.c +@@ -430,6 +430,13 @@ int _gnutls_fips_perform_self_checks2(void) + goto error; + } + ++ /* PBKDF2 */ ++ ret = gnutls_pbkdf2_self_test(0, GNUTLS_MAC_SHA256); ++ if (ret < 0) { ++ gnutls_assert(); ++ goto error; ++ } ++ + if (_gnutls_rnd_ops.self_test == NULL) { + gnutls_assert(); + goto error; +diff --git a/lib/includes/gnutls/self-test.h b/lib/includes/gnutls/self-test.h +index 9b7be8159..958c0da8f 100644 +--- a/lib/includes/gnutls/self-test.h ++++ b/lib/includes/gnutls/self-test.h +@@ -35,5 +35,6 @@ int gnutls_mac_self_test(unsigned flags, gnutls_mac_algorithm_t mac); + int gnutls_digest_self_test(unsigned flags, gnutls_digest_algorithm_t digest); + int gnutls_pk_self_test(unsigned flags, gnutls_pk_algorithm_t pk); + int gnutls_hkdf_self_test(unsigned flags, gnutls_mac_algorithm_t mac); ++int gnutls_pbkdf2_self_test(unsigned flags, gnutls_mac_algorithm_t mac); + + #endif +diff --git a/lib/libgnutls.map b/lib/libgnutls.map +index 386b66f83..f5537a386 100644 +--- a/lib/libgnutls.map ++++ b/lib/libgnutls.map +@@ -1348,6 +1348,7 @@ GNUTLS_FIPS140_3_4 { + gnutls_mac_self_test; + gnutls_digest_self_test; + gnutls_hkdf_self_test; ++ gnutls_pbkdf2_self_test; + #for FIPS140-2 validation + drbg_aes_reseed; + drbg_aes_init; +-- +2.26.2 + + +From d1a3235e8c829855969d00364d8b5456fce2c78c Mon Sep 17 00:00:00 2001 +From: Daiki Ueno +Date: Mon, 5 Oct 2020 17:44:30 +0200 +Subject: [PATCH 3/4] fips: add self-tests for TLS-PRF + +FIPS140-2 IG D.8 mandates self-tests on approved KDF algorithms. As +the guidance only requires to run a single instance of each KDF +mechanism, this only exercises TLS1.2 PRF with HMAC-SHA-256 as the +underlying MAC algorithm. + +Signed-off-by: Daiki Ueno +--- + devel/libgnutls-latest-x86_64.abi | 1 + + lib/crypto-selftests.c | 196 ++++++++++++++++++++++++++++++ + lib/fips.c | 7 ++ + lib/includes/gnutls/self-test.h | 1 + + lib/libgnutls.map | 1 + + 5 files changed, 206 insertions(+) + +diff --git a/lib/crypto-selftests.c b/lib/crypto-selftests.c +index c4b0bd207..b740936d6 100644 +--- a/lib/crypto-selftests.c ++++ b/lib/crypto-selftests.c +@@ -3183,3 +3183,199 @@ int gnutls_pbkdf2_self_test(unsigned flags, gnutls_mac_algorithm_t mac) + + return 0; + } ++ ++struct tlsprf_vectors_st { ++ const uint8_t *key; ++ size_t key_size; ++ const uint8_t *label; ++ size_t label_size; ++ const uint8_t *seed; ++ size_t seed_size; ++ const uint8_t *output; ++ size_t output_size; ++}; ++ ++const struct tlsprf_vectors_st tls10prf_vectors[] = { ++ /* tests/tls10-prf.c: test1 */ ++ { ++ STR(key, key_size, ++ "\x26\x3b\xdb\xbb\x6f\x6d\x4c\x66\x4e\x05\x8d\x0a\xa9\xd3" ++ "\x21\xbe"), ++ STR(label, label_size, ++ "test label"), ++ STR(seed, seed_size, ++ "\xb9\x20\x57\x3b\x19\x96\x01\x02\x4f\x04\xd6\xdc\x61\x96" ++ "\x6e\x65"), ++ STR(output, output_size, ++ "\x66\x17\x99\x37\x65\xfa\x6c\xa7\x03\xd1\x9e\xc7\x0d\xd5" ++ "\xdd\x16\x0f\xfc\xc0\x77\x25\xfa\xfb\x71\x4a\x9f\x81\x5a" ++ "\x2a\x30\xbf\xb7\xe3\xbb\xfb\x7e\xee\x57\x4b\x3b\x61\x3e" ++ "\xb7\xfe\x80\xee\xc9\x69\x1d\x8c\x1b\x0e\x2d\x9b\x3c\x8b" ++ "\x4b\x02\xb6\xb6\xd6\xdb\x88\xe2\x09\x46\x23\xef\x62\x40" ++ "\x60\x7e\xda\x7a\xbe\x3c\x84\x6e\x82\xa3"), ++ }, ++}; ++ ++const struct tlsprf_vectors_st tls12prf_sha256_vectors[] = { ++ /* tests/tls12-prf.c: sha256_test1 */ ++ { ++ STR(key, key_size, ++ "\x04\x50\xb0\xea\x9e\xcd\x36\x02\xee\x0d\x76\xc5\xc3\xc8" ++ "\x6f\x4a"), ++ STR(label, label_size, ++ "test label"), ++ STR(seed, seed_size, ++ "\x20\x7a\xcc\x02\x54\xb8\x67\xf5\xb9\x25\xb4\x5a\x33\x60" ++ "\x1d\x8b"), ++ STR(output, output_size, ++ "\xae\x67\x9e\x0e\x71\x4f\x59\x75\x76\x37\x68\xb1\x66\x97" ++ "\x9e\x1d"), ++ }, ++ /* tests/tls12-prf.c: sha256_test2 */ ++ { ++ STR(key, key_size, ++ "\x34\x20\x4a\x9d\xf0\xbe\x6e\xb4\xe9\x25\xa8\x02\x7c\xf6" ++ "\xc6\x02"), ++ STR(label, label_size, ++ "test label"), ++ STR(seed, seed_size, ++ "\x98\xb2\xc4\x0b\xcd\x66\x4c\x83\xbb\x92\x0c\x18\x20\x1a" ++ "\x63\x95"), ++ STR(output, output_size, ++ "\xaf\xa9\x31\x24\x53\xc2\x2f\xa8\x3d\x2b\x51\x1b\x37\x2d" ++ "\x73\xa4\x02\xa2\xa6\x28\x73\x23\x9a\x51\xfa\xde\x45\x08" ++ "\x2f\xaf\x3f\xd2\xbb\x7f\xfb\x3e\x9b\xf3\x6e\x28\xb3\x14" ++ "\x1a\xab\xa4\x84\x00\x53\x32\xa9\xf9\xe3\x88\xa4\xd3\x29" ++ "\xf1\x58\x7a\x4b\x31\x7d\xa0\x77\x08\xea\x1b\xa9\x5a\x53" ++ "\xf8\x78\x67\x24\xbd\x83\xce\x4b\x03\xaf"), ++ }, ++ /* tests/tls12-prf.c: sha256_test3 */ ++ { ++ STR(key, key_size, ++ "\xa3\x69\x1a\xa1\xf6\x81\x4b\x80\x59\x2b\xf1\xcf\x2a\xcf" ++ "\x16\x97"), ++ STR(label, label_size, ++ "test label"), ++ STR(seed, seed_size, ++ "\x55\x23\xd4\x1e\x32\x0e\x69\x4d\x0c\x1f\xf5\x73\x4d\x83" ++ "\x0b\x93\x3e\x46\x92\x70\x71\xc9\x26\x21"), ++ STR(output, output_size, ++ "\x6a\xd0\x98\x4f\xa0\x6f\x78\xfe\x16\x1b\xd4\x6d\x7c\x26" ++ "\x1d\xe4\x33\x40\xd7\x28\xdd\xdc\x3d\x0f\xf0\xdd\x7e\x0d"), ++ }, ++ /* tests/tls12-prf.c: sha256_test4 */ ++ { ++ STR(key, key_size, ++ "\x21\x0e\xc9\x37\x06\x97\x07\xe5\x46\x5b\xc4\x6b\xf7\x79" ++ "\xe1\x04\x10\x8b\x18\xfd\xb7\x93\xbe\x7b\x21\x8d\xbf\x14" ++ "\x5c\x86\x41\xf3"), ++ STR(label, label_size, ++ "test label"), ++ STR(seed, seed_size, ++ "\x1e\x35\x1a\x0b\xaf\x35\xc7\x99\x45\x92\x43\x94\xb8\x81" ++ "\xcf\xe3\x1d\xae\x8f\x1c\x1e\xd5\x4d\x3b"), ++ STR(output, output_size, ++ "\x76\x53\xfa\x80\x9c\xde\x3b\x55\x3c\x4a\x17\xe2\xcd\xbc" ++ "\xc9\x18\xf3\x65\x27\xf2\x22\x19\xa7\xd7\xf9\x5d\x97\x24" ++ "\x3f\xf2\xd5\xde\xe8\x26\x5e\xf0\xaf\x03"), ++ }, ++}; ++ ++const struct tlsprf_vectors_st tls12prf_sha384_vectors[] = { ++ /* tests/tls12-prf.c: sha384_test1 ++ * https://www.ietf.org/mail-archive/web/tls/current/msg03416.html ++ */ ++ { ++ STR(key, key_size, ++ "\xb8\x0b\x73\x3d\x6c\xee\xfc\xdc\x71\x56\x6e\xa4\x8e\x55" ++ "\x67\xdf"), ++ STR(label, label_size, ++ "test label"), ++ STR(seed, seed_size, ++ "\xcd\x66\x5c\xf6\xa8\x44\x7d\xd6\xff\x8b\x27\x55\x5e\xdb" ++ "\x74\x65"), ++ STR(output, output_size, ++ "\x7b\x0c\x18\xe9\xce\xd4\x10\xed\x18\x04\xf2\xcf\xa3\x4a" ++ "\x33\x6a\x1c\x14\xdf\xfb\x49\x00\xbb\x5f\xd7\x94\x21\x07" ++ "\xe8\x1c\x83\xcd\xe9\xca\x0f\xaa\x60\xbe\x9f\xe3\x4f\x82" ++ "\xb1\x23\x3c\x91\x46\xa0\xe5\x34\xcb\x40\x0f\xed\x27\x00" ++ "\x88\x4f\x9d\xc2\x36\xf8\x0e\xdd\x8b\xfa\x96\x11\x44\xc9" ++ "\xe8\xd7\x92\xec\xa7\x22\xa7\xb3\x2f\xc3\xd4\x16\xd4\x73" ++ "\xeb\xc2\xc5\xfd\x4a\xbf\xda\xd0\x5d\x91\x84\x25\x9b\x5b" ++ "\xf8\xcd\x4d\x90\xfa\x0d\x31\xe2\xde\xc4\x79\xe4\xf1\xa2" ++ "\x60\x66\xf2\xee\xa9\xa6\x92\x36\xa3\xe5\x26\x55\xc9\xe9" ++ "\xae\xe6\x91\xc8\xf3\xa2\x68\x54\x30\x8d\x5e\xaa\x3b\xe8" ++ "\x5e\x09\x90\x70\x3d\x73\xe5\x6f"), ++ }, ++}; ++ ++static int test_tlsprf(gnutls_mac_algorithm_t mac, ++ const struct tlsprf_vectors_st *vectors, ++ size_t vectors_size, unsigned flags) ++{ ++ unsigned int i; ++ ++ for (i = 0; i < vectors_size; i++) { ++ char output[4096]; ++ int ret; ++ ++ ret = _gnutls_prf_raw(mac, ++ vectors[i].key_size, vectors[i].key, ++ vectors[i].label_size, (const char *)vectors[i].label, ++ vectors[i].seed_size, vectors[i].seed, ++ vectors[i].output_size, output); ++ if (ret < 0) { ++ _gnutls_debug_log("error calculating TLS-PRF: MAC-%s\n", ++ gnutls_mac_get_name(mac)); ++ return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR); ++ } ++ ++ if (memcmp(output, vectors[i].output, vectors[i].output_size) != 0) { ++ _gnutls_debug_log ++ ("TLS-PRF: MAC-%s test vector failed!\n", ++ gnutls_mac_get_name(mac)); ++ ++ return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR); ++ } ++ } ++ ++ _gnutls_debug_log ++ ("TLS-PRF: MAC-%s self check succeeded\n", ++ gnutls_mac_get_name(mac)); ++ ++ return 0; ++} ++ ++/*- ++ * gnutls_tlsprf_self_test: ++ * @flags: GNUTLS_SELF_TEST_FLAG flags ++ * @mac: the message authentication algorithm to use ++ * ++ * This function will run self tests on TLS-PRF with the provided mac. ++ * ++ * Returns: Zero or a negative error code on error. ++ * ++ * Since: 3.3.0-FIPS140 ++ -*/ ++int gnutls_tlsprf_self_test(unsigned flags, gnutls_mac_algorithm_t mac) ++{ ++ int ret; ++ ++ if (flags & GNUTLS_SELF_TEST_FLAG_ALL) ++ mac = GNUTLS_MAC_UNKNOWN; ++ ++ switch (mac) { ++ case GNUTLS_MAC_UNKNOWN: ++ NON_FIPS_CASE(GNUTLS_MAC_MD5_SHA1, test_tlsprf, tls10prf_vectors); ++ FALLTHROUGH; ++ CASE(GNUTLS_MAC_SHA256, test_tlsprf, tls12prf_sha256_vectors); ++ FALLTHROUGH; ++ CASE(GNUTLS_MAC_SHA384, test_tlsprf, tls12prf_sha384_vectors); ++ ++ break; ++ default: ++ return gnutls_assert_val(GNUTLS_E_NO_SELF_TEST); ++ } ++ ++ return 0; ++} +diff --git a/lib/fips.c b/lib/fips.c +index 7cfab1049..30d396b2c 100644 +--- a/lib/fips.c ++++ b/lib/fips.c +@@ -437,6 +437,13 @@ int _gnutls_fips_perform_self_checks2(void) + goto error; + } + ++ /* TLS-PRF */ ++ ret = gnutls_tlsprf_self_test(0, GNUTLS_MAC_SHA256); ++ if (ret < 0) { ++ gnutls_assert(); ++ goto error; ++ } ++ + if (_gnutls_rnd_ops.self_test == NULL) { + gnutls_assert(); + goto error; +diff --git a/lib/includes/gnutls/self-test.h b/lib/includes/gnutls/self-test.h +index 958c0da8f..88b5a8dbf 100644 +--- a/lib/includes/gnutls/self-test.h ++++ b/lib/includes/gnutls/self-test.h +@@ -36,5 +36,6 @@ int gnutls_digest_self_test(unsigned flags, gnutls_digest_algorithm_t digest); + int gnutls_pk_self_test(unsigned flags, gnutls_pk_algorithm_t pk); + int gnutls_hkdf_self_test(unsigned flags, gnutls_mac_algorithm_t mac); + int gnutls_pbkdf2_self_test(unsigned flags, gnutls_mac_algorithm_t mac); ++int gnutls_tlsprf_self_test(unsigned flags, gnutls_mac_algorithm_t mac); + + #endif +diff --git a/lib/libgnutls.map b/lib/libgnutls.map +index f5537a386..643d400a1 100644 +--- a/lib/libgnutls.map ++++ b/lib/libgnutls.map +@@ -1349,6 +1349,7 @@ GNUTLS_FIPS140_3_4 { + gnutls_digest_self_test; + gnutls_hkdf_self_test; + gnutls_pbkdf2_self_test; ++ gnutls_tlsprf_self_test; + #for FIPS140-2 validation + drbg_aes_reseed; + drbg_aes_init; +-- +2.26.2 + + +From af3df0102fc377591a6de3112b034d4a492fc92c Mon Sep 17 00:00:00 2001 +From: Daiki Ueno +Date: Mon, 5 Oct 2020 17:59:46 +0200 +Subject: [PATCH 4/4] fips: run CMAC self-tests + +FIPS140-2 IG D.8 mandates self-tests on CMAC. + +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 30d396b2c..51567953d 100644 +--- a/lib/fips.c ++++ b/lib/fips.c +@@ -398,6 +398,12 @@ int _gnutls_fips_perform_self_checks2(void) + goto error; + } + ++ ret = gnutls_mac_self_test(0, GNUTLS_MAC_AES_CMAC_256); ++ if (ret < 0) { ++ gnutls_assert(); ++ goto error; ++ } ++ + /* PK */ + ret = gnutls_pk_self_test(0, GNUTLS_PK_RSA); + if (ret < 0) { +-- +2.26.2 + diff --git a/SOURCES/gnutls-3.6.14-no-renegotiation.patch b/SOURCES/gnutls-3.6.14-no-renegotiation.patch new file mode 100644 index 0000000..cb935bc --- /dev/null +++ b/SOURCES/gnutls-3.6.14-no-renegotiation.patch @@ -0,0 +1,118 @@ +From 29ee67c205855e848a0a26e6d0e4f65b6b943e0a Mon Sep 17 00:00:00 2001 +From: Daiki Ueno +Date: Sat, 22 Aug 2020 17:19:39 +0200 +Subject: [PATCH] handshake: reject no_renegotiation alert if handshake is + incomplete + +If the initial handshake is incomplete and the server sends a +no_renegotiation alert, the client should treat it as a fatal error +even if its level is warning. Otherwise the same handshake +state (e.g., DHE parameters) are reused in the next gnutls_handshake +call, if it is called in the loop idiom: + + do { + ret = gnutls_handshake(session); + } while (ret < 0 && gnutls_error_is_fatal(ret) == 0); + +Signed-off-by: Daiki Ueno +--- + ...a04b3d3f7dcc0ab4571cf0df3b67ab7e1005e9e7a8 | Bin 0 -> 671 bytes + ...1da801fb3c6d1f7f846f227721e221adea08aa319c | Bin 0 -> 729 bytes + lib/gnutls_int.h | 1 + + lib/handshake.c | 48 +++++++++++++----- + 4 files changed, 36 insertions(+), 13 deletions(-) + create mode 100644 fuzz/gnutls_client_fuzzer.in/00ea40761ce11e769f1817a04b3d3f7dcc0ab4571cf0df3b67ab7e1005e9e7a8 + create mode 100644 fuzz/gnutls_psk_client_fuzzer.in/b16434290b77e13d7a983d1da801fb3c6d1f7f846f227721e221adea08aa319c + +diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h +index bb6c19713..31cec5c0c 100644 +--- a/lib/gnutls_int.h ++++ b/lib/gnutls_int.h +@@ -1370,6 +1370,7 @@ typedef struct { + #define HSK_RECORD_SIZE_LIMIT_RECEIVED (1<<26) /* server: record_size_limit extension was seen but not accepted yet */ + #define HSK_OCSP_REQUESTED (1<<27) /* server: client requested OCSP stapling */ + #define HSK_CLIENT_OCSP_REQUESTED (1<<28) /* client: server requested OCSP stapling */ ++#define HSK_SERVER_HELLO_RECEIVED (1<<29) /* client: Server Hello message has been received */ + + /* The hsk_flags are for use within the ongoing handshake; + * they are reset to zero prior to handshake start by gnutls_handshake. */ +diff --git a/lib/handshake.c b/lib/handshake.c +index b40f84b3d..ce2d160e2 100644 +--- a/lib/handshake.c ++++ b/lib/handshake.c +@@ -2061,6 +2061,8 @@ read_server_hello(gnutls_session_t session, + if (ret < 0) + return gnutls_assert_val(ret); + ++ session->internals.hsk_flags |= HSK_SERVER_HELLO_RECEIVED; ++ + return 0; + } + +@@ -2585,16 +2587,42 @@ int gnutls_rehandshake(gnutls_session_t session) + return 0; + } + ++/* This function checks whether the error code should be treated fatal ++ * or not, and also does the necessary state transition. In ++ * particular, in the case of a rehandshake abort it resets the ++ * handshake's internal state. ++ */ + inline static int + _gnutls_abort_handshake(gnutls_session_t session, int ret) + { +- if (((ret == GNUTLS_E_WARNING_ALERT_RECEIVED) && +- (gnutls_alert_get(session) == GNUTLS_A_NO_RENEGOTIATION)) +- || ret == GNUTLS_E_GOT_APPLICATION_DATA) +- return 0; ++ switch (ret) { ++ case GNUTLS_E_WARNING_ALERT_RECEIVED: ++ if (gnutls_alert_get(session) == GNUTLS_A_NO_RENEGOTIATION) { ++ /* The server always toleretes a "no_renegotiation" alert. */ ++ if (session->security_parameters.entity == GNUTLS_SERVER) { ++ STATE = STATE0; ++ return ret; ++ } ++ ++ /* The client should tolerete a "no_renegotiation" alert only if: ++ * - the initial handshake has completed, or ++ * - a Server Hello is not yet received ++ */ ++ if (session->internals.initial_negotiation_completed || ++ !(session->internals.hsk_flags & HSK_SERVER_HELLO_RECEIVED)) { ++ STATE = STATE0; ++ return ret; ++ } + +- /* this doesn't matter */ +- return GNUTLS_E_INTERNAL_ERROR; ++ return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET); ++ } ++ return ret; ++ case GNUTLS_E_GOT_APPLICATION_DATA: ++ STATE = STATE0; ++ return ret; ++ default: ++ return ret; ++ } + } + + +@@ -2756,13 +2784,7 @@ int gnutls_handshake(gnutls_session_t session) + } + + if (ret < 0) { +- /* In the case of a rehandshake abort +- * we should reset the handshake's internal state. +- */ +- if (_gnutls_abort_handshake(session, ret) == 0) +- STATE = STATE0; +- +- return ret; ++ return _gnutls_abort_handshake(session, ret); + } + + /* clear handshake buffer */ +-- +2.26.2 + diff --git a/SPECS/gnutls.spec b/SPECS/gnutls.spec index 9ec2d80..c3a7103 100644 --- a/SPECS/gnutls.spec +++ b/SPECS/gnutls.spec @@ -1,5 +1,5 @@ Version: 3.6.14 -Release: 6%{?dist} +Release: 7%{?dist} Patch1: gnutls-3.2.7-rpath.patch Patch2: gnutls-3.6.4-no-now-guile.patch Patch3: gnutls-3.6.13-enable-intel-cet.patch @@ -9,6 +9,9 @@ Patch6: gnutls-3.6.14-fips-dh-primes.patch Patch7: gnutls-3.6.14-memcmp.patch Patch8: gnutls-3.6.14-fips-dh-check.patch Patch9: gnutls-3.6.14-fix-iovec-memory-leak.patch +Patch10: gnutls-3.6.14-fips-dh-selftests.patch +Patch11: gnutls-3.6.14-fips-kdf-selftests.patch +Patch12: gnutls-3.6.14-no-renegotiation.patch %bcond_without dane %if 0%{?rhel} %bcond_with guile @@ -292,6 +295,11 @@ fi %endif %changelog +* Tue Nov 3 2020 Daiki Ueno - 3.6.14-7 +- Increase DH key bits to >= 2048 in self-tests (#1879506) +- Implement self-tests for KDF and CMAC (#1890870) +- Fix CVE-2020-24659: heap buffer-overflow when "no_renegotiation" alert is received (#1873959) + * Mon Aug 24 2020 Daiki Ueno - 3.6.14-6 - Fix memory leak when serializing iovec_t (#1844112)