Blame SOURCES/gnutls-3.7.6-fips-run-selftests.patch

e79d4b
From 036fb360e5775f01ef25f5e712024a29930c462e Mon Sep 17 00:00:00 2001
e79d4b
From: Daiki Ueno <ueno@gnu.org>
e79d4b
Date: Fri, 3 Jun 2022 15:43:00 +0900
e79d4b
Subject: [PATCH] fips: provide function to manually run FIPS self-tests
e79d4b
e79d4b
FIPS140-3 IG 10.3.E Periodic Self-Testing says:
e79d4b
e79d4b
  At security levels 1 and 2, acceptable means for initiating the
e79d4b
  periodic self-tests include a provided service, resetting, rebooting
e79d4b
  or power cycling.
e79d4b
e79d4b
Neither resetting, rebooting, nor power-cycling is suitable because
e79d4b
those involve operations outside of the module.  Therefore this patch
e79d4b
adds a new API to manually run the substance of FIPS140 self-tests.
e79d4b
e79d4b
Suggeested by Richard Costa and Stephan Mueller in:
e79d4b
https://gitlab.com/gnutls/gnutls/-/issues/1364
e79d4b
e79d4b
Signed-off-by: Daiki Ueno <ueno@gnu.org>
e79d4b
---
e79d4b
 NEWS                            |   5 ++
e79d4b
 devel/libgnutls.abignore        |   2 +
e79d4b
 devel/symbols.last              |   2 +
e79d4b
 doc/Makefile.am                 |   2 +
e79d4b
 doc/manpages/Makefile.am        |   1 +
e79d4b
 lib/fips.c                      | 139 ++++++++++++++++----------------
e79d4b
 lib/global.c                    |  14 +++-
e79d4b
 lib/includes/gnutls/gnutls.h.in |   2 +
e79d4b
 lib/libgnutls.map               |   8 ++
e79d4b
 tests/fips-test.c               |   7 ++
e79d4b
 10 files changed, 110 insertions(+), 72 deletions(-)
e79d4b
e79d4b
diff --git a/NEWS b/NEWS
e79d4b
index 70dd8a12b5..389be8acaa 100644
e79d4b
--- a/NEWS
e79d4b
+++ b/NEWS
e79d4b
@@ -5,6 +5,11 @@ Copyright (C) 2000-2016 Free Software Foundation, Inc.
e79d4b
 Copyright (C) 2013-2019 Nikos Mavrogiannopoulos
e79d4b
 See the end for copying conditions.
e79d4b
 
e79d4b
+* Version 3.7.7 (unreleased)
e79d4b
+
e79d4b
+** API and ABI modifications:
e79d4b
+gnutls_fips140_run_self_tests: New function
e79d4b
+
e79d4b
 * Version 3.7.6 (released 2022-05-27)
e79d4b
 
e79d4b
 ** libgnutls: Fixed invalid write when gnutls_realloc_zero()
e79d4b
diff --git a/doc/Makefile.am b/doc/Makefile.am
e79d4b
index d20a021d97..34ef43866c 100644
e79d4b
--- a/doc/Makefile.am
e79d4b
+++ b/doc/Makefile.am
e79d4b
@@ -1096,6 +1096,8 @@ FUNCS += functions/gnutls_fips140_pop_context
e79d4b
 FUNCS += functions/gnutls_fips140_pop_context.short
e79d4b
 FUNCS += functions/gnutls_fips140_push_context
e79d4b
 FUNCS += functions/gnutls_fips140_push_context.short
e79d4b
+FUNCS += functions/gnutls_fips140_run_self_tests
e79d4b
+FUNCS += functions/gnutls_fips140_run_self_tests.short
e79d4b
 FUNCS += functions/gnutls_fips140_set_mode
e79d4b
 FUNCS += functions/gnutls_fips140_set_mode.short
e79d4b
 FUNCS += functions/gnutls_get_library_config
e79d4b
diff --git a/doc/manpages/Makefile.am b/doc/manpages/Makefile.am
e79d4b
index d8c5f2854d..90906b0574 100644
e79d4b
--- a/doc/manpages/Makefile.am
e79d4b
+++ b/doc/manpages/Makefile.am
e79d4b
@@ -380,6 +380,7 @@ APIMANS += gnutls_fips140_get_operation_state.3
e79d4b
 APIMANS += gnutls_fips140_mode_enabled.3
e79d4b
 APIMANS += gnutls_fips140_pop_context.3
e79d4b
 APIMANS += gnutls_fips140_push_context.3
e79d4b
+APIMANS += gnutls_fips140_run_self_tests.3
e79d4b
 APIMANS += gnutls_fips140_set_mode.3
e79d4b
 APIMANS += gnutls_get_library_config.3
e79d4b
 APIMANS += gnutls_get_system_config_file.3
e79d4b
diff --git a/lib/fips.c b/lib/fips.c
e79d4b
index e9c27f6df6..656d43e74a 100644
e79d4b
--- a/lib/fips.c
e79d4b
+++ b/lib/fips.c
e79d4b
@@ -419,8 +419,6 @@ int _gnutls_fips_perform_self_checks1(void)
e79d4b
 {
e79d4b
 	int ret;
e79d4b
 
e79d4b
-	_gnutls_switch_lib_state(LIB_STATE_SELFTEST);
e79d4b
-
e79d4b
 	/* Tests the FIPS algorithms used by nettle internally.
e79d4b
 	 * In our case we test AES-CBC since nettle's AES is used by
e79d4b
 	 * the DRBG-AES.
e79d4b
@@ -429,193 +427,153 @@ int _gnutls_fips_perform_self_checks1(void)
e79d4b
 	/* ciphers - one test per cipher */
e79d4b
 	ret = gnutls_cipher_self_test(0, GNUTLS_CIPHER_AES_128_CBC);
e79d4b
 	if (ret < 0) {
e79d4b
-		gnutls_assert();
e79d4b
-		goto error;
e79d4b
+		return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
e79d4b
 	}
e79d4b
 
e79d4b
 	return 0;
e79d4b
-
e79d4b
-error:
e79d4b
-	_gnutls_switch_lib_state(LIB_STATE_ERROR);
e79d4b
-	_gnutls_audit_log(NULL, "FIPS140-2 self testing part1 failed\n");
e79d4b
-
e79d4b
-	return GNUTLS_E_SELF_TEST_ERROR;
e79d4b
 }
e79d4b
 
e79d4b
 int _gnutls_fips_perform_self_checks2(void)
e79d4b
 {
e79d4b
 	int ret;
e79d4b
 
e79d4b
-	_gnutls_switch_lib_state(LIB_STATE_SELFTEST);
e79d4b
-
e79d4b
 	/* Tests the FIPS algorithms */
e79d4b
 
e79d4b
 	/* ciphers - one test per cipher */
e79d4b
 	ret = gnutls_cipher_self_test(0, GNUTLS_CIPHER_3DES_CBC);
e79d4b
 	if (ret < 0) {
e79d4b
-		gnutls_assert();
e79d4b
-		goto error;
e79d4b
+		return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
e79d4b
 	}
e79d4b
 
e79d4b
 	ret = gnutls_cipher_self_test(0, GNUTLS_CIPHER_AES_256_CBC);
e79d4b
 	if (ret < 0) {
e79d4b
-		gnutls_assert();
e79d4b
-		goto error;
e79d4b
+		return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
e79d4b
 	}
e79d4b
 
e79d4b
 	ret = gnutls_cipher_self_test(0, GNUTLS_CIPHER_AES_256_GCM);
e79d4b
 	if (ret < 0) {
e79d4b
-		gnutls_assert();
e79d4b
-		goto error;
e79d4b
+		return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
e79d4b
 	}
e79d4b
 
e79d4b
 	ret = gnutls_cipher_self_test(0, GNUTLS_CIPHER_AES_256_XTS);
e79d4b
 	if (ret < 0) {
e79d4b
-		gnutls_assert();
e79d4b
-		goto error;
e79d4b
+		return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
e79d4b
 	}
e79d4b
 
e79d4b
 	ret = gnutls_cipher_self_test(0, GNUTLS_CIPHER_AES_256_CFB8);
e79d4b
 	if (ret < 0) {
e79d4b
-		gnutls_assert();
e79d4b
-		goto error;
e79d4b
+		return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
e79d4b
 	}
e79d4b
 
e79d4b
 	/* Digest tests */
e79d4b
 	ret = gnutls_digest_self_test(0, GNUTLS_DIG_SHA3_224);
e79d4b
 	if (ret < 0) {
e79d4b
-		gnutls_assert();
e79d4b
-		goto error;
e79d4b
+		return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
e79d4b
 	}
e79d4b
 
e79d4b
 	ret = gnutls_digest_self_test(0, GNUTLS_DIG_SHA3_256);
e79d4b
 	if (ret < 0) {
e79d4b
-		gnutls_assert();
e79d4b
-		goto error;
e79d4b
+		return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
e79d4b
 	}
e79d4b
 
e79d4b
 	ret = gnutls_digest_self_test(0, GNUTLS_DIG_SHA3_384);
e79d4b
 	if (ret < 0) {
e79d4b
-		gnutls_assert();
e79d4b
-		goto error;
e79d4b
+		return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
e79d4b
 	}
e79d4b
 
e79d4b
 	ret = gnutls_digest_self_test(0, GNUTLS_DIG_SHA3_512);
e79d4b
 	if (ret < 0) {
e79d4b
-		gnutls_assert();
e79d4b
-		goto error;
e79d4b
+		return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
e79d4b
 	}
e79d4b
 
e79d4b
 	/* MAC (includes message digest test) */
e79d4b
 	ret = gnutls_mac_self_test(0, GNUTLS_MAC_SHA1);
e79d4b
 	if (ret < 0) {
e79d4b
-		gnutls_assert();
e79d4b
-		goto error;
e79d4b
+		return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
e79d4b
 	}
e79d4b
 
e79d4b
 	ret = gnutls_mac_self_test(0, GNUTLS_MAC_SHA224);
e79d4b
 	if (ret < 0) {
e79d4b
-		gnutls_assert();
e79d4b
-		goto error;
e79d4b
+		return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
e79d4b
 	}
e79d4b
 
e79d4b
 	ret = gnutls_mac_self_test(0, GNUTLS_MAC_SHA256);
e79d4b
 	if (ret < 0) {
e79d4b
-		gnutls_assert();
e79d4b
-		goto error;
e79d4b
+		return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
e79d4b
 	}
e79d4b
 
e79d4b
 	ret = gnutls_mac_self_test(0, GNUTLS_MAC_SHA384);
e79d4b
 	if (ret < 0) {
e79d4b
-		gnutls_assert();
e79d4b
-		goto error;
e79d4b
+		return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
e79d4b
 	}
e79d4b
 
e79d4b
 	ret = gnutls_mac_self_test(0, GNUTLS_MAC_SHA512);
e79d4b
 	if (ret < 0) {
e79d4b
-		gnutls_assert();
e79d4b
-		goto error;
e79d4b
+		return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
e79d4b
 	}
e79d4b
 
e79d4b
 	ret = gnutls_mac_self_test(0, GNUTLS_MAC_AES_CMAC_256);
e79d4b
 	if (ret < 0) {
e79d4b
-		gnutls_assert();
e79d4b
-		goto error;
e79d4b
+		return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
e79d4b
 	}
e79d4b
 
e79d4b
 	/* PK */
e79d4b
 	ret = gnutls_pk_self_test(0, GNUTLS_PK_RSA);
e79d4b
 	if (ret < 0) {
e79d4b
-		gnutls_assert();
e79d4b
-		goto error;
e79d4b
+		return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
e79d4b
 	}
e79d4b
 
e79d4b
 	ret = gnutls_pk_self_test(0, GNUTLS_PK_DSA);
e79d4b
 	if (ret < 0) {
e79d4b
-		gnutls_assert();
e79d4b
-		goto error;
e79d4b
+		return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
e79d4b
 	}
e79d4b
 
e79d4b
 	ret = gnutls_pk_self_test(0, GNUTLS_PK_EC);
e79d4b
 	if (ret < 0) {
e79d4b
-		gnutls_assert();
e79d4b
-		goto error;
e79d4b
+		return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
e79d4b
 	}
e79d4b
 
e79d4b
 	ret = gnutls_pk_self_test(0, GNUTLS_PK_DH);
e79d4b
 	if (ret < 0) {
e79d4b
-		gnutls_assert();
e79d4b
-		goto error;
e79d4b
+		return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
e79d4b
 	}
e79d4b
 
e79d4b
 	/* HKDF */
e79d4b
 	ret = gnutls_hkdf_self_test(0, GNUTLS_MAC_SHA256);
e79d4b
 	if (ret < 0) {
e79d4b
-		gnutls_assert();
e79d4b
-		goto error;
e79d4b
+		return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
e79d4b
 	}
e79d4b
 
e79d4b
 	/* PBKDF2 */
e79d4b
 	ret = gnutls_pbkdf2_self_test(0, GNUTLS_MAC_SHA256);
e79d4b
 	if (ret < 0) {
e79d4b
-		gnutls_assert();
e79d4b
-		goto error;
e79d4b
+		return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
e79d4b
 	}
e79d4b
 
e79d4b
 	/* TLS-PRF */
e79d4b
 	ret = gnutls_tlsprf_self_test(0, GNUTLS_MAC_SHA256);
e79d4b
 	if (ret < 0) {
e79d4b
-		gnutls_assert();
e79d4b
-		goto error;
e79d4b
+		return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
e79d4b
 	}
e79d4b
 
e79d4b
 	if (_gnutls_rnd_ops.self_test == NULL) {
e79d4b
-		gnutls_assert();
e79d4b
-		goto error;
e79d4b
+		return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
e79d4b
 	}
e79d4b
 
e79d4b
 	/* this does not require rng initialization */
e79d4b
 	ret = _gnutls_rnd_ops.self_test();
e79d4b
 	if (ret < 0) {
e79d4b
-		gnutls_assert();
e79d4b
-		goto error;
e79d4b
+		return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
e79d4b
 	}
e79d4b
 
e79d4b
 	if (_skip_integrity_checks == 0) {
e79d4b
 		ret = check_binary_integrity();
e79d4b
 		if (ret < 0) {
e79d4b
-			gnutls_assert();
e79d4b
-			goto error;
e79d4b
+			return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
e79d4b
 		}
e79d4b
 	}
e79d4b
 
e79d4b
 	return 0;
e79d4b
-
e79d4b
-error:
e79d4b
-	_gnutls_switch_lib_state(LIB_STATE_ERROR);
e79d4b
-	_gnutls_audit_log(NULL, "FIPS140-2 self testing part 2 failed\n");
e79d4b
-
e79d4b
-	return GNUTLS_E_SELF_TEST_ERROR;
e79d4b
 }
e79d4b
 #endif
e79d4b
 
e79d4b
@@ -894,3 +852,48 @@ _gnutls_switch_fips_state(gnutls_fips140_operation_state_t state)
e79d4b
 	(void)state;
e79d4b
 #endif
e79d4b
 }
e79d4b
+
e79d4b
+/**
e79d4b
+ * gnutls_fips140_run_self_tests:
e79d4b
+ *
e79d4b
+ * Manually perform the second round of the FIPS140 self-tests,
e79d4b
+ * including:
e79d4b
+ *
e79d4b
+ * - Known answer tests (KAT) for the selected set of symmetric
e79d4b
+ *   cipher, MAC, public key, KDF, and DRBG
e79d4b
+ * - Library integrity checks
e79d4b
+ *
e79d4b
+ * Upon failure with FIPS140 mode enabled, it makes the library
e79d4b
+ * unusable.  This function is not thread-safe.
e79d4b
+ *
e79d4b
+ * Returns: 0 upon success, a negative error code otherwise
e79d4b
+ *
e79d4b
+ * Since: 3.7.7
e79d4b
+ */
e79d4b
+int
e79d4b
+gnutls_fips140_run_self_tests(void)
e79d4b
+{
e79d4b
+#ifdef ENABLE_FIPS140
e79d4b
+	int ret;
e79d4b
+	unsigned prev_lib_state;
e79d4b
+
e79d4b
+	/* Temporarily switch to LIB_STATE_SELFTEST as some of the
e79d4b
+	 * algorithms are implemented using special constructs in
e79d4b
+	 * self-tests (such as deterministic variants) */
e79d4b
+	prev_lib_state = _gnutls_get_lib_state();
e79d4b
+	_gnutls_switch_lib_state(LIB_STATE_SELFTEST);
e79d4b
+
e79d4b
+	ret = _gnutls_fips_perform_self_checks2();
e79d4b
+	if (gnutls_fips140_mode_enabled() != GNUTLS_FIPS140_DISABLED &&
e79d4b
+	    ret < 0) {
e79d4b
+		_gnutls_switch_lib_state(LIB_STATE_ERROR);
e79d4b
+		_gnutls_audit_log(NULL, "FIPS140-2 self testing part 2 failed\n");
e79d4b
+	} else {
e79d4b
+		/* Restore the previous library state */
e79d4b
+		_gnutls_switch_lib_state(prev_lib_state);
e79d4b
+	}
e79d4b
+	return ret;
e79d4b
+#else
e79d4b
+	return 0;
e79d4b
+#endif
e79d4b
+}
e79d4b
diff --git a/lib/global.c b/lib/global.c
e79d4b
index faa7f0afb2..1b372c15bd 100644
e79d4b
--- a/lib/global.c
e79d4b
+++ b/lib/global.c
e79d4b
@@ -336,9 +336,12 @@ static int _gnutls_global_init(unsigned constructor)
e79d4b
 
e79d4b
 		/* first round of self checks, these are done on the
e79d4b
 		 * nettle algorithms which are used internally */
e79d4b
+		_gnutls_switch_lib_state(LIB_STATE_SELFTEST);
e79d4b
 		ret = _gnutls_fips_perform_self_checks1();
e79d4b
-		if (res != 2) {
e79d4b
-			if (ret < 0) {
e79d4b
+		if (ret < 0) {
e79d4b
+			_gnutls_switch_lib_state(LIB_STATE_ERROR);
e79d4b
+			_gnutls_audit_log(NULL, "FIPS140-2 self testing part1 failed\n");
e79d4b
+			if (res != 2) {
e79d4b
 				gnutls_assert();
e79d4b
 				goto out;
e79d4b
 			}
e79d4b
@@ -355,9 +358,12 @@ static int _gnutls_global_init(unsigned constructor)
e79d4b
 	 * (e.g., AESNI overridden AES). They are after _gnutls_register_accel_crypto()
e79d4b
 	 * intentionally */
e79d4b
 	if (res != 0) {
e79d4b
+		_gnutls_switch_lib_state(LIB_STATE_SELFTEST);
e79d4b
 		ret = _gnutls_fips_perform_self_checks2();
e79d4b
-		if (res != 2) {
e79d4b
-			if (ret < 0) {
e79d4b
+		if (ret < 0) {
e79d4b
+			_gnutls_switch_lib_state(LIB_STATE_ERROR);
e79d4b
+			_gnutls_audit_log(NULL, "FIPS140-2 self testing part 2 failed\n");
e79d4b
+			if (res != 2) {
e79d4b
 				gnutls_assert();
e79d4b
 				goto out;
e79d4b
 			}
e79d4b
diff --git a/lib/includes/gnutls/gnutls.h.in b/lib/includes/gnutls/gnutls.h.in
e79d4b
index f7fc5d114a..5840f331e9 100644
e79d4b
--- a/lib/includes/gnutls/gnutls.h.in
e79d4b
+++ b/lib/includes/gnutls/gnutls.h.in
e79d4b
@@ -3416,6 +3416,8 @@ gnutls_fips140_get_operation_state(gnutls_fips140_context_t context);
e79d4b
 int gnutls_fips140_push_context(gnutls_fips140_context_t context);
e79d4b
 int gnutls_fips140_pop_context(void);
e79d4b
 
e79d4b
+int gnutls_fips140_run_self_tests(void);
e79d4b
+
e79d4b
   /* Gnutls error codes. The mapping to a TLS alert is also shown in
e79d4b
    * comments.
e79d4b
    */
e79d4b
diff --git a/lib/libgnutls.map b/lib/libgnutls.map
e79d4b
index 0241946c8a..f42d5f9fae 100644
e79d4b
--- a/lib/libgnutls.map
e79d4b
+++ b/lib/libgnutls.map
e79d4b
@@ -1399,6 +1399,14 @@ GNUTLS_3_7_5
e79d4b
 	*;
e79d4b
 } GNUTLS_3_7_4;
e79d4b
 
e79d4b
+GNUTLS_3_7_7
e79d4b
+{
e79d4b
+ global:
e79d4b
+	gnutls_fips140_run_self_tests;
e79d4b
+ local:
e79d4b
+	*;
e79d4b
+} GNUTLS_3_7_5;
e79d4b
+
e79d4b
 GNUTLS_FIPS140_3_4 {
e79d4b
   global:
e79d4b
 	gnutls_cipher_self_test;
e79d4b
diff --git a/tests/fips-test.c b/tests/fips-test.c
e79d4b
index a6a283fa67..31a5e26111 100644
e79d4b
--- a/tests/fips-test.c
e79d4b
+++ b/tests/fips-test.c
e79d4b
@@ -525,6 +525,13 @@ void doit(void)
e79d4b
 	}
e79d4b
 
e79d4b
 	gnutls_fips140_context_deinit(fips_context);
e79d4b
+
e79d4b
+	/* run self-tests manually */
e79d4b
+	ret = gnutls_fips140_run_self_tests();
e79d4b
+	if (ret < 0) {
e79d4b
+		fail("gnutls_fips140_run_self_tests failed\n");
e79d4b
+	}
e79d4b
+
e79d4b
 	gnutls_global_deinit();
e79d4b
 	return;
e79d4b
 }
e79d4b
-- 
e79d4b
2.36.1
e79d4b
a74aed
From 354027c0c09db60d3083fa48ae791046d336957b Mon Sep 17 00:00:00 2001
a74aed
From: Alexander Sosedkin <asosedkin@redhat.com>
a74aed
Date: Tue, 28 Jun 2022 17:22:36 +0200
a74aed
Subject: [PATCH] tests/fips-test: minor extension
a74aed
a74aed
Signed-off-by: Alexander Sosedkin <asosedkin@redhat.com>
a74aed
---
a74aed
 tests/fips-test.c | 36 +++++++++++++++++++++++++++---------
a74aed
 1 file changed, 27 insertions(+), 9 deletions(-)
a74aed
a74aed
diff --git a/tests/fips-test.c b/tests/fips-test.c
a74aed
index 31a5e26111..f9bd34586a 100644
a74aed
--- a/tests/fips-test.c
a74aed
+++ b/tests/fips-test.c
a74aed
@@ -427,34 +427,43 @@ void doit(void)
a74aed
 	rsa_import_keypair(&privkey, &pubkey, "rsa-2432.pem");
a74aed
 	FIPS_POP_CONTEXT(INITIAL);
a74aed
 
a74aed
-	/* Create a signature with SHA256; approved */
a74aed
+	/* Create a signature with 2432-bit RSA and SHA256; approved */
a74aed
 	FIPS_PUSH_CONTEXT();
a74aed
 	ret = gnutls_privkey_sign_data(privkey, GNUTLS_DIG_SHA256, 0,
a74aed
 				       &data, &signature);
a74aed
 	if (ret < 0) {
a74aed
 		fail("gnutls_privkey_sign_data failed\n");
a74aed
 	}
a74aed
-	gnutls_free(signature.data);
a74aed
 	FIPS_POP_CONTEXT(APPROVED);
a74aed
 
a74aed
-	/* Create a signature with SHA-1; not approved */
a74aed
+	/* Verify a signature with 2432-bit RSA and SHA256; approved */
a74aed
+	FIPS_PUSH_CONTEXT();
a74aed
+	ret = gnutls_pubkey_verify_data2(pubkey, GNUTLS_SIGN_RSA_SHA256, 0,
a74aed
+	                                 &data, &signature);
a74aed
+	if (ret < 0) {
a74aed
+		fail("gnutls_pubkey_verify_data2 failed\n");
a74aed
+	}
a74aed
+	FIPS_POP_CONTEXT(APPROVED);
a74aed
+	gnutls_free(signature.data);
a74aed
+
a74aed
+	/* Create a signature with 2432-bit RSA and SHA-1; not approved */
a74aed
 	FIPS_PUSH_CONTEXT();
a74aed
 	ret = gnutls_privkey_sign_data(privkey, GNUTLS_DIG_SHA1, 0,
a74aed
 				       &data, &signature);
a74aed
 	if (ret < 0) {
a74aed
 		fail("gnutls_privkey_sign_data failed\n");
a74aed
 	}
a74aed
-	gnutls_free(signature.data);
a74aed
 	FIPS_POP_CONTEXT(NOT_APPROVED);
a74aed
 
a74aed
-	/* Verify a signature created with SHA-1; approved */
a74aed
+	/* Verify a signature created with 2432-bit RSA and SHA-1; approved */
a74aed
 	FIPS_PUSH_CONTEXT();
a74aed
-	ret = gnutls_pubkey_verify_data2(pubkey, GNUTLS_SIGN_RSA_SHA1, 0, &data,
a74aed
-					 &rsa2342_sha1_sig);
a74aed
+	ret = gnutls_pubkey_verify_data2(pubkey, GNUTLS_SIGN_RSA_SHA1, 0,
a74aed
+	                                 &data, &rsa2342_sha1_sig);
a74aed
 	if (ret < 0) {
a74aed
 		fail("gnutls_pubkey_verify_data2 failed\n");
a74aed
 	}
a74aed
 	FIPS_POP_CONTEXT(APPROVED);
a74aed
+	gnutls_free(signature.data);
a74aed
 	gnutls_pubkey_deinit(pubkey);
a74aed
 	gnutls_privkey_deinit(privkey);
a74aed
 
a74aed
@@ -463,15 +472,24 @@ void doit(void)
a74aed
 	rsa_import_keypair(&privkey, &pubkey, "rsa-512.pem");
a74aed
 	FIPS_POP_CONTEXT(INITIAL);
a74aed
 
a74aed
-	/* Create a signature; not approved */
a74aed
+	/* Create a signature with 512-bit RSA and SHA256; not approved */
a74aed
 	FIPS_PUSH_CONTEXT();
a74aed
 	ret = gnutls_privkey_sign_data(privkey, GNUTLS_DIG_SHA256, 0,
a74aed
 				       &data, &signature);
a74aed
 	if (ret < 0) {
a74aed
 		fail("gnutls_privkey_sign_data failed\n");
a74aed
 	}
a74aed
-	gnutls_free(signature.data);
a74aed
 	FIPS_POP_CONTEXT(NOT_APPROVED);
a74aed
+
a74aed
+	/* Verify a signature with 512-bit RSA and SHA256; not approved */
a74aed
+	FIPS_PUSH_CONTEXT();
a74aed
+	ret = gnutls_pubkey_verify_data2(pubkey, GNUTLS_SIGN_RSA_SHA256, 0,
a74aed
+	                                 &data, &signature);
a74aed
+	if (ret < 0) {
a74aed
+		fail("gnutls_pubkey_verify_data2 failed\n");
a74aed
+	}
a74aed
+	FIPS_POP_CONTEXT(NOT_APPROVED);
a74aed
+	gnutls_free(signature.data);
a74aed
 	gnutls_pubkey_deinit(pubkey);
a74aed
 	gnutls_privkey_deinit(privkey);
a74aed
 
a74aed
-- 
a74aed
2.37.3
a74aed
a74aed
From 5a745120148861d873f47c1428c8c6dcadcf109b Mon Sep 17 00:00:00 2001
a74aed
From: Richard Costa <richard.costa@suse.com>
a74aed
Date: Sat, 9 Jul 2022 00:50:21 +0000
a74aed
Subject: [PATCH] Add self-test code inside a FIPS context
a74aed
a74aed
Self-test code exercise lots of different FIPS-related code with
a74aed
side-effects. So, in order to prevent it from losing information when
a74aed
executing inside another context, we create an appropriated one.
a74aed
a74aed
If the self-test fails, then the library is placed in error state, so it
a74aed
doesn't matter for other contexts.
a74aed
a74aed
Signed-off-by: Richard Maciel Costa <richard.costa@suse.com>
a74aed
---
a74aed
 lib/fips.c        | 19 +++++++++++++++++++
a74aed
 tests/fips-test.c | 20 ++++++++++++--------
a74aed
 2 files changed, 31 insertions(+), 8 deletions(-)
a74aed
a74aed
diff --git a/lib/fips.c b/lib/fips.c
a74aed
index 31a52a990f..7d143e608e 100644
a74aed
--- a/lib/fips.c
a74aed
+++ b/lib/fips.c
a74aed
@@ -902,6 +902,16 @@ gnutls_fips140_run_self_tests(void)
a74aed
 #ifdef ENABLE_FIPS140
a74aed
 	int ret;
a74aed
 	unsigned prev_lib_state;
a74aed
+	gnutls_fips140_context_t fips_context = NULL;
a74aed
+
a74aed
+	/* Save the FIPS context, because self tests change it */
a74aed
+	if (gnutls_fips140_mode_enabled() != GNUTLS_FIPS140_DISABLED) {
a74aed
+		if (gnutls_fips140_context_init(&fips_context) < 0 ||
a74aed
+		    gnutls_fips140_push_context(fips_context) < 0) {
a74aed
+			gnutls_fips140_context_deinit(fips_context);
a74aed
+			fips_context = NULL;
a74aed
+		}
a74aed
+	}
a74aed
 
a74aed
 	/* Temporarily switch to LIB_STATE_SELFTEST as some of the
a74aed
 	 * algorithms are implemented using special constructs in
a74aed
@@ -918,6 +928,15 @@ gnutls_fips140_run_self_tests(void)
a74aed
 		/* Restore the previous library state */
a74aed
 		_gnutls_switch_lib_state(prev_lib_state);
a74aed
 	}
a74aed
+
a74aed
+	/* Restore the previous FIPS context */
a74aed
+	if (gnutls_fips140_mode_enabled() != GNUTLS_FIPS140_DISABLED && fips_context) {
a74aed
+		if (gnutls_fips140_pop_context() < 0) {
a74aed
+			_gnutls_switch_lib_state(LIB_STATE_ERROR);
a74aed
+			_gnutls_audit_log(NULL, "FIPS140-2 context restoration failed\n");
a74aed
+		}
a74aed
+		gnutls_fips140_context_deinit(fips_context);
a74aed
+	}
a74aed
 	return ret;
a74aed
 #else
a74aed
 	return 0;
a74aed
diff --git a/tests/fips-test.c b/tests/fips-test.c
a74aed
index f9bd34586a..475b739197 100644
a74aed
--- a/tests/fips-test.c
a74aed
+++ b/tests/fips-test.c
a74aed
@@ -457,8 +457,9 @@ void doit(void)
a74aed
 
a74aed
 	/* Verify a signature created with 2432-bit RSA and SHA-1; approved */
a74aed
 	FIPS_PUSH_CONTEXT();
a74aed
-	ret = gnutls_pubkey_verify_data2(pubkey, GNUTLS_SIGN_RSA_SHA1, 0,
a74aed
-	                                 &data, &rsa2342_sha1_sig);
a74aed
+	ret = gnutls_pubkey_verify_data2(pubkey, GNUTLS_SIGN_RSA_SHA1,
a74aed
+					 GNUTLS_VERIFY_ALLOW_SIGN_WITH_SHA1, &data,
a74aed
+					 &rsa2342_sha1_sig);
a74aed
 	if (ret < 0) {
a74aed
 		fail("gnutls_pubkey_verify_data2 failed\n");
a74aed
 	}
a74aed
@@ -501,6 +502,15 @@ void doit(void)
a74aed
 	}
a74aed
 	FIPS_POP_CONTEXT(APPROVED);
a74aed
 
a74aed
+        /* run self-tests manually */
a74aed
+	FIPS_PUSH_CONTEXT();
a74aed
+	ret = gnutls_rnd(GNUTLS_RND_RANDOM, key16, sizeof(key16));
a74aed
+	ret = gnutls_fips140_run_self_tests();
a74aed
+	if (ret < 0) {
a74aed
+		fail("gnutls_fips140_run_self_tests failed\n");
a74aed
+	}
a74aed
+	FIPS_POP_CONTEXT(APPROVED);
a74aed
+
a74aed
 	/* Test when FIPS140 is set to error state */
a74aed
 	_gnutls_lib_simulate_error();
a74aed
 
a74aed
@@ -544,12 +554,6 @@ void doit(void)
a74aed
 
a74aed
 	gnutls_fips140_context_deinit(fips_context);
a74aed
 
a74aed
-	/* run self-tests manually */
a74aed
-	ret = gnutls_fips140_run_self_tests();
a74aed
-	if (ret < 0) {
a74aed
-		fail("gnutls_fips140_run_self_tests failed\n");
a74aed
-	}
a74aed
-
a74aed
 	gnutls_global_deinit();
a74aed
 	return;
a74aed
 }
a74aed
-- 
a74aed
2.37.3
a74aed