177 lines
6.1 KiB
Diff
177 lines
6.1 KiB
Diff
|
|
From 90d00b832a2fcab9424fff1859bb2b9b4be01a2a Mon Sep 17 00:00:00 2001
|
||
|
|
From: James Bottomley <jejb@linux.ibm.com>
|
||
|
|
Date: Mon, 11 Nov 2024 14:20:23 +0800
|
||
|
|
Subject: [PATCH 1/2] cryptodisk: add OS provided secret support
|
||
|
|
|
||
|
|
cherry-picked from https://mail.gnu.org/archive/html/grub-devel/2022-02/msg00065.html.
|
||
|
|
|
||
|
|
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.
|
||
|
|
|
||
|
|
[ hly: The patch from James Bottomley can not work properly, fix it
|
||
|
|
when backport the patch. ]
|
||
|
|
|
||
|
|
Signed-off-by: James Bottomley <jejb@linux.ibm.com>
|
||
|
|
Signed-off-by: hanliyang <hanliyang@hygon.cn>
|
||
|
|
---
|
||
|
|
grub-core/disk/cryptodisk.c | 62 +++++++++++++++++++++++++++++++++++--
|
||
|
|
include/grub/cryptodisk.h | 14 +++++++++
|
||
|
|
2 files changed, 73 insertions(+), 3 deletions(-)
|
||
|
|
|
||
|
|
diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
|
||
|
|
index 8bc559b..4d8deba 100644
|
||
|
|
--- a/grub-core/disk/cryptodisk.c
|
||
|
|
+++ b/grub-core/disk/cryptodisk.c
|
||
|
|
@@ -48,7 +48,8 @@ enum
|
||
|
|
OPTION_KEYFILE_OFFSET,
|
||
|
|
OPTION_KEYFILE_SIZE,
|
||
|
|
OPTION_HEADER,
|
||
|
|
- OPTION_PROTECTOR
|
||
|
|
+ OPTION_PROTECTOR,
|
||
|
|
+ OPTION_SECRET
|
||
|
|
};
|
||
|
|
|
||
|
|
static const struct grub_arg_option options[] =
|
||
|
|
@@ -64,6 +65,7 @@ static const struct grub_arg_option options[] =
|
||
|
|
{"header", 'H', 0, N_("Read header from file"), 0, ARG_TYPE_STRING},
|
||
|
|
{"protector", 'P', GRUB_ARG_OPTION_REPEATABLE,
|
||
|
|
N_("Unlock volume(s) using key protector(s)."), 0, ARG_TYPE_STRING},
|
||
|
|
+ {"secret", 's', 0, N_("Get secret passphrase from named module and optional identifier"), 0, 0},
|
||
|
|
{0, 0, 0, 0, 0, 0}
|
||
|
|
};
|
||
|
|
|
||
|
|
@@ -1026,6 +1028,9 @@ grub_util_cryptodisk_get_uuid (grub_disk_t disk)
|
||
|
|
|
||
|
|
#endif
|
||
|
|
|
||
|
|
+/* variable to hold the list of secret providers */
|
||
|
|
+static struct grub_secret_entry *secret_providers;
|
||
|
|
+
|
||
|
|
static void
|
||
|
|
cryptodisk_close (grub_cryptodisk_t dev)
|
||
|
|
{
|
||
|
|
@@ -1260,6 +1265,18 @@ grub_cryptodisk_scan_device_real (const char *name,
|
||
|
|
return dev;
|
||
|
|
}
|
||
|
|
|
||
|
|
+void
|
||
|
|
+grub_cryptodisk_add_secret_provider (struct grub_secret_entry *e)
|
||
|
|
+{
|
||
|
|
+ grub_list_push(GRUB_AS_LIST_P (&secret_providers), GRUB_AS_LIST (e));
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
+void
|
||
|
|
+grub_cryptodisk_remove_secret_provider (struct grub_secret_entry *e)
|
||
|
|
+{
|
||
|
|
+ grub_list_remove (GRUB_AS_LIST (e));
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
#ifdef GRUB_UTIL
|
||
|
|
#include <grub/util/misc.h>
|
||
|
|
grub_err_t
|
||
|
|
@@ -1376,7 +1393,7 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args)
|
||
|
|
struct grub_arg_list *state = ctxt->state;
|
||
|
|
struct grub_cryptomount_args cargs = {0};
|
||
|
|
|
||
|
|
- if (argc < 1 && !state[OPTION_ALL].set && !state[OPTION_BOOT].set)
|
||
|
|
+ if (argc < 1 && !state[OPTION_ALL].set && !state[OPTION_BOOT].set && !state[OPTION_SECRET].set)
|
||
|
|
return grub_error (GRUB_ERR_BAD_ARGUMENT, "device name required");
|
||
|
|
|
||
|
|
if (grub_cryptodisk_list == NULL)
|
||
|
|
@@ -1386,6 +1403,11 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args)
|
||
|
|
return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||
|
|
"a password and a key protector cannot both be set");
|
||
|
|
|
||
|
|
+ if (state[OPTION_SECRET].set &&
|
||
|
|
+ (state[OPTION_PASSWORD].set || state[OPTION_PROTECTOR].set)) /* secret module and password/key protector */
|
||
|
|
+ return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||
|
|
+ "a secret module and a password/key protector cannot both be set");
|
||
|
|
+
|
||
|
|
if (state[OPTION_PASSWORD].set) /* password */
|
||
|
|
{
|
||
|
|
cargs.key_data = (grub_uint8_t *) state[OPTION_PASSWORD].arg;
|
||
|
|
@@ -1527,6 +1549,40 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args)
|
||
|
|
grub_cryptodisk_clear_key_cache (&cargs);
|
||
|
|
return GRUB_ERR_NONE;
|
||
|
|
}
|
||
|
|
+ else if (state[OPTION_SECRET].set) /* secret module */
|
||
|
|
+ {
|
||
|
|
+ struct grub_secret_entry *se = NULL;
|
||
|
|
+ grub_err_t rc;
|
||
|
|
+
|
||
|
|
+ if (argc < 1)
|
||
|
|
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "secret module must be specified");
|
||
|
|
+#ifndef GRUB_UTIL
|
||
|
|
+ grub_dl_load (args[0]);
|
||
|
|
+#endif
|
||
|
|
+ se = grub_named_list_find (GRUB_AS_NAMED_LIST (secret_providers), args[0]);
|
||
|
|
+ if (se == NULL)
|
||
|
|
+ return grub_error (GRUB_ERR_INVALID_COMMAND, "No secret provider is found");
|
||
|
|
+
|
||
|
|
+ rc = se->get (args[1], &cargs.key_data);
|
||
|
|
+ if (rc)
|
||
|
|
+ return rc;
|
||
|
|
+
|
||
|
|
+ cargs.key_len = grub_strlen((char *) cargs.key_data);
|
||
|
|
+
|
||
|
|
+ cargs.check_boot = state[OPTION_BOOT].set;
|
||
|
|
+ cargs.search_uuid = NULL;
|
||
|
|
+
|
||
|
|
+ grub_device_iterate (&grub_cryptodisk_scan_device, &cargs);
|
||
|
|
+
|
||
|
|
+ if (state[OPTION_SECRET].set)
|
||
|
|
+ {
|
||
|
|
+ rc = se->put (args[1], 1, &cargs.key_data);
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
+ grub_cryptodisk_clear_key_cache (&cargs);
|
||
|
|
+
|
||
|
|
+ return rc;
|
||
|
|
+ }
|
||
|
|
else
|
||
|
|
{
|
||
|
|
grub_disk_t disk;
|
||
|
|
@@ -1721,7 +1777,7 @@ GRUB_MOD_INIT (cryptodisk)
|
||
|
|
N_("[ [-p password] | [-k keyfile"
|
||
|
|
" [-O keyoffset] [-S keysize] ] ] [-H file]"
|
||
|
|
" [-P protector [-P protector ...]]"
|
||
|
|
- " <SOURCE|-u UUID|-a|-b>"),
|
||
|
|
+ " <SOURCE|-u UUID|-a|-b|-s MOD [ID]>"),
|
||
|
|
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 0b41e24..d0804a7 100644
|
||
|
|
--- a/include/grub/cryptodisk.h
|
||
|
|
+++ b/include/grub/cryptodisk.h
|
||
|
|
@@ -203,4 +203,18 @@ 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);
|
||
|
|
|
||
|
|
+struct grub_secret_entry {
|
||
|
|
+ /* as named list */
|
||
|
|
+ struct grub_secret_entry *next;
|
||
|
|
+ struct grub_secret_entry **prev;
|
||
|
|
+ const char *name;
|
||
|
|
+
|
||
|
|
+ /* additional entries */
|
||
|
|
+ grub_err_t (*get) (const char *arg, grub_uint8_t **secret);
|
||
|
|
+ grub_err_t (*put) (const char *arg, int have_it, grub_uint8_t **secret);
|
||
|
|
+};
|
||
|
|
+
|
||
|
|
+void grub_cryptodisk_add_secret_provider (struct grub_secret_entry *e);
|
||
|
|
+void grub_cryptodisk_remove_secret_provider (struct grub_secret_entry *e);
|
||
|
|
+
|
||
|
|
#endif
|
||
|
|
--
|
||
|
|
2.25.1
|
||
|
|
|