Blame SOURCES/gnutls-3.7.8-xts-key-check.patch

a74aed
diff --color -ruNp a/lib/accelerated/x86/aes-xts-x86-aesni.c b/lib/accelerated/x86/aes-xts-x86-aesni.c
a74aed
--- a/lib/accelerated/x86/aes-xts-x86-aesni.c	2022-03-02 12:38:09.000000000 +0100
a74aed
+++ b/lib/accelerated/x86/aes-xts-x86-aesni.c	2022-11-07 14:12:38.476982750 +0100
a74aed
@@ -73,7 +73,6 @@ x86_aes_xts_cipher_setkey(void *_ctx, co
a74aed
 	/* Check key block according to FIPS-140-2 IG A.9 */
a74aed
 	if (_gnutls_fips_mode_enabled()){
a74aed
 		if (gnutls_memcmp(key, key + (keysize / 2), keysize / 2) == 0) {
a74aed
-			_gnutls_switch_lib_state(LIB_STATE_ERROR);
a74aed
 			return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
a74aed
 		}
a74aed
 	}
a74aed
diff --color -ruNp a/lib/nettle/cipher.c b/lib/nettle/cipher.c
a74aed
--- a/lib/nettle/cipher.c	2022-11-07 14:10:13.672085930 +0100
a74aed
+++ b/lib/nettle/cipher.c	2022-11-07 14:12:38.477982770 +0100
a74aed
@@ -448,12 +448,14 @@ _gcm_decrypt(struct nettle_cipher_ctx *c
a74aed
 		    length, dst, src);
a74aed
 }
a74aed
 
a74aed
-static void _des_set_key(struct des_ctx *ctx, const uint8_t *key)
a74aed
+static void
a74aed
+_des_set_key(struct des_ctx *ctx, const uint8_t *key)
a74aed
 {
a74aed
 	des_set_key(ctx, key);
a74aed
 }
a74aed
 
a74aed
-static void _des3_set_key(struct des3_ctx *ctx, const uint8_t *key)
a74aed
+static void
a74aed
+_des3_set_key(struct des3_ctx *ctx, const uint8_t *key)
a74aed
 {
a74aed
 	des3_set_key(ctx, key);
a74aed
 }
a74aed
@@ -477,50 +479,6 @@ _cfb8_decrypt(struct nettle_cipher_ctx *
a74aed
 }
a74aed
 
a74aed
 static void
a74aed
-_xts_aes128_set_encrypt_key(struct xts_aes128_key *xts_key,
a74aed
-			    const uint8_t *key)
a74aed
-{
a74aed
-	if (_gnutls_fips_mode_enabled() &&
a74aed
-	    gnutls_memcmp(key, key + AES128_KEY_SIZE, AES128_KEY_SIZE) == 0)
a74aed
-		_gnutls_switch_lib_state(LIB_STATE_ERROR);
a74aed
-
a74aed
-	xts_aes128_set_encrypt_key(xts_key, key);
a74aed
-}
a74aed
-
a74aed
-static void
a74aed
-_xts_aes128_set_decrypt_key(struct xts_aes128_key *xts_key,
a74aed
-			    const uint8_t *key)
a74aed
-{
a74aed
-	if (_gnutls_fips_mode_enabled() &&
a74aed
-	    gnutls_memcmp(key, key + AES128_KEY_SIZE, AES128_KEY_SIZE) == 0)
a74aed
-		_gnutls_switch_lib_state(LIB_STATE_ERROR);
a74aed
-
a74aed
-	xts_aes128_set_decrypt_key(xts_key, key);
a74aed
-}
a74aed
-
a74aed
-static void
a74aed
-_xts_aes256_set_encrypt_key(struct xts_aes256_key *xts_key,
a74aed
-			    const uint8_t *key)
a74aed
-{
a74aed
-	if (_gnutls_fips_mode_enabled() &&
a74aed
-	    gnutls_memcmp(key, key + AES256_KEY_SIZE, AES256_KEY_SIZE) == 0)
a74aed
-		_gnutls_switch_lib_state(LIB_STATE_ERROR);
a74aed
-
a74aed
-	xts_aes256_set_encrypt_key(xts_key, key);
a74aed
-}
a74aed
-
a74aed
-static void
a74aed
-_xts_aes256_set_decrypt_key(struct xts_aes256_key *xts_key,
a74aed
-			    const uint8_t *key)
a74aed
-{
a74aed
-	if (_gnutls_fips_mode_enabled() &&
a74aed
-	    gnutls_memcmp(key, key + AES256_KEY_SIZE, AES256_KEY_SIZE) == 0)
a74aed
-		_gnutls_switch_lib_state(LIB_STATE_ERROR);
a74aed
-
a74aed
-	xts_aes256_set_decrypt_key(xts_key, key);
a74aed
-}
a74aed
-
a74aed
-static void
a74aed
 _xts_aes128_encrypt(struct nettle_cipher_ctx *ctx, size_t length, uint8_t * dst,
a74aed
 		    const uint8_t * src)
a74aed
 {
a74aed
@@ -1041,8 +999,8 @@ static const struct nettle_cipher_st bui
a74aed
 	   .ctx_size = sizeof(struct xts_aes128_key),
a74aed
 	   .encrypt = _xts_aes128_encrypt,
a74aed
 	   .decrypt = _xts_aes128_decrypt,
a74aed
-	   .set_encrypt_key = (nettle_set_key_func*)_xts_aes128_set_encrypt_key,
a74aed
-	   .set_decrypt_key = (nettle_set_key_func*)_xts_aes128_set_decrypt_key,
a74aed
+	   .set_encrypt_key = (nettle_set_key_func*)xts_aes128_set_encrypt_key,
a74aed
+	   .set_decrypt_key = (nettle_set_key_func*)xts_aes128_set_decrypt_key,
a74aed
 	   .max_iv_size = AES_BLOCK_SIZE,
a74aed
 	},
a74aed
 	{  .algo = GNUTLS_CIPHER_AES_256_XTS,
a74aed
@@ -1052,8 +1010,8 @@ static const struct nettle_cipher_st bui
a74aed
 	   .ctx_size = sizeof(struct xts_aes256_key),
a74aed
 	   .encrypt = _xts_aes256_encrypt,
a74aed
 	   .decrypt = _xts_aes256_decrypt,
a74aed
-	   .set_encrypt_key = (nettle_set_key_func*)_xts_aes256_set_encrypt_key,
a74aed
-	   .set_decrypt_key = (nettle_set_key_func*)_xts_aes256_set_decrypt_key,
a74aed
+	   .set_encrypt_key = (nettle_set_key_func*)xts_aes256_set_encrypt_key,
a74aed
+	   .set_decrypt_key = (nettle_set_key_func*)xts_aes256_set_decrypt_key,
a74aed
 	   .max_iv_size = AES_BLOCK_SIZE,
a74aed
 	},
a74aed
 	{  .algo = GNUTLS_CIPHER_AES_128_SIV,
a74aed
@@ -1144,6 +1102,21 @@ wrap_nettle_cipher_setkey(void *_ctx, co
a74aed
 		return 0;
a74aed
 	}
a74aed
 
a74aed
+	switch (ctx->cipher->algo) {
a74aed
+	case GNUTLS_CIPHER_AES_128_XTS:
a74aed
+		if (_gnutls_fips_mode_enabled() &&
a74aed
+		    gnutls_memcmp(key, (char *)key + AES128_KEY_SIZE, AES128_KEY_SIZE) == 0)
a74aed
+			return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
a74aed
+		break;
a74aed
+	case GNUTLS_CIPHER_AES_256_XTS:
a74aed
+		if (_gnutls_fips_mode_enabled() &&
a74aed
+		    gnutls_memcmp(key, (char *)key + AES256_KEY_SIZE, AES256_KEY_SIZE) == 0)
a74aed
+			return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
a74aed
+		break;
a74aed
+	default:
a74aed
+		break;
a74aed
+	}
a74aed
+
a74aed
 	if (ctx->enc)
a74aed
 		ctx->cipher->set_encrypt_key(ctx->ctx_ptr, key);
a74aed
 	else
a74aed
diff --color -ruNp a/tests/Makefile.am b/tests/Makefile.am
a74aed
--- a/tests/Makefile.am	2022-11-07 14:10:13.836089211 +0100
a74aed
+++ b/tests/Makefile.am	2022-11-07 14:12:38.478982790 +0100
a74aed
@@ -233,7 +233,7 @@ ctests += mini-record-2 simple gnutls_hm
a74aed
 	 tls13-without-timeout-func buffer status-request-revoked \
a74aed
 	 set_x509_ocsp_multi_cli kdf-api keylog-func handshake-write \
a74aed
 	 x509cert-dntypes id-on-xmppAddr tls13-compat-mode ciphersuite-name \
a74aed
-	 x509-upnconstraint pkcs7-verify-double-free \
a74aed
+	 x509-upnconstraint xts-key-check pkcs7-verify-double-free \
a74aed
 	 fips-rsa-sizes
a74aed
 
a74aed
 ctests += tls-channel-binding
a74aed
diff --color -ruNp a/tests/xts-key-check.c b/tests/xts-key-check.c
a74aed
--- a/tests/xts-key-check.c	1970-01-01 01:00:00.000000000 +0100
a74aed
+++ b/tests/xts-key-check.c	2022-11-07 14:12:38.478982790 +0100
a74aed
@@ -0,0 +1,78 @@
a74aed
+/*
a74aed
+ * Copyright (C) 2022 Red Hat, Inc.
a74aed
+ *
a74aed
+ * Author: Zoltan Fridrich
a74aed
+ *
a74aed
+ * This file is part of GnuTLS.
a74aed
+ *
a74aed
+ * GnuTLS is free software: you can redistribute it and/or modify it
a74aed
+ * under the terms of the GNU General Public License as published by
a74aed
+ * the Free Software Foundation, either version 3 of the License, or
a74aed
+ * (at your option) any later version.
a74aed
+ *
a74aed
+ * GnuTLS is distributed in the hope that it will be useful, but
a74aed
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
a74aed
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
a74aed
+ * General Public License for more details.
a74aed
+ *
a74aed
+ * You should have received a copy of the GNU General Public License
a74aed
+ * along with GnuTLS. If not, see <https://www.gnu.org/licenses/>.
a74aed
+ */
a74aed
+
a74aed
+#ifdef HAVE_CONFIG_H
a74aed
+#include <config.h>
a74aed
+#endif
a74aed
+
a74aed
+#include <gnutls/crypto.h>
a74aed
+
a74aed
+#include "utils.h"
a74aed
+
a74aed
+static void test_xts_check(gnutls_cipher_algorithm_t alg)
a74aed
+{
a74aed
+	int ret;
a74aed
+	gnutls_cipher_hd_t ctx;
a74aed
+	gnutls_datum_t key, iv;
a74aed
+
a74aed
+	iv.size = gnutls_cipher_get_iv_size(alg);
a74aed
+	iv.data = gnutls_malloc(iv.size);
a74aed
+	if (iv.data == NULL)
a74aed
+		fail("Error: %s\n", gnutls_strerror(GNUTLS_E_MEMORY_ERROR));
a74aed
+	gnutls_memset(iv.data, 0xf0, iv.size);
a74aed
+
a74aed
+	key.size = gnutls_cipher_get_key_size(alg);
a74aed
+	key.data = gnutls_malloc(key.size);
a74aed
+	if (key.data == NULL) {
a74aed
+		gnutls_free(iv.data);
a74aed
+		fail("Error: %s\n", gnutls_strerror(GNUTLS_E_MEMORY_ERROR));
a74aed
+	}
a74aed
+	gnutls_memset(key.data, 0xf0, key.size);
a74aed
+
a74aed
+	ret = gnutls_cipher_init(&ctx, alg, &key, &iv;;
a74aed
+	if (ret == GNUTLS_E_SUCCESS) {
a74aed
+		gnutls_cipher_deinit(ctx);
a74aed
+		gnutls_free(iv.data);
a74aed
+		gnutls_free(key.data);
a74aed
+		fail("cipher initialization should fail for key1 == key2\n");
a74aed
+	}
a74aed
+
a74aed
+	key.data[0] = 0xff;
a74aed
+
a74aed
+	ret = gnutls_cipher_init(&ctx, alg, &key, &iv;;
a74aed
+	gnutls_free(iv.data);
a74aed
+	gnutls_free(key.data);
a74aed
+
a74aed
+	if (ret == GNUTLS_E_SUCCESS)
a74aed
+		gnutls_cipher_deinit(ctx);
a74aed
+	else
a74aed
+		fail("cipher initialization should succeed with key1 != key2"
a74aed
+		     "\n%s\n", gnutls_strerror(ret));
a74aed
+}
a74aed
+
a74aed
+void doit(void)
a74aed
+{
a74aed
+	if (!gnutls_fips140_mode_enabled())
a74aed
+		exit(77);
a74aed
+
a74aed
+	test_xts_check(GNUTLS_CIPHER_AES_128_XTS);
a74aed
+	test_xts_check(GNUTLS_CIPHER_AES_256_XTS);
a74aed
+}