lkml.org 
[lkml]   [2021]   [Jul]   [12]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.10 585/593] fscrypt: fix derivation of SipHash keys on big endian CPUs
    Date
    From: Eric Biggers <ebiggers@google.com>

    commit 2fc2b430f559fdf32d5d1dd5ceaa40e12fb77bdf upstream.

    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() and fscrypt_setup_iv_ino_lblk_32_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, as do the SipHash keys used to hash inode numbers for
    IV_INO_LBLK_32-encrypted directories. 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 these features (encrypt+casefold support, and the IV_INO_LBLK_32
    flag) aren't known to actually be used on any big endian platforms yet.

    Fixes: aa408f835d02 ("fscrypt: derive dirhash key for casefolded directories")
    Fixes: e3b1078bedd3 ("fscrypt: add support for IV_INO_LBLK_32 policies")
    Cc: <stable@vger.kernel.org> # v5.6+
    Link: https://lore.kernel.org/r/20210605075033.54424-1-ebiggers@kernel.org
    Signed-off-by: Eric Biggers <ebiggers@google.com>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

    ---
    fs/crypto/keysetup.c | 40 ++++++++++++++++++++++++++++++++--------
    1 file changed, 32 insertions(+), 8 deletions(-)

    --- a/fs/crypto/keysetup.c
    +++ b/fs/crypto/keysetup.c
    @@ -210,15 +210,40 @@ out_unlock:
    return err;
    }

    +/*
    + * Derive a SipHash key from the given fscrypt master key and the given
    + * application-specific information string.
    + *
    + * Note that the KDF produces a byte array, but the SipHash APIs expect the key
    + * as a pair of 64-bit words. Therefore, on big endian CPUs we have to do an
    + * endianness swap in order to get the same results as on little endian CPUs.
    + */
    +static int fscrypt_derive_siphash_key(const struct fscrypt_master_key *mk,
    + u8 context, const u8 *info,
    + unsigned int infolen, siphash_key_t *key)
    +{
    + int err;
    +
    + err = fscrypt_hkdf_expand(&mk->mk_secret.hkdf, context, info, infolen,
    + (u8 *)key, sizeof(*key));
    + if (err)
    + return err;
    +
    + BUILD_BUG_ON(sizeof(*key) != 16);
    + BUILD_BUG_ON(ARRAY_SIZE(key->key) != 2);
    + le64_to_cpus(&key->key[0]);
    + le64_to_cpus(&key->key[1]);
    + return 0;
    +}
    +
    int fscrypt_derive_dirhash_key(struct fscrypt_info *ci,
    const struct fscrypt_master_key *mk)
    {
    int err;

    - err = fscrypt_hkdf_expand(&mk->mk_secret.hkdf, HKDF_CONTEXT_DIRHASH_KEY,
    - ci->ci_nonce, FSCRYPT_FILE_NONCE_SIZE,
    - (u8 *)&ci->ci_dirhash_key,
    - sizeof(ci->ci_dirhash_key));
    + err = fscrypt_derive_siphash_key(mk, HKDF_CONTEXT_DIRHASH_KEY,
    + ci->ci_nonce, FSCRYPT_FILE_NONCE_SIZE,
    + &ci->ci_dirhash_key);
    if (err)
    return err;
    ci->ci_dirhash_key_initialized = true;
    @@ -253,10 +278,9 @@ static int fscrypt_setup_iv_ino_lblk_32_
    if (mk->mk_ino_hash_key_initialized)
    goto unlock;

    - err = fscrypt_hkdf_expand(&mk->mk_secret.hkdf,
    - HKDF_CONTEXT_INODE_HASH_KEY, NULL, 0,
    - (u8 *)&mk->mk_ino_hash_key,
    - sizeof(mk->mk_ino_hash_key));
    + err = fscrypt_derive_siphash_key(mk,
    + HKDF_CONTEXT_INODE_HASH_KEY,
    + NULL, 0, &mk->mk_ino_hash_key);
    if (err)
    goto unlock;
    /* pairs with smp_load_acquire() above */

    \
     
     \ /
      Last update: 2021-07-12 09:19    [W:2.439 / U:0.340 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site