blob: 647cc0d5484f06e62462ec9d6333eaad237dbbff [file] [log] [blame]
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));