Skip to contentSkip to conversation

fscrypt: fix derivation of SipHash keys on big endian CPUs

PATCH Superseded Eric Biggers 1 participant 2 messages May 27, 2021 – Jun 5, 2021

Subsystems (2)

v1 of 2 Superseded Latest is v2 →

lore
Share & tools
lore

Eric Biggers

author maintainer
#0 lore raw

PATCH 1/1 fscrypt: fix derivation of SipHash keys on big endian CPUs

From: Eric Biggers <[email protected]>

Typically, the cryptographic APIs that fscrypt uses take keys as byte arrays, which avoids endianness issues. However, siphash_key_t is an exception. It is defined as 'u64 key[2];', i.e. the 128-bit key is expected to be given directly as two 64-bit words in CPU endianness.

fscrypt_derive_dirhash_key() forgot to take this into account. Therefore, the SipHash keys used to index encrypted+casefolded directories differ on big endian vs. little endian platforms. This makes such directories non-portable between these platforms.

Fix this by always using the little endian order. This is a breaking change for big endian platforms, but this should be fine in practice since the encrypt+casefold support isn't known to actually be used on any big endian platforms yet.

Fixes aa408f835d02 ("fscrypt: derive dirhash key for casefolded directories")
Cc <[email protected]> # v5.6+
---
 fs/crypto/keysetup.c | 10 ++++++++++
 1 file changed, 10 insertions(+)
fs/crypto/keysetup.c +10 -0
index 261293fb7097..4d98377c07a7 100644
@@ -221,6 +221,16 @@ int fscrypt_derive_dirhash_key(struct fscrypt_info *ci,
 				  sizeof(ci->ci_dirhash_key));
 	if (err)
 		return err;
+
+	/*
+	 * The SipHash APIs expect the key as a pair of 64-bit words, not as a
+	 * byte array.  Make sure to use a consistent endianness.
+	 */
+	BUILD_BUG_ON(sizeof(ci->ci_dirhash_key) != 16);
+	BUILD_BUG_ON(ARRAY_SIZE(ci->ci_dirhash_key.key) != 2);
+	le64_to_cpus(&ci->ci_dirhash_key.key[0]);
+	le64_to_cpus(&ci->ci_dirhash_key.key[1]);
+
 	ci->ci_dirhash_key_initialized = true;
 	return 0;
 }
Signature · 1 line
2.32.0.rc0.204.g9fa02ecfa5-goog
author maintainer
#1 lore raw
Quoted 17 lines · Eric Biggers

From: Eric Biggers <[email protected]>

Typically, the cryptographic APIs that fscrypt uses take keys as byte arrays, which avoids endianness issues. However, siphash_key_t is an exception. It is defined as 'u64 key[2];', i.e. the 128-bit key is expected to be given directly as two 64-bit words in CPU endianness.

fscrypt_derive_dirhash_key() forgot to take this into account. Therefore, the SipHash keys used to index encrypted+casefolded directories differ on big endian vs. little endian platforms. This makes such directories non-portable between these platforms.

Fix this by always using the little endian order. This is a breaking change for big endian platforms, but this should be fine in practice since the encrypt+casefold support isn't known to actually be used on any big endian platforms yet.

Quoted 6 lines
Fixes aa408f835d02 ("fscrypt: derive dirhash key for casefolded directories")
Cc <[email protected]> # v5.6+
---
 fs/crypto/keysetup.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

I missed that fscrypt_setup_iv_ino_lblk_32_key() has the same bug too. I'll send out a new patch which fixes both of these...

- Eric