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