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: Eric Biggers <ebiggers@google.com>
Git-commit: 8f078b1b3a
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: Neeraj Soni <neersoni@codeaurora.org>
This commit is contained in:
Eric Biggers 2020-04-03 12:06:11 -07:00 committed by Gerrit - the friendly Code Review server
parent 96101a1c1f
commit a8f636f2ba
12 changed files with 79 additions and 22 deletions

View File

@ -600,9 +600,11 @@ int __init blk_crypto_fallback_init(void)
crypto_mode_supported[i] = 0xFFFFFFFF; crypto_mode_supported[i] = 0xFFFFFFFF;
crypto_mode_supported[BLK_ENCRYPTION_MODE_INVALID] = 0; 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(
&blk_crypto_ksm_ll_ops, NULL, blk_crypto_num_keyslots,
crypto_mode_supported, NULL); &blk_crypto_ksm_ll_ops,
BLK_CRYPTO_FEATURE_STANDARD_KEYS,
crypto_mode_supported, NULL);
if (!blk_crypto_ksm) if (!blk_crypto_ksm)
return -ENOMEM; return -ENOMEM;

View File

@ -109,7 +109,8 @@ int blk_crypto_submit_bio(struct bio **bio_ptr)
/* Get device keyslot if supported */ /* Get device keyslot if supported */
if (keyslot_manager_crypto_mode_supported(q->ksm, if (keyslot_manager_crypto_mode_supported(q->ksm,
bc->bc_key->crypto_mode, 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); err = bio_crypt_ctx_acquire_keyslot(bc, q->ksm);
if (!err) if (!err)
return 0; 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 * blk_crypto_start_using_mode() - Start using blk-crypto on a device
* @crypto_mode: the crypto mode that will be used * @crypto_mode: the crypto mode that will be used
* @data_unit_size: the data unit size 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 * @q: the request queue for the device
* *
* Upper layers must call this function to ensure that either the hardware * 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, int blk_crypto_start_using_mode(enum blk_crypto_mode_num crypto_mode,
unsigned int data_unit_size, unsigned int data_unit_size,
bool is_hw_wrapped_key,
struct request_queue *q) struct request_queue *q)
{ {
if (keyslot_manager_crypto_mode_supported(q->ksm, crypto_mode, if (keyslot_manager_crypto_mode_supported(q->ksm, crypto_mode,
data_unit_size)) data_unit_size,
is_hw_wrapped_key))
return 0; 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); return blk_crypto_fallback_start_using_mode(crypto_mode);
} }
EXPORT_SYMBOL_GPL(blk_crypto_start_using_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 && if (q->ksm &&
keyslot_manager_crypto_mode_supported(q->ksm, key->crypto_mode, 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 keyslot_manager_evict_key(q->ksm, key);
return blk_crypto_fallback_evict_key(key); return blk_crypto_fallback_evict_key(key);

View File

@ -43,6 +43,7 @@ struct keyslot {
struct keyslot_manager { struct keyslot_manager {
unsigned int num_slots; unsigned int num_slots;
struct keyslot_mgmt_ll_ops ksm_ll_ops; struct keyslot_mgmt_ll_ops ksm_ll_ops;
unsigned int features;
unsigned int crypto_mode_supported[BLK_ENCRYPTION_MODE_MAX]; unsigned int crypto_mode_supported[BLK_ENCRYPTION_MODE_MAX];
void *ll_priv_data; 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 * @ksm_ll_ops: The struct keyslot_mgmt_ll_ops for the device that this keyslot
* manager will use to perform operations like programming and * manager will use to perform operations like programming and
* evicting keys. * 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 * @crypto_mode_supported: Array of size BLK_ENCRYPTION_MODE_MAX of
* bitmasks that represents whether a crypto mode * bitmasks that represents whether a crypto mode
* and data unit size are supported. The i'th bit * and data unit size are supported. The i'th bit
@ -154,6 +157,7 @@ struct keyslot_manager *keyslot_manager_create(
struct device *dev, struct device *dev,
unsigned int num_slots, unsigned int num_slots,
const struct keyslot_mgmt_ll_ops *ksm_ll_ops, const struct keyslot_mgmt_ll_ops *ksm_ll_ops,
unsigned int features,
const unsigned int crypto_mode_supported[BLK_ENCRYPTION_MODE_MAX], const unsigned int crypto_mode_supported[BLK_ENCRYPTION_MODE_MAX],
void *ll_priv_data) void *ll_priv_data)
{ {
@ -175,6 +179,7 @@ struct keyslot_manager *keyslot_manager_create(
ksm->num_slots = num_slots; ksm->num_slots = num_slots;
ksm->ksm_ll_ops = *ksm_ll_ops; ksm->ksm_ll_ops = *ksm_ll_ops;
ksm->features = features;
memcpy(ksm->crypto_mode_supported, crypto_mode_supported, memcpy(ksm->crypto_mode_supported, crypto_mode_supported,
sizeof(ksm->crypto_mode_supported)); sizeof(ksm->crypto_mode_supported));
ksm->ll_priv_data = ll_priv_data; 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 * keyslot_manager_crypto_mode_supported() - Find out if a crypto_mode /
* unit size combination is supported * data unit size / is_hw_wrapped_key
* by a ksm. * combination is supported by a ksm.
* @ksm: The keyslot manager to check * @ksm: The keyslot manager to check
* @crypto_mode: The crypto mode to check for. * @crypto_mode: The crypto mode to check for.
* @data_unit_size: The data_unit_size for the mode. * @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 * Calls and returns the result of the crypto_mode_supported function specified
* by the ksm. * by the ksm.
* *
* Context: Process context. * Context: Process context.
* Return: Whether or not this ksm supports the specified crypto_mode/ * Return: Whether or not this ksm supports the specified crypto settings.
* data_unit_size combo.
*/ */
bool keyslot_manager_crypto_mode_supported(struct keyslot_manager *ksm, bool keyslot_manager_crypto_mode_supported(struct keyslot_manager *ksm,
enum blk_crypto_mode_num crypto_mode, enum blk_crypto_mode_num crypto_mode,
unsigned int data_unit_size) unsigned int data_unit_size,
bool is_hw_wrapped_key)
{ {
if (!ksm) if (!ksm)
return false; return false;
@ -405,6 +411,13 @@ bool keyslot_manager_crypto_mode_supported(struct keyslot_manager *ksm,
return false; return false;
if (WARN_ON(!is_power_of_2(data_unit_size))) if (WARN_ON(!is_power_of_2(data_unit_size)))
return false; 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; 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 * keyslot_manager_create_passthrough() - Create a passthrough keyslot manager
* @dev: Device for runtime power management (NULL if none) * @dev: Device for runtime power management (NULL if none)
* @ksm_ll_ops: The struct keyslot_mgmt_ll_ops * @ksm_ll_ops: The struct keyslot_mgmt_ll_ops
* @features: Bitmask of BLK_CRYPTO_FEATURE_* flags
* @crypto_mode_supported: Bitmasks for supported encryption modes * @crypto_mode_supported: Bitmasks for supported encryption modes
* @ll_priv_data: Private data passed as is to the functions in ksm_ll_ops. * @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 keyslot_manager *keyslot_manager_create_passthrough(
struct device *dev, struct device *dev,
const struct keyslot_mgmt_ll_ops *ksm_ll_ops, const struct keyslot_mgmt_ll_ops *ksm_ll_ops,
unsigned int features,
const unsigned int crypto_mode_supported[BLK_ENCRYPTION_MODE_MAX], const unsigned int crypto_mode_supported[BLK_ENCRYPTION_MODE_MAX],
void *ll_priv_data) void *ll_priv_data)
{ {
@ -547,6 +562,7 @@ struct keyslot_manager *keyslot_manager_create_passthrough(
return NULL; return NULL;
ksm->ksm_ll_ops = *ksm_ll_ops; ksm->ksm_ll_ops = *ksm_ll_ops;
ksm->features = features;
memcpy(ksm->crypto_mode_supported, crypto_mode_supported, memcpy(ksm->crypto_mode_supported, crypto_mode_supported,
sizeof(ksm->crypto_mode_supported)); sizeof(ksm->crypto_mode_supported));
ksm->ll_priv_data = ll_priv_data; ksm->ll_priv_data = ll_priv_data;
@ -575,11 +591,13 @@ void keyslot_manager_intersect_modes(struct keyslot_manager *parent,
if (child) { if (child) {
unsigned int i; unsigned int i;
parent->features &= child->features;
for (i = 0; i < ARRAY_SIZE(child->crypto_mode_supported); i++) { for (i = 0; i < ARRAY_SIZE(child->crypto_mode_supported); i++) {
parent->crypto_mode_supported[i] &= parent->crypto_mode_supported[i] &=
child->crypto_mode_supported[i]; child->crypto_mode_supported[i];
} }
} else { } else {
parent->features = 0;
memset(parent->crypto_mode_supported, 0, memset(parent->crypto_mode_supported, 0,
sizeof(parent->crypto_mode_supported)); sizeof(parent->crypto_mode_supported));
} }

View File

@ -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, err = blk_crypto_start_using_mode(cipher->mode_num, dkc->sector_size,
dkc->is_hw_wrapped,
dkc->dev->bdev->bd_queue); dkc->dev->bdev->bd_queue);
if (err) { if (err) {
ti->error = "Error starting to use blk-crypto"; ti->error = "Error starting to use blk-crypto";

View File

@ -2350,16 +2350,21 @@ static struct keyslot_mgmt_ll_ops dm_ksm_ll_ops = {
static int dm_init_inline_encryption(struct mapped_device *md) static int dm_init_inline_encryption(struct mapped_device *md)
{ {
unsigned int features;
unsigned int mode_masks[BLK_ENCRYPTION_MODE_MAX]; unsigned int mode_masks[BLK_ENCRYPTION_MODE_MAX];
/* /*
* Start out with all crypto mode support bits set. Any unsupported * Initially declare support for all crypto settings. Anything
* bits will be cleared later when calculating the device restrictions. * 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)); memset(mode_masks, 0xFF, sizeof(mode_masks));
md->queue->ksm = keyslot_manager_create_passthrough(NULL, md->queue->ksm = keyslot_manager_create_passthrough(NULL,
&dm_ksm_ll_ops, &dm_ksm_ll_ops,
features,
mode_masks, md); mode_masks, md);
if (!md->queue->ksm) if (!md->queue->ksm)
return -ENOMEM; return -ENOMEM;

View File

@ -221,9 +221,10 @@ int cqhci_host_init_crypto_qti_spec(struct cqhci_host *host,
} }
host->ksm = keyslot_manager_create(host->mmc->parent, host->ksm = keyslot_manager_create(host->mmc->parent,
cqhci_num_keyslots(host), cqhci_num_keyslots(host), ksm_ops,
ksm_ops, crypto_modes_supported, BLK_CRYPTO_FEATURE_STANDARD_KEYS |
host); BLK_CRYPTO_FEATURE_WRAPPED_KEYS,
crypto_modes_supported, host);
if (!host->ksm) { if (!host->ksm) {
err = -ENOMEM; err = -ENOMEM;

View File

@ -335,8 +335,10 @@ int cqhci_host_init_crypto_spec(struct cqhci_host *host,
cqhci_crypto_clear_all_keyslots(host); cqhci_crypto_clear_all_keyslots(host);
host->ksm = keyslot_manager_create(host->mmc->parent, host->ksm = keyslot_manager_create(host->mmc->parent,
cqhci_num_keyslots(host), cqhci_num_keyslots(host), ksm_ops,
ksm_ops, crypto_modes_supported, BLK_CRYPTO_FEATURE_STANDARD_KEYS |
BLK_CRYPTO_FEATURE_WRAPPED_KEYS,
crypto_modes_supported,
host); host);
if (!host->ksm) { if (!host->ksm) {

View File

@ -237,7 +237,10 @@ static int ufshcd_hba_init_crypto_qti_spec(struct ufs_hba *hba,
} }
hba->ksm = keyslot_manager_create(hba->dev, ufshcd_num_keyslots(hba), hba->ksm = keyslot_manager_create(hba->dev, ufshcd_num_keyslots(hba),
ksm_ops, crypto_modes_supported, hba); ksm_ops,
BLK_CRYPTO_FEATURE_STANDARD_KEYS |
BLK_CRYPTO_FEATURE_WRAPPED_KEYS,
crypto_modes_supported, hba);
if (!hba->ksm) { if (!hba->ksm) {
err = -ENOMEM; err = -ENOMEM;

View File

@ -336,7 +336,9 @@ int ufshcd_hba_init_crypto_spec(struct ufs_hba *hba,
ufshcd_clear_all_keyslots(hba); ufshcd_clear_all_keyslots(hba);
hba->ksm = keyslot_manager_create(hba->dev, ufshcd_num_keyslots(hba), hba->ksm = keyslot_manager_create(hba->dev, ufshcd_num_keyslots(hba),
ksm_ops, crypto_modes_supported, hba); ksm_ops,
BLK_CRYPTO_FEATURE_STANDARD_KEYS,
crypto_modes_supported, hba);
if (!hba->ksm) { if (!hba->ksm) {
err = -ENOMEM; err = -ENOMEM;

View File

@ -103,6 +103,7 @@ int fscrypt_prepare_inline_crypt_key(struct fscrypt_prepared_key *prep_key,
queue_refs++; queue_refs++;
err = blk_crypto_start_using_mode(crypto_mode, sb->s_blocksize, err = blk_crypto_start_using_mode(crypto_mode, sb->s_blocksize,
is_hw_wrapped,
blk_key->devs[i]); blk_key->devs[i]);
if (err) { if (err) {
fscrypt_err(inode, fscrypt_err(inode,

View File

@ -22,6 +22,7 @@ int blk_crypto_init_key(struct blk_crypto_key *blk_key,
int blk_crypto_start_using_mode(enum blk_crypto_mode_num crypto_mode, int blk_crypto_start_using_mode(enum blk_crypto_mode_num crypto_mode,
unsigned int data_unit_size, unsigned int data_unit_size,
bool is_hw_wrapped_key,
struct request_queue *q); struct request_queue *q);
int blk_crypto_evict_key(struct request_queue *q, int blk_crypto_evict_key(struct request_queue *q,

View File

@ -8,6 +8,15 @@
#include <linux/bio.h> #include <linux/bio.h>
/* Inline crypto feature bits. Must set at least one. */
enum {
/* Support for standard software-specified keys */
BLK_CRYPTO_FEATURE_STANDARD_KEYS = BIT(0),
/* Support for hardware-wrapped keys */
BLK_CRYPTO_FEATURE_WRAPPED_KEYS = BIT(1),
};
#ifdef CONFIG_BLK_INLINE_ENCRYPTION #ifdef CONFIG_BLK_INLINE_ENCRYPTION
struct keyslot_manager; struct keyslot_manager;
@ -45,6 +54,7 @@ struct keyslot_manager *keyslot_manager_create(
struct device *dev, struct device *dev,
unsigned int num_slots, unsigned int num_slots,
const struct keyslot_mgmt_ll_ops *ksm_ops, const struct keyslot_mgmt_ll_ops *ksm_ops,
unsigned int features,
const unsigned int crypto_mode_supported[BLK_ENCRYPTION_MODE_MAX], const unsigned int crypto_mode_supported[BLK_ENCRYPTION_MODE_MAX],
void *ll_priv_data); void *ll_priv_data);
@ -57,7 +67,8 @@ void keyslot_manager_put_slot(struct keyslot_manager *ksm, unsigned int slot);
bool keyslot_manager_crypto_mode_supported(struct keyslot_manager *ksm, bool keyslot_manager_crypto_mode_supported(struct keyslot_manager *ksm,
enum blk_crypto_mode_num crypto_mode, enum blk_crypto_mode_num crypto_mode,
unsigned int data_unit_size); unsigned int data_unit_size,
bool is_hw_wrapped_key);
int keyslot_manager_evict_key(struct keyslot_manager *ksm, int keyslot_manager_evict_key(struct keyslot_manager *ksm,
const struct blk_crypto_key *key); const struct blk_crypto_key *key);
@ -71,6 +82,7 @@ void keyslot_manager_destroy(struct keyslot_manager *ksm);
struct keyslot_manager *keyslot_manager_create_passthrough( struct keyslot_manager *keyslot_manager_create_passthrough(
struct device *dev, struct device *dev,
const struct keyslot_mgmt_ll_ops *ksm_ops, const struct keyslot_mgmt_ll_ops *ksm_ops,
unsigned int features,
const unsigned int crypto_mode_supported[BLK_ENCRYPTION_MODE_MAX], const unsigned int crypto_mode_supported[BLK_ENCRYPTION_MODE_MAX],
void *ll_priv_data); void *ll_priv_data);