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