Accepting request 1032598 from Base:System

OBS-URL: https://build.opensuse.org/request/show/1032598
OBS-URL: https://build.opensuse.org/package/show/openSUSE:Factory/grub2?expand=0&rev=272
This commit is contained in:
Dominique Leuenberger 2022-11-09 11:56:40 +00:00 committed by Git OBS Bridge
commit f981d91789
55 changed files with 12037 additions and 11 deletions

View File

@ -0,0 +1,39 @@
From d2c0426b3f0f91b941037263c83859a46ebb0c4f Mon Sep 17 00:00:00 2001
From: Lu Ken <ken.lu@intel.com>
Date: Wed, 13 Jul 2022 10:06:10 +0800
Subject: [PATCH 1/3] commands/efi/tpm: Refine the status of log event
1. Use macro GRUB_ERR_NONE instead of hard code 0.
2. Keep lowercase of the first char for the status string of log event.
Signed-off-by: Lu Ken <ken.lu@intel.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
grub-core/commands/efi/tpm.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/grub-core/commands/efi/tpm.c b/grub-core/commands/efi/tpm.c
index f296b8698..19737b462 100644
--- a/grub-core/commands/efi/tpm.c
+++ b/grub-core/commands/efi/tpm.c
@@ -136,13 +136,13 @@ grub_efi_log_event_status (grub_efi_status_t status)
switch (status)
{
case GRUB_EFI_SUCCESS:
- return 0;
+ return GRUB_ERR_NONE;
case GRUB_EFI_DEVICE_ERROR:
- return grub_error (GRUB_ERR_IO, N_("Command failed"));
+ return grub_error (GRUB_ERR_IO, N_("command failed"));
case GRUB_EFI_INVALID_PARAMETER:
- return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("Invalid parameter"));
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("invalid parameter"));
case GRUB_EFI_BUFFER_TOO_SMALL:
- return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("Output buffer too small"));
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("output buffer too small"));
case GRUB_EFI_NOT_FOUND:
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, N_("TPM unavailable"));
default:
--
2.35.3

View File

@ -0,0 +1,33 @@
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

@ -0,0 +1,53 @@
From ebe4ac49e800b18b539564169593ab1c6f163378 Mon Sep 17 00:00:00 2001
From: Josselin Poiret via Grub-devel <grub-devel@gnu.org>
Date: Tue, 14 Jun 2022 15:47:29 +0200
Subject: [PATCH 01/10] devmapper/getroot: Have devmapper recognize LUKS2
Changes UUID comparisons so that LUKS1 and LUKS2 are both recognized
as being LUKS cryptodisks.
---
grub-core/osdep/devmapper/getroot.c | 11 +++++++----
1 file changed, 7 insertions(+), 4 deletions(-)
diff --git a/grub-core/osdep/devmapper/getroot.c b/grub-core/osdep/devmapper/getroot.c
index 9ba5c98655..2bf4264cf0 100644
--- a/grub-core/osdep/devmapper/getroot.c
+++ b/grub-core/osdep/devmapper/getroot.c
@@ -138,7 +138,8 @@ grub_util_get_dm_abstraction (const char *os_dev)
grub_free (uuid);
return GRUB_DEV_ABSTRACTION_LVM;
}
- if (strncmp (uuid, "CRYPT-LUKS1-", 12) == 0)
+ if (strncmp (uuid, "CRYPT-LUKS1-", sizeof ("CRYPT-LUKS1-") - 1) == 0
+ || strncmp (uuid, "CRYPT-LUKS2-", sizeof ("CRYPT-LUKS2-") - 1) == 0)
{
grub_free (uuid);
return GRUB_DEV_ABSTRACTION_LUKS;
@@ -179,7 +180,9 @@ grub_util_pull_devmapper (const char *os_dev)
grub_util_pull_device (subdev);
}
}
- if (uuid && strncmp (uuid, "CRYPT-LUKS1-", sizeof ("CRYPT-LUKS1-") - 1) == 0
+ if (uuid
+ && (strncmp (uuid, "CRYPT-LUKS1-", sizeof ("CRYPT-LUKS1-") - 1) == 0
+ || strncmp (uuid, "CRYPT-LUKS2-", sizeof ("CRYPT-LUKS2-") - 1) == 0)
&& lastsubdev)
{
char *grdev = grub_util_get_grub_dev (lastsubdev);
@@ -253,11 +256,11 @@ grub_util_get_devmapper_grub_dev (const char *os_dev)
{
char *dash;
- dash = grub_strchr (uuid + sizeof ("CRYPT-LUKS1-") - 1, '-');
+ dash = grub_strchr (uuid + sizeof ("CRYPT-LUKS*-") - 1, '-');
if (dash)
*dash = 0;
grub_dev = grub_xasprintf ("cryptouuid/%s",
- uuid + sizeof ("CRYPT-LUKS1-") - 1);
+ uuid + sizeof ("CRYPT-LUKS*-") - 1);
grub_free (uuid);
return grub_dev;
}
--
2.34.1

View File

@ -0,0 +1,32 @@
From grub-devel-bounces@gnu.org Thu Aug 25 08:11:08 2022
From: Michael Chang <mchang@suse.com>
Date: Thu, 25 Aug 2022 14:05:01 +0800
Subject: [PATCH] grub-install: set point of no return for powerpc-ieee1275
install
The point of no return is used to define a point where no change should
be reverted in a wake of fatal error that consequently aborts the
process. The powerpc-ieee1275 install apparently missed this point of no
return defintion that newly installed modules could be inadvertently
reverted after successful image embedding so that boot failure is
incurred due to inconsistent state.
Signed-off-by: Michael Chang <mchang@suse.com>
[iluceno@suse.de: Backported to SLES-15-SP4]
Signed-off-by: Ismael Luceno <iluceno@suse.de>
---
util/grub-install.c | 1 +
1 file changed, 1 insertion(+)
Index: grub-2.06/util/grub-install.c
===================================================================
--- grub-2.06.orig/util/grub-install.c
+++ grub-2.06/util/grub-install.c
@@ -2160,6 +2160,7 @@ main (int argc, char *argv[])
{
grub_util_error ("%s", _("failed to copy Grub to the PReP partition"));
}
+ grub_set_install_backup_ponr ();
if ((signed_grub_mode >= SIGNED_GRUB_FORCE) || ((signed_grub_mode == SIGNED_GRUB_AUTO) && (ppc_sb_state > 0)))
{

View File

@ -0,0 +1,239 @@
From f86bd28391e6d92f8084f0b789ba4a8f6d789dfa Mon Sep 17 00:00:00 2001
From: Stefan Berger <stefanb@linux.ibm.com>
Date: Sun, 15 Mar 2020 12:37:10 -0400
Subject: [PATCH 1/2] ibmvtpm: Add support for trusted boot using a vTPM 2.0
Add support for trusted boot using a vTPM 2.0 on the IBM IEEE1275
PowerPC platform. With this patch grub now measures text and binary data
into the TPM's PCRs 8 and 9 in the same way as the x86_64 platform
does.
This patch requires Daniel Axtens's patches for claiming more memory.
For vTPM support to work on PowerVM, system driver levels 1010.30
or 1020.00 are required.
Note: Previous versions of firmware levels with the 2hash-ext-log
API call have a bug that, once this API call is invoked, has the
effect of disabling the vTPM driver under Linux causing an error
message to be displayed in the Linux kernel log. Those users will
have to update their machines to the firmware levels mentioned
above.
Cc: Eric Snowberg <eric.snowberg@oracle.com>
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
---
docs/grub.texi | 3 +-
grub-core/Makefile.core.def | 7 ++
grub-core/commands/ieee1275/ibmvtpm.c | 152 ++++++++++++++++++++++++++
include/grub/ieee1275/ieee1275.h | 3 +
4 files changed, 164 insertions(+), 1 deletion(-)
create mode 100644 grub-core/commands/ieee1275/ibmvtpm.c
diff --git a/docs/grub.texi b/docs/grub.texi
index 4504bcabe..026aacacf 100644
--- a/docs/grub.texi
+++ b/docs/grub.texi
@@ -6204,7 +6204,8 @@ tpm module is loaded. As such it is recommended that the tpm module be built
into @file{core.img} in order to avoid a potential gap in measurement between
@file{core.img} being loaded and the tpm module being loaded.
-Measured boot is currently only supported on EFI platforms.
+Measured boot is currently only supported on EFI and IBM IEEE1275 PowerPC
+platforms.
@node Lockdown
@section Lockdown when booting on a secure setup
diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
index cee596872..54733425c 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -1141,6 +1141,13 @@ module = {
enable = powerpc_ieee1275;
};
+module = {
+ name = tpm;
+ common = commands/tpm.c;
+ ieee1275 = commands/ieee1275/ibmvtpm.c;
+ enable = powerpc_ieee1275;
+};
+
module = {
name = terminal;
common = commands/terminal.c;
diff --git a/grub-core/commands/ieee1275/ibmvtpm.c b/grub-core/commands/ieee1275/ibmvtpm.c
new file mode 100644
index 000000000..e68b8448b
--- /dev/null
+++ b/grub-core/commands/ieee1275/ibmvtpm.c
@@ -0,0 +1,152 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2021 Free Software Foundation, Inc.
+ * Copyright (C) 2021 IBM 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/>.
+ *
+ * IBM vTPM support code.
+ */
+
+#include <grub/err.h>
+#include <grub/types.h>
+#include <grub/tpm.h>
+#include <grub/ieee1275/ieee1275.h>
+#include <grub/mm.h>
+#include <grub/misc.h>
+
+static grub_ieee1275_ihandle_t tpm_ihandle;
+static grub_uint8_t tpm_version;
+
+#define IEEE1275_IHANDLE_INVALID ((grub_ieee1275_ihandle_t)0)
+
+static void
+tpm_get_tpm_version (void)
+{
+ grub_ieee1275_phandle_t vtpm;
+ char buffer[20];
+
+ if (!grub_ieee1275_finddevice ("/vdevice/vtpm", &vtpm) &&
+ !grub_ieee1275_get_property (vtpm, "compatible", buffer,
+ sizeof (buffer), NULL) &&
+ !grub_strcmp (buffer, "IBM,vtpm20"))
+ tpm_version = 2;
+}
+
+static grub_err_t
+tpm_init (void)
+{
+ static int init_success = 0;
+
+ if (!init_success)
+ {
+ if (grub_ieee1275_open ("/vdevice/vtpm", &tpm_ihandle) < 0) {
+ tpm_ihandle = IEEE1275_IHANDLE_INVALID;
+ return GRUB_ERR_UNKNOWN_DEVICE;
+ }
+
+ init_success = 1;
+
+ tpm_get_tpm_version ();
+ }
+
+ return GRUB_ERR_NONE;
+}
+
+static int
+ibmvtpm_2hash_ext_log (grub_uint8_t pcrindex,
+ grub_uint32_t eventtype,
+ const char *description,
+ grub_size_t description_size,
+ void *buf, grub_size_t size)
+{
+ struct tpm_2hash_ext_log
+ {
+ struct grub_ieee1275_common_hdr common;
+ grub_ieee1275_cell_t method;
+ grub_ieee1275_cell_t ihandle;
+ grub_ieee1275_cell_t size;
+ grub_ieee1275_cell_t buf;
+ grub_ieee1275_cell_t description_size;
+ grub_ieee1275_cell_t description;
+ grub_ieee1275_cell_t eventtype;
+ grub_ieee1275_cell_t pcrindex;
+ grub_ieee1275_cell_t catch_result;
+ grub_ieee1275_cell_t rc;
+ }
+ args;
+
+ INIT_IEEE1275_COMMON (&args.common, "call-method", 8, 2);
+ args.method = (grub_ieee1275_cell_t) "2hash-ext-log";
+ args.ihandle = tpm_ihandle;
+ args.pcrindex = pcrindex;
+ args.eventtype = eventtype;
+ args.description = (grub_ieee1275_cell_t) description;
+ args.description_size = description_size;
+ args.buf = (grub_ieee1275_cell_t) buf;
+ args.size = (grub_ieee1275_cell_t) size;
+
+ if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
+ return -1;
+
+ /*
+ * catch_result is set if firmware does not support 2hash-ext-log
+ * rc is GRUB_IEEE1275_CELL_FALSE (0) on failure
+ */
+ if ((args.catch_result) || args.rc == GRUB_IEEE1275_CELL_FALSE)
+ return -1;
+
+ return 0;
+}
+
+static grub_err_t
+tpm2_log_event (unsigned char *buf,
+ grub_size_t size, grub_uint8_t pcr,
+ const char *description)
+{
+ static int error_displayed = 0;
+ int err;
+
+ err = ibmvtpm_2hash_ext_log (pcr, EV_IPL,
+ description,
+ grub_strlen(description) + 1,
+ buf, size);
+ if (err && !error_displayed)
+ {
+ error_displayed++;
+ return grub_error (GRUB_ERR_BAD_DEVICE,
+ "2HASH-EXT-LOG failed: Firmware is likely too old.\n");
+ }
+
+ return GRUB_ERR_NONE;
+}
+
+grub_err_t
+grub_tpm_measure (unsigned char *buf, grub_size_t size, grub_uint8_t pcr,
+ const char *description)
+{
+ grub_err_t err = tpm_init();
+
+ /* Absence of a TPM isn't a failure. */
+ if (err != GRUB_ERR_NONE)
+ return GRUB_ERR_NONE;
+
+ grub_dprintf ("tpm", "log_event, pcr = %d, size = 0x%" PRIxGRUB_SIZE ", %s\n",
+ pcr, size, description);
+
+ if (tpm_version == 2)
+ return tpm2_log_event (buf, size, pcr, description);
+
+ return GRUB_ERR_NONE;
+}
diff --git a/include/grub/ieee1275/ieee1275.h b/include/grub/ieee1275/ieee1275.h
index 591f4f12c..8a621af7c 100644
--- a/include/grub/ieee1275/ieee1275.h
+++ b/include/grub/ieee1275/ieee1275.h
@@ -24,6 +24,9 @@
#include <grub/types.h>
#include <grub/machine/ieee1275.h>
+#define GRUB_IEEE1275_CELL_FALSE ((grub_ieee1275_cell_t) 0)
+#define GRUB_IEEE1275_CELL_TRUE ((grub_ieee1275_cell_t) -1)
+
struct grub_ieee1275_mem_region
{
unsigned int start;
--
2.35.3

View File

@ -0,0 +1,250 @@
From c125cb45a7885d7bf168a05cfa4da3e681244649 Mon Sep 17 00:00:00 2001
From: Diego Domingos <diegodo@br.ibm.com>
Date: Tue, 15 Feb 2022 13:11:48 -0500
Subject: [PATCH 1/4] ieee1275: add support for NVMeoFC
Implements the functions to scan and discovery of NVMeoFC.
---
grub-core/disk/ieee1275/ofdisk.c | 217 ++++++++++++++++++++++++++++++-
1 file changed, 213 insertions(+), 4 deletions(-)
diff --git a/grub-core/disk/ieee1275/ofdisk.c b/grub-core/disk/ieee1275/ofdisk.c
index 410f4b849..852bb95be 100644
--- a/grub-core/disk/ieee1275/ofdisk.c
+++ b/grub-core/disk/ieee1275/ofdisk.c
@@ -206,12 +206,10 @@ dev_iterate_real (const char *name, const char *path)
return;
}
+
static void
-dev_iterate (const struct grub_ieee1275_devalias *alias)
+dev_iterate_fcp_disks(const struct grub_ieee1275_devalias *alias)
{
- if (grub_strcmp (alias->type, "fcp") == 0)
- {
-
/* If we are dealing with fcp devices, we need
* to find the WWPNs and LUNs to iterate them */
grub_ieee1275_ihandle_t ihandle;
@@ -323,6 +321,217 @@ dev_iterate (const struct grub_ieee1275_devalias *alias)
grub_free (buf);
return;
+}
+
+static void
+dev_iterate_fcp_nvmeof (const struct grub_ieee1275_devalias *alias)
+{
+
+
+ char *bufptr;
+ grub_ieee1275_ihandle_t ihandle;
+
+
+ // Create the structs for the parameters passing to PFW
+ struct nvme_args_
+ {
+ struct grub_ieee1275_common_hdr common;
+ grub_ieee1275_cell_t method;
+ grub_ieee1275_cell_t ihandle;
+ grub_ieee1275_cell_t catch_result;
+ grub_ieee1275_cell_t nentries;
+ grub_ieee1275_cell_t table;
+ } nvme_discovery_controllers_args, nvme_controllers_args, nvme_namespaces_args;
+
+
+ // Create the structs for the results from PFW
+
+ struct discovery_controllers_table_struct_
+ {
+ grub_uint64_t table[256];
+ grub_uint32_t len;
+ } discovery_controllers_table;
+
+ /* struct nvme_controllers_table_entry
+ * this the return of nvme-controllers method tables, containing:
+ * - 2-byte controller ID
+ * - 256-byte transport address string
+ * - 256-byte field containing null-terminated NVM subsystem NQN string up to 223 characters
+ */
+ struct nvme_controllers_table_entry_
+ {
+ grub_uint16_t id;
+ char wwpn[256];
+ char nqn[256];
+ };
+
+ struct nvme_controllers_table_entry_* nvme_controllers_table = grub_malloc(sizeof(struct nvme_controllers_table_entry_)*256);
+
+ grub_uint32_t nvme_controllers_table_entries;
+
+ struct nvme_controllers_table_entry_real
+ {
+ grub_uint16_t id;
+ char wwpn[256];
+ char nqn[256];
+ };
+
+ /* Allocate memory for building the NVMeoF path */
+ char *buf = grub_malloc (grub_strlen (alias->path) + 512);
+ if (!buf)
+ {
+ grub_ieee1275_close(ihandle);
+ return;
+ }
+
+ /* Copy the alias->path to buf so we can work with */
+ bufptr = grub_stpcpy (buf, alias->path);
+ grub_snprintf (bufptr, 32, "/nvme-of");
+
+ /*
+ * Open the nvme-of layer
+ * Ex. /pci@bus/fibre-channel@@dev,func/nvme-of
+ */
+ if(grub_ieee1275_open (buf, &ihandle))
+ {
+ grub_dprintf("disk", "failed to open the disk while iterating FCP disk path=%s\n", buf);
+ return;
+ }
+
+ /*
+ * Call to nvme-discovery-controllers method from the nvme-of layer
+ * to get a list of the NVMe discovery controllers per the binding
+ */
+
+ INIT_IEEE1275_COMMON (&nvme_discovery_controllers_args.common, "call-method", 2, 2);
+ nvme_discovery_controllers_args.method = (grub_ieee1275_cell_t) "nvme-discovery-controllers";
+ nvme_discovery_controllers_args.ihandle = ihandle;
+
+ if (IEEE1275_CALL_ENTRY_FN (&nvme_discovery_controllers_args) == -1)
+ {
+ grub_dprintf("disk", "failed to get the targets while iterating FCP disk path=%s\n", buf);
+ grub_ieee1275_close(ihandle);
+ return;
+ }
+
+ /* After closing the device, the info is lost. So lets copy each buffer in the buffers table */
+
+ discovery_controllers_table.len = (grub_uint32_t) nvme_discovery_controllers_args.nentries;
+
+ unsigned int i=0;
+ for(i = 0; i < discovery_controllers_table.len; i++){
+ discovery_controllers_table.table[i] = ((grub_uint64_t*)nvme_discovery_controllers_args.table)[i];
+ }
+
+ grub_ieee1275_close(ihandle);
+
+ grub_dprintf("ofdisk","NVMeoF: Found %d discovery controllers\n",discovery_controllers_table.len);
+
+ /* For each nvme discovery controller */
+ int current_buffer_index;
+ for(current_buffer_index = 0; current_buffer_index < (int) discovery_controllers_table.len; current_buffer_index++){
+
+
+ grub_snprintf (bufptr, 64, "/nvme-of/controller@%" PRIxGRUB_UINT64_T ",ffff",
+ discovery_controllers_table.table[current_buffer_index]);
+
+ grub_dprintf("ofdisk","nvmeof controller=%s\n",buf);
+
+ if(grub_ieee1275_open (buf, &ihandle))
+ {
+ grub_dprintf("ofdisk", "failed to open the disk while getting nvme-controllers path=%s\n", buf);
+ continue;
+ }
+
+
+ INIT_IEEE1275_COMMON (&nvme_controllers_args.common, "call-method", 2, 2);
+ nvme_controllers_args.method = (grub_ieee1275_cell_t) "nvme-controllers";
+ nvme_controllers_args.ihandle = ihandle;
+ nvme_controllers_args.catch_result = 0;
+
+
+ if (IEEE1275_CALL_ENTRY_FN (&nvme_controllers_args) == -1)
+ {
+ grub_dprintf("ofdisk", "failed to get the nvme-controllers while iterating FCP disk path\n");
+ grub_ieee1275_close(ihandle);
+ continue;
+ }
+
+
+ /* Copy the buffer list to nvme_controllers_table */
+ nvme_controllers_table_entries = ((grub_uint32_t) nvme_controllers_args.nentries);
+ struct nvme_controllers_table_entry_* nvme_controllers_table_ = (struct nvme_controllers_table_entry_*) nvme_controllers_args.table;
+
+ for(i = 0; i < nvme_controllers_table_entries; i++){
+ nvme_controllers_table[i].id = (grub_uint16_t) nvme_controllers_table_[i].id;
+ grub_strcpy(nvme_controllers_table[i].wwpn, nvme_controllers_table_[i].wwpn);
+ grub_strcpy(nvme_controllers_table[i].nqn, nvme_controllers_table_[i].nqn);
+ }
+
+ grub_ieee1275_close(ihandle);
+
+ int nvme_controller_index;
+ int bufptr_pos2;
+ grub_dprintf("ofdisk","NVMeoF: found %d nvme controllers\n",(int) nvme_controllers_args.nentries);
+
+ /* For each nvme controller */
+ for(nvme_controller_index = 0; nvme_controller_index < (int) nvme_controllers_args.nentries; nvme_controller_index++){
+ /* Open the nvme controller
+ * /pci@bus/fibre-channel@dev,func/nvme-of/controller@transport-addr,ctlr-id:nqn=tgt-subsystem-nqn
+ */
+
+ bufptr_pos2 = grub_snprintf (bufptr, 512, "/nvme-of/controller@%s,ffff:nqn=%s",
+ nvme_controllers_table[nvme_controller_index].wwpn, nvme_controllers_table[nvme_controller_index].nqn);
+
+ grub_dprintf("ofdisk","NVMeoF: nvmeof controller=%s\n",buf);
+
+ if(grub_ieee1275_open (buf, &ihandle)){
+ grub_dprintf("ofdisk","failed to open the path=%s\n",buf);
+ continue;
+ }
+
+ INIT_IEEE1275_COMMON (&nvme_namespaces_args.common, "call-method", 2, 2);
+ nvme_namespaces_args.method = (grub_ieee1275_cell_t) "get-namespace-list";
+ nvme_namespaces_args.ihandle = ihandle;
+ nvme_namespaces_args.catch_result = 0;
+
+ if (IEEE1275_CALL_ENTRY_FN (&nvme_namespaces_args) == -1)
+ {
+ grub_dprintf("ofdisk", "failed to get the nvme-namespace-list while iterating FCP disk path\n");
+ grub_ieee1275_close(ihandle);
+ continue;
+ }
+
+ grub_uint32_t *namespaces = (grub_uint32_t*) nvme_namespaces_args.table;
+ grub_dprintf("ofdisk","NVMeoF: found %d namespaces\n",(int)nvme_namespaces_args.nentries);
+
+ grub_ieee1275_close(ihandle);
+
+ grub_uint32_t namespace_index = 0;
+ for(namespace_index=0; namespace_index < nvme_namespaces_args.nentries; namespace_index++){
+ grub_snprintf (bufptr+bufptr_pos2, 512, "/namespace@%"PRIxGRUB_UINT32_T,namespaces[namespace_index]);
+ grub_dprintf("ofdisk","NVMeoF: namespace=%s\n",buf);
+ dev_iterate_real(buf,buf);
+ }
+
+ dev_iterate_real(buf,buf);
+ }
+ }
+ grub_free(buf);
+ return;
+}
+
+static void
+dev_iterate (const struct grub_ieee1275_devalias *alias)
+{
+ if (grub_strcmp (alias->type, "fcp") == 0)
+ {
+ // Iterate disks
+ dev_iterate_fcp_disks(alias);
+
+ // Iterate NVMeoF
+ dev_iterate_fcp_nvmeof(alias);
+
}
else if (grub_strcmp (alias->type, "vscsi") == 0)
{
--
2.35.3

View File

@ -0,0 +1,32 @@
From 3e08d9afd273b5dade84fec5f7f17113c47b6b75 Mon Sep 17 00:00:00 2001
From: Gary Lin <glin@suse.com>
Date: Fri, 2 Sep 2022 11:26:39 +0800
Subject: [PATCH 1/2] kern/efi/mm: Enlarge the default heap size
The default heap size (0x100000, 1MB) is not enough for the
openSUSE/SUSE theme, and the additional dynamical allocation of memory
regions significantly slows down the loading of the grub2 menu theme.
This commit increases the default heap size to 0x2000000, 32MB, and this
should be enough to cover the theme files.
Signed-off-by: Gary Lin <glin@suse.com>
---
grub-core/kern/efi/mm.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/grub-core/kern/efi/mm.c b/grub-core/kern/efi/mm.c
index 48380d3..70d3e3d 100644
--- a/grub-core/kern/efi/mm.c
+++ b/grub-core/kern/efi/mm.c
@@ -39,7 +39,7 @@
#define MEMORY_MAP_SIZE 0x3000
/* The default heap size for GRUB itself in bytes. */
-#define DEFAULT_HEAP_SIZE 0x100000
+#define DEFAULT_HEAP_SIZE 0x2000000
static void *finish_mmap_buf = 0;
static grub_efi_uintn_t finish_mmap_size = 0;
--
2.35.3

View File

@ -0,0 +1,182 @@
From 80487d82ee1c179c01fad1a23f26fcca79c0ace5 Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Mon, 26 Sep 2022 12:04:41 +0800
Subject: [PATCH] linux: fix efi_relocate_kernel failure
With the dynamic allocated heap in new memory manager, it could use up all
usable memory with no reservation on subsequent kernel loading leading to
following error:
EFI stub: ERROR: Failed to allocate usable memory for kernel
EFI stub: ERROR: efi_relocate_kernel() failed!
EFI stub: ERROR: efi_main failed!
The patch tries to returning the memory pages allocated by grub to the firmware
before handing over to linux kernel. This could eliminate the worry that we
have no limited amount of memory exclusively set for grub to guarentee the
memory requirement for booting subsequent component can be met.
Signed-off-by: Michael Chang <mchang@suse.com>
---
grub-core/Makefile.am | 7 +++++++
grub-core/Makefile.core.def | 2 +-
grub-core/loader/efi/linux.c | 16 ++++++++++++++++
grub-core/loader/i386/efi/linux.c | 13 ++++++++++---
4 files changed, 34 insertions(+), 4 deletions(-)
diff --git a/grub-core/Makefile.am b/grub-core/Makefile.am
index dc07ba6f8..3b1f101fd 100644
--- a/grub-core/Makefile.am
+++ b/grub-core/Makefile.am
@@ -124,6 +124,7 @@ if COND_i386_efi
KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/kernel.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/efi.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/disk.h
+KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/linux.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/tsc.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/acpi.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/pci.h
@@ -185,6 +186,7 @@ if COND_x86_64_efi
KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/kernel.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/efi.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/disk.h
+KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/linux.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/tsc.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/pci.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/acpi.h
@@ -194,6 +196,7 @@ endif
if COND_ia64_efi
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/efi.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/disk.h
+KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/linux.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/acpi.h
endif
@@ -281,6 +284,7 @@ endif
if COND_arm_efi
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/efi.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/disk.h
+KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/linux.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/arm/system.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/acpi.h
endif
@@ -288,18 +292,21 @@ endif
if COND_arm64_efi
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/efi.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/disk.h
+KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/linux.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/acpi.h
endif
if COND_riscv32_efi
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/efi.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/disk.h
+KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/linux.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/acpi.h
endif
if COND_riscv64_efi
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/efi.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/disk.h
+KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/linux.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/acpi.h
endif
diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
index 211d2166b..a8c5684dd 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -392,6 +392,7 @@ kernel = {
extra_dist = kern/i386/realmode.S;
extra_dist = boot/i386/pc/lzma_decode.S;
extra_dist = kern/mips/cache_flush.S;
+ efi = loader/efi/linux.c;
};
program = {
@@ -1855,7 +1856,6 @@ module = {
riscv64 = loader/riscv/linux.c;
emu = loader/emu/linux.c;
common = loader/linux.c;
- efi = loader/efi/linux.c;
};
module = {
diff --git a/grub-core/loader/efi/linux.c b/grub-core/loader/efi/linux.c
index 9265cf420..6ee0ca966 100644
--- a/grub-core/loader/efi/linux.c
+++ b/grub-core/loader/efi/linux.c
@@ -23,6 +23,8 @@
#include <grub/efi/efi.h>
#include <grub/efi/pe32.h>
#include <grub/efi/linux.h>
+#include <grub/kernel.h>
+#include <grub/loader.h>
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wcast-align"
@@ -38,6 +40,8 @@ grub_efi_linux_boot (void *kernel_addr, grub_off_t handover_offset,
int offset = 0;
#ifdef __x86_64__
+ grub_efi_simple_text_output_interface_t *o;
+ o = grub_efi_system_table->con_out;
offset = 512;
#endif
@@ -55,9 +59,21 @@ grub_efi_linux_boot (void *kernel_addr, grub_off_t handover_offset,
grub_dprintf ("linux", "kernel_addr: %p handover_offset: %p params: %p\n",
kernel_addr, (void *)(grub_efi_uintn_t)handover_offset, kernel_params);
hf = (handover_func)((char *)kernel_addr + handover_offset + offset);
+#ifdef __x86_64__
+ grub_machine_fini (GRUB_LOADER_FLAG_NORETURN);
+#endif
hf (grub_efi_image_handle, grub_efi_system_table, kernel_params);
+#ifdef __x86_64__
+ efi_call_2 (o->output_string, o, L"cannot boot linux kernel via efi handover\r\n"
+ L"rebooting in 5 seconds... *\r\n");
+ efi_call_1 (grub_efi_system_table->boot_services->stall, 5000000);
+ efi_call_4 (grub_efi_system_table->runtime_services->reset_system,
+ GRUB_EFI_RESET_COLD, GRUB_EFI_SUCCESS, 0, NULL);
+ for (;;) ;
+#else
return GRUB_ERR_BUG;
+#endif
}
#pragma GCC diagnostic pop
diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c
index 6b06a8f2f..b9b0d4a5f 100644
--- a/grub-core/loader/i386/efi/linux.c
+++ b/grub-core/loader/i386/efi/linux.c
@@ -90,6 +90,8 @@ kernel_alloc(grub_efi_uintn_t size, const char * const errmsg)
{
grub_uint64_t max = max_addresses[i].addr;
grub_efi_uintn_t pages;
+ grub_efi_status_t status;
+ grub_efi_boot_services_t *b;
/*
* When we're *not* loading the kernel, or >4GB allocations aren't
@@ -104,9 +106,14 @@ kernel_alloc(grub_efi_uintn_t size, const char * const errmsg)
pages, (void *)(grub_addr_t)max);
prev_max = max;
- addr = grub_efi_allocate_pages_real (max, pages,
- max_addresses[i].alloc_type,
- GRUB_EFI_LOADER_DATA);
+ b = grub_efi_system_table->boot_services;
+ status = efi_call_4 (b->allocate_pages, max_addresses[i].alloc_type, GRUB_EFI_LOADER_DATA, pages, &max);
+ if (status != GRUB_EFI_SUCCESS)
+ {
+ grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
+ max = 0;
+ }
+ addr = (void *) ((grub_addr_t) max);
if (addr)
grub_dprintf ("linux", "Allocated at %p\n", addr);
}
--
2.37.3

View File

@ -0,0 +1,31 @@
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

@ -0,0 +1,133 @@
From 23bca58a68264657f176885c3564d07c9938b7f6 Mon Sep 17 00:00:00 2001
From: Patrick Steinhardt <ps@pks.im>
Date: Thu, 21 Apr 2022 15:24:18 +1000
Subject: [PATCH 1/5] mm: Allow dynamically requesting additional memory
regions
Currently, all platforms will set up their heap on initialization of the
platform code. While this works mostly fine, it poses some limitations
on memory management on us. Most notably, allocating big chunks of
memory in the gigabyte range would require us to pre-request this many
bytes from the firmware and add it to the heap from the beginning on
some platforms like EFI. As this isn't needed for most configurations,
it is inefficient and may even negatively impact some usecases when,
e.g., chainloading. Nonetheless, allocating big chunks of memory is
required sometimes, where one example is the upcoming support for the
Argon2 key derival function in LUKS2.
In order to avoid pre-allocating big chunks of memory, this commit
implements a runtime mechanism to add more pages to the system. When
a given allocation cannot be currently satisfied, we'll call a given
callback set up by the platform's own memory management subsystem,
asking it to add a memory area with at least "n" bytes. If this
succeeds, we retry searching for a valid memory region, which should
now succeed.
If this fails, we try asking for "n" bytes, possibly spread across
multiple regions, in hopes that region merging means that we end up
with enough memory for things to work out.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Daniel Axtens <dja@axtens.net>
Tested-by: Stefan Berger <stefanb@linux.ibm.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
Tested-by: Patrick Steinhardt <ps@pks.im>
---
grub-core/kern/mm.c | 30 ++++++++++++++++++++++++++++++
include/grub/mm.h | 18 ++++++++++++++++++
2 files changed, 48 insertions(+)
diff --git a/grub-core/kern/mm.c b/grub-core/kern/mm.c
index 5c0a624..0bd9f75 100644
--- a/grub-core/kern/mm.c
+++ b/grub-core/kern/mm.c
@@ -28,6 +28,9 @@
- multiple regions may be used as free space. They may not be
contiguous.
+ - if existing regions are insufficient to satisfy an allocation, a new
+ region can be requested from firmware.
+
Regions are managed by a singly linked list, and the meta information is
stored in the beginning of each region. Space after the meta information
is used to allocate memory.
@@ -77,6 +80,7 @@
grub_mm_region_t grub_mm_base;
+grub_mm_add_region_func_t grub_mm_add_region_fn;
/* Get a header from the pointer PTR, and set *P and *R to a pointer
to the header and a pointer to its region, respectively. PTR must
@@ -364,6 +368,32 @@ grub_memalign (grub_size_t align, grub_size_t size)
goto again;
#endif
+ case 1:
+ /* Request additional pages, contiguous */
+ count++;
+
+ if (grub_mm_add_region_fn != NULL &&
+ grub_mm_add_region_fn (size, GRUB_MM_ADD_REGION_CONSECUTIVE) == GRUB_ERR_NONE)
+ goto again;
+
+ /* fallthrough */
+
+ case 2:
+ /* Request additional pages, anything at all */
+ count++;
+
+ if (grub_mm_add_region_fn != NULL)
+ {
+ /*
+ * Try again even if this fails, in case it was able to partially
+ * satisfy the request
+ */
+ grub_mm_add_region_fn (size, GRUB_MM_ADD_REGION_NONE);
+ goto again;
+ }
+
+ /* fallthrough */
+
default:
break;
}
diff --git a/include/grub/mm.h b/include/grub/mm.h
index 1754635..67faebf 100644
--- a/include/grub/mm.h
+++ b/include/grub/mm.h
@@ -20,6 +20,7 @@
#ifndef GRUB_MM_H
#define GRUB_MM_H 1
+#include <grub/err.h>
#include <grub/types.h>
#include <grub/symbol.h>
#include <config.h>
@@ -28,6 +29,23 @@
# define NULL ((void *) 0)
#endif
+#define GRUB_MM_ADD_REGION_NONE 0
+#define GRUB_MM_ADD_REGION_CONSECUTIVE (1 << 0)
+
+/*
+ * Function used to request memory regions of `grub_size_t` bytes. The second
+ * parameter is a bitfield of `GRUB_MM_ADD_REGION` flags.
+ */
+typedef grub_err_t (*grub_mm_add_region_func_t) (grub_size_t, unsigned int);
+
+/*
+ * Set this function pointer to enable adding memory-regions at runtime in case
+ * a memory allocation cannot be satisfied with existing regions.
+ */
+#ifndef GRUB_MACHINE_EMU
+extern grub_mm_add_region_func_t EXPORT_VAR(grub_mm_add_region_fn);
+#endif
+
void grub_mm_init_region (void *addr, grub_size_t size);
void *EXPORT_FUNC(grub_malloc) (grub_size_t size);
void *EXPORT_FUNC(grub_zalloc) (grub_size_t size);
--
2.35.3

View File

@ -0,0 +1,88 @@
From 12378be5243c1c02ce28de2e5703e87197c69157 Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Mon, 29 Aug 2022 11:28:28 +0800
Subject: [PATCH] tpm: Disable tpm verifier if tpm is not present
This helps to prevent out of memory error when reading large files via disablig
tpm device as verifier has to read all content into memory in one chunk to
measure the hash and extend to tpm.
Signed-off-by: Michael Chang <mchang@suse.com>
---
grub-core/commands/efi/tpm.c | 37 +++++++++++++++++++++++++++++++++++++
grub-core/commands/tpm.c | 4 ++++
include/grub/tpm.h | 1 +
3 files changed, 42 insertions(+)
--- a/grub-core/commands/efi/tpm.c
+++ b/grub-core/commands/efi/tpm.c
@@ -349,3 +349,40 @@
return result;
}
+
+int
+grub_tpm_present ()
+{
+ grub_efi_handle_t tpm_handle;
+ grub_efi_uint8_t protocol_version;
+
+ if (!grub_tpm_handle_find (&tpm_handle, &protocol_version))
+ return 0;
+
+ if (protocol_version == 1)
+ {
+ grub_efi_tpm_protocol_t *tpm;
+
+ tpm = grub_efi_open_protocol (tpm_handle, &tpm_guid,
+ GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+ if (!tpm)
+ {
+ grub_dprintf ("tpm", "Cannot open TPM protocol\n");
+ return 0;
+ }
+ return grub_tpm1_present (tpm);
+ }
+ else
+ {
+ grub_efi_tpm2_protocol_t *tpm;
+
+ tpm = grub_efi_open_protocol (tpm_handle, &tpm2_guid,
+ GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+ if (!tpm)
+ {
+ grub_dprintf ("tpm", "Cannot open TPM protocol\n");
+ return 0;
+ }
+ return grub_tpm2_present (tpm);
+ }
+}
--- a/grub-core/commands/tpm.c
+++ b/grub-core/commands/tpm.c
@@ -291,6 +291,8 @@
GRUB_MOD_INIT (tpm)
{
+ if (!grub_tpm_present())
+ return;
grub_verifier_register (&grub_tpm_verifier);
cmd = grub_register_extcmd ("tpm_record_pcrs", grub_tpm_record_pcrs, 0,
@@ -301,6 +303,8 @@
GRUB_MOD_FINI (tpm)
{
+ if (!grub_tpm_present())
+ return;
grub_verifier_unregister (&grub_tpm_verifier);
grub_unregister_extcmd (cmd);
}
--- a/include/grub/tpm.h
+++ b/include/grub/tpm.h
@@ -44,5 +44,6 @@
grub_uint8_t pcr, const char *description);
struct grub_tpm_digest *grub_tpm_read_pcr (grub_uint8_t index, const char *algo);
void grub_tpm_digest_free (struct grub_tpm_digest *d);
+int grub_tpm_present (void);
#endif

View File

@ -0,0 +1,40 @@
From 1f41f020f73131574cd7aee4e0e09d4c56277d1e Mon Sep 17 00:00:00 2001
From: Lu Ken <ken.lu@intel.com>
Date: Wed, 13 Jul 2022 10:06:11 +0800
Subject: [PATCH 2/3] commands/efi/tpm: Use grub_strcpy() instead of
grub_memcpy()
The event description is a string, so using grub_strcpy() is cleaner than
using grub_memcpy().
Signed-off-by: Lu Ken <ken.lu@intel.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
grub-core/commands/efi/tpm.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/grub-core/commands/efi/tpm.c b/grub-core/commands/efi/tpm.c
index 19737b462..e032617d8 100644
--- a/grub-core/commands/efi/tpm.c
+++ b/grub-core/commands/efi/tpm.c
@@ -177,7 +177,7 @@ grub_tpm1_log_event (grub_efi_handle_t tpm_handle, unsigned char *buf,
event->PCRIndex = pcr;
event->EventType = EV_IPL;
event->EventSize = grub_strlen (description) + 1;
- grub_memcpy (event->Event, description, event->EventSize);
+ grub_strcpy ((char *) event->Event, description);
algorithm = TCG_ALG_SHA;
status = efi_call_7 (tpm->log_extend_event, tpm, (grub_addr_t) buf, (grub_uint64_t) size,
@@ -299,7 +299,7 @@ grub_tpm2_log_event (grub_efi_handle_t tpm_handle, unsigned char *buf,
event->Header.EventType = EV_IPL;
event->Size =
sizeof (*event) - sizeof (event->Event) + grub_strlen (description) + 1;
- grub_memcpy (event->Event, description, grub_strlen (description) + 1);
+ grub_strcpy ((char *) event->Event, description);
status = efi_call_5 (tpm->hash_log_extend_event, tpm, 0, (grub_addr_t) buf,
(grub_uint64_t) size, event);
--
2.35.3

View File

@ -0,0 +1,187 @@
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

@ -0,0 +1,127 @@
From a25627c13b7e1e6998a14b5dd23b04b28465d737 Mon Sep 17 00:00:00 2001
From: Josselin Poiret via Grub-devel <grub-devel@gnu.org>
Date: Tue, 14 Jun 2022 15:47:30 +0200
Subject: [PATCH 02/10] devmapper/getroot: Set up cheated LUKS2 cryptodisk
mount from DM parameters
This lets a LUKS2 cryptodisk have its cipher and hash filled out,
otherwise they wouldn't be initialized if cheat mounted.
---
grub-core/osdep/devmapper/getroot.c | 91 +++++++++++++++++++++++++++++++++++-
1 file changed, 90 insertions(+), 1 deletion(-)
--- a/grub-core/osdep/devmapper/getroot.c
+++ b/grub-core/osdep/devmapper/getroot.c
@@ -51,6 +51,8 @@
#include <grub/emu/misc.h>
#include <grub/emu/hostdisk.h>
+#include <grub/cryptodisk.h>
+
static int
grub_util_open_dm (const char *os_dev, struct dm_tree **tree,
struct dm_tree_node **node)
@@ -186,7 +188,6 @@
&& lastsubdev)
{
char *grdev = grub_util_get_grub_dev (lastsubdev);
- dm_tree_free (tree);
if (grdev)
{
grub_err_t err;
@@ -194,7 +195,95 @@
if (err)
grub_util_error (_("can't mount encrypted volume `%s': %s"),
lastsubdev, grub_errmsg);
+ if (strncmp (uuid, "CRYPT-LUKS2-", sizeof ("CRYPT-LUKS2-") - 1) == 0)
+ {
+ /* set LUKS2 cipher from dm parameters, since it is not
+ * possible to determine the correct one without
+ * unlocking, as there might be multiple segments.
+ */
+ grub_disk_t source;
+ grub_cryptodisk_t cryptodisk;
+ grub_uint64_t start, length;
+ char *target_type;
+ char *params;
+ const char *name;
+ char *cipher, *cipher_mode;
+ struct dm_task *dmt;
+ char *seek_head, *c;
+ unsigned int remaining;
+
+ source = grub_disk_open (grdev);
+ cryptodisk = grub_cryptodisk_get_by_source_disk (source);
+ grub_disk_close (source);
+
+ name = dm_tree_node_get_name (node);
+
+ grub_util_info ("populating parameters of cryptomount `%s' from DM device `%s'",
+ uuid, name);
+
+ dmt = dm_task_create (DM_DEVICE_TABLE);
+ if (dmt == 0)
+ grub_util_error (_("can't create dm task DM_DEVICE_TABLE"));
+ if (dm_task_set_name (dmt, name) == 0)
+ grub_util_error (_("can't set dm task name to `%s'"), name);
+ if (dm_task_run (dmt) == 0)
+ grub_util_error (_("can't run dm task for `%s'"), name);
+ /* dm_get_next_target doesn't have any error modes, everything has
+ * been handled by dm_task_run.
+ */
+ dm_get_next_target (dmt, NULL, &start, &length,
+ &target_type, &params);
+ if (strncmp (target_type, "crypt", sizeof ("crypt")) != 0)
+ grub_util_error (_("dm target of type `%s' is not `crypt'"),
+ target_type);
+
+ /* dm target parameters for dm-crypt is
+ * <cipher> <key> <iv_offset> <device path> <offset> [<#opt_params> <opt_param1> ...]
+ */
+ c = params;
+ remaining = grub_strlen (c);
+
+ /* first, get the cipher name from the cipher */
+ if (!(seek_head = grub_memchr (c, '-', remaining)))
+ grub_util_error (_("can't get cipher from dm-crypt parameters `%s'"),
+ params);
+ cipher = grub_strndup (c, seek_head - c);
+ remaining -= seek_head - c + 1;
+ c = seek_head + 1;
+
+ /* now, the cipher mode */
+ if (!(seek_head = grub_memchr (c, ' ', remaining)))
+ grub_util_error (_("can't get cipher mode from dm-crypt parameters `%s'"),
+ params);
+ cipher_mode = grub_strndup (c, seek_head - c);
+ remaining -= seek_head - c + 1;
+ c = seek_head + 1;
+
+ err = grub_cryptodisk_setcipher (cryptodisk, cipher, cipher_mode);
+ if (err)
+ {
+ grub_util_error (_("can't set cipher of cryptodisk `%s' to `%s' with mode `%s'"),
+ uuid, cipher, cipher_mode);
+ }
+
+ grub_free (cipher);
+ grub_free (cipher_mode);
+
+ /* This is the only hash usable by PBKDF2, and we don't
+ * have Argon2 support yet, so set it by default,
+ * otherwise grub-probe would miss the required
+ * abstraction
+ */
+ cryptodisk->hash = grub_crypto_lookup_md_by_name ("sha256");
+ if (cryptodisk->hash == 0)
+ {
+ grub_util_error (_("can't lookup hash sha256 by name"));
+ }
+
+ dm_task_destroy (dmt);
+ }
}
+ dm_tree_free (tree);
grub_free (grdev);
}
else

View File

@ -0,0 +1,73 @@
From 6c7c4007ad621029295797b439158d36d0f62487 Mon Sep 17 00:00:00 2001
From: Diego Domingos <diegodo@linux.vnet.ibm.com>
Date: Thu, 25 Aug 2022 11:37:56 -0400
Subject: [PATCH 2/2] ieee1275: implement vec5 for cas negotiation
As a legacy support, if the vector 5 is not implemented, Power
Hypervisor will consider the max CPUs as 64 instead 256 currently
supported during client-architecture-support negotiation.
This patch implements the vector 5 and set the MAX CPUs to 256 while
setting the others values to 0 (default).
Signed-off-by: Diego Domingos <diegodo@linux.vnet.ibm.com>
Signed-off-by: Robbie Harwood <rharwood@redhat.com>
---
grub-core/kern/ieee1275/init.c | 20 +++++++++++++++++++-
1 file changed, 19 insertions(+), 1 deletion(-)
diff --git a/grub-core/kern/ieee1275/init.c b/grub-core/kern/ieee1275/init.c
index 7d7178d3e..3aa40313f 100644
--- a/grub-core/kern/ieee1275/init.c
+++ b/grub-core/kern/ieee1275/init.c
@@ -311,6 +311,18 @@ struct option_vector2 {
grub_uint8_t max_pft_size;
} __attribute__((packed));
+struct option_vector5 {
+ grub_uint8_t byte1;
+ grub_uint8_t byte2;
+ grub_uint8_t byte3;
+ grub_uint8_t cmo;
+ grub_uint8_t associativity;
+ grub_uint8_t bin_opts;
+ grub_uint8_t micro_checkpoint;
+ grub_uint8_t reserved0;
+ grub_uint32_t max_cpus;
+} __attribute__((packed));
+
struct pvr_entry {
grub_uint32_t mask;
grub_uint32_t entry;
@@ -329,6 +341,8 @@ struct cas_vector {
grub_uint16_t vec3;
grub_uint8_t vec4_size;
grub_uint16_t vec4;
+ grub_uint8_t vec5_size;
+ struct option_vector5 vec5;
} __attribute__((packed));
/* Call ibm,client-architecture-support to try to get more RMA.
@@ -349,7 +363,7 @@ grub_ieee1275_ibm_cas (void)
} args;
struct cas_vector vector = {
.pvr_list = { { 0x00000000, 0xffffffff } }, /* any processor */
- .num_vecs = 4 - 1,
+ .num_vecs = 5 - 1,
.vec1_size = 0,
.vec1 = 0x80, /* ignore */
.vec2_size = 1 + sizeof(struct option_vector2) - 2,
@@ -360,6 +374,10 @@ grub_ieee1275_ibm_cas (void)
.vec3 = 0x00e0, // ask for FP + VMX + DFP but don't halt if unsatisfied
.vec4_size = 2 - 1,
.vec4 = 0x0001, // set required minimum capacity % to the lowest value
+ .vec5_size = 1 + sizeof(struct option_vector5) - 2,
+ .vec5 = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 256
+ }
};
INIT_IEEE1275_COMMON (&args.common, "call-method", 3, 2);
--
2.35.3

View File

@ -0,0 +1,373 @@
From 9e61624db77e5073961126457f599bc70e877fd1 Mon Sep 17 00:00:00 2001
From: Diego Domingos <diegodo@br.ibm.com>
Date: Tue, 15 Mar 2022 15:59:41 -0400
Subject: [PATCH 2/4] ieee1275/ofpath: enable NVMeoF logical device translation
This patch add code to enable the translation of logical devices to the of NVMeoFC paths.
---
grub-core/osdep/linux/ofpath.c | 260 +++++++++++++++++++++++++++++++--
include/grub/util/ofpath.h | 29 ++++
2 files changed, 280 insertions(+), 9 deletions(-)
diff --git a/grub-core/osdep/linux/ofpath.c b/grub-core/osdep/linux/ofpath.c
index 89beceef4..212782d3f 100644
--- a/grub-core/osdep/linux/ofpath.c
+++ b/grub-core/osdep/linux/ofpath.c
@@ -137,7 +137,7 @@ trim_newline (char *path)
*end-- = '\0';
}
-#define MAX_DISK_CAT 64
+#define MAX_DISK_CAT 512
static char *
find_obppath (const char *sysfs_path_orig)
@@ -313,6 +313,69 @@ get_basename(char *p)
return ret;
}
+
+void
+add_filename_to_pile(char *filename, struct ofpath_files_list_root* root){
+ struct ofpath_files_list_node* file;
+
+ file = malloc(sizeof(struct ofpath_files_list_node));
+
+ file->filename = filename;
+
+ if(root->first == NULL){
+ root->items = 1;
+ root->first = file;
+ file->next = NULL;
+ } else {
+ root->items++;
+ file->next = root->first;
+ root->first = file;
+ }
+}
+
+
+void
+find_file(char* filename, char* directory, struct ofpath_files_list_root* root, int max_depth, int depth){
+ struct dirent *ep;
+ struct stat statbuf;
+ DIR *dp;
+
+ if(depth > max_depth){
+ return;
+ }
+
+ if((dp = opendir(directory)) == NULL){
+
+ return;
+ }
+
+ while((ep = readdir(dp)) != NULL){
+
+ char* full_path = malloc(1024*sizeof(char));
+ snprintf(full_path,1024,"%s/%s",directory,ep->d_name);
+
+ lstat(full_path,&statbuf);
+
+ if(S_ISLNK(statbuf.st_mode)){
+
+ continue;
+ }
+
+ if(!strcmp(ep->d_name,".") || !strcmp(ep->d_name,"..")){
+ continue;
+ }
+
+ if(!strcmp(ep->d_name,filename)){
+ add_filename_to_pile(full_path, root);
+ }
+
+ find_file(filename, full_path, root, max_depth, depth+1);
+
+ }
+ closedir(dp);
+}
+
+
static char *
of_path_of_vdisk(const char *sys_devname __attribute__((unused)),
const char *device,
@@ -351,7 +414,142 @@ of_path_of_ide(const char *sys_devname __attribute__((unused)), const char *devi
return ret;
}
-#ifdef __sparc__
+char*
+of_find_fc_host(char* host_wwpn){
+
+ FILE* fp;
+ char *buf;
+ char portname_filename[sizeof("port_name")] = "port_name";
+ char devices_path[sizeof("/sys/devices")] = "/sys/devices";
+
+ struct ofpath_files_list_root* portnames_file_list;
+
+ portnames_file_list=malloc(sizeof(portnames_file_list));
+ portnames_file_list->items=0;
+ portnames_file_list->first=NULL;
+
+ find_file(portname_filename, devices_path, portnames_file_list, 10, 0);
+
+ struct ofpath_files_list_node* node = portnames_file_list->first;
+ while(node != NULL){
+ fp = fopen(node->filename,"r");
+ buf = malloc(sizeof(char)*512);
+ fscanf(fp, "%s", buf);
+ fclose(fp);
+ if((strcmp(buf,host_wwpn) == 0) && grub_strstr(node->filename, "fc_host")){
+ return node->filename;
+ }
+ node = node->next;
+ }
+
+ return NULL;
+}
+
+void
+of_path_get_nvmeof_adapter_info(char* sysfs_path,
+ struct ofpath_nvmeof_info* nvmeof_info){
+
+ FILE *fp;
+ char *buf, *buf2, *buf3;
+
+ nvmeof_info->host_wwpn = malloc(sizeof(char)*256);
+ nvmeof_info->target_wwpn = malloc(sizeof(char)*256);
+ nvmeof_info->nqn = malloc(sizeof(char)*256);
+
+ buf = malloc(sizeof(char)*512);
+ snprintf(buf,512,"%s/subsysnqn",sysfs_path);
+ fp = fopen(buf,"r");
+ fscanf(fp, "%s", nvmeof_info->nqn);
+ fclose(fp);
+
+ snprintf(buf,512,"%s/cntlid",sysfs_path);
+ fp = fopen(buf,"r");
+ fscanf(fp, "%u", &(nvmeof_info->cntlid));
+ fclose(fp);
+
+ //snprintf(buf,512,"%s/nsid",sysfs_path);
+ //fp = fopen(buf,"r");
+ //fscanf(fp, "%u", &(nvmeof_info->nsid));
+ //fclose(fp);
+
+ snprintf(buf,512,"%s/address",sysfs_path);
+ fp = fopen(buf,"r");
+ buf2 = malloc(sizeof(char)*512);
+ fscanf(fp, "%s", buf2);
+ fclose(fp);
+
+ nvmeof_info->host_wwpn = strrchr(buf2,'-')+1;
+
+ buf3=strchr(buf2,'-')+1;
+ buf3=strchr(buf3,'-')+1;
+ nvmeof_info->target_wwpn = buf3;
+ buf3 = strchr(nvmeof_info->target_wwpn,',');
+ *buf3 = '\0';
+
+
+ free(buf);
+
+ return;
+}
+
+#define MAX_NVME_NSID_DIGITS 6
+
+static char *
+of_path_get_nvme_controller_name_node(const char* devname)
+{
+ char *controller_node, *end;
+
+ controller_node = strdup(devname);
+
+ end = grub_strchr(controller_node+1, 'n');
+
+ if(end != NULL){
+ *end = '\0';
+ }
+
+ return controller_node;
+}
+
+unsigned int
+of_path_get_nvme_nsid(const char* devname)
+{
+ unsigned int nsid;
+ char *sysfs_path, *buf;
+ FILE *fp;
+
+ buf=malloc(sizeof(char)*512);
+
+ sysfs_path = block_device_get_sysfs_path_and_link (devname);
+
+ snprintf(buf,512,"%s/%s/nsid",sysfs_path,devname);
+ fp = fopen(buf,"r");
+ fscanf(fp, "%u", &(nsid));
+ fclose(fp);
+
+ free(sysfs_path);
+ free(buf);
+
+ return nsid;
+
+}
+
+static char *
+nvme_get_syspath(const char *nvmedev)
+{
+ char *sysfs_path, *controller_node;
+ sysfs_path = block_device_get_sysfs_path_and_link (nvmedev);
+
+ if(strstr(sysfs_path,"nvme-subsystem")){
+ controller_node = of_path_get_nvme_controller_name_node(nvmedev);
+ strcat(sysfs_path,"/");
+ strcat(sysfs_path,controller_node);
+ sysfs_path = xrealpath(sysfs_path);
+ }
+
+ return sysfs_path;
+}
+
+
static char *
of_path_of_nvme(const char *sys_devname __attribute__((unused)),
const char *device,
@@ -360,6 +558,7 @@ of_path_of_nvme(const char *sys_devname __attribute__((unused)),
{
char *sysfs_path, *of_path, disk[MAX_DISK_CAT];
const char *digit_string, *part_end;
+ int chars_written;
digit_string = trailing_digits (device);
part_end = devicenode + strlen (devicenode) - 1;
@@ -379,15 +578,61 @@ of_path_of_nvme(const char *sys_devname __attribute__((unused)),
/* Remove the p. */
*end = '\0';
sscanf (digit_string, "%d", &part);
- snprintf (disk, sizeof (disk), "/disk@1:%c", 'a' + (part - 1));
- sysfs_path = block_device_get_sysfs_path_and_link (nvmedev);
+
+ sysfs_path = nvme_get_syspath(nvmedev);
+
+ /* If is a NVMeoF */
+ if(strstr(sysfs_path,"nvme-fabrics")){
+ struct ofpath_nvmeof_info* nvmeof_info;
+ nvmeof_info = malloc(sizeof(nvmeof_info));
+
+ of_path_get_nvmeof_adapter_info(sysfs_path, nvmeof_info);
+
+ sysfs_path = of_find_fc_host(nvmeof_info->host_wwpn);
+
+ chars_written = snprintf(disk,sizeof(disk),"/nvme-of/controller@%s,%x:nqn=%s",
+ nvmeof_info->target_wwpn,
+ 0xffff,
+ nvmeof_info->nqn);
+
+ unsigned int nsid = of_path_get_nvme_nsid(nvmedev);
+
+ if(nsid){
+ snprintf(disk+chars_written,sizeof(disk) - chars_written,
+ "/namespace@%x:%d",nsid, part);
+ }
+
+ } else {
+ snprintf (disk, sizeof (disk), "/disk@1:%c", 'a' + (part - 1));
+ }
free (nvmedev);
}
else
{
/* We do not have the parition. */
- snprintf (disk, sizeof (disk), "/disk@1");
- sysfs_path = block_device_get_sysfs_path_and_link (device);
+ sysfs_path = nvme_get_syspath (device);
+ if(strstr(sysfs_path,"nvme-fabrics")){
+ struct ofpath_nvmeof_info* nvmeof_info;
+ nvmeof_info = malloc(sizeof(nvmeof_info));
+
+ of_path_get_nvmeof_adapter_info(sysfs_path, nvmeof_info);
+
+ sysfs_path = of_find_fc_host(nvmeof_info->host_wwpn);
+
+ chars_written = snprintf(disk,sizeof(disk),"/nvme-of/controller@%s,%x:nqn=%s",
+ nvmeof_info->target_wwpn,
+ 0xffff,
+ nvmeof_info->nqn);
+
+ unsigned int nsid = of_path_get_nvme_nsid(device);
+ if(nsid){
+ snprintf(disk+chars_written,sizeof(disk) - chars_written,
+ "/namespace@%x",nsid);
+ }
+ } else {
+ snprintf (disk, sizeof (disk), "/disk@1");
+ }
+
}
of_path = find_obppath (sysfs_path);
@@ -398,7 +643,6 @@ of_path_of_nvme(const char *sys_devname __attribute__((unused)),
free (sysfs_path);
return of_path;
}
-#endif
static void
of_fc_port_name(const char *path, const char *subpath, char *port_name)
@@ -840,11 +1084,9 @@ grub_util_devname_to_ofpath (const char *sys_devname)
/* All the models I've seen have a devalias "floppy".
New models have no floppy at all. */
ofpath = xstrdup ("floppy");
-#ifdef __sparc__
else if (device[0] == 'n' && device[1] == 'v' && device[2] == 'm'
&& device[3] == 'e')
ofpath = of_path_of_nvme (name_buf, device, devnode, devicenode);
-#endif
else
{
grub_util_warn (_("unknown device type %s"), device);
diff --git a/include/grub/util/ofpath.h b/include/grub/util/ofpath.h
index b43c523cb..a0ec30620 100644
--- a/include/grub/util/ofpath.h
+++ b/include/grub/util/ofpath.h
@@ -3,4 +3,33 @@
char *grub_util_devname_to_ofpath (const char *devname);
+struct ofpath_files_list_node {
+ char* filename;
+ struct ofpath_files_list_node* next;
+};
+
+struct ofpath_files_list_root {
+ int items;
+ struct ofpath_files_list_node* first;
+};
+
+struct ofpath_nvmeof_info {
+ char* host_wwpn;
+ char* target_wwpn;
+ char* nqn;
+ int cntlid;
+ int nsid;
+};
+
+void of_path_get_nvmeof_adapter_info(char* sysfs_path,
+ struct ofpath_nvmeof_info* nvmeof_info);
+
+unsigned int of_path_get_nvme_nsid(const char* devname);
+
+void add_filename_to_pile(char *filename, struct ofpath_files_list_root* root);
+
+void find_file(char* filename, char* directory, struct ofpath_files_list_root* root, int max_depth, int depth);
+
+char* of_find_fc_host(char* host_wwpn);
+
#endif /* ! GRUB_OFPATH_MACHINE_UTIL_HEADER */
--
2.35.3

View File

@ -0,0 +1,106 @@
From 834cb2ca9ed2d9d7a6926e598accdfe280b615da Mon Sep 17 00:00:00 2001
From: Patrick Steinhardt <ps@pks.im>
Date: Thu, 21 Apr 2022 15:24:19 +1000
Subject: [PATCH 2/5] kern/efi/mm: Always request a fixed number of pages on
init
When initializing the EFI memory subsystem, we will by default request
a quarter of the available memory, bounded by a minimum/maximum value.
Given that we're about to extend the EFI memory system to dynamically
request additional pages from the firmware as required, this scaling of
requested memory based on available memory will not make a lot of sense
anymore.
Remove this logic as a preparatory patch such that we'll instead defer
to the runtime memory allocator. Note that ideally, we'd want to change
this after dynamic requesting of pages has been implemented for the EFI
platform. But because we'll need to split up initialization of the
memory subsystem and the request of pages from the firmware, we'd have
to duplicate quite some logic at first only to remove it afterwards
again. This seems quite pointless, so we instead have patches slightly
out of order.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Daniel Axtens <dja@axtens.net>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
Tested-by: Patrick Steinhardt <ps@pks.im>
---
grub-core/kern/efi/mm.c | 35 +++--------------------------------
1 file changed, 3 insertions(+), 32 deletions(-)
diff --git a/grub-core/kern/efi/mm.c b/grub-core/kern/efi/mm.c
index 67a691d..2874522 100644
--- a/grub-core/kern/efi/mm.c
+++ b/grub-core/kern/efi/mm.c
@@ -38,9 +38,8 @@
a multiplier of 4KB. */
#define MEMORY_MAP_SIZE 0x3000
-/* The minimum and maximum heap size for GRUB itself. */
-#define MIN_HEAP_SIZE 0x100000
-#define MAX_HEAP_SIZE (1600 * 0x100000)
+/* The default heap size for GRUB itself in bytes. */
+#define DEFAULT_HEAP_SIZE 0x100000
static void *finish_mmap_buf = 0;
static grub_efi_uintn_t finish_mmap_size = 0;
@@ -514,23 +513,6 @@ filter_memory_map (grub_efi_memory_descriptor_t *memory_map,
return filtered_desc;
}
-/* Return the total number of pages. */
-static grub_efi_uint64_t
-get_total_pages (grub_efi_memory_descriptor_t *memory_map,
- grub_efi_uintn_t desc_size,
- grub_efi_memory_descriptor_t *memory_map_end)
-{
- grub_efi_memory_descriptor_t *desc;
- grub_efi_uint64_t total = 0;
-
- for (desc = memory_map;
- desc < memory_map_end;
- desc = NEXT_MEMORY_DESCRIPTOR (desc, desc_size))
- total += desc->num_pages;
-
- return total;
-}
-
/* Add memory regions. */
static void
add_memory_regions (grub_efi_memory_descriptor_t *memory_map,
@@ -619,8 +601,6 @@ grub_efi_mm_init (void)
grub_efi_memory_descriptor_t *filtered_memory_map_end;
grub_efi_uintn_t map_size;
grub_efi_uintn_t desc_size;
- grub_efi_uint64_t total_pages;
- grub_efi_uint64_t required_pages;
int mm_status;
/* Prepare a memory region to store two memory maps. */
@@ -660,22 +640,13 @@ grub_efi_mm_init (void)
filtered_memory_map_end = filter_memory_map (memory_map, filtered_memory_map,
desc_size, memory_map_end);
- /* By default, request a quarter of the available memory. */
- total_pages = get_total_pages (filtered_memory_map, desc_size,
- filtered_memory_map_end);
- required_pages = (total_pages >> 2);
- if (required_pages < BYTES_TO_PAGES (MIN_HEAP_SIZE))
- required_pages = BYTES_TO_PAGES (MIN_HEAP_SIZE);
- else if (required_pages > BYTES_TO_PAGES (MAX_HEAP_SIZE))
- required_pages = BYTES_TO_PAGES (MAX_HEAP_SIZE);
-
/* Sort the filtered descriptors, so that GRUB can allocate pages
from smaller regions. */
sort_memory_map (filtered_memory_map, desc_size, filtered_memory_map_end);
/* Allocate memory regions for GRUB's memory management. */
add_memory_regions (filtered_memory_map, desc_size,
- filtered_memory_map_end, required_pages);
+ filtered_memory_map_end, BYTES_TO_PAGES (DEFAULT_HEAP_SIZE));
#if 0
/* For debug. */
--
2.35.3

View File

@ -0,0 +1,68 @@
From 4284d40799aaf5aab11c690f232ce0a191dcfbdb Mon Sep 17 00:00:00 2001
From: Gary Lin <glin@suse.com>
Date: Fri, 16 Sep 2022 10:59:55 +0800
Subject: [PATCH 2/2] mm: Defer the disk cache invalidation
When the heap memory is used up, the memory management code invalidates
the disk caches first and then requests the additional memory regioins.
Although this could minimize the memory usage, it hurts the loading time
since the disk caches may always miss.
This patch defers the disk cache invalidation to avoid the possible
delays.
Signen-off-by: Gary Lin <glin@suse.com>
---
grub-core/kern/mm.c | 22 +++++++---------------
1 file changed, 7 insertions(+), 15 deletions(-)
diff --git a/grub-core/kern/mm.c b/grub-core/kern/mm.c
index 0bd9f75..5280e8c 100644
--- a/grub-core/kern/mm.c
+++ b/grub-core/kern/mm.c
@@ -355,20 +355,6 @@ grub_memalign (grub_size_t align, grub_size_t size)
switch (count)
{
case 0:
- /* Invalidate disk caches. */
- grub_disk_cache_invalidate_all ();
- count++;
- goto again;
-
-#if 0
- case 1:
- /* Unload unneeded modules. */
- grub_dl_unload_unneeded ();
- count++;
- goto again;
-#endif
-
- case 1:
/* Request additional pages, contiguous */
count++;
@@ -378,7 +364,7 @@ grub_memalign (grub_size_t align, grub_size_t size)
/* fallthrough */
- case 2:
+ case 1:
/* Request additional pages, anything at all */
count++;
@@ -394,6 +380,12 @@ grub_memalign (grub_size_t align, grub_size_t size)
/* fallthrough */
+ case 2:
+ /* Invalidate disk caches. */
+ grub_disk_cache_invalidate_all ();
+ count++;
+ goto again;
+
default:
break;
}
--
2.35.3

View File

@ -0,0 +1,32 @@
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

@ -0,0 +1,71 @@
From 5b694a13545224c2d21afc3e94831be1bcc85770 Mon Sep 17 00:00:00 2001
From: Fabian Vogt <fvogt@suse.de>
Date: Tue, 14 Jun 2022 15:55:21 +0200
Subject: [PATCH 03/10] disk/cryptodisk: When cheatmounting, use the sector
info of the cheat device
When using grub-probe with cryptodisk, the mapped block device from the host
is used directly instead of decrypting the source device in GRUB code.
In that case, the sector size and count of the host device needs to be used.
This is especially important when using luks2, which does not assign
total_sectors and log_sector_size when scanning, but only later when the
segments in the JSON area are evaluated. With an unset log_sector_size,
grub_open_device complains.
This fixes grub-probe failing with
"error: sector sizes of 1 bytes aren't supported yet."
Signed-off-by: Fabian Vogt <fvogt@suse.de>
---
grub-core/disk/cryptodisk.c | 20 ++++++++++++++++++--
1 file changed, 18 insertions(+), 2 deletions(-)
diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
index 6d22bf871c..ae8790f10f 100644
--- a/grub-core/disk/cryptodisk.c
+++ b/grub-core/disk/cryptodisk.c
@@ -698,16 +698,31 @@ grub_cryptodisk_open (const char *name, grub_disk_t disk)
if (!dev)
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "No such device");
- disk->log_sector_size = dev->log_sector_size;
-
#ifdef GRUB_UTIL
if (dev->cheat)
{
+ grub_uint64_t cheat_dev_size;
+ unsigned int cheat_log_sector_size;
+
if (!GRUB_UTIL_FD_IS_VALID (dev->cheat_fd))
dev->cheat_fd = grub_util_fd_open (dev->cheat, GRUB_UTIL_FD_O_RDONLY);
if (!GRUB_UTIL_FD_IS_VALID (dev->cheat_fd))
return grub_error (GRUB_ERR_IO, N_("cannot open `%s': %s"),
dev->cheat, grub_util_fd_strerror ());
+
+ /* Use the sector size and count of the cheat device */
+ cheat_dev_size = grub_util_get_fd_size (dev->cheat_fd, dev->cheat, &cheat_log_sector_size);
+ if (cheat_dev_size == -1)
+ {
+ const char *errmsg = grub_util_fd_strerror ();
+ grub_util_fd_close (dev->cheat_fd);
+ dev->cheat_fd = GRUB_UTIL_FD_INVALID;
+ return grub_error (GRUB_ERR_IO, N_("failed to query size of device `%s': %s"),
+ dev->cheat, errmsg);
+ }
+
+ dev->log_sector_size = cheat_log_sector_size;
+ dev->total_sectors = cheat_dev_size >> cheat_log_sector_size;
}
#endif
@@ -721,6 +736,7 @@ grub_cryptodisk_open (const char *name, grub_disk_t disk)
}
disk->data = dev;
+ disk->log_sector_size = dev->log_sector_size;
disk->total_sectors = dev->total_sectors;
disk->max_agglomerate = GRUB_DISK_MAX_MAX_AGGLOMERATE;
disk->id = dev->id;
--
2.34.1

View File

@ -0,0 +1,260 @@
From 029c952f37dedb086c85bfb5fbc0de15cd4dbf0f Mon Sep 17 00:00:00 2001
From: Lu Ken <ken.lu@intel.com>
Date: Wed, 13 Jul 2022 10:06:12 +0800
Subject: [PATCH 3/3] efi/tpm: Add EFI_CC_MEASUREMENT_PROTOCOL support
The EFI_CC_MEASUREMENT_PROTOCOL abstracts the measurement for virtual firmware
in confidential computing environment. It is similar to the EFI_TCG2_PROTOCOL.
It was proposed by Intel and ARM and approved by UEFI organization.
It is defined in Intel GHCI specification: https://cdrdv2.intel.com/v1/dl/getContent/726790 .
The EDKII header file is available at https://github.com/tianocore/edk2/blob/master/MdePkg/Include/Protocol/CcMeasurement.h .
Signed-off-by: Lu Ken <ken.lu@intel.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
grub-core/commands/efi/tpm.c | 48 +++++++++++
include/grub/efi/cc.h | 151 +++++++++++++++++++++++++++++++++++
2 files changed, 199 insertions(+)
create mode 100644 include/grub/efi/cc.h
diff --git a/grub-core/commands/efi/tpm.c b/grub-core/commands/efi/tpm.c
index e032617d8..630fd8a82 100644
--- a/grub-core/commands/efi/tpm.c
+++ b/grub-core/commands/efi/tpm.c
@@ -22,6 +22,7 @@
#include <grub/i18n.h>
#include <grub/efi/api.h>
#include <grub/efi/efi.h>
+#include <grub/efi/cc.h>
#include <grub/efi/tpm.h>
#include <grub/tpm2/tpm2.h>
#include <grub/mm.h>
@@ -32,6 +33,7 @@ typedef TCG_PCR_EVENT grub_tpm_event_t;
static grub_efi_guid_t tpm_guid = EFI_TPM_GUID;
static grub_efi_guid_t tpm2_guid = EFI_TPM2_GUID;
+static grub_efi_guid_t cc_measurement_guid = GRUB_EFI_CC_MEASUREMENT_PROTOCOL_GUID;
static grub_efi_handle_t *grub_tpm_handle;
static grub_uint8_t grub_tpm_version;
@@ -308,6 +310,50 @@ grub_tpm2_log_event (grub_efi_handle_t tpm_handle, unsigned char *buf,
return grub_efi_log_event_status (status);
}
+static void
+grub_cc_log_event (unsigned char *buf, grub_size_t size, grub_uint8_t pcr,
+ const char *description)
+{
+ grub_efi_cc_event_t *event;
+ grub_efi_status_t status;
+ grub_efi_cc_protocol_t *cc;
+ grub_efi_cc_mr_index_t mr;
+
+ cc = grub_efi_locate_protocol (&cc_measurement_guid, NULL);
+ if (cc == NULL)
+ return;
+
+ status = efi_call_3 (cc->map_pcr_to_mr_index, cc, pcr, &mr);
+ if (status != GRUB_EFI_SUCCESS)
+ {
+ grub_efi_log_event_status (status);
+ return;
+ }
+
+ event = grub_zalloc (sizeof (grub_efi_cc_event_t) +
+ grub_strlen (description) + 1);
+ if (event == NULL)
+ {
+ grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("cannot allocate CC event buffer"));
+ return;
+ }
+
+ event->Header.HeaderSize = sizeof (grub_efi_cc_event_header_t);
+ event->Header.HeaderVersion = GRUB_EFI_CC_EVENT_HEADER_VERSION;
+ event->Header.MrIndex = mr;
+ event->Header.EventType = EV_IPL;
+ event->Size = sizeof (*event) + grub_strlen (description) + 1;
+ grub_strcpy ((char *) event->Event, description);
+
+ status = efi_call_5 (cc->hash_log_extend_event, cc, 0,
+ (grub_efi_physical_address_t)(grub_addr_t) buf,
+ (grub_efi_uint64_t) size, event);
+ grub_free (event);
+
+ if (status != GRUB_EFI_SUCCESS)
+ grub_efi_log_event_status (status);
+}
+
grub_err_t
grub_tpm_measure (unsigned char *buf, grub_size_t size, grub_uint8_t pcr,
const char *description)
@@ -315,6 +361,8 @@ grub_tpm_measure (unsigned char *buf, grub_size_t size, grub_uint8_t pcr,
grub_efi_handle_t tpm_handle;
grub_efi_uint8_t protocol_version;
+ grub_cc_log_event(buf, size, pcr, description);
+
if (!grub_tpm_handle_find (&tpm_handle, &protocol_version))
return 0;
diff --git a/include/grub/efi/cc.h b/include/grub/efi/cc.h
new file mode 100644
index 000000000..896030689
--- /dev/null
+++ b/include/grub/efi/cc.h
@@ -0,0 +1,151 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2022 Free Software Foundation, Inc.
+ *
+ * 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_EFI_CC_H
+#define GRUB_EFI_CC_H 1
+
+#include <grub/efi/api.h>
+#include <grub/efi/efi.h>
+#include <grub/err.h>
+
+#define GRUB_EFI_CC_MEASUREMENT_PROTOCOL_GUID \
+ { 0x96751a3d, 0x72f4, 0x41a6, \
+ { 0xa7, 0x94, 0xed, 0x5d, 0x0e, 0x67, 0xae, 0x6b } \
+ };
+
+struct grub_efi_cc_version
+{
+ grub_efi_uint8_t Major;
+ grub_efi_uint8_t Minor;
+};
+typedef struct grub_efi_cc_version grub_efi_cc_version_t;
+
+/* EFI_CC Type/SubType definition. */
+#define GRUB_EFI_CC_TYPE_NONE 0
+#define GRUB_EFI_CC_TYPE_SEV 1
+#define GRUB_EFI_CC_TYPE_TDX 2
+
+struct grub_efi_cc_type
+{
+ grub_efi_uint8_t Type;
+ grub_efi_uint8_t SubType;
+};
+typedef struct grub_efi_cc_type grub_efi_cc_type_t;
+
+typedef grub_efi_uint32_t grub_efi_cc_event_log_bitmap_t;
+typedef grub_efi_uint32_t grub_efi_cc_event_log_format_t;
+typedef grub_efi_uint32_t grub_efi_cc_event_algorithm_bitmap_t;
+typedef grub_efi_uint32_t grub_efi_cc_mr_index_t;
+
+/* Intel TDX measure register index. */
+#define GRUB_TDX_MR_INDEX_MRTD 0
+#define GRUB_TDX_MR_INDEX_RTMR0 1
+#define GRUB_TDX_MR_INDEX_RTMR1 2
+#define GRUB_TDX_MR_INDEX_RTMR2 3
+#define GRUB_TDX_MR_INDEX_RTMR3 4
+
+#define GRUB_EFI_CC_EVENT_LOG_FORMAT_TCG_2 0x00000002
+#define GRUB_EFI_CC_BOOT_HASH_ALG_SHA384 0x00000004
+#define GRUB_EFI_CC_EVENT_HEADER_VERSION 1
+
+struct grub_efi_cc_event_header
+{
+ /* Size of the event header itself (sizeof(EFI_TD_EVENT_HEADER)). */
+ grub_efi_uint32_t HeaderSize;
+
+ /*
+ * Header version. For this version of this specification,
+ * the value shall be 1.
+ */
+ grub_efi_uint16_t HeaderVersion;
+
+ /* Index of the MR that shall be extended. */
+ grub_efi_cc_mr_index_t MrIndex;
+
+ /* Type of the event that shall be extended (and optionally logged). */
+ grub_efi_uint32_t EventType;
+} GRUB_PACKED;
+typedef struct grub_efi_cc_event_header grub_efi_cc_event_header_t;
+
+struct grub_efi_cc_event
+{
+ /* Total size of the event including the Size component, the header and the Event data. */
+ grub_efi_uint32_t Size;
+ grub_efi_cc_event_header_t Header;
+ grub_efi_uint8_t Event[0];
+} GRUB_PACKED;
+typedef struct grub_efi_cc_event grub_efi_cc_event_t;
+
+struct grub_efi_cc_boot_service_capability
+{
+ /* Allocated size of the structure. */
+ grub_efi_uint8_t Size;
+
+ /*
+ * Version of the grub_efi_cc_boot_service_capability_t structure itself.
+ * For this version of the protocol, the Major version shall be set to 1
+ * and the Minor version shall be set to 1.
+ */
+ grub_efi_cc_version_t StructureVersion;
+
+ /*
+ * Version of the EFI TD protocol.
+ * For this version of the protocol, the Major version shall be set to 1
+ * and the Minor version shall be set to 1.
+ */
+ grub_efi_cc_version_t ProtocolVersion;
+
+ /* Supported hash algorithms. */
+ grub_efi_cc_event_algorithm_bitmap_t HashAlgorithmBitmap;
+
+ /* Bitmap of supported event log formats. */
+ grub_efi_cc_event_log_bitmap_t SupportedEventLogs;
+
+ /* Indicates the CC type. */
+ grub_efi_cc_type_t CcType;
+};
+typedef struct grub_efi_cc_boot_service_capability grub_efi_cc_boot_service_capability_t;
+
+struct grub_efi_cc_protocol
+{
+ grub_efi_status_t
+ (*get_capability) (struct grub_efi_cc_protocol *this,
+ grub_efi_cc_boot_service_capability_t *ProtocolCapability);
+
+ grub_efi_status_t
+ (*get_event_log) (struct grub_efi_cc_protocol *this,
+ grub_efi_cc_event_log_format_t EventLogFormat,
+ grub_efi_physical_address_t *EventLogLocation,
+ grub_efi_physical_address_t *EventLogLastEntry,
+ grub_efi_boolean_t *EventLogTruncated);
+
+ grub_efi_status_t
+ (*hash_log_extend_event) (struct grub_efi_cc_protocol *this,
+ grub_efi_uint64_t Flags,
+ grub_efi_physical_address_t DataToHash,
+ grub_efi_uint64_t DataToHashLen,
+ grub_efi_cc_event_t *EfiCcEvent);
+
+ grub_efi_status_t
+ (*map_pcr_to_mr_index) (struct grub_efi_cc_protocol *this,
+ grub_efi_uint32_t PcrIndex,
+ grub_efi_cc_mr_index_t *MrIndex);
+};
+typedef struct grub_efi_cc_protocol grub_efi_cc_protocol_t;
+
+#endif
--
2.35.3

View File

@ -0,0 +1,62 @@
From 1729400ab816804a28ebf50cb1310607b2c4b75e Mon Sep 17 00:00:00 2001
From: Diego Domingos <diegodo@br.ibm.com>
Date: Fri, 25 Feb 2022 12:49:51 -0500
Subject: [PATCH 3/4] ieee1275: change the logic of ieee1275_get_devargs()
Usually grub will parse the PFW arguments by searching for the first occurence of the character ':'.
However, we can have this char more than once on NQN.
This patch changes the logic to find the last occurence of this char so we can get the proper values
for NVMeoFC
---
grub-core/kern/ieee1275/openfw.c | 21 ++++++++++++++++++++-
1 file changed, 20 insertions(+), 1 deletion(-)
diff --git a/grub-core/kern/ieee1275/openfw.c b/grub-core/kern/ieee1275/openfw.c
index f819bd106..655a71310 100644
--- a/grub-core/kern/ieee1275/openfw.c
+++ b/grub-core/kern/ieee1275/openfw.c
@@ -354,6 +354,13 @@ static char *
grub_ieee1275_get_devargs (const char *path)
{
char *colon = grub_strchr (path, ':');
+ char *colon_check = colon;
+
+ /* Find the last occurence of colon */
+ while(colon_check){
+ colon = colon_check;
+ colon_check = grub_strchr (colon+1, ':');
+ }
if (! colon)
return 0;
@@ -368,6 +375,18 @@ grub_ieee1275_get_devname (const char *path)
char *colon = grub_strchr (path, ':');
int pathlen = grub_strlen (path);
struct grub_ieee1275_devalias curalias;
+
+ /* Check some special cases */
+ if(grub_strstr(path, "nvme-of")){
+ char *namespace_split = grub_strstr(path,"/namespace@");
+ if(namespace_split){
+ colon = grub_strchr (namespace_split, ':');
+ } else {
+ colon = NULL;
+ }
+
+ }
+
if (colon)
pathlen = (int)(colon - path);
@@ -693,7 +712,7 @@ grub_ieee1275_get_boot_dev (void)
return NULL;
}
- bootpath = (char *) grub_malloc ((grub_size_t) bootpath_size + 64);
+ bootpath = (char *) grub_malloc ((grub_size_t) bootpath_size + 64 + 256);
if (! bootpath)
{
grub_print_error ();
--
2.35.3

View File

@ -0,0 +1,86 @@
From b4500ff77efe3b36256fae1e456ded65fd77cf04 Mon Sep 17 00:00:00 2001
From: Patrick Steinhardt <ps@pks.im>
Date: Thu, 21 Apr 2022 15:24:20 +1000
Subject: [PATCH 3/5] kern/efi/mm: Extract function to add memory regions
In preparation of support for runtime-allocating additional memory
region, this patch extracts the function to retrieve the EFI memory
map and add a subset of it to GRUB's own memory regions.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Daniel Axtens <dja@axtens.net>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
Tested-by: Patrick Steinhardt <ps@pks.im>
---
grub-core/kern/efi/mm.c | 21 +++++++++++++++------
1 file changed, 15 insertions(+), 6 deletions(-)
diff --git a/grub-core/kern/efi/mm.c b/grub-core/kern/efi/mm.c
index 2874522..087272f 100644
--- a/grub-core/kern/efi/mm.c
+++ b/grub-core/kern/efi/mm.c
@@ -592,8 +592,8 @@ print_memory_map (grub_efi_memory_descriptor_t *memory_map,
}
#endif
-void
-grub_efi_mm_init (void)
+static grub_err_t
+grub_efi_mm_add_regions (grub_size_t required_bytes)
{
grub_efi_memory_descriptor_t *memory_map;
grub_efi_memory_descriptor_t *memory_map_end;
@@ -606,7 +606,7 @@ grub_efi_mm_init (void)
/* Prepare a memory region to store two memory maps. */
memory_map = grub_efi_allocate_any_pages (2 * BYTES_TO_PAGES (MEMORY_MAP_SIZE));
if (! memory_map)
- grub_fatal ("cannot allocate memory");
+ return grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot allocate memory for memory map");
/* Obtain descriptors for available memory. */
map_size = MEMORY_MAP_SIZE;
@@ -624,14 +624,14 @@ grub_efi_mm_init (void)
memory_map = grub_efi_allocate_any_pages (2 * BYTES_TO_PAGES (map_size));
if (! memory_map)
- grub_fatal ("cannot allocate memory");
+ return grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot allocate memory for new memory map");
mm_status = grub_efi_get_memory_map (&map_size, memory_map, 0,
&desc_size, 0);
}
if (mm_status < 0)
- grub_fatal ("cannot get memory map");
+ return grub_error (GRUB_ERR_OUT_OF_MEMORY, "error fetching memory map from EFI");
memory_map_end = NEXT_MEMORY_DESCRIPTOR (memory_map, map_size);
@@ -646,7 +646,7 @@ grub_efi_mm_init (void)
/* Allocate memory regions for GRUB's memory management. */
add_memory_regions (filtered_memory_map, desc_size,
- filtered_memory_map_end, BYTES_TO_PAGES (DEFAULT_HEAP_SIZE));
+ filtered_memory_map_end, BYTES_TO_PAGES (required_bytes));
#if 0
/* For debug. */
@@ -664,6 +664,15 @@ grub_efi_mm_init (void)
/* Release the memory maps. */
grub_efi_free_pages ((grub_addr_t) memory_map,
2 * BYTES_TO_PAGES (MEMORY_MAP_SIZE));
+
+ return GRUB_ERR_NONE;
+}
+
+void
+grub_efi_mm_init (void)
+{
+ if (grub_efi_mm_add_regions (DEFAULT_HEAP_SIZE) != GRUB_ERR_NONE)
+ grub_fatal ("%s", grub_errmsg);
}
#if defined (__aarch64__) || defined (__arm__) || defined (__riscv)
--
2.35.3

View File

@ -0,0 +1,58 @@
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

@ -0,0 +1,89 @@
From 4287786dde414d9b0517d12762904b4b2be19d2a Mon Sep 17 00:00:00 2001
From: Patrick Steinhardt <ps@pks.im>
Date: Thu, 21 Apr 2022 15:24:21 +1000
Subject: [PATCH 4/5] kern/efi/mm: Pass up errors from add_memory_regions()
The function add_memory_regions() is currently only called on system
initialization to allocate a fixed amount of pages. As such, it didn't
need to return any errors: in case it failed, we cannot proceed anyway.
This will change with the upcoming support for requesting more memory
from the firmware at runtime, where it doesn't make sense anymore to
fail hard.
Refactor the function to return an error to prepare for this. Note that
this does not change the behaviour when initializing the memory system
because grub_efi_mm_init() knows to call grub_fatal() in case
grub_efi_mm_add_regions() returns an error.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Daniel Axtens <dja@axtens.net>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
Tested-by: Patrick Steinhardt <ps@pks.im>
---
grub-core/kern/efi/mm.c | 22 +++++++++++++++-------
1 file changed, 15 insertions(+), 7 deletions(-)
diff --git a/grub-core/kern/efi/mm.c b/grub-core/kern/efi/mm.c
index 087272f..45ea6d5 100644
--- a/grub-core/kern/efi/mm.c
+++ b/grub-core/kern/efi/mm.c
@@ -514,7 +514,7 @@ filter_memory_map (grub_efi_memory_descriptor_t *memory_map,
}
/* Add memory regions. */
-static void
+static grub_err_t
add_memory_regions (grub_efi_memory_descriptor_t *memory_map,
grub_efi_uintn_t desc_size,
grub_efi_memory_descriptor_t *memory_map_end,
@@ -542,9 +542,9 @@ add_memory_regions (grub_efi_memory_descriptor_t *memory_map,
GRUB_EFI_ALLOCATE_ADDRESS,
GRUB_EFI_LOADER_CODE);
if (! addr)
- grub_fatal ("cannot allocate conventional memory %p with %u pages",
- (void *) ((grub_addr_t) start),
- (unsigned) pages);
+ return grub_error (GRUB_ERR_OUT_OF_MEMORY,
+ "Memory starting at %p (%u pages) marked as free, but EFI would not allocate",
+ (void *) ((grub_addr_t) start), (unsigned) pages);
grub_mm_init_region (addr, PAGES_TO_BYTES (pages));
@@ -554,7 +554,11 @@ add_memory_regions (grub_efi_memory_descriptor_t *memory_map,
}
if (required_pages > 0)
- grub_fatal ("too little memory");
+ return grub_error (GRUB_ERR_OUT_OF_MEMORY,
+ "could not allocate all requested memory: %" PRIuGRUB_UINT64_T " pages still required after iterating EFI memory map",
+ required_pages);
+
+ return GRUB_ERR_NONE;
}
void
@@ -601,6 +605,7 @@ grub_efi_mm_add_regions (grub_size_t required_bytes)
grub_efi_memory_descriptor_t *filtered_memory_map_end;
grub_efi_uintn_t map_size;
grub_efi_uintn_t desc_size;
+ grub_err_t err;
int mm_status;
/* Prepare a memory region to store two memory maps. */
@@ -645,8 +650,11 @@ grub_efi_mm_add_regions (grub_size_t required_bytes)
sort_memory_map (filtered_memory_map, desc_size, filtered_memory_map_end);
/* Allocate memory regions for GRUB's memory management. */
- add_memory_regions (filtered_memory_map, desc_size,
- filtered_memory_map_end, BYTES_TO_PAGES (required_bytes));
+ err = add_memory_regions (filtered_memory_map, desc_size,
+ filtered_memory_map_end,
+ BYTES_TO_PAGES (required_bytes));
+ if (err != GRUB_ERR_NONE)
+ return err;
#if 0
/* For debug. */
--
2.35.3

View File

@ -0,0 +1,93 @@
From d4eb747f831d8b011c712f4335f12b572d6f32d9 Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Fri, 28 Jan 2022 11:30:32 +0100
Subject: [PATCH 04/10] normal/menu: Don't show "Booting `%s'" msg when
auto-booting with TIMEOUT_STYLE_HIDDEN
When the user has asked the menu code to be hidden/quiet and the current
entry is being autobooted because the timeout has expired don't show
the "Booting `%s'" msg.
This is necessary to let flicker-free boots really be flicker free,
otherwise the "Booting `%s'" msg will kick the EFI fb into text mode
and show the msg, breaking the flicker-free experience.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
grub-core/normal/menu.c | 24 ++++++++++++++++--------
1 file changed, 16 insertions(+), 8 deletions(-)
diff --git a/grub-core/normal/menu.c b/grub-core/normal/menu.c
index 47fc12551f..470bfc839b 100644
--- a/grub-core/normal/menu.c
+++ b/grub-core/normal/menu.c
@@ -651,13 +651,15 @@ workaround_snapshot_menu_default_entry (grub_menu_t menu, const char *name, int
entry to be executed is a result of an automatic default selection because
of the timeout. */
static int
-run_menu (grub_menu_t menu, int nested, int *auto_boot)
+run_menu (grub_menu_t menu, int nested, int *auto_boot, int *notify_boot)
{
grub_uint64_t saved_time;
int default_entry, current_entry;
int timeout;
enum timeout_style timeout_style;
+ *notify_boot = 1;
+
default_entry = get_entry_number (menu, "default");
workaround_snapshot_menu_default_entry (menu, "default", &default_entry);
@@ -734,6 +736,7 @@ run_menu (grub_menu_t menu, int nested, int *auto_boot)
if (timeout == 0)
{
*auto_boot = 1;
+ *notify_boot = timeout_style != TIMEOUT_STYLE_HIDDEN;
return default_entry;
}
@@ -894,12 +897,16 @@ run_menu (grub_menu_t menu, int nested, int *auto_boot)
/* Callback invoked immediately before a menu entry is executed. */
static void
-notify_booting (grub_menu_entry_t entry,
- void *userdata __attribute__((unused)))
+notify_booting (grub_menu_entry_t entry, void *userdata)
{
- grub_printf (" ");
- grub_printf_ (N_("Booting `%s'"), entry->title);
- grub_printf ("\n\n");
+ int *notify_boot = userdata;
+
+ if (*notify_boot)
+ {
+ grub_printf (" ");
+ grub_printf_ (N_("Booting `%s'"), entry->title);
+ grub_printf ("\n\n");
+ }
}
/* Callback invoked when a default menu entry executed because of a timeout
@@ -947,8 +954,9 @@ show_menu (grub_menu_t menu, int nested, int autobooted)
int boot_entry;
grub_menu_entry_t e;
int auto_boot;
+ int notify_boot;
- boot_entry = run_menu (menu, nested, &auto_boot);
+ boot_entry = run_menu (menu, nested, &auto_boot, &notify_boot);
if (boot_entry < 0)
break;
@@ -960,7 +968,7 @@ show_menu (grub_menu_t menu, int nested, int autobooted)
if (auto_boot)
grub_menu_execute_with_fallback (menu, e, autobooted,
- &execution_callback, 0);
+ &execution_callback, &notify_boot);
else
grub_menu_execute_entry (e, 0);
if (autobooted)
--
2.34.1

View File

@ -0,0 +1,28 @@
From 7717cd9c27f18703287403af1a955588e3d0261f Mon Sep 17 00:00:00 2001
From: mamatha <mainamdar@in.ibm.com>
Date: Sat, 24 Sep 2022 11:22:39 +0530
Subject: [PATCH 4/4] ofpath controller name update
patch to update ofpath controller name
Signed-off-by: mamatha <mainamdar@in.ibm.com>
---
grub-core/osdep/linux/ofpath.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/grub-core/osdep/linux/ofpath.c b/grub-core/osdep/linux/ofpath.c
index 212782d3f..7d31cfd0f 100644
--- a/grub-core/osdep/linux/ofpath.c
+++ b/grub-core/osdep/linux/ofpath.c
@@ -483,6 +483,8 @@ of_path_get_nvmeof_adapter_info(char* sysfs_path,
buf3=strchr(buf2,'-')+1;
buf3=strchr(buf3,'-')+1;
nvmeof_info->target_wwpn = buf3;
+ buf3=strchr(buf3,'x')+1;
+ nvmeof_info->target_wwpn = buf3;
buf3 = strchr(nvmeof_info->target_wwpn,',');
*buf3 = '\0';
--
2.35.3

View File

@ -0,0 +1,45 @@
From d9c7bfe88ce7391618192401c426c218d2a17795 Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Fri, 28 Jan 2022 11:30:33 +0100
Subject: [PATCH 05/10] EFI: suppress the "Welcome to GRUB!" message in EFI
builds
Grub EFI builds are now often used in combination with flicker-free
boot, but this breaks with upstream grub because the "Welcome to GRUB!"
message will kick the EFI fb into text mode and show the msg,
breaking the flicker-free experience.
EFI systems are so fast, that when the menu or the countdown are enabled
the message will be immediately overwritten, so in these cases not
printing the message does not matter.
And in case when the timeout_style is set to TIMEOUT_STYLE_HIDDEN,
the user has asked grub to be quiet (for example to allow flickfree
boot) annd thus the message should not be printed.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
grub-core/kern/main.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/grub-core/kern/main.c b/grub-core/kern/main.c
index 42ea96e39e..35dee404e8 100644
--- a/grub-core/kern/main.c
+++ b/grub-core/kern/main.c
@@ -272,10 +272,13 @@ grub_main (void)
grub_boot_time ("After machine init.");
+ /* This breaks flicker-free boot on EFI systems, so disable it there. */
+#ifndef GRUB_MACHINE_EFI
/* Hello. */
grub_setcolorstate (GRUB_TERM_COLOR_HIGHLIGHT);
grub_printf ("Welcome to GRUB!\n\n");
grub_setcolorstate (GRUB_TERM_COLOR_STANDARD);
+#endif
#ifndef GRUB_MACHINE_PCBIOS
/* Init verifiers API. */
--
2.34.1

View File

@ -0,0 +1,31 @@
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

@ -0,0 +1,77 @@
From 3a2119e11b9c216f3b008a2c61aca52b91ad7547 Mon Sep 17 00:00:00 2001
From: Patrick Steinhardt <ps@pks.im>
Date: Thu, 21 Apr 2022 15:24:22 +1000
Subject: [PATCH 5/5] kern/efi/mm: Implement runtime addition of pages
Adjust the interface of grub_efi_mm_add_regions() to take a set of
GRUB_MM_ADD_REGION_* flags, which most notably is currently only the
GRUB_MM_ADD_REGION_CONSECUTIVE flag. This allows us to set the function
up as callback for the memory subsystem and have it call out to us in
case there's not enough pages available in the current heap.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Daniel Axtens <dja@axtens.net>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
Tested-by: Patrick Steinhardt <ps@pks.im>
---
grub-core/kern/efi/mm.c | 15 +++++++++++----
1 file changed, 11 insertions(+), 4 deletions(-)
diff --git a/grub-core/kern/efi/mm.c b/grub-core/kern/efi/mm.c
index 45ea6d5..48380d3 100644
--- a/grub-core/kern/efi/mm.c
+++ b/grub-core/kern/efi/mm.c
@@ -518,7 +518,8 @@ static grub_err_t
add_memory_regions (grub_efi_memory_descriptor_t *memory_map,
grub_efi_uintn_t desc_size,
grub_efi_memory_descriptor_t *memory_map_end,
- grub_efi_uint64_t required_pages)
+ grub_efi_uint64_t required_pages,
+ unsigned int flags)
{
grub_efi_memory_descriptor_t *desc;
@@ -532,6 +533,10 @@ add_memory_regions (grub_efi_memory_descriptor_t *memory_map,
start = desc->physical_start;
pages = desc->num_pages;
+
+ if (pages < required_pages && (flags & GRUB_MM_ADD_REGION_CONSECUTIVE))
+ continue;
+
if (pages > required_pages)
{
start += PAGES_TO_BYTES (pages - required_pages);
@@ -597,7 +602,7 @@ print_memory_map (grub_efi_memory_descriptor_t *memory_map,
#endif
static grub_err_t
-grub_efi_mm_add_regions (grub_size_t required_bytes)
+grub_efi_mm_add_regions (grub_size_t required_bytes, unsigned int flags)
{
grub_efi_memory_descriptor_t *memory_map;
grub_efi_memory_descriptor_t *memory_map_end;
@@ -652,7 +657,8 @@ grub_efi_mm_add_regions (grub_size_t required_bytes)
/* Allocate memory regions for GRUB's memory management. */
err = add_memory_regions (filtered_memory_map, desc_size,
filtered_memory_map_end,
- BYTES_TO_PAGES (required_bytes));
+ BYTES_TO_PAGES (required_bytes),
+ flags);
if (err != GRUB_ERR_NONE)
return err;
@@ -679,8 +685,9 @@ grub_efi_mm_add_regions (grub_size_t required_bytes)
void
grub_efi_mm_init (void)
{
- if (grub_efi_mm_add_regions (DEFAULT_HEAP_SIZE) != GRUB_ERR_NONE)
+ if (grub_efi_mm_add_regions (DEFAULT_HEAP_SIZE, GRUB_MM_ADD_REGION_NONE) != GRUB_ERR_NONE)
grub_fatal ("%s", grub_errmsg);
+ grub_mm_add_region_fn = grub_efi_mm_add_regions;
}
#if defined (__aarch64__) || defined (__arm__) || defined (__riscv)
--
2.35.3

View File

@ -0,0 +1,54 @@
From 81339347bc10ec609227361434f75c5e36b85b9f Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Fri, 28 Jan 2022 12:43:48 +0100
Subject: [PATCH 06/10] EFI: console: Do not set colorstate until the first
text output
GRUB_MOD_INIT(normal) does an unconditional:
grub_env_set ("color_normal", "light-gray/black");
which triggers a grub_term_setcolorstate() call. The original version
of the "efi/console: Do not set text-mode until we actually need it" patch:
https://lists.gnu.org/archive/html/grub-devel/2018-03/msg00125.html
Protected against this by caching the requested state in
grub_console_setcolorstate () and then only applying it when the first
text output actually happens. During refactoring to move the
grub_console_setcolorstate () up higher in the grub-core/term/efi/console.c
file the code to cache the color-state + bail early was accidentally
dropped.
Restore the cache the color-state + bail early behavior from the original.
Cc: Javier Martinez Canillas <javierm@redhat.com>
Fixes: 2d7c3abd871f ("efi/console: Do not set text-mode until we actually need it")
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
grub-core/term/efi/console.c | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/grub-core/term/efi/console.c b/grub-core/term/efi/console.c
index 2f1ae85ba7..c44b2ac318 100644
--- a/grub-core/term/efi/console.c
+++ b/grub-core/term/efi/console.c
@@ -82,6 +82,16 @@ grub_console_setcolorstate (struct grub_term_output *term
{
grub_efi_simple_text_output_interface_t *o;
+ if (grub_efi_is_finished || text_mode != GRUB_TEXT_MODE_AVAILABLE)
+ {
+ /*
+ * Cache colorstate changes before the first text-output, this avoids
+ * "color_normal" environment writes causing a switch to textmode.
+ */
+ text_colorstate = state;
+ return;
+ }
+
if (grub_efi_is_finished)
return;
--
2.34.1

View File

@ -0,0 +1,252 @@
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

@ -0,0 +1,75 @@
From 9b12dc80d4254e22c41805cecf2494a8e6a50e3e Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Fri, 28 Jan 2022 12:43:49 +0100
Subject: [PATCH 07/10] EFI: console: Do not set cursor until the first text
output
To allow flickerfree boot the EFI console code does not call
grub_efi_set_text_mode (1) until some text is actually output.
Depending on if the output text is because of an error loading
e.g. the .cfg file; or because of showing the menu the cursor needs
to be on or off when the first text is shown.
So far the cursor was hardcoded to being on, but this is causing
drawing artifacts + slow drawing of the menu as reported here:
https://bugzilla.redhat.com/show_bug.cgi?id=1946969
Handle the cursorstate in the same way as the colorstate to fix this,
when no text has been output yet, just cache the cursorstate and
then use the last set value when the first text is output.
Fixes: 2d7c3abd871f ("efi/console: Do not set text-mode until we actually need it")
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
grub-core/term/efi/console.c | 19 ++++++++++++++++---
1 file changed, 16 insertions(+), 3 deletions(-)
diff --git a/grub-core/term/efi/console.c b/grub-core/term/efi/console.c
index c44b2ac318..a3622e4fe5 100644
--- a/grub-core/term/efi/console.c
+++ b/grub-core/term/efi/console.c
@@ -31,7 +31,15 @@ typedef enum {
}
grub_text_mode;
+typedef enum {
+ GRUB_CURSOR_MODE_UNDEFINED = -1,
+ GRUB_CURSOR_MODE_OFF = 0,
+ GRUB_CURSUR_MODE_ON
+}
+grub_cursor_mode;
+
static grub_text_mode text_mode = GRUB_TEXT_MODE_UNDEFINED;
+static grub_cursor_mode cursor_mode = GRUB_CURSOR_MODE_UNDEFINED;
static grub_term_color_state text_colorstate = GRUB_TERM_COLOR_UNDEFINED;
static grub_uint32_t
@@ -119,8 +127,12 @@ grub_console_setcursor (struct grub_term_output *term __attribute__ ((unused)),
{
grub_efi_simple_text_output_interface_t *o;
- if (grub_efi_is_finished)
- return;
+ if (grub_efi_is_finished || text_mode != GRUB_TEXT_MODE_AVAILABLE)
+ {
+ /* Cache cursor changes before the first text-output */
+ cursor_mode = on;
+ return;
+ }
o = grub_efi_system_table->con_out;
efi_call_2 (o->enable_cursor, o, on);
@@ -143,7 +155,8 @@ grub_prepare_for_text_output (struct grub_term_output *term)
return GRUB_ERR_BAD_DEVICE;
}
- grub_console_setcursor (term, 1);
+ if (cursor_mode != GRUB_CURSOR_MODE_UNDEFINED)
+ grub_console_setcursor (term, cursor_mode);
if (text_colorstate != GRUB_TERM_COLOR_UNDEFINED)
grub_console_setcolorstate (term, text_colorstate);
text_mode = GRUB_TEXT_MODE_AVAILABLE;
--
2.34.1

View File

@ -0,0 +1,342 @@
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

@ -0,0 +1,248 @@
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

@ -0,0 +1,156 @@
From adf486860fe0d395579be8b01d4fda8b93377768 Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Wed, 8 Jun 2022 16:04:12 +0800
Subject: [PATCH 08/10] linuxefi: Use common grub_initrd_load
By using the common initrd loading routine factored out allows to share between
features like concatenating initramfs component.
For eg.
initrdefi /initrd-5.16.15-1-default newc:grub.cfg:/grub2/grub.cfg
The file /grub2/grub.cfg read off from root disk will be available to use as
/grub.cfg in the target initramfs loaded by grub.
Signed-off-by: Michael Chang <mchang@suse.com>
---
grub-core/loader/i386/efi/linux.c | 87 ++++---------------------------
1 file changed, 10 insertions(+), 77 deletions(-)
diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c
index 6b06a8f2ff..f93395fc62 100644
--- a/grub-core/loader/i386/efi/linux.c
+++ b/grub-core/loader/i386/efi/linux.c
@@ -30,6 +30,7 @@
#include <grub/cpu/efi/memory.h>
#include <grub/tpm.h>
#include <grub/safemath.h>
+#include <grub/linux.h>
GRUB_MOD_LICENSE ("GPLv3+");
@@ -146,44 +147,6 @@ grub_linuxefi_unload (void)
return GRUB_ERR_NONE;
}
-#define BOUNCE_BUFFER_MAX 0x1000000ull
-
-static grub_ssize_t
-read(grub_file_t file, grub_uint8_t *bufp, grub_size_t len)
-{
- grub_ssize_t bufpos = 0;
- static grub_size_t bbufsz = 0;
- static char *bbuf = NULL;
-
- if (bbufsz == 0)
- bbufsz = MIN(BOUNCE_BUFFER_MAX, len);
-
- while (!bbuf && bbufsz)
- {
- bbuf = grub_malloc(bbufsz);
- if (!bbuf)
- bbufsz >>= 1;
- }
- if (!bbuf)
- grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("cannot allocate bounce buffer"));
-
- while (bufpos < (long long)len)
- {
- grub_ssize_t sz;
-
- sz = grub_file_read (file, bbuf, MIN(bbufsz, len - bufpos));
- if (sz < 0)
- return sz;
- if (sz == 0)
- break;
-
- grub_memcpy(bufp + bufpos, bbuf, sz);
- bufpos += sz;
- }
-
- return bufpos;
-}
-
#define LOW_U32(val) ((grub_uint32_t)(((grub_addr_t)(val)) & 0xffffffffull))
#define HIGH_U32(val) ((grub_uint32_t)(((grub_addr_t)(val) >> 32) & 0xffffffffull))
@@ -191,10 +154,8 @@ static grub_err_t
grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
int argc, char *argv[])
{
- grub_file_t *files = 0;
- int i, nfiles = 0;
+ struct grub_linux_initrd_context initrd_ctx = { 0, 0, 0 };
grub_size_t size = 0;
- grub_uint8_t *ptr;
if (argc == 0)
{
@@ -208,24 +169,10 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
goto fail;
}
- files = grub_calloc (argc, sizeof (files[0]));
- if (!files)
+ if (grub_initrd_init (argc, argv, &initrd_ctx))
goto fail;
- for (i = 0; i < argc; i++)
- {
- files[i] = grub_file_open (argv[i], GRUB_FILE_TYPE_LINUX_INITRD
- | GRUB_FILE_TYPE_NO_DECOMPRESS);
- if (! files[i])
- goto fail;
- nfiles++;
- if (grub_add (size, ALIGN_UP (grub_file_size (files[i]), 4), &size))
- {
- grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow is detected"));
- goto fail;
- }
- }
-
+ size = grub_get_initrd_size (&initrd_ctx);
initrd_mem = kernel_alloc(size, N_("can't allocate initrd"));
if (initrd_mem == NULL)
goto fail;
@@ -238,30 +185,16 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
params->ext_ramdisk_image = HIGH_U32(initrd_mem);
#endif
- ptr = initrd_mem;
-
- for (i = 0; i < nfiles; i++)
- {
- grub_ssize_t cursize = grub_file_size (files[i]);
- if (read (files[i], ptr, cursize) != cursize)
- {
- if (!grub_errno)
- grub_error (GRUB_ERR_FILE_READ_ERROR, N_("premature end of file %s"),
- argv[i]);
- goto fail;
- }
- ptr += cursize;
- grub_memset (ptr, 0, ALIGN_UP_OVERHEAD (cursize, 4));
- ptr += ALIGN_UP_OVERHEAD (cursize, 4);
- }
+ /* FIXME: Use bounce buffers as many UEFI machines apparently can't DMA
+ * correctly above 4GB
+ */
+ if (grub_initrd_load (&initrd_ctx, argv, initrd_mem))
+ goto fail;
params->ramdisk_size = size;
fail:
- for (i = 0; i < nfiles; i++)
- grub_file_close (files[i]);
- grub_free (files);
-
+ grub_initrd_close (&initrd_ctx);
if (initrd_mem && grub_errno)
grub_efi_free_pages((grub_efi_physical_address_t)(grub_addr_t)initrd_mem, BYTES_TO_PAGES(size));
--
2.34.1

View File

@ -0,0 +1,328 @@
From 749f7dee6f63217e536663aebb817aec72a65d5a Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Thu, 9 Jun 2022 21:06:00 +0800
Subject: [PATCH 09/10] Add crypttab_entry to obviate the need to input
password twice
This patch adds crypttab_entry command to hint grub where to put the key file
automatically loaded by linux cryptsetup. It's syntax is similar to
/etc/crypttab so that it is relatively straightforward to import.
crypttab_entry <volume-name> <encrypted-device> <key-file>
For eg:
crypttab_entry cr_root 5e1dd109e39343f984da57fd742d3f23 none
Please note the "encrypted-device" only accepts UUID without dashes as it is
the only identification used by grub's cryptodisk device. The crypttab_entry
can also be used multiple times to specify encrypted volumes unlocked by
"cryptomount -a".
Signed-off-by: Michael Chang <mchang@suse.com>
---
grub-core/Makefile.core.def | 5 +
grub-core/commands/crypttab.c | 42 ++++++++++++
grub-core/disk/cryptodisk.c | 6 +
grub-core/loader/linux.c | 137 ++++++++++++++++++++++++++++++++++++++++--
include/grub/linux.h | 3
5 files changed, 188 insertions(+), 5 deletions(-)
create mode 100644 grub-core/commands/crypttab.c
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -2643,3 +2643,8 @@
cflags = '$(CFLAGS_POSIX) $(CFLAGS_GNULIB)';
cppflags = '$(CPPFLAGS_POSIX) $(CPPFLAGS_GNULIB)';
};
+
+module = {
+ name = crypttab;
+ common = commands/crypttab.c;
+};
--- /dev/null
+++ b/grub-core/commands/crypttab.c
@@ -0,0 +1,42 @@
+
+#include <grub/dl.h>
+#include <grub/command.h>
+#include <grub/misc.h>
+#include <grub/i18n.h>
+#include <grub/linux.h>
+
+GRUB_MOD_LICENSE ("GPLv3+");
+
+static grub_err_t
+grub_cmd_crypttab_entry (grub_command_t cmd __attribute__ ((unused)),
+ int argc, char **argv)
+{
+ char buf[64];
+ const char *path = argv[2];
+
+ if (argc != 3)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("three arguments expected"));
+
+ if (grub_strcmp (argv[2], "none") == 0
+ || grub_strcmp (argv[2], "-") == 0)
+ {
+ grub_snprintf (buf, sizeof (buf), "/etc/cryptsetup-keys.d/%s.key", argv[0]);
+ path = buf;
+ }
+
+ /*FIXME: Validate UUID string*/
+ return grub_initrd_publish_key (argv[1], NULL, 0, path);
+}
+
+static grub_command_t cmd;
+
+GRUB_MOD_INIT(crypttab)
+{
+ cmd = grub_register_command ("crypttab_entry", grub_cmd_crypttab_entry,
+ N_("VOLUME-NAME ENCRYPTED-DEVICE KEY-FILE") , N_("No description"));
+}
+
+GRUB_MOD_FINI(crypttab)
+{
+ grub_unregister_command (cmd);
+}
--- a/grub-core/disk/cryptodisk.c
+++ b/grub-core/disk/cryptodisk.c
@@ -30,6 +30,8 @@
#ifdef GRUB_UTIL
#include <grub/emu/hostdisk.h>
+#else
+#include <grub/linux.h>
#endif
GRUB_MOD_LICENSE ("GPLv3+");
@@ -1146,6 +1148,10 @@
dev = NULL;
cleanup:
+#ifndef GRUB_UTIL
+ if (cargs->key_data && dev)
+ grub_initrd_publish_key (dev->uuid, (const char *)cargs->key_data, cargs->key_len, NULL);
+#endif
if (askpass)
{
cargs->key_len = 0;
--- a/grub-core/loader/linux.c
+++ b/grub-core/loader/linux.c
@@ -5,6 +5,7 @@
#include <grub/file.h>
#include <grub/mm.h>
#include <grub/safemath.h>
+#include <grub/list.h>
struct newc_head
{
@@ -27,6 +28,7 @@
struct grub_linux_initrd_component
{
grub_file_t file;
+ char *buf;
char *newc_name;
grub_off_t size;
};
@@ -38,6 +40,18 @@
struct dir *child;
};
+struct grub_key_publisher
+{
+ struct grub_key_publisher *next;
+ struct grub_key_publisher **prev;
+ char *name; /* UUID */
+ char *path;
+ char *key;
+ grub_size_t key_len;
+};
+
+static struct grub_key_publisher *kpuber;
+
static char
hex (grub_uint8_t val)
{
@@ -149,6 +163,65 @@
return GRUB_ERR_NONE;
}
+static grub_err_t
+grub_initrd_component (const char *buf, int bufsz, const char *newc_name,
+ struct grub_linux_initrd_context *initrd_ctx)
+{
+ struct dir *root = 0;
+ struct grub_linux_initrd_component *comp = initrd_ctx->components + initrd_ctx->nfiles;
+ grub_size_t dir_size, name_len;
+
+ while (*newc_name == '/')
+ newc_name++;
+
+ initrd_ctx->size = ALIGN_UP (initrd_ctx->size, 4);
+ comp->newc_name = grub_strdup (newc_name);
+ if (!comp->newc_name ||
+ insert_dir (comp->newc_name, &root, 0, &dir_size))
+ {
+ /* FIXME: Check NULL file pointer before close */
+ grub_initrd_close (initrd_ctx);
+ return grub_errno;
+ }
+ /* Should name_len count terminating null ? */
+ name_len = grub_strlen (comp->newc_name) + 1;
+ if (grub_add (initrd_ctx->size,
+ ALIGN_UP (sizeof (struct newc_head) + name_len, 4),
+ &initrd_ctx->size) ||
+ grub_add (initrd_ctx->size, dir_size, &initrd_ctx->size))
+ goto overflow;
+
+ comp->buf = grub_malloc (bufsz);
+ if (!comp->buf)
+ {
+ free_dir (root);
+ grub_initrd_close (initrd_ctx);
+ return grub_errno;
+ }
+ grub_memcpy (comp->buf, buf, bufsz);
+ initrd_ctx->nfiles++;
+ comp->size = bufsz;
+ if (grub_add (initrd_ctx->size, comp->size,
+ &initrd_ctx->size))
+ goto overflow;
+
+ initrd_ctx->size = ALIGN_UP (initrd_ctx->size, 4);
+ if (grub_add (initrd_ctx->size,
+ ALIGN_UP (sizeof (struct newc_head)
+ + sizeof ("TRAILER!!!") - 1, 4),
+ &initrd_ctx->size))
+ goto overflow;
+
+ free_dir (root);
+ root = 0;
+ return GRUB_ERR_NONE;
+
+ overflow:
+ free_dir (root);
+ grub_initrd_close (initrd_ctx);
+ return grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow is detected"));
+}
+
grub_err_t
grub_initrd_init (int argc, char *argv[],
struct grub_linux_initrd_context *initrd_ctx)
@@ -156,11 +229,17 @@
int i;
int newc = 0;
struct dir *root = 0;
+ struct grub_key_publisher *pk;
+ int numkey = 0;
initrd_ctx->nfiles = 0;
initrd_ctx->components = 0;
- initrd_ctx->components = grub_calloc (argc, sizeof (initrd_ctx->components[0]));
+ FOR_LIST_ELEMENTS (pk, kpuber)
+ if (pk->key && pk->path)
+ numkey++;
+
+ initrd_ctx->components = grub_calloc (argc + numkey, sizeof (initrd_ctx->components[0]));
if (!initrd_ctx->components)
return grub_errno;
@@ -239,7 +318,10 @@
free_dir (root);
root = 0;
}
-
+
+ FOR_LIST_ELEMENTS (pk, kpuber)
+ if (pk->key && pk->path)
+ grub_initrd_component (pk->key, pk->key_len, pk->path, initrd_ctx);
return GRUB_ERR_NONE;
overflow:
@@ -263,7 +345,9 @@
for (i = 0; i < initrd_ctx->nfiles; i++)
{
grub_free (initrd_ctx->components[i].newc_name);
- grub_file_close (initrd_ctx->components[i].file);
+ if (initrd_ctx->components[i].file)
+ grub_file_close (initrd_ctx->components[i].file);
+ grub_free (initrd_ctx->components[i].buf);
}
grub_free (initrd_ctx->components);
initrd_ctx->components = 0;
@@ -297,7 +381,7 @@
}
ptr += dir_size;
ptr = make_header (ptr, initrd_ctx->components[i].newc_name,
- grub_strlen (initrd_ctx->components[i].newc_name),
+ grub_strlen (initrd_ctx->components[i].newc_name) + 1,
0100777,
initrd_ctx->components[i].size);
newc = 1;
@@ -312,7 +396,12 @@
}
cursize = initrd_ctx->components[i].size;
- if (grub_file_read (initrd_ctx->components[i].file, ptr, cursize)
+ if (initrd_ctx->components[i].buf)
+ {
+ grub_memcpy (ptr, initrd_ctx->components[i].buf, cursize);
+ newc = 1;
+ }
+ else if (grub_file_read (initrd_ctx->components[i].file, ptr, cursize)
!= cursize)
{
if (!grub_errno)
@@ -333,3 +422,41 @@
root = 0;
return GRUB_ERR_NONE;
}
+
+grub_err_t
+grub_initrd_publish_key (const char *uuid, const char *key, grub_size_t key_len, const char *path)
+{
+ struct grub_key_publisher *cur = grub_named_list_find (GRUB_AS_NAMED_LIST (kpuber), uuid);
+
+ if (!cur)
+ cur = grub_zalloc (sizeof (*cur));
+ if (!cur)
+ return grub_errno;
+
+ if (key && key_len)
+ {
+ grub_free (cur->key);
+ cur->key = grub_malloc (key_len);
+ if (!cur->key)
+ {
+ grub_free (cur);
+ return grub_errno;
+ }
+ grub_memcpy (cur->key, key, key_len);
+ cur->key_len = key_len;
+ }
+
+ if (path)
+ {
+ grub_free (cur->path);
+ cur->path = grub_strdup (path);
+ }
+
+ if (!cur->name)
+ {
+ cur->name = grub_strdup (uuid);
+ grub_list_push (GRUB_AS_LIST_P (&kpuber), GRUB_AS_LIST (cur));
+ }
+
+ return GRUB_ERR_NONE;
+}
--- a/include/grub/linux.h
+++ b/include/grub/linux.h
@@ -22,3 +22,6 @@
grub_err_t
grub_initrd_load (struct grub_linux_initrd_context *initrd_ctx,
char *argv[], void *target);
+
+grub_err_t
+grub_initrd_publish_key (const char *uuid, const char *key, grub_size_t key_len, const char *path);

View File

@ -0,0 +1,39 @@
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

@ -0,0 +1,189 @@
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

View File

@ -0,0 +1,81 @@
From 2d3130c289b293269dcf558a26674f83f77729a6 Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Tue, 14 Jun 2022 17:10:01 +0800
Subject: [PATCH 10/10] templates: import /etc/crypttab to grub.cfg
The /etc/crypptab is used to setup location of encryption key files during
boot, among other things. It is useful to make use the information by grub to
determine where keys are being looked up.
This script can be used to import relevant /etc/crypptab entry to grub.cfg.
Signed-off-by: Michael Chang <mchang@suse.com>
---
Makefile.util.def | 7 +++++++
util/grub.d/05_crypttab.in | 36 ++++++++++++++++++++++++++++++++++++
2 files changed, 43 insertions(+)
create mode 100644 util/grub.d/05_crypttab.in
diff --git a/Makefile.util.def b/Makefile.util.def
index 08f681cd8b..5e0ba22f3d 100644
--- a/Makefile.util.def
+++ b/Makefile.util.def
@@ -476,6 +476,13 @@ script = {
installdir = grubconf;
};
+script = {
+ name = '05_crypttab';
+ common = util/grub.d/05_crypttab.in;
+ installdir = grubconf;
+ condition = COND_HOST_LINUX;
+};
+
script = {
name = '10_windows';
common = util/grub.d/10_windows.in;
diff --git a/util/grub.d/05_crypttab.in b/util/grub.d/05_crypttab.in
new file mode 100644
index 0000000000..c539bc061e
--- /dev/null
+++ b/util/grub.d/05_crypttab.in
@@ -0,0 +1,36 @@
+#! /bin/sh
+set -e
+
+# grub-mkconfig helper script.
+# Copyright (C) 2022 Free Software Foundation, Inc.
+#
+# 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/>.
+
+prefix="@prefix@"
+exec_prefix="@exec_prefix@"
+datarootdir="@datarootdir@"
+
+export TEXTDOMAIN=@PACKAGE@
+export TEXTDOMAINDIR="@localedir@"
+
+. "$pkgdatadir/grub-mkconfig_lib"
+
+CRYPTTAB=/etc/crypttab
+
+if [ -r "$CRYPTTAB" ]; then
+ awk '/UUID=/ { sub(/UUID=/,"",$2); \
+ gsub(/-/,"",$2); \
+ printf("crypttab_entry %s %s %s\n",$1,$2,$3) \
+ }' "$CRYPTTAB"
+fi
--
2.34.1

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,977 @@
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

@ -0,0 +1,336 @@
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

@ -0,0 +1,51 @@
Index: grub-2.06/include/grub/efi/efi.h
===================================================================
--- grub-2.06.orig/include/grub/efi/efi.h
+++ grub-2.06/include/grub/efi/efi.h
@@ -86,6 +86,11 @@ grub_efi_status_t EXPORT_FUNC (grub_efi_
const grub_efi_guid_t *guid,
grub_size_t *datasize_out,
void **data_out);
+grub_err_t EXPORT_FUNC (grub_efi_set_variable_with_attributes) (const char *var,
+ const grub_efi_guid_t *guid,
+ grub_efi_uint32_t attributes,
+ void *data,
+ grub_size_t datasize);
grub_err_t
EXPORT_FUNC (grub_efi_set_variable) (const char *var,
const grub_efi_guid_t *guid,
Index: grub-2.06/grub-core/kern/efi/efi.c
===================================================================
--- grub-2.06.orig/grub-core/kern/efi/efi.c
+++ grub-2.06/grub-core/kern/efi/efi.c
@@ -196,6 +196,17 @@ grub_err_t
grub_efi_set_variable(const char *var, const grub_efi_guid_t *guid,
void *data, grub_size_t datasize)
{
+ return grub_efi_set_variable_with_attributes(var, guid,
+ (GRUB_EFI_VARIABLE_NON_VOLATILE
+ | GRUB_EFI_VARIABLE_BOOTSERVICE_ACCESS
+ | GRUB_EFI_VARIABLE_RUNTIME_ACCESS),
+ data, datasize);
+}
+
+grub_err_t
+grub_efi_set_variable_with_attributes(const char *var, const grub_efi_guid_t *guid, grub_efi_uint32_t attributes,
+ void *data, grub_size_t datasize)
+{
grub_efi_status_t status;
grub_efi_runtime_services_t *r;
grub_efi_char16_t *var16;
@@ -211,10 +222,8 @@ grub_efi_set_variable(const char *var, c
r = grub_efi_system_table->runtime_services;
- status = efi_call_5 (r->set_variable, var16, guid,
- (GRUB_EFI_VARIABLE_NON_VOLATILE
- | GRUB_EFI_VARIABLE_BOOTSERVICE_ACCESS
- | GRUB_EFI_VARIABLE_RUNTIME_ACCESS),
+ status = efi_call_5 (r->set_variable, var16, guid,
+ attributes,
datasize, data);
grub_free (var16);
if (status == GRUB_EFI_SUCCESS)

38
fix-tpm2-build.patch Normal file
View File

@ -0,0 +1,38 @@
---
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

@ -0,0 +1,18 @@
Index: grub-2.06/util/grub-install.c
===================================================================
--- grub-2.06.orig/util/grub-install.c
+++ grub-2.06/util/grub-install.c
@@ -1457,6 +1457,13 @@ main (int argc, char *argv[])
grub_util_unlink (load_cfg);
+ if (1)
+ {
+ load_cfg_f = grub_util_fopen (load_cfg, "wb");
+ have_load_cfg = 1;
+ fprintf (load_cfg_f, "tpm_record_pcrs 0-9\n");
+ }
+
if (debug_image && debug_image[0])
{
load_cfg_f = grub_util_fopen (load_cfg, "wb");

151
grub-read-pcr.patch Normal file
View File

@ -0,0 +1,151 @@
Index: grub-2.06/include/grub/tpm.h
===================================================================
--- grub-2.06.orig/include/grub/tpm.h
+++ grub-2.06/include/grub/tpm.h
@@ -34,6 +34,15 @@
#define EV_IPL 0x0d
+struct grub_tpm_digest {
+ const char * algorithm;
+ unsigned int size;
+ unsigned char value[1]; /* variable length */
+};
+
grub_err_t grub_tpm_measure (unsigned char *buf, grub_size_t size,
grub_uint8_t pcr, const char *description);
+struct grub_tpm_digest *grub_tpm_read_pcr (grub_uint8_t index, const char *algo);
+void grub_tpm_digest_free (struct grub_tpm_digest *d);
+
#endif
Index: grub-2.06/grub-core/commands/efi/tpm.c
===================================================================
--- grub-2.06.orig/grub-core/commands/efi/tpm.c
+++ grub-2.06/grub-core/commands/efi/tpm.c
@@ -23,6 +23,7 @@
#include <grub/efi/api.h>
#include <grub/efi/efi.h>
#include <grub/efi/tpm.h>
+#include <grub/tpm2/tpm2.h>
#include <grub/mm.h>
#include <grub/tpm.h>
#include <grub/term.h>
@@ -186,6 +187,91 @@ grub_tpm1_log_event (grub_efi_handle_t t
return grub_efi_log_event_status (status);
}
+static void
+grub_tpm2_select_pcr(TPML_PCR_SELECTION *o, unsigned int pcrIndex, unsigned int algo)
+{
+ TPMS_PCR_SELECTION *pcr;
+
+ pcr = &o->pcrSelections[o->count++];
+ pcr->hash = algo;
+ pcr->sizeOfSelect = 3;
+ pcr->pcrSelect[TPM2_PCR_TO_SELECT(pcrIndex)] |= TPM2_PCR_TO_BIT(pcrIndex);
+}
+
+struct grub_tpm_hash_info {
+ const char *name;
+ grub_size_t size;
+ int id;
+};
+
+static const struct grub_tpm_hash_info *
+grub_tpm2_get_digest_info (const char *algo)
+{
+ static struct grub_tpm_hash_info __hashes[] = {
+ { "sha256", 32, TPM_ALG_SHA256 }, /* first entry is the default */
+ { "sha512", 64, TPM_ALG_SHA512 },
+ { "sha1", 20, TPM_ALG_SHA1 },
+ { NULL }
+ };
+ struct grub_tpm_hash_info *h;
+
+ if (algo == NULL)
+ return &__hashes[0];
+
+ for (h = __hashes; h->name; ++h)
+ if (!grub_strcmp(h->name, algo))
+ return h;
+
+ return NULL;
+}
+
+static grub_err_t
+grub_tpm2_read_pcr (grub_int8_t pcrIndex, const char *algo, struct grub_tpm_digest **ret)
+{
+ const struct grub_tpm_hash_info *info;
+ TPML_PCR_SELECTION inSelection, outSelection;
+ grub_uint32_t pcrUpdateCounter;
+ TPML_DIGEST digests = { 0 };
+ TPM2B_DIGEST *d;
+ struct grub_tpm_digest *result;
+ int rc;
+
+ info = grub_tpm2_get_digest_info (algo);
+ if (info == NULL)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("Unknown digest algorithm %s"), algo);
+
+ grub_memset(&inSelection, 0, sizeof(inSelection));
+ grub_memset(&outSelection, 0, sizeof(outSelection));
+ grub_tpm2_select_pcr(&inSelection, pcrIndex, info->id);
+
+ rc = TPM2_PCR_Read(
+ NULL,
+ &inSelection,
+ &pcrUpdateCounter,
+ &outSelection,
+ &digests,
+ NULL
+ );
+
+ if (rc != 0)
+ return grub_error (GRUB_ERR_BAD_DEVICE, "TPM2_PCR_Read failed, status=%d", rc);
+
+ d = &digests.digests[0];
+
+ *ret = result = grub_malloc (sizeof (*result) + d->size);
+ grub_memcpy (result->value, d->buffer, d->size);
+ result->algorithm = info->name;
+ result->size = d->size;
+
+ return GRUB_ERR_NONE;
+}
+
+void
+grub_tpm_digest_free (struct grub_tpm_digest *d)
+{
+ grub_free (d);
+}
+
static grub_err_t
grub_tpm2_log_event (grub_efi_handle_t tpm_handle, unsigned char *buf,
grub_size_t size, grub_uint8_t pcr,
@@ -240,3 +326,26 @@ grub_tpm_measure (unsigned char *buf, gr
else
return grub_tpm2_log_event (tpm_handle, buf, size, pcr, description);
}
+
+struct grub_tpm_digest *
+grub_tpm_read_pcr (grub_uint8_t pcr, const char *algo)
+{
+ grub_efi_handle_t tpm_handle;
+ grub_efi_uint8_t protocol_version;
+ struct grub_tpm_digest *result = NULL;
+
+
+ if (!grub_tpm_handle_find (&tpm_handle, &protocol_version))
+ return 0;
+
+ if (protocol_version != 2)
+ {
+ grub_error (GRUB_ERR_BAD_DEVICE, N_("%s: TPM version %d not implemented"), __func__, protocol_version);
+ return NULL;
+ }
+
+ if (grub_tpm2_read_pcr (pcr, algo, &result))
+ return NULL;
+
+ return result;
+}

41
grub-unseal-debug.patch Normal file
View File

@ -0,0 +1,41 @@
Index: grub-2.06/grub-core/tpm2/module.c
===================================================================
--- grub-2.06.orig/grub-core/tpm2/module.c
+++ grub-2.06/grub-core/tpm2/module.c
@@ -22,6 +22,7 @@
#include <grub/misc.h>
#include <grub/mm.h>
#include <grub/protector.h>
+#include <grub/time.h>
#include <grub/tpm2/buffer.h>
#include <grub/tpm2/internal/args.h>
#include <grub/tpm2/mu.h>
@@ -449,6 +450,7 @@ grub_tpm2_protector_srk_recover (const s
{
grub_error (err, N_("Failed to unseal sealed key (TPM2_Unseal failed "
"with TSS/TPM error %u)"), rc);
+ grub_millisleep(500);
goto exit4;
}
@@ -461,6 +463,8 @@ grub_tpm2_protector_srk_recover (const s
goto exit4;
}
+ grub_printf("TPM2: unsealed %u bytes of key material\n", data.size);
+
if (ctx->efivar)
{
rc = grub_tpm2_protector_publish_key (data.buffer, data.size, ctx->efivar);
Index: grub-2.06/grub-core/loader/linux.c
===================================================================
--- grub-2.06.orig/grub-core/loader/linux.c
+++ grub-2.06/grub-core/loader/linux.c
@@ -171,6 +171,7 @@ grub_initrd_component (const char *buf,
struct grub_linux_initrd_component *comp = initrd_ctx->components + initrd_ctx->nfiles;
grub_size_t dir_size, name_len;
+ grub_printf("Creating initrd component \"%s\" with %u bytes\n", newc_name, bufsz);
while (*newc_name == '/')
newc_name++;

View File

@ -1,3 +1,137 @@
-------------------------------------------------------------------
Fri Oct 28 04:58:28 UTC 2022 - Michael Chang <mchang@suse.com>
- NVMeoFC support on grub (jsc#PED-996)
* 0001-ieee1275-add-support-for-NVMeoFC.patch
* 0002-ieee1275-ofpath-enable-NVMeoF-logical-device-transla.patch
* 0003-ieee1275-change-the-logic-of-ieee1275_get_devargs.patch
* 0004-ofpath-controller-name-update.patch
- TDX: Enhance grub2 measurement to TD RTMR (jsc#PED-1265)
* 0001-commands-efi-tpm-Refine-the-status-of-log-event.patch
* 0002-commands-efi-tpm-Use-grub_strcpy-instead-of-grub_mem.patch
* 0003-efi-tpm-Add-EFI_CC_MEASUREMENT_PROTOCOL-support.patch
- Measure the kernel on POWER10 and extend TPM PCRs (PED-1990)
* 0001-ibmvtpm-Add-support-for-trusted-boot-using-a-vTPM-2..patch
* 0002-ieee1275-implement-vec5-for-cas-negotiation.patch
- Fix efi pcr snapshot related funtion is defined but not used on powerpc
platform.
* safe_tpm_pcr_snapshot.patch
-------------------------------------------------------------------
Mon Oct 24 01:58:08 UTC 2022 - Michael Chang <mchang@suse.com>
- Include loopback into signed grub2 image (jsc#PED-2150)
-------------------------------------------------------------------
Thu Oct 6 07:13:23 UTC 2022 - Michael Chang <mchang@suse.com>
- Fix firmware oops after disk decrypting failure (bsc#1204037)
* 0009-Add-crypttab_entry-to-obviate-the-need-to-input-pass.patch
-------------------------------------------------------------------
Fri Sep 23 10:13:54 UTC 2022 - Michael Chang <mchang@suse.com>
- Add patch to fix kernel relocation error in low memory
* 0001-linux-fix-efi_relocate_kernel-failure.patch
-------------------------------------------------------------------
Mon Sep 19 04:07:36 UTC 2022 - Michael Chang <mchang@suse.com>
- Add safety measure to pcr snapshot by checking platform and tpm status
* safe_tpm_pcr_snapshot.patch
-------------------------------------------------------------------
Fri Sep 16 03:56:14 UTC 2022 - Michael Chang <mchang@suse.com>
- Fix installation failure due to unavailable nvram device on
ppc64le (bsc#1201361)
* 0001-grub-install-set-point-of-no-return-for-powerpc-ieee1275.patch
-------------------------------------------------------------------
Fri Sep 16 03:12:36 UTC 2022 - Gary Ching-Pang Lin <glin@suse.com>
- Add patches to dynamically allocate additional memory regions for
EFI systems (bsc#1202438)
* 0001-mm-Allow-dynamically-requesting-additional-memory-re.patch
* 0002-kern-efi-mm-Always-request-a-fixed-number-of-pages-o.patch
* 0003-kern-efi-mm-Extract-function-to-add-memory-regions.patch
* 0004-kern-efi-mm-Pass-up-errors-from-add_memory_regions.patch
* 0005-kern-efi-mm-Implement-runtime-addition-of-pages.patch
- Enlarge the default heap size and defer the disk cache
invalidation (bsc#1202438)
* 0001-kern-efi-mm-Enlarge-the-default-heap-size.patch
* 0002-mm-Defer-the-disk-cache-invalidation.patch
-------------------------------------------------------------------
Thu Sep 15 09:51:07 UTC 2022 - Michael Chang <mchang@suse.com>
- Add patches for ALP FDE support
* 0001-devmapper-getroot-Have-devmapper-recognize-LUKS2.patch
* 0002-devmapper-getroot-Set-up-cheated-LUKS2-cryptodisk-mo.patch
* 0003-disk-cryptodisk-When-cheatmounting-use-the-sector-in.patch
* 0004-normal-menu-Don-t-show-Booting-s-msg-when-auto-booti.patch
* 0005-EFI-suppress-the-Welcome-to-GRUB-message-in-EFI-buil.patch
* 0006-EFI-console-Do-not-set-colorstate-until-the-first-te.patch
* 0007-EFI-console-Do-not-set-cursor-until-the-first-text-o.patch
* 0008-linuxefi-Use-common-grub_initrd_load.patch
* 0009-Add-crypttab_entry-to-obviate-the-need-to-input-pass.patch
* 0010-templates-import-etc-crypttab-to-grub.cfg.patch
* grub-read-pcr.patch
* efi-set-variable-with-attrs.patch
* tpm-record-pcrs.patch
* tpm-protector-dont-measure-sealed-key.patch
* tpm-protector-export-secret-key.patch
* grub-install-record-pcrs.patch
* grub-unseal-debug.patch
-------------------------------------------------------------------
Mon Aug 29 03:48:55 UTC 2022 - Michael Chang <mchang@suse.com>
- Fix out of memory error cannot be prevented via disabling tpm (bsc#1202438)
* 0001-tpm-Disable-tpm-verifier-if-tpm-is-not-present.patch
-------------------------------------------------------------------
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,6 +407,65 @@ 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
# fde
Patch901: 0001-devmapper-getroot-Have-devmapper-recognize-LUKS2.patch
Patch902: 0002-devmapper-getroot-Set-up-cheated-LUKS2-cryptodisk-mo.patch
Patch903: 0003-disk-cryptodisk-When-cheatmounting-use-the-sector-in.patch
Patch904: 0004-normal-menu-Don-t-show-Booting-s-msg-when-auto-booti.patch
Patch905: 0005-EFI-suppress-the-Welcome-to-GRUB-message-in-EFI-buil.patch
Patch906: 0006-EFI-console-Do-not-set-colorstate-until-the-first-te.patch
Patch907: 0007-EFI-console-Do-not-set-cursor-until-the-first-text-o.patch
Patch908: 0008-linuxefi-Use-common-grub_initrd_load.patch
Patch909: 0009-Add-crypttab_entry-to-obviate-the-need-to-input-pass.patch
Patch910: 0010-templates-import-etc-crypttab-to-grub.cfg.patch
Patch911: grub-read-pcr.patch
Patch912: efi-set-variable-with-attrs.patch
Patch913: tpm-record-pcrs.patch
Patch914: tpm-protector-dont-measure-sealed-key.patch
Patch915: tpm-protector-export-secret-key.patch
Patch916: grub-install-record-pcrs.patch
Patch917: grub-unseal-debug.patch
# efi mm
Patch918: 0001-tpm-Disable-tpm-verifier-if-tpm-is-not-present.patch
Patch919: 0001-mm-Allow-dynamically-requesting-additional-memory-re.patch
Patch920: 0002-kern-efi-mm-Always-request-a-fixed-number-of-pages-o.patch
Patch921: 0003-kern-efi-mm-Extract-function-to-add-memory-regions.patch
Patch922: 0004-kern-efi-mm-Pass-up-errors-from-add_memory_regions.patch
Patch923: 0005-kern-efi-mm-Implement-runtime-addition-of-pages.patch
Patch924: 0001-kern-efi-mm-Enlarge-the-default-heap-size.patch
Patch925: 0002-mm-Defer-the-disk-cache-invalidation.patch
# powerpc-ieee1275
Patch926: 0001-grub-install-set-point-of-no-return-for-powerpc-ieee1275.patch
Patch927: safe_tpm_pcr_snapshot.patch
Patch928: 0001-linux-fix-efi_relocate_kernel-failure.patch
# (PED-996) NVMeoFC support on Grub (grub2)
Patch929: 0001-ieee1275-add-support-for-NVMeoFC.patch
Patch930: 0002-ieee1275-ofpath-enable-NVMeoF-logical-device-transla.patch
Patch931: 0003-ieee1275-change-the-logic-of-ieee1275_get_devargs.patch
Patch932: 0004-ofpath-controller-name-update.patch
# (PED-1265) TDX: Enhance grub2 measurement to TD RTMR
Patch933: 0001-commands-efi-tpm-Refine-the-status-of-log-event.patch
Patch934: 0002-commands-efi-tpm-Use-grub_strcpy-instead-of-grub_mem.patch
Patch935: 0003-efi-tpm-Add-EFI_CC_MEASUREMENT_PROTOCOL-support.patch
# (PED-1990) GRUB2: Measure the kernel on POWER10 and extend TPM PCRs
Patch936: 0001-ibmvtpm-Add-support-for-trusted-boot-using-a-vTPM-2..patch
Patch937: 0002-ieee1275-implement-vec5-for-cas-negotiation.patch
Requires: gettext-runtime
%if 0%{?suse_version} >= 1140
@ -673,11 +732,11 @@ CD_MODULES="all_video boot cat configfile echo true \
font gfxmenu gfxterm gzio halt iso9660 \
jpeg minicmd normal part_apple part_msdos part_gpt \
password password_pbkdf2 png reboot search search_fs_uuid \
search_fs_file search_label sleep test video fat loadenv"
search_fs_file search_label sleep test video fat loadenv loopback"
PXE_MODULES="tftp http"
CRYPTO_MODULES="luks gcry_rijndael gcry_sha1 gcry_sha256"
CRYPTO_MODULES="luks luks2 gcry_rijndael gcry_sha1 gcry_sha256 gcry_sha512 crypttab"
%ifarch %{efi}
CD_MODULES="${CD_MODULES} chain efifwsetup efinet read"
CD_MODULES="${CD_MODULES} chain efifwsetup efinet read tpm tpm2"
PXE_MODULES="${PXE_MODULES} efinet"
%else
CD_MODULES="${CD_MODULES} net"
@ -715,10 +774,6 @@ 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
@ -898,7 +953,7 @@ cd build-efi
%make_install
install -m 644 grub.efi %{buildroot}/%{_datadir}/%{name}/%{grubefiarch}/.
%ifarch x86_64
install -m 644 grub-tpm.efi %{buildroot}/%{_datadir}/%{name}/%{grubefiarch}/.
ln -srf %{buildroot}/%{_datadir}/%{name}/%{grubefiarch}/grub.efi %{buildroot}/%{_datadir}/%{name}/%{grubefiarch}/grub-tpm.efi
%endif
# Create grub.efi link to system efi directory
@ -920,9 +975,6 @@ 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
@ -1205,6 +1257,7 @@ fi
%dir %{_sysconfdir}/grub.d
%{_sysconfdir}/grub.d/README
%config(noreplace) %{_sysconfdir}/grub.d/00_header
%config(noreplace) %{_sysconfdir}/grub.d/05_crypttab
%config(noreplace) %{_sysconfdir}/grub.d/10_linux
%config(noreplace) %{_sysconfdir}/grub.d/20_linux_xen
%config(noreplace) %{_sysconfdir}/grub.d/30_uefi-firmware
@ -1249,6 +1302,7 @@ 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

125
safe_tpm_pcr_snapshot.patch Normal file
View File

@ -0,0 +1,125 @@
---
grub-core/commands/tpm.c | 46 ++++++++++++++++++++++++++++++++++++----------
util/grub-install.c | 6 ++++--
2 files changed, 40 insertions(+), 12 deletions(-)
--- a/grub-core/commands/tpm.c
+++ b/grub-core/commands/tpm.c
@@ -27,8 +27,10 @@
#include <grub/verify.h>
#include <grub/dl.h>
#include <grub/extcmd.h>
+#ifdef GRUB_MACHINE_EFI
#include <grub/tpm2/tpm2.h>
#include <grub/efi/efi.h>
+#endif
GRUB_MOD_LICENSE ("GPLv3+");
@@ -87,12 +89,6 @@
.verify_string = grub_tpm_verify_string,
};
-/*
- * Preserve current PCR values and record them to an EFI variable
- */
-#define GRUB2_PCR_BITMASK_DEFAULT ((1 << 16) - 1)
-#define GRUB2_PCR_BITMASK_ALL ((1 << 24) - 1)
-
static const struct grub_arg_option grub_tpm_record_pcrs_options[] =
{
{
@@ -108,6 +104,14 @@
{0, 0, 0, 0, 0, 0}
};
+#ifdef GRUB_MACHINE_EFI
+
+/*
+ * Preserve current PCR values and record them to an EFI variable
+ */
+#define GRUB2_PCR_BITMASK_DEFAULT ((1 << 16) - 1)
+#define GRUB2_PCR_BITMASK_ALL ((1 << 24) - 1)
+
static grub_err_t
grub_tpm_parse_pcr_index (const char *word, const char **end_ret, unsigned int *index)
{
@@ -259,6 +263,10 @@
grub_size_t size = 0;
int n, rv = 1;
+ /* To prevent error: unable to read PCR from TPM, if no TPM device available */
+ if (!grub_tpm_present())
+ return GRUB_ERR_NONE;
+
if (argc == 0)
pcr_bitmask = GRUB2_PCR_BITMASK_DEFAULT;
else
@@ -287,13 +295,28 @@
return rv;
}
+#else
+
+static grub_err_t
+grub_tpm_record_pcrs (grub_extcmd_context_t ctxt __attribute__((unused)),
+ int argc __attribute__((unused)),
+ char **args __attribute__((unused)))
+{
+ return GRUB_ERR_NONE;
+}
+
+#endif
+
static grub_extcmd_t cmd;
GRUB_MOD_INIT (tpm)
{
- if (!grub_tpm_present())
- return;
+#ifdef GRUB_MACHINE_EFI
+ if (grub_tpm_present())
+ grub_verifier_register (&grub_tpm_verifier);
+#else
grub_verifier_register (&grub_tpm_verifier);
+#endif
cmd = grub_register_extcmd ("tpm_record_pcrs", grub_tpm_record_pcrs, 0,
N_("LIST_OF_PCRS"),
@@ -303,8 +326,11 @@
GRUB_MOD_FINI (tpm)
{
- if (!grub_tpm_present())
- return;
+#ifdef GRUB_MACHINE_EFI
+ if (grub_tpm_present())
+ grub_verifier_unregister (&grub_tpm_verifier);
+#else
grub_verifier_unregister (&grub_tpm_verifier);
+#endif
grub_unregister_extcmd (cmd);
}
--- a/util/grub-install.c
+++ b/util/grub-install.c
@@ -1457,8 +1457,9 @@
grub_util_unlink (load_cfg);
- if (1)
+ if (platform == GRUB_INSTALL_PLATFORM_X86_64_EFI && have_cryptodisk)
{
+ grub_install_push_module ("tpm");
load_cfg_f = grub_util_fopen (load_cfg, "wb");
have_load_cfg = 1;
fprintf (load_cfg_f, "tpm_record_pcrs 0-9\n");
@@ -1466,7 +1467,8 @@
if (debug_image && debug_image[0])
{
- load_cfg_f = grub_util_fopen (load_cfg, "wb");
+ if (!load_cfg_f)
+ load_cfg_f = grub_util_fopen (load_cfg, "wb");
have_load_cfg = 1;
fprintf (load_cfg_f, "set debug='%s'\n",
debug_image);

View File

@ -0,0 +1,15 @@
Index: grub-2.06/grub-core/tpm2/module.c
===================================================================
--- grub-2.06.orig/grub-core/tpm2/module.c
+++ grub-2.06/grub-core/tpm2/module.c
@@ -139,7 +139,9 @@ grub_tpm2_protector_srk_read_keyfile (co
void *sealed_key_buffer;
grub_off_t sealed_key_read;
- sealed_key_file = grub_file_open (filepath, GRUB_FILE_TYPE_NONE);
+ /* Using GRUB_FILE_TYPE_SIGNATURE ensures we do not hash the keyfile into PCR9
+ * otherwise we'll never be able to predict the value of PCR9 at unseal time */
+ sealed_key_file = grub_file_open (filepath, GRUB_FILE_TYPE_SIGNATURE);
if (!sealed_key_file)
{
grub_dprintf ("tpm2", "Could not open sealed key file.\n");

View File

@ -0,0 +1,138 @@
Index: grub-2.06/grub-core/tpm2/module.c
===================================================================
--- grub-2.06.orig/grub-core/tpm2/module.c
+++ grub-2.06/grub-core/tpm2/module.c
@@ -26,6 +26,7 @@
#include <grub/tpm2/internal/args.h>
#include <grub/tpm2/mu.h>
#include <grub/tpm2/tpm2.h>
+#include <grub/efi/efi.h>
GRUB_MOD_LICENSE ("GPLv3+");
@@ -46,6 +47,7 @@ struct grub_tpm2_protector_context
const char *keyfile;
TPM_HANDLE srk;
TPM_HANDLE nv;
+ const char *efivar;
};
static const struct grub_arg_option grub_tpm2_protector_init_cmd_options[] =
@@ -122,6 +124,16 @@ static const struct grub_arg_option grub
N_("Required in NV Index mode, the NV handle to read which must "
"readily exist on the TPM and which contains the key."),
},
+ /* When publishing the unsealed key to a UEFI variable */
+ {
+ .longarg = "efivar",
+ .shortarg = 'E',
+ .flags = 0,
+ .arg = NULL,
+ .type = ARG_TYPE_STRING,
+ .doc =
+ N_("Publish the unsealed key to the indicated UEFI variable."),
+ },
/* End of list */
{0, 0, 0, 0, 0, 0}
};
@@ -302,6 +314,34 @@ grub_tpm2_protector_srk_get (const struc
}
static grub_err_t
+grub_tpm2_protector_publish_key (grub_uint8_t *key, grub_size_t key_size,
+ const char *var_name)
+{
+ grub_efi_guid_t vendor_guid = { 0x58aca851, 0x8af7, 0x4738, { 0xa5, 0x42, 0x26, 0x6e, 0x21, 0xf5, 0xca, 0xd9 }};
+ grub_uint8_t *tmp_key;
+ grub_err_t err;
+
+ /* It appears that EFI's set_var function overwrites the key. */
+ tmp_key = grub_malloc (key_size);
+ if (!tmp_key)
+ {
+ grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("No memory left to allocate temporary key buffer"));
+ return GRUB_ERR_OUT_OF_MEMORY;
+ }
+
+ grub_memcpy(tmp_key, key, key_size);
+
+ err = grub_efi_set_variable_with_attributes(var_name, &vendor_guid,
+ GRUB_EFI_VARIABLE_BOOTSERVICE_ACCESS | GRUB_EFI_VARIABLE_RUNTIME_ACCESS,
+ tmp_key, key_size);
+ if (err)
+ grub_error (err, N_("Failed to export LUKS key as EFI variable %s"), var_name);
+
+ grub_free (tmp_key);
+ return err;
+}
+
+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)
{
@@ -421,6 +461,13 @@ grub_tpm2_protector_srk_recover (const s
goto exit4;
}
+ if (ctx->efivar)
+ {
+ rc = grub_tpm2_protector_publish_key (data.buffer, data.size, ctx->efivar);
+ if (rc)
+ goto exit4;
+ }
+
grub_memcpy (key_out, data.buffer, data.size);
*key = key_out;
@@ -549,20 +596,32 @@ grub_tpm2_protector_check_args (struct g
}
static grub_err_t
-grub_tpm2_protector_parse_keyfile (const char *value, const char **keyfile)
+grub_tpm2_protector_parse_string (const char *value, const char **var, const char *arg_name)
{
if (grub_strlen (value) == 0)
return GRUB_ERR_BAD_ARGUMENT;
- *keyfile = grub_strdup (value);
- if (!*keyfile)
+ *var = grub_strdup (value);
+ if (!*var)
return grub_error (GRUB_ERR_OUT_OF_MEMORY,
- N_("No memory to duplicate keyfile path"));
+ N_("No memory to duplicate %s argument"), arg_name);
return GRUB_ERR_NONE;
}
static grub_err_t
+grub_tpm2_protector_parse_keyfile (const char *value, const char **keyfile)
+{
+ return grub_tpm2_protector_parse_string (value, keyfile, "keyfile");
+}
+
+static grub_err_t
+grub_tpm2_protector_parse_efivar (const char *value, const char **efivar)
+{
+ return grub_tpm2_protector_parse_string (value, efivar, "efivar");
+}
+
+static grub_err_t
grub_tpm2_protector_parse_mode (const char *value,
grub_tpm2_protector_mode_t *mode)
{
@@ -650,6 +709,14 @@ grub_tpm2_protector_init_cmd_handler (gr
if (err)
return err;
}
+
+ if (state[7].set) /* efivar */
+ {
+ err = grub_tpm2_protector_parse_efivar (state[7].arg,
+ &grub_tpm2_protector_ctx.efivar);
+ if (err)
+ return err;
+ }
err = grub_tpm2_protector_check_args (&grub_tpm2_protector_ctx);

235
tpm-record-pcrs.patch Normal file
View File

@ -0,0 +1,235 @@
Index: grub-2.06/grub-core/commands/tpm.c
===================================================================
--- grub-2.06.orig/grub-core/commands/tpm.c
+++ grub-2.06/grub-core/commands/tpm.c
@@ -26,6 +26,9 @@
#include <grub/term.h>
#include <grub/verify.h>
#include <grub/dl.h>
+#include <grub/extcmd.h>
+#include <grub/tpm2/tpm2.h>
+#include <grub/efi/efi.h>
GRUB_MOD_LICENSE ("GPLv3+");
@@ -84,12 +87,220 @@ struct grub_file_verifier grub_tpm_verif
.verify_string = grub_tpm_verify_string,
};
+/*
+ * Preserve current PCR values and record them to an EFI variable
+ */
+#define GRUB2_PCR_BITMASK_DEFAULT ((1 << 16) - 1)
+#define GRUB2_PCR_BITMASK_ALL ((1 << 24) - 1)
+
+static const struct grub_arg_option grub_tpm_record_pcrs_options[] =
+ {
+ {
+ .longarg = "efivar",
+ .shortarg = 'E',
+ .flags = 0,
+ .arg = NULL,
+ .type = ARG_TYPE_STRING,
+ .doc =
+ N_("The EFI variable to publish the PCRs to (default GrubPcrSnapshot)"),
+ },
+
+ {0, 0, 0, 0, 0, 0}
+ };
+
+static grub_err_t
+grub_tpm_parse_pcr_index (const char *word, const char **end_ret, unsigned int *index)
+{
+ const char *end;
+
+ if (!grub_isdigit (word[0]))
+ return GRUB_ERR_BAD_NUMBER;
+
+ *index = grub_strtoul(word, &end, 0);
+ if (*index > 32)
+ return GRUB_ERR_BAD_NUMBER;
+
+ *end_ret = end;
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_tpm_parse_pcr_list (const char *arg, grub_uint32_t *bitmask)
+{
+ const char *word, *end;
+ unsigned int index, last_index;
+
+ if (!grub_strcmp (arg, "all"))
+ {
+ *bitmask = GRUB2_PCR_BITMASK_ALL;
+ return GRUB_ERR_NONE;
+ }
+
+ word = arg;
+ while (1)
+ {
+ if (grub_tpm_parse_pcr_index (word, &end, &index))
+ goto bad_pcr_index;
+
+ if (*end == '-')
+ {
+ if (grub_tpm_parse_pcr_index (end + 1, &end, &last_index) || last_index < index)
+ goto bad_pcr_index;
+
+ while (index <= last_index)
+ *bitmask |= (1 << (index++));
+ }
+ else
+ *bitmask |= (1 << index);
+
+ if (*end == '\0')
+ break;
+
+ if (*end != ',')
+ goto bad_pcr_index;
+
+ word = end + 1;
+ }
+
+ return GRUB_ERR_NONE;
+
+bad_pcr_index:
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("cannot parse PCR list \"%s\""), arg);
+}
+
+static inline unsigned int
+nbits(grub_uint32_t mask)
+{
+ unsigned int r = 0;
+
+ for (; mask != 0; mask >>= 1)
+ r += (mask & 1);
+ return r;
+}
+
+static grub_err_t
+grub_tpm_snapshot_pcrs (grub_uint32_t pcr_bitmask, const char *algo,
+ void **buffer_ret, grub_size_t *size_ret)
+{
+ char *buffer;
+ grub_size_t size = 65536;
+ unsigned int wpos = 0;
+ grub_uint8_t pcr;
+
+ buffer = grub_malloc (size);
+ for (pcr = 0; pcr < 32; ++pcr)
+ {
+ struct grub_tpm_digest *d;
+ unsigned int need, k;
+
+ if (!(pcr_bitmask & (1 << pcr)))
+ continue;
+
+ d = grub_tpm_read_pcr (pcr, algo);
+ if (d == NULL)
+ {
+ grub_error (GRUB_ERR_BAD_DEVICE, N_("unable to read PCR %d from TPM"), pcr);
+ continue;
+ }
+
+ /* We need room for the PCR index, 2 spaces, newline, NUL. 16 should be enough. */
+ need = 16 + grub_strlen(d->algorithm) + 2 * d->size;
+ if (wpos + need > size)
+ {
+ buffer = grub_realloc (buffer, size + need);
+ if (buffer == NULL)
+ return grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("Not enough memory when dumping PCR registers"));
+ }
+
+ grub_snprintf (buffer + wpos, size - wpos, "%02d %s ", pcr, d->algorithm);
+ wpos = grub_strlen(buffer);
+
+ for (k = 0; k < d->size; ++k)
+ {
+ grub_snprintf (buffer + wpos, size - wpos, "%02x", d->value[k]);
+ wpos += 2;
+ }
+
+ buffer[wpos++] = '\n';
+ buffer[wpos] = '\0';
+
+ grub_tpm_digest_free (d);
+ }
+
+ *buffer_ret = buffer;
+ *size_ret = wpos;
+
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_tpm_write_pcrs_to_efi (void *data, grub_size_t size, const char *var_name)
+{
+ grub_efi_guid_t vendor_guid = { 0x7ce323f2, 0xb841, 0x4d30, { 0xa0, 0xe9, 0x54, 0x74, 0xa7, 0x6c, 0x9a, 0x3f }};
+ grub_err_t rc;
+
+ rc = grub_efi_set_variable_with_attributes(var_name, &vendor_guid,
+ GRUB_EFI_VARIABLE_BOOTSERVICE_ACCESS | GRUB_EFI_VARIABLE_RUNTIME_ACCESS,
+ data, size);
+
+ if (rc)
+ return grub_error (GRUB_ERR_BAD_DEVICE, N_("Failed to publish PCR snapshot to UEFI variable %s"), var_name);
+
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_tpm_record_pcrs (grub_extcmd_context_t ctxt, int argc, char **args)
+{
+ struct grub_arg_list *state = ctxt->state;
+ grub_uint32_t pcr_bitmask = 0;
+ const char *efivar;
+ void *buffer = NULL;
+ grub_size_t size = 0;
+ int n, rv = 1;
+
+ if (argc == 0)
+ pcr_bitmask = GRUB2_PCR_BITMASK_DEFAULT;
+ else
+ {
+ for (n = 0; n < argc; ++n)
+ if (grub_tpm_parse_pcr_list (args[n], &pcr_bitmask))
+ return 1;
+ }
+
+ if (grub_tpm_snapshot_pcrs (pcr_bitmask, NULL, &buffer, &size))
+ goto out;
+
+ if (state[0].set)
+ efivar = state[0].arg;
+ else
+ efivar = "GrubPcrSnapshot";
+
+ if (grub_tpm_write_pcrs_to_efi (buffer, size, efivar))
+ goto out;
+
+ rv = 0;
+
+out:
+ if (buffer)
+ grub_free (buffer);
+ return rv;
+}
+
+static grub_extcmd_t cmd;
+
GRUB_MOD_INIT (tpm)
{
grub_verifier_register (&grub_tpm_verifier);
+
+ cmd = grub_register_extcmd ("tpm_record_pcrs", grub_tpm_record_pcrs, 0,
+ N_("LIST_OF_PCRS"),
+ N_("Snapshot one or more PCR values and record them in an EFI variable."),
+ grub_tpm_record_pcrs_options);
}
GRUB_MOD_FINI (tpm)
{
grub_verifier_unregister (&grub_tpm_verifier);
+ grub_unregister_extcmd (cmd);
}