7e1ffc
From 3bd42dc88ff062bf9ede2b593e1ad1afa6f68f62 Mon Sep 17 00:00:00 2001
7e1ffc
From: Daiki Ueno <ueno@gnu.org>
7e1ffc
Date: Wed, 16 Nov 2022 23:02:13 +0900
7e1ffc
Subject: [PATCH] nettle: mark non-compliant RSA-PSS salt length to be
7e1ffc
 not-approved
7e1ffc
7e1ffc
According to FIPS 186-5 5.4, the salt length must be in the range
7e1ffc
between 0 and the hash length inclusive.  While the use of those salt
7e1ffc
lengths is still allowed for compatibility, it is reported as
7e1ffc
non-approved operation through FIPS service indicator.
7e1ffc
7e1ffc
Signed-off-by: Daiki Ueno <ueno@gnu.org>
7e1ffc
---
7e1ffc
 lib/nettle/pk.c     |  9 ++++++++
7e1ffc
 tests/rsa-rsa-pss.c | 54 ++++++++++++++++++++++++++++++++++++---------
7e1ffc
 2 files changed, 53 insertions(+), 10 deletions(-)
7e1ffc
7e1ffc
diff --git a/lib/nettle/pk.c b/lib/nettle/pk.c
7e1ffc
index c098e2aa45..7732e90542 100644
7e1ffc
--- a/lib/nettle/pk.c
7e1ffc
+++ b/lib/nettle/pk.c
7e1ffc
@@ -1316,6 +1316,15 @@ _wrap_nettle_pk_sign(gnutls_pk_algorithm_t algo,
7e1ffc
 
7e1ffc
 			mpz_init(s);
7e1ffc
 
7e1ffc
+			me = hash_to_entry(sign_params->rsa_pss_dig);
7e1ffc
+
7e1ffc
+			/* According to FIPS 186-5 5.4, the salt length must be
7e1ffc
+			 * in the range between 0 and the hash length inclusive.
7e1ffc
+			 */
7e1ffc
+			if (sign_params->salt_size > _gnutls_mac_get_algo_len(me)) {
7e1ffc
+				not_approved = true;
7e1ffc
+			}
7e1ffc
+
7e1ffc
 			ret =
7e1ffc
 			    _rsa_pss_sign_digest_tr(sign_params->rsa_pss_dig,
7e1ffc
 						    &pub, &priv,
7e1ffc
diff --git a/tests/rsa-rsa-pss.c b/tests/rsa-rsa-pss.c
7e1ffc
index 19a175b722..d7799c1961 100644
7e1ffc
--- a/tests/rsa-rsa-pss.c
7e1ffc
+++ b/tests/rsa-rsa-pss.c
7e1ffc
@@ -46,6 +46,8 @@ const gnutls_datum_t raw_data = {
7e1ffc
 	11
7e1ffc
 };
7e1ffc
 
7e1ffc
+static gnutls_fips140_context_t fips_context;
7e1ffc
+
7e1ffc
 static void inv_sign_check(unsigned sigalgo,
7e1ffc
 			   gnutls_privkey_t privkey, int exp_error)
7e1ffc
 {
7e1ffc
@@ -86,13 +88,16 @@ static void inv_encryption_check(gnutls_pk_algorithm_t algorithm,
7e1ffc
 
7e1ffc
 static void sign_verify_data(unsigned sigalgo, gnutls_privkey_t privkey,
7e1ffc
 			     unsigned int sign_flags, unsigned int verify_flags,
7e1ffc
-			     int sign_exp_error, int verify_exp_error)
7e1ffc
+			     int sign_exp_error, int verify_exp_error,
7e1ffc
+			     gnutls_fips140_operation_state_t sign_exp_state)
7e1ffc
 {
7e1ffc
 	int ret;
7e1ffc
 	gnutls_datum_t signature = { NULL, 0 };
7e1ffc
 
7e1ffc
+	fips_push_context(fips_context);
7e1ffc
 	ret = gnutls_privkey_sign_data2(privkey, sigalgo, sign_flags,
7e1ffc
 					&raw_data, &signature);
7e1ffc
+	fips_pop_context(fips_context, sign_exp_state);
7e1ffc
 	if (ret != sign_exp_error)
7e1ffc
 		fail("gnutls_x509_privkey_sign_data returned unexpected error: %s\n",
7e1ffc
 		     gnutls_strerror(ret));
7e1ffc
@@ -180,11 +185,16 @@ void doit(void)
7e1ffc
 	if (debug)
7e1ffc
 		gnutls_global_set_log_level(4711);
7e1ffc
 
7e1ffc
+	assert(gnutls_fips140_context_init(&fips_context) >= 0);
7e1ffc
+
7e1ffc
 	prepare_keys(&pkey_rsa_pss, &pkey_rsa, GNUTLS_DIG_SHA256, 32);
7e1ffc
 
7e1ffc
-	sign_verify_data(GNUTLS_SIGN_RSA_PSS_SHA256, pkey_rsa_pss, 0, 0, 0, 0);
7e1ffc
-	sign_verify_data(GNUTLS_SIGN_RSA_PSS_RSAE_SHA256, pkey_rsa, 0, 0, 0, 0);
7e1ffc
-	sign_verify_data(GNUTLS_SIGN_RSA_PSS_SHA256, pkey_rsa, 0, 0, 0, 0);
7e1ffc
+	sign_verify_data(GNUTLS_SIGN_RSA_PSS_SHA256, pkey_rsa_pss, 0, 0, 0, 0,
7e1ffc
+			 GNUTLS_FIPS140_OP_APPROVED);
7e1ffc
+	sign_verify_data(GNUTLS_SIGN_RSA_PSS_RSAE_SHA256, pkey_rsa, 0, 0, 0, 0,
7e1ffc
+			 GNUTLS_FIPS140_OP_APPROVED);
7e1ffc
+	sign_verify_data(GNUTLS_SIGN_RSA_PSS_SHA256, pkey_rsa, 0, 0, 0, 0,
7e1ffc
+			 GNUTLS_FIPS140_OP_APPROVED);
7e1ffc
 
7e1ffc
 	if (debug)
7e1ffc
 		success("success signing with RSA-PSS-SHA256\n");
7e1ffc
@@ -213,41 +223,65 @@ void doit(void)
7e1ffc
 	gnutls_privkey_deinit(pkey_rsa_pss);
7e1ffc
 	gnutls_privkey_deinit(pkey_rsa);
7e1ffc
 
7e1ffc
+	/* Restrict key to use salt length larger than hash output
7e1ffc
+	 * length (not approved in FIPS).
7e1ffc
+	 */
7e1ffc
+	prepare_keys(&pkey_rsa_pss, &pkey_rsa, GNUTLS_DIG_SHA256, 33);
7e1ffc
+
7e1ffc
+	sign_verify_data(GNUTLS_SIGN_RSA_PSS_SHA256, pkey_rsa_pss, 0, 0, 0, 0,
7e1ffc
+			 GNUTLS_FIPS140_OP_NOT_APPROVED);
7e1ffc
+
7e1ffc
+	gnutls_privkey_deinit(pkey_rsa_pss);
7e1ffc
+	gnutls_privkey_deinit(pkey_rsa);
7e1ffc
+
7e1ffc
 	/* Use the mismatched salt length with the digest length */
7e1ffc
 	prepare_keys(&pkey_rsa_pss, &pkey_rsa, GNUTLS_DIG_SHA256, 48);
7e1ffc
 
7e1ffc
 	sign_verify_data(GNUTLS_SIGN_RSA_PSS_RSAE_SHA256, pkey_rsa_pss,
7e1ffc
-			 0, 0, 0, 0);
7e1ffc
+			 0, 0, 0, 0, GNUTLS_FIPS140_OP_NOT_APPROVED);
7e1ffc
 	sign_verify_data(GNUTLS_SIGN_RSA_PSS_SHA256, pkey_rsa_pss,
7e1ffc
 			 GNUTLS_PRIVKEY_FLAG_RSA_PSS_FIXED_SALT_LENGTH,
7e1ffc
 			 0,
7e1ffc
 			 GNUTLS_E_CONSTRAINT_ERROR,
7e1ffc
-			 0);
7e1ffc
+			 0,
7e1ffc
+			 /* The error is caught before calling the actual
7e1ffc
+			  * signing operation.
7e1ffc
+			  */
7e1ffc
+			 GNUTLS_FIPS140_OP_INITIAL);
7e1ffc
 	sign_verify_data(GNUTLS_SIGN_RSA_PSS_SHA256, pkey_rsa_pss,
7e1ffc
 			 0,
7e1ffc
 			 GNUTLS_VERIFY_RSA_PSS_FIXED_SALT_LENGTH,
7e1ffc
 			 0,
7e1ffc
-			 GNUTLS_E_PK_SIG_VERIFY_FAILED);
7e1ffc
+			 GNUTLS_E_PK_SIG_VERIFY_FAILED,
7e1ffc
+			 GNUTLS_FIPS140_OP_NOT_APPROVED);
7e1ffc
 
7e1ffc
 	assert(gnutls_x509_spki_init(&spki)>=0);
7e1ffc
 	gnutls_x509_spki_set_rsa_pss_params(spki, GNUTLS_DIG_SHA256, 48);
7e1ffc
 	assert(gnutls_privkey_set_spki(pkey_rsa, spki, 0)>=0);
7e1ffc
 
7e1ffc
-	sign_verify_data(GNUTLS_SIGN_RSA_PSS_RSAE_SHA256, pkey_rsa, 0, 0, 0, 0);
7e1ffc
+	sign_verify_data(GNUTLS_SIGN_RSA_PSS_RSAE_SHA256, pkey_rsa, 0, 0, 0, 0,
7e1ffc
+			 GNUTLS_FIPS140_OP_NOT_APPROVED);
7e1ffc
 	sign_verify_data(GNUTLS_SIGN_RSA_PSS_RSAE_SHA256, pkey_rsa,
7e1ffc
 			 GNUTLS_PRIVKEY_FLAG_RSA_PSS_FIXED_SALT_LENGTH,
7e1ffc
 			 0,
7e1ffc
 			 GNUTLS_E_CONSTRAINT_ERROR,
7e1ffc
-			 0);
7e1ffc
+			 0,
7e1ffc
+			 /* The error is caught before calling the actual
7e1ffc
+			  * signing operation.
7e1ffc
+			  */
7e1ffc
+			 GNUTLS_FIPS140_OP_INITIAL);
7e1ffc
 	sign_verify_data(GNUTLS_SIGN_RSA_PSS_RSAE_SHA256, pkey_rsa,
7e1ffc
 			 0,
7e1ffc
 			 GNUTLS_VERIFY_RSA_PSS_FIXED_SALT_LENGTH,
7e1ffc
 			 0,
7e1ffc
-			 GNUTLS_E_PK_SIG_VERIFY_FAILED);
7e1ffc
+			 GNUTLS_E_PK_SIG_VERIFY_FAILED,
7e1ffc
+			 GNUTLS_FIPS140_OP_NOT_APPROVED);
7e1ffc
 
7e1ffc
 	gnutls_privkey_deinit(pkey_rsa_pss);
7e1ffc
 	gnutls_privkey_deinit(pkey_rsa);
7e1ffc
 	gnutls_x509_spki_deinit(spki);
7e1ffc
 
7e1ffc
+	gnutls_fips140_context_deinit(fips_context);
7e1ffc
+
7e1ffc
 	gnutls_global_deinit();
7e1ffc
 }
7e1ffc
-- 
7e1ffc
2.38.1
7e1ffc