Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8ab4496d authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "BACKPORT: FROMLIST: fscrypt: add support for IV_INO_LBLK_32 policies"

parents 928987bd e470a75e
Loading
Loading
Loading
Loading
+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.

+17 −3
Original line number Diff line number Diff line
@@ -38,6 +38,7 @@ static const struct dm_default_key_cipher {
 * @sector_size: crypto sector size in bytes (usually 4096)
 * @sector_bits: log2(sector_size)
 * @key: the encryption key to use
 * @max_dun: the maximum DUN that may be used (computed from other params)
 */
struct default_key_c {
	struct dm_dev *dev;
@@ -48,6 +49,7 @@ struct default_key_c {
	unsigned int sector_bits;
	struct blk_crypto_key key;
	bool is_hw_wrapped;
	u64 max_dun;
};

static const struct dm_default_key_cipher *
@@ -178,6 +180,7 @@ static int default_key_ctr(struct dm_target *ti, unsigned int argc, char **argv)
	const struct dm_default_key_cipher *cipher;
	u8 raw_key[DM_DEFAULT_KEY_MAX_WRAPPED_KEY_SIZE];
	unsigned int raw_key_size;
	unsigned int dun_bytes;
	unsigned long long tmpll;
	char dummy;
	int err;
@@ -283,15 +286,19 @@ static int default_key_ctr(struct dm_target *ti, unsigned int argc, char **argv)
		goto bad;
	}

	err = blk_crypto_init_key(&dkc->key, raw_key, cipher->key_size,
	dkc->max_dun = (dkc->iv_offset + ti->len - 1) >>
		       (dkc->sector_bits - SECTOR_SHIFT);
	dun_bytes = DIV_ROUND_UP(fls64(dkc->max_dun), 8);

	err = blk_crypto_init_key(&dkc->key, raw_key, raw_key_size,
				  dkc->is_hw_wrapped, cipher->mode_num,
				  sizeof(u64), dkc->sector_size);
				  dun_bytes, dkc->sector_size);
	if (err) {
		ti->error = "Error initializing blk-crypto key";
		goto bad;
	}

	err = blk_crypto_start_using_mode(cipher->mode_num, sizeof(u64),
	err = blk_crypto_start_using_mode(cipher->mode_num, dun_bytes,
					  dkc->sector_size, dkc->is_hw_wrapped,
					  dkc->dev->bdev->bd_queue);
	if (err) {
@@ -353,6 +360,13 @@ static int default_key_map(struct dm_target *ti, struct bio *bio)
		return DM_MAPIO_KILL;
	dun[0] >>= dkc->sector_bits - SECTOR_SHIFT; /* crypto sectors */

	/*
	 * This check isn't necessary as we should have calculated max_dun
	 * correctly, but be safe.
	 */
	if (WARN_ON_ONCE(dun[0] > dkc->max_dun))
		return DM_MAPIO_KILL;

	bio_crypt_set_ctx(bio, &dkc->key, dun, GFP_NOIO);

	return DM_MAPIO_REMAPPED;
+5 −1
Original line number Diff line number Diff line
@@ -82,8 +82,12 @@ void fscrypt_generate_iv(union fscrypt_iv *iv, u64 lblk_num,
	if (flags & FSCRYPT_POLICY_FLAG_IV_INO_LBLK_64 ||
		((fscrypt_policy_contents_mode(&ci->ci_policy) ==
		  FSCRYPT_MODE_PRIVATE) && inlinecrypt)) {
		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);
	}
+14 −3
Original line number Diff line number Diff line
@@ -246,6 +246,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 {
@@ -317,6 +320,8 @@ 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,
			       const u8 *info, unsigned int infolen,
@@ -513,11 +518,17 @@ struct fscrypt_master_key {
	struct list_head	mk_decrypted_inodes;
	spinlock_t		mk_decrypted_inodes_lock;

	/* Per-mode keys for DIRECT_KEY policies, allocated on-demand */
	/*
	 * Per-mode encryption keys for the various types of encryption policies
	 * that use them.  Allocated and derived on-demand.
	 */
	struct fscrypt_prepared_key mk_direct_keys[__FSCRYPT_MODE_MAX + 1];

	/* Per-mode keys for IV_INO_LBLK_64 policies, allocated on-demand */
	struct fscrypt_prepared_key mk_iv_ino_lblk_64_keys[__FSCRYPT_MODE_MAX + 1];
	struct fscrypt_prepared_key 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;

+15 −5
Original line number Diff line number Diff line
@@ -43,13 +43,23 @@ static void fscrypt_get_devices(struct super_block *sb, int num_devs,

static unsigned int fscrypt_get_dun_bytes(const struct fscrypt_info *ci)
{
	unsigned int dun_bytes = 8;
	struct super_block *sb = ci->ci_inode->i_sb;
	unsigned int flags = fscrypt_policy_flags(&ci->ci_policy);
	int ino_bits = 64, lblk_bits = 64;

	if (fscrypt_policy_flags(&ci->ci_policy) &
	    FSCRYPT_POLICY_FLAG_DIRECT_KEY)
		dun_bytes += FS_KEY_DERIVATION_NONCE_SIZE;
	if (flags & FSCRYPT_POLICY_FLAG_DIRECT_KEY)
		return offsetofend(union fscrypt_iv, nonce);

	return dun_bytes;
	if (flags & FSCRYPT_POLICY_FLAG_IV_INO_LBLK_64)
		return sizeof(__le64);

	if (flags & FSCRYPT_POLICY_FLAG_IV_INO_LBLK_32)
		return sizeof(__le32);

	/* Default case: IVs are just the file logical block number */
	if (sb->s_cop->get_ino_and_lblk_bits)
		sb->s_cop->get_ino_and_lblk_bits(sb, &ino_bits, &lblk_bits);
	return DIV_ROUND_UP(lblk_bits, 8);
}

/* Enable inline encryption for this file if supported. */
Loading