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