Commit d3e94fdc authored by Jeff Layton's avatar Jeff Layton Committed by Ilya Dryomov
Browse files

fscrypt: export fscrypt_fname_encrypt and fscrypt_fname_encrypted_size



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: default avatarJeff Layton <jlayton@kernel.org>
Reviewed-by: default avatarXiubo Li <xiubli@redhat.com>
Acked-by: default avatarEric Biggers <ebiggers@google.com>
Signed-off-by: default avatarIlya Dryomov <idryomov@gmail.com>
parent 18cc912b
Loading
Loading
Loading
Loading
+30 −6
Original line number Diff line number Diff line
@@ -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,7 +266,7 @@ 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,
bool __fscrypt_fname_encrypted_size(const union fscrypt_policy *policy,
				    u32 orig_len, u32 max_len,
				    u32 *encrypted_len_ret)
{
@@ -280,6 +282,29 @@ bool fscrypt_fname_encrypted_size(const union fscrypt_policy *policy,
	return true;
}

/**
 * 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
@@ -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,
+3 −6
Original line number Diff line number Diff line
@@ -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,
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;
};
+3 −3
Original line number Diff line number Diff line
@@ -228,7 +228,7 @@ 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,
	if (!__fscrypt_fname_encrypted_size(policy, len,
					    max_len - sizeof(struct fscrypt_symlink_data),
					    &disk_link->len))
		return -ENAMETOOLONG;
+4 −0
Original line number Diff line number Diff line
@@ -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);