Commit 379a6485 authored by Milan Broz's avatar Milan Broz
Browse files

Use "IEEE" variant for SM4-XTS in OpenSSL backend

OpenSSL defines two versions of SM4-XTS; we have to use IEEE
version to match kernel.
Otherwise encryptin/decryption in userspace can corrupt data.

Unfortunately, this change could make some existing configurations
no longer usable.
parent ea34c8ae
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -346,6 +346,7 @@ AC_DEFUN([CONFIGURE_OPENSSL], [
	saved_LIBS=$LIBS
	AC_CHECK_DECLS([OSSL_get_max_threads], [], [], [#include <openssl/thread.h>])
	AC_CHECK_DECLS([OSSL_KDF_PARAM_ARGON2_VERSION], [use_internal_argon2=0], [], [#include <openssl/core_names.h>])
	AC_CHECK_DECLS([OSSL_CIPHER_PARAM_XTS_STANDARD], [], [], [#include <openssl/core_names.h>])
	LIBS=$saved_LIBS
])

+34 −2
Original line number Diff line number Diff line
@@ -716,20 +716,47 @@ static void _cipher_destroy(EVP_CIPHER_CTX **hd_enc, EVP_CIPHER_CTX **hd_dec, co
	*cipher_type = NULL;
}

/*
 * SM4-XTS can have two variants of tweak calculation:
 *     "GB": GB/T 17964-2021 tweak multiplication
 *   "IEEE": IEEE Std 1619-2007 tweak multiplication (as used by AES-XTS)
 *
 * "GB" is the default, but we need to use mode implemented by the kernel here (IEEE).
 */
static int _cipher_xts_ieee(EVP_CIPHER_CTX **hd_enc, EVP_CIPHER_CTX **hd_dec)
{
#if OPENSSL3_API && HAVE_DECL_OSSL_CIPHER_PARAM_XTS_STANDARD
	OSSL_PARAM p[] = {
		OSSL_PARAM_construct_utf8_string(OSSL_CIPHER_PARAM_XTS_STANDARD, CONST_CAST(char*)"IEEE", 0),
		OSSL_PARAM_construct_end()
	};

	if (EVP_CIPHER_CTX_set_params(*hd_enc, p) != 1 ||
	    EVP_CIPHER_CTX_set_params(*hd_dec, p) != 1)
		return -EINVAL;
#else
	UNUSED(hd_enc);
	UNUSED(hd_dec);
#endif
	return 0;
}

static int _cipher_init(EVP_CIPHER_CTX **hd_enc, EVP_CIPHER_CTX **hd_dec, const EVP_CIPHER **cipher_type, const char *name,
			const char *mode, const void *key, size_t key_length, size_t *iv_length)
{
	char cipher_name[256];
	const EVP_CIPHER *type;
	int r, key_bits;
	bool set_xts_ieee = false;

	key_bits = key_length * 8;
	if (!strcmp(mode, "xts"))
		key_bits /= 2;

	if ((!strcmp(name, "sm4")) && key_bits == 128)
	if ((!strcmp(name, "sm4")) && key_bits == 128) {
		set_xts_ieee = true;
		r = snprintf(cipher_name, sizeof(cipher_name), "%s-%s", name, mode);
	else
	} else
		r = snprintf(cipher_name, sizeof(cipher_name), "%s-%d-%s", name, key_bits, mode);
	if (r < 0 || (size_t)r >= sizeof(cipher_name))
		return -EINVAL;
@@ -758,6 +785,11 @@ static int _cipher_init(EVP_CIPHER_CTX **hd_enc, EVP_CIPHER_CTX **hd_dec, const
		return -EINVAL;
	}

	if (set_xts_ieee && _cipher_xts_ieee(hd_enc, hd_dec) < 0) {
		_cipher_destroy(hd_enc, hd_dec, &type);
		return -EINVAL;
	}

	if (EVP_CIPHER_CTX_set_padding(*hd_enc, 0) != 1 ||
	    EVP_CIPHER_CTX_set_padding(*hd_dec, 0) != 1) {
		_cipher_destroy(hd_enc, hd_dec, &type);
+3 −0
Original line number Diff line number Diff line
@@ -499,6 +499,9 @@ elif get_option('crypto-backend') == 'openssl'
    if _have_ossl_argon2
        use_internal_argon2 = false
    endif
    conf.set10('HAVE_DECL_OSSL_CIPHER_PARAM_XTS_STANDARD',
        cc.has_header_symbol('openssl/core_names.h', 'OSSL_CIPHER_PARAM_XTS_STANDARD',
            dependencies: crypto_backend_library))
elif get_option('crypto-backend') == 'nss'
    if get_option('fips')
        error('nss crypto backend is not supported with FIPS enabled')