[PATCH v3 03/22] fscrypt: allow fscrypt_generate_iv() to distinguish filenames

Sweet Tea Dorminy
2022-10-20T16:59:12Z

For extent-based file contents encryption, filenames will need to
generate an IV based on the inode context, while file contents will need
to generate an IV based on the extent context. Currently filenames and
the first block of file contents both pass fscrypt_generate_iv() a block
number of 0, making it hard to distinguish the two cases.

To enable distinguishing these two cases for extent-based encryption,
this change adjusts all callers to pass U64_MAX when requesting an IV
for filename encryption, and then changes fscrypt_generate_iv() to
convert U64_MAX to 0 for traditional inode-context encryption. For
extent-based encryption, any block number other than U64_MAX will get an
IV from the extent context, while U64_MAX will indicate falling back to
inode contexts.

Signed-off-by: Sweet Tea Dorminy <sweettea-kernel@dorminy.me>
---
fs/crypto/crypto.c | 9 ++++++++-
fs/crypto/fname.c | 4 ++--
2 files changed, 10 insertions(+), 3 deletions(-)

diff --git a/fs/crypto/crypto.c b/fs/crypto/crypto.c
index e78be66bbf01..7fe5979fbea2 100644
--- a/fs/crypto/crypto.c
+++ b/fs/crypto/crypto.c
@@ -71,7 +71,7 @@ EXPORT_SYMBOL(fscrypt_free_bounce_page);

/*
* Generate the IV for the given logical block number within the given file.
- * For filenames encryption, lblk_num == 0.
+ * For filenames encryption, lblk_num == U64_MAX.
*
* Keep this in sync with fscrypt_limit_io_blocks(). fscrypt_limit_io_blocks()
* needs to know about any IV generation methods where the low bits of IV don't
@@ -84,6 +84,13 @@ void fscrypt_generate_iv(union fscrypt_iv *iv, u64 lblk_num,

memset(iv, 0, ci->ci_mode->ivsize);

+ /*
+ * Filename encryption. For inode-based policies, filenames are
+ * encrypted as though they are lblk 0.
+ */
+ if (lblk_num == U64_MAX)
+ lblk_num = 0;
+
if (flags & FSCRYPT_POLICY_FLAG_IV_INO_LBLK_64) {
WARN_ON_ONCE(lblk_num > U32_MAX);
WARN_ON_ONCE(ci->ci_inode->i_ino > U32_MAX);
diff --git a/fs/crypto/fname.c b/fs/crypto/fname.c
index 6c092a1533f7..b3e7e3a66312 100644
--- a/fs/crypto/fname.c
+++ b/fs/crypto/fname.c
@@ -79,7 +79,7 @@ int fscrypt_fname_encrypt(const struct inode *inode, const struct qstr *iname,
memset(out + iname->len, 0, olen - iname->len);

/* Initialize the IV */
- fscrypt_generate_iv(&iv, 0, ci);
+ fscrypt_generate_iv(&iv, U64_MAX, ci);

/* Set up the encryption request */
req = skcipher_request_alloc(tfm, GFP_NOFS);
@@ -134,7 +134,7 @@ static int fname_decrypt(const struct inode *inode,
crypto_req_done, &wait);

/* Initialize IV */
- fscrypt_generate_iv(&iv, 0, ci);
+ fscrypt_generate_iv(&iv, U64_MAX, ci);

/* Create decryption request */
sg_init_one(&src_sg, iname->name, iname->len);
--
2.35.1