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

Commit a8f636f2 authored by Eric Biggers's avatar Eric Biggers Committed by Gerrit - the friendly Code Review server
Browse files

ANDROID: block: require drivers to declare supported crypto key type(s)



We need a way to tell which type of keys the inline crypto hardware
supports (standard, wrapped, or both), so that fallbacks can be used
when needed (either blk-crypto-fallback, or fscrypt fs-layer crypto).

We can't simply assume that

    keyslot_mgmt_ll_ops::derive_raw_secret == NULL

means only standard keys are supported and that

    keyslot_mgmt_ll_ops::derive_raw_secret != NULL

means that only wrapped keys are supported, because device-mapper
devices always implement this method.  Also, hardware might support both
types of keys.

Therefore, add a field keyslot_manager::features which contains a
bitmask of flags which indicate the supported types of keys.  Drivers
will need to fill this in.  This patch makes the UFS standard crypto
code set BLK_CRYPTO_FEATURE_STANDARD_KEYS, but UFS variant drivers may
need to set BLK_CRYPTO_FEATURE_WRAPPED_KEYS instead.

Then, make keyslot_manager_crypto_mode_supported() take the key type
into account.

Bug: 137270441
Bug: 151100202
Test: 'atest vts_kernel_encryption_test' on Pixel 4 with the
      inline crypto patches backported, and also on Cuttlefish.
Change-Id: Ied846c2767c1fd2f438792dcfd3649157e68b005
Signed-off-by: default avatarEric Biggers <ebiggers@google.com>
Git-commit: 8f078b1b
Git-repo: https://android.googlesource.com/kernel/common/+/refs/heads/android-4.19


[neersoni@codeaurora.org: key capability parameter added for ufs and emmc]
Signed-off-by: default avatarNeeraj Soni <neersoni@codeaurora.org>
parent 96101a1c
Loading
Loading
Loading
Loading
+5 −3
Original line number Diff line number Diff line
@@ -600,8 +600,10 @@ int __init blk_crypto_fallback_init(void)
		crypto_mode_supported[i] = 0xFFFFFFFF;
	crypto_mode_supported[BLK_ENCRYPTION_MODE_INVALID] = 0;

	blk_crypto_ksm = keyslot_manager_create(NULL, blk_crypto_num_keyslots,
	blk_crypto_ksm = keyslot_manager_create(
				NULL, blk_crypto_num_keyslots,
				&blk_crypto_ksm_ll_ops,
				BLK_CRYPTO_FEATURE_STANDARD_KEYS,
				crypto_mode_supported, NULL);
	if (!blk_crypto_ksm)
		return -ENOMEM;
+12 −3
Original line number Diff line number Diff line
@@ -109,7 +109,8 @@ 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,
						  bc->bc_key->data_unit_size)) {
						  bc->bc_key->data_unit_size,
						  bc->bc_key->is_hw_wrapped)) {
		err = bio_crypt_ctx_acquire_keyslot(bc, q->ksm);
		if (!err)
			return 0;
@@ -236,6 +237,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
 * @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
 *
 * Upper layers must call this function to ensure that either the hardware
@@ -248,11 +250,17 @@ EXPORT_SYMBOL_GPL(blk_crypto_init_key);
 */
int blk_crypto_start_using_mode(enum blk_crypto_mode_num crypto_mode,
				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))
						  data_unit_size,
						  is_hw_wrapped_key))
		return 0;
	if (is_hw_wrapped_key) {
		pr_warn_once("hardware doesn't support wrapped keys\n");
		return -EOPNOTSUPP;
	}
	return blk_crypto_fallback_start_using_mode(crypto_mode);
}
EXPORT_SYMBOL_GPL(blk_crypto_start_using_mode);
@@ -277,7 +285,8 @@ int blk_crypto_evict_key(struct request_queue *q,
{
	if (q->ksm &&
	    keyslot_manager_crypto_mode_supported(q->ksm, key->crypto_mode,
						  key->data_unit_size))
						  key->data_unit_size,
						  key->is_hw_wrapped))
		return keyslot_manager_evict_key(q->ksm, key);

	return blk_crypto_fallback_evict_key(key);
+24 −6
Original line number Diff line number Diff line
@@ -43,6 +43,7 @@ struct keyslot {
struct keyslot_manager {
	unsigned int num_slots;
	struct keyslot_mgmt_ll_ops ksm_ll_ops;
	unsigned int features;
	unsigned int crypto_mode_supported[BLK_ENCRYPTION_MODE_MAX];
	void *ll_priv_data;

@@ -135,6 +136,8 @@ static inline void keyslot_manager_hw_exit(struct keyslot_manager *ksm)
 * @ksm_ll_ops: The struct keyslot_mgmt_ll_ops for the device that this keyslot
 *		manager will use to perform operations like programming and
 *		evicting keys.
 * @features: The supported features as a bitmask of BLK_CRYPTO_FEATURE_* flags.
 *	      Most drivers should set BLK_CRYPTO_FEATURE_STANDARD_KEYS here.
 * @crypto_mode_supported:	Array of size BLK_ENCRYPTION_MODE_MAX of
 *				bitmasks that represents whether a crypto mode
 *				and data unit size are supported. The i'th bit
@@ -154,6 +157,7 @@ struct keyslot_manager *keyslot_manager_create(
	struct device *dev,
	unsigned int num_slots,
	const struct keyslot_mgmt_ll_ops *ksm_ll_ops,
	unsigned int features,
	const unsigned int crypto_mode_supported[BLK_ENCRYPTION_MODE_MAX],
	void *ll_priv_data)
{
@@ -175,6 +179,7 @@ struct keyslot_manager *keyslot_manager_create(

	ksm->num_slots = num_slots;
	ksm->ksm_ll_ops = *ksm_ll_ops;
	ksm->features = features;
	memcpy(ksm->crypto_mode_supported, crypto_mode_supported,
	       sizeof(ksm->crypto_mode_supported));
	ksm->ll_priv_data = ll_priv_data;
@@ -381,23 +386,24 @@ void keyslot_manager_put_slot(struct keyslot_manager *ksm, unsigned int slot)
}

/**
 * keyslot_manager_crypto_mode_supported() - Find out if a crypto_mode/data
 *					     unit size combination is supported
 *					     by a ksm.
 * keyslot_manager_crypto_mode_supported() - Find out if a crypto_mode /
 *					     data unit size / is_hw_wrapped_key
 *					     combination is supported by a ksm.
 * @ksm: The keyslot manager to check
 * @crypto_mode: The crypto mode to check for.
 * @data_unit_size: The data_unit_size for the mode.
 * @is_hw_wrapped_key: Whether a hardware-wrapped key will be used.
 *
 * Calls and returns the result of the crypto_mode_supported function specified
 * by the ksm.
 *
 * Context: Process context.
 * Return: Whether or not this ksm supports the specified crypto_mode/
 *	   data_unit_size combo.
 * Return: Whether or not this ksm supports the specified crypto settings.
 */
bool keyslot_manager_crypto_mode_supported(struct keyslot_manager *ksm,
					   enum blk_crypto_mode_num crypto_mode,
					   unsigned int data_unit_size)
					   unsigned int data_unit_size,
					   bool is_hw_wrapped_key)
{
	if (!ksm)
		return false;
@@ -405,6 +411,13 @@ bool keyslot_manager_crypto_mode_supported(struct keyslot_manager *ksm,
		return false;
	if (WARN_ON(!is_power_of_2(data_unit_size)))
		return false;
	if (is_hw_wrapped_key) {
		if (!(ksm->features & BLK_CRYPTO_FEATURE_WRAPPED_KEYS))
			return false;
	} else {
		if (!(ksm->features & BLK_CRYPTO_FEATURE_STANDARD_KEYS))
			return false;
	}
	return ksm->crypto_mode_supported[crypto_mode] & data_unit_size;
}

@@ -520,6 +533,7 @@ EXPORT_SYMBOL_GPL(keyslot_manager_destroy);
 * keyslot_manager_create_passthrough() - Create a passthrough keyslot manager
 * @dev: Device for runtime power management (NULL if none)
 * @ksm_ll_ops: The struct keyslot_mgmt_ll_ops
 * @features: Bitmask of BLK_CRYPTO_FEATURE_* flags
 * @crypto_mode_supported: Bitmasks for supported encryption modes
 * @ll_priv_data: Private data passed as is to the functions in ksm_ll_ops.
 *
@@ -537,6 +551,7 @@ EXPORT_SYMBOL_GPL(keyslot_manager_destroy);
struct keyslot_manager *keyslot_manager_create_passthrough(
	struct device *dev,
	const struct keyslot_mgmt_ll_ops *ksm_ll_ops,
	unsigned int features,
	const unsigned int crypto_mode_supported[BLK_ENCRYPTION_MODE_MAX],
	void *ll_priv_data)
{
@@ -547,6 +562,7 @@ struct keyslot_manager *keyslot_manager_create_passthrough(
		return NULL;

	ksm->ksm_ll_ops = *ksm_ll_ops;
	ksm->features = features;
	memcpy(ksm->crypto_mode_supported, crypto_mode_supported,
	       sizeof(ksm->crypto_mode_supported));
	ksm->ll_priv_data = ll_priv_data;
@@ -575,11 +591,13 @@ void keyslot_manager_intersect_modes(struct keyslot_manager *parent,
	if (child) {
		unsigned int i;

		parent->features &= child->features;
		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;
		memset(parent->crypto_mode_supported, 0,
		       sizeof(parent->crypto_mode_supported));
	}
+1 −0
Original line number Diff line number Diff line
@@ -292,6 +292,7 @@ static int default_key_ctr(struct dm_target *ti, unsigned int argc, char **argv)
	}

	err = blk_crypto_start_using_mode(cipher->mode_num, dkc->sector_size,
					  dkc->is_hw_wrapped,
					  dkc->dev->bdev->bd_queue);
	if (err) {
		ti->error = "Error starting to use blk-crypto";
+7 −2
Original line number Diff line number Diff line
@@ -2350,16 +2350,21 @@ static struct keyslot_mgmt_ll_ops dm_ksm_ll_ops = {

static int dm_init_inline_encryption(struct mapped_device *md)
{
	unsigned int features;
	unsigned int mode_masks[BLK_ENCRYPTION_MODE_MAX];

	/*
	 * Start out with all crypto mode support bits set.  Any unsupported
	 * bits will be cleared later when calculating the device restrictions.
	 * Initially declare support for all crypto settings.  Anything
	 * unsupported by a child device will be removed later when calculating
	 * the device restrictions.
	 */
	features = BLK_CRYPTO_FEATURE_STANDARD_KEYS |
		   BLK_CRYPTO_FEATURE_WRAPPED_KEYS;
	memset(mode_masks, 0xFF, sizeof(mode_masks));

	md->queue->ksm = keyslot_manager_create_passthrough(NULL,
							    &dm_ksm_ll_ops,
							    features,
							    mode_masks, md);
	if (!md->queue->ksm)
		return -ENOMEM;
Loading