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:
parent
96101a1c1f
commit
a8f636f2ba
12 changed files with 79 additions and 22 deletions
|
@ -600,9 +600,11 @@ 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_ll_ops,
|
||||
crypto_mode_supported, NULL);
|
||||
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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -221,9 +221,10 @@ int cqhci_host_init_crypto_qti_spec(struct cqhci_host *host,
|
|||
}
|
||||
|
||||
host->ksm = keyslot_manager_create(host->mmc->parent,
|
||||
cqhci_num_keyslots(host),
|
||||
ksm_ops, crypto_modes_supported,
|
||||
host);
|
||||
cqhci_num_keyslots(host), ksm_ops,
|
||||
BLK_CRYPTO_FEATURE_STANDARD_KEYS |
|
||||
BLK_CRYPTO_FEATURE_WRAPPED_KEYS,
|
||||
crypto_modes_supported, host);
|
||||
|
||||
if (!host->ksm) {
|
||||
err = -ENOMEM;
|
||||
|
|
|
@ -335,8 +335,10 @@ int cqhci_host_init_crypto_spec(struct cqhci_host *host,
|
|||
cqhci_crypto_clear_all_keyslots(host);
|
||||
|
||||
host->ksm = keyslot_manager_create(host->mmc->parent,
|
||||
cqhci_num_keyslots(host),
|
||||
ksm_ops, crypto_modes_supported,
|
||||
cqhci_num_keyslots(host), ksm_ops,
|
||||
BLK_CRYPTO_FEATURE_STANDARD_KEYS |
|
||||
BLK_CRYPTO_FEATURE_WRAPPED_KEYS,
|
||||
crypto_modes_supported,
|
||||
host);
|
||||
|
||||
if (!host->ksm) {
|
||||
|
|
|
@ -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),
|
||||
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) {
|
||||
err = -ENOMEM;
|
||||
|
|
|
@ -336,7 +336,9 @@ int ufshcd_hba_init_crypto_spec(struct ufs_hba *hba,
|
|||
ufshcd_clear_all_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) {
|
||||
err = -ENOMEM;
|
||||
|
|
|
@ -103,6 +103,7 @@ int fscrypt_prepare_inline_crypt_key(struct fscrypt_prepared_key *prep_key,
|
|||
queue_refs++;
|
||||
|
||||
err = blk_crypto_start_using_mode(crypto_mode, sb->s_blocksize,
|
||||
is_hw_wrapped,
|
||||
blk_key->devs[i]);
|
||||
if (err) {
|
||||
fscrypt_err(inode,
|
||||
|
|
|
@ -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,
|
||||
unsigned int data_unit_size,
|
||||
bool is_hw_wrapped_key,
|
||||
struct request_queue *q);
|
||||
|
||||
int blk_crypto_evict_key(struct request_queue *q,
|
||||
|
|
|
@ -8,6 +8,15 @@
|
|||
|
||||
#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
|
||||
|
||||
struct keyslot_manager;
|
||||
|
@ -45,6 +54,7 @@ struct keyslot_manager *keyslot_manager_create(
|
|||
struct device *dev,
|
||||
unsigned int num_slots,
|
||||
const struct keyslot_mgmt_ll_ops *ksm_ops,
|
||||
unsigned int features,
|
||||
const unsigned int crypto_mode_supported[BLK_ENCRYPTION_MODE_MAX],
|
||||
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,
|
||||
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,
|
||||
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 device *dev,
|
||||
const struct keyslot_mgmt_ll_ops *ksm_ops,
|
||||
unsigned int features,
|
||||
const unsigned int crypto_mode_supported[BLK_ENCRYPTION_MODE_MAX],
|
||||
void *ll_priv_data);
|
||||
|
||||
|
|
Loading…
Reference in a new issue