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