| From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 |
| From: Barani Muthukumaran <bmuthuku@codeaurora.org> |
| Date: Thu, 6 Feb 2020 18:01:29 -0800 |
| Subject: ANDROID: dm: add support for passing through derive_sw_secret |
| |
| Update the device-mapper core to support exposing the inline crypto |
| support of wrapped keys through the device-mapper device. |
| |
| derive_sw_secret in keyslot manager is used to derive the software |
| secret from the given wrapped keyblob using the underlying blk device. |
| Given that the sw_secret is the same for a given wrapped keyblob the |
| call exits when the first underlying blk-device suceeds. |
| |
| This is a reworked version of a patch which was temporily reverted by |
| https://android-review.googlesource.com/c/kernel/common/+/1867366, and |
| which originated from |
| https://android-review.googlesource.com/c/kernel/common/+/1229460. |
| |
| Bug: 147209885 |
| Bug: 160883266 |
| Bug: 160883801 |
| |
| Test: Validated FBE with wrappedkey_v0 when /data is mounted on a |
| dm device. |
| |
| Change-Id: Id30d00afdbd3114e089887db1493ffd41e833e21 |
| Signed-off-by: Barani Muthukumaran <bmuthuku@codeaurora.org> |
| Signed-off-by: Eric Biggers <ebiggers@google.com> |
| --- |
| block/blk-crypto-profile.c | 1 + |
| drivers/md/dm-table.c | 65 ++++++++++++++++++++++++++++++++++++++ |
| 2 files changed, 66 insertions(+) |
| |
| diff --git a/block/blk-crypto-profile.c b/block/blk-crypto-profile.c |
| --- a/block/blk-crypto-profile.c |
| +++ b/block/blk-crypto-profile.c |
| @@ -505,6 +505,7 @@ int blk_crypto_derive_sw_secret(struct blk_crypto_profile *profile, |
| } |
| return err; |
| } |
| +EXPORT_SYMBOL_GPL(blk_crypto_derive_sw_secret); |
| |
| /** |
| * blk_crypto_intersect_capabilities() - restrict supported crypto capabilities |
| diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c |
| --- a/drivers/md/dm-table.c |
| +++ b/drivers/md/dm-table.c |
| @@ -1237,6 +1237,70 @@ static int dm_keyslot_evict(struct blk_crypto_profile *profile, |
| return args.err; |
| } |
| |
| +struct dm_derive_sw_secret_args { |
| + const u8 *wrapped_key; |
| + unsigned int wrapped_key_size; |
| + u8 *secret; |
| + int err; |
| +}; |
| + |
| +static int dm_derive_sw_secret_callback(struct dm_target *ti, |
| + struct dm_dev *dev, sector_t start, |
| + sector_t len, void *data) |
| +{ |
| + struct dm_derive_sw_secret_args *args = data; |
| + struct request_queue *q = bdev_get_queue(dev->bdev); |
| + |
| + if (!args->err) |
| + return 0; |
| + |
| + args->err = blk_crypto_derive_sw_secret(q->crypto_profile, |
| + args->wrapped_key, |
| + args->wrapped_key_size, |
| + args->secret); |
| + /* Try another device in case this fails. */ |
| + return 0; |
| +} |
| + |
| +/* |
| + * Retrieve the sw_secret from the underlying device. Given that only one |
| + * sw_secret can exist for a particular wrapped key, retrieve it only from the |
| + * first device that supports derive_sw_secret(). |
| + */ |
| +static int dm_derive_sw_secret(struct blk_crypto_profile *profile, |
| + const u8 *wrapped_key, |
| + unsigned int wrapped_key_size, |
| + u8 secret[BLK_CRYPTO_SW_SECRET_SIZE]) |
| +{ |
| + struct mapped_device *md = |
| + container_of(profile, struct dm_crypto_profile, profile)->md; |
| + struct dm_derive_sw_secret_args args = { |
| + .wrapped_key = wrapped_key, |
| + .wrapped_key_size = wrapped_key_size, |
| + .secret = secret, |
| + .err = -EOPNOTSUPP, |
| + }; |
| + struct dm_table *t; |
| + int srcu_idx; |
| + int i; |
| + struct dm_target *ti; |
| + |
| + t = dm_get_live_table(md, &srcu_idx); |
| + if (!t) |
| + return -EOPNOTSUPP; |
| + for (i = 0; i < dm_table_get_num_targets(t); i++) { |
| + ti = dm_table_get_target(t, i); |
| + if (!ti->type->iterate_devices) |
| + continue; |
| + ti->type->iterate_devices(ti, dm_derive_sw_secret_callback, |
| + &args); |
| + if (!args.err) |
| + break; |
| + } |
| + dm_put_live_table(md, srcu_idx); |
| + return args.err; |
| +} |
| + |
| static int |
| device_intersect_crypto_capabilities(struct dm_target *ti, struct dm_dev *dev, |
| sector_t start, sector_t len, void *data) |
| @@ -1293,6 +1357,7 @@ static int dm_table_construct_crypto_profile(struct dm_table *t) |
| profile = &dmcp->profile; |
| blk_crypto_profile_init(profile, 0); |
| profile->ll_ops.keyslot_evict = dm_keyslot_evict; |
| + profile->ll_ops.derive_sw_secret = dm_derive_sw_secret; |
| profile->max_dun_bytes_supported = UINT_MAX; |
| memset(profile->modes_supported, 0xFF, |
| sizeof(profile->modes_supported)); |