ANDROID: block: provide key size as input to inline crypto APIs

Currently, blk-crypto uses the algorithm to determine the size of keys.
However, some inline encryption hardware supports protecting keys from
software by wrapping the storage keys with an ephemeral key.  Since
these wrapped keys are not of a fixed size, add the capability to
provide the key size when initializing a blk_crypto_key, and update the
keyslot manager to take size into account when comparing keys.

Bug: 147209885

Change-Id: I9bf26d06d18a2d671c51111b4896abe4df303988
Co-developed-by: Gaurav Kashyap <gaurkash@codeaurora.org>
Signed-off-by: Gaurav Kashyap <gaurkash@codeaurora.org>
Signed-off-by: Barani Muthukumaran <bmuthuku@codeaurora.org>
Signed-off-by: Eric Biggers <ebiggers@google.com>
This commit is contained in:
Barani Muthukumaran 2020-01-02 11:57:39 -08:00 committed by Todd Kjos
parent bb7f6203fb
commit 3e8c41805f
6 changed files with 7282 additions and 7121 deletions

File diff suppressed because it is too large Load diff

View file

@ -171,15 +171,19 @@ bool blk_crypto_endio(struct bio *bio)
/**
* blk_crypto_init_key() - Prepare a key for use with blk-crypto
* @blk_key: Pointer to the blk_crypto_key to initialize.
* @raw_key: Pointer to the raw key. Must be the correct length for the chosen
* @crypto_mode; see blk_crypto_modes[].
* @raw_key: Pointer to the raw key.
* @raw_key_size: Size of raw key. Must be at least the required size for the
* chosen @crypto_mode; see blk_crypto_modes[]. (It's allowed
* to be longer than the mode's actual key size, in order to
* support inline encryption hardware that accepts wrapped keys.)
* @crypto_mode: identifier for the encryption algorithm to use
* @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
* done using the key, it must be freed with blk_crypto_free_key().
*/
int blk_crypto_init_key(struct blk_crypto_key *blk_key, const u8 *raw_key,
int blk_crypto_init_key(struct blk_crypto_key *blk_key,
const u8 *raw_key, unsigned int raw_key_size,
enum blk_crypto_mode_num crypto_mode,
unsigned int data_unit_size)
{
@ -191,8 +195,11 @@ int blk_crypto_init_key(struct blk_crypto_key *blk_key, const u8 *raw_key,
if (crypto_mode >= ARRAY_SIZE(blk_crypto_modes))
return -EINVAL;
BUILD_BUG_ON(BLK_CRYPTO_MAX_WRAPPED_KEY_SIZE < BLK_CRYPTO_MAX_KEY_SIZE);
mode = &blk_crypto_modes[crypto_mode];
if (mode->keysize == 0)
if (raw_key_size < mode->keysize ||
raw_key_size > BLK_CRYPTO_MAX_WRAPPED_KEY_SIZE)
return -EINVAL;
if (!is_power_of_2(data_unit_size))
@ -201,8 +208,8 @@ int blk_crypto_init_key(struct blk_crypto_key *blk_key, const u8 *raw_key,
blk_key->crypto_mode = crypto_mode;
blk_key->data_unit_size = data_unit_size;
blk_key->data_unit_size_bits = ilog2(data_unit_size);
blk_key->size = mode->keysize;
memcpy(blk_key->raw, raw_key, mode->keysize);
blk_key->size = raw_key_size;
memcpy(blk_key->raw, raw_key, raw_key_size);
/*
* The keyslot manager uses the SipHash of the key to implement O(1) key
@ -210,7 +217,7 @@ int blk_crypto_init_key(struct blk_crypto_key *blk_key, const u8 *raw_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, mode->keysize, &hash_key);
blk_key->hash = siphash(raw_key, raw_key_size, &hash_key);
return 0;
}

View file

@ -168,6 +168,7 @@ static int find_keyslot(struct keyslot_manager *ksm,
hlist_for_each_entry(slotp, head, hash_node) {
if (slotp->key.hash == key->hash &&
slotp->key.crypto_mode == key->crypto_mode &&
slotp->key.size == key->size &&
slotp->key.data_unit_size == key->data_unit_size &&
!crypto_memneq(slotp->key.raw, key->raw, key->size))
return slotp - ksm->slots;

View file

@ -74,8 +74,8 @@ int fscrypt_prepare_inline_crypt_key(struct fscrypt_prepared_key *prep_key,
else
sb->s_cop->get_devices(sb, blk_key->devs);
err = blk_crypto_init_key(&blk_key->base, raw_key, crypto_mode,
sb->s_blocksize);
err = blk_crypto_init_key(&blk_key->base, raw_key, ci->ci_mode->keysize,
crypto_mode, sb->s_blocksize);
if (err) {
fscrypt_err(inode, "error %d initializing blk-crypto key", err);
goto fail;

View file

@ -19,6 +19,7 @@ enum blk_crypto_mode_num {
#ifdef CONFIG_BLK_INLINE_ENCRYPTION
#define BLK_CRYPTO_MAX_KEY_SIZE 64
#define BLK_CRYPTO_MAX_WRAPPED_KEY_SIZE 128
/**
* struct blk_crypto_key - an inline encryption key
@ -41,7 +42,7 @@ struct blk_crypto_key {
unsigned int data_unit_size_bits;
unsigned int size;
unsigned int hash;
u8 raw[BLK_CRYPTO_MAX_KEY_SIZE];
u8 raw[BLK_CRYPTO_MAX_WRAPPED_KEY_SIZE];
};
#define BLK_CRYPTO_MAX_IV_SIZE 32

View file

@ -14,7 +14,8 @@ int blk_crypto_submit_bio(struct bio **bio_ptr);
bool blk_crypto_endio(struct bio *bio);
int blk_crypto_init_key(struct blk_crypto_key *blk_key, const u8 *raw_key,
int blk_crypto_init_key(struct blk_crypto_key *blk_key,
const u8 *raw_key, unsigned int raw_key_size,
enum blk_crypto_mode_num crypto_mode,
unsigned int data_unit_size);