[PATCH 03/16] blk-crypto: Allow control over whether hardware is used
Eric Biggers <[email protected]> Tue, 23 Jun 2026 22:03:21 -0700
| Newsgroups | org.kernel.vger.linux-fscrypt,net.sourceforge.lists.linux-f2fs-devel,org.kernel.vger.linux-block,org.kernel.vger.linux-ext4,org.kernel.vger.linux-fsdevel |
|---|---|
| Message-ID | <[email protected]> |
fscrypt uses inline encryption hardware only when the "inlinecrypt" mount option is given. I'd like to keep that behavior even after standardizing on the blk-crypto API for file contents encryption. That is, the default should continue to be the well-tested CPU-based encryption code, and the use of inline encryption hardware should continue to be an opt-in feature for systems where it's beneficial and has been fully validated (including verifying ciphertext correctness). To support this use case, add an allow_hw field to struct blk_crypto_config. For now it's always set to true. Later commits will change that. Signed-off-by: Eric Biggers <[email protected]> --- block/blk-crypto.c | 8 +++++++- drivers/md/dm-inlinecrypt.c | 2 +- fs/crypto/inline_crypt.c | 3 ++- include/linux/blk-crypto.h | 6 +++++- 4 files changed, 15 insertions(+), 4 deletions(-) diff --git a/block/blk-crypto.c b/block/blk-crypto.c index dd83fc5af282..c157db869183 100644 --- a/block/blk-crypto.c +++ b/block/blk-crypto.c @@ -298,20 +298,21 @@ int __blk_crypto_rq_bio_prep(struct request *rq, struct bio *bio, * @key_type: type of the key -- either raw or hardware-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 + * @allow_hw: true if using inline encryption hardware is allowed * * Return: 0 on success, -errno on failure. The caller is responsible for * zeroizing both blk_key and key_bytes when done with them. */ int blk_crypto_init_key(struct blk_crypto_key *blk_key, const u8 *key_bytes, size_t key_size, enum blk_crypto_key_type key_type, enum blk_crypto_mode_num crypto_mode, unsigned int dun_bytes, - unsigned int data_unit_size) + unsigned int data_unit_size, bool allow_hw) { const struct blk_crypto_mode *mode; memset(blk_key, 0, sizeof(*blk_key)); @@ -326,10 +327,12 @@ int blk_crypto_init_key(struct blk_crypto_key *blk_key, break; case BLK_CRYPTO_KEY_TYPE_HW_WRAPPED: if (key_size < mode->security_strength || key_size > BLK_CRYPTO_MAX_HW_WRAPPED_KEY_SIZE) return -EINVAL; + if (!allow_hw) + return -EINVAL; break; default: return -EINVAL; } @@ -341,10 +344,11 @@ int blk_crypto_init_key(struct blk_crypto_key *blk_key, blk_key->crypto_cfg.crypto_mode = crypto_mode; blk_key->crypto_cfg.dun_bytes = dun_bytes; blk_key->crypto_cfg.data_unit_size = data_unit_size; blk_key->crypto_cfg.key_type = key_type; + blk_key->crypto_cfg.allow_hw = allow_hw; blk_key->data_unit_size_bits = ilog2(data_unit_size); blk_key->size = key_size; memcpy(blk_key->bytes, key_bytes, key_size); return 0; @@ -366,10 +370,12 @@ bool blk_crypto_config_supported_natively(struct block_device *bdev, { struct blk_crypto_profile *profile = bdev_get_queue(bdev)->crypto_profile; if (!profile) return false; + if (!cfg->allow_hw) + return false; if (!(profile->modes_supported[cfg->crypto_mode] & cfg->data_unit_size)) return false; if (profile->max_dun_bytes_supported < cfg->dun_bytes) return false; if (!(profile->key_types_supported & cfg->key_type)) diff --git a/drivers/md/dm-inlinecrypt.c b/drivers/md/dm-inlinecrypt.c index be1b4aa8f28b..a0f039c1e153 100644 --- a/drivers/md/dm-inlinecrypt.c +++ b/drivers/md/dm-inlinecrypt.c @@ -404,11 +404,11 @@ static int inlinecrypt_ctr(struct dm_target *ti, unsigned int argc, char **argv) (ctx->sector_bits - SECTOR_SHIFT); dun_bytes = DIV_ROUND_UP(fls64(ctx->max_dun), 8); err = blk_crypto_init_key(&ctx->key, key_bytes, ctx->key_size, ctx->key_type, cipher->mode_num, - dun_bytes, ctx->sector_size); + dun_bytes, ctx->sector_size, true); if (err) { ti->error = "Error initializing blk-crypto key"; goto bad; } diff --git a/fs/crypto/inline_crypt.c b/fs/crypto/inline_crypt.c index 47324062fee5..0d4c0dd04d20 100644 --- a/fs/crypto/inline_crypt.c +++ b/fs/crypto/inline_crypt.c @@ -132,10 +132,11 @@ int fscrypt_select_encryption_impl(struct fscrypt_inode_info *ci, crypto_cfg.crypto_mode = ci->ci_mode->blk_crypto_mode; crypto_cfg.data_unit_size = 1U << ci->ci_data_unit_bits; crypto_cfg.dun_bytes = fscrypt_get_dun_bytes(ci); crypto_cfg.key_type = is_hw_wrapped_key ? BLK_CRYPTO_KEY_TYPE_HW_WRAPPED : BLK_CRYPTO_KEY_TYPE_RAW; + crypto_cfg.allow_hw = true; devs = fscrypt_get_devices(sb, &num_devs); if (IS_ERR(devs)) return PTR_ERR(devs); @@ -173,11 +174,11 @@ int fscrypt_prepare_inline_crypt_key(struct fscrypt_prepared_key *prep_key, if (!blk_key) return -ENOMEM; err = blk_crypto_init_key(blk_key, key_bytes, key_size, key_type, crypto_mode, fscrypt_get_dun_bytes(ci), - 1U << ci->ci_data_unit_bits); + 1U << ci->ci_data_unit_bits, true); if (err) { fscrypt_err(inode, "error %d initializing blk-crypto key", err); goto fail; } diff --git a/include/linux/blk-crypto.h b/include/linux/blk-crypto.h index f7c3cb4a342f..7b9dca89aec9 100644 --- a/include/linux/blk-crypto.h +++ b/include/linux/blk-crypto.h @@ -75,16 +75,20 @@ enum blk_crypto_key_type { * key. This is the size in bytes of each individual plaintext and * ciphertext. This is always a power of 2. It might be e.g. the * filesystem block size or the disk sector size. * @dun_bytes: the maximum number of bytes of DUN used when using this key * @key_type: the type of this key -- either raw or hardware-wrapped + * @allow_hw: true if inline encryption hardware will be used if available; + * false to always use CPU-based encryption (requires + * CONFIG_BLK_INLINE_ENCRYPTION_FALLBACK) */ struct blk_crypto_config { enum blk_crypto_mode_num crypto_mode; unsigned int data_unit_size; unsigned int dun_bytes; enum blk_crypto_key_type key_type; + bool allow_hw; }; /** * struct blk_crypto_key - an inline encryption key * @crypto_cfg: the crypto mode, data unit size, key type, and other @@ -148,11 +152,11 @@ bool bio_crypt_dun_is_contiguous(const struct bio_crypt_ctx *bc, int blk_crypto_init_key(struct blk_crypto_key *blk_key, const u8 *key_bytes, size_t key_size, enum blk_crypto_key_type key_type, enum blk_crypto_mode_num crypto_mode, unsigned int dun_bytes, - unsigned int data_unit_size); + unsigned int data_unit_size, bool allow_hw); int blk_crypto_start_using_key(struct block_device *bdev, const struct blk_crypto_key *key); void blk_crypto_evict_key(struct block_device *bdev, -- 2.54.0