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

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

Merge "mmc: host: Set the supported dun size for crypto"

parents 7a0a9203 b3dc7689
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 −5
Original line number Diff line number Diff line
@@ -109,6 +109,7 @@ int blk_crypto_submit_bio(struct bio **bio_ptr)
	/* Get device keyslot if supported */
	if (keyslot_manager_crypto_mode_supported(q->ksm,
				bc->bc_key->crypto_mode,
				blk_crypto_key_dun_bytes(bc->bc_key),
				bc->bc_key->data_unit_size,
				bc->bc_key->is_hw_wrapped)) {
		err = bio_crypt_ctx_acquire_keyslot(bc, q->ksm);
@@ -180,6 +181,8 @@ bool blk_crypto_endio(struct bio *bio)
 *                @is_hw_wrapped has to be set for such keys)
 * @is_hw_wrapped: Denotes @raw_key is wrapped.
 * @crypto_mode: identifier for the encryption algorithm to use
 * @dun_bytes: number of bytes that will be used to specify the DUN when this
 *	       key is used
 * @data_unit_size: the data unit size to use for en/decryption
 *
 * Return: The blk_crypto_key that was prepared, or an ERR_PTR() on error.  When
@@ -189,10 +192,12 @@ int blk_crypto_init_key(struct blk_crypto_key *blk_key,
			const u8 *raw_key, unsigned int raw_key_size,
			bool is_hw_wrapped,
			enum blk_crypto_mode_num crypto_mode,
			unsigned int dun_bytes,
			unsigned int data_unit_size)
{
	const struct blk_crypto_mode *mode;
	static siphash_key_t hash_key;
	u32 hash;

	memset(blk_key, 0, sizeof(*blk_key));

@@ -211,6 +216,9 @@ int blk_crypto_init_key(struct blk_crypto_key *blk_key,
			return -EINVAL;
	}

	if (dun_bytes <= 0 || dun_bytes > BLK_CRYPTO_MAX_IV_SIZE)
		return -EINVAL;

	if (!is_power_of_2(data_unit_size))
		return -EINVAL;

@@ -227,7 +235,8 @@ int blk_crypto_init_key(struct blk_crypto_key *blk_key,
	 * precomputed here so that it only needs to be computed once per key.
	 */
	get_random_once(&hash_key, sizeof(hash_key));
	blk_key->hash = siphash(raw_key, raw_key_size, &hash_key);
	hash = (u32)siphash(raw_key, raw_key_size, &hash_key);
	blk_crypto_key_set_hash_and_dun_bytes(blk_key, hash, dun_bytes);

	return 0;
}
@@ -236,6 +245,7 @@ EXPORT_SYMBOL_GPL(blk_crypto_init_key);
/**
 * blk_crypto_start_using_mode() - Start using blk-crypto on a device
 * @crypto_mode: the crypto mode that will be used
 * @dun_bytes: number of bytes that will be used to specify the DUN
 * @data_unit_size: the data unit size that will be used
 * @is_hw_wrapped_key: whether the key will be hardware-wrapped
 * @q: the request queue for the device
@@ -249,12 +259,13 @@ EXPORT_SYMBOL_GPL(blk_crypto_init_key);
 *	   algorithm is disabled in the crypto API; or another -errno code.
 */
int blk_crypto_start_using_mode(enum blk_crypto_mode_num crypto_mode,
				unsigned int dun_bytes,
				unsigned int data_unit_size,
				bool is_hw_wrapped_key,
				struct request_queue *q)
{
	if (keyslot_manager_crypto_mode_supported(q->ksm, crypto_mode,
						  data_unit_size,
						  dun_bytes, data_unit_size,
						  is_hw_wrapped_key))
		return 0;
	if (is_hw_wrapped_key) {
@@ -285,6 +296,7 @@ int blk_crypto_evict_key(struct request_queue *q,
{
	if (q->ksm &&
	    keyslot_manager_crypto_mode_supported(q->ksm, key->crypto_mode,
						  blk_crypto_key_dun_bytes(key),
						  key->data_unit_size,
						  key->is_hw_wrapped))
		return keyslot_manager_evict_key(q->ksm, key);
+22 −2
Original line number Diff line number Diff line
@@ -45,6 +45,7 @@ struct keyslot_manager {
	struct keyslot_mgmt_ll_ops ksm_ll_ops;
	unsigned int features;
	unsigned int crypto_mode_supported[BLK_ENCRYPTION_MODE_MAX];
	unsigned int max_dun_bytes_supported;
	void *ll_priv_data;

	/* Protects programming and evicting keys from the device */
@@ -123,6 +124,7 @@ struct keyslot_manager *keyslot_manager_create(unsigned int num_slots,
	ksm->features = features;
	memcpy(ksm->crypto_mode_supported, crypto_mode_supported,
	       sizeof(ksm->crypto_mode_supported));
	ksm->max_dun_bytes_supported = BLK_CRYPTO_MAX_IV_SIZE;
	ksm->ll_priv_data = ll_priv_data;

	init_rwsem(&ksm->lock);
@@ -154,11 +156,19 @@ struct keyslot_manager *keyslot_manager_create(unsigned int num_slots,
}
EXPORT_SYMBOL_GPL(keyslot_manager_create);

void keyslot_manager_set_max_dun_bytes(struct keyslot_manager *ksm,
				       unsigned int max_dun_bytes)
{
	ksm->max_dun_bytes_supported = max_dun_bytes;
}
EXPORT_SYMBOL_GPL(keyslot_manager_set_max_dun_bytes);

static inline struct hlist_head *
hash_bucket_for_key(struct keyslot_manager *ksm,
		    const struct blk_crypto_key *key)
{
	return &ksm->slot_hashtable[key->hash & (ksm->slot_hashtable_size - 1)];
	return &ksm->slot_hashtable[blk_crypto_key_hash(key) &
				    (ksm->slot_hashtable_size - 1)];
}

static void remove_slot_from_lru_list(struct keyslot_manager *ksm, int slot)
@@ -331,6 +341,7 @@ void keyslot_manager_put_slot(struct keyslot_manager *ksm, unsigned int slot)
 *					     combination is supported by a ksm.
 * @ksm: The keyslot manager to check
 * @crypto_mode: The crypto mode to check for.
 * @dun_bytes: The number of bytes that will be used to specify the DUN
 * @data_unit_size: The data_unit_size for the mode.
 * @is_hw_wrapped_key: Whether a hardware-wrapped key will be used.
 *
@@ -342,6 +353,7 @@ void keyslot_manager_put_slot(struct keyslot_manager *ksm, unsigned int slot)
 */
bool keyslot_manager_crypto_mode_supported(struct keyslot_manager *ksm,
					   enum blk_crypto_mode_num crypto_mode,
					   unsigned int dun_bytes,
					   unsigned int data_unit_size,
					   bool is_hw_wrapped_key)
{
@@ -358,7 +370,10 @@ bool keyslot_manager_crypto_mode_supported(struct keyslot_manager *ksm,
		if (!(ksm->features & BLK_CRYPTO_FEATURE_STANDARD_KEYS))
			return false;
	}
	return ksm->crypto_mode_supported[crypto_mode] & data_unit_size;
	if (!(ksm->crypto_mode_supported[crypto_mode] & data_unit_size))
		return false;

	return ksm->max_dun_bytes_supported >= dun_bytes;
}

/**
@@ -501,6 +516,7 @@ struct keyslot_manager *keyslot_manager_create_passthrough(
	ksm->features = features;
	memcpy(ksm->crypto_mode_supported, crypto_mode_supported,
	       sizeof(ksm->crypto_mode_supported));
	ksm->max_dun_bytes_supported = BLK_CRYPTO_MAX_IV_SIZE;
	ksm->ll_priv_data = ll_priv_data;

	init_rwsem(&ksm->lock);
@@ -527,12 +543,16 @@ void keyslot_manager_intersect_modes(struct keyslot_manager *parent,
		unsigned int i;

		parent->features &= child->features;
		parent->max_dun_bytes_supported =
			min(parent->max_dun_bytes_supported,
			    child->max_dun_bytes_supported);
		for (i = 0; i < ARRAY_SIZE(child->crypto_mode_supported); i++) {
			parent->crypto_mode_supported[i] &=
				child->crypto_mode_supported[i];
		}
	} else {
		parent->features = 0;
		parent->max_dun_bytes_supported = 0;
		memset(parent->crypto_mode_supported, 0,
		       sizeof(parent->crypto_mode_supported));
	}
+18 −4
Original line number Diff line number Diff line
@@ -40,6 +40,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;
@@ -50,6 +51,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 *
@@ -165,6 +167,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;
@@ -251,16 +254,20 @@ 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,
				  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, dkc->sector_size,
					  dkc->is_hw_wrapped,
	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) {
		ti->error = "Error starting to use blk-crypto";
@@ -321,6 +328,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;
+2 −0
Original line number Diff line number Diff line
@@ -231,6 +231,8 @@ int cmdq_host_init_crypto_qti_spec(struct cmdq_host *host,
		err = -ENOMEM;
		goto out;
	}
	keyslot_manager_set_max_dun_bytes(host->ksm, sizeof(u32));

	/*
	 * In case host controller supports cryptographic operations
	 * then, it uses 128bit task descriptor. Upper 64 bits of task
Loading