Merge "ANDROID: block: backport the ability to specify max_dun_bytes"

This commit is contained in:
qctecmdr 2020-07-25 03:20:36 -07:00 committed by Gerrit - the friendly Code Review server
commit 7150299ac3
8 changed files with 99 additions and 12 deletions

View file

@ -108,9 +108,10 @@ 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->is_hw_wrapped)) {
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);
if (!err)
return 0;
@ -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);

View file

@ -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;
#ifdef CONFIG_PM
@ -182,6 +183,7 @@ struct keyslot_manager *keyslot_manager_create(
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;
keyslot_manager_set_dev(ksm, dev);
@ -214,11 +216,19 @@ err_free_ksm:
}
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)
@ -391,6 +401,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.
*
@ -402,6 +413,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)
{
@ -418,7 +430,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;
}
/**
@ -565,6 +580,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;
keyslot_manager_set_dev(ksm, dev);
@ -592,12 +608,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));
}

View file

@ -285,14 +285,14 @@ static int default_key_ctr(struct dm_target *ti, unsigned int argc, char **argv)
err = blk_crypto_init_key(&dkc->key, raw_key, cipher->key_size,
dkc->is_hw_wrapped, cipher->mode_num,
dkc->sector_size);
sizeof(u64), 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, sizeof(u64),
dkc->sector_size, dkc->is_hw_wrapped,
dkc->dev->bdev->bd_queue);
if (err) {
ti->error = "Error starting to use blk-crypto";

View file

@ -344,6 +344,7 @@ int ufshcd_hba_init_crypto_spec(struct ufs_hba *hba,
err = -ENOMEM;
goto out_free_caps;
}
keyslot_manager_set_max_dun_bytes(hba->ksm, sizeof(u64));
return 0;

View file

@ -41,6 +41,17 @@ static void fscrypt_get_devices(struct super_block *sb, int num_devs,
sb->s_cop->get_devices(sb, devs);
}
static unsigned int fscrypt_get_dun_bytes(const struct fscrypt_info *ci)
{
unsigned int dun_bytes = 8;
if (fscrypt_policy_flags(&ci->ci_policy) &
FSCRYPT_POLICY_FLAG_DIRECT_KEY)
dun_bytes += FS_KEY_DERIVATION_NONCE_SIZE;
return dun_bytes;
}
/* Enable inline encryption for this file if supported. */
int fscrypt_select_encryption_impl(struct fscrypt_info *ci,
bool is_hw_wrapped_key)
@ -48,6 +59,7 @@ int fscrypt_select_encryption_impl(struct fscrypt_info *ci,
const struct inode *inode = ci->ci_inode;
struct super_block *sb = inode->i_sb;
enum blk_crypto_mode_num crypto_mode = ci->ci_mode->blk_crypto_mode;
unsigned int dun_bytes;
struct request_queue **devs;
int num_devs;
int i;
@ -83,9 +95,12 @@ int fscrypt_select_encryption_impl(struct fscrypt_info *ci,
fscrypt_get_devices(sb, num_devs, devs);
dun_bytes = fscrypt_get_dun_bytes(ci);
for (i = 0; i < num_devs; i++) {
if (!keyslot_manager_crypto_mode_supported(devs[i]->ksm,
crypto_mode,
dun_bytes,
sb->s_blocksize,
is_hw_wrapped_key))
goto out_free_devs;
@ -106,6 +121,7 @@ int fscrypt_prepare_inline_crypt_key(struct fscrypt_prepared_key *prep_key,
const struct inode *inode = ci->ci_inode;
struct super_block *sb = inode->i_sb;
enum blk_crypto_mode_num crypto_mode = ci->ci_mode->blk_crypto_mode;
unsigned int dun_bytes;
int num_devs;
int queue_refs = 0;
struct fscrypt_blk_crypto_key *blk_key;
@ -123,11 +139,14 @@ int fscrypt_prepare_inline_crypt_key(struct fscrypt_prepared_key *prep_key,
blk_key->num_devs = num_devs;
fscrypt_get_devices(sb, num_devs, blk_key->devs);
dun_bytes = fscrypt_get_dun_bytes(ci);
BUILD_BUG_ON(FSCRYPT_MAX_HW_WRAPPED_KEY_SIZE >
BLK_CRYPTO_MAX_WRAPPED_KEY_SIZE);
err = blk_crypto_init_key(&blk_key->base, raw_key, raw_key_size,
is_hw_wrapped, crypto_mode, sb->s_blocksize);
is_hw_wrapped, crypto_mode, dun_bytes,
sb->s_blocksize);
if (err) {
fscrypt_err(inode, "error %d initializing blk-crypto key", err);
goto fail;
@ -148,7 +167,8 @@ 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,
err = blk_crypto_start_using_mode(crypto_mode, dun_bytes,
sb->s_blocksize,
is_hw_wrapped,
blk_key->devs[i]);
if (err) {

View file

@ -45,7 +45,15 @@ struct blk_crypto_key {
unsigned int data_unit_size;
unsigned int data_unit_size_bits;
unsigned int size;
/*
* Hack to avoid breaking KMI: pack both hash and dun_bytes into the
* hash field...
*/
#define BLK_CRYPTO_KEY_HASH_MASK 0xffffff
#define BLK_CRYPTO_KEY_DUN_BYTES_SHIFT 24
unsigned int hash;
bool is_hw_wrapped;
u8 raw[BLK_CRYPTO_MAX_WRAPPED_KEY_SIZE];
};
@ -53,6 +61,26 @@ struct blk_crypto_key {
#define BLK_CRYPTO_MAX_IV_SIZE 32
#define BLK_CRYPTO_DUN_ARRAY_SIZE (BLK_CRYPTO_MAX_IV_SIZE/sizeof(u64))
static inline void
blk_crypto_key_set_hash_and_dun_bytes(struct blk_crypto_key *key,
u32 hash, unsigned int dun_bytes)
{
key->hash = (dun_bytes << BLK_CRYPTO_KEY_DUN_BYTES_SHIFT) |
(hash & BLK_CRYPTO_KEY_HASH_MASK);
}
static inline u32
blk_crypto_key_hash(const struct blk_crypto_key *key)
{
return key->hash & BLK_CRYPTO_KEY_HASH_MASK;
}
static inline unsigned int
blk_crypto_key_dun_bytes(const struct blk_crypto_key *key)
{
return key->hash >> BLK_CRYPTO_KEY_DUN_BYTES_SHIFT;
}
/**
* struct bio_crypt_ctx - an inline encryption context
* @bc_key: the key, algorithm, and data unit size to use

View file

@ -18,9 +18,11 @@ 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);
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);

View file

@ -58,6 +58,9 @@ struct keyslot_manager *keyslot_manager_create(
const unsigned int crypto_mode_supported[BLK_ENCRYPTION_MODE_MAX],
void *ll_priv_data);
void keyslot_manager_set_max_dun_bytes(struct keyslot_manager *ksm,
unsigned int max_dun_bytes);
int keyslot_manager_get_slot_for_key(struct keyslot_manager *ksm,
const struct blk_crypto_key *key);
@ -67,6 +70,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);