Skip to content

Commit a58e203

Browse files
committed
Merge tag 'fscrypt-for-linus' of git://git.kernel.org/pub/scm/fs/fscrypt/fscrypt
Pull fscrypt updates from Eric Biggers: "A couple bug fixes for fs/crypto/: - Fix handling of major dirhash values that happen to be 0. - Fix cases where keys were derived differently on big endian systems than on little endian systems (affecting some newer features only)" * tag 'fscrypt-for-linus' of git://git.kernel.org/pub/scm/fs/fscrypt/fscrypt: fscrypt: fix derivation of SipHash keys on big endian CPUs fscrypt: don't ignore minor_hash when hash is 0
2 parents a60c538 + 2fc2b43 commit a58e203

File tree

2 files changed

+35
-15
lines changed

2 files changed

+35
-15
lines changed

fs/crypto/fname.c

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -344,13 +344,9 @@ int fscrypt_fname_disk_to_usr(const struct inode *inode,
344344
offsetof(struct fscrypt_nokey_name, sha256));
345345
BUILD_BUG_ON(BASE64_CHARS(FSCRYPT_NOKEY_NAME_MAX) > NAME_MAX);
346346

347-
if (hash) {
348-
nokey_name.dirhash[0] = hash;
349-
nokey_name.dirhash[1] = minor_hash;
350-
} else {
351-
nokey_name.dirhash[0] = 0;
352-
nokey_name.dirhash[1] = 0;
353-
}
347+
nokey_name.dirhash[0] = hash;
348+
nokey_name.dirhash[1] = minor_hash;
349+
354350
if (iname->len <= sizeof(nokey_name.bytes)) {
355351
memcpy(nokey_name.bytes, iname->name, iname->len);
356352
size = offsetof(struct fscrypt_nokey_name, bytes[iname->len]);

fs/crypto/keysetup.c

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -210,15 +210,40 @@ static int setup_per_mode_enc_key(struct fscrypt_info *ci,
210210
return err;
211211
}
212212

213+
/*
214+
* Derive a SipHash key from the given fscrypt master key and the given
215+
* application-specific information string.
216+
*
217+
* Note that the KDF produces a byte array, but the SipHash APIs expect the key
218+
* as a pair of 64-bit words. Therefore, on big endian CPUs we have to do an
219+
* endianness swap in order to get the same results as on little endian CPUs.
220+
*/
221+
static int fscrypt_derive_siphash_key(const struct fscrypt_master_key *mk,
222+
u8 context, const u8 *info,
223+
unsigned int infolen, siphash_key_t *key)
224+
{
225+
int err;
226+
227+
err = fscrypt_hkdf_expand(&mk->mk_secret.hkdf, context, info, infolen,
228+
(u8 *)key, sizeof(*key));
229+
if (err)
230+
return err;
231+
232+
BUILD_BUG_ON(sizeof(*key) != 16);
233+
BUILD_BUG_ON(ARRAY_SIZE(key->key) != 2);
234+
le64_to_cpus(&key->key[0]);
235+
le64_to_cpus(&key->key[1]);
236+
return 0;
237+
}
238+
213239
int fscrypt_derive_dirhash_key(struct fscrypt_info *ci,
214240
const struct fscrypt_master_key *mk)
215241
{
216242
int err;
217243

218-
err = fscrypt_hkdf_expand(&mk->mk_secret.hkdf, HKDF_CONTEXT_DIRHASH_KEY,
219-
ci->ci_nonce, FSCRYPT_FILE_NONCE_SIZE,
220-
(u8 *)&ci->ci_dirhash_key,
221-
sizeof(ci->ci_dirhash_key));
244+
err = fscrypt_derive_siphash_key(mk, HKDF_CONTEXT_DIRHASH_KEY,
245+
ci->ci_nonce, FSCRYPT_FILE_NONCE_SIZE,
246+
&ci->ci_dirhash_key);
222247
if (err)
223248
return err;
224249
ci->ci_dirhash_key_initialized = true;
@@ -253,10 +278,9 @@ static int fscrypt_setup_iv_ino_lblk_32_key(struct fscrypt_info *ci,
253278
if (mk->mk_ino_hash_key_initialized)
254279
goto unlock;
255280

256-
err = fscrypt_hkdf_expand(&mk->mk_secret.hkdf,
257-
HKDF_CONTEXT_INODE_HASH_KEY, NULL, 0,
258-
(u8 *)&mk->mk_ino_hash_key,
259-
sizeof(mk->mk_ino_hash_key));
281+
err = fscrypt_derive_siphash_key(mk,
282+
HKDF_CONTEXT_INODE_HASH_KEY,
283+
NULL, 0, &mk->mk_ino_hash_key);
260284
if (err)
261285
goto unlock;
262286
/* pairs with smp_load_acquire() above */

0 commit comments

Comments
 (0)