Received: by 2002:a25:8b91:0:0:0:0:0 with SMTP id j17csp22113973ybl; Mon, 6 Jan 2020 18:34:34 -0800 (PST) X-Google-Smtp-Source: APXvYqyPKwfAL7GeQSVUlPYCIleHIR+vqYRgrAjAxGBTZlTALo8dfFEchvovBk/PeRO4uaEBo4zQ X-Received: by 2002:aca:d6d2:: with SMTP id n201mr6874455oig.112.1578364474080; Mon, 06 Jan 2020 18:34:34 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1578364474; cv=none; d=google.com; s=arc-20160816; b=GIMIE/GKNcFJxZV9VoZTBSa7cUxAZ8WgRXtX/BL2MNQ8+7yBx+2VSVz5+alhkjyRdC p6QFkAj9XP1vwef/FpXUv1ad46Y6gLDDFF5tabZnszTE/qHFePkARjfb13ZIo/u0l5dv AgJa/OTwASO4HWYFzDnEdUmk6Tt57BZBp/8nrSydckPVr9qacqoCeMLoeHZlFNirzzCb uF7cz3WTA65Vai8sWAppwLihTvzSLNLZ1QTneTescppSrR7KcakLxLZv7ElyPKkwAq+p xdi4chGUfph0U6abIc9I9EYZ/R1ydVXtUBhoGq9j8BRdv6+4y/H3yEPzJRS6nxvz///p VQyg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:cc:to:from:subject:references :mime-version:message-id:in-reply-to:date:dkim-signature; bh=Y/HXwTMWbePLkX7jf55rAi5wOsdmr84mYc7PuSsZxzo=; b=LyEtr27/a+vrSxwwtiKTkQNY07r9WXhbtJAJ6riSUcDdHXN4HSIxASR27UqOb6C+a/ ev0ApAA8Yf+RlXLoaITYl5gebphzhvAqVhun6rBL9dwwlO2V8XEXqUoK4iZpVZm7vJcd LqmDhV1bnN/hAXDRzXQUW2YCVNRj8aHZ/XK89ZbFgQPNhWBLfhTWUNHOVWe/zPlLKy2e pLDbp8aMrhB9chWbLhimVigrAqDSBsKZbtus3WjiwCsZT1HC7r5zEqIJpSf0LMGKBXNg cZCxyCFSO/K/68tvis/YaRYYpseNIIO1CGtxlQML9wd9rTDdlquoMquTYihtd29RYCgV iPrg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@google.com header.s=20161025 header.b="Kno/qnE9"; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id p62si26014478oig.101.2020.01.06.18.34.21; Mon, 06 Jan 2020 18:34:34 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@google.com header.s=20161025 header.b="Kno/qnE9"; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727511AbgAGCdj (ORCPT + 99 others); Mon, 6 Jan 2020 21:33:39 -0500 Received: from mail-pf1-f202.google.com ([209.85.210.202]:51688 "EHLO mail-pf1-f202.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727479AbgAGCdi (ORCPT ); Mon, 6 Jan 2020 21:33:38 -0500 Received: by mail-pf1-f202.google.com with SMTP id z19so11213497pfn.18 for ; Mon, 06 Jan 2020 18:33:38 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=Y/HXwTMWbePLkX7jf55rAi5wOsdmr84mYc7PuSsZxzo=; b=Kno/qnE91qjrVqc5lgWjRzkPJxNZe86Tn3KM88Jxgm+YgNcMchtZFjdT1hnlqjg8dg gjL6ly2Ww2cCXSjUnq8Q3k+25zvwXddlG+3CzSoGZENA5cua5aS7c7/WtiUuF8362Ajb tovKHGJNsrsnvFwiDZVX+1EKweo3MURM1LnHDNjL1MZ6+K7jz5yI6dUbltVGM3r1PGU1 XTQl6wqZLramzVsdYAWHGQgZ0wlLwCUXAd02w8dnBOs9Uu6IWYFdyBuM2djR6GZQk06/ TYsZUwcx6sDcbYH24QCp95OXARO88cjY6o+VgPz2ZiA/E+/4qFOZ38euSbaDFY0T0PQB 2mZQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=Y/HXwTMWbePLkX7jf55rAi5wOsdmr84mYc7PuSsZxzo=; b=JskSrzxrjYte5TRBhJeOfGxMD+5EicvSP7RQ0LnBypyV3fwQZGhEe41uoyOUStp8Ih Fi0Gvito1hWRgFNhfReTGLBY1rnZE2ochddBtOrThNjnyyLAJM2TNckmNYx8YtyOk8NV dIm0uPiIrqOthjHdx9OVTaM/lYNMSJBTo2LlPWzzrzPA/DMq+ye2ySLH6SMtPfd2/fjP DRsFfP7M1RebWPb4Npyul5CLnJ1WQrWA1pSA0YKqB7N2PJwaDEC7w4ffq/S0h0BG4qZi MHxnFRqyDzBGO21MwTJokEBhhGSRCZOIwbwvbQFn48KPr5k5/I5H7HlDiMG4JrFaay0r 16Og== X-Gm-Message-State: APjAAAUwYFGBtNmIjagP1ONjK4Eu3oASn/zYJAbhslITTa8yXYWdBH+l cO0tMnDS0RhXVfNb4i0Xof775rmZJJs= X-Received: by 2002:a63:1953:: with SMTP id 19mr112379139pgz.157.1578364417939; Mon, 06 Jan 2020 18:33:37 -0800 (PST) Date: Mon, 6 Jan 2020 18:33:21 -0800 In-Reply-To: <20200107023323.38394-1-drosen@google.com> Message-Id: <20200107023323.38394-2-drosen@google.com> Mime-Version: 1.0 References: <20200107023323.38394-1-drosen@google.com> X-Mailer: git-send-email 2.24.1.735.g03f4e72817-goog Subject: [PATCH v2 1/3] fscrypt: Add siphash and hash key for policy v2 From: Daniel Rosenberg To: Eric Biggers , linux-fscrypt@vger.kernel.org Cc: linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org, Gabriel Krisman Bertazi , kernel-team@android.com, Daniel Rosenberg Content-Type: text/plain; charset="UTF-8" Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org With encryption and casefolding, we cannot simply take the hash of the ciphertext because of case insensitivity, and we can't take the hash of the unencrypted name since that would leak information about the encrypted name. Instead we can use siphash to compute a keyed hash of the file names. When a v2 policy is used on a directory, we derive a key for use with siphash. Signed-off-by: Daniel Rosenberg --- fs/crypto/fname.c | 22 ++++++++++++++++++++++ fs/crypto/fscrypt_private.h | 9 +++++++++ fs/crypto/keysetup.c | 32 +++++++++++++++++++++++--------- include/linux/fscrypt.h | 9 +++++++++ 4 files changed, 63 insertions(+), 9 deletions(-) diff --git a/fs/crypto/fname.c b/fs/crypto/fname.c index 3fd27e14ebdd..371e8f01d1c8 100644 --- a/fs/crypto/fname.c +++ b/fs/crypto/fname.c @@ -402,6 +402,28 @@ int fscrypt_setup_filename(struct inode *dir, const struct qstr *iname, } EXPORT_SYMBOL(fscrypt_setup_filename); +/** + * fscrypt_fname_siphash() - Calculate the siphash for a file name + * @dir: the parent directory + * @name: the name of the file to get the siphash of + * + * Given a user-provided filename @name, this function calculates the siphash of + * that name using the directory's hash key. + * + * This assumes the directory uses a v2 policy, and the key is available. + * + * Return: the siphash of @name using the hash key of @dir + */ +u64 fscrypt_fname_siphash(const struct inode *dir, const struct qstr *name) +{ + struct fscrypt_info *ci = dir->i_crypt_info; + + WARN_ON(!ci->ci_hash_key_initialized); + + return siphash(name->name, name->len, &ci->ci_hash_key); +} +EXPORT_SYMBOL(fscrypt_fname_siphash); + /* * Validate dentries in encrypted directories to make sure we aren't potentially * caching stale dentries after a key has been added. diff --git a/fs/crypto/fscrypt_private.h b/fs/crypto/fscrypt_private.h index b22e8decebed..8b37a5eebb57 100644 --- a/fs/crypto/fscrypt_private.h +++ b/fs/crypto/fscrypt_private.h @@ -12,6 +12,7 @@ #define _FSCRYPT_PRIVATE_H #include +#include #include #define CONST_STRLEN(str) (sizeof(str) - 1) @@ -188,6 +189,13 @@ struct fscrypt_info { */ struct fscrypt_direct_key *ci_direct_key; + /* + * With v2 policies, this can be used with siphash + * When the key has been set, ci_hash_key_initialized is set to true + */ + siphash_key_t ci_hash_key; + bool ci_hash_key_initialized; + /* The encryption policy used by this inode */ union fscrypt_policy ci_policy; @@ -262,6 +270,7 @@ extern int fscrypt_init_hkdf(struct fscrypt_hkdf *hkdf, const u8 *master_key, #define HKDF_CONTEXT_PER_FILE_KEY 2 #define HKDF_CONTEXT_DIRECT_KEY 3 #define HKDF_CONTEXT_IV_INO_LBLK_64_KEY 4 +#define HKDF_CONTEXT_FNAME_HASH_KEY 5 extern int fscrypt_hkdf_expand(const struct fscrypt_hkdf *hkdf, u8 context, const u8 *info, unsigned int infolen, diff --git a/fs/crypto/keysetup.c b/fs/crypto/keysetup.c index 96074054bdbc..c1bd897c9310 100644 --- a/fs/crypto/keysetup.c +++ b/fs/crypto/keysetup.c @@ -189,7 +189,7 @@ static int fscrypt_setup_v2_file_key(struct fscrypt_info *ci, * This ensures that the master key is consistently used only * for HKDF, avoiding key reuse issues. */ - return setup_per_mode_key(ci, mk, mk->mk_direct_tfms, + err = setup_per_mode_key(ci, mk, mk->mk_direct_tfms, HKDF_CONTEXT_DIRECT_KEY, false); } else if (ci->ci_policy.v2.flags & FSCRYPT_POLICY_FLAG_IV_INO_LBLK_64) { @@ -199,20 +199,34 @@ static int fscrypt_setup_v2_file_key(struct fscrypt_info *ci, * the IVs. This format is optimized for use with inline * encryption hardware compliant with the UFS or eMMC standards. */ - return setup_per_mode_key(ci, mk, mk->mk_iv_ino_lblk_64_tfms, + err = setup_per_mode_key(ci, mk, mk->mk_iv_ino_lblk_64_tfms, HKDF_CONTEXT_IV_INO_LBLK_64_KEY, true); + } else { + err = fscrypt_hkdf_expand(&mk->mk_secret.hkdf, + HKDF_CONTEXT_PER_FILE_KEY, + ci->ci_nonce, + FS_KEY_DERIVATION_NONCE_SIZE, + derived_key, ci->ci_mode->keysize); + if (err) + return err; + + err = fscrypt_set_derived_key(ci, derived_key); + memzero_explicit(derived_key, ci->ci_mode->keysize); } - - err = fscrypt_hkdf_expand(&mk->mk_secret.hkdf, - HKDF_CONTEXT_PER_FILE_KEY, - ci->ci_nonce, FS_KEY_DERIVATION_NONCE_SIZE, - derived_key, ci->ci_mode->keysize); if (err) return err; - err = fscrypt_set_derived_key(ci, derived_key); - memzero_explicit(derived_key, ci->ci_mode->keysize); + if (S_ISDIR(ci->ci_inode->i_mode)) { + err = fscrypt_hkdf_expand(&mk->mk_secret.hkdf, + HKDF_CONTEXT_FNAME_HASH_KEY, + ci->ci_nonce, + FS_KEY_DERIVATION_NONCE_SIZE, + (u8 *)&ci->ci_hash_key, + sizeof(ci->ci_hash_key)); + if (!err) + ci->ci_hash_key_initialized = true; + } return err; } diff --git a/include/linux/fscrypt.h b/include/linux/fscrypt.h index 6fe8d0f96a4a..1dfbed855bee 100644 --- a/include/linux/fscrypt.h +++ b/include/linux/fscrypt.h @@ -172,6 +172,8 @@ extern int fscrypt_fname_disk_to_usr(const struct inode *inode, u32 hash, u32 minor_hash, const struct fscrypt_str *iname, struct fscrypt_str *oname); +extern u64 fscrypt_fname_siphash(const struct inode *dir, + const struct qstr *name); #define FSCRYPT_FNAME_MAX_UNDIGESTED_SIZE 32 @@ -468,6 +470,13 @@ static inline int fscrypt_fname_disk_to_usr(const struct inode *inode, return -EOPNOTSUPP; } +static inline u64 fscrypt_fname_siphash(const struct inode *dir, + const struct qstr *name) +{ + WARN_ON_ONCE(1); + return 0; +} + static inline bool fscrypt_match_name(const struct fscrypt_name *fname, const u8 *de_name, u32 de_name_len) { -- 2.24.1.735.g03f4e72817-goog