diff --git a/block/blk-crypto.c b/block/blk-crypto.c index 2c47e8eec865..3e1bb4192498 100644 --- a/block/blk-crypto.c +++ b/block/blk-crypto.c @@ -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; } diff --git a/block/keyslot-manager.c b/block/keyslot-manager.c index cdf0607019d4..52f94a5a9680 100644 --- a/block/keyslot-manager.c +++ b/block/keyslot-manager.c @@ -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; diff --git a/fs/crypto/inline_crypt.c b/fs/crypto/inline_crypt.c index aa04e8a7d674..7bfafe28011f 100644 --- a/fs/crypto/inline_crypt.c +++ b/fs/crypto/inline_crypt.c @@ -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; diff --git a/include/linux/bio-crypt-ctx.h b/include/linux/bio-crypt-ctx.h index 4535df0a6349..2e06b06fce47 100644 --- a/include/linux/bio-crypt-ctx.h +++ b/include/linux/bio-crypt-ctx.h @@ -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 diff --git a/include/linux/blk-crypto.h b/include/linux/blk-crypto.h index 07d32e33f0bb..6dd37961888a 100644 --- a/include/linux/blk-crypto.h +++ b/include/linux/blk-crypto.h @@ -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);