Blame SOURCES/gnutls-3.7.6-fips-symkey-limit.patch

a74aed
From f8a8961cfa176fc74c153cb6e1e68aff5e2d42f2 Mon Sep 17 00:00:00 2001
a74aed
From: rpm-build <rpm-build>
a74aed
Date: Tue, 27 Sep 2022 10:52:19 +0900
a74aed
Subject: [PATCH] gnutls-3.7.6-fips-symkey-limit.patch
a74aed
a74aed
---
a74aed
 lib/crypto-api.c  | 26 ++++++++++++++++++++++---
a74aed
 tests/fips-test.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++
a74aed
 tests/kdf-api.c   |  9 ++++++++-
a74aed
 3 files changed, 80 insertions(+), 4 deletions(-)
a74aed
a74aed
diff --git a/lib/crypto-api.c b/lib/crypto-api.c
a74aed
index b3e1eec..35200fb 100644
a74aed
--- a/lib/crypto-api.c
a74aed
+++ b/lib/crypto-api.c
a74aed
@@ -896,6 +896,7 @@ gnutls_hash_hd_t gnutls_hash_copy(gnutls_hash_hd_t handle)
a74aed
 int gnutls_key_generate(gnutls_datum_t * key, unsigned int key_size)
a74aed
 {
a74aed
 	int ret;
a74aed
+	bool not_approved = false;
a74aed
 
a74aed
 	FAIL_IF_LIB_ERROR;
a74aed
 
a74aed
@@ -912,17 +913,31 @@ int gnutls_key_generate(gnutls_datum_t * key, unsigned int key_size)
a74aed
 	key->data = gnutls_malloc(key->size);
a74aed
 	if (!key->data) {
a74aed
 		gnutls_assert();
a74aed
-		return GNUTLS_E_MEMORY_ERROR;
a74aed
+		ret = GNUTLS_E_MEMORY_ERROR;
a74aed
+		goto error;
a74aed
+	}
a74aed
+
a74aed
+	/* Key lengths of less than 112 bits are not approved */
a74aed
+	if (key_size < 14) {
a74aed
+		not_approved = true;
a74aed
 	}
a74aed
 
a74aed
 	ret = gnutls_rnd(GNUTLS_RND_RANDOM, key->data, key->size);
a74aed
 	if (ret < 0) {
a74aed
 		gnutls_assert();
a74aed
 		_gnutls_free_datum(key);
a74aed
-		return ret;
a74aed
+		goto error;
a74aed
 	}
a74aed
 
a74aed
-	return 0;
a74aed
+ error:
a74aed
+	if (ret < 0) {
a74aed
+		_gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
a74aed
+	} else if (not_approved) {
a74aed
+		_gnutls_switch_fips_state(GNUTLS_FIPS140_OP_NOT_APPROVED);
a74aed
+	} else {
a74aed
+		_gnutls_switch_fips_state(GNUTLS_FIPS140_OP_APPROVED);
a74aed
+	}
a74aed
+	return ret;
a74aed
 }
a74aed
 
a74aed
 /* AEAD API */
a74aed
@@ -2058,6 +2073,11 @@ gnutls_pbkdf2(gnutls_mac_algorithm_t mac,
a74aed
 		not_approved = true;
a74aed
 	}
a74aed
 
a74aed
+	/* Key lengths and output sizes of less than 112 bits are not approved */
a74aed
+	if (key->size < 14 || length < 14) {
a74aed
+		not_approved = true;
a74aed
+	}
a74aed
+
a74aed
 	ret = _gnutls_kdf_ops.pbkdf2(mac, key->data, key->size,
a74aed
 				     salt->data, salt->size, iter_count,
a74aed
 				     output, length);
a74aed
diff --git a/tests/fips-test.c b/tests/fips-test.c
a74aed
index 31a5e26..27da414 100644
a74aed
--- a/tests/fips-test.c
a74aed
+++ b/tests/fips-test.c
a74aed
@@ -274,6 +274,8 @@ void doit(void)
a74aed
 	gnutls_datum_t signature;
a74aed
 	unsigned int bits;
a74aed
 	uint8_t hmac[64];
a74aed
+	uint8_t pbkdf2[64];
a74aed
+	gnutls_datum_t temp_key = { NULL, 0 };
a74aed
 
a74aed
 	fprintf(stderr,
a74aed
 		"Please note that if in FIPS140 mode, you need to assure the library's integrity prior to running this test\n");
a74aed
@@ -371,11 +373,58 @@ void doit(void)
a74aed
 	}
a74aed
 	FIPS_POP_CONTEXT(NOT_APPROVED);
a74aed
 
a74aed
+	/* PBKDF2 with key equal to or longer than 112 bits: approved */
a74aed
+	FIPS_PUSH_CONTEXT();
a74aed
+	ret = gnutls_pbkdf2(GNUTLS_MAC_SHA256, &key, &iv, 100,
a74aed
+			    &pbkdf2, sizeof(pbkdf2));
a74aed
+	if (ret < 0) {
a74aed
+		fail("gnutls_pbkdf2 failed\n");
a74aed
+	}
a74aed
+	FIPS_POP_CONTEXT(APPROVED);
a74aed
+
a74aed
+	/* PBKDF2 with key shorter than 112 bits: not approved */
a74aed
+	FIPS_PUSH_CONTEXT();
a74aed
+	key.size = 13;
a74aed
+	ret = gnutls_pbkdf2(GNUTLS_MAC_SHA256, &key, &iv, 100,
a74aed
+			    &pbkdf2, sizeof(pbkdf2));
a74aed
+	if (ret < 0) {
a74aed
+		fail("gnutls_pbkdf2 failed\n");
a74aed
+	}
a74aed
+	key.size = sizeof(key16);
a74aed
+	FIPS_POP_CONTEXT(NOT_APPROVED);
a74aed
+
a74aed
+	/* PBKDF2 with output shorter than 112 bits: not approved */
a74aed
+	FIPS_PUSH_CONTEXT();
a74aed
+	ret = gnutls_pbkdf2(GNUTLS_MAC_SHA256, &key, &iv, 100,
a74aed
+			    &pbkdf2, 13);
a74aed
+	if (ret < 0) {
a74aed
+		fail("gnutls_pbkdf2 failed\n");
a74aed
+	}
a74aed
+	FIPS_POP_CONTEXT(NOT_APPROVED);
a74aed
+
a74aed
 	ret = gnutls_rnd(GNUTLS_RND_NONCE, key16, sizeof(key16));
a74aed
 	if (ret < 0) {
a74aed
 		fail("gnutls_rnd failed\n");
a74aed
 	}
a74aed
 
a74aed
+	/* Symmetric key generation equal to or longer than 112 bits: approved */
a74aed
+	FIPS_PUSH_CONTEXT();
a74aed
+	ret = gnutls_key_generate(&temp_key, 14);
a74aed
+	if (ret < 0) {
a74aed
+		fail("gnutls_key_generate failed\n");
a74aed
+	}
a74aed
+	gnutls_free(temp_key.data);
a74aed
+	FIPS_POP_CONTEXT(APPROVED);
a74aed
+
a74aed
+	/* Symmetric key generation shorter than 112 bits: not approved */
a74aed
+	FIPS_PUSH_CONTEXT();
a74aed
+	ret = gnutls_key_generate(&temp_key, 13);
a74aed
+	if (ret < 0) {
a74aed
+		fail("gnutls_key_generate failed\n");
a74aed
+	}
a74aed
+	gnutls_free(temp_key.data);
a74aed
+	FIPS_POP_CONTEXT(NOT_APPROVED);
a74aed
+
a74aed
 	ret = gnutls_pubkey_init(&pubkey);
a74aed
 	if (ret < 0) {
a74aed
 		fail("gnutls_pubkey_init failed\n");
a74aed
diff --git a/tests/kdf-api.c b/tests/kdf-api.c
a74aed
index 25fbc6a..8a4677c 100644
a74aed
--- a/tests/kdf-api.c
a74aed
+++ b/tests/kdf-api.c
a74aed
@@ -89,6 +89,7 @@ test_hkdf(gnutls_mac_algorithm_t mac,
a74aed
 
a74aed
 	FIPS_PUSH_CONTEXT();
a74aed
 	assert(gnutls_hkdf_extract(mac, &ikm, &salt, buf) >= 0);
a74aed
+	/* HKDF outside of TLS usage is not approved */
a74aed
 	FIPS_POP_CONTEXT(NOT_APPROVED);
a74aed
 	gnutls_free(ikm.data);
a74aed
 	gnutls_free(salt.data);
a74aed
@@ -110,6 +111,7 @@ test_hkdf(gnutls_mac_algorithm_t mac,
a74aed
 
a74aed
 	FIPS_PUSH_CONTEXT();
a74aed
 	assert(gnutls_hkdf_expand(mac, &prk, &info, buf, length) >= 0);
a74aed
+	/* HKDF outside of TLS usage is not approved */
a74aed
 	FIPS_POP_CONTEXT(NOT_APPROVED);
a74aed
 	gnutls_free(info.data);
a74aed
 
a74aed
@@ -151,7 +153,12 @@ test_pbkdf2(gnutls_mac_algorithm_t mac,
a74aed
 
a74aed
 	FIPS_PUSH_CONTEXT();
a74aed
 	assert(gnutls_pbkdf2(mac, &ikm, &salt, iter_count, buf, length) >= 0);
a74aed
-	FIPS_POP_CONTEXT(APPROVED);
a74aed
+	/* Key sizes and output sizes less than 112-bit are not approved.  */
a74aed
+	if (ikm.size < 14 || length < 14) {
a74aed
+		FIPS_POP_CONTEXT(NOT_APPROVED);
a74aed
+	} else {
a74aed
+		FIPS_POP_CONTEXT(APPROVED);
a74aed
+	}
a74aed
 	gnutls_free(ikm.data);
a74aed
 	gnutls_free(salt.data);
a74aed
 
a74aed
-- 
a74aed
2.37.3
a74aed
a74aed
From 86eded166f77612c70201c0d85d3abe711edd77d Mon Sep 17 00:00:00 2001
a74aed
From: Daiki Ueno <ueno@gnu.org>
a74aed
Date: Thu, 29 Sep 2022 21:19:26 +0900
a74aed
Subject: [PATCH] fips: only mark HMAC as approved in PBKDF2
a74aed
a74aed
As ACVP only allows HMAC used with PBKDF2[1], this change marks other
a74aed
hash algorithms not-approved.
a74aed
a74aed
1. https://pages.nist.gov/ACVP/draft-celi-acvp-pbkdf.html
a74aed
a74aed
Signed-off-by: Daiki Ueno <ueno@gnu.org>
a74aed
---
a74aed
 lib/crypto-api.c |  5 ++++-
a74aed
 lib/fips.h       | 16 +++++++++++++++-
a74aed
 tests/kdf-api.c  | 30 +++++++++++++++++++++++++++++-
a74aed
 3 files changed, 48 insertions(+), 3 deletions(-)
a74aed
a74aed
diff --git a/lib/crypto-api.c b/lib/crypto-api.c
a74aed
index d3e601ab3a..9f7e18db11 100644
a74aed
--- a/lib/crypto-api.c
a74aed
+++ b/lib/crypto-api.c
a74aed
@@ -2229,7 +2229,10 @@ gnutls_pbkdf2(gnutls_mac_algorithm_t mac,
a74aed
 	if (!is_mac_algo_allowed(mac)) {
a74aed
 		_gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
a74aed
 		return gnutls_assert_val(GNUTLS_E_UNWANTED_ALGORITHM);
a74aed
-	} else if (!is_mac_algo_approved_in_fips(mac)) {
a74aed
+	} else if (!is_mac_algo_hmac_approved_in_fips(mac)) {
a74aed
+		/* ACVP only allows HMAC used with PBKDF2:
a74aed
+		 * https://pages.nist.gov/ACVP/draft-celi-acvp-pbkdf.html
a74aed
+		 */
a74aed
 		not_approved = true;
a74aed
 	}
a74aed
 
a74aed
diff --git a/lib/fips.h b/lib/fips.h
a74aed
index 3a74f254e7..bf61b36741 100644
a74aed
--- a/lib/fips.h
a74aed
+++ b/lib/fips.h
a74aed
@@ -76,7 +76,7 @@ void _gnutls_lib_simulate_error(void);
a74aed
 void _gnutls_lib_force_operational(void);
a74aed
 
a74aed
 inline static bool
a74aed
-is_mac_algo_approved_in_fips(gnutls_mac_algorithm_t algo)
a74aed
+is_mac_algo_hmac_approved_in_fips(gnutls_mac_algorithm_t algo)
a74aed
 {
a74aed
 	switch (algo) {
a74aed
 	case GNUTLS_MAC_SHA1:
a74aed
@@ -88,6 +88,20 @@ is_mac_algo_approved_in_fips(gnutls_mac_algorithm_t algo)
a74aed
 	case GNUTLS_MAC_SHA3_256:
a74aed
 	case GNUTLS_MAC_SHA3_384:
a74aed
 	case GNUTLS_MAC_SHA3_512:
a74aed
+		return true;
a74aed
+	default:
a74aed
+		return false;
a74aed
+	}
a74aed
+}
a74aed
+
a74aed
+inline static bool
a74aed
+is_mac_algo_approved_in_fips(gnutls_mac_algorithm_t algo)
a74aed
+{
a74aed
+	if (is_mac_algo_hmac_approved_in_fips(algo)) {
a74aed
+		return true;
a74aed
+	}
a74aed
+
a74aed
+	switch (algo) {
a74aed
 	case GNUTLS_MAC_AES_CMAC_128:
a74aed
 	case GNUTLS_MAC_AES_CMAC_256:
a74aed
 	case GNUTLS_MAC_AES_GMAC_128:
a74aed
diff --git a/tests/kdf-api.c b/tests/kdf-api.c
a74aed
index 577cbf7a17..4feb22688b 100644
a74aed
--- a/tests/kdf-api.c
a74aed
+++ b/tests/kdf-api.c
a74aed
@@ -26,6 +26,7 @@
a74aed
 #include <gnutls/crypto.h>
a74aed
 
a74aed
 #include <assert.h>
a74aed
+#include <stdbool.h>
a74aed
 #include <stdint.h>
a74aed
 
a74aed
 #include "utils.h"
a74aed
@@ -133,6 +134,25 @@ test_hkdf(gnutls_mac_algorithm_t mac,
a74aed
 	gnutls_free(hex.data);
a74aed
 }
a74aed
 
a74aed
+inline static bool
a74aed
+is_mac_algo_hmac_approved_in_fips(gnutls_mac_algorithm_t algo)
a74aed
+{
a74aed
+	switch (algo) {
a74aed
+	case GNUTLS_MAC_SHA1:
a74aed
+	case GNUTLS_MAC_SHA256:
a74aed
+	case GNUTLS_MAC_SHA384:
a74aed
+	case GNUTLS_MAC_SHA512:
a74aed
+	case GNUTLS_MAC_SHA224:
a74aed
+	case GNUTLS_MAC_SHA3_224:
a74aed
+	case GNUTLS_MAC_SHA3_256:
a74aed
+	case GNUTLS_MAC_SHA3_384:
a74aed
+	case GNUTLS_MAC_SHA3_512:
a74aed
+		return true;
a74aed
+	default:
a74aed
+		return false;
a74aed
+	}
a74aed
+}
a74aed
+
a74aed
 static void
a74aed
 test_pbkdf2(gnutls_mac_algorithm_t mac,
a74aed
 	    const char *ikm_hex,
a74aed
@@ -161,7 +181,8 @@ test_pbkdf2(gnutls_mac_algorithm_t mac,
a74aed
 	FIPS_PUSH_CONTEXT();
a74aed
 	assert(gnutls_pbkdf2(mac, &ikm, &salt, iter_count, buf, length) >= 0);
a74aed
 	/* Key sizes and output sizes less than 112-bit are not approved.  */
a74aed
-	if (ikm.size < 14 || length < 14) {
a74aed
+	if (ikm.size < 14 || length < 14 ||
a74aed
+	    !is_mac_algo_hmac_approved_in_fips(mac)) {
a74aed
 		FIPS_POP_CONTEXT(NOT_APPROVED);
a74aed
 	} else {
a74aed
 		FIPS_POP_CONTEXT(APPROVED);
a74aed
@@ -208,5 +229,12 @@ doit(void)
a74aed
 		    20,
a74aed
 		    "4b007901b765489abead49d926f721d065a429c1");
a74aed
 
a74aed
+	test_pbkdf2(GNUTLS_MAC_AES_CMAC_128,
a74aed
+		    "70617373776f726470617373776f7264", /* "passwordpassword" */
a74aed
+		    "73616c74",		/* "salt" */
a74aed
+		    4096,
a74aed
+		    20,
a74aed
+		    "c4c112c6e1e3b8757640603dec78825ff87605a7");
a74aed
+
a74aed
 	gnutls_fips140_context_deinit(fips_context);
a74aed
 }
a74aed
-- 
a74aed
2.37.3
a74aed