fscrypt: export fscrypt_fname_encrypt and fscrypt_fname_encrypted_size
authorJeff Layton <jlayton@kernel.org>
Fri, 8 Jan 2021 20:34:38 +0000 (15:34 -0500)
committerIlya Dryomov <idryomov@gmail.com>
Tue, 2 Aug 2022 22:54:11 +0000 (00:54 +0200)
For ceph, we want to use our own scheme for handling filenames that are
are longer than NAME_MAX after encryption and Base64 encoding. This
allows us to have a consistent view of the encrypted filenames for
clients that don't support fscrypt and clients that do but that don't
have the key.

Currently, fs/crypto only supports encrypting filenames using
fscrypt_setup_filename, but that also handles encoding nokey names. Ceph
can't use that because it handles nokey names in a different way.

Export fscrypt_fname_encrypt. Rename fscrypt_fname_encrypted_size to
__fscrypt_fname_encrypted_size and add a new wrapper called
fscrypt_fname_encrypted_size that takes an inode argument rather than a
pointer to a fscrypt_policy union.

Signed-off-by: Jeff Layton <jlayton@kernel.org>
Reviewed-by: Xiubo Li <xiubli@redhat.com>
Acked-by: Eric Biggers <ebiggers@google.com>
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
fs/crypto/fname.c
fs/crypto/fscrypt_private.h
fs/crypto/hooks.c
include/linux/fscrypt.h

index 14e0ef5..12bd61d 100644 (file)
@@ -86,7 +86,8 @@ static inline bool fscrypt_is_dot_dotdot(const struct qstr *str)
 /**
  * fscrypt_fname_encrypt() - encrypt a filename
  * @inode: inode of the parent directory (for regular filenames)
- *        or of the symlink (for symlink targets)
+ *        or of the symlink (for symlink targets). Key must already be
+ *        set up.
  * @iname: the filename to encrypt
  * @out: (output) the encrypted filename
  * @olen: size of the encrypted filename.  It must be at least @iname->len.
@@ -137,6 +138,7 @@ int fscrypt_fname_encrypt(const struct inode *inode, const struct qstr *iname,
 
        return 0;
 }
+EXPORT_SYMBOL_GPL(fscrypt_fname_encrypt);
 
 /**
  * fname_decrypt() - decrypt a filename
@@ -264,9 +266,9 @@ static int fscrypt_base64url_decode(const char *src, int srclen, u8 *dst)
        return bp - dst;
 }
 
-bool fscrypt_fname_encrypted_size(const union fscrypt_policy *policy,
-                                 u32 orig_len, u32 max_len,
-                                 u32 *encrypted_len_ret)
+bool __fscrypt_fname_encrypted_size(const union fscrypt_policy *policy,
+                                   u32 orig_len, u32 max_len,
+                                   u32 *encrypted_len_ret)
 {
        int padding = 4 << (fscrypt_policy_flags(policy) &
                            FSCRYPT_POLICY_FLAGS_PAD_MASK);
@@ -281,6 +283,29 @@ bool fscrypt_fname_encrypted_size(const union fscrypt_policy *policy,
 }
 
 /**
+ * fscrypt_fname_encrypted_size() - calculate length of encrypted filename
+ * @inode:             parent inode of dentry name being encrypted. Key must
+ *                     already be set up.
+ * @orig_len:          length of the original filename
+ * @max_len:           maximum length to return
+ * @encrypted_len_ret: where calculated length should be returned (on success)
+ *
+ * Filenames that are shorter than the maximum length may have their lengths
+ * increased slightly by encryption, due to padding that is applied.
+ *
+ * Return: false if the orig_len is greater than max_len. Otherwise, true and
+ *        fill out encrypted_len_ret with the length (up to max_len).
+ */
+bool fscrypt_fname_encrypted_size(const struct inode *inode, u32 orig_len,
+                                 u32 max_len, u32 *encrypted_len_ret)
+{
+       return __fscrypt_fname_encrypted_size(&inode->i_crypt_info->ci_policy,
+                                             orig_len, max_len,
+                                             encrypted_len_ret);
+}
+EXPORT_SYMBOL_GPL(fscrypt_fname_encrypted_size);
+
+/**
  * fscrypt_fname_alloc_buffer() - allocate a buffer for presented filenames
  * @max_encrypted_len: maximum length of encrypted filenames the buffer will be
  *                    used to present
@@ -435,8 +460,7 @@ int fscrypt_setup_filename(struct inode *dir, const struct qstr *iname,
                return ret;
 
        if (fscrypt_has_encryption_key(dir)) {
-               if (!fscrypt_fname_encrypted_size(&dir->i_crypt_info->ci_policy,
-                                                 iname->len, NAME_MAX,
+               if (!fscrypt_fname_encrypted_size(dir, iname->len, NAME_MAX,
                                                  &fname->crypto_buf.len))
                        return -ENAMETOOLONG;
                fname->crypto_buf.name = kmalloc(fname->crypto_buf.len,
index 6b4c809..11fe9d2 100644 (file)
@@ -297,14 +297,11 @@ void fscrypt_generate_iv(union fscrypt_iv *iv, u64 lblk_num,
                         const struct fscrypt_info *ci);
 
 /* fname.c */
-int fscrypt_fname_encrypt(const struct inode *inode, const struct qstr *iname,
-                         u8 *out, unsigned int olen);
-bool fscrypt_fname_encrypted_size(const union fscrypt_policy *policy,
-                                 u32 orig_len, u32 max_len,
-                                 u32 *encrypted_len_ret);
+bool __fscrypt_fname_encrypted_size(const union fscrypt_policy *policy,
+                                   u32 orig_len, u32 max_len,
+                                   u32 *encrypted_len_ret);
 
 /* hkdf.c */
-
 struct fscrypt_hkdf {
        struct crypto_shash *hmac_tfm;
 };
index af74599..7c01025 100644 (file)
@@ -228,9 +228,9 @@ int fscrypt_prepare_symlink(struct inode *dir, const char *target,
         * counting it (even though it is meaningless for ciphertext) is simpler
         * for now since filesystems will assume it is there and subtract it.
         */
-       if (!fscrypt_fname_encrypted_size(policy, len,
-                                         max_len - sizeof(struct fscrypt_symlink_data),
-                                         &disk_link->len))
+       if (!__fscrypt_fname_encrypted_size(policy, len,
+                                           max_len - sizeof(struct fscrypt_symlink_data),
+                                           &disk_link->len))
                return -ENAMETOOLONG;
        disk_link->len += sizeof(struct fscrypt_symlink_data);
 
index e60d57c..5926a40 100644 (file)
@@ -327,6 +327,10 @@ void fscrypt_free_inode(struct inode *inode);
 int fscrypt_drop_inode(struct inode *inode);
 
 /* fname.c */
+int fscrypt_fname_encrypt(const struct inode *inode, const struct qstr *iname,
+                         u8 *out, unsigned int olen);
+bool fscrypt_fname_encrypted_size(const struct inode *inode, u32 orig_len,
+                                 u32 max_len, u32 *encrypted_len_ret);
 int fscrypt_setup_filename(struct inode *inode, const struct qstr *iname,
                           int lookup, struct fscrypt_name *fname);