Commit afdb0f2e authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'fscrypt-for-linus' of git://git.kernel.org/pub/scm/fs/fscrypt/fscrypt

Pull fscrypt updates from Eric Biggers:

 - Add the IV_INO_LBLK_32 encryption policy flag which modifies the
   encryption to be optimized for eMMC inline encryption hardware.

 - Make the test_dummy_encryption mount option for ext4 and f2fs support
   v2 encryption policies.

 - Fix kerneldoc warnings and some coding style inconsistencies.

* tag 'fscrypt-for-linus' of git://git.kernel.org/pub/scm/fs/fscrypt/fscrypt:
  fscrypt: add support for IV_INO_LBLK_32 policies
  fscrypt: make test_dummy_encryption use v2 by default
  fscrypt: support test_dummy_encryption=v2
  fscrypt: add fscrypt_add_test_dummy_key()
  linux/parser.h: add include guards
  fscrypt: remove unnecessary extern keywords
  fscrypt: name all function parameters
  fscrypt: fix all kerneldoc warnings
parents 829f3b94 e3b1078b
Loading
Loading
Loading
Loading
+5 −1
Original line number Diff line number Diff line
@@ -225,8 +225,12 @@ fsync_mode=%s Control the policy of fsync. Currently supports "posix",
                       pass, but the performance will regress. "nobarrier" is
                       based on "posix", but doesn't issue flush command for
                       non-atomic files likewise "nobarrier" mount option.
test_dummy_encryption  Enable dummy encryption, which provides a fake fscrypt
test_dummy_encryption
test_dummy_encryption=%s
                       Enable dummy encryption, which provides a fake fscrypt
                       context. The fake fscrypt context is used by xfstests.
                       The argument may be either "v1" or "v2", in order to
                       select the corresponding fscrypt policy version.
checkpoint=%s[:%u[%]]  Set to "disable" to turn off checkpointing. Set to "enable"
                       to reenable checkpointing. Is enabled by default. While
                       disabled, any unmounting or unexpected shutdowns will cause
+29 −4
Original line number Diff line number Diff line
@@ -292,8 +292,22 @@ files' data differently, inode numbers are included in the IVs.
Consequently, shrinking the filesystem may not be allowed.

This format is optimized for use with inline encryption hardware
compliant with the UFS or eMMC standards, which support only 64 IV
bits per I/O request and may have only a small number of keyslots.
compliant with the UFS standard, which supports only 64 IV bits per
I/O request and may have only a small number of keyslots.

IV_INO_LBLK_32 policies
-----------------------

IV_INO_LBLK_32 policies work like IV_INO_LBLK_64, except that for
IV_INO_LBLK_32, the inode number is hashed with SipHash-2-4 (where the
SipHash key is derived from the master key) and added to the file
logical block number mod 2^32 to produce a 32-bit IV.

This format is optimized for use with inline encryption hardware
compliant with the eMMC v5.2 standard, which supports only 32 IV bits
per I/O request and may have only a small number of keyslots.  This
format results in some level of IV reuse, so it should only be used
when necessary due to hardware limitations.

Key identifiers
---------------
@@ -369,6 +383,10 @@ a little endian number, except that:
  to 32 bits and is placed in bits 0-31 of the IV.  The inode number
  (which is also limited to 32 bits) is placed in bits 32-63.

- With `IV_INO_LBLK_32 policies`_, the logical block number is limited
  to 32 bits and is placed in bits 0-31 of the IV.  The inode number
  is then hashed and added mod 2^32.

Note that because file logical block numbers are included in the IVs,
filesystems must enforce that blocks are never shifted around within
encrypted files, e.g. via "collapse range" or "insert range".
@@ -465,8 +483,15 @@ This structure must be initialized as follows:
    (0x3).
  - FSCRYPT_POLICY_FLAG_DIRECT_KEY: See `DIRECT_KEY policies`_.
  - FSCRYPT_POLICY_FLAG_IV_INO_LBLK_64: See `IV_INO_LBLK_64
    policies`_.  This is mutually exclusive with DIRECT_KEY and is not
    supported on v1 policies.
    policies`_.
  - FSCRYPT_POLICY_FLAG_IV_INO_LBLK_32: See `IV_INO_LBLK_32
    policies`_.

  v1 encryption policies only support the PAD_* and DIRECT_KEY flags.
  The other flags are only supported by v2 encryption policies.

  The DIRECT_KEY, IV_INO_LBLK_64, and IV_INO_LBLK_32 flags are
  mutually exclusive.

- For v2 encryption policies, ``__reserved`` must be zeroed.

+12 −3
Original line number Diff line number Diff line
@@ -54,6 +54,7 @@ struct page *fscrypt_alloc_bounce_page(gfp_t gfp_flags)

/**
 * fscrypt_free_bounce_page() - free a ciphertext bounce page
 * @bounce_page: the bounce page to free, or NULL
 *
 * Free a bounce page that was allocated by fscrypt_encrypt_pagecache_blocks(),
 * or by fscrypt_alloc_bounce_page() directly.
@@ -76,8 +77,12 @@ void fscrypt_generate_iv(union fscrypt_iv *iv, u64 lblk_num,
	memset(iv, 0, ci->ci_mode->ivsize);

	if (flags & FSCRYPT_POLICY_FLAG_IV_INO_LBLK_64) {
		WARN_ON_ONCE((u32)lblk_num != lblk_num);
		WARN_ON_ONCE(lblk_num > U32_MAX);
		WARN_ON_ONCE(ci->ci_inode->i_ino > U32_MAX);
		lblk_num |= (u64)ci->ci_inode->i_ino << 32;
	} else if (flags & FSCRYPT_POLICY_FLAG_IV_INO_LBLK_32) {
		WARN_ON_ONCE(lblk_num > U32_MAX);
		lblk_num = (u32)(ci->ci_hashed_ino + lblk_num);
	} else if (flags & FSCRYPT_POLICY_FLAG_DIRECT_KEY) {
		memcpy(iv->nonce, ci->ci_nonce, FS_KEY_DERIVATION_NONCE_SIZE);
	}
@@ -132,7 +137,8 @@ int fscrypt_crypt_block(const struct inode *inode, fscrypt_direction_t rw,
}

/**
 * fscrypt_encrypt_pagecache_blocks() - Encrypt filesystem blocks from a pagecache page
 * fscrypt_encrypt_pagecache_blocks() - Encrypt filesystem blocks from a
 *					pagecache page
 * @page:      The locked pagecache page containing the block(s) to encrypt
 * @len:       Total size of the block(s) to encrypt.  Must be a nonzero
 *		multiple of the filesystem's block size.
@@ -222,7 +228,8 @@ int fscrypt_encrypt_block_inplace(const struct inode *inode, struct page *page,
EXPORT_SYMBOL(fscrypt_encrypt_block_inplace);

/**
 * fscrypt_decrypt_pagecache_blocks() - Decrypt filesystem blocks in a pagecache page
 * fscrypt_decrypt_pagecache_blocks() - Decrypt filesystem blocks in a
 *					pagecache page
 * @page:      The locked pagecache page containing the block(s) to decrypt
 * @len:       Total size of the block(s) to decrypt.  Must be a nonzero
 *		multiple of the filesystem's block size.
@@ -346,6 +353,8 @@ void fscrypt_msg(const struct inode *inode, const char *level,

/**
 * fscrypt_init() - Set up for fs encryption.
 *
 * Return: 0 on success; -errno on failure
 */
static int __init fscrypt_init(void)
{
+38 −14
Original line number Diff line number Diff line
@@ -18,7 +18,7 @@
#include <crypto/skcipher.h>
#include "fscrypt_private.h"

/**
/*
 * struct fscrypt_nokey_name - identifier for directory entry when key is absent
 *
 * When userspace lists an encrypted directory without access to the key, the
@@ -100,8 +100,11 @@ static inline bool fscrypt_is_dot_dotdot(const struct qstr *str)

/**
 * fscrypt_fname_encrypt() - encrypt a filename
 *
 * The output buffer must be at least as large as the input buffer.
 * @inode: inode of the parent directory (for regular filenames)
 *	   or of the symlink (for symlink targets)
 * @iname: the filename to encrypt
 * @out: (output) the encrypted filename
 * @olen: size of the encrypted filename.  It must be at least @iname->len.
 *	  Any extra space is filled with NUL padding before encryption.
 *
 * Return: 0 on success, -errno on failure
@@ -152,8 +155,11 @@ int fscrypt_fname_encrypt(const struct inode *inode, const struct qstr *iname,

/**
 * fname_decrypt() - decrypt a filename
 *
 * The caller must have allocated sufficient memory for the @oname string.
 * @inode: inode of the parent directory (for regular filenames)
 *	   or of the symlink (for symlink targets)
 * @iname: the encrypted filename to decrypt
 * @oname: (output) the decrypted filename.  The caller must have allocated
 *	   enough space for this, e.g. using fscrypt_fname_alloc_buffer().
 *
 * Return: 0 on success, -errno on failure
 */
@@ -201,7 +207,10 @@ static const char lookup_table[65] =
#define BASE64_CHARS(nbytes)	DIV_ROUND_UP((nbytes) * 4, 3)

/**
 * base64_encode() -
 * base64_encode() - base64-encode some bytes
 * @src: the bytes to encode
 * @len: number of bytes to encode
 * @dst: (output) the base64-encoded string.  Not NUL-terminated.
 *
 * Encodes the input string using characters from the set [A-Za-z0-9+,].
 * The encoded string is roughly 4/3 times the size of the input string.
@@ -267,7 +276,12 @@ bool fscrypt_fname_encrypted_size(const struct inode *inode, u32 orig_len,
}

/**
 * fscrypt_fname_alloc_buffer - allocate a buffer for presented filenames
 * fscrypt_fname_alloc_buffer() - allocate a buffer for presented filenames
 * @inode: inode of the parent directory (for regular filenames)
 *	   or of the symlink (for symlink targets)
 * @max_encrypted_len: maximum length of encrypted filenames the buffer will be
 *		       used to present
 * @crypto_str: (output) buffer to allocate
 *
 * Allocate a buffer that is large enough to hold any decrypted or encoded
 * filename (null-terminated), for the given maximum encrypted filename length.
@@ -292,9 +306,10 @@ int fscrypt_fname_alloc_buffer(const struct inode *inode,
EXPORT_SYMBOL(fscrypt_fname_alloc_buffer);

/**
 * fscrypt_fname_free_buffer - free the buffer for presented filenames
 * fscrypt_fname_free_buffer() - free a buffer for presented filenames
 * @crypto_str: the buffer to free
 *
 * Free the buffer allocated by fscrypt_fname_alloc_buffer().
 * Free a buffer that was allocated by fscrypt_fname_alloc_buffer().
 */
void fscrypt_fname_free_buffer(struct fscrypt_str *crypto_str)
{
@@ -306,10 +321,19 @@ void fscrypt_fname_free_buffer(struct fscrypt_str *crypto_str)
EXPORT_SYMBOL(fscrypt_fname_free_buffer);

/**
 * fscrypt_fname_disk_to_usr() - converts a filename from disk space to user
 * space
 *
 * The caller must have allocated sufficient memory for the @oname string.
 * fscrypt_fname_disk_to_usr() - convert an encrypted filename to
 *				 user-presentable form
 * @inode: inode of the parent directory (for regular filenames)
 *	   or of the symlink (for symlink targets)
 * @hash: first part of the name's dirhash, if applicable.  This only needs to
 *	  be provided if the filename is located in an indexed directory whose
 *	  encryption key may be unavailable.  Not needed for symlink targets.
 * @minor_hash: second part of the name's dirhash, if applicable
 * @iname: encrypted filename to convert.  May also be "." or "..", which
 *	   aren't actually encrypted.
 * @oname: output buffer for the user-presentable filename.  The caller must
 *	   have allocated enough space for this, e.g. using
 *	   fscrypt_fname_alloc_buffer().
 *
 * If the key is available, we'll decrypt the disk name.  Otherwise, we'll
 * encode it for presentation in fscrypt_nokey_name format.
+59 −52
Original line number Diff line number Diff line
@@ -43,7 +43,7 @@ struct fscrypt_context_v2 {
	u8 nonce[FS_KEY_DERIVATION_NONCE_SIZE];
};

/**
/*
 * fscrypt_context - the encryption context of an inode
 *
 * This is the on-disk equivalent of an fscrypt_policy, stored alongside each
@@ -157,7 +157,7 @@ fscrypt_policy_flags(const union fscrypt_policy *policy)
	BUG();
}

/**
/*
 * For encrypted symlinks, the ciphertext length is stored at the beginning
 * of the string in little-endian format.
 */
@@ -222,6 +222,9 @@ struct fscrypt_info {

	/* This inode's nonce, copied from the fscrypt_context */
	u8 ci_nonce[FS_KEY_DERIVATION_NONCE_SIZE];

	/* Hashed inode number.  Only set for IV_INO_LBLK_32 */
	u32 ci_hashed_ino;
};

typedef enum {
@@ -231,15 +234,14 @@ typedef enum {

/* crypto.c */
extern struct kmem_cache *fscrypt_info_cachep;
extern int fscrypt_initialize(unsigned int cop_flags);
extern int fscrypt_crypt_block(const struct inode *inode,
			       fscrypt_direction_t rw, u64 lblk_num,
			       struct page *src_page, struct page *dest_page,
			       unsigned int len, unsigned int offs,
			       gfp_t gfp_flags);
extern struct page *fscrypt_alloc_bounce_page(gfp_t gfp_flags);

extern void __printf(3, 4) __cold
int fscrypt_initialize(unsigned int cop_flags);
int fscrypt_crypt_block(const struct inode *inode, fscrypt_direction_t rw,
			u64 lblk_num, struct page *src_page,
			struct page *dest_page, unsigned int len,
			unsigned int offs, gfp_t gfp_flags);
struct page *fscrypt_alloc_bounce_page(gfp_t gfp_flags);

void __printf(3, 4) __cold
fscrypt_msg(const struct inode *inode, const char *level, const char *fmt, ...);

#define fscrypt_warn(inode, fmt, ...)		\
@@ -264,12 +266,10 @@ void fscrypt_generate_iv(union fscrypt_iv *iv, u64 lblk_num,
			 const struct fscrypt_info *ci);

/* fname.c */
extern int fscrypt_fname_encrypt(const struct inode *inode,
				 const struct qstr *iname,
int fscrypt_fname_encrypt(const struct inode *inode, const struct qstr *iname,
			  u8 *out, unsigned int olen);
extern bool fscrypt_fname_encrypted_size(const struct inode *inode,
					 u32 orig_len, u32 max_len,
					 u32 *encrypted_len_ret);
bool fscrypt_fname_encrypted_size(const struct inode *inode, u32 orig_len,
				  u32 max_len, u32 *encrypted_len_ret);
extern const struct dentry_operations fscrypt_d_ops;

/* hkdf.c */
@@ -278,7 +278,7 @@ struct fscrypt_hkdf {
	struct crypto_shash *hmac_tfm;
};

extern int fscrypt_init_hkdf(struct fscrypt_hkdf *hkdf, const u8 *master_key,
int fscrypt_init_hkdf(struct fscrypt_hkdf *hkdf, const u8 *master_key,
		      unsigned int master_key_size);

/*
@@ -293,12 +293,14 @@ extern int fscrypt_init_hkdf(struct fscrypt_hkdf *hkdf, const u8 *master_key,
#define HKDF_CONTEXT_DIRECT_KEY		3
#define HKDF_CONTEXT_IV_INO_LBLK_64_KEY	4
#define HKDF_CONTEXT_DIRHASH_KEY	5
#define HKDF_CONTEXT_IV_INO_LBLK_32_KEY	6
#define HKDF_CONTEXT_INODE_HASH_KEY	7

extern int fscrypt_hkdf_expand(const struct fscrypt_hkdf *hkdf, u8 context,
int fscrypt_hkdf_expand(const struct fscrypt_hkdf *hkdf, u8 context,
			const u8 *info, unsigned int infolen,
			u8 *okm, unsigned int okmlen);

extern void fscrypt_destroy_hkdf(struct fscrypt_hkdf *hkdf);
void fscrypt_destroy_hkdf(struct fscrypt_hkdf *hkdf);

/* keyring.c */

@@ -389,14 +391,17 @@ struct fscrypt_master_key {
	struct list_head	mk_decrypted_inodes;
	spinlock_t		mk_decrypted_inodes_lock;

	/* Crypto API transforms for DIRECT_KEY policies, allocated on-demand */
	struct crypto_skcipher	*mk_direct_tfms[__FSCRYPT_MODE_MAX + 1];

	/*
	 * Crypto API transforms for filesystem-layer implementation of
	 * IV_INO_LBLK_64 policies, allocated on-demand.
	 * Per-mode encryption keys for the various types of encryption policies
	 * that use them.  Allocated and derived on-demand.
	 */
	struct crypto_skcipher	*mk_iv_ino_lblk_64_tfms[__FSCRYPT_MODE_MAX + 1];
	struct crypto_skcipher *mk_direct_keys[__FSCRYPT_MODE_MAX + 1];
	struct crypto_skcipher *mk_iv_ino_lblk_64_keys[__FSCRYPT_MODE_MAX + 1];
	struct crypto_skcipher *mk_iv_ino_lblk_32_keys[__FSCRYPT_MODE_MAX + 1];

	/* Hash key for inode numbers.  Initialized only when needed. */
	siphash_key_t		mk_ino_hash_key;
	bool			mk_ino_hash_key_initialized;

} __randomize_layout;

@@ -436,14 +441,17 @@ static inline int master_key_spec_len(const struct fscrypt_key_specifier *spec)
	return 0;
}

extern struct key *
struct key *
fscrypt_find_master_key(struct super_block *sb,
			const struct fscrypt_key_specifier *mk_spec);

extern int fscrypt_verify_key_added(struct super_block *sb,
int fscrypt_add_test_dummy_key(struct super_block *sb,
			       struct fscrypt_key_specifier *key_spec);

int fscrypt_verify_key_added(struct super_block *sb,
			     const u8 identifier[FSCRYPT_KEY_IDENTIFIER_SIZE]);

extern int __init fscrypt_init_keyring(void);
int __init fscrypt_init_keyring(void);

/* keysetup.c */

@@ -457,32 +465,31 @@ struct fscrypt_mode {

extern struct fscrypt_mode fscrypt_modes[];

extern struct crypto_skcipher *
fscrypt_allocate_skcipher(struct fscrypt_mode *mode, const u8 *raw_key,
struct crypto_skcipher *fscrypt_allocate_skcipher(struct fscrypt_mode *mode,
						  const u8 *raw_key,
						  const struct inode *inode);

extern int fscrypt_set_per_file_enc_key(struct fscrypt_info *ci,
					const u8 *raw_key);
int fscrypt_set_per_file_enc_key(struct fscrypt_info *ci, const u8 *raw_key);

extern int fscrypt_derive_dirhash_key(struct fscrypt_info *ci,
int fscrypt_derive_dirhash_key(struct fscrypt_info *ci,
			       const struct fscrypt_master_key *mk);

/* keysetup_v1.c */

extern void fscrypt_put_direct_key(struct fscrypt_direct_key *dk);
void fscrypt_put_direct_key(struct fscrypt_direct_key *dk);

extern int fscrypt_setup_v1_file_key(struct fscrypt_info *ci,
int fscrypt_setup_v1_file_key(struct fscrypt_info *ci,
			      const u8 *raw_master_key);

extern int fscrypt_setup_v1_file_key_via_subscribed_keyrings(
					struct fscrypt_info *ci);
int fscrypt_setup_v1_file_key_via_subscribed_keyrings(struct fscrypt_info *ci);

/* policy.c */

extern bool fscrypt_policies_equal(const union fscrypt_policy *policy1,
bool fscrypt_policies_equal(const union fscrypt_policy *policy1,
			    const union fscrypt_policy *policy2);
extern bool fscrypt_supported_policy(const union fscrypt_policy *policy_u,
bool fscrypt_supported_policy(const union fscrypt_policy *policy_u,
			      const struct inode *inode);
extern int fscrypt_policy_from_context(union fscrypt_policy *policy_u,
int fscrypt_policy_from_context(union fscrypt_policy *policy_u,
				const union fscrypt_context *ctx_u,
				int ctx_size);

Loading