File gnutls-FIPS-Mark-HKDF-and-AES-GCM-as-approved-when-used-in-TLS.patch of Package gnutls.28150

From eb152c2e1b3e399d5f9d118cf72227710b56b2e3 Mon Sep 17 00:00:00 2001
From: Zoltan Fridrich <zfridric@redhat.com>
Date: Fri, 1 Apr 2022 12:34:12 +0200
Subject: [PATCH 2/2] Mark HKDF and AES-GCM as approved when used in TLS

Co-authored-by: Pedro Monreal <pmgdeb@gmail.com>
Signed-off-by: Zoltan Fridrich <zfridric@redhat.com>
---
 lib/constate.c   | 22 ++++++++++++---
 lib/crypto-api.c | 70 +++++++++++++++++++++++++++++++-----------------
 lib/crypto-api.h | 12 +++++++++
 lib/secrets.c    | 20 +++++++++++---
 4 files changed, 91 insertions(+), 33 deletions(-)

diff --git a/lib/constate.c b/lib/constate.c
index b8437c7a6..b1925f693 100644
--- a/lib/constate.c
+++ b/lib/constate.c
@@ -28,6 +28,7 @@
 #include "gnutls_int.h"
 #include <constate.h>
 #include "errors.h"
+#include "fips.h"
 #include <kx.h>
 #include <algorithms.h>
 #include <num.h>
@@ -576,8 +577,15 @@ _gnutls_init_record_state(record_parameters_st * params,
 				       (ver->id == GNUTLS_SSL3) ? 1 : 0,
 #endif
 				       1 - read /*1==encrypt */ );
-	if (ret < 0 && params->cipher->id != GNUTLS_CIPHER_NULL)
+	if (ret < 0 && params->cipher->id != GNUTLS_CIPHER_NULL) {
+		_gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
 		return gnutls_assert_val(ret);
+	}
+	
+	if (is_cipher_algo_allowed(params->cipher->id))
+		_gnutls_switch_fips_state(GNUTLS_FIPS140_OP_APPROVED);
+	else
+		_gnutls_switch_fips_state(GNUTLS_FIPS140_OP_NOT_APPROVED);
 
 	return 0;
 }
@@ -1290,10 +1298,16 @@ _tls13_init_record_state(gnutls_cipher_algorithm_t algo, record_state_st *state)
 	key.data = state->key;
 	key.size = state->key_size;
 
-	ret = _gnutls_aead_cipher_init(&state->ctx.aead,
-				       algo, &key);
-	if (ret < 0)
+	ret = _gnutls_aead_cipher_init(&state->ctx.aead, algo, &key);
+	if (ret < 0) {
+		_gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
 		return gnutls_assert_val(ret);
+	}
+
+	if (is_cipher_algo_allowed(algo))
+		_gnutls_switch_fips_state(GNUTLS_FIPS140_OP_APPROVED);
+	else
+		_gnutls_switch_fips_state(GNUTLS_FIPS140_OP_NOT_APPROVED);
 
 	state->aead_tag_size = gnutls_cipher_get_tag_size(algo);
 	state->is_aead = 1;
diff --git a/lib/crypto-api.c b/lib/crypto-api.c
index e1f40408e..af18e230f 100644
--- a/lib/crypto-api.c
+++ b/lib/crypto-api.c
@@ -1694,6 +1694,28 @@ void gnutls_aead_cipher_deinit(gnutls_aead_cipher_hd_t handle)
 
 extern gnutls_crypto_kdf_st _gnutls_kdf_ops;
 
+/* Same as @gnutls_hkdf_extract but without changing FIPS context */
+int
+_gnutls_hkdf_extract(gnutls_mac_algorithm_t mac,
+		    const gnutls_datum_t *key,
+		    const gnutls_datum_t *salt,
+		    void *output)
+{
+	/* MD5 is only allowed internally for TLS */
+	if (!is_mac_algo_allowed(mac)) {
+		_gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
+		return gnutls_assert_val(GNUTLS_E_UNWANTED_ALGORITHM);
+	}
+
+	/* We don't check whether MAC is approved, because HKDF is
+	 * only approved in TLS, which is handled separately. */
+
+	return _gnutls_kdf_ops.hkdf_extract(mac, key->data, key->size,
+					    salt ? salt->data : NULL,
+					    salt ? salt->size : 0,
+					    output);
+}
+
 /**
  * gnutls_hkdf_extract:
  * @mac: the mac algorithm used internally
@@ -1716,6 +1738,22 @@ gnutls_hkdf_extract(gnutls_mac_algorithm_t mac,
 {
 	int ret;
 
+	ret = _gnutls_hkdf_extract(mac, key, salt, output);
+	if (ret < 0)
+		_gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
+	else
+		_gnutls_switch_fips_state(GNUTLS_FIPS140_OP_NOT_APPROVED);
+
+	return ret;
+}
+
+/* Same as @gnutls_hkdf_expand but without changing FIPS context */
+int
+_gnutls_hkdf_expand(gnutls_mac_algorithm_t mac,
+		   const gnutls_datum_t *key,
+		   const gnutls_datum_t *info,
+		   void *output, size_t length)
+{
 	/* MD5 is only allowed internally for TLS */
 	if (!is_mac_algo_allowed(mac)) {
 		_gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
@@ -1725,16 +1763,9 @@ gnutls_hkdf_extract(gnutls_mac_algorithm_t mac,
 	/* We don't check whether MAC is approved, because HKDF is
 	 * only approved in TLS, which is handled separately. */
 
-	ret = _gnutls_kdf_ops.hkdf_extract(mac, key->data, key->size,
-					   salt ? salt->data : NULL,
-					   salt ? salt->size : 0,
-					   output);
-	if (ret < 0) {
-		_gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
-	} else {
-		_gnutls_switch_fips_state(GNUTLS_FIPS140_OP_NOT_APPROVED);
-	}
-	return ret;
+	return _gnutls_kdf_ops.hkdf_expand(mac, key->data, key->size,
+					  info->data, info->size,
+					  output, length);
 }
 
 /**
@@ -1761,23 +1792,12 @@ gnutls_hkdf_expand(gnutls_mac_algorithm_t mac,
 {
 	int ret;
 
-	/* MD5 is only allowed internally for TLS */
-	if (!is_mac_algo_allowed(mac)) {
-		_gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
-		return gnutls_assert_val(GNUTLS_E_UNWANTED_ALGORITHM);
-	}
-
-	/* We don't check whether MAC is approved, because HKDF is
-	 * only approved in TLS, which is handled separately. */
-
-	ret = _gnutls_kdf_ops.hkdf_expand(mac, key->data, key->size,
-					  info->data, info->size,
-					  output, length);
-	if (ret < 0) {
+	ret = _gnutls_hkdf_expand(mac, key, info, output, length);
+	if (ret < 0)
 		_gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
-	} else {
+	else
 		_gnutls_switch_fips_state(GNUTLS_FIPS140_OP_NOT_APPROVED);
-	}
+
 	return ret;
 }
 
diff --git a/lib/crypto-api.h b/lib/crypto-api.h
index d539534da..9ed760081 100644
--- a/lib/crypto-api.h
+++ b/lib/crypto-api.h
@@ -50,4 +50,16 @@ void _gnutls_aead_cipher_deinit(gnutls_aead_cipher_hd_t handle)
 	_gnutls_cipher_deinit(&h->ctx_enc);
 }
 
+int
+_gnutls_hkdf_extract(gnutls_mac_algorithm_t mac,
+		     const gnutls_datum_t *key,
+		     const gnutls_datum_t *salt,
+		     void *output);
+
+int
+_gnutls_hkdf_expand(gnutls_mac_algorithm_t mac,
+		    const gnutls_datum_t *key,
+		    const gnutls_datum_t *info,
+		    void *output, size_t length);
+
 #endif /* GNUTLS_LIB_CRYPTO_API_H */
diff --git a/lib/secrets.c b/lib/secrets.c
index 8ae6b552a..728876ede 100644
--- a/lib/secrets.c
+++ b/lib/secrets.c
@@ -24,6 +24,8 @@
  */
 
 #include <config.h>
+#include "crypto-api.h"
+#include "fips.h"
 #include "gnutls_int.h"
 #include "secrets.h"
 
@@ -67,15 +69,22 @@ int _tls13_update_secret(gnutls_session_t session, const uint8_t *key, size_t ke
 {
 	gnutls_datum_t _key;
 	gnutls_datum_t salt;
+	int ret;
 
 	_key.data = (void *)key;
 	_key.size = key_size;
 	salt.data = (void *)session->key.proto.tls13.temp_secret;
 	salt.size = session->key.proto.tls13.temp_secret_size;
 
-	return gnutls_hkdf_extract(session->security_parameters.prf->id,
-				   &_key, &salt,
-				   session->key.proto.tls13.temp_secret);
+	ret = _gnutls_hkdf_extract(session->security_parameters.prf->id,
+			           &_key, &salt,
+			           session->key.proto.tls13.temp_secret);
+	if (ret < 0)
+		_gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
+	else
+		_gnutls_switch_fips_state(GNUTLS_FIPS140_OP_APPROVED);
+
+	return ret;
 }
 
 /* Derive-Secret(Secret, Label, Messages) */
@@ -161,10 +170,13 @@ int _tls13_expand_secret2(const mac_entry_st *prf,
 	info.data = str.data;
 	info.size = str.length;
 
-	ret = gnutls_hkdf_expand(prf->id, &key, &info, out, out_size);
+	ret = _gnutls_hkdf_expand(prf->id, &key, &info, out, out_size);
 	if (ret < 0) {
+		_gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
 		gnutls_assert();
 		goto cleanup;
+	} else {
+		_gnutls_switch_fips_state(GNUTLS_FIPS140_OP_APPROVED);
 	}
 
 #if 0
-- 
2.35.1

openSUSE Build Service is sponsored by