151 lines
5.3 KiB
Diff
151 lines
5.3 KiB
Diff
From 0a11bc48ea60f7611df2c5b640cecc325c7c4fd9 Mon Sep 17 00:00:00 2001
|
|
From: Maxim Suhanov <dfirblog@gmail.com>
|
|
Date: Thu, 8 May 2025 19:02:12 +0200
|
|
Subject: [PATCH 6/8] disk/cryptodisk: Add the "erase secrets" function
|
|
|
|
This commit adds the grub_cryptodisk_erasesecrets() function to wipe
|
|
master keys from all cryptodisks. This function is EFI-only.
|
|
|
|
Since there is no easy way to "force unmount" a given encrypted disk,
|
|
this function renders all mounted cryptodisks unusable. An attempt to
|
|
read them will return garbage.
|
|
|
|
This is why this function must be used in "no way back" conditions.
|
|
|
|
Currently, it is used when unloading the cryptodisk module and when
|
|
performing the "exit" command (it is often used to switch to the next
|
|
EFI application). This function is not called when performing the
|
|
"chainloader" command, because the callee may return to GRUB. For this
|
|
reason, users are encouraged to use "exit" instead of "chainloader" to
|
|
execute third-party boot applications.
|
|
|
|
This function does not guarantee that all secrets are wiped from RAM.
|
|
Console output, chunks from disk read requests and other may remain.
|
|
|
|
This function does not clear the IV prefix and rekey key for geli disks.
|
|
|
|
Also, this commit adds the relevant documentation improvements.
|
|
|
|
Signed-off-by: Maxim Suhanov <dfirblog@gmail.com>
|
|
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
|
---
|
|
docs/grub.texi | 6 ++++++
|
|
grub-core/commands/minicmd.c | 11 +++++++++++
|
|
grub-core/disk/cryptodisk.c | 28 ++++++++++++++++++++++++++++
|
|
include/grub/cryptodisk.h | 1 +
|
|
4 files changed, 46 insertions(+)
|
|
|
|
diff --git a/docs/grub.texi b/docs/grub.texi
|
|
index 1c078c5c5b..c4936db8c1 100644
|
|
--- a/docs/grub.texi
|
|
+++ b/docs/grub.texi
|
|
@@ -4727,6 +4727,11 @@ namespace in addition to the cryptodisk namespace.
|
|
|
|
Support for plain encryption mode (plain dm-crypt) is provided via separate
|
|
@command{@pxref{plainmount}} command.
|
|
+
|
|
+On the EFI platform, GRUB tries to erase master keys from memory when the cryptodisk
|
|
+module is unloaded or the command @command{exit} is executed. All secrets remain in
|
|
+memory when the command @command{chainloader} is issued, because execution can
|
|
+return to GRUB on the EFI platform.
|
|
@end deffn
|
|
|
|
@node cutmem
|
|
@@ -6981,6 +6986,7 @@ USB support provides benefits similar to ATA (for USB disks) or AT (for USB
|
|
keyboards). In addition it allows USBserial.
|
|
|
|
Chainloading refers to the ability to load another bootloader through the same protocol
|
|
+and on some platforms, like EFI, allow that bootloader to return to the GRUB.
|
|
|
|
Hints allow faster disk discovery by already knowing in advance which is the disk in
|
|
question. On some platforms hints are correct unless you move the disk between boots.
|
|
diff --git a/grub-core/commands/minicmd.c b/grub-core/commands/minicmd.c
|
|
index 903af33131..bd9cb681ec 100644
|
|
--- a/grub-core/commands/minicmd.c
|
|
+++ b/grub-core/commands/minicmd.c
|
|
@@ -29,6 +29,10 @@
|
|
#include <grub/command.h>
|
|
#include <grub/i18n.h>
|
|
|
|
+#ifdef GRUB_MACHINE_EFI
|
|
+#include <grub/cryptodisk.h>
|
|
+#endif
|
|
+
|
|
GRUB_MOD_LICENSE ("GPLv3+");
|
|
|
|
/* cat FILE */
|
|
@@ -187,6 +191,13 @@ grub_mini_cmd_exit (struct grub_command *cmd __attribute__ ((unused)),
|
|
int argc __attribute__ ((unused)),
|
|
char *argv[] __attribute__ ((unused)))
|
|
{
|
|
+#ifdef GRUB_MACHINE_EFI
|
|
+ /*
|
|
+ * The "exit" command is often used to launch the next boot application.
|
|
+ * So, erase the secrets.
|
|
+ */
|
|
+ grub_cryptodisk_erasesecrets ();
|
|
+#endif
|
|
grub_exit ();
|
|
/* Not reached. */
|
|
}
|
|
diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
|
|
index 33eb6568ca..f9ae750f85 100644
|
|
--- a/grub-core/disk/cryptodisk.c
|
|
+++ b/grub-core/disk/cryptodisk.c
|
|
@@ -1784,6 +1784,31 @@ grub_cryptodisk_challenge_password (void)
|
|
|
|
return GRUB_ERR_NONE;
|
|
}
|
|
+
|
|
+void
|
|
+grub_cryptodisk_erasesecrets (void)
|
|
+{
|
|
+ grub_cryptodisk_t i;
|
|
+ grub_uint8_t *buf;
|
|
+
|
|
+ buf = grub_zalloc (GRUB_CRYPTODISK_MAX_KEYLEN);
|
|
+ if (buf == NULL)
|
|
+ grub_fatal ("grub_cryptodisk_erasesecrets: cannot allocate memory");
|
|
+
|
|
+ for (i = cryptodisk_list; i != NULL; i = i->next)
|
|
+ if (grub_cryptodisk_setkey (i, buf, i->keysize))
|
|
+ grub_fatal ("grub_cryptodisk_erasesecrets: cannot erase secrets for %s", i->source);
|
|
+ else
|
|
+ grub_printf ("Erased crypto secrets for %s\n", i->source);
|
|
+ /*
|
|
+ * Unfortunately, there is no way to "force unmount" a given disk, it may
|
|
+ * have mounted "child" disks as well, e.g., an LVM volume. So, this
|
|
+ * function MUST be called when there is no way back, e.g., when exiting.
|
|
+ * Otherwise, subsequent read calls for a cryptodisk will return garbage.
|
|
+ */
|
|
+
|
|
+ grub_free (buf);
|
|
+}
|
|
#endif /* GRUB_MACHINE_EFI */
|
|
|
|
struct grub_procfs_entry luks_script =
|
|
@@ -1808,6 +1833,9 @@ GRUB_MOD_INIT (cryptodisk)
|
|
|
|
GRUB_MOD_FINI (cryptodisk)
|
|
{
|
|
+#ifdef GRUB_MACHINE_EFI
|
|
+ grub_cryptodisk_erasesecrets ();
|
|
+#endif
|
|
grub_disk_dev_unregister (&grub_cryptodisk_dev);
|
|
cryptodisk_cleanup ();
|
|
grub_unregister_extcmd (cmd);
|
|
diff --git a/include/grub/cryptodisk.h b/include/grub/cryptodisk.h
|
|
index b3291519b1..08abfb7b6c 100644
|
|
--- a/include/grub/cryptodisk.h
|
|
+++ b/include/grub/cryptodisk.h
|
|
@@ -205,5 +205,6 @@ grub_cryptodisk_t grub_cryptodisk_get_by_source_disk (grub_disk_t disk);
|
|
|
|
#ifdef GRUB_MACHINE_EFI
|
|
grub_err_t grub_cryptodisk_challenge_password (void);
|
|
+void grub_cryptodisk_erasesecrets (void);
|
|
#endif
|
|
#endif
|
|
--
|
|
2.49.0
|
|
|