SHA256
1
0
forked from pool/grub2

Revert to revision 268, boo#1202438

OBS-URL: https://build.opensuse.org/package/show/openSUSE:Factory/grub2?expand=0&rev=271
This commit is contained in:
Richard Brown 2022-08-26 09:20:20 +00:00 committed by Git OBS Bridge
parent ee92804613
commit 1ac59cb02a
18 changed files with 10 additions and 7786 deletions

View File

@ -1,33 +0,0 @@
From 822f71318a69c150da3ad7df5fe8667dfa6e8069 Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Thu, 31 Mar 2022 15:45:35 +0800
Subject: [PATCH] crytodisk: fix cryptodisk module looking up
The error "no cryptodisk module can handle this device" may happen even
encrypted disk were correctly formatted and required modules were loaded.
It is casued by missing break to the loop in which cryptodisk modules are
iterated to find the one matching target's disk format. With the break
statement, the loop will be always ended with testing last cryptodisk module on
the list that may not be able to handle the format of encrypted disk's.
Signed-off-by: Michael Chang <mchang@suse.com>
---
grub-core/disk/cryptodisk.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
index 00c44773fb..6d22bf871c 100644
--- a/grub-core/disk/cryptodisk.c
+++ b/grub-core/disk/cryptodisk.c
@@ -1021,6 +1021,7 @@ grub_cryptodisk_scan_device_real (const char *name,
if (!dev)
continue;
crd = cr;
+ break;
}
if (!dev)
--
2.34.1

View File

@ -1,31 +0,0 @@
From 8eae4c33a32d9951641e289d2809a92a223b1642 Mon Sep 17 00:00:00 2001
From: Glenn Washburn <development@efficientek.com>
Date: Thu, 9 Dec 2021 11:14:50 -0600
Subject: [PATCH 01/14] luks2: Add debug message to align with luks and geli
modules
Signed-off-by: Glenn Washburn <development@efficientek.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
grub-core/disk/luks2.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
index 371a53b837..fea196dd4a 100644
--- a/grub-core/disk/luks2.c
+++ b/grub-core/disk/luks2.c
@@ -370,7 +370,10 @@ luks2_scan (grub_disk_t disk, const char *check_uuid, int check_boot)
uuid[j] = '\0';
if (check_uuid && grub_strcasecmp (check_uuid, uuid) != 0)
- return NULL;
+ {
+ grub_dprintf ("luks2", "%s != %s\n", uuid, check_uuid);
+ return NULL;
+ }
cryptodisk = grub_zalloc (sizeof (*cryptodisk));
if (!cryptodisk)
--
2.34.1

View File

@ -1,187 +0,0 @@
From 4ace73cc192bc63a00f4208b34981a6d91947811 Mon Sep 17 00:00:00 2001
From: Glenn Washburn <development@efficientek.com>
Date: Thu, 9 Dec 2021 11:14:51 -0600
Subject: [PATCH 02/14] cryptodisk: Refactor to discard have_it global
The global "have_it" was never used by the crypto-backends, but was used to
determine if a crypto-backend successfully mounted a cryptodisk with a given
UUID. This is not needed however, because grub_device_iterate() will return
1 if and only if grub_cryptodisk_scan_device() returns 1. And
grub_cryptodisk_scan_device() will now only return 1 if a search_uuid has
been specified and a cryptodisk was successfully setup by a crypto-backend or
a cryptodisk of the requested UUID is already open.
To implement this grub_cryptodisk_scan_device_real() is modified to return
a cryptodisk or NULL on failure and having the appropriate grub_errno set to
indicated failure. Note that grub_cryptodisk_scan_device_real() will fail now
with a new errno GRUB_ERR_BAD_MODULE when none of the cryptodisk backend
modules succeed in identifying the source disk.
With this change grub_device_iterate() will return 1 when a crypto device is
successfully decrypted or when the source device has already been successfully
opened. Prior to this change, trying to mount an already successfully opened
device would trigger an error with the message "no such cryptodisk found",
which is at best misleading. The mount should silently succeed in this case,
which is what happens with this patch.
Signed-off-by: Glenn Washburn <development@efficientek.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
grub-core/disk/cryptodisk.c | 56 +++++++++++++++++++++++--------------
1 file changed, 35 insertions(+), 21 deletions(-)
diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
index 90f82b2d39..9df3d310fe 100644
--- a/grub-core/disk/cryptodisk.c
+++ b/grub-core/disk/cryptodisk.c
@@ -983,7 +983,7 @@ grub_util_cryptodisk_get_uuid (grub_disk_t disk)
#endif
-static int check_boot, have_it;
+static int check_boot;
static char *search_uuid;
static void
@@ -995,7 +995,7 @@ cryptodisk_close (grub_cryptodisk_t dev)
grub_free (dev);
}
-static grub_err_t
+static grub_cryptodisk_t
grub_cryptodisk_scan_device_real (const char *name, grub_disk_t source)
{
grub_err_t err;
@@ -1005,13 +1005,13 @@ grub_cryptodisk_scan_device_real (const char *name, grub_disk_t source)
dev = grub_cryptodisk_get_by_source_disk (source);
if (dev)
- return GRUB_ERR_NONE;
+ return dev;
FOR_CRYPTODISK_DEVS (cr)
{
dev = cr->scan (source, search_uuid, check_boot);
if (grub_errno)
- return grub_errno;
+ return NULL;
if (!dev)
continue;
@@ -1019,16 +1019,16 @@ grub_cryptodisk_scan_device_real (const char *name, grub_disk_t source)
if (err)
{
cryptodisk_close (dev);
- return err;
+ return NULL;
}
grub_cryptodisk_insert (dev, name, source);
- have_it = 1;
-
- return GRUB_ERR_NONE;
+ return dev;
}
- return GRUB_ERR_NONE;
+
+ grub_error (GRUB_ERR_BAD_MODULE, "no cryptodisk module can handle this device");
+ return NULL;
}
#ifdef GRUB_UTIL
@@ -1082,8 +1082,10 @@ static int
grub_cryptodisk_scan_device (const char *name,
void *data __attribute__ ((unused)))
{
- grub_err_t err;
+ int ret = 0;
grub_disk_t source;
+ grub_cryptodisk_t dev;
+ grub_errno = GRUB_ERR_NONE;
/* Try to open disk. */
source = grub_disk_open (name);
@@ -1093,13 +1095,26 @@ grub_cryptodisk_scan_device (const char *name,
return 0;
}
- err = grub_cryptodisk_scan_device_real (name, source);
+ dev = grub_cryptodisk_scan_device_real (name, source);
+ if (dev)
+ {
+ ret = (search_uuid != NULL && grub_strcasecmp (search_uuid, dev->uuid) == 0);
+ goto cleanup;
+ }
- grub_disk_close (source);
-
- if (err)
+ /*
+ * Do not print error when err is GRUB_ERR_BAD_MODULE to avoid many unhelpful
+ * error messages.
+ */
+ if (grub_errno == GRUB_ERR_BAD_MODULE)
+ grub_error_pop ();
+
+ if (grub_errno != GRUB_ERR_NONE)
grub_print_error ();
- return have_it && search_uuid ? 1 : 0;
+
+ cleanup:
+ grub_disk_close (source);
+ return ret;
}
static grub_err_t
@@ -1110,9 +1125,9 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args)
if (argc < 1 && !state[1].set && !state[2].set)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "device name required");
- have_it = 0;
if (state[0].set)
{
+ int found_uuid;
grub_cryptodisk_t dev;
dev = grub_cryptodisk_get_by_uuid (args[0]);
@@ -1125,10 +1140,10 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args)
check_boot = state[2].set;
search_uuid = args[0];
- grub_device_iterate (&grub_cryptodisk_scan_device, NULL);
+ found_uuid = grub_device_iterate (&grub_cryptodisk_scan_device, NULL);
search_uuid = NULL;
- if (!have_it)
+ if (!found_uuid)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "no such cryptodisk found");
return GRUB_ERR_NONE;
}
@@ -1142,7 +1157,6 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args)
}
else
{
- grub_err_t err;
grub_disk_t disk;
grub_cryptodisk_t dev;
char *diskname;
@@ -1178,13 +1192,13 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args)
return GRUB_ERR_NONE;
}
- err = grub_cryptodisk_scan_device_real (diskname, disk);
+ dev = grub_cryptodisk_scan_device_real (diskname, disk);
grub_disk_close (disk);
if (disklast)
*disklast = ')';
- return err;
+ return (dev == NULL) ? grub_errno : GRUB_ERR_NONE;
}
}
--
2.34.1

View File

@ -1,32 +0,0 @@
From 86fe3bbbf75e62387cc9842654fd6c852e9457a6 Mon Sep 17 00:00:00 2001
From: Glenn Washburn <development@efficientek.com>
Date: Thu, 9 Dec 2021 11:14:52 -0600
Subject: [PATCH 03/14] cryptodisk: Return failure in cryptomount when no
cryptodisk modules are loaded
This displays an error notifying the user that they'll want to load
a backend module to make cryptomount useful.
Signed-off-by: Glenn Washburn <development@efficientek.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
grub-core/disk/cryptodisk.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
index 9df3d310fe..27491871a5 100644
--- a/grub-core/disk/cryptodisk.c
+++ b/grub-core/disk/cryptodisk.c
@@ -1125,6 +1125,9 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args)
if (argc < 1 && !state[1].set && !state[2].set)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "device name required");
+ if (grub_cryptodisk_list == NULL)
+ return grub_error (GRUB_ERR_BAD_MODULE, "no cryptodisk modules loaded");
+
if (state[0].set)
{
int found_uuid;
--
2.34.1

View File

@ -1,58 +0,0 @@
From f41488d0e361a34f4d3f8fb6c92729a2901a5c76 Mon Sep 17 00:00:00 2001
From: Glenn Washburn <development@efficientek.com>
Date: Thu, 9 Dec 2021 11:14:53 -0600
Subject: [PATCH 04/14] cryptodisk: Improve error messaging in cryptomount
invocations
Update such that "cryptomount -u UUID" will not print two error messages
when an invalid passphrase is given and the most relevant error message
will be displayed.
Signed-off-by: Glenn Washburn <development@efficientek.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
grub-core/disk/cryptodisk.c | 21 +++++++++++++++++----
1 file changed, 17 insertions(+), 4 deletions(-)
diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
index 27491871a5..3a896c6634 100644
--- a/grub-core/disk/cryptodisk.c
+++ b/grub-core/disk/cryptodisk.c
@@ -1109,7 +1109,10 @@ grub_cryptodisk_scan_device (const char *name,
if (grub_errno == GRUB_ERR_BAD_MODULE)
grub_error_pop ();
- if (grub_errno != GRUB_ERR_NONE)
+ if (search_uuid != NULL)
+ /* Push error onto stack to save for cryptomount. */
+ grub_error_push ();
+ else
grub_print_error ();
cleanup:
@@ -1146,9 +1149,19 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args)
found_uuid = grub_device_iterate (&grub_cryptodisk_scan_device, NULL);
search_uuid = NULL;
- if (!found_uuid)
- return grub_error (GRUB_ERR_BAD_ARGUMENT, "no such cryptodisk found");
- return GRUB_ERR_NONE;
+ if (found_uuid)
+ return GRUB_ERR_NONE;
+ else if (grub_errno == GRUB_ERR_NONE)
+ {
+ /*
+ * Try to pop the next error on the stack. If there is not one, then
+ * no device matched the given UUID.
+ */
+ grub_error_pop ();
+ if (grub_errno == GRUB_ERR_NONE)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "no such cryptodisk found");
+ }
+ return grub_errno;
}
else if (state[1].set || (argc == 0 && state[2].set))
{
--
2.34.1

View File

@ -1,31 +0,0 @@
From 9ef619a7c1d38988f6d91496ea5c59062dcf6013 Mon Sep 17 00:00:00 2001
From: Glenn Washburn <development@efficientek.com>
Date: Thu, 9 Dec 2021 11:14:54 -0600
Subject: [PATCH 05/14] cryptodisk: Improve cryptomount -u error message
When a cryptmount is specified with a UUID, but no cryptodisk backends find
a disk with that UUID, return a more detailed message giving telling the
user that they might not have a needed cryptobackend module loaded.
Signed-off-by: Glenn Washburn <development@efficientek.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
grub-core/disk/cryptodisk.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
index 3a896c6634..5a9780b14c 100644
--- a/grub-core/disk/cryptodisk.c
+++ b/grub-core/disk/cryptodisk.c
@@ -1159,7 +1159,7 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args)
*/
grub_error_pop ();
if (grub_errno == GRUB_ERR_NONE)
- return grub_error (GRUB_ERR_BAD_ARGUMENT, "no such cryptodisk found");
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "no such cryptodisk found, perhaps a needed disk or cryptodisk module is not loaded");
}
return grub_errno;
}
--
2.34.1

View File

@ -1,252 +0,0 @@
From 0a5619abd170b3ad43e44cb8036062506d8623cc Mon Sep 17 00:00:00 2001
From: Glenn Washburn <development@efficientek.com>
Date: Thu, 9 Dec 2021 11:14:55 -0600
Subject: [PATCH 06/14] cryptodisk: Add infrastructure to pass data from
cryptomount to cryptodisk modules
Previously, the cryptomount arguments were passed by global variable and
function call argument, neither of which are ideal. This change passes data
via a grub_cryptomount_args struct, which can be added to over time as
opposed to continually adding arguments to the cryptodisk scan and
recover_key.
As an example, passing a password as a cryptomount argument is implemented.
However, the backends are not implemented, so testing this will return a not
implemented error.
Also, add comments to cryptomount argument parsing to make it more obvious
which argument states are being handled.
Signed-off-by: Glenn Washburn <development@efficientek.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
grub-core/disk/cryptodisk.c | 31 +++++++++++++++++++++----------
grub-core/disk/geli.c | 6 +++++-
grub-core/disk/luks.c | 7 ++++++-
grub-core/disk/luks2.c | 7 ++++++-
include/grub/cryptodisk.h | 9 ++++++++-
5 files changed, 46 insertions(+), 14 deletions(-)
diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
index 5a9780b14c..14c661a86e 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},
+ {"password", 'p', 0, N_("Password to open volumes."), 0, ARG_TYPE_STRING},
{0, 0, 0, 0, 0, 0}
};
@@ -996,7 +997,9 @@ cryptodisk_close (grub_cryptodisk_t dev)
}
static grub_cryptodisk_t
-grub_cryptodisk_scan_device_real (const char *name, grub_disk_t source)
+grub_cryptodisk_scan_device_real (const char *name,
+ grub_disk_t source,
+ grub_cryptomount_args_t cargs)
{
grub_err_t err;
grub_cryptodisk_t dev;
@@ -1015,7 +1018,7 @@ grub_cryptodisk_scan_device_real (const char *name, grub_disk_t source)
if (!dev)
continue;
- err = cr->recover_key (source, dev);
+ err = cr->recover_key (source, dev, cargs);
if (err)
{
cryptodisk_close (dev);
@@ -1080,11 +1083,12 @@ grub_cryptodisk_cheat_mount (const char *sourcedev, const char *cheat)
static int
grub_cryptodisk_scan_device (const char *name,
- void *data __attribute__ ((unused)))
+ void *data)
{
int ret = 0;
grub_disk_t source;
grub_cryptodisk_t dev;
+ grub_cryptomount_args_t cargs = data;
grub_errno = GRUB_ERR_NONE;
/* Try to open disk. */
@@ -1095,7 +1099,7 @@ grub_cryptodisk_scan_device (const char *name,
return 0;
}
- dev = grub_cryptodisk_scan_device_real (name, source);
+ dev = grub_cryptodisk_scan_device_real (name, source, cargs);
if (dev)
{
ret = (search_uuid != NULL && grub_strcasecmp (search_uuid, dev->uuid) == 0);
@@ -1124,6 +1128,7 @@ static grub_err_t
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[1].set && !state[2].set)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "device name required");
@@ -1131,7 +1136,13 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args)
if (grub_cryptodisk_list == NULL)
return grub_error (GRUB_ERR_BAD_MODULE, "no cryptodisk modules loaded");
- if (state[0].set)
+ if (state[3].set) /* password */
+ {
+ cargs.key_data = (grub_uint8_t *) state[3].arg;
+ cargs.key_len = grub_strlen (state[3].arg);
+ }
+
+ if (state[0].set) /* uuid */
{
int found_uuid;
grub_cryptodisk_t dev;
@@ -1146,7 +1157,7 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args)
check_boot = state[2].set;
search_uuid = args[0];
- found_uuid = grub_device_iterate (&grub_cryptodisk_scan_device, NULL);
+ found_uuid = grub_device_iterate (&grub_cryptodisk_scan_device, &cargs);
search_uuid = NULL;
if (found_uuid)
@@ -1163,11 +1174,11 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args)
}
return grub_errno;
}
- else if (state[1].set || (argc == 0 && state[2].set))
+ else if (state[1].set || (argc == 0 && state[2].set)) /* -a|-b */
{
search_uuid = NULL;
check_boot = state[2].set;
- grub_device_iterate (&grub_cryptodisk_scan_device, NULL);
+ grub_device_iterate (&grub_cryptodisk_scan_device, &cargs);
search_uuid = NULL;
return GRUB_ERR_NONE;
}
@@ -1208,7 +1219,7 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args)
return GRUB_ERR_NONE;
}
- dev = grub_cryptodisk_scan_device_real (diskname, disk);
+ dev = grub_cryptodisk_scan_device_real (diskname, disk, &cargs);
grub_disk_close (disk);
if (disklast)
@@ -1347,7 +1358,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_("[-p password] <SOURCE|-u UUID|-a|-b>"),
N_("Mount a crypto device."), options);
grub_procfs_register ("luks_script", &luks_script);
}
diff --git a/grub-core/disk/geli.c b/grub-core/disk/geli.c
index 2f34a35e6b..777da3a055 100644
--- a/grub-core/disk/geli.c
+++ b/grub-core/disk/geli.c
@@ -398,7 +398,7 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
}
static grub_err_t
-recover_key (grub_disk_t source, grub_cryptodisk_t dev)
+recover_key (grub_disk_t source, grub_cryptodisk_t dev, grub_cryptomount_args_t cargs)
{
grub_size_t keysize;
grub_uint8_t digest[GRUB_CRYPTO_MAX_MDLEN];
@@ -414,6 +414,10 @@ recover_key (grub_disk_t source, grub_cryptodisk_t dev)
grub_disk_addr_t sector;
grub_err_t err;
+ /* Keyfiles are not implemented yet */
+ if (cargs->key_data != NULL || cargs->key_len)
+ return GRUB_ERR_NOT_IMPLEMENTED_YET;
+
if (dev->cipher->cipher->blocksize > GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE)
return grub_error (GRUB_ERR_BUG, "cipher block is too long");
diff --git a/grub-core/disk/luks.c b/grub-core/disk/luks.c
index 13103ea6a2..c5858fcf8a 100644
--- a/grub-core/disk/luks.c
+++ b/grub-core/disk/luks.c
@@ -152,7 +152,8 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
static grub_err_t
luks_recover_key (grub_disk_t source,
- grub_cryptodisk_t dev)
+ grub_cryptodisk_t dev,
+ grub_cryptomount_args_t cargs)
{
struct grub_luks_phdr header;
grub_size_t keysize;
@@ -165,6 +166,10 @@ luks_recover_key (grub_disk_t source,
grub_size_t max_stripes = 1;
char *tmp;
+ /* Keyfiles are not implemented yet */
+ if (cargs->key_data != NULL || cargs->key_len)
+ return GRUB_ERR_NOT_IMPLEMENTED_YET;
+
err = grub_disk_read (source, 0, 0, sizeof (header), &header);
if (err)
return err;
diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
index fea196dd4a..2cbec8acc2 100644
--- a/grub-core/disk/luks2.c
+++ b/grub-core/disk/luks2.c
@@ -545,7 +545,8 @@ luks2_decrypt_key (grub_uint8_t *out_key,
static grub_err_t
luks2_recover_key (grub_disk_t source,
- grub_cryptodisk_t crypt)
+ grub_cryptodisk_t crypt,
+ grub_cryptomount_args_t cargs)
{
grub_uint8_t candidate_key[GRUB_CRYPTODISK_MAX_KEYLEN];
char passphrase[MAX_PASSPHRASE], cipher[32];
@@ -559,6 +560,10 @@ luks2_recover_key (grub_disk_t source,
grub_json_t *json = NULL, keyslots;
grub_err_t ret;
+ /* Keyfiles are not implemented yet */
+ if (cargs->key_data != NULL || cargs->key_len)
+ return GRUB_ERR_NOT_IMPLEMENTED_YET;
+
ret = luks2_read_header (source, &header);
if (ret)
return ret;
diff --git a/include/grub/cryptodisk.h b/include/grub/cryptodisk.h
index dcf17fbb3a..282f8ac456 100644
--- a/include/grub/cryptodisk.h
+++ b/include/grub/cryptodisk.h
@@ -66,6 +66,13 @@ typedef gcry_err_code_t
(*grub_cryptodisk_rekey_func_t) (struct grub_cryptodisk *dev,
grub_uint64_t zoneno);
+struct grub_cryptomount_args
+{
+ grub_uint8_t *key_data;
+ grub_size_t key_len;
+};
+typedef struct grub_cryptomount_args *grub_cryptomount_args_t;
+
struct grub_cryptodisk
{
struct grub_cryptodisk *next;
@@ -119,7 +126,7 @@ struct grub_cryptodisk_dev
grub_cryptodisk_t (*scan) (grub_disk_t disk, const char *check_uuid,
int boot_only);
- grub_err_t (*recover_key) (grub_disk_t disk, grub_cryptodisk_t dev);
+ grub_err_t (*recover_key) (grub_disk_t disk, grub_cryptodisk_t dev, grub_cryptomount_args_t cargs);
};
typedef struct grub_cryptodisk_dev *grub_cryptodisk_dev_t;
--
2.34.1

View File

@ -1,342 +0,0 @@
From a3ae3f800f6aa3f6036351133ed69fa47c9fa371 Mon Sep 17 00:00:00 2001
From: Glenn Washburn <development@efficientek.com>
Date: Thu, 9 Dec 2021 11:14:56 -0600
Subject: [PATCH 07/14] cryptodisk: Refactor password input out of crypto dev
modules into cryptodisk
The crypto device modules should only be setting up the crypto devices and
not getting user input. This has the added benefit of simplifying the code
such that three essentially duplicate pieces of code are merged into one.
Add documentation of passphrase option for cryptomount as it is now usable.
Signed-off-by: Glenn Washburn <development@efficientek.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
docs/grub.texi | 8 ++++--
grub-core/disk/cryptodisk.c | 56 +++++++++++++++++++++++++++++--------
grub-core/disk/geli.c | 26 ++++-------------
grub-core/disk/luks.c | 27 +++---------------
grub-core/disk/luks2.c | 25 +++--------------
include/grub/cryptodisk.h | 1 +
6 files changed, 64 insertions(+), 79 deletions(-)
diff --git a/docs/grub.texi b/docs/grub.texi
index f4794fddac..4504bcabec 100644
--- a/docs/grub.texi
+++ b/docs/grub.texi
@@ -4310,9 +4310,11 @@ Alias for @code{hashsum --hash crc32 arg @dots{}}. See command @command{hashsum}
@node cryptomount
@subsection cryptomount
-@deffn Command cryptomount device|@option{-u} uuid|@option{-a}|@option{-b}
-Setup access to encrypted device. If necessary, passphrase
-is requested interactively. Option @var{device} configures specific grub device
+@deffn Command cryptomount [@option{-p} password] device|@option{-u} uuid|@option{-a}|@option{-b}
+Setup access to encrypted device. If @option{-p} is not given, a passphrase
+is requested interactively. Otherwise, the given @var{password} will be used and
+no passphrase will be requested interactively.
+Option @var{device} configures specific grub device
(@pxref{Naming convention}); option @option{-u} @var{uuid} configures device
with specified @var{uuid}; option @option{-a} configures all detected encrypted
devices; option @option{-b} configures all geli containers that have boot flag set.
diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
index 14c661a86e..d12368a1f7 100644
--- a/grub-core/disk/cryptodisk.c
+++ b/grub-core/disk/cryptodisk.c
@@ -1001,9 +1001,11 @@ grub_cryptodisk_scan_device_real (const char *name,
grub_disk_t source,
grub_cryptomount_args_t cargs)
{
- grub_err_t err;
+ grub_err_t ret = GRUB_ERR_NONE;
grub_cryptodisk_t dev;
grub_cryptodisk_dev_t cr;
+ int askpass = 0;
+ char *part = NULL;
dev = grub_cryptodisk_get_by_source_disk (source);
@@ -1017,21 +1019,53 @@ grub_cryptodisk_scan_device_real (const char *name,
return NULL;
if (!dev)
continue;
-
- err = cr->recover_key (source, dev, cargs);
- if (err)
- {
- cryptodisk_close (dev);
- return NULL;
- }
+
+ if (!cargs->key_len)
+ {
+ /* Get the passphrase from the user, if no key data. */
+ askpass = 1;
+ if (source->partition != NULL)
+ part = grub_partition_get_name (source->partition);
+ grub_printf_ (N_("Enter passphrase for %s%s%s (%s): "), source->name,
+ source->partition != NULL ? "," : "",
+ part != NULL ? part : "",
+ dev->uuid);
+ grub_free (part);
+
+ cargs->key_data = grub_malloc (GRUB_CRYPTODISK_MAX_PASSPHRASE);
+ if (cargs->key_data == NULL)
+ return NULL;
+
+ if (!grub_password_get ((char *) cargs->key_data, GRUB_CRYPTODISK_MAX_PASSPHRASE))
+ {
+ grub_error (GRUB_ERR_BAD_ARGUMENT, "passphrase not supplied");
+ goto error;
+ }
+ cargs->key_len = grub_strlen ((char *) cargs->key_data);
+ }
+
+ ret = cr->recover_key (source, dev, cargs);
+ if (ret != GRUB_ERR_NONE)
+ goto error;
grub_cryptodisk_insert (dev, name, source);
- return dev;
+ goto cleanup;
}
-
grub_error (GRUB_ERR_BAD_MODULE, "no cryptodisk module can handle this device");
- return NULL;
+ goto cleanup;
+
+ error:
+ cryptodisk_close (dev);
+ dev = NULL;
+
+ cleanup:
+ if (askpass)
+ {
+ cargs->key_len = 0;
+ grub_free (cargs->key_data);
+ }
+ return dev;
}
#ifdef GRUB_UTIL
diff --git a/grub-core/disk/geli.c b/grub-core/disk/geli.c
index 777da3a055..7299a47d19 100644
--- a/grub-core/disk/geli.c
+++ b/grub-core/disk/geli.c
@@ -135,8 +135,6 @@ const char *algorithms[] = {
[0x16] = "aes"
};
-#define MAX_PASSPHRASE 256
-
static gcry_err_code_t
geli_rekey (struct grub_cryptodisk *dev, grub_uint64_t zoneno)
{
@@ -406,17 +404,14 @@ recover_key (grub_disk_t source, grub_cryptodisk_t dev, grub_cryptomount_args_t
grub_uint8_t verify_key[GRUB_CRYPTO_MAX_MDLEN];
grub_uint8_t zero[GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE];
grub_uint8_t geli_cipher_key[64];
- char passphrase[MAX_PASSPHRASE] = "";
unsigned i;
gcry_err_code_t gcry_err;
struct grub_geli_phdr header;
- char *tmp;
grub_disk_addr_t sector;
grub_err_t err;
- /* Keyfiles are not implemented yet */
- if (cargs->key_data != NULL || cargs->key_len)
- return GRUB_ERR_NOT_IMPLEMENTED_YET;
+ if (cargs->key_data == NULL || cargs->key_len == 0)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "no key data");
if (dev->cipher->cipher->blocksize > GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE)
return grub_error (GRUB_ERR_BUG, "cipher block is too long");
@@ -438,23 +433,12 @@ recover_key (grub_disk_t source, grub_cryptodisk_t dev, grub_cryptomount_args_t
grub_puts_ (N_("Attempting to decrypt master key..."));
- /* Get the passphrase from the user. */
- tmp = NULL;
- if (source->partition)
- tmp = grub_partition_get_name (source->partition);
- grub_printf_ (N_("Enter passphrase for %s%s%s (%s): "), source->name,
- source->partition ? "," : "", tmp ? : "",
- dev->uuid);
- grub_free (tmp);
- if (!grub_password_get (passphrase, MAX_PASSPHRASE))
- return grub_error (GRUB_ERR_BAD_ARGUMENT, "Passphrase not supplied");
-
/* Calculate the PBKDF2 of the user supplied passphrase. */
if (grub_le_to_cpu32 (header.niter) != 0)
{
grub_uint8_t pbkdf_key[64];
- gcry_err = grub_crypto_pbkdf2 (dev->hash, (grub_uint8_t *) passphrase,
- grub_strlen (passphrase),
+ gcry_err = grub_crypto_pbkdf2 (dev->hash, cargs->key_data,
+ cargs->key_len,
header.salt,
sizeof (header.salt),
grub_le_to_cpu32 (header.niter),
@@ -477,7 +461,7 @@ recover_key (grub_disk_t source, grub_cryptodisk_t dev, grub_cryptomount_args_t
return grub_crypto_gcry_error (GPG_ERR_OUT_OF_MEMORY);
grub_crypto_hmac_write (hnd, header.salt, sizeof (header.salt));
- grub_crypto_hmac_write (hnd, passphrase, grub_strlen (passphrase));
+ grub_crypto_hmac_write (hnd, cargs->key_data, cargs->key_len);
gcry_err = grub_crypto_hmac_fini (hnd, geomkey);
if (gcry_err)
diff --git a/grub-core/disk/luks.c b/grub-core/disk/luks.c
index c5858fcf8a..39a7af6a43 100644
--- a/grub-core/disk/luks.c
+++ b/grub-core/disk/luks.c
@@ -29,8 +29,6 @@
GRUB_MOD_LICENSE ("GPLv3+");
-#define MAX_PASSPHRASE 256
-
#define LUKS_KEY_ENABLED 0x00AC71F3
/* On disk LUKS header */
@@ -158,17 +156,14 @@ luks_recover_key (grub_disk_t source,
struct grub_luks_phdr header;
grub_size_t keysize;
grub_uint8_t *split_key = NULL;
- char passphrase[MAX_PASSPHRASE] = "";
grub_uint8_t candidate_digest[sizeof (header.mkDigest)];
unsigned i;
grub_size_t length;
grub_err_t err;
grub_size_t max_stripes = 1;
- char *tmp;
- /* Keyfiles are not implemented yet */
- if (cargs->key_data != NULL || cargs->key_len)
- return GRUB_ERR_NOT_IMPLEMENTED_YET;
+ if (cargs->key_data == NULL || cargs->key_len == 0)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "no key data");
err = grub_disk_read (source, 0, 0, sizeof (header), &header);
if (err)
@@ -188,20 +183,6 @@ luks_recover_key (grub_disk_t source,
if (!split_key)
return grub_errno;
- /* Get the passphrase from the user. */
- tmp = NULL;
- if (source->partition)
- tmp = grub_partition_get_name (source->partition);
- grub_printf_ (N_("Enter passphrase for %s%s%s (%s): "), source->name,
- source->partition ? "," : "", tmp ? : "",
- dev->uuid);
- grub_free (tmp);
- if (!grub_password_get (passphrase, MAX_PASSPHRASE))
- {
- grub_free (split_key);
- return grub_error (GRUB_ERR_BAD_ARGUMENT, "Passphrase not supplied");
- }
-
/* Try to recover master key from each active keyslot. */
for (i = 0; i < ARRAY_SIZE (header.keyblock); i++)
{
@@ -216,8 +197,8 @@ luks_recover_key (grub_disk_t source,
grub_dprintf ("luks", "Trying keyslot %d\n", i);
/* Calculate the PBKDF2 of the user supplied passphrase. */
- gcry_err = grub_crypto_pbkdf2 (dev->hash, (grub_uint8_t *) passphrase,
- grub_strlen (passphrase),
+ gcry_err = grub_crypto_pbkdf2 (dev->hash, cargs->key_data,
+ cargs->key_len,
header.keyblock[i].passwordSalt,
sizeof (header.keyblock[i].passwordSalt),
grub_be_to_cpu32 (header.keyblock[i].
diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
index 2cbec8acc2..09740b53f9 100644
--- a/grub-core/disk/luks2.c
+++ b/grub-core/disk/luks2.c
@@ -35,8 +35,6 @@ GRUB_MOD_LICENSE ("GPLv3+");
#define LUKS_MAGIC_1ST "LUKS\xBA\xBE"
#define LUKS_MAGIC_2ND "SKUL\xBA\xBE"
-#define MAX_PASSPHRASE 256
-
enum grub_luks2_kdf_type
{
LUKS2_KDF_TYPE_ARGON2I,
@@ -549,8 +547,7 @@ luks2_recover_key (grub_disk_t source,
grub_cryptomount_args_t cargs)
{
grub_uint8_t candidate_key[GRUB_CRYPTODISK_MAX_KEYLEN];
- char passphrase[MAX_PASSPHRASE], cipher[32];
- char *json_header = NULL, *part = NULL, *ptr;
+ char cipher[32], *json_header = NULL, *ptr;
grub_size_t candidate_key_len = 0, json_idx, size;
grub_luks2_header_t header;
grub_luks2_keyslot_t keyslot;
@@ -560,9 +557,8 @@ luks2_recover_key (grub_disk_t source,
grub_json_t *json = NULL, keyslots;
grub_err_t ret;
- /* Keyfiles are not implemented yet */
- if (cargs->key_data != NULL || cargs->key_len)
- return GRUB_ERR_NOT_IMPLEMENTED_YET;
+ if (cargs->key_data == NULL || cargs->key_len == 0)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "no key data");
ret = luks2_read_header (source, &header);
if (ret)
@@ -589,18 +585,6 @@ luks2_recover_key (grub_disk_t source,
goto err;
}
- /* Get the passphrase from the user. */
- if (source->partition)
- part = grub_partition_get_name (source->partition);
- grub_printf_ (N_("Enter passphrase for %s%s%s (%s): "), source->name,
- source->partition ? "," : "", part ? : "",
- crypt->uuid);
- if (!grub_password_get (passphrase, MAX_PASSPHRASE))
- {
- ret = grub_error (GRUB_ERR_BAD_ARGUMENT, "Passphrase not supplied");
- goto err;
- }
-
if (grub_json_getvalue (&keyslots, json, "keyslots") ||
grub_json_getsize (&size, &keyslots))
{
@@ -725,7 +709,7 @@ luks2_recover_key (grub_disk_t source,
}
ret = luks2_decrypt_key (candidate_key, source, crypt, &keyslot,
- (const grub_uint8_t *) passphrase, grub_strlen (passphrase));
+ cargs->key_data, cargs->key_len);
if (ret)
{
grub_dprintf ("luks2", "Decryption with keyslot \"%" PRIuGRUB_UINT64_T "\" failed: %s\n",
@@ -777,7 +761,6 @@ luks2_recover_key (grub_disk_t source,
}
err:
- grub_free (part);
grub_free (json_header);
grub_json_free (json);
return ret;
diff --git a/include/grub/cryptodisk.h b/include/grub/cryptodisk.h
index 282f8ac456..5bd970692f 100644
--- a/include/grub/cryptodisk.h
+++ b/include/grub/cryptodisk.h
@@ -59,6 +59,7 @@ typedef enum
#define GRUB_CRYPTODISK_GF_LOG_BYTES (GRUB_CRYPTODISK_GF_LOG_SIZE - 3)
#define GRUB_CRYPTODISK_GF_BYTES (1U << GRUB_CRYPTODISK_GF_LOG_BYTES)
#define GRUB_CRYPTODISK_MAX_KEYLEN 128
+#define GRUB_CRYPTODISK_MAX_PASSPHRASE 256
struct grub_cryptodisk;
--
2.34.1

View File

@ -1,248 +0,0 @@
From 5323778d84a7289acba0e50d84fb1afd45fff596 Mon Sep 17 00:00:00 2001
From: Glenn Washburn <development@efficientek.com>
Date: Thu, 9 Dec 2021 11:14:57 -0600
Subject: [PATCH 08/14] cryptodisk: Move global variables into
grub_cryptomount_args struct
Note that cargs.search_uuid does not need to be initialized in various parts
of the cryptomount argument parsing, just once when cargs is declared with
a struct initializer. The previous code used a global variable which would
retain the value across cryptomount invocations.
Signed-off-by: Glenn Washburn <development@efficientek.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
grub-core/disk/cryptodisk.c | 24 +++++++++---------------
grub-core/disk/geli.c | 9 ++++-----
grub-core/disk/luks.c | 9 ++++-----
grub-core/disk/luks2.c | 8 ++++----
include/grub/cryptodisk.h | 9 +++++++--
5 files changed, 28 insertions(+), 31 deletions(-)
diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
index d12368a1f7..7ca880402d 100644
--- a/grub-core/disk/cryptodisk.c
+++ b/grub-core/disk/cryptodisk.c
@@ -984,9 +984,6 @@ grub_util_cryptodisk_get_uuid (grub_disk_t disk)
#endif
-static int check_boot;
-static char *search_uuid;
-
static void
cryptodisk_close (grub_cryptodisk_t dev)
{
@@ -1014,7 +1011,7 @@ grub_cryptodisk_scan_device_real (const char *name,
FOR_CRYPTODISK_DEVS (cr)
{
- dev = cr->scan (source, search_uuid, check_boot);
+ dev = cr->scan (source, cargs);
if (grub_errno)
return NULL;
if (!dev)
@@ -1077,6 +1074,7 @@ grub_cryptodisk_cheat_mount (const char *sourcedev, const char *cheat)
grub_cryptodisk_t dev;
grub_cryptodisk_dev_t cr;
grub_disk_t source;
+ struct grub_cryptomount_args cargs = {0};
/* Try to open disk. */
source = grub_disk_open (sourcedev);
@@ -1093,7 +1091,7 @@ grub_cryptodisk_cheat_mount (const char *sourcedev, const char *cheat)
FOR_CRYPTODISK_DEVS (cr)
{
- dev = cr->scan (source, search_uuid, check_boot);
+ dev = cr->scan (source, &cargs);
if (grub_errno)
return grub_errno;
if (!dev)
@@ -1136,7 +1134,7 @@ grub_cryptodisk_scan_device (const char *name,
dev = grub_cryptodisk_scan_device_real (name, source, cargs);
if (dev)
{
- ret = (search_uuid != NULL && grub_strcasecmp (search_uuid, dev->uuid) == 0);
+ ret = (cargs->search_uuid != NULL && grub_strcasecmp (cargs->search_uuid, dev->uuid) == 0);
goto cleanup;
}
@@ -1147,7 +1145,7 @@ grub_cryptodisk_scan_device (const char *name,
if (grub_errno == GRUB_ERR_BAD_MODULE)
grub_error_pop ();
- if (search_uuid != NULL)
+ if (cargs->search_uuid != NULL)
/* Push error onto stack to save for cryptomount. */
grub_error_push ();
else
@@ -1189,10 +1187,9 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args)
return GRUB_ERR_NONE;
}
- check_boot = state[2].set;
- search_uuid = args[0];
+ cargs.check_boot = state[2].set;
+ cargs.search_uuid = args[0];
found_uuid = grub_device_iterate (&grub_cryptodisk_scan_device, &cargs);
- search_uuid = NULL;
if (found_uuid)
return GRUB_ERR_NONE;
@@ -1210,10 +1207,8 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args)
}
else if (state[1].set || (argc == 0 && state[2].set)) /* -a|-b */
{
- search_uuid = NULL;
- check_boot = state[2].set;
+ cargs.check_boot = state[2].set;
grub_device_iterate (&grub_cryptodisk_scan_device, &cargs);
- search_uuid = NULL;
return GRUB_ERR_NONE;
}
else
@@ -1224,8 +1219,7 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args)
char *disklast = NULL;
grub_size_t len;
- search_uuid = NULL;
- check_boot = state[2].set;
+ cargs.check_boot = state[2].set;
diskname = args[0];
len = grub_strlen (diskname);
if (len && diskname[0] == '(' && diskname[len - 1] == ')')
diff --git a/grub-core/disk/geli.c b/grub-core/disk/geli.c
index 7299a47d19..23789c43f3 100644
--- a/grub-core/disk/geli.c
+++ b/grub-core/disk/geli.c
@@ -240,8 +240,7 @@ grub_util_get_geli_uuid (const char *dev)
#endif
static grub_cryptodisk_t
-configure_ciphers (grub_disk_t disk, const char *check_uuid,
- int boot_only)
+configure_ciphers (grub_disk_t disk, grub_cryptomount_args_t cargs)
{
grub_cryptodisk_t newdev;
struct grub_geli_phdr header;
@@ -289,7 +288,7 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
return NULL;
}
- if (boot_only && !(grub_le_to_cpu32 (header.flags) & GRUB_GELI_FLAGS_BOOT))
+ if (cargs->check_boot && !(grub_le_to_cpu32 (header.flags) & GRUB_GELI_FLAGS_BOOT))
{
grub_dprintf ("geli", "not a boot volume\n");
return NULL;
@@ -302,9 +301,9 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
return NULL;
}
- if (check_uuid && grub_strcasecmp (check_uuid, uuid) != 0)
+ if (cargs->search_uuid != NULL && grub_strcasecmp (cargs->search_uuid, uuid) != 0)
{
- grub_dprintf ("geli", "%s != %s\n", uuid, check_uuid);
+ grub_dprintf ("geli", "%s != %s\n", uuid, cargs->search_uuid);
return NULL;
}
diff --git a/grub-core/disk/luks.c b/grub-core/disk/luks.c
index 39a7af6a43..f0feb38447 100644
--- a/grub-core/disk/luks.c
+++ b/grub-core/disk/luks.c
@@ -63,8 +63,7 @@ gcry_err_code_t AF_merge (const gcry_md_spec_t * hash, grub_uint8_t * src,
grub_size_t blocknumbers);
static grub_cryptodisk_t
-configure_ciphers (grub_disk_t disk, const char *check_uuid,
- int check_boot)
+configure_ciphers (grub_disk_t disk, grub_cryptomount_args_t cargs)
{
grub_cryptodisk_t newdev;
const char *iptr;
@@ -76,7 +75,7 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
char hashspec[sizeof (header.hashSpec) + 1];
grub_err_t err;
- if (check_boot)
+ if (cargs->check_boot)
return NULL;
/* Read the LUKS header. */
@@ -103,9 +102,9 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
}
*optr = 0;
- if (check_uuid && grub_strcasecmp (check_uuid, uuid) != 0)
+ if (cargs->search_uuid != NULL && grub_strcasecmp (cargs->search_uuid, uuid) != 0)
{
- grub_dprintf ("luks", "%s != %s\n", uuid, check_uuid);
+ grub_dprintf ("luks", "%s != %s\n", uuid, cargs->search_uuid);
return NULL;
}
diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
index 09740b53f9..ccfacb63a3 100644
--- a/grub-core/disk/luks2.c
+++ b/grub-core/disk/luks2.c
@@ -346,14 +346,14 @@ luks2_read_header (grub_disk_t disk, grub_luks2_header_t *outhdr)
}
static grub_cryptodisk_t
-luks2_scan (grub_disk_t disk, const char *check_uuid, int check_boot)
+luks2_scan (grub_disk_t disk, grub_cryptomount_args_t cargs)
{
grub_cryptodisk_t cryptodisk;
grub_luks2_header_t header;
char uuid[sizeof (header.uuid) + 1];
grub_size_t i, j;
- if (check_boot)
+ if (cargs->check_boot)
return NULL;
if (luks2_read_header (disk, &header))
@@ -367,9 +367,9 @@ luks2_scan (grub_disk_t disk, const char *check_uuid, int check_boot)
uuid[j++] = header.uuid[i];
uuid[j] = '\0';
- if (check_uuid && grub_strcasecmp (check_uuid, uuid) != 0)
+ if (cargs->search_uuid != NULL && grub_strcasecmp (cargs->search_uuid, uuid) != 0)
{
- grub_dprintf ("luks2", "%s != %s\n", uuid, check_uuid);
+ grub_dprintf ("luks2", "%s != %s\n", uuid, cargs->search_uuid);
return NULL;
}
diff --git a/include/grub/cryptodisk.h b/include/grub/cryptodisk.h
index 5bd970692f..c6524c9ea9 100644
--- a/include/grub/cryptodisk.h
+++ b/include/grub/cryptodisk.h
@@ -69,7 +69,13 @@ typedef gcry_err_code_t
struct grub_cryptomount_args
{
+ /* scan: Flag to indicate that only bootable volumes should be decrypted */
+ grub_uint32_t check_boot : 1;
+ /* scan: Only volumes matching this UUID should be decrpyted */
+ char *search_uuid;
+ /* recover_key: Key data used to decrypt voume */
grub_uint8_t *key_data;
+ /* recover_key: Length of key_data */
grub_size_t key_len;
};
typedef struct grub_cryptomount_args *grub_cryptomount_args_t;
@@ -125,8 +131,7 @@ struct grub_cryptodisk_dev
struct grub_cryptodisk_dev *next;
struct grub_cryptodisk_dev **prev;
- grub_cryptodisk_t (*scan) (grub_disk_t disk, const char *check_uuid,
- int boot_only);
+ grub_cryptodisk_t (*scan) (grub_disk_t disk, grub_cryptomount_args_t cargs);
grub_err_t (*recover_key) (grub_disk_t disk, grub_cryptodisk_t dev, grub_cryptomount_args_t cargs);
};
typedef struct grub_cryptodisk_dev *grub_cryptodisk_dev_t;
--
2.34.1

View File

@ -1,39 +0,0 @@
From b1acd971fa648fa3c6f3a54db4fdf45fae02ce54 Mon Sep 17 00:00:00 2001
From: Glenn Washburn <development@efficientek.com>
Date: Thu, 9 Dec 2021 11:14:58 -0600
Subject: [PATCH 09/14] cryptodisk: Improve handling of partition name in
cryptomount password prompt
Call grub_partition_get_name() unconditionally to initialize the part
variable. Then part will only be NULL when grub_partition_get_name() errors.
Note that when source->partition is NULL, then grub_partition_get_name()
returns an allocated empty string. So no comma or partition will be printed,
as desired.
Signed-off-by: Glenn Washburn <development@efficientek.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
grub-core/disk/cryptodisk.c | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
index 7ca880402d..497097394f 100644
--- a/grub-core/disk/cryptodisk.c
+++ b/grub-core/disk/cryptodisk.c
@@ -1021,11 +1021,10 @@ grub_cryptodisk_scan_device_real (const char *name,
{
/* Get the passphrase from the user, if no key data. */
askpass = 1;
- if (source->partition != NULL)
- part = grub_partition_get_name (source->partition);
+ part = grub_partition_get_name (source->partition);
grub_printf_ (N_("Enter passphrase for %s%s%s (%s): "), source->name,
source->partition != NULL ? "," : "",
- part != NULL ? part : "",
+ part != NULL ? part : N_("UNKNOWN"),
dev->uuid);
grub_free (part);
--
2.34.1

View File

@ -1,189 +0,0 @@
From 2d959549857305d5e4d95a19a0850885f85179d6 Mon Sep 17 00:00:00 2001
From: Hernan Gatta <hegatta@linux.microsoft.com>
Date: Tue, 1 Feb 2022 05:02:53 -0800
Subject: [PATCH 10/14] protectors: Add key protectors framework
A key protector encapsulates functionality to retrieve an unlocking key for a
fully-encrypted disk from a specific source. A key protector module registers
itself with the key protectors framework when it is loaded and unregisters when
unloaded. Additionally, a key protector may accept parameters that describe how
it should operate.
The key protectors framework, besides offering registration and unregistration
functions, also offers a one-stop routine for finding and invoking a key
protector by name. If a key protector with the specified name exists and if an
unlocking key is successfully retrieved by it, the function returns to the
caller the retrieved key and its length.
Signed-off-by: Hernan Gatta <hegatta@linux.microsoft.com>
---
grub-core/Makefile.am | 1 +
grub-core/Makefile.core.def | 1 +
grub-core/kern/protectors.c | 75 +++++++++++++++++++++++++++++++++++++
include/grub/protector.h | 48 ++++++++++++++++++++++++
4 files changed, 125 insertions(+)
create mode 100644 grub-core/kern/protectors.c
create mode 100644 include/grub/protector.h
diff --git a/grub-core/Makefile.am b/grub-core/Makefile.am
index de241f0d04..dc07ba6f87 100644
--- a/grub-core/Makefile.am
+++ b/grub-core/Makefile.am
@@ -90,6 +90,7 @@ endif
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/mm.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/parser.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/partition.h
+KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/protector.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/stack_protector.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/term.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/time.h
diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
index f3140815b8..b0001a33cf 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -138,6 +138,7 @@ kernel = {
common = kern/misc.c;
common = kern/parser.c;
common = kern/partition.c;
+ common = kern/protectors.c;
common = kern/rescue_parser.c;
common = kern/rescue_reader.c;
common = kern/term.c;
diff --git a/grub-core/kern/protectors.c b/grub-core/kern/protectors.c
new file mode 100644
index 0000000000..21954dfa48
--- /dev/null
+++ b/grub-core/kern/protectors.c
@@ -0,0 +1,75 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2022 Microsoft Corporation
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/list.h>
+#include <grub/misc.h>
+#include <grub/mm.h>
+#include <grub/protector.h>
+
+struct grub_key_protector *grub_key_protectors = NULL;
+
+grub_err_t
+grub_key_protector_register (struct grub_key_protector *protector)
+{
+ if (!protector || !protector->name || !grub_strlen(protector->name))
+ return GRUB_ERR_BAD_ARGUMENT;
+
+ if (grub_key_protectors &&
+ grub_named_list_find (GRUB_AS_NAMED_LIST (grub_key_protectors),
+ protector->name))
+ return GRUB_ERR_BAD_ARGUMENT;
+
+ grub_list_push (GRUB_AS_LIST_P (&grub_key_protectors),
+ GRUB_AS_LIST (protector));
+
+ return GRUB_ERR_NONE;
+}
+
+grub_err_t
+grub_key_protector_unregister (struct grub_key_protector *protector)
+{
+ if (!protector)
+ return GRUB_ERR_BAD_ARGUMENT;
+
+ grub_list_remove (GRUB_AS_LIST (protector));
+
+ return GRUB_ERR_NONE;
+}
+
+grub_err_t
+grub_key_protector_recover_key (const char *protector, grub_uint8_t **key,
+ grub_size_t *key_size)
+{
+ struct grub_key_protector *kp = NULL;
+
+ if (!grub_key_protectors)
+ return GRUB_ERR_OUT_OF_RANGE;
+
+ if (!protector || !grub_strlen (protector))
+ return GRUB_ERR_BAD_ARGUMENT;
+
+ kp = grub_named_list_find (GRUB_AS_NAMED_LIST (grub_key_protectors),
+ protector);
+ if (!kp)
+ return grub_error (GRUB_ERR_OUT_OF_RANGE,
+ N_("A key protector with name '%s' could not be found. "
+ "Is the name spelled correctly and is the "
+ "corresponding module loaded?"), protector);
+
+ return kp->recover_key (key, key_size);
+}
diff --git a/include/grub/protector.h b/include/grub/protector.h
new file mode 100644
index 0000000000..179020a344
--- /dev/null
+++ b/include/grub/protector.h
@@ -0,0 +1,48 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2022 Microsoft Corporation
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_PROTECTOR_HEADER
+#define GRUB_PROTECTOR_HEADER 1
+
+#include <grub/err.h>
+#include <grub/types.h>
+
+struct grub_key_protector
+{
+ struct grub_key_protector *next;
+ struct grub_key_protector **prev;
+
+ const char *name;
+
+ grub_err_t (*recover_key) (grub_uint8_t **key, grub_size_t *key_size);
+};
+
+extern struct grub_key_protector *EXPORT_VAR (grub_key_protectors);
+
+grub_err_t
+EXPORT_FUNC (grub_key_protector_register) (struct grub_key_protector *protector);
+
+grub_err_t
+EXPORT_FUNC (grub_key_protector_unregister) (struct grub_key_protector *protector);
+
+grub_err_t
+EXPORT_FUNC (grub_key_protector_recover_key) (const char *protector,
+ grub_uint8_t **key,
+ grub_size_t *key_size);
+
+#endif /* ! GRUB_PROTECTOR_HEADER */
--
2.34.1

File diff suppressed because it is too large Load Diff

View File

@ -1,977 +0,0 @@
From b173db7537920ee5706e1c961fea3086ada6b6dd Mon Sep 17 00:00:00 2001
From: Hernan Gatta <hegatta@linux.microsoft.com>
Date: Tue, 1 Feb 2022 05:02:55 -0800
Subject: [PATCH 12/14] protectors: Add TPM2 Key Protector
The TPM2 key protector is a module that enables the automatic retrieval of a
fully-encrypted disk's unlocking key from a TPM 2.0.
The theory of operation is such that the module accepts various arguments, most
of which are optional and therefore possess reasonable defaults. One of these
arguments is the keyfile parameter, which is mandatory.
The value of this parameter must be a path to a sealed key file (e.g.,
(hd0,gpt1)/boot/grub2/sealed_key). This sealed key file is created via the
grub-protect tool. The tool utilizes the TPM's sealing functionality to seal
(i.e., encrypt) an unlocking key using a Storage Root Key (SRK) to the values of
various Platform Configuration Registers (PCRs). These PCRs reflect the state of
the system as it boots. If the values are as expected, the system may be
considered trustworthy, at which point the TPM allows for a caller to utilize
the private component of the SRK to unseal (i.e., decrypt) the sealed key file.
The caller, in this case, is this key protector.
The TPM2 key protector registers two commands:
- tpm2_key_protector_init: Initializes the state of the TPM2 key protector for
later usage, clearing any previous state, too, if
any.
- tpm2_key_protector_clear: Clears any state set by tpm2_key_protector_init.
The way this is expected to be used requires the user to, either interactively
or, normally, via a boot script, initialize (i.e., configure) the key protector
and then specify that it be used by the cryptomount command (modifications to
this command are in a different patch).
For instance:
tpm2_key_protector_init --keyfile=KEYFILE1
cryptomount DISK1 -k tpm2
tpm2_key_protector_init --keyfile=KEYFILE2 --pcrs=7,11
cryptomount DISK2 -k tpm2
If a user does not initialize the key protector and attempts to use it anyway,
the protector returns an error.
Signed-off-by: Hernan Gatta <hegatta@linux.microsoft.com>
---
grub-core/Makefile.core.def | 10 +
grub-core/tpm2/args.c | 129 ++++++
grub-core/tpm2/module.c | 710 ++++++++++++++++++++++++++++++
include/grub/tpm2/internal/args.h | 39 ++
4 files changed, 888 insertions(+)
create mode 100644 grub-core/tpm2/args.c
create mode 100644 grub-core/tpm2/module.c
create mode 100644 include/grub/tpm2/internal/args.h
diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
index b0001a33cf..850cee2b13 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -2561,6 +2561,16 @@ module = {
enable = efi;
};
+module = {
+ name = tpm2;
+ common = tpm2/args.c;
+ common = tpm2/buffer.c;
+ common = tpm2/module.c;
+ common = tpm2/mu.c;
+ common = tpm2/tpm2.c;
+ efi = tpm2/tcg2.c;
+};
+
module = {
name = tr;
common = commands/tr.c;
diff --git a/grub-core/tpm2/args.c b/grub-core/tpm2/args.c
new file mode 100644
index 0000000000..90c7cd8991
--- /dev/null
+++ b/grub-core/tpm2/args.c
@@ -0,0 +1,129 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2022 Microsoft Corporation
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/err.h>
+#include <grub/mm.h>
+#include <grub/misc.h>
+#include <grub/tpm2/internal/args.h>
+
+grub_err_t
+grub_tpm2_protector_parse_pcrs (char *value, grub_uint8_t *pcrs,
+ grub_uint8_t *pcr_count)
+{
+ char *current_pcr = value;
+ char *next_pcr;
+ unsigned long pcr;
+ grub_uint8_t i;
+
+ if (grub_strlen (value) == 0)
+ return GRUB_ERR_BAD_ARGUMENT;
+
+ *pcr_count = 0;
+ for (i = 0; i < TPM_MAX_PCRS; i++)
+ {
+ next_pcr = grub_strchr (current_pcr, ',');
+ if (next_pcr == current_pcr)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT,
+ N_("Empty entry in PCR list"));
+ if (next_pcr)
+ *next_pcr = '\0';
+
+ grub_errno = GRUB_ERR_NONE;
+ pcr = grub_strtoul (current_pcr, NULL, 10);
+ if (grub_errno != GRUB_ERR_NONE)
+ return grub_error (grub_errno,
+ N_("Entry '%s' in PCR list is not a number"),
+ current_pcr);
+
+ if (pcr > TPM_MAX_PCRS)
+ return grub_error (GRUB_ERR_OUT_OF_RANGE,
+ N_("Entry %lu in PCR list is too large to be a PCR "
+ "number, PCR numbers range from 0 to %u"),
+ pcr, TPM_MAX_PCRS);
+
+ pcrs[i] = (grub_uint8_t)pcr;
+ *pcr_count += 1;
+
+ if (!next_pcr)
+ break;
+
+ current_pcr = next_pcr + 1;
+ if (*current_pcr == '\0')
+ return grub_error (GRUB_ERR_BAD_ARGUMENT,
+ N_("Trailing comma at the end of PCR list"));
+ }
+
+ if (i == TPM_MAX_PCRS)
+ return grub_error (GRUB_ERR_OUT_OF_RANGE,
+ N_("Too many PCRs in PCR list, the maximum number of "
+ "PCRs is %u"), TPM_MAX_PCRS);
+
+ return GRUB_ERR_NONE;
+}
+
+grub_err_t
+grub_tpm2_protector_parse_asymmetric (const char *value, TPM_ALG_ID *asymmetric)
+{
+ if (grub_strcasecmp (value, "ECC") == 0)
+ *asymmetric = TPM_ALG_ECC;
+ else if (grub_strcasecmp (value, "RSA") == 0)
+ *asymmetric = TPM_ALG_RSA;
+ else
+ return grub_error (GRUB_ERR_OUT_OF_RANGE,
+ N_("Value '%s' is not a valid asymmetric key type"),
+ value);
+
+ return GRUB_ERR_NONE;
+}
+
+grub_err_t
+grub_tpm2_protector_parse_bank (const char *value, TPM_ALG_ID *bank)
+{
+ if (grub_strcasecmp (value, "SHA1") == 0)
+ *bank = TPM_ALG_SHA1;
+ else if (grub_strcasecmp (value, "SHA256") == 0)
+ *bank = TPM_ALG_SHA256;
+ else if (grub_strcasecmp (value, "SHA384") == 0)
+ *bank = TPM_ALG_SHA384;
+ else
+ return grub_error (GRUB_ERR_OUT_OF_RANGE,
+ N_("Value '%s' is not a valid PCR bank"), value);
+
+ return GRUB_ERR_NONE;
+}
+
+grub_err_t
+grub_tpm2_protector_parse_tpm_handle (const char *value, TPM_HANDLE *handle)
+{
+ unsigned long num;
+
+ grub_errno = GRUB_ERR_NONE;
+ num = grub_strtoul (value, NULL, 0);
+ if (grub_errno != GRUB_ERR_NONE)
+ return grub_error (grub_errno, N_("TPM handle value '%s' is not a number"),
+ value);
+
+ if (num > GRUB_UINT_MAX)
+ return grub_error (GRUB_ERR_OUT_OF_RANGE,
+ N_("Value %lu is too large to be a TPM handle, TPM "
+ "handles are unsigned 32-bit integers"), num);
+
+ *handle = (TPM_HANDLE)num;
+
+ return GRUB_ERR_NONE;
+}
diff --git a/grub-core/tpm2/module.c b/grub-core/tpm2/module.c
new file mode 100644
index 0000000000..3f2f386f7e
--- /dev/null
+++ b/grub-core/tpm2/module.c
@@ -0,0 +1,710 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2022 Microsoft Corporation
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/dl.h>
+#include <grub/extcmd.h>
+#include <grub/file.h>
+#include <grub/misc.h>
+#include <grub/mm.h>
+#include <grub/protector.h>
+#include <grub/tpm2/buffer.h>
+#include <grub/tpm2/internal/args.h>
+#include <grub/tpm2/mu.h>
+#include <grub/tpm2/tpm2.h>
+
+GRUB_MOD_LICENSE ("GPLv3+");
+
+typedef enum grub_tpm2_protector_mode
+{
+ GRUB_TPM2_PROTECTOR_MODE_UNSET,
+ GRUB_TPM2_PROTECTOR_MODE_SRK,
+ GRUB_TPM2_PROTECTOR_MODE_NV
+} grub_tpm2_protector_mode_t;
+
+struct grub_tpm2_protector_context
+{
+ grub_tpm2_protector_mode_t mode;
+ grub_uint8_t pcrs[TPM_MAX_PCRS];
+ grub_uint8_t pcr_count;
+ TPM_ALG_ID asymmetric;
+ TPM_ALG_ID bank;
+ const char *keyfile;
+ TPM_HANDLE srk;
+ TPM_HANDLE nv;
+};
+
+static const struct grub_arg_option grub_tpm2_protector_init_cmd_options[] =
+ {
+ /* Options for all modes */
+ {
+ .longarg = "mode",
+ .shortarg = 'm',
+ .flags = 0,
+ .arg = NULL,
+ .type = ARG_TYPE_STRING,
+ .doc =
+ N_("Unseal key using SRK ('srk') (default) or retrieve it from an NV "
+ "Index ('nv')."),
+ },
+ {
+ .longarg = "pcrs",
+ .shortarg = 'p',
+ .flags = 0,
+ .arg = NULL,
+ .type = ARG_TYPE_STRING,
+ .doc =
+ N_("Comma-separated list of PCRs used to authorize key release "
+ "(e.g., '7,11', default is 7."),
+ },
+ {
+ .longarg = "bank",
+ .shortarg = 'b',
+ .flags = 0,
+ .arg = NULL,
+ .type = ARG_TYPE_STRING,
+ .doc =
+ N_("Bank of PCRs used to authorize key release: "
+ "SHA1, SHA256 (default), or SHA384."),
+ },
+ /* SRK-mode options */
+ {
+ .longarg = "keyfile",
+ .shortarg = 'k',
+ .flags = 0,
+ .arg = NULL,
+ .type = ARG_TYPE_STRING,
+ .doc =
+ N_("Required in SRK mode, path to the sealed key file to unseal using "
+ "the TPM (e.g., (hd0,gpt1)/boot/grub2/sealed_key)."),
+ },
+ {
+ .longarg = "srk",
+ .shortarg = 's',
+ .flags = 0,
+ .arg = NULL,
+ .type = ARG_TYPE_STRING,
+ .doc =
+ N_("In SRK mode, the SRK handle if the SRK is persistent "
+ "(default is 0x81000001)."),
+ },
+ {
+ .longarg = "asymmetric",
+ .shortarg = 'a',
+ .flags = 0,
+ .arg = NULL,
+ .type = ARG_TYPE_STRING,
+ .doc =
+ N_("In SRK mode, the type of SRK: RSA (default) or ECC."),
+ },
+ /* NV Index-mode options */
+ {
+ .longarg = "nvindex",
+ .shortarg = 'n',
+ .flags = 0,
+ .arg = NULL,
+ .type = ARG_TYPE_STRING,
+ .doc =
+ N_("Required in NV Index mode, the NV handle to read which must "
+ "readily exist on the TPM and which contains the key."),
+ },
+ /* End of list */
+ {0, 0, 0, 0, 0, 0}
+ };
+
+static grub_extcmd_t grub_tpm2_protector_init_cmd;
+static grub_extcmd_t grub_tpm2_protector_clear_cmd;
+static struct grub_tpm2_protector_context grub_tpm2_protector_ctx = { 0 };
+
+static grub_err_t
+grub_tpm2_protector_srk_read_keyfile (const char *filepath, void **buffer,
+ grub_size_t *buffer_size)
+{
+ grub_file_t sealed_key_file;
+ grub_off_t sealed_key_size;
+ void *sealed_key_buffer;
+ grub_off_t sealed_key_read;
+
+ sealed_key_file = grub_file_open (filepath, GRUB_FILE_TYPE_NONE);
+ if (!sealed_key_file)
+ {
+ grub_dprintf ("tpm2", "Could not open sealed key file.\n");
+ /* grub_file_open sets grub_errno on error, and if we do no unset it,
+ * future calls to grub_file_open will fail (and so will anybody up the
+ * stack who checks the value, if any). */
+ grub_errno = GRUB_ERR_NONE;
+ return GRUB_ERR_FILE_NOT_FOUND;
+ }
+
+ sealed_key_size = grub_file_size (sealed_key_file);
+ if (!sealed_key_size)
+ {
+ grub_dprintf ("tpm2", "Could not read sealed key file size.\n");
+ grub_file_close (sealed_key_file);
+ return GRUB_ERR_OUT_OF_RANGE;
+ }
+
+ sealed_key_buffer = grub_malloc (sealed_key_size);
+ if (!sealed_key_buffer)
+ {
+ grub_dprintf ("tpm2", "Could not allocate buffer for sealed key.\n");
+ grub_file_close (sealed_key_file);
+ return GRUB_ERR_OUT_OF_MEMORY;
+ }
+
+ sealed_key_read = grub_file_read (sealed_key_file, sealed_key_buffer,
+ sealed_key_size);
+ if (sealed_key_read != sealed_key_size)
+ {
+ grub_dprintf ("tpm2", "Could not retrieve sealed key file contents.\n");
+ grub_free (sealed_key_buffer);
+ grub_file_close (sealed_key_file);
+ return GRUB_ERR_FILE_READ_ERROR;
+ }
+
+ grub_file_close (sealed_key_file);
+
+ *buffer = sealed_key_buffer;
+ *buffer_size = sealed_key_size;
+
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_tpm2_protector_srk_unmarshal_keyfile (void *sealed_key,
+ grub_size_t sealed_key_size,
+ TPM2_SEALED_KEY *sk)
+{
+ struct grub_tpm2_buffer buf;
+
+ grub_tpm2_buffer_init (&buf);
+ if (sealed_key_size > buf.cap)
+ {
+ grub_dprintf ("tpm2", "Sealed key file is larger than decode buffer "
+ "(%lu vs %lu bytes).\n", sealed_key_size, buf.cap);
+ return GRUB_ERR_BAD_ARGUMENT;
+ }
+
+ grub_memcpy (buf.data, sealed_key, sealed_key_size);
+ buf.size = sealed_key_size;
+
+ grub_tpm2_mu_TPM2B_PUBLIC_Unmarshal (&buf, &sk->public);
+ grub_tpm2_mu_TPM2B_Unmarshal (&buf, (TPM2B *)&sk->private);
+
+ if (buf.error)
+ {
+ grub_dprintf ("tpm2", "Could not unmarshal sealed key file, it is likely "
+ "malformed.\n");
+ return GRUB_ERR_BAD_ARGUMENT;
+ }
+
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_tpm2_protector_srk_get (const struct grub_tpm2_protector_context *ctx,
+ TPM_HANDLE *srk)
+{
+ TPM_RC rc;
+ TPM2B_PUBLIC public;
+ TPMS_AUTH_COMMAND authCommand = { 0 };
+ TPM2B_SENSITIVE_CREATE inSensitive = { 0 };
+ TPM2B_PUBLIC inPublic = { 0 };
+ TPM2B_DATA outsideInfo = { 0 };
+ TPML_PCR_SELECTION creationPcr = { 0 };
+ TPM2B_PUBLIC outPublic = { 0 };
+ TPM2B_CREATION_DATA creationData = { 0 };
+ TPM2B_DIGEST creationHash = { 0 };
+ TPMT_TK_CREATION creationTicket = { 0 };
+ TPM2B_NAME srkName = { 0 };
+ TPM_HANDLE srkHandle;
+
+ /* Find SRK */
+ rc = TPM2_ReadPublic (ctx->srk, NULL, &public);
+ if (rc == TPM_RC_SUCCESS)
+ {
+ *srk = ctx->srk;
+ return GRUB_ERR_NONE;
+ }
+
+ /* The handle exists but its public area could not be read. */
+ if ((rc & ~TPM_RC_N_MASK) != TPM_RC_HANDLE)
+ {
+ grub_dprintf ("tpm2", "The SRK handle (0x%x) exists on the TPM but its "
+ "public area could not be read (TPM2_ReadPublic "
+ "failed with TSS/TPM error %u).\n", ctx->srk, rc);
+ return GRUB_ERR_BAD_DEVICE;
+ }
+
+ /* Create SRK */
+ authCommand.sessionHandle = TPM_RS_PW;
+ inPublic.publicArea.type = ctx->asymmetric;
+ inPublic.publicArea.nameAlg = TPM_ALG_SHA256;
+ inPublic.publicArea.objectAttributes.restricted = 1;
+ inPublic.publicArea.objectAttributes.userWithAuth = 1;
+ inPublic.publicArea.objectAttributes.decrypt = 1;
+ inPublic.publicArea.objectAttributes.fixedTPM = 1;
+ inPublic.publicArea.objectAttributes.fixedParent = 1;
+ inPublic.publicArea.objectAttributes.sensitiveDataOrigin = 1;
+ inPublic.publicArea.objectAttributes.noDA = 1;
+
+ if (ctx->asymmetric == TPM_ALG_RSA)
+ {
+ inPublic.publicArea.parameters.rsaDetail.symmetric.algorithm = TPM_ALG_AES;
+ inPublic.publicArea.parameters.rsaDetail.symmetric.keyBits.aes = 128;
+ inPublic.publicArea.parameters.rsaDetail.symmetric.mode.aes = TPM_ALG_CFB;
+ inPublic.publicArea.parameters.rsaDetail.scheme.scheme = TPM_ALG_NULL;
+ inPublic.publicArea.parameters.rsaDetail.keyBits = 2048;
+ inPublic.publicArea.parameters.rsaDetail.exponent = 0;
+ }
+ else if (ctx->asymmetric == TPM_ALG_ECC)
+ {
+ inPublic.publicArea.parameters.eccDetail.symmetric.algorithm = TPM_ALG_AES;
+ inPublic.publicArea.parameters.eccDetail.symmetric.keyBits.aes = 128;
+ inPublic.publicArea.parameters.eccDetail.symmetric.mode.aes = TPM_ALG_CFB;
+ inPublic.publicArea.parameters.eccDetail.scheme.scheme = TPM_ALG_NULL;
+ inPublic.publicArea.parameters.eccDetail.curveID = TPM_ECC_NIST_P256;
+ inPublic.publicArea.parameters.eccDetail.kdf.scheme = TPM_ALG_NULL;
+ }
+ else
+ return GRUB_ERR_BAD_ARGUMENT;
+
+ rc = TPM2_CreatePrimary (TPM_RH_OWNER, &authCommand, &inSensitive, &inPublic,
+ &outsideInfo, &creationPcr, &srkHandle, &outPublic,
+ &creationData, &creationHash, &creationTicket,
+ &srkName, NULL);
+ if (rc != TPM_RC_SUCCESS)
+ {
+ grub_dprintf ("tpm2", "Could not create SRK (TPM2_CreatePrimary failed "
+ "with TSS/TPM error %u).\n", rc);
+ return GRUB_ERR_BAD_DEVICE;
+ }
+
+ *srk = srkHandle;
+
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_tpm2_protector_srk_recover (const struct grub_tpm2_protector_context *ctx,
+ grub_uint8_t **key, grub_size_t *key_size)
+{
+ TPM_RC rc;
+ TPM2_SEALED_KEY sealed_key;
+ void *sealed_key_bytes;
+ grub_size_t sealed_key_size;
+ TPM_HANDLE srk_handle;
+ TPM2B_NONCE nonceCaller = { 0 };
+ TPM2B_ENCRYPTED_SECRET salt = { 0 };
+ TPMT_SYM_DEF symmetric = { 0 };
+ TPM2B_NONCE nonceTPM = { 0 };
+ TPMI_SH_AUTH_SESSION session;
+ TPML_PCR_SELECTION pcrSel = {
+ .count = 1,
+ .pcrSelections = {
+ {
+ .hash = ctx->bank,
+ .sizeOfSelect = 3,
+ .pcrSelect = { 0 }
+ },
+ }
+ };
+ TPMS_AUTH_COMMAND authCmd = { 0 };
+ TPM_HANDLE sealed_key_handle;
+ TPM2B_NAME name;
+ TPMS_AUTH_RESPONSE authResponse;
+ TPM2B_SENSITIVE_DATA data;
+ grub_uint8_t *key_out;
+ grub_uint8_t i;
+ grub_err_t err;
+
+ /* Retrieve Sealed Key */
+ err = grub_tpm2_protector_srk_read_keyfile (ctx->keyfile, &sealed_key_bytes,
+ &sealed_key_size);
+ if (err)
+ return grub_error (err, N_("Failed to read key file %s"), ctx->keyfile);
+
+ err = grub_tpm2_protector_srk_unmarshal_keyfile (sealed_key_bytes,
+ sealed_key_size,
+ &sealed_key);
+ if (err)
+ {
+ grub_error (err, N_("Failed to unmarshal key, ensure the key file is in "
+ "TPM wire format"));
+ goto exit1;
+ }
+
+ /* Get SRK */
+ err = grub_tpm2_protector_srk_get (ctx, &srk_handle);
+ if (err)
+ {
+ grub_error (err, N_("Failed to retrieve the SRK"));
+ goto exit1;
+ }
+
+ err = GRUB_ERR_BAD_DEVICE;
+
+ /* Start Auth Session */
+ nonceCaller.size = TPM_SHA256_DIGEST_SIZE;
+ symmetric.algorithm = TPM_ALG_NULL;
+
+ rc = TPM2_StartAuthSession (TPM_RH_NULL, TPM_RH_NULL, 0, &nonceCaller, &salt,
+ TPM_SE_POLICY, &symmetric, TPM_ALG_SHA256,
+ &session, &nonceTPM, 0);
+ if (rc)
+ {
+ grub_error (err, N_("Failed to start auth session (TPM2_StartAuthSession "
+ "failed with TSS/TPM error %u)"), rc);
+ goto exit2;
+ }
+
+ /* Policy PCR */
+ for (i = 0; i < ctx->pcr_count; i++)
+ pcrSel
+ .pcrSelections[0]
+ .pcrSelect[TPM2_PCR_TO_SELECT(ctx->pcrs[i])]
+ |= TPM2_PCR_TO_BIT(ctx->pcrs[i]);
+
+ rc = TPM2_PolicyPCR (session, NULL, NULL, &pcrSel, NULL);
+ if (rc)
+ {
+ grub_error (err, N_("Failed to submit PCR policy (TPM2_PolicyPCR failed "
+ "with TSS/TPM error %u)"), rc);
+ goto exit3;
+ }
+
+ /* Load Sealed Key */
+ authCmd.sessionHandle = TPM_RS_PW;
+ rc = TPM2_Load (srk_handle, &authCmd, &sealed_key.private, &sealed_key.public,
+ &sealed_key_handle, &name, &authResponse);
+ if (rc)
+ {
+ grub_error (err, N_("Failed to load sealed key (TPM2_Load failed with "
+ "TSS/TPM error %u)"), rc);
+ goto exit3;
+ }
+
+ /* Unseal Sealed Key */
+ authCmd.sessionHandle = session;
+ grub_memset (&authResponse, 0, sizeof (authResponse));
+
+ rc = TPM2_Unseal (sealed_key_handle, &authCmd, &data, &authResponse);
+ if (rc)
+ {
+ grub_error (err, N_("Failed to unseal sealed key (TPM2_Unseal failed "
+ "with TSS/TPM error %u)"), rc);
+ goto exit4;
+ }
+
+ /* Epilogue */
+ key_out = grub_malloc (data.size);
+ if (!key_out)
+ {
+ err = GRUB_ERR_OUT_OF_MEMORY;
+ grub_error (err, N_("No memory left to allocate unlock key buffer"));
+ goto exit4;
+ }
+
+ grub_memcpy (key_out, data.buffer, data.size);
+
+ *key = key_out;
+ *key_size = data.size;
+
+ err = GRUB_ERR_NONE;
+
+exit4:
+ TPM2_FlushContext (sealed_key_handle);
+
+exit3:
+ TPM2_FlushContext (session);
+
+exit2:
+ TPM2_FlushContext (srk_handle);
+
+exit1:
+ grub_free (sealed_key_bytes);
+ return err;
+}
+
+static grub_err_t
+grub_tpm2_protector_nv_recover (const struct grub_tpm2_protector_context *ctx,
+ grub_uint8_t **key, grub_size_t *key_size)
+{
+ (void)ctx;
+ (void)key;
+ (void)key_size;
+
+ return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
+ N_("NV Index mode is not implemented yet"));
+}
+
+static grub_err_t
+grub_tpm2_protector_recover (const struct grub_tpm2_protector_context *ctx,
+ grub_uint8_t **key, grub_size_t *key_size)
+{
+ switch (ctx->mode)
+ {
+ case GRUB_TPM2_PROTECTOR_MODE_SRK:
+ return grub_tpm2_protector_srk_recover (ctx, key, key_size);
+ case GRUB_TPM2_PROTECTOR_MODE_NV:
+ return grub_tpm2_protector_nv_recover (ctx, key, key_size);
+ default:
+ return GRUB_ERR_BAD_ARGUMENT;
+ }
+}
+
+static grub_err_t
+grub_tpm2_protector_recover_key (grub_uint8_t **key, grub_size_t *key_size)
+{
+ grub_err_t err;
+
+ /* Expect a call to tpm2_protector_init before anybody tries to use us */
+ if (grub_tpm2_protector_ctx.mode == GRUB_TPM2_PROTECTOR_MODE_UNSET)
+ return grub_error (GRUB_ERR_INVALID_COMMAND,
+ N_("Cannot use TPM2 key protector without initializing "
+ "it, call tpm2_protector_init first"));
+
+ if (!key)
+ return GRUB_ERR_BAD_ARGUMENT;
+
+ err = grub_tpm2_protector_recover (&grub_tpm2_protector_ctx, key, key_size);
+ if (err)
+ return err;
+
+ return GRUB_ERR_NONE;
+}
+
+
+static grub_err_t
+grub_tpm2_protector_check_args (struct grub_tpm2_protector_context *ctx)
+{
+ if (ctx->mode == GRUB_TPM2_PROTECTOR_MODE_UNSET)
+ ctx->mode = GRUB_TPM2_PROTECTOR_MODE_SRK;
+
+ /* Checks for SRK mode */
+ if (ctx->mode == GRUB_TPM2_PROTECTOR_MODE_SRK && !ctx->keyfile)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT,
+ N_("In SRK mode, a key file must be specified: "
+ "--keyfile or -k"));
+
+ if (ctx->mode == GRUB_TPM2_PROTECTOR_MODE_SRK && ctx->nv)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT,
+ N_("In SRK mode, an NV Index cannot be specified"));
+
+ /* Checks for NV mode */
+ if (ctx->mode == GRUB_TPM2_PROTECTOR_MODE_NV && !ctx->nv)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT,
+ N_("In NV Index mode, an NV Index must be specified: "
+ "--nvindex or -n"));
+
+ if (ctx->mode == GRUB_TPM2_PROTECTOR_MODE_NV && ctx->keyfile)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT,
+ N_("In NV Index mode, a keyfile cannot be specified"));
+
+ if (ctx->mode == GRUB_TPM2_PROTECTOR_MODE_NV && ctx->srk)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT,
+ N_("In NV Index mode, an SRK cannot be specified"));
+
+ if (ctx->mode == GRUB_TPM2_PROTECTOR_MODE_NV && ctx->asymmetric)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT,
+ N_("In NV Index mode, an asymmetric key type cannot be "
+ "specified"));
+
+ /* Defaults assignment */
+ if (!ctx->bank)
+ ctx->bank = TPM_ALG_SHA256;
+
+ if (!ctx->pcr_count)
+ {
+ ctx->pcrs[0] = 7;
+ ctx->pcr_count = 1;
+ }
+
+ if (ctx->mode == GRUB_TPM2_PROTECTOR_MODE_SRK)
+ {
+ if (!ctx->srk)
+ ctx->srk = TPM2_SRK_HANDLE;
+
+ if (!ctx->asymmetric)
+ ctx->asymmetric = TPM_ALG_RSA;
+ }
+
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_tpm2_protector_parse_keyfile (const char *value, const char **keyfile)
+{
+ if (grub_strlen (value) == 0)
+ return GRUB_ERR_BAD_ARGUMENT;
+
+ *keyfile = grub_strdup (value);
+ if (!*keyfile)
+ return grub_error (GRUB_ERR_OUT_OF_MEMORY,
+ N_("No memory to duplicate keyfile path"));
+
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_tpm2_protector_parse_mode (const char *value,
+ grub_tpm2_protector_mode_t *mode)
+{
+ if (grub_strcmp (value, "srk") == 0)
+ *mode = GRUB_TPM2_PROTECTOR_MODE_SRK;
+ else if (grub_strcmp (value, "nv") == 0)
+ *mode = GRUB_TPM2_PROTECTOR_MODE_NV;
+ else
+ return grub_error (GRUB_ERR_OUT_OF_RANGE,
+ N_("Value '%s' is not a valid TPM2 key protector mode"),
+ value);
+
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_tpm2_protector_init_cmd_handler (grub_extcmd_context_t ctxt, int argc,
+ char **args __attribute__ ((unused)))
+{
+ struct grub_arg_list *state = ctxt->state;
+ grub_err_t err;
+
+ if (argc)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT,
+ N_("The TPM2 key protector does not accept any "
+ "non-option arguments (i.e., like -o and/or --option "
+ "only)"));
+
+ grub_free ((void *) grub_tpm2_protector_ctx.keyfile);
+ grub_memset (&grub_tpm2_protector_ctx, 0, sizeof (grub_tpm2_protector_ctx));
+
+ if (state[0].set) /* mode */
+ {
+ err = grub_tpm2_protector_parse_mode (state[0].arg,
+ &grub_tpm2_protector_ctx.mode);
+ if (err)
+ return err;
+ }
+
+ if (state[1].set) /* pcrs */
+ {
+ err = grub_tpm2_protector_parse_pcrs (state[1].arg,
+ grub_tpm2_protector_ctx.pcrs,
+ &grub_tpm2_protector_ctx.pcr_count);
+ if (err)
+ return err;
+ }
+
+ if (state[2].set) /* bank */
+ {
+ err = grub_tpm2_protector_parse_bank (state[2].arg,
+ &grub_tpm2_protector_ctx.bank);
+ if (err)
+ return err;
+ }
+
+ if (state[3].set) /* keyfile */
+ {
+ err = grub_tpm2_protector_parse_keyfile (state[3].arg,
+ &grub_tpm2_protector_ctx.keyfile);
+ if (err)
+ return err;
+ }
+
+ if (state[4].set) /* srk */
+ {
+ err = grub_tpm2_protector_parse_tpm_handle (state[4].arg,
+ &grub_tpm2_protector_ctx.srk);
+ if (err)
+ return err;
+ }
+
+ if (state[5].set) /* asymmetric */
+ {
+ err = grub_tpm2_protector_parse_asymmetric (state[5].arg,
+ &grub_tpm2_protector_ctx.asymmetric);
+ if (err)
+ return err;
+ }
+
+ if (state[6].set) /* nvindex */
+ {
+ err = grub_tpm2_protector_parse_tpm_handle (state[6].arg,
+ &grub_tpm2_protector_ctx.nv);
+ if (err)
+ return err;
+ }
+
+ err = grub_tpm2_protector_check_args (&grub_tpm2_protector_ctx);
+
+ /* This command only initializes the protector, so nothing else to do. */
+
+ return err;
+}
+
+static grub_err_t
+grub_tpm2_protector_clear_cmd_handler (grub_extcmd_context_t ctxt __attribute__ ((unused)),
+ int argc,
+ char **args __attribute__ ((unused)))
+{
+ if (argc)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT,
+ N_("tpm2_key_protector_clear accepts no arguments"));
+
+ grub_free ((void *) grub_tpm2_protector_ctx.keyfile);
+ grub_memset (&grub_tpm2_protector_ctx, 0, sizeof (grub_tpm2_protector_ctx));
+
+ return GRUB_ERR_NONE;
+}
+
+static struct grub_key_protector grub_tpm2_key_protector =
+ {
+ .name = "tpm2",
+ .recover_key = grub_tpm2_protector_recover_key
+ };
+
+GRUB_MOD_INIT (tpm2)
+{
+ grub_tpm2_protector_init_cmd =
+ grub_register_extcmd ("tpm2_key_protector_init",
+ grub_tpm2_protector_init_cmd_handler, 0,
+ N_("[-m mode] "
+ "[-p pcr_list] "
+ "[-b pcr_bank] "
+ "[-k sealed_key_file_path] "
+ "[-s srk_handle] "
+ "[-a asymmetric_key_type] "
+ "[-n nv_index]"),
+ N_("Initialize the TPM2 key protector."),
+ grub_tpm2_protector_init_cmd_options);
+ grub_tpm2_protector_clear_cmd =
+ grub_register_extcmd ("tpm2_key_protector_clear",
+ grub_tpm2_protector_clear_cmd_handler, 0, NULL,
+ N_("Clear the TPM2 key protector if previously initialized."),
+ NULL);
+ grub_key_protector_register (&grub_tpm2_key_protector);
+}
+
+GRUB_MOD_FINI (tpm2)
+{
+ grub_free ((void *) grub_tpm2_protector_ctx.keyfile);
+ grub_memset (&grub_tpm2_protector_ctx, 0, sizeof (grub_tpm2_protector_ctx));
+
+ grub_key_protector_unregister (&grub_tpm2_key_protector);
+ grub_unregister_extcmd (grub_tpm2_protector_clear_cmd);
+ grub_unregister_extcmd (grub_tpm2_protector_init_cmd);
+}
diff --git a/include/grub/tpm2/internal/args.h b/include/grub/tpm2/internal/args.h
new file mode 100644
index 0000000000..6341fce1c5
--- /dev/null
+++ b/include/grub/tpm2/internal/args.h
@@ -0,0 +1,39 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2022 Microsoft Corporation
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_TPM2_INTERNAL_ARGS_HEADER
+#define GRUB_TPM2_INTERNAL_ARGS_HEADER 1
+
+#include <grub/err.h>
+#include <grub/tpm2/tpm2.h>
+
+grub_err_t
+grub_tpm2_protector_parse_pcrs (char *value, grub_uint8_t *pcrs,
+ grub_uint8_t *pcr_count);
+
+grub_err_t
+grub_tpm2_protector_parse_asymmetric (const char *value,
+ TPM_ALG_ID *asymmetric);
+
+grub_err_t
+grub_tpm2_protector_parse_bank (const char *value, TPM_ALG_ID *bank);
+
+grub_err_t
+grub_tpm2_protector_parse_tpm_handle (const char *value, TPM_HANDLE *handle);
+
+#endif /* ! GRUB_TPM2_INTERNAL_ARGS_HEADER */
--
2.34.1

View File

@ -1,336 +0,0 @@
From 9888bf40d960339a59dc18fb6e1df5f65b4668e3 Mon Sep 17 00:00:00 2001
From: Hernan Gatta <hegatta@linux.microsoft.com>
Date: Tue, 1 Feb 2022 05:02:56 -0800
Subject: [PATCH 13/14] cryptodisk: Support key protectors
Add a new parameter to cryptomount to support the key protectors framework: -k.
The parameter is used to automatically retrieve a key from specified key
protectors. The parameter may be repeated to specify any number of key
protectors. These are tried in order until one provides a usable key for any
given disk.
Signed-off-by: <Hernan Gatta hegatta@linux.microsoft.com>
---
Makefile.util.def | 1 +
grub-core/disk/cryptodisk.c | 166 +++++++++++++++++++++++++++++-------
include/grub/cryptodisk.h | 14 +++
3 files changed, 151 insertions(+), 30 deletions(-)
diff --git a/Makefile.util.def b/Makefile.util.def
index ef5c818e0e..b3ec2a4bb6 100644
--- a/Makefile.util.def
+++ b/Makefile.util.def
@@ -35,6 +35,7 @@ library = {
common = grub-core/kern/list.c;
common = grub-core/kern/misc.c;
common = grub-core/kern/partition.c;
+ common = grub-core/kern/protectors.c;
common = grub-core/lib/crypto.c;
common = grub-core/lib/json/json.c;
common = grub-core/disk/luks.c;
diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
index 497097394f..00c44773fb 100644
--- a/grub-core/disk/cryptodisk.c
+++ b/grub-core/disk/cryptodisk.c
@@ -26,6 +26,7 @@
#include <grub/file.h>
#include <grub/procfs.h>
#include <grub/partition.h>
+#include <grub/protector.h>
#ifdef GRUB_UTIL
#include <grub/emu/hostdisk.h>
@@ -42,6 +43,8 @@ static const struct grub_arg_option options[] =
{"all", 'a', 0, N_("Mount all."), 0, 0},
{"boot", 'b', 0, N_("Mount all volumes with `boot' flag set."), 0, 0},
{"password", 'p', 0, N_("Password to open volumes."), 0, ARG_TYPE_STRING},
+ {"protector", 'k', GRUB_ARG_OPTION_REPEATABLE,
+ N_("Unlock volume(s) using key protector(s)."), 0, ARG_TYPE_STRING},
{0, 0, 0, 0, 0, 0}
};
@@ -1000,7 +1003,8 @@ grub_cryptodisk_scan_device_real (const char *name,
{
grub_err_t ret = GRUB_ERR_NONE;
grub_cryptodisk_t dev;
- grub_cryptodisk_dev_t cr;
+ grub_cryptodisk_dev_t cr, crd = NULL;
+ int i;
int askpass = 0;
char *part = NULL;
@@ -1016,39 +1020,108 @@ grub_cryptodisk_scan_device_real (const char *name,
return NULL;
if (!dev)
continue;
+ crd = cr;
+ }
- if (!cargs->key_len)
- {
- /* Get the passphrase from the user, if no key data. */
- askpass = 1;
- part = grub_partition_get_name (source->partition);
- grub_printf_ (N_("Enter passphrase for %s%s%s (%s): "), source->name,
- source->partition != NULL ? "," : "",
- part != NULL ? part : N_("UNKNOWN"),
- dev->uuid);
- grub_free (part);
-
- cargs->key_data = grub_malloc (GRUB_CRYPTODISK_MAX_PASSPHRASE);
- if (cargs->key_data == NULL)
- return NULL;
-
- if (!grub_password_get ((char *) cargs->key_data, GRUB_CRYPTODISK_MAX_PASSPHRASE))
- {
- grub_error (GRUB_ERR_BAD_ARGUMENT, "passphrase not supplied");
- goto error;
- }
- cargs->key_len = grub_strlen ((char *) cargs->key_data);
- }
+ if (!dev)
+ {
+ grub_error (GRUB_ERR_BAD_MODULE,
+ "no cryptodisk module can handle this device");
+ return NULL;
+ }
- ret = cr->recover_key (source, dev, cargs);
- if (ret != GRUB_ERR_NONE)
+ if (cargs->protectors)
+ {
+ for (i = 0; cargs->protectors[i]; i++)
+ {
+ if (cargs->key_cache[i].invalid)
+ continue;
+
+ if (!cargs->key_cache[i].key)
+ {
+ ret = grub_key_protector_recover_key (cargs->protectors[i],
+ &cargs->key_cache[i].key,
+ &cargs->key_cache[i].key_len);
+ if (ret)
+ {
+ if (grub_errno)
+ {
+ grub_print_error ();
+ grub_errno = GRUB_ERR_NONE;
+ }
+
+ grub_dprintf ("cryptodisk",
+ "failed to recover a key from key protector "
+ "%s, will not try it again for any other "
+ "disks, if any, during this invocation of "
+ "cryptomount\n",
+ cargs->protectors[i]);
+
+ cargs->key_cache[i].invalid = 1;
+ continue;
+ }
+ }
+
+ cargs->key_data = cargs->key_cache[i].key;
+ cargs->key_len = cargs->key_cache[i].key_len;
+
+ ret = crd->recover_key (source, dev, cargs);
+ if (ret)
+ {
+ part = grub_partition_get_name (source->partition);
+ grub_dprintf ("cryptodisk",
+ "recovered a key from key protector %s but it "
+ "failed to unlock %s%s%s (%s)\n",
+ cargs->protectors[i], source->name,
+ source->partition != NULL ? "," : "",
+ part != NULL ? part : N_("UNKNOWN"), dev->uuid);
+ grub_free (part);
+ continue;
+ }
+ else
+ {
+ grub_cryptodisk_insert (dev, name, source);
+ goto cleanup;
+ };
+ }
+
+ part = grub_partition_get_name (source->partition);
+ grub_error (GRUB_ERR_ACCESS_DENIED,
+ N_("no key protector provided a usable key for %s%s%s (%s)"),
+ source->name, source->partition != NULL ? "," : "",
+ part != NULL ? part : N_("UNKNOWN"), dev->uuid);
+ grub_free (part);
goto error;
+ }
- grub_cryptodisk_insert (dev, name, source);
+ if (!cargs->key_len)
+ {
+ /* Get the passphrase from the user, if no key data. */
+ askpass = 1;
+ part = grub_partition_get_name (source->partition);
+ grub_printf_ (N_("Enter passphrase for %s%s%s (%s): "), source->name,
+ source->partition != NULL ? "," : "",
+ part != NULL ? part : N_("UNKNOWN"), dev->uuid);
+ grub_free (part);
+
+ cargs->key_data = grub_malloc (GRUB_CRYPTODISK_MAX_PASSPHRASE);
+ if (cargs->key_data == NULL)
+ goto error;
+
+ if (!grub_password_get ((char *) cargs->key_data, GRUB_CRYPTODISK_MAX_PASSPHRASE))
+ {
+ grub_error (GRUB_ERR_BAD_ARGUMENT, "passphrase not supplied");
+ goto error;
+ }
+ cargs->key_len = grub_strlen ((char *) cargs->key_data);
+ }
+
+ ret = crd->recover_key (source, dev, cargs);
+ if (ret != GRUB_ERR_NONE)
+ goto error;
+
+ grub_cryptodisk_insert (dev, name, source);
- goto cleanup;
- }
- grub_error (GRUB_ERR_BAD_MODULE, "no cryptodisk module can handle this device");
goto cleanup;
error:
@@ -1155,6 +1228,20 @@ grub_cryptodisk_scan_device (const char *name,
return ret;
}
+static void
+grub_cryptodisk_clear_key_cache (struct grub_cryptomount_args *cargs)
+{
+ int i;
+
+ if (!cargs->key_cache)
+ return;
+
+ for (i = 0; cargs->protectors[i]; i++)
+ grub_free (cargs->key_cache[i].key);
+
+ grub_free (cargs->key_cache);
+}
+
static grub_err_t
grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args)
{
@@ -1167,12 +1254,25 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args)
if (grub_cryptodisk_list == NULL)
return grub_error (GRUB_ERR_BAD_MODULE, "no cryptodisk modules loaded");
+ if (state[3].set && state[4].set) /* password and key protector */
+ return grub_error (GRUB_ERR_BAD_ARGUMENT,
+ "a password and a key protector cannot both be set");
+
if (state[3].set) /* password */
{
cargs.key_data = (grub_uint8_t *) state[3].arg;
cargs.key_len = grub_strlen (state[3].arg);
}
+ if (state[4].set) /* key protector(s) */
+ {
+ cargs.key_cache = grub_zalloc (state[4].set * sizeof (*cargs.key_cache));
+ if (!cargs.key_cache)
+ return grub_error (GRUB_ERR_OUT_OF_MEMORY,
+ "no memory for key protector key cache");
+ cargs.protectors = state[4].args;
+ }
+
if (state[0].set) /* uuid */
{
int found_uuid;
@@ -1181,6 +1281,7 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args)
dev = grub_cryptodisk_get_by_uuid (args[0]);
if (dev)
{
+ grub_cryptodisk_clear_key_cache (&cargs);
grub_dprintf ("cryptodisk",
"already mounted as crypto%lu\n", dev->id);
return GRUB_ERR_NONE;
@@ -1189,6 +1290,7 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args)
cargs.check_boot = state[2].set;
cargs.search_uuid = args[0];
found_uuid = grub_device_iterate (&grub_cryptodisk_scan_device, &cargs);
+ grub_cryptodisk_clear_key_cache (&cargs);
if (found_uuid)
return GRUB_ERR_NONE;
@@ -1208,6 +1310,7 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args)
{
cargs.check_boot = state[2].set;
grub_device_iterate (&grub_cryptodisk_scan_device, &cargs);
+ grub_cryptodisk_clear_key_cache (&cargs);
return GRUB_ERR_NONE;
}
else
@@ -1231,6 +1334,7 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args)
disk = grub_disk_open (diskname);
if (!disk)
{
+ grub_cryptodisk_clear_key_cache (&cargs);
if (disklast)
*disklast = ')';
return grub_errno;
@@ -1241,12 +1345,14 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args)
{
grub_dprintf ("cryptodisk", "already mounted as crypto%lu\n", dev->id);
grub_disk_close (disk);
+ grub_cryptodisk_clear_key_cache (&cargs);
if (disklast)
*disklast = ')';
return GRUB_ERR_NONE;
}
dev = grub_cryptodisk_scan_device_real (diskname, disk, &cargs);
+ grub_cryptodisk_clear_key_cache (&cargs);
grub_disk_close (disk);
if (disklast)
@@ -1385,7 +1491,7 @@ GRUB_MOD_INIT (cryptodisk)
{
grub_disk_dev_register (&grub_cryptodisk_dev);
cmd = grub_register_extcmd ("cryptomount", grub_cmd_cryptomount, 0,
- N_("[-p password] <SOURCE|-u UUID|-a|-b>"),
+ N_("[-p password] [-k protector [-k protector ...]] <SOURCE|-u UUID|-a|-b>"),
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 c6524c9ea9..b556498fba 100644
--- a/include/grub/cryptodisk.h
+++ b/include/grub/cryptodisk.h
@@ -67,6 +67,16 @@ typedef gcry_err_code_t
(*grub_cryptodisk_rekey_func_t) (struct grub_cryptodisk *dev,
grub_uint64_t zoneno);
+struct grub_cryptomount_cached_key
+{
+ grub_uint8_t *key;
+ grub_size_t key_len;
+
+ /* The key protector associated with this cache entry failed, so avoid it
+ * even if the cached entry (an instance of this structure) is empty. */
+ int invalid;
+};
+
struct grub_cryptomount_args
{
/* scan: Flag to indicate that only bootable volumes should be decrypted */
@@ -77,6 +87,10 @@ struct grub_cryptomount_args
grub_uint8_t *key_data;
/* recover_key: Length of key_data */
grub_size_t key_len;
+ /* recover_key: Names of the key protectors to use (NULL-terminated) */
+ char **protectors;
+ /* recover_key: Key cache to avoid invoking the same key protector twice */
+ struct grub_cryptomount_cached_key *key_cache;
};
typedef struct grub_cryptomount_args *grub_cryptomount_args_t;
--
2.34.1

File diff suppressed because it is too large Load Diff

View File

@ -1,38 +0,0 @@
---
grub-core/Makefile.core.def | 1 +
grub-core/tpm2/module.c | 2 +-
util/grub-protect.c | 2 +-
3 files changed, 3 insertions(+), 2 deletions(-)
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -2569,6 +2569,7 @@
common = tpm2/mu.c;
common = tpm2/tpm2.c;
efi = tpm2/tcg2.c;
+ enable = efi;
};
module = {
--- a/util/grub-protect.c
+++ b/util/grub-protect.c
@@ -542,7 +542,7 @@
if (pcr_values.digests[i].size != pcr_digest_len)
{
fprintf (stderr,
- _("Bad PCR value size: expected %lu bytes but got %u bytes.\n"),
+ _("Bad PCR value size: expected %" PRIuGRUB_SIZE " bytes but got %u bytes.\n"),
pcr_digest_len, pcr_values.digests[i].size);
goto exit2;
}
--- a/grub-core/tpm2/module.c
+++ b/grub-core/tpm2/module.c
@@ -195,7 +195,7 @@
if (sealed_key_size > buf.cap)
{
grub_dprintf ("tpm2", "Sealed key file is larger than decode buffer "
- "(%lu vs %lu bytes).\n", sealed_key_size, buf.cap);
+ "(%" PRIuGRUB_SIZE " vs %" PRIuGRUB_SIZE " bytes).\n", sealed_key_size, buf.cap);
return GRUB_ERR_BAD_ARGUMENT;
}

View File

@ -1,45 +1,3 @@
-------------------------------------------------------------------
Thu Aug 18 02:47:28 UTC 2022 - Michael Chang <mchang@suse.com>
- Fix tpm error stop tumbleweed from booting (bsc#1202374)
* 0001-tpm-Pass-unknown-error-as-non-fatal-but-debug-print-.patch
- Patch Removed
* 0001-tpm-Log-EFI_VOLUME_FULL-and-continue.patch
-------------------------------------------------------------------
Wed Jun 8 03:25:26 UTC 2022 - Michael Chang <mchang@suse.com>
- Add tpm, tpm2, luks2 and gcry_sha512 to default grub.efi (bsc#1197625)
- Make grub-tpm.efi a symlink to grub.efi
* grub2.spec
- Log error when tpm event log is full and continue
* 0001-tpm-Log-EFI_VOLUME_FULL-and-continue.patch
- Patch superseded
* 0001-tpm-Pass-unknown-error-as-non-fatal-but-debug-print-.patch
-------------------------------------------------------------------
Wed Jun 8 03:17:29 UTC 2022 - Michael Chang <mchang@suse.com>
- Add patches for automatic TPM disk unlock (jsc#SLE-24018) (bsc#1196668)
* 0001-luks2-Add-debug-message-to-align-with-luks-and-geli-.patch
* 0002-cryptodisk-Refactor-to-discard-have_it-global.patch
* 0003-cryptodisk-Return-failure-in-cryptomount-when-no-cry.patch
* 0004-cryptodisk-Improve-error-messaging-in-cryptomount-in.patch
* 0005-cryptodisk-Improve-cryptomount-u-error-message.patch
* 0006-cryptodisk-Add-infrastructure-to-pass-data-from-cryp.patch
* 0007-cryptodisk-Refactor-password-input-out-of-crypto-dev.patch
* 0008-cryptodisk-Move-global-variables-into-grub_cryptomou.patch
* 0009-cryptodisk-Improve-handling-of-partition-name-in-cry.patch
* 0010-protectors-Add-key-protectors-framework.patch
* 0011-tpm2-Add-TPM-Software-Stack-TSS.patch
* 0012-protectors-Add-TPM2-Key-Protector.patch
* 0013-cryptodisk-Support-key-protectors.patch
* 0014-util-grub-protect-Add-new-tool.patch
- Fix no disk unlocking happen (bsc#1196668)
* 0001-crytodisk-fix-cryptodisk-module-looking-up.patch
- Fix build error
* fix-tpm2-build.patch
-------------------------------------------------------------------
Tue May 31 04:44:18 UTC 2022 - Michael Chang <mchang@suse.com>

View File

@ -407,22 +407,6 @@ Patch881: 0029-fs-btrfs-Fix-several-fuzz-issues-with-invalid-dir-it.patch
Patch882: 0030-fs-btrfs-Fix-more-ASAN-and-SEGV-issues-found-with-fu.patch
Patch883: 0031-fs-btrfs-Fix-more-fuzz-issues-related-to-chunks.patch
Patch884: 0032-Use-grub_loader_set_ex-for-secureboot-chainloader.patch
Patch885: 0001-luks2-Add-debug-message-to-align-with-luks-and-geli-.patch
Patch886: 0002-cryptodisk-Refactor-to-discard-have_it-global.patch
Patch887: 0003-cryptodisk-Return-failure-in-cryptomount-when-no-cry.patch
Patch888: 0004-cryptodisk-Improve-error-messaging-in-cryptomount-in.patch
Patch889: 0005-cryptodisk-Improve-cryptomount-u-error-message.patch
Patch890: 0006-cryptodisk-Add-infrastructure-to-pass-data-from-cryp.patch
Patch891: 0007-cryptodisk-Refactor-password-input-out-of-crypto-dev.patch
Patch892: 0008-cryptodisk-Move-global-variables-into-grub_cryptomou.patch
Patch893: 0009-cryptodisk-Improve-handling-of-partition-name-in-cry.patch
Patch894: 0010-protectors-Add-key-protectors-framework.patch
Patch895: 0011-tpm2-Add-TPM-Software-Stack-TSS.patch
Patch896: 0012-protectors-Add-TPM2-Key-Protector.patch
Patch897: 0013-cryptodisk-Support-key-protectors.patch
Patch898: 0014-util-grub-protect-Add-new-tool.patch
Patch899: fix-tpm2-build.patch
Patch900: 0001-crytodisk-fix-cryptodisk-module-looking-up.patch
Requires: gettext-runtime
%if 0%{?suse_version} >= 1140
@ -691,9 +675,9 @@ CD_MODULES="all_video boot cat configfile echo true \
password password_pbkdf2 png reboot search search_fs_uuid \
search_fs_file search_label sleep test video fat loadenv"
PXE_MODULES="tftp http"
CRYPTO_MODULES="luks luks2 gcry_rijndael gcry_sha1 gcry_sha256 gcry_sha512"
CRYPTO_MODULES="luks gcry_rijndael gcry_sha1 gcry_sha256"
%ifarch %{efi}
CD_MODULES="${CD_MODULES} chain efifwsetup efinet read tpm tpm2"
CD_MODULES="${CD_MODULES} chain efifwsetup efinet read"
PXE_MODULES="${PXE_MODULES} efinet"
%else
CD_MODULES="${CD_MODULES} net"
@ -731,6 +715,10 @@ echo "grub.%{sbat_distro},%{sbat_generation},%{sbat_distro_summary},%{name},%{ve
./grub-mkimage -O %{grubefiarch} -o grub.efi --prefix= %{?sbat_generation:--sbat sbat.csv} \
-d grub-core ${GRUB_MODULES}
%ifarch x86_64
./grub-mkimage -O %{grubefiarch} -o grub-tpm.efi --prefix= %{?sbat_generation:--sbat sbat.csv} \
-d grub-core ${GRUB_MODULES} tpm
%endif
%ifarch x86_64 aarch64
if test -e %{_sourcedir}/_projectcert.crt ; then
@ -910,7 +898,7 @@ cd build-efi
%make_install
install -m 644 grub.efi %{buildroot}/%{_datadir}/%{name}/%{grubefiarch}/.
%ifarch x86_64
ln -srf %{buildroot}/%{_datadir}/%{name}/%{grubefiarch}/grub.efi %{buildroot}/%{_datadir}/%{name}/%{grubefiarch}/grub-tpm.efi
install -m 644 grub-tpm.efi %{buildroot}/%{_datadir}/%{name}/%{grubefiarch}/.
%endif
# Create grub.efi link to system efi directory
@ -932,6 +920,9 @@ EoM
%ifarch x86_64 aarch64
export BRP_PESIGN_FILES="%{_datadir}/%{name}/%{grubefiarch}/grub.efi"
%ifarch x86_64
BRP_PESIGN_FILES="${BRP_PESIGN_FILES} %{_datadir}/%{name}/%{grubefiarch}/grub-tpm.efi"
%endif
install -m 444 grub.der %{buildroot}/%{sysefidir}/
%endif
@ -1258,7 +1249,6 @@ fi
%{_bindir}/%{name}-render-label
%{_bindir}/%{name}-script-check
%{_bindir}/%{name}-syslinux2cfg
%{_bindir}/%{name}-protect
%if 0%{?has_systemd:1}
%{_unitdir}/grub2-once.service
%endif