Make use of the new OS provided secrets API so that if the new '-s' option is passed in we try to extract the secret from the API rather than prompting for it.
The primary consumer of this is AMD SEV, which has been programmed to provide an injectable secret to the encrypted virtual machine. OVMF provides the secret area and passes it into the EFI Configuration Tables. The grub EFI layer pulls the secret out and primes the secrets API with it. The upshot of all of this is that a SEV protected VM can do an encrypted boot with a protected boot secret. Signed-off-by: James Bottomley <j...@linux.ibm.com> --- grub-core/disk/cryptodisk.c | 60 ++++++++++++++++++++++++++++++++++--- include/grub/cryptodisk.h | 2 ++ 2 files changed, 58 insertions(+), 4 deletions(-) diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c index 682f5a55d..02104aad4 100644 --- a/grub-core/disk/cryptodisk.c +++ b/grub-core/disk/cryptodisk.c @@ -41,6 +41,7 @@ static const struct grub_arg_option options[] = /* TRANSLATORS: It's still restricted to cryptodisks only. */ {"all", 'a', 0, N_("Mount all."), 0, 0}, {"boot", 'b', 0, N_("Mount all volumes with `boot' flag set."), 0, 0}, + {"secret", 's', 0, N_("Get OS provisioned secret and mount all volumes encrypted with that secret"), 0, 0}, {0, 0, 0, 0, 0, 0} }; @@ -967,6 +968,10 @@ grub_util_cryptodisk_get_uuid (grub_disk_t disk) static int check_boot, have_it; static char *search_uuid; +static char *os_passwd; + +/* variable to hold the passed in secret area. */ +static char *os_secret_area; static void cryptodisk_close (grub_cryptodisk_t dev) @@ -977,6 +982,17 @@ cryptodisk_close (grub_cryptodisk_t dev) grub_free (dev); } +static int +os_password_get(char buf[], unsigned len) +{ + /* os_passwd should be null terminated, so just copy everything */ + grub_strncpy(buf, os_passwd, len); + /* and add a terminator just in case */ + buf[len - 1] = 0; + + return 1; +} + static grub_err_t grub_cryptodisk_scan_device_real (const char *name, grub_disk_t source) { @@ -996,8 +1012,17 @@ grub_cryptodisk_scan_device_real (const char *name, grub_disk_t source) return grub_errno; if (!dev) continue; - - err = cr->recover_key (source, dev, grub_password_get); + + if (os_passwd) + { + err = cr->recover_key (source, dev, os_password_get); + if (err) + /* if the key doesn't work ignore the access denied error */ + grub_error_pop(); + } + else + err = cr->recover_key (source, dev, grub_password_get); + if (err) { cryptodisk_close (dev); @@ -1013,6 +1038,14 @@ grub_cryptodisk_scan_device_real (const char *name, grub_disk_t source) return GRUB_ERR_NONE; } +grub_err_t +grub_cryptodisk_set_secret (char *secret) +{ + os_secret_area = secret; + + return GRUB_ERR_NONE; +} + #ifdef GRUB_UTIL #include <grub/util/misc.h> grub_err_t @@ -1089,7 +1122,7 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args) { struct grub_arg_list *state = ctxt->state; - if (argc < 1 && !state[1].set && !state[2].set) + if (argc < 1 && !state[1].set && !state[2].set && !state[3].set) return grub_error (GRUB_ERR_BAD_ARGUMENT, "device name required"); have_it = 0; @@ -1107,6 +1140,7 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args) check_boot = state[2].set; search_uuid = args[0]; + os_passwd = NULL; grub_device_iterate (&grub_cryptodisk_scan_device, NULL); search_uuid = NULL; @@ -1117,11 +1151,28 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args) else if (state[1].set || (argc == 0 && state[2].set)) { search_uuid = NULL; + os_passwd = NULL; check_boot = state[2].set; grub_device_iterate (&grub_cryptodisk_scan_device, NULL); search_uuid = NULL; return GRUB_ERR_NONE; } + else if (state[3].set) + { + /* do we have a secret? */ + if (os_secret_area == NULL) + return grub_error (GRUB_ERR_INVALID_COMMAND, "No OS secret is provisioned"); + + os_passwd = os_secret_area; + search_uuid = NULL; + grub_device_iterate (&grub_cryptodisk_scan_device, NULL); + os_passwd = NULL; + + if (!have_it) + return grub_error (GRUB_ERR_ACCESS_DENIED, "SEV password failed to unlock any volumes"); + + return GRUB_ERR_NONE; + } else { grub_err_t err; @@ -1132,6 +1183,7 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args) grub_size_t len; search_uuid = NULL; + os_passwd = NULL; check_boot = state[2].set; diskname = args[0]; len = grub_strlen (diskname); @@ -1299,7 +1351,7 @@ GRUB_MOD_INIT (cryptodisk) { grub_disk_dev_register (&grub_cryptodisk_dev); cmd = grub_register_extcmd ("cryptomount", grub_cmd_cryptomount, 0, - N_("SOURCE|-u UUID|-a|-b"), + N_("SOURCE|-u UUID|-a|-b|-s"), N_("Mount a crypto device."), options); grub_procfs_register ("luks_script", &luks_script); } diff --git a/include/grub/cryptodisk.h b/include/grub/cryptodisk.h index 45dae5483..55c411754 100644 --- a/include/grub/cryptodisk.h +++ b/include/grub/cryptodisk.h @@ -163,4 +163,6 @@ grub_util_get_geli_uuid (const char *dev); grub_cryptodisk_t grub_cryptodisk_get_by_uuid (const char *uuid); grub_cryptodisk_t grub_cryptodisk_get_by_source_disk (grub_disk_t disk); +grub_err_t grub_cryptodisk_set_secret(char *secret); + #endif -- 2.26.2 _______________________________________________ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel