diff --git a/Documentation/block/inline-encryption.rst b/Documentation/block/inline-encryption.rst index 7ab203be0117..4fd2b1171301 100644 --- a/Documentation/block/inline-encryption.rst +++ b/Documentation/block/inline-encryption.rst @@ -388,8 +388,8 @@ such as in file-based encryption. Key wrapping is a commonly used technique.) The key which wraps (encrypts) hardware-wrapped keys is a hardware-internal key that is never exposed to software; it is either a persistent key (a "long-term wrapping key") or a per-boot key (an "ephemeral wrapping key"). The long-term -wrapped form of the key is what is initially unlocked, but it is discarded as -soon as it is converted into an ephemerally-wrapped key. In-use +wrapped form of the key is what is initially unlocked, but it is erased from +memory as soon as it is converted into an ephemerally-wrapped key. In-use hardware-wrapped keys are always ephemerally-wrapped, not long-term wrapped. As inline encryption hardware can only be used to encrypt/decrypt data on-disk, @@ -442,8 +442,8 @@ The components are: for cryptographic applications that require up to a 256-bit security strength. Some use cases (e.g. full-disk encryption) won't require the software secret. -Example: in the case of fscrypt, the fscrypt master key (the key used to unlock -a particular set of encrypted directories) is made hardware-wrapped. The inline +Example: in the case of fscrypt, the fscrypt master key (the key that protects a +particular set of encrypted directories) is made hardware-wrapped. The inline encryption key is used as the file contents encryption key, while the software secret (rather than the master key directly) is used to key fscrypt's KDF (HKDF-SHA512) to derive other subkeys such as filenames encryption keys. @@ -512,5 +512,6 @@ the hardware RNG and its use to generate the key, as well as the testing of the "import" mode as that should cover all parts other than the key generation. For an example of a test that verifies the ciphertext written to disk in the -"import" mode, see `Android's vts_kernel_encryption_test +"import" mode, see the fscrypt hardware-wrapped key tests in xfstests, or +`Android's vts_kernel_encryption_test `_. diff --git a/block/blk-crypto-fallback.c b/block/blk-crypto-fallback.c index e1a6179f8f2e..06b6f778504b 100644 --- a/block/blk-crypto-fallback.c +++ b/block/blk-crypto-fallback.c @@ -540,7 +540,7 @@ static int blk_crypto_fallback_init(void) if (blk_crypto_fallback_inited) return 0; - prandom_bytes(blank_key, BLK_CRYPTO_MAX_STANDARD_KEY_SIZE); + prandom_bytes(blank_key, sizeof(blank_key)); err = bioset_init(&crypto_bio_split, 64, 0, 0); if (err) diff --git a/block/blk-crypto-profile.c b/block/blk-crypto-profile.c index c319c62380d8..c03be20af6b3 100644 --- a/block/blk-crypto-profile.c +++ b/block/blk-crypto-profile.c @@ -466,42 +466,60 @@ bool blk_crypto_register(struct blk_crypto_profile *profile, EXPORT_SYMBOL_GPL(blk_crypto_register); /** - * blk_crypto_derive_sw_secret() - Derive software secret from hardware-wrapped - * key - * @profile: the crypto profile of the device the key will be used on - * @wrapped_key: the hardware-wrapped key - * @wrapped_key_size: size of @wrapped_key in bytes + * blk_crypto_derive_sw_secret() - Derive software secret from wrapped key + * @bdev: a block device whose hardware-wrapped keys implementation is + * compatible (blk_crypto_hw_wrapped_keys_compatible()) with all block + * devices on which the key will be used. + * @eph_key: the hardware-wrapped key in ephemerally-wrapped form + * @eph_key_size: size of @eph_key in bytes * @sw_secret: (output) the software secret * - * Given a hardware-wrapped key, ask the hardware to derive the secret which - * software can use for cryptographic tasks other than inline encryption. This - * secret is guaranteed to be cryptographically isolated from the inline - * encryption key, i.e. derived with a different KDF context. + * Given a hardware-wrapped key in ephemerally-wrapped form (the same form that + * it is used for I/O), ask the hardware to derive the secret which software can + * use for cryptographic tasks other than inline encryption. This secret is + * guaranteed to be cryptographically isolated from the inline encryption key, + * i.e. derived with a different KDF context. * - * Return: 0 on success, -EOPNOTSUPP if the given @profile doesn't support - * hardware-wrapped keys (or is NULL), -EBADMSG if the key isn't a valid + * Return: 0 on success, -EOPNOTSUPP if the block device doesn't support + * hardware-wrapped keys, -EBADMSG if the key isn't a valid * hardware-wrapped key, or another -errno code. */ -int blk_crypto_derive_sw_secret(struct blk_crypto_profile *profile, - const u8 *wrapped_key, - unsigned int wrapped_key_size, +int blk_crypto_derive_sw_secret(struct block_device *bdev, + const u8 *eph_key, size_t eph_key_size, u8 sw_secret[BLK_CRYPTO_SW_SECRET_SIZE]) { - int err = -EOPNOTSUPP; + struct blk_crypto_profile *profile = + bdev_get_queue(bdev)->crypto_profile; + int err; - if (profile && - (profile->key_types_supported & BLK_CRYPTO_KEY_TYPE_HW_WRAPPED) && - profile->ll_ops.derive_sw_secret) { - blk_crypto_hw_enter(profile); - err = profile->ll_ops.derive_sw_secret(profile, wrapped_key, - wrapped_key_size, - sw_secret); - blk_crypto_hw_exit(profile); - } + if (!profile) + return -EOPNOTSUPP; + if (!(profile->key_types_supported & BLK_CRYPTO_KEY_TYPE_HW_WRAPPED)) + return -EOPNOTSUPP; + if (!profile->ll_ops.derive_sw_secret) + return -EOPNOTSUPP; + blk_crypto_hw_enter(profile); + err = profile->ll_ops.derive_sw_secret(profile, eph_key, eph_key_size, + sw_secret); + blk_crypto_hw_exit(profile); return err; } EXPORT_SYMBOL_GPL(blk_crypto_derive_sw_secret); +/** + * blk_crypto_hw_wrapped_keys_compatible() - Check HW-wrapped key compatibility + * @bdev1: the first block device + * @bdev2: the second block device + * + * Return: true if HW-wrapped keys used on @bdev1 can also be used on @bdev2. + */ +bool blk_crypto_hw_wrapped_keys_compatible(struct block_device *bdev1, + struct block_device *bdev2) +{ + return bdev_get_queue(bdev1)->crypto_profile == + bdev_get_queue(bdev2)->crypto_profile; +} + /** * blk_crypto_intersect_capabilities() - restrict supported crypto capabilities * by child device diff --git a/block/blk-crypto.c b/block/blk-crypto.c index 9292f413a265..47c9b672690d 100644 --- a/block/blk-crypto.c +++ b/block/blk-crypto.c @@ -72,7 +72,10 @@ static int __init bio_crypt_ctx_init(void) /* This is assumed in various places. */ BUILD_BUG_ON(BLK_ENCRYPTION_MODE_INVALID != 0); - /* Sanity check that no algorithm exceeds the defined limits. */ + /* + * Validate the crypto mode properties. This ideally would be done with + * static assertions, but boot-time checks are the next best thing. + */ for (i = 0; i < BLK_ENCRYPTION_MODE_MAX; i++) { BUG_ON(blk_crypto_modes[i].keysize > BLK_CRYPTO_MAX_STANDARD_KEY_SIZE); @@ -328,7 +331,7 @@ int __blk_crypto_rq_bio_prep(struct request *rq, struct bio *bio, * zeroizing both blk_key and raw_key when done with them. */ int blk_crypto_init_key(struct blk_crypto_key *blk_key, - const u8 *raw_key, unsigned int raw_key_size, + const u8 *raw_key, size_t raw_key_size, enum blk_crypto_key_type key_type, enum blk_crypto_mode_num crypto_mode, unsigned int dun_bytes, diff --git a/include/linux/blk-crypto-profile.h b/include/linux/blk-crypto-profile.h index 189f9b65b764..8b30d04ef008 100644 --- a/include/linux/blk-crypto-profile.h +++ b/include/linux/blk-crypto-profile.h @@ -60,7 +60,7 @@ struct blk_crypto_ll_ops { /** * @derive_sw_secret: Derive the software secret from a hardware-wrapped - * key. + * key in ephemerally-wrapped form. * * This only needs to be implemented if BLK_CRYPTO_KEY_TYPE_HW_WRAPPED * is supported. @@ -69,8 +69,7 @@ struct blk_crypto_ll_ops { * -errno code on other errors. */ int (*derive_sw_secret)(struct blk_crypto_profile *profile, - const u8 *wrapped_key, - unsigned int wrapped_key_size, + const u8 *eph_key, size_t eph_key_size, u8 sw_secret[BLK_CRYPTO_SW_SECRET_SIZE]); }; @@ -100,7 +99,7 @@ struct blk_crypto_profile { unsigned int max_dun_bytes_supported; /** - * @key_types_supported: Supported types of keys -- + * @key_types_supported: A bitmask of the supported key types: * BLK_CRYPTO_KEY_TYPE_STANDARD and/or BLK_CRYPTO_KEY_TYPE_HW_WRAPPED. */ unsigned int key_types_supported; @@ -163,11 +162,6 @@ void blk_crypto_reprogram_all_keys(struct blk_crypto_profile *profile); void blk_crypto_profile_destroy(struct blk_crypto_profile *profile); -int blk_crypto_derive_sw_secret(struct blk_crypto_profile *profile, - const u8 *wrapped_key, - unsigned int wrapped_key_size, - u8 sw_secret[BLK_CRYPTO_SW_SECRET_SIZE]); - void blk_crypto_intersect_capabilities(struct blk_crypto_profile *parent, const struct blk_crypto_profile *child); diff --git a/include/linux/blk-crypto.h b/include/linux/blk-crypto.h index f2b269d695f1..44d19e451b63 100644 --- a/include/linux/blk-crypto.h +++ b/include/linux/blk-crypto.h @@ -17,7 +17,7 @@ enum blk_crypto_mode_num { }; /* - * Supported types of keys. Must be bit-flags due to their use in + * Supported types of keys. Must be bitflags due to their use in * blk_crypto_profile::key_types_supported. */ enum blk_crypto_key_type { @@ -141,7 +141,7 @@ bool bio_crypt_dun_is_contiguous(const struct bio_crypt_ctx *bc, const u64 next_dun[BLK_CRYPTO_DUN_ARRAY_SIZE]); int blk_crypto_init_key(struct blk_crypto_key *blk_key, - const u8 *raw_key, unsigned int raw_key_size, + const u8 *raw_key, size_t raw_key_size, enum blk_crypto_key_type key_type, enum blk_crypto_mode_num crypto_mode, unsigned int dun_bytes, @@ -158,6 +158,13 @@ bool blk_crypto_config_supported_natively(struct block_device *bdev, bool blk_crypto_config_supported(struct block_device *bdev, const struct blk_crypto_config *cfg); +int blk_crypto_derive_sw_secret(struct block_device *bdev, + const u8 *eph_key, size_t eph_key_size, + u8 sw_secret[BLK_CRYPTO_SW_SECRET_SIZE]); + +bool blk_crypto_hw_wrapped_keys_compatible(struct block_device *bdev1, + struct block_device *bdev2); + #else /* CONFIG_BLK_INLINE_ENCRYPTION */ static inline bool bio_has_crypt_ctx(struct bio *bio)