From 95bfca0d88bf0795f1b993ee7dd4ebc117243a59 Mon Sep 17 00:00:00 2001 From: Cong Zhang Date: Wed, 8 Feb 2023 02:21:14 -0800 Subject: [PATCH] dm verity: Add root_hash_sig_key_value parameter With root_hash_sig_key_value parameter, signature can be passed by kernel command line. So the root has signature verification can be supported at init time. Change-Id: Id40b3b781898543a7f5a3ddb75a1e2745e2d74f5 Signed-off-by: Cong Zhang --- drivers/md/Kconfig | 9 +++++ drivers/md/dm-verity-target.c | 9 +++++ drivers/md/dm-verity-verify-sig.c | 55 +++++++++++++++++++++++++++++++ drivers/md/dm-verity-verify-sig.h | 10 ++++++ 4 files changed, 83 insertions(+) diff --git a/drivers/md/Kconfig b/drivers/md/Kconfig index dd70f540016a..f66c1a7643f7 100644 --- a/drivers/md/Kconfig +++ b/drivers/md/Kconfig @@ -527,6 +527,15 @@ config DM_INIT If unsure, say N. +config DM_VERITY_SIG_VALUE + bool "DM \"root_hash_sig_key_value\" parameter support" + depends on DM_INIT=y + help + Enable "root_hash_sig_key_value" parameter in "dm-mod.create=" to create + mapped devices at init time. The option is used to directly pass root hash + signature value from kernel command line. So root hash signature + verification can be enabled without initramfs. + config DM_UEVENT bool "DM uevents" depends on BLK_DEV_DM diff --git a/drivers/md/dm-verity-target.c b/drivers/md/dm-verity-target.c index ccf5b852fbf7..63f3871d5dd6 100644 --- a/drivers/md/dm-verity-target.c +++ b/drivers/md/dm-verity-target.c @@ -1132,6 +1132,15 @@ static int verity_parse_opt_args(struct dm_arg_set *as, struct dm_verity *v, * properly parse all options (and their extra args). */ continue; +#if defined(CONFIG_DM_VERITY_SIG_VALUE) + } else if (verity_verify_is_sig_value_opt_arg(arg_name)) { + r = verity_verify_sig_value_parse_opt_args( + as, v, verify_args, &argc, arg_name); + + if (r) + return r; + continue; +#endif } DMERR("Unrecognized verity feature request: %s", arg_name); diff --git a/drivers/md/dm-verity-verify-sig.c b/drivers/md/dm-verity-verify-sig.c index db61a1f43ae9..d3199742bebb 100644 --- a/drivers/md/dm-verity-verify-sig.c +++ b/drivers/md/dm-verity-verify-sig.c @@ -93,6 +93,61 @@ int verity_verify_sig_parse_opt_args(struct dm_arg_set *as, return ret; } +#if defined(CONFIG_DM_VERITY_SIG_VALUE) +bool verity_verify_is_sig_value_opt_arg(const char *arg_name) +{ + return (!strcasecmp( + arg_name, DM_VERITY_ROOT_HASH_VERIFICATION_OPT_SIG_KEY_VALUE)); +} + +static int +verity_verify_get_sig_from_key_value(const char *key_value, + struct dm_verity_sig_opts *sig_opts) +{ + int ret = 0; + + if (!key_value) + return -ENOMEM; + + sig_opts->sig_size = strlen(key_value) / 2; + sig_opts->sig = kmalloc(sig_opts->sig_size, GFP_KERNEL); + if (!sig_opts->sig) { + ret = -ENOMEM; + goto end; + } + + ret = hex2bin(sig_opts->sig, key_value, strlen(key_value) / 2); +end: + return ret; +} + +int verity_verify_sig_value_parse_opt_args(struct dm_arg_set *as, + struct dm_verity *v, + struct dm_verity_sig_opts *sig_opts, + unsigned int *argc, + const char *arg_name) +{ + struct dm_target *ti = v->ti; + int ret = 0; + const char *sig_key_value = NULL; + + if (!*argc) { + ti->error = DM_VERITY_VERIFY_ERR( + "Signature key value not specified"); + return -EINVAL; + } + + sig_key_value = dm_shift_arg(as); + (*argc)--; + + ret = verity_verify_get_sig_from_key_value(sig_key_value, sig_opts); + if (ret < 0) + ti->error = DM_VERITY_VERIFY_ERR("Invalid key specified"); + + return ret; +} +#endif + /* * verify_verify_roothash - Verify the root hash of the verity hash device * using builtin trusted keys. diff --git a/drivers/md/dm-verity-verify-sig.h b/drivers/md/dm-verity-verify-sig.h index 3987c7141f79..f1d97f15693e 100644 --- a/drivers/md/dm-verity-verify-sig.h +++ b/drivers/md/dm-verity-verify-sig.h @@ -10,6 +10,7 @@ #define DM_VERITY_ROOT_HASH_VERIFICATION "DM Verity Sig Verification" #define DM_VERITY_ROOT_HASH_VERIFICATION_OPT_SIG_KEY "root_hash_sig_key_desc" +#define DM_VERITY_ROOT_HASH_VERIFICATION_OPT_SIG_KEY_VALUE "root_hash_sig_key_value" struct dm_verity_sig_opts { unsigned int sig_size; @@ -28,6 +29,15 @@ int verity_verify_sig_parse_opt_args(struct dm_arg_set *as, struct dm_verity *v, struct dm_verity_sig_opts *sig_opts, unsigned int *argc, const char *arg_name); +#ifdef CONFIG_DM_VERITY_SIG_VALUE +bool verity_verify_is_sig_value_opt_arg(const char *arg_name); +int verity_verify_sig_value_parse_opt_args(struct dm_arg_set *as, + struct dm_verity *v, + struct dm_verity_sig_opts *sig_opts, + unsigned int *argc, + const char *arg_name); +#endif + void verity_verify_sig_opts_cleanup(struct dm_verity_sig_opts *sig_opts); #else