Sync from SUSE:SLFO:Main grub2 revision 63018e250eec224553909fb27623e281

This commit is contained in:
Adrian Schröter 2024-11-04 17:27:44 +01:00
parent a1d205fd6c
commit 5668489852
21 changed files with 4107 additions and 240 deletions

View File

@ -0,0 +1,188 @@
From 8201e8e6fbb7ee992c430679705852ede91efcd6 Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Tue, 20 Aug 2024 12:14:35 +0800
Subject: [PATCH] Streamline BLS and improve PCR stability
Introduce an environment variable enable_blscfg to allow looking for and
reading BLS (Boot Loader Specification) configurations right at startup,
rather than relying on the traditional grub.cfg. The benefit of this
approach is that it eliminates the layer of using an external grub.cfg
to piggyback the blscfg command. This change reduces the complexity of
managing command sequences, which would otherwise complicate the PCR
(Platform Configuration Register) policy. Managing a sequence of
commands can be difficult to maintain and ensure they remain in order
indefinitely.
Along the way, we can remove the external grub.cfg and have everything
embedded in memdisk and early embedded configurations. This approach
significantly improves the overall stability and makes it easier to
maintain a consistent and predictable PCR outcome.
The grubenv in the EFI boot directory can be used to override default
settings in the grubbls image, allowing for continued customization.
By introducing grubbls.efi for managing BLS configuration integration,
all necessary modules are built-in, and sensible default settings are
applied. This allows us to remove the following hardcoded command
sequences in blscfg:
load_video
set gfxpalyload=keep
insmod gzio
Since these are now part of the EFI image, this change effectively
simplifies the TPM event log, making it easier to handle with tools like
pcr-oracle or systemd-pcrlock.
Signed-Off-by: Michael Chang <mchang@suse.com>
---
grub-core/commands/blscfg.c | 4 ++
grub-core/normal/main.c | 82 +++++++++++++++++++++++++++++++++++++
include/grub/parser.h | 4 ++
3 files changed, 90 insertions(+)
diff --git a/grub-core/commands/blscfg.c b/grub-core/commands/blscfg.c
index cbe2a289e..e08f35817 100644
--- a/grub-core/commands/blscfg.c
+++ b/grub-core/commands/blscfg.c
@@ -953,10 +953,14 @@ static void create_entry (struct bls_entry *entry)
const char *sdval = grub_env_get("save_default");
bool savedefault = ((NULL != sdval) && (grub_strcmp(sdval, "true") == 0));
+#ifdef GRUB_MACHINE_EFI
+ src = grub_xasprintf ("%slinux %s%s%s%s\n"
+#else
src = grub_xasprintf ("%sload_video\n"
"set gfxpayload=keep\n"
"insmod gzio\n"
"linux %s%s%s%s\n"
+#endif
"%s%s",
savedefault ? "savedefault\n" : "",
#ifdef GRUB_MACHINE_EMU
diff --git a/grub-core/normal/main.c b/grub-core/normal/main.c
index 03631f07a..8e58ced67 100644
--- a/grub-core/normal/main.c
+++ b/grub-core/normal/main.c
@@ -113,6 +113,65 @@ read_config_file_getline (char **line, int cont __attribute__ ((unused)),
return GRUB_ERR_NONE;
}
+#ifdef GRUB_MACHINE_EFI
+
+static void
+read_envblk_from_cmdpath (void)
+{
+ const char *cmdpath;
+ char *envfile = NULL;
+ int found = 0;
+
+ cmdpath = grub_env_get ("cmdpath");
+
+ if (cmdpath)
+ envfile = grub_xasprintf ("%s/grubenv", cmdpath);
+
+ if (envfile)
+ {
+ grub_file_t file;
+
+ file = grub_file_open (envfile, GRUB_FILE_TYPE_FS_SEARCH
+ | GRUB_FILE_TYPE_NO_DECOMPRESS | GRUB_FILE_TYPE_SKIP_SIGNATURE);
+ if (file)
+ {
+ found = 1;
+ grub_file_close (file);
+ }
+ }
+
+ if (found)
+ {
+ char *cfg;
+
+ cfg = grub_xasprintf ("load_env -f %s\n", envfile);
+ grub_parser_execute ((char *)cfg);
+ grub_free (cfg);
+ }
+
+ grub_free (envfile);
+}
+
+static grub_menu_t
+read_blscfg (void)
+{
+ grub_menu_t newmenu;
+ newmenu = grub_env_get_menu ();
+ if (! newmenu)
+ {
+ newmenu = grub_zalloc (sizeof (*newmenu));
+ if (! newmenu)
+ return 0;
+
+ grub_env_set_menu (newmenu);
+ }
+
+ grub_parser_execute ((char *)"blscfg\n");
+ return newmenu;
+}
+
+#endif
+
static grub_menu_t
read_config_file (const char *config)
{
@@ -282,6 +341,26 @@ grub_normal_execute (const char *config, int nested, int batch)
grub_boot_time ("Executing config file");
+#ifdef GRUB_MACHINE_EFI
+ const char *val;
+
+ val = grub_env_get ("enable_blscfg");
+ if (val && (val[0] == '1' || val[0] == 'y'))
+ read_envblk_from_cmdpath ();
+
+ /* Above would be used to override enable_blscfg, so verify again */
+ val = grub_env_get ("enable_blscfg");
+ if (val && (val[0] == '1' || val[0] == 'y'))
+ {
+ menu = read_blscfg ();
+ /* Ignore any error. */
+ grub_errno = GRUB_ERR_NONE;
+ /* unset to let configfile and source commands continue to work */
+ grub_env_unset ("enable_blscfg");
+ goto check_batch;
+ }
+#endif
+
if (config)
{
menu = read_config_file (config);
@@ -307,6 +386,9 @@ grub_normal_execute (const char *config, int nested, int batch)
grub_boot_time ("Executed config file");
+#ifdef GRUB_MACHINE_EFI
+ check_batch:
+#endif
if (! batch)
{
if (menu && menu->size)
diff --git a/include/grub/parser.h b/include/grub/parser.h
index 64f9f5cc2..9d702571a 100644
--- a/include/grub/parser.h
+++ b/include/grub/parser.h
@@ -86,7 +86,11 @@ struct grub_parser
};
typedef struct grub_parser *grub_parser_t;
+#ifdef GRUB_MACHINE_EFI
+grub_err_t EXPORT_FUNC (grub_parser_execute) (char *source);
+#else
grub_err_t grub_parser_execute (char *source);
+#endif
grub_err_t
grub_rescue_parse_line (char *line,
--
2.46.0

View File

@ -0,0 +1,82 @@
From 552a2de0642bb95dd38fcdb7894ea7e07171975e Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Mon, 15 Jul 2024 11:43:07 +0800
Subject: [PATCH] bli: Fix crash in get_part_uuid
The get_part_uuid() function made an assumption that the target grub
device is a partition device and accessed device->disk->partition
without checking for NULL. There are four situations where this
assumption is problematic:
1. The device is a net device instead of a disk.
2. The device is an abstraction device, like LVM, RAID, or CRYPTO, which
is mostly logical "disk" ((lvmid/<UUID>) and so on).
3. Firmware RAID may present the ESP to grub as an EFI disk (hd0) device
if it is contained within a Linux software RAID.
4. When booting from a cdrom, the ESP is a vfat image indexed by the El
Torito boot catalog. The boot device is set to (cd0), corresponding
to the cdrom image mounted as an iso9660 filesystem.
As a result, get_part_uuid() could lead to a NULL pointer dereference
and trigger a synchronous exception during boot if the ESP falls into
one of these categories. This patch fixes the problem by adding the
necessary checks to handle cases where the ESP is not a partition
device.
Additionally, to avoid disrupting the boot process, this patch relaxes
the severity of the errors in this context to non-critical. Errors will
be logged, but they will not prevent the boot process from continuing.
Fixes: e0fa7dc84 (bli: Add a module for the Boot Loader Interface)
Signed-off-by: Michael Chang <mchang@suse.com>
Reviewed-By: Oliver Steffen <osteffen@redhat.com>
---
grub-core/commands/bli.c | 20 +++++++++++++++++++-
1 file changed, 19 insertions(+), 1 deletion(-)
diff --git a/grub-core/commands/bli.c b/grub-core/commands/bli.c
index e0d8a54f7..298c5f70a 100644
--- a/grub-core/commands/bli.c
+++ b/grub-core/commands/bli.c
@@ -48,6 +48,22 @@ get_part_uuid (const char *device_name, char **part_uuid)
if (device == NULL)
return grub_error (grub_errno, N_("cannot open device: %s"), device_name);
+ if (device->disk == NULL)
+ {
+ grub_dprintf ("bli", "%s is not a disk device, partuuid skipped\n", device_name);
+ *part_uuid = NULL;
+ grub_device_close (device);
+ return GRUB_ERR_NONE;
+ }
+
+ if (device->disk->partition == NULL)
+ {
+ grub_dprintf ("bli", "%s has no partition, partuuid skipped\n", device_name);
+ *part_uuid = NULL;
+ grub_device_close (device);
+ return GRUB_ERR_NONE;
+ }
+
disk = grub_disk_open (device->disk->name);
if (disk == NULL)
{
@@ -99,7 +115,7 @@ set_loader_device_part_uuid (void)
status = get_part_uuid (device_name, &part_uuid);
- if (status == GRUB_ERR_NONE)
+ if (status == GRUB_ERR_NONE && part_uuid)
status = grub_efi_set_variable_to_string ("LoaderDevicePartUUID", &bli_vendor_guid, part_uuid,
GRUB_EFI_VARIABLE_BOOTSERVICE_ACCESS |
GRUB_EFI_VARIABLE_RUNTIME_ACCESS);
@@ -117,4 +133,6 @@ GRUB_MOD_INIT (bli)
GRUB_EFI_VARIABLE_BOOTSERVICE_ACCESS |
GRUB_EFI_VARIABLE_RUNTIME_ACCESS);
set_loader_device_part_uuid ();
+ /* No error here is critical, other than being logged */
+ grub_print_error ();
}
--
2.46.0

View File

@ -0,0 +1,55 @@
From 8b9234c7e482edd49a9b3377da8e48fbd54aab28 Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Tue, 24 Sep 2024 18:59:34 +0800
Subject: [PATCH] efinet: Skip virtual VLAN devices during card enumeration
Similar to the fix in commit "c52ae4057 efinet: skip virtual IPv4 and
IPv6 devices during card enumeration", the UEFI PXE driver creates
additional VLAN child devices when a VLAN ID is configured on a network
interface associated with a physical NIC. These virtual VLAN devices
must be skipped during card enumeration to ensure that the subsequent
SNP exclusive open operation targets the correct physical card
instances, otherwise packet transfer would fail.
Example device path with VLAN nodes:
/MAC(123456789ABC,0x1)/Vlan(20)/IPv4(0.0.0.0,0x0,DHCP,0.0.0.0,0.0.0.0,0.0.0.0)
Signed-Off-by: Michael Chang <mchang@suse.com>
---
grub-core/net/drivers/efi/efinet.c | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)
diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c
index 720b5d0e1..3d0bf34fa 100644
--- a/grub-core/net/drivers/efi/efinet.c
+++ b/grub-core/net/drivers/efi/efinet.c
@@ -280,7 +280,8 @@ grub_efinet_findcards (void)
|| GRUB_EFI_DEVICE_PATH_SUBTYPE (child) == GRUB_EFI_IPV6_DEVICE_PATH_SUBTYPE)
&& parent
&& GRUB_EFI_DEVICE_PATH_TYPE (parent) == GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE
- && GRUB_EFI_DEVICE_PATH_SUBTYPE (parent) == GRUB_EFI_MAC_ADDRESS_DEVICE_PATH_SUBTYPE)
+ && (GRUB_EFI_DEVICE_PATH_SUBTYPE (parent) == GRUB_EFI_MAC_ADDRESS_DEVICE_PATH_SUBTYPE
+ || GRUB_EFI_DEVICE_PATH_SUBTYPE (parent) == GRUB_EFI_VLAN_DEVICE_PATH_SUBTYPE))
continue;
net = grub_efi_open_protocol (*handle, &net_io_guid,
@@ -810,6 +811,15 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device,
dup_ldp->type = GRUB_EFI_END_DEVICE_PATH_TYPE;
dup_ldp->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE;
dup_ldp->length = sizeof (*dup_ldp);
+
+ dup_ldp = grub_efi_find_last_device_path (dup_dp);
+ if (GRUB_EFI_DEVICE_PATH_SUBTYPE (dup_ldp) == GRUB_EFI_VLAN_DEVICE_PATH_SUBTYPE)
+ {
+ dup_ldp->type = GRUB_EFI_END_DEVICE_PATH_TYPE;
+ dup_ldp->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE;
+ dup_ldp->length = sizeof (*dup_ldp);
+ }
+
match = grub_efi_compare_device_paths (dup_dp, cdp) == 0;
grub_free (dup_dp);
if (!match)
--
2.46.1

View File

@ -0,0 +1,48 @@
From 44f3c7978a8ac5cc94a5c885ac9e983ba2980f5e Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Wed, 29 May 2024 12:32:32 +0800
Subject: [PATCH] fix grub screen filled with post screen artifects
---
grub-core/normal/menu.c | 7 ++++---
grub-core/term/efi/console.c | 2 +-
2 files changed, 5 insertions(+), 4 deletions(-)
diff --git a/grub-core/normal/menu.c b/grub-core/normal/menu.c
index 1df2638d7..b11b28e0d 100644
--- a/grub-core/normal/menu.c
+++ b/grub-core/normal/menu.c
@@ -975,13 +975,14 @@ show_menu (grub_menu_t menu, int nested, int autobooted)
if (! e)
continue; /* Menu is empty. */
- grub_cls ();
-
if (auto_boot)
grub_menu_execute_with_fallback (menu, e, autobooted,
&execution_callback, &notify_boot);
else
- grub_menu_execute_entry (e, 0);
+ {
+ grub_cls ();
+ grub_menu_execute_entry (e, 0);
+ }
if (autobooted)
break;
}
diff --git a/grub-core/term/efi/console.c b/grub-core/term/efi/console.c
index bb587f39d..258b52737 100644
--- a/grub-core/term/efi/console.c
+++ b/grub-core/term/efi/console.c
@@ -432,7 +432,7 @@ grub_console_cls (struct grub_term_output *term __attribute__ ((unused)))
grub_efi_simple_text_output_interface_t *o;
grub_efi_int32_t orig_attr;
- if (grub_efi_is_finished || text_mode != GRUB_TEXT_MODE_AVAILABLE)
+ if (grub_prepare_for_text_output (term) != GRUB_ERR_NONE)
return;
o = grub_efi_system_table->con_out;
--
2.45.1

View File

@ -1,44 +0,0 @@
From a59b58f6ae327a8f6949991cb5531db01e1ba14d Mon Sep 17 00:00:00 2001
From: Wen Xiong <wenxiong@linux.ibm.com>
Date: Tue, 7 Feb 2023 15:10:15 -0500
Subject: [PATCH] grub2: Can't setup a default boot device correctly on nvme
device in Beta3
The patch in Bug 200486 - SUSE1205666 - SLES15SP5 Beta1: Setup multiple dev path
for a nvmf boot device in grub2 caused the issue. That patch didn't consider
nvme devices carefully.
The new patch will check "nvme-of" instead of "nvme" to call
build_multi_boot_device().
Signed-off-by: Wen Xiong<wenxiong@linux.ibm.com>
---
grub-core/osdep/unix/platform.c | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/grub-core/osdep/unix/platform.c b/grub-core/osdep/unix/platform.c
index db8fa4b95..fb47c0ffa 100644
--- a/grub-core/osdep/unix/platform.c
+++ b/grub-core/osdep/unix/platform.c
@@ -288,11 +288,15 @@ grub_install_register_ieee1275 (int is_prep, const char *install_device,
}
*ptr = '\0';
}
- else if (grub_strstr(install_device, "nvme"))
- boot_device = build_multi_boot_device(install_device);
- else
+ else {
boot_device = get_ofpathname (install_device);
+ if (grub_strstr(boot_device, "nvme-of")) {
+ free (boot_device);
+ boot_device = build_multi_boot_device(install_device);
+ }
+ }
+
if (grub_util_exec ((const char * []){ "nvsetenv", "boot-device",
boot_device, NULL }))
{
--
2.39.1

View File

@ -1,164 +0,0 @@
From 3e77c5494fd06f430588ae9c304fea370439d531 Mon Sep 17 00:00:00 2001
From: Wen Xiong <Wen Xiong>
Date: Thu, 15 Dec 2022 21:33:41 -0500
Subject: [PATCH] grub2: Set multiple device path for a nvmf boot device
nvmf support native multipath(ANA) by default.
The patch added the support for setting multiple
device path for a nvmf boot device.
localhost:~ grub2-install -v /dev/nvme1n1p1
...
...
...
grub2-install: info: executing nvsetenv boot-device /pci@800000020000132/fibre-channel@0,1/nvme-of/controller@5005076810193675,ffff:nqn=nqn.1986-03.com.ibm:nvme:2145.0000020420006CEA/namespace@ec /pci@800000020000132/fibre-channel@0/nvme-of/controller@5005076810193675,ffff:nqn=nqn.1986-03.com.ibm:nvme:2145.0000020420006CEA/namespace@ec /pci@800000020000132/fibre-channel@0/nvme-of/controller@50050768101935e5,ffff:nqn=nqn.1986-03.com.ibm:nvme:2145.0000020420006CEA/namespace@ec /pci@800000020000132/fibre-channel@0,1/nvme-of/controller@50050768101935e5,ffff:nqn=nqn.1986-03.com.ibm:nvme:2145.0000020420006CEA/namespace@ec.
Installation finished. No error reported.
localhost:~ # bootlist -m normal -o
nvme7n1
nvme5n1
nvme1n1
nvme4n1
localhost:~ # bootlist -m normal -r
/pci@800000020000132/fibre-channel@0,1/nvme-of/controller@5005076810193675,ffff:nqn=nqn.1986-03.com.ibm:nvme:2145.0000020420006CEA/namespace@ec
/pci@800000020000132/fibre-channel@0/nvme-of/controller@5005076810193675,ffff:nqn=nqn.1986-03.com.ibm:nvme:2145.0000020420006CEA/namespace@ec
/pci@800000020000132/fibre-channel@0/nvme-of/controller@50050768101935e5,ffff:nqn=nqn.1986-03.com.ibm:nvme:2145.0000020420006CEA/namespace@ec
/pci@800000020000132/fibre-channel@0,1/nvme-of/controller@50050768101935e5,ffff:nqn=nqn.1986-03.com.ibm:nvme:2145.0000020420006CEA/namespace@ec
Signed-off-by: Wen Xiong <wenxiong@linux.ibm.com>
---
grub-core/osdep/linux/ofpath.c | 6 ++---
grub-core/osdep/unix/platform.c | 48 +++++++++++++++++++++++++++++++++
include/grub/util/install.h | 3 +++
include/grub/util/ofpath.h | 9 +++++++
4 files changed, 63 insertions(+), 3 deletions(-)
--- a/grub-core/osdep/linux/ofpath.c
+++ b/grub-core/osdep/linux/ofpath.c
@@ -209,7 +209,7 @@
}
}
-static char *
+char *
xrealpath (const char *in)
{
char *out;
@@ -224,7 +224,7 @@
return out;
}
-static char *
+char *
block_device_get_sysfs_path_and_link(const char *devicenode)
{
char *rpath;
@@ -535,7 +535,7 @@
}
-static char *
+char *
nvme_get_syspath(const char *nvmedev)
{
char *sysfs_path, *controller_node;
--- a/grub-core/osdep/unix/platform.c
+++ b/grub-core/osdep/unix/platform.c
@@ -19,6 +19,7 @@
#include <config.h>
#include <grub/util/install.h>
+#include <grub/util/ofpath.h>
#include <grub/emu/hostdisk.h>
#include <grub/util/misc.h>
#include <grub/misc.h>
@@ -131,6 +132,51 @@
return rc;
}
+char *
+build_multi_boot_device(const char *install_device)
+{
+ char *sysfs_path;
+ char *nvme_ns;
+ unsigned int nsid;
+ char *ptr;
+ char *boot_device_string;
+ struct dirent *ep;
+ DIR *dp;
+
+ nvme_ns = strchr(install_device, 'n');
+ nsid = of_path_get_nvme_nsid(nvme_ns);
+ sysfs_path = nvme_get_syspath(nvme_ns);
+ strcat(sysfs_path, "/device");
+ sysfs_path = xrealpath(sysfs_path);
+
+ dp = opendir(sysfs_path);
+ ptr = boot_device_string = xmalloc (1000);
+
+ /* We cannot have a boot list with more than five entries */
+ while((ep = readdir(dp)) != NULL){
+ char *nvme_device;
+
+ if (grub_strstr(ep->d_name, "nvme")) {
+ nvme_device = xasprintf ("%s%s%x ",
+ get_ofpathname(ep->d_name),"/namespace@", nsid);
+ if ((strlen(boot_device_string) + strlen(nvme_device)) >= 200*5 - 1) {
+ grub_util_warn (_("More than five entries cannot be specified in the bootlist"));
+ free(nvme_device);
+ break;
+ }
+
+ strncpy(ptr, nvme_device, strlen(nvme_device));
+ ptr += strlen(nvme_device);
+ free(nvme_device);
+ }
+ }
+
+ *--ptr = '\0';
+ closedir(dp);
+
+ return boot_device_string;
+}
+
int
grub_install_register_efi (const grub_disk_t *efidir_grub_disk,
const char *efifile_path,
@@ -242,6 +288,8 @@
}
*ptr = '\0';
}
+ else if (grub_strstr(install_device, "nvme"))
+ boot_device = build_multi_boot_device(install_device);
else
boot_device = get_ofpathname (install_device);
--- a/include/grub/util/install.h
+++ b/include/grub/util/install.h
@@ -241,6 +241,9 @@
const char *efi_distributor,
const char *force_disk);
+char *
+build_multi_boot_device(const char *install_device);
+
void
grub_install_register_ieee1275 (int is_prep, const char *install_device,
int partno, const char *relpath);
--- a/include/grub/util/ofpath.h
+++ b/include/grub/util/ofpath.h
@@ -32,4 +32,13 @@
char* of_find_fc_host(char* host_wwpn);
+char* nvme_get_syspath(const char *nvmedev);
+
+char* block_device_get_sysfs_path_and_link(const char *devicenode);
+
+char* xrealpath (const char *in);
+
+unsigned int of_path_get_nvme_nsid(const char* devname);
+
+
#endif /* ! GRUB_OFPATH_MACHINE_UTIL_HEADER */

View File

@ -0,0 +1,171 @@
From 04e8509f04a4cd123bc9f290e60f582d57b2f258 Mon Sep 17 00:00:00 2001
From: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
Date: Tue, 27 Dec 2022 17:47:41 +0530
Subject: [PATCH 1/8] ieee1275: Platform Keystore (PKS) Support
enhancing the infrastructure to enable the Platform Keystore (PKS) feature,
which provides access to the SB VERSION, DB, and DBX secure boot variables
from PKS.
Signed-off-by: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
Tested-by: Nageswara Sastry <rnsastry@linux.ibm.com>
---
grub-core/kern/ieee1275/ieee1275.c | 117 +++++++++++++++++++++++++++++
include/grub/ieee1275/ieee1275.h | 15 ++++
2 files changed, 132 insertions(+)
diff --git a/grub-core/kern/ieee1275/ieee1275.c b/grub-core/kern/ieee1275/ieee1275.c
index 36ca2dbfc..8d0048844 100644
--- a/grub-core/kern/ieee1275/ieee1275.c
+++ b/grub-core/kern/ieee1275/ieee1275.c
@@ -807,3 +807,120 @@ grub_ieee1275_get_block_size (grub_ieee1275_ihandle_t ihandle)
return args.size;
}
+
+int
+grub_ieee1275_test (const char *name, grub_ieee1275_cell_t *missing)
+{
+ struct test_args
+ {
+ struct grub_ieee1275_common_hdr common;
+ grub_ieee1275_cell_t name;
+ grub_ieee1275_cell_t missing;
+ } args;
+
+ INIT_IEEE1275_COMMON (&args.common, "test", 1, 1);
+ args.name = (grub_ieee1275_cell_t) name;
+
+ if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
+ return -1;
+
+ if (args.missing == IEEE1275_CELL_INVALID)
+ return -1;
+
+ *missing = args.missing;
+
+ return 0;
+}
+
+int
+grub_ieee1275_pks_max_object_size (grub_size_t *result)
+{
+ struct mos_args
+ {
+ struct grub_ieee1275_common_hdr common;
+ grub_ieee1275_cell_t size;
+ } args;
+
+ INIT_IEEE1275_COMMON (&args.common, "pks-max-object-size", 0, 1);
+
+ if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
+ return -1;
+
+ if (args.size == IEEE1275_CELL_INVALID)
+ return -1;
+
+ *result = args.size;
+
+ return 0;
+}
+
+int
+grub_ieee1275_pks_read_object (grub_uint8_t consumer, grub_uint8_t *label,
+ grub_size_t label_len, grub_uint8_t *buffer,
+ grub_size_t buffer_len, grub_size_t *data_len,
+ grub_uint32_t *policies)
+{
+ struct pks_read_args
+ {
+ struct grub_ieee1275_common_hdr common;
+ grub_ieee1275_cell_t consumer;
+ grub_ieee1275_cell_t label;
+ grub_ieee1275_cell_t label_len;
+ grub_ieee1275_cell_t buffer;
+ grub_ieee1275_cell_t buffer_len;
+ grub_ieee1275_cell_t data_len;
+ grub_ieee1275_cell_t policies;
+ grub_ieee1275_cell_t rc;
+ } args;
+
+ INIT_IEEE1275_COMMON (&args.common, "pks-read-object", 5, 3);
+ args.consumer = (grub_ieee1275_cell_t) consumer;
+ args.label = (grub_ieee1275_cell_t) label;
+ args.label_len = (grub_ieee1275_cell_t) label_len;
+ args.buffer = (grub_ieee1275_cell_t) buffer;
+ args.buffer_len = (grub_ieee1275_cell_t) buffer_len;
+
+ if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
+ return -1;
+
+ if (args.data_len == IEEE1275_CELL_INVALID)
+ return -1;
+
+ *data_len = args.data_len;
+ *policies = args.policies;
+
+ return (int) args.rc;
+}
+
+int
+grub_ieee1275_pks_read_sbvar (grub_uint8_t sbvarflags, grub_uint8_t sbvartype,
+ grub_uint8_t *buffer, grub_size_t buffer_len,
+ grub_size_t *data_len)
+{
+ struct pks_read_sbvar_args
+ {
+ struct grub_ieee1275_common_hdr common;
+ grub_ieee1275_cell_t sbvarflags;
+ grub_ieee1275_cell_t sbvartype;
+ grub_ieee1275_cell_t buffer;
+ grub_ieee1275_cell_t buffer_len;
+ grub_ieee1275_cell_t data_len;
+ grub_ieee1275_cell_t rc;
+ } args;
+
+ INIT_IEEE1275_COMMON (&args.common, "pks-read-sbvar", 4, 2);
+ args.sbvarflags = (grub_ieee1275_cell_t) sbvarflags;
+ args.sbvartype = (grub_ieee1275_cell_t) sbvartype;
+ args.buffer = (grub_ieee1275_cell_t) buffer;
+ args.buffer_len = (grub_ieee1275_cell_t) buffer_len;
+
+ if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
+ return -1;
+
+ if (args.data_len == IEEE1275_CELL_INVALID)
+ return -1;
+
+ *data_len = args.data_len;
+
+ return (int) args.rc;
+}
diff --git a/include/grub/ieee1275/ieee1275.h b/include/grub/ieee1275/ieee1275.h
index ea90d79f7..6d8dd9463 100644
--- a/include/grub/ieee1275/ieee1275.h
+++ b/include/grub/ieee1275/ieee1275.h
@@ -237,6 +237,21 @@ char *EXPORT_FUNC(grub_ieee1275_encode_uint4) (grub_ieee1275_ihandle_t ihandle,
grub_size_t *size);
int EXPORT_FUNC(grub_ieee1275_get_block_size) (grub_ieee1275_ihandle_t ihandle);
+int EXPORT_FUNC (grub_ieee1275_test) (const char *name,
+ grub_ieee1275_cell_t *missing);
+
+// not exported: I don't want modules interacting with PKS.
+int grub_ieee1275_pks_max_object_size (grub_size_t *result);
+
+int grub_ieee1275_pks_read_object (grub_uint8_t consumer, grub_uint8_t *label,
+ grub_size_t label_len, grub_uint8_t *buffer,
+ grub_size_t buffer_len, grub_size_t *data_len,
+ grub_uint32_t *policies);
+
+int grub_ieee1275_pks_read_sbvar (grub_uint8_t sbvarflags, grub_uint8_t sbvartype,
+ grub_uint8_t *buffer, grub_size_t buffer_len,
+ grub_size_t *data_len);
+
grub_err_t EXPORT_FUNC(grub_claimmap) (grub_addr_t addr, grub_size_t size);
void EXPORT_FUNC(grub_releasemap) (void);
--
2.47.0

View File

@ -0,0 +1,170 @@
From 219b06c69d38a10349183002efb82bfec3b7ff5b Mon Sep 17 00:00:00 2001
From: Avnish Chouhan <avnish@linux.ibm.com>
Date: Wed, 21 Aug 2024 14:13:05 +0530
Subject: [PATCH] ieee1275: support added for multiple nvme bootpaths
This patch sets mupltiple NVMe boot-devices for more robust boot.
Scenario where NVMe multipaths are available, all the available bootpaths (Max 5)
will be added as the boot-device.
Signed-off-by: Avnish Chouhan <avnish@linux.ibm.com>
---
grub-core/osdep/linux/ofpath.c | 6 +--
grub-core/osdep/unix/platform.c | 65 ++++++++++++++++++++++++++++++++-
include/grub/util/install.h | 3 ++
include/grub/util/ofpath.h | 4 ++
4 files changed, 74 insertions(+), 4 deletions(-)
diff --git a/grub-core/osdep/linux/ofpath.c b/grub-core/osdep/linux/ofpath.c
index 51d331f06..55ed7ddf2 100644
--- a/grub-core/osdep/linux/ofpath.c
+++ b/grub-core/osdep/linux/ofpath.c
@@ -209,7 +209,7 @@ find_obppath (const char *sysfs_path_orig)
}
}
-static char *
+char *
xrealpath (const char *in)
{
char *out;
@@ -224,7 +224,7 @@ xrealpath (const char *in)
return out;
}
-static char *
+char *
block_device_get_sysfs_path_and_link(const char *devicenode)
{
char *rpath;
@@ -535,7 +535,7 @@ of_path_get_nvme_nsid(const char* devname)
}
-static char *
+char *
nvme_get_syspath(const char *nvmedev)
{
char *sysfs_path, *controller_node;
diff --git a/grub-core/osdep/unix/platform.c b/grub-core/osdep/unix/platform.c
index 1e2961e00..bafcc84d7 100644
--- a/grub-core/osdep/unix/platform.c
+++ b/grub-core/osdep/unix/platform.c
@@ -28,6 +28,8 @@
#include <dirent.h>
#include <string.h>
#include <errno.h>
+#include <grub/util/ofpath.h>
+#define BOOTDEV_BUFFER 1000
static char *
get_ofpathname (const char *dev)
@@ -203,6 +205,56 @@ grub_install_register_efi (const grub_disk_t *efidir_grub_disk,
return 0;
}
+char *
+add_multiple_nvme_bootdevices (const char *install_device)
+{
+ char *sysfs_path, *nvme_ns, *ptr;
+ unsigned int nsid;
+ char *multipath_boot;
+ struct dirent *ep;
+ DIR *dp;
+
+ /*
+ * Extracting the namespace from install_device.
+ * ex. install_device : /dev/nvme1n1
+ */
+ nvme_ns = grub_strstr (install_device, "nvme");
+ nsid = of_path_get_nvme_nsid (nvme_ns);
+ if (nsid == 0)
+ return NULL;
+
+ sysfs_path = nvme_get_syspath (nvme_ns);
+ strcat (sysfs_path, "/subsystem");
+ sysfs_path = xrealpath (sysfs_path);
+ dp = opendir (sysfs_path);
+ if (!dp)
+ return NULL;
+
+ ptr = multipath_boot = xmalloc (BOOTDEV_BUFFER);
+ while ((ep = readdir (dp)) != NULL)
+ {
+ char *path;
+ if (grub_strstr (ep->d_name, "nvme"))
+ {
+ path = xasprintf ("%s%s%x ", get_ofpathname (ep->d_name), "/namespace@", nsid);
+ if ((strlen (multipath_boot) + strlen (path)) > BOOTDEV_BUFFER)
+ {
+ grub_util_warn (_("Maximum five entries are allowed in the bootlist"));
+ free (path);
+ break;
+ }
+ strncpy (ptr, path, strlen (path));
+ ptr += strlen (path);
+ free (path);
+ }
+ }
+
+ *--ptr = '\0';
+ closedir (dp);
+
+ return multipath_boot;
+}
+
void
grub_install_register_ieee1275 (int is_prep, const char *install_device,
int partno, const char *relpath)
@@ -242,8 +294,19 @@ grub_install_register_ieee1275 (int is_prep, const char *install_device,
}
*ptr = '\0';
}
+ else if (grub_strstr (install_device, "nvme"))
+ {
+ boot_device = add_multiple_nvme_bootdevices (install_device);
+ }
else
- boot_device = get_ofpathname (install_device);
+ {
+ boot_device = get_ofpathname (install_device);
+ if (grub_strstr (boot_device, "nvme-of"))
+ {
+ free (boot_device);
+ boot_device = add_multiple_nvme_bootdevices (install_device);
+ }
+ }
if (grub_util_exec ((const char * []){ "nvsetenv", "boot-device",
boot_device, NULL }))
diff --git a/include/grub/util/install.h b/include/grub/util/install.h
index 563cf68e9..2fd102649 100644
--- a/include/grub/util/install.h
+++ b/include/grub/util/install.h
@@ -241,6 +241,9 @@ grub_install_register_efi (const grub_disk_t *efidir_grub_disk,
const char *efi_distributor,
const char *force_disk);
+char *
+add_multiple_nvme_bootdevices (const char *install_device);
+
void
grub_install_register_ieee1275 (int is_prep, const char *install_device,
int partno, const char *relpath);
diff --git a/include/grub/util/ofpath.h b/include/grub/util/ofpath.h
index a0ec30620..cc3c4bfbd 100644
--- a/include/grub/util/ofpath.h
+++ b/include/grub/util/ofpath.h
@@ -31,5 +31,9 @@ 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);
+char* nvme_get_syspath (const char *nvmedev);
+char* block_device_get_sysfs_path_and_link (const char *devicenode);
+char* xrealpath (const char *in);
+unsigned int of_path_get_nvme_nsid (const char* devname);
#endif /* ! GRUB_OFPATH_MACHINE_UTIL_HEADER */
--
2.47.0

View File

@ -0,0 +1,122 @@
From ba65f46ffd2952a3f69d85a4534b1e55291f080c Mon Sep 17 00:00:00 2001
From: Avnish Chouhan <avnish@linux.ibm.com>
Date: Thu, 23 May 2024 18:43:14 +0530
Subject: [PATCH] kern/ieee1275/init: Add IEEE 1275 Radix support for KVM on
Power
This patch adds support for Radix, Xive and Radix_gtse in Options
vector5 which is required for KVM LPARs. KVM LPARs ONLY support
Radix and not the Hash. Not enabling Radix on any PowerVM KVM LPARs
will result in boot failure.
Signed-off-by: Avnish Chouhan <avnish@linux.ibm.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
grub-core/kern/ieee1275/init.c | 63 +++++++++++++++++++++++++++++++++-
1 file changed, 62 insertions(+), 1 deletion(-)
diff --git a/grub-core/kern/ieee1275/init.c b/grub-core/kern/ieee1275/init.c
index bb800b275..8e08e5dd5 100644
--- a/grub-core/kern/ieee1275/init.c
+++ b/grub-core/kern/ieee1275/init.c
@@ -115,6 +115,16 @@ grub_addr_t grub_ieee1275_original_stack;
#define DRC_INFO 0x40
#define BYTE22 (DY_MEM_V2 | DRC_INFO)
+/* For ibm,arch-vec-5-platform-support. */
+#define XIVE_INDEX 0x17
+#define MMU_INDEX 0x18
+#define RADIX_GTSE_INDEX 0x1a
+#define RADIX_ENABLED 0x40
+#define XIVE_ENABLED 0x40
+#define HASH_ENABLED 0x00
+#define MAX_SUPPORTED 0xC0
+#define RADIX_GTSE_ENABLED 0x40
+
void
grub_exit (void)
{
@@ -740,6 +750,10 @@ struct option_vector5
grub_uint32_t platform_facilities;
grub_uint8_t sub_processors;
grub_uint8_t byte22;
+ grub_uint8_t xive;
+ grub_uint8_t mmu;
+ grub_uint8_t hpt_ext;
+ grub_uint8_t radix_gtse;
} GRUB_PACKED;
struct pvr_entry
@@ -778,6 +792,13 @@ grub_ieee1275_ibm_cas (void)
{
int rc;
grub_ieee1275_ihandle_t root;
+ grub_uint8_t ibm_arch_platform_support[8];
+ grub_ssize_t actual;
+ grub_uint8_t xive_support = 0;
+ grub_uint8_t mmu_support = 0;
+ grub_uint8_t radix_gtse_support = 0;
+ int i = 0;
+ int prop_len = 8;
struct cas_args
{
struct grub_ieee1275_common_hdr common;
@@ -786,6 +807,46 @@ grub_ieee1275_ibm_cas (void)
grub_ieee1275_cell_t cas_addr;
grub_ieee1275_cell_t result;
} args;
+
+ grub_ieee1275_get_integer_property (grub_ieee1275_chosen,
+ "ibm,arch-vec-5-platform-support",
+ (grub_uint32_t *) ibm_arch_platform_support,
+ sizeof (ibm_arch_platform_support),
+ &actual);
+
+ for (i = 0; i < prop_len; i++)
+ {
+ switch (ibm_arch_platform_support[i])
+ {
+ case XIVE_INDEX:
+ if (ibm_arch_platform_support[i + 1] & MAX_SUPPORTED)
+ xive_support = XIVE_ENABLED;
+ else
+ xive_support = 0;
+ break;
+
+ case MMU_INDEX:
+ if (ibm_arch_platform_support[i + 1] & MAX_SUPPORTED)
+ mmu_support = RADIX_ENABLED;
+ else
+ mmu_support = HASH_ENABLED;
+ break;
+
+ case RADIX_GTSE_INDEX:
+ if (mmu_support == RADIX_ENABLED)
+ radix_gtse_support = ibm_arch_platform_support[i + 1] & RADIX_GTSE_ENABLED;
+ else
+ radix_gtse_support = 0;
+ break;
+
+ default:
+ /* Ignoring the other indexes of ibm,arch-vec-5-platform-support. */
+ break;
+ }
+ /* Skipping the property value. */
+ i++;
+ }
+
struct cas_vector vector =
{
.pvr_list = { { 0x00000000, 0xffffffff } }, /* any processor */
@@ -802,7 +863,7 @@ grub_ieee1275_ibm_cas (void)
.vec4 = 0x0001, /* set required minimum capacity % to the lowest value */
.vec5_size = 1 + sizeof (struct option_vector5) - 2,
.vec5 = {
- 0, BYTE2, 0, CMO, ASSOCIATIVITY, BIN_OPTS, 0, 0, MAX_CPU, 0, 0, PLATFORM_FACILITIES, SUB_PROCESSORS, BYTE22
+ 0, BYTE2, 0, CMO, ASSOCIATIVITY, BIN_OPTS, 0, 0, MAX_CPU, 0, 0, PLATFORM_FACILITIES, SUB_PROCESSORS, BYTE22, xive_support, mmu_support, 0, radix_gtse_support
}
};
--
2.47.0

View File

@ -0,0 +1,44 @@
From cda4b7a415eb45743ea54a7760b302c0cfe718cf Mon Sep 17 00:00:00 2001
From: Michael Chang <mchang@suse.com>
Date: Mon, 23 Sep 2024 10:32:18 +0800
Subject: [PATCH] tpm: Skip loopback image measurement
The loopback image is configured to function as a disk by being mapped
as a block device. Instead of measuring the entire block device, we
should focus on tracking the individual files accessed from it. For
example, we do not directly measure block devices like disk hd0, but the
files opened from it.
This method is important to avoid running out of memory, since loopback
images can be very large. Trying to read and measure the whole image at
once could cause out of memory errors and disrupt the boot process.
Signed-Off-by: Michael Chang <mchang@suse.com>
---
grub-core/commands/tpm.c | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/grub-core/commands/tpm.c b/grub-core/commands/tpm.c
index bb9aee210..ebbb4fef0 100644
--- a/grub-core/commands/tpm.c
+++ b/grub-core/commands/tpm.c
@@ -41,6 +41,16 @@ grub_tpm_verify_init (grub_file_t io,
{
*context = io->name;
*flags |= GRUB_VERIFY_FLAGS_SINGLE_CHUNK;
+
+ /*
+ * The loopback image is mapped as a disk, allowing it to function like a
+ * block device. However, we measure the files read from the block device,
+ * not the device itself. For example, we don't measure block devices like
+ * disk hd0 directly. This process is crucial to prevent out-of-memory
+ * errors, as loopback images are inherently large.
+ */
+ if ((type & GRUB_FILE_TYPE_MASK) == GRUB_FILE_TYPE_LOOPBACK)
+ *flags = GRUB_VERIFY_FLAGS_SKIP_VERIFICATION;
return GRUB_ERR_NONE;
}
--
2.46.1

View File

@ -0,0 +1,671 @@
From 8ef821ea18ed35f5969b98f2df6a76fefb71b175 Mon Sep 17 00:00:00 2001
From: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
Date: Wed, 28 Dec 2022 17:49:24 +0530
Subject: [PATCH 2/8] ieee1275: Read the DB and DBX secure boot variables
If secure boot is enabled with PKS, it will read secure boot variables
such as db and dbx from PKS and extract certificates from ESL.
It would be saved in the platform keystore buffer, and
the appendedsig (module) would read it later to extract
the certificate's details.
In the following scenarios, static key mode will be activated:
1. When secure boot is enabled with static
2. When SB Version is unavailable but Secure Boot is enabled
3. When PKS support is unavailable but secure boot is enabled
Note:-
SB Version - secure boot mode
1 - PKS
0 - static key (embeded key)
Signed-off-by: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
Tested-by: Nageswara Sastry <rnsastry@linux.ibm.com>
---
grub-core/Makefile.am | 1 +
grub-core/Makefile.core.def | 1 +
grub-core/kern/ieee1275/init.c | 12 +-
grub-core/kern/ieee1275/platform_keystore.c | 377 ++++++++++++++++++++
include/grub/platform_keystore.h | 190 ++++++++++
5 files changed, 580 insertions(+), 1 deletion(-)
create mode 100644 grub-core/kern/ieee1275/platform_keystore.c
create mode 100644 include/grub/platform_keystore.h
diff --git a/grub-core/Makefile.am b/grub-core/Makefile.am
index 9d3d5f519..4630e2ba3 100644
--- a/grub-core/Makefile.am
+++ b/grub-core/Makefile.am
@@ -79,6 +79,7 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/file.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/fs.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i18n.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/kernel.h
+KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/platform_keystore.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/list.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/lockdown.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/misc.h
diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
index dc639dd24..4ff35afb7 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -170,6 +170,7 @@ kernel = {
ieee1275 = kern/ieee1275/openfw.c;
ieee1275 = term/ieee1275/console.c;
ieee1275 = kern/ieee1275/init.c;
+ ieee1275 = kern/ieee1275/platform_keystore.c;
uboot = disk/uboot/ubootdisk.c;
uboot = kern/uboot/uboot.c;
diff --git a/grub-core/kern/ieee1275/init.c b/grub-core/kern/ieee1275/init.c
index 38f1f1f6e..bb800b275 100644
--- a/grub-core/kern/ieee1275/init.c
+++ b/grub-core/kern/ieee1275/init.c
@@ -50,6 +50,7 @@
#include <grub/ieee1275/alloc.h>
#endif
#include <grub/lockdown.h>
+#include <grub/platform_keystore.h>
/* The maximum heap size we're going to claim at boot. Not used by sparc. */
#ifdef __i386__
@@ -915,7 +916,16 @@ grub_get_ieee1275_secure_boot (void)
* We only support enforce.
*/
if (rc >= 0 && is_sb >= 2)
- grub_lockdown ();
+ {
+ grub_printf ("secure boot enabled\n");
+ rc = grub_platform_keystore_init ();
+ if (rc != GRUB_ERR_NONE)
+ grub_printf ("Warning: initialization of the platform keystore failed!\n");
+
+ grub_lockdown ();
+ }
+ else
+ grub_printf ("secure boot disabled\n");
}
grub_addr_t grub_modbase;
diff --git a/grub-core/kern/ieee1275/platform_keystore.c b/grub-core/kern/ieee1275/platform_keystore.c
new file mode 100644
index 000000000..976e4e9b5
--- /dev/null
+++ b/grub-core/kern/ieee1275/platform_keystore.c
@@ -0,0 +1,377 @@
+#include <grub/mm.h>
+#include <grub/ieee1275/ieee1275.h>
+#include <grub/types.h>
+#include <grub/misc.h>
+#include <grub/lockdown.h>
+#include <grub/platform_keystore.h>
+
+#define PKS_CONSUMER_FW 1
+#define SB_VERSION_KEY_NAME ((grub_uint8_t *) "SB_VERSION")
+#define SB_VERSION_KEY_LEN 10
+#define DB 1
+#define DBX 2
+
+#define PKS_OBJECT_NOT_FOUND -7
+#define PKS_UNPACK_ERROR 0x200
+#define PKS_UNPACK_VERSION_ERROR 0x201
+
+struct pks_timestamp
+{
+ grub_uint16_t year;
+ grub_uint8_t month;
+ grub_uint8_t day;
+ grub_uint8_t hour;
+ grub_uint8_t minute;
+ grub_uint8_t second;
+} GRUB_PACKED;
+
+struct pks_signed_var
+{
+ grub_uint8_t version;
+ struct pks_timestamp time;
+} GRUB_PACKED;
+
+/* Platform Keystore */
+static grub_size_t pks_max_object_size;
+grub_uint8_t grub_use_platform_keystore = 0;
+grub_pks_t grub_platform_keystore = { .use_static_keys = 0, .db = NULL, .dbx = NULL, .db_entries = 0, .dbx_entries = 0 };
+
+/* converts the esl data into the ESL */
+static grub_esl_t *
+grub_convert_to_esl (const grub_uint8_t *esl_data, const grub_size_t esl_data_size)
+{
+ grub_esl_t *esl = NULL;
+
+ if (esl_data_size < sizeof (grub_esl_t) || esl_data == NULL)
+ return esl;
+
+ esl = (grub_esl_t *) esl_data;
+
+ return esl;
+}
+
+/*
+ * imports the GUID, esd, and its size into the pks sd buffer and
+ * pks sd entries from the EFI signature list.
+ */
+static grub_err_t
+grub_esd_from_esl (const grub_uint8_t *esl_data, grub_size_t esl_size,
+ const grub_size_t signature_size, const grub_uuid_t *guid,
+ grub_pks_sd_t **pks_sd, grub_size_t *pks_sd_entries)
+{
+ grub_esd_t *esd = NULL;
+ grub_pks_sd_t *signature = *pks_sd;
+ grub_size_t entries = *pks_sd_entries;
+ grub_size_t data_size = 0, offset = 0;
+
+ /* reads the esd from esl */
+ while (esl_size > 0)
+ {
+ esd = (grub_esd_t *) (esl_data + offset);
+ data_size = signature_size - sizeof (grub_esd_t);
+
+ if (signature != NULL)
+ signature = grub_realloc (signature, (entries + 1) * sizeof (grub_pks_sd_t));
+ else
+ signature = grub_malloc (sizeof (grub_pks_sd_t));
+
+ if (signature == NULL)
+ return grub_error (GRUB_ERR_OUT_OF_MEMORY, "out of memory");
+
+ signature[entries].data = grub_malloc (data_size * sizeof (grub_uint8_t));
+ if (signature[entries].data == NULL)
+ {
+ /*
+ * allocated memory will be freed by
+ * grub_release_platform_keystore
+ */
+ *pks_sd = signature;
+ *pks_sd_entries = entries + 1;
+ return grub_error (GRUB_ERR_OUT_OF_MEMORY, "out of memory");
+ }
+
+ grub_memcpy (signature[entries].data, esd->signaturedata, data_size);
+ signature[entries].data_size = data_size;
+ signature[entries].guid = *guid;
+ entries++;
+ esl_size -= signature_size;
+ offset += signature_size;
+ }
+
+ *pks_sd = signature;
+ *pks_sd_entries = entries;
+
+ return GRUB_ERR_NONE;
+}
+
+/*
+ * extracts the esd after removing the esl header from esl.
+ */
+static grub_err_t
+grub_esl_to_esd (const grub_uint8_t *esl_data, grub_size_t *next_esl,
+ grub_pks_sd_t **pks_sd, grub_size_t *pks_sd_entries)
+{
+ grub_uuid_t guid = { 0 };
+ grub_esl_t *esl = NULL;
+ grub_size_t offset = 0, esl_size = 0,
+ signature_size = 0, signature_header_size = 0;
+
+ esl = grub_convert_to_esl (esl_data, *next_esl);
+ if (esl == NULL)
+ return grub_error (GRUB_ERR_BUG, "invalid ESL");
+
+ esl_size = grub_le_to_cpu32 (esl->signaturelistsize);
+ signature_header_size = grub_le_to_cpu32 (esl->signatureheadersize);
+ signature_size = grub_le_to_cpu32 (esl->signaturesize);
+ guid = esl->signaturetype;
+
+ if (esl_size < sizeof (grub_esl_t) || esl_size > *next_esl)
+ return grub_error (GRUB_ERR_BUG, "invalid ESL size (%u)\n", esl_size);
+
+ *next_esl = esl_size;
+ offset = sizeof (grub_esl_t) + signature_header_size;
+ esl_size = esl_size - offset;
+
+ return grub_esd_from_esl (esl_data + offset, esl_size, signature_size, &guid,
+ pks_sd, pks_sd_entries);
+}
+
+/*
+ * imports the EFI signature data and the number of esd from the esl
+ * into the pks sd buffer and pks sd entries.
+ */
+static grub_err_t
+grub_pks_sd_from_esl (const grub_uint8_t *esl_data, grub_size_t esl_size,
+ grub_pks_sd_t **pks_sd, grub_size_t *pks_sd_entries)
+{
+ grub_err_t rc = GRUB_ERR_NONE;
+ grub_size_t next_esl = esl_size;
+
+ do
+ {
+ rc = grub_esl_to_esd (esl_data, &next_esl, pks_sd, pks_sd_entries);
+ if (rc != GRUB_ERR_NONE)
+ break;
+
+ esl_data += next_esl;
+ esl_size -= next_esl;
+ next_esl = esl_size;
+ }
+ while (esl_size > 0);
+
+ return rc;
+}
+
+/*
+ * unpacking the signed secure boot variable
+ * return error if size too small or version mismatch
+ * discards timestamp, only needed in verifying updates
+ */
+static grub_err_t
+grub_unpack_signed_variable (grub_uint8_t *indata, grub_size_t insize,
+ grub_uint8_t **data, grub_size_t *size)
+{
+ struct pks_signed_var *psv = NULL;
+
+ /* do not permit negative or size 0 data */
+ if (insize <= sizeof (struct pks_signed_var))
+ return PKS_UNPACK_ERROR;
+
+ psv = (struct pks_signed_var *) indata;
+ if (psv->version != 0)
+ return PKS_UNPACK_VERSION_ERROR;
+
+ *data = indata + sizeof (struct pks_signed_var);
+ *size = insize - sizeof (struct pks_signed_var);
+
+ return GRUB_ERR_NONE;
+}
+
+/*
+ * reads the secure boot version from PKS as an object.
+ * caller must free result
+ */
+static grub_err_t
+grub_sbversion_from_pks (grub_uint8_t **out, grub_size_t *outlen, grub_size_t *policy)
+{
+ *out = grub_malloc (pks_max_object_size);
+ if (*out == NULL)
+ return grub_error (GRUB_ERR_OUT_OF_MEMORY, "out of memory");
+
+ return grub_ieee1275_pks_read_object (PKS_CONSUMER_FW, SB_VERSION_KEY_NAME,
+ SB_VERSION_KEY_LEN, *out, pks_max_object_size,
+ outlen, policy);
+}
+
+/*
+ * reads the secure boot variable from PKS.
+ * caller must free result
+ */
+static grub_err_t
+grub_sbvar_from_pks (const grub_uint8_t sbvarflags, const grub_uint8_t sbvartype,
+ grub_uint8_t **out, grub_size_t *outlen)
+{
+ *out = grub_malloc (pks_max_object_size);
+ if (*out == NULL)
+ return grub_error (GRUB_ERR_OUT_OF_MEMORY, "out of memory");
+
+ return grub_ieee1275_pks_read_sbvar (sbvarflags, sbvartype, *out,
+ pks_max_object_size, outlen);
+}
+
+/* Test the availability of PKS support. */
+static grub_err_t
+grub_is_support_pks (void)
+{
+ grub_err_t rc = GRUB_ERR_NONE;
+ grub_ieee1275_cell_t missing = 0;
+
+ rc = grub_ieee1275_test ("pks-max-object-size", &missing);
+ if (rc != GRUB_ERR_NONE || (int) missing == -1)
+ grub_printf ("Warning: doesn't have PKS support!\n");
+ else
+ {
+ rc = grub_ieee1275_pks_max_object_size (&pks_max_object_size);
+ if (rc != GRUB_ERR_NONE)
+ grub_printf ("Warning: PKS support is there but it has zero objects!\n");
+ }
+
+ return rc;
+}
+
+/*
+ * retrieves the secure boot variable from PKS, unpacks it, reads the esd
+ * from ESL, and stores the information in the pks sd buffer.
+ */
+static grub_err_t
+grub_secure_boot_variables (const grub_uint8_t sbvarflags, const grub_uint8_t sbvartype,
+ grub_pks_sd_t **pks_sd, grub_size_t *pks_sd_entries)
+{
+ grub_err_t rc = GRUB_ERR_NONE;
+ grub_uint8_t *data = NULL, *esl_data = NULL;
+ grub_size_t data_len = 0, esl_data_size = 0;
+
+ rc = grub_sbvar_from_pks (sbvarflags, sbvartype, &data, &data_len);
+ /*
+ * at this point we have SB_VERSION, so any error is worth
+ * at least some user-visible info
+ */
+ if (rc != GRUB_ERR_NONE)
+ rc = grub_error (rc, "secure boot variable %s reading (%d)",
+ (sbvartype == DB ? "db" : "dbx"), rc);
+ else
+ {
+ rc = grub_unpack_signed_variable (data, data_len, &esl_data, &esl_data_size);
+ if (rc != GRUB_ERR_NONE)
+ rc = grub_error (rc, "unpacking of signed variable %s structure (%d)",
+ (sbvartype == DB ? "db" : "dbx"), rc);
+ else
+ rc = grub_pks_sd_from_esl ((const grub_uint8_t *) esl_data, esl_data_size,
+ pks_sd, pks_sd_entries);
+ }
+
+ grub_free (data);
+
+ return rc;
+}
+
+/* reads secure boot version (SB_VERSION) */
+static grub_err_t
+grub_secure_boot_version (void)
+{
+ grub_err_t rc = GRUB_ERR_NONE;
+ grub_uint8_t *data = NULL;
+ grub_size_t len = 0, policy = 0;
+
+ rc = grub_sbversion_from_pks (&data, &len, &policy);
+ if (rc != GRUB_ERR_NONE)
+ grub_printf ("Warning: SB version read failed! (%d)\n", rc);
+ else if (len != 1 || (*data != 1 && *data != 0))
+ {
+ grub_printf ("Warning: found unexpected SB version! (%d)\n", *data);
+ rc = GRUB_ERR_INVALID_COMMAND;
+ }
+
+ if (rc != GRUB_ERR_NONE)
+ {
+ grub_printf ("Warning: switch to static key!\n");
+ if (grub_is_lockdown () == GRUB_LOCKDOWN_ENABLED)
+ grub_fatal ("Secure Boot locked down");
+ }
+ else
+ grub_use_platform_keystore = *data;
+
+ grub_free (data);
+
+ return rc;
+}
+
+/* releasing allocated memory */
+void
+grub_release_platform_keystore (void)
+{
+ grub_size_t i = 0;
+
+ for (i = 0; i < grub_platform_keystore.db_entries; i++)
+ grub_free (grub_platform_keystore.db[i].data);
+
+ for (i = 0; i < grub_platform_keystore.dbx_entries; i++)
+ grub_free (grub_platform_keystore.dbx[i].data);
+
+ grub_free (grub_platform_keystore.db);
+ grub_free (grub_platform_keystore.dbx);
+ grub_memset (&grub_platform_keystore, 0x00, sizeof (grub_pks_t));
+}
+
+/* initialization of the Platform Keystore */
+grub_err_t
+grub_platform_keystore_init (void)
+{
+ grub_err_t rc = GRUB_ERR_NONE;
+
+ grub_printf ("trying to load Platform Keystore\n");
+
+ rc = grub_is_support_pks ();
+ if (rc != GRUB_ERR_NONE)
+ {
+ grub_printf ("Warning: switch to static key!\n");
+ return rc;
+ }
+
+ /* SB_VERSION */
+ rc = grub_secure_boot_version ();
+ if (rc != GRUB_ERR_NONE)
+ return rc;
+
+ if (grub_use_platform_keystore)
+ {
+ grub_memset (&grub_platform_keystore, 0x00, sizeof (grub_pks_t));
+ /* DB */
+ rc = grub_secure_boot_variables (0, DB, &grub_platform_keystore.db,
+ &grub_platform_keystore.db_entries);
+ if ((int)rc == PKS_OBJECT_NOT_FOUND)
+ {
+ rc = GRUB_ERR_NONE;
+ /* DB variable won't be available by default in PKS, So, it will loads the Default Keys from ELF Note */
+ grub_platform_keystore.use_static_keys = 1;
+ }
+
+ if (rc == GRUB_ERR_NONE)
+ {
+ /* DBX */
+ rc = grub_secure_boot_variables (0, DBX, &grub_platform_keystore.dbx,
+ &grub_platform_keystore.dbx_entries);
+ if ((int)rc == PKS_OBJECT_NOT_FOUND)
+ {
+ grub_printf ("Warning: dbx is not found!\n");
+ rc = GRUB_ERR_NONE;
+ }
+ }
+
+ }
+
+ if (rc != GRUB_ERR_NONE)
+ grub_release_platform_keystore ();
+
+ return rc;
+}
diff --git a/include/grub/platform_keystore.h b/include/grub/platform_keystore.h
new file mode 100644
index 000000000..8cc4266c9
--- /dev/null
+++ b/include/grub/platform_keystore.h
@@ -0,0 +1,190 @@
+#ifndef __PLATFORM_KEYSTORE_H__
+#define __PLATFORM_KEYSTORE_H__
+
+#include <grub/symbol.h>
+#include <grub/mm.h>
+#include <grub/types.h>
+
+#if __GNUC__ >= 9
+#pragma GCC diagnostic ignored "-Waddress-of-packed-member"
+#endif
+
+#define GRUB_UUID_SIZE 16
+#define GRUB_MAX_HASH_SIZE 64
+
+typedef struct grub_uuid grub_uuid_t;
+typedef struct grub_esd grub_esd_t;
+typedef struct grub_esl grub_esl_t;
+
+/* The structure of a UUID.*/
+struct grub_uuid
+{
+ grub_uint8_t b[GRUB_UUID_SIZE];
+};
+
+/* The structure of an EFI signature database (ESD).*/
+struct grub_esd
+{
+ /*
+ * An identifier which identifies the agent which added
+ * the signature to the list.
+ */
+ grub_uuid_t signatureowner;
+ /* The format of the signature is defined by the SignatureType.*/
+ grub_uint8_t signaturedata[];
+} GRUB_PACKED;
+
+/* The structure of an EFI signature list (ESL).*/
+struct grub_esl
+{
+ /* Type of the signature. GUID signature types are defined in below.*/
+ grub_uuid_t signaturetype;
+ /* Total size of the signature list, including this header.*/
+ grub_uint32_t signaturelistsize;
+ /*
+ * Size of the signature header which precedes
+ * the array of signatures.
+ */
+ grub_uint32_t signatureheadersize;
+ /* Size of each signature.*/
+ grub_uint32_t signaturesize;
+} GRUB_PACKED;
+
+/*
+ * The GRUB_PKS_CERT_* is derived from the following files referred from edk2-staging[1] repo
+ * of tianocore
+ *
+ * MdePkg/Include/Guid/ImageAuthentication.h
+ *
+ * [1] https://github.com/tianocore/edk2-staging
+ */
+
+#define GRUB_PKS_CERT_X509_GUID \
+ (grub_uuid_t) \
+ { \
+ { \
+ 0xa1, 0x59, 0xc0, 0xa5, 0xe4, 0x94, \
+ 0xa7, 0x4a, 0x87, 0xb5, 0xab, 0x15, \
+ 0x5c, 0x2b, 0xf0, 0x72 \
+ } \
+ }
+
+#define GRUB_PKS_CERT_SHA1_GUID \
+ (grub_uuid_t) \
+ { \
+ { \
+ 0x12, 0xa5, 0x6c, 0x82, 0x10, 0xcf, \
+ 0xc9, 0x4a, 0xb1, 0x87, 0xbe, 0x1, \
+ 0x49, 0x66, 0x31, 0xbd \
+ } \
+ }
+
+#define GRUB_PKS_CERT_SHA224_GUID \
+ (grub_uuid_t) \
+ { \
+ { \
+ 0x33, 0x52, 0x6e, 0xb, 0x5c, 0xa6, \
+ 0xc9, 0x44, 0x94, 0x7, 0xd9, 0xab, \
+ 0x83, 0xbf, 0xc8, 0xbd \
+ } \
+ }
+
+#define GRUB_PKS_CERT_SHA256_GUID \
+ (grub_uuid_t) \
+ { \
+ { \
+ 0x26, 0x16, 0xc4, 0xc1, 0x4c, 0x50, \
+ 0x92, 0x40, 0xac, 0xa9, 0x41, 0xf9, \
+ 0x36, 0x93, 0x43, 0x28 \
+ } \
+ }
+
+#define GRUB_PKS_CERT_SHA384_GUID \
+ (grub_uuid_t) \
+ { \
+ { \
+ 0x07, 0x53, 0x3e, 0xff, 0xd0, 0x9f, \
+ 0xc9, 0x48, 0x85, 0xf1, 0x8a, 0xd5, \
+ 0x6c, 0x70, 0x1e, 0x1 \
+ } \
+ }
+
+#define GRUB_PKS_CERT_SHA512_GUID \
+ (grub_uuid_t) \
+ { \
+ { \
+ 0xae, 0x0f, 0x3e, 0x09, 0xc4, 0xa6, \
+ 0x50, 0x4f, 0x9f, 0x1b, 0xd4, 0x1e, \
+ 0x2b, 0x89, 0xc1, 0x9a \
+ } \
+ }
+
+#define GRUB_PKS_CERT_X509_SHA256_GUID \
+ (grub_uuid_t) \
+ { \
+ { \
+ 0x92, 0xa4, 0xd2, 0x3b, 0xc0, 0x96, \
+ 0x79, 0x40, 0xb4, 0x20, 0xfc, 0xf9, \
+ 0x8e, 0xf1, 0x03, 0xed \
+ } \
+ }
+
+#define GRUB_PKS_CERT_X509_SHA384_GUID \
+ (grub_uuid_t) \
+ { \
+ { \
+ 0x6e, 0x87, 0x76, 0x70, 0xc2, 0x80, \
+ 0xe6, 0x4e, 0xaa, 0xd2, 0x28, 0xb3, \
+ 0x49, 0xa6, 0x86, 0x5b \
+ } \
+ }
+
+#define GRUB_PKS_CERT_X509_SHA512_GUID \
+ (grub_uuid_t) \
+ { \
+ { \
+ 0x63, 0xbf, 0x6d, 0x44, 0x02, 0x25, \
+ 0xda, 0x4c, 0xbc, 0xfa, 0x24, 0x65, \
+ 0xd2, 0xb0, 0xfe, 0x9d \
+ } \
+ }
+
+typedef struct grub_pks_sd grub_pks_sd_t;
+typedef struct grub_pks grub_pks_t;
+
+/* The structure of a PKS signature data.*/
+struct grub_pks_sd
+{
+ grub_uuid_t guid; /* signature type */
+ grub_uint8_t *data; /* signature data */
+ grub_size_t data_size; /* size of signature data */
+} GRUB_PACKED;
+
+/* The structure of a PKS.*/
+struct grub_pks
+{
+ grub_uint8_t use_static_keys;
+ grub_pks_sd_t *db; /* signature database */
+ grub_pks_sd_t *dbx; /* forbidden signature database */
+ grub_size_t db_entries; /* size of signature database */
+ grub_size_t dbx_entries; /* size of forbidden signature database */
+} GRUB_PACKED;
+
+#ifdef __powerpc__
+
+/* initialization of the Platform Keystore */
+grub_err_t grub_platform_keystore_init (void);
+/* releasing allocated memory */
+void EXPORT_FUNC(grub_release_platform_keystore) (void);
+extern grub_uint8_t EXPORT_VAR(grub_use_platform_keystore);
+extern grub_pks_t EXPORT_VAR(grub_platform_keystore);
+
+#else
+
+#define grub_use_platform_keystore 0
+grub_pks_t grub_platform_keystore = {0, NULL, NULL, 0, 0};
+void grub_release_platform_keystore (void);
+
+#endif
+
+#endif
--
2.47.0

View File

@ -0,0 +1,831 @@
From 350e8d823db1febc2c81635115ef3c4c0f41f3e7 Mon Sep 17 00:00:00 2001
From: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
Date: Tue, 17 Jan 2023 22:38:05 +0530
Subject: [PATCH 3/8] appendedsig: The creation of trusted and distrusted lists
The trusted certificates and binary hashes, distrusted certificates and
binary/certificate hashes will be extracted from the platform keystore buffer
if Secure Boot is enabled with PKS.
In order to verify the integerity of the kernel, the extracted data
would be stored in the buffer db and dbx.
The trusted certificates will be extracted from the grub ELFNOTE if Secure Boot is
enabled with static key. In order to verify the integerity of the kernel,
the extracted data would be stored in the buffer db.
Note:-
if the trusted certificate nor binary hash exists in the distrusted list (DBX),
rejected it while extracting it from the platform keystore buffer.
Signed-off-by: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
Tested-by: Nageswara Sastry <rnsastry@linux.ibm.com>
---
grub-core/commands/appendedsig/appendedsig.c | 701 +++++++++++++++++--
1 file changed, 635 insertions(+), 66 deletions(-)
diff --git a/grub-core/commands/appendedsig/appendedsig.c b/grub-core/commands/appendedsig/appendedsig.c
index e63ad1ac6..5bb09e349 100644
--- a/grub-core/commands/appendedsig/appendedsig.c
+++ b/grub-core/commands/appendedsig/appendedsig.c
@@ -33,7 +33,7 @@
#include <grub/libtasn1.h>
#include <grub/env.h>
#include <grub/lockdown.h>
-
+#include <grub/platform_keystore.h>
#include "appendedsig.h"
GRUB_MOD_LICENSE ("GPLv3+");
@@ -66,8 +66,23 @@ struct grub_appended_signature
struct pkcs7_signedData pkcs7; /* Parsed PKCS#7 data */
};
-/* Trusted certificates for verifying appended signatures */
-struct x509_certificate *grub_trusted_key;
+/* This represents a trusted/distrusted list*/
+struct grub_database
+{
+ struct x509_certificate *keys; /* Certificates */
+ grub_size_t key_entries; /* Number of certificates */
+ grub_uint8_t **signatures; /* Certificate/binary hashes */
+ grub_size_t *signature_size; /* Size of certificate/binary hashes */
+ grub_size_t signature_entries; /* Number of certificate/binary hashes */
+};
+
+/* Trusted list */
+struct grub_database grub_db = {.keys = NULL, .key_entries = 0, .signatures = NULL,
+ .signature_size = NULL, .signature_entries = 0};
+
+/* Distrusted list */
+struct grub_database grub_dbx = {.signatures = NULL, .signature_size = NULL,
+ .signature_entries = 0};
/*
* Force gcry_rsa to be a module dependency.
@@ -90,12 +105,263 @@ struct x509_certificate *grub_trusted_key;
*/
extern gcry_pk_spec_t _gcry_pubkey_spec_rsa;
+extern gcry_md_spec_t _gcry_digest_spec_sha224;
+extern gcry_md_spec_t _gcry_digest_spec_sha384;
+
+/* releasing trusted list memory */
+static void grub_release_trusted_list (void);
+/* releasing distrusted list memory */
+static void grub_release_distrusted_list (void);
+
static enum
{ check_sigs_no = 0,
check_sigs_enforce = 1,
check_sigs_forced = 2
} check_sigs = check_sigs_no;
+/*
+ * GUID can be used to determine the hashing function and
+ * generate the hash using determined hashing function.
+ */
+static grub_err_t
+grub_get_hash (const grub_uuid_t *guid, const grub_uint8_t *data, const grub_size_t data_size,
+ grub_uint8_t *hash, grub_size_t *hash_size)
+{
+ gcry_md_spec_t *hash_func = NULL;
+
+ if (guid == NULL)
+ return grub_error (GRUB_ERR_OUT_OF_RANGE, "signature data type is null");
+
+ if (grub_memcmp (guid, &GRUB_PKS_CERT_SHA256_GUID, GRUB_UUID_SIZE) == 0 ||
+ grub_memcmp (guid, &GRUB_PKS_CERT_X509_SHA256_GUID, GRUB_UUID_SIZE) == 0)
+ hash_func = &_gcry_digest_spec_sha256;
+ else if (grub_memcmp (guid, &GRUB_PKS_CERT_SHA384_GUID, GRUB_UUID_SIZE) == 0 ||
+ grub_memcmp (guid, &GRUB_PKS_CERT_X509_SHA384_GUID, GRUB_UUID_SIZE) == 0)
+ hash_func = &_gcry_digest_spec_sha384;
+ else if (grub_memcmp (guid, &GRUB_PKS_CERT_SHA512_GUID, GRUB_UUID_SIZE) == 0 ||
+ grub_memcmp (guid, &GRUB_PKS_CERT_X509_SHA512_GUID, GRUB_UUID_SIZE) == 0)
+ hash_func = &_gcry_digest_spec_sha512;
+ else
+ return GRUB_ERR_UNKNOWN_COMMAND;
+
+ grub_memset (hash, 0x00, GRUB_MAX_HASH_SIZE);
+ grub_crypto_hash (hash_func, hash, data, data_size);
+ *hash_size = hash_func->mdlen;
+
+ return GRUB_ERR_NONE;
+}
+
+/* adding the certificate/binary hash into the trusted/distrusted list */
+static grub_err_t
+grub_add_hash (const grub_uint8_t **data, const grub_size_t data_size,
+ grub_uint8_t ***signature_list, grub_size_t **signature_size_list,
+ grub_size_t *signature_list_entries)
+{
+ grub_uint8_t **signatures = *signature_list;
+ grub_size_t *signature_size = *signature_size_list;
+ grub_size_t signature_entries = *signature_list_entries;
+
+ if (*data == NULL || data_size == 0)
+ return grub_error (GRUB_ERR_OUT_OF_RANGE, "certificate/binary hash data/size is null");
+
+ if (signatures == NULL && signature_size == NULL)
+ {
+ signatures = grub_zalloc (sizeof (grub_uint8_t *));
+ signature_size = grub_zalloc (sizeof (grub_size_t));
+ }
+ else
+ {
+ signatures = grub_realloc (signatures, sizeof (grub_uint8_t *) * (signature_entries + 1));
+ signature_size = grub_realloc (signature_size,
+ sizeof (grub_size_t) * (signature_entries + 1));
+ }
+
+ if (signatures == NULL || signature_size == NULL)
+ {
+ /*
+ * allocated memory will be freed by
+ * grub_release_trusted_list/grub_release_distrusted_list
+ */
+ if (signatures != NULL)
+ {
+ *signature_list = signatures;
+ *signature_list_entries = signature_entries + 1;
+ }
+
+ if (signature_size != NULL)
+ *signature_size_list = signature_size;
+
+ return grub_error (GRUB_ERR_OUT_OF_MEMORY, "out of memory");
+ }
+
+ signatures[signature_entries] = (grub_uint8_t *) *data;
+ signature_size[signature_entries] = data_size;
+ signature_entries++;
+ *data = NULL;
+
+ *signature_list = signatures;
+ *signature_size_list = signature_size;
+ *signature_list_entries = signature_entries;
+
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_is_x509 (const grub_uuid_t *guid)
+{
+ if (grub_memcmp (guid, &GRUB_PKS_CERT_X509_GUID, GRUB_UUID_SIZE) == 0)
+ return GRUB_ERR_NONE;
+
+ return GRUB_ERR_UNKNOWN_COMMAND;
+}
+
+static grub_err_t
+grub_is_cert_match (const struct x509_certificate *distrusted_cert,
+ const struct x509_certificate *db_cert)
+{
+
+ if (grub_memcmp (distrusted_cert->subject, db_cert->subject, db_cert->subject_len) == 0
+ && grub_memcmp (distrusted_cert->serial, db_cert->serial, db_cert->serial_len) == 0
+ && grub_memcmp (distrusted_cert->mpis[0], db_cert->mpis[0], sizeof (db_cert->mpis[0])) == 0
+ && grub_memcmp (distrusted_cert->mpis[1], db_cert->mpis[1], sizeof (db_cert->mpis[1])) == 0)
+ return GRUB_ERR_NONE;
+
+ return GRUB_ERR_UNKNOWN_COMMAND;
+}
+
+/*
+ * verify the certificate against the certificate from platform keystore buffer's
+ * distrusted list, if it is present, return a bad signature.
+ * else, no errors.
+ */
+static grub_err_t
+grub_is_distrusted_cert (const struct x509_certificate *db_cert)
+{
+ grub_err_t rc = GRUB_ERR_NONE;
+ grub_size_t i = 0;
+ struct x509_certificate *distrusted_cert = NULL;
+
+ for (i = 0; i < grub_platform_keystore.dbx_entries; i++)
+ {
+ if (grub_platform_keystore.dbx[i].data == NULL &&
+ grub_platform_keystore.dbx[i].data_size == 0)
+ continue;
+
+ if (grub_is_x509 (&grub_platform_keystore.dbx[i].guid) == GRUB_ERR_NONE)
+ {
+ distrusted_cert = grub_zalloc (sizeof (struct x509_certificate));
+ if (distrusted_cert == NULL)
+ return grub_error (GRUB_ERR_OUT_OF_MEMORY, "out of memory");
+
+ rc = parse_x509_certificate (grub_platform_keystore.dbx[i].data,
+ grub_platform_keystore.dbx[i].data_size, distrusted_cert);
+ if (rc != GRUB_ERR_NONE)
+ {
+ grub_free (distrusted_cert);
+ continue;
+ }
+
+ if (grub_is_cert_match (distrusted_cert, db_cert) == GRUB_ERR_NONE)
+ {
+ grub_printf ("Warning: a trusted certificate CN='%s' is ignored "
+ "because it is on the distrusted list (dbx).\n", db_cert->subject);
+ grub_free (grub_platform_keystore.dbx[i].data);
+ grub_memset (&grub_platform_keystore.dbx[i], 0x00,
+ sizeof (grub_platform_keystore.dbx[i]));
+ certificate_release (distrusted_cert);
+ grub_free (distrusted_cert);
+ return GRUB_ERR_BAD_SIGNATURE;
+ }
+
+ certificate_release (distrusted_cert);
+ grub_free (distrusted_cert);
+ }
+ }
+
+ return GRUB_ERR_NONE;
+}
+
+/* adding the certificate into the trusted/distrusted list */
+static grub_err_t
+grub_add_certificate (const grub_uint8_t *data, const grub_size_t data_size,
+ struct grub_database *database, const grub_uint8_t is_db)
+{
+ grub_err_t rc = GRUB_ERR_NONE;
+ grub_size_t key_entries = database->key_entries;
+ struct x509_certificate *cert = NULL;
+
+ if (data == NULL || data_size == 0)
+ return grub_error (GRUB_ERR_OUT_OF_RANGE, "certificate data/size is null");
+
+ cert = grub_zalloc (sizeof (struct x509_certificate));
+ if (cert == NULL)
+ return grub_error (GRUB_ERR_OUT_OF_MEMORY, "out of memory");
+
+ rc = parse_x509_certificate (data, data_size, cert);
+ if (rc != GRUB_ERR_NONE)
+ {
+ grub_printf ("Warning: skipping %s certificate (%d)\n",
+ (is_db ? "trusted":"distrused"), rc);
+ grub_free (cert);
+ return rc;
+ }
+
+ if (is_db)
+ {
+ rc = grub_is_distrusted_cert (cert);
+ if (rc != GRUB_ERR_NONE)
+ {
+ certificate_release (cert);
+ grub_free (cert);
+ return rc;
+ }
+ }
+
+ grub_dprintf ("appendedsig", "add a %s certificate CN='%s'\n",
+ (is_db ? "trusted":"distrused"), cert->subject);
+
+ key_entries++;
+ cert->next = database->keys;
+ database->keys = cert;
+ database->key_entries = key_entries;
+
+ return rc;
+}
+
+static grub_err_t
+grub_read_file (const grub_file_t file, grub_uint8_t **data, grub_ssize_t *data_size)
+{
+ grub_uint8_t *buffer = NULL;
+ grub_ssize_t read_size = 0;
+ grub_off_t total_read_size = 0;
+ grub_off_t file_size = grub_file_size (file);
+
+ if (file_size == GRUB_FILE_SIZE_UNKNOWN)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT,
+ N_("could not parse the unknown size of the file."));
+
+ buffer = grub_zalloc (file_size);
+ if (buffer == NULL)
+ return grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
+
+ while (total_read_size < file_size)
+ {
+ read_size = grub_file_read (file, &buffer[total_read_size], file_size - total_read_size);
+ if (read_size < 0)
+ {
+ grub_free (buffer);
+ return grub_error (GRUB_ERR_READ_ERROR, N_("unable to read the file"));
+ }
+
+ total_read_size += read_size;
+ }
+
+ *data = buffer;
+ *data_size = total_read_size;
+
+ return GRUB_ERR_NONE;
+}
+
static const char *
grub_env_read_sec (struct grub_env_var *var __attribute__((unused)),
const char *val __attribute__((unused)))
@@ -153,10 +419,7 @@ file_read_all (grub_file_t file, grub_uint8_t **buf, grub_size_t *len)
while (total_read_size < file_size)
{
- read_size =
- grub_file_read (file, *buf + total_read_size,
- file_size - total_read_size);
-
+ read_size = grub_file_read (file, *buf + total_read_size, file_size - total_read_size);
if (read_size < 0)
{
grub_free (*buf);
@@ -267,9 +530,8 @@ grub_verify_appended_signature (const grub_uint8_t *buf, grub_size_t bufsize)
struct pkcs7_signerInfo *si;
int i;
- if (!grub_trusted_key)
- return grub_error (GRUB_ERR_BAD_SIGNATURE,
- N_("No trusted keys to verify against"));
+ if (!grub_db.key_entries)
+ return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("No trusted keys to verify against"));
err = extract_appended_signature (buf, bufsize, &sig);
if (err != GRUB_ERR_NONE)
@@ -299,17 +561,16 @@ grub_verify_appended_signature (const grub_uint8_t *buf, grub_size_t bufsize)
datasize, i, hash[0], hash[1], hash[2], hash[3]);
err = GRUB_ERR_BAD_SIGNATURE;
- for (pk = grub_trusted_key; pk; pk = pk->next)
- {
- rc = grub_crypto_rsa_pad (&hashmpi, hash, si->hash, pk->mpis[0]);
- if (rc)
- {
- err = grub_error (GRUB_ERR_BAD_SIGNATURE,
- N_("Error padding hash for RSA verification: %d"),
- rc);
- grub_free (context);
- goto cleanup;
- }
+ for (pk = grub_db.keys; pk; pk = pk->next)
+ {
+ rc = grub_crypto_rsa_pad (&hashmpi, hash, si->hash, pk->mpis[0]);
+ if (rc)
+ {
+ err = grub_error (GRUB_ERR_BAD_SIGNATURE,
+ N_("Error padding hash for RSA verification: %d"), rc);
+ grub_free (context);
+ goto cleanup;
+ }
rc = _gcry_pubkey_spec_rsa.verify (0, hashmpi, &si->sig_mpi,
pk->mpis, NULL, NULL);
@@ -402,16 +663,16 @@ grub_cmd_distrust (grub_command_t cmd __attribute__((unused)),
if (cert_num == 1)
{
- cert = grub_trusted_key;
- grub_trusted_key = cert->next;
+ cert = grub_db.keys;
+ grub_db.keys = cert->next;
certificate_release (cert);
grub_free (cert);
return GRUB_ERR_NONE;
}
i = 2;
- prev = grub_trusted_key;
- cert = grub_trusted_key->next;
+ prev = grub_db.keys;
+ cert = grub_db.keys->next;
while (cert)
{
if (i == cert_num)
@@ -464,8 +725,8 @@ grub_cmd_trust (grub_command_t cmd __attribute__((unused)),
grub_dprintf ("appendedsig", "Loaded certificate with CN: %s\n",
cert->subject);
- cert->next = grub_trusted_key;
- grub_trusted_key = cert;
+ cert->next = grub_db.keys;
+ grub_db.keys = cert;
return GRUB_ERR_NONE;
}
@@ -479,7 +740,7 @@ grub_cmd_list (grub_command_t cmd __attribute__((unused)),
int cert_num = 1;
grub_size_t i;
- for (cert = grub_trusted_key; cert; cert = cert->next)
+ for (cert = grub_db.keys; cert; cert = cert->next)
{
grub_printf (N_("Certificate %d:\n"), cert_num);
@@ -577,6 +838,305 @@ static struct grub_fs pseudo_fs = {
.fs_read = pseudo_read
};
+/*
+ * verify the trusted certificate against the certificate hashes from platform keystore buffer's
+ * distrusted list, if it is present, return a bad signature.
+ * else, no errors.
+ */
+static grub_err_t
+grub_is_distrusted_cert_hash (const grub_uint8_t *data, const grub_size_t data_size)
+{
+ grub_err_t rc = GRUB_ERR_NONE;
+ grub_size_t i = 0, cert_hash_size = 0;
+ grub_uint8_t cert_hash[GRUB_MAX_HASH_SIZE] = { 0 };
+
+ if (data == NULL || data_size == 0)
+ return grub_error (GRUB_ERR_OUT_OF_RANGE, "trusted certificate data/size is null");
+
+ for (i = 0; i < grub_platform_keystore.dbx_entries; i++)
+ {
+ if (grub_platform_keystore.dbx[i].data == NULL &&
+ grub_platform_keystore.dbx[i].data_size == 0)
+ continue;
+
+ rc = grub_get_hash (&grub_platform_keystore.dbx[i].guid, data, data_size,
+ cert_hash, &cert_hash_size);
+ if (rc != GRUB_ERR_NONE)
+ continue;
+
+ if (cert_hash_size == grub_platform_keystore.dbx[i].data_size &&
+ grub_memcmp (grub_platform_keystore.dbx[i].data, cert_hash, cert_hash_size) == 0)
+ {
+ grub_printf ("Warning: a trusted certificate (%02x%02x%02x%02x) is ignored "
+ "because this certificate hash is on the distrusted list (dbx).\n",
+ cert_hash[0], cert_hash[1], cert_hash[2], cert_hash[3]);
+ grub_free (grub_platform_keystore.dbx[i].data);
+ grub_memset (&grub_platform_keystore.dbx[i], 0x00,
+ sizeof (grub_platform_keystore.dbx[i]));
+ return GRUB_ERR_BAD_SIGNATURE;
+ }
+ }
+
+ return GRUB_ERR_NONE;
+}
+
+/*
+ * verify the trusted binary hash against the platform keystore buffer's
+ * distrusted list, if it is present, return a bad signature.
+ * else, no errors.
+ */
+static grub_err_t
+grub_is_distrusted_binary_hash (const grub_uint8_t *binary_hash,
+ const grub_size_t binary_hash_size)
+{
+ grub_size_t i = 0;
+
+ for (i = 0; i < grub_platform_keystore.dbx_entries; i++)
+ {
+ if (grub_platform_keystore.dbx[i].data == NULL &&
+ grub_platform_keystore.dbx[i].data_size == 0)
+ continue;
+
+ if (binary_hash_size == grub_platform_keystore.dbx[i].data_size &&
+ grub_memcmp (grub_platform_keystore.dbx[i].data, binary_hash, binary_hash_size) == 0)
+ {
+ grub_printf ("Warning: a trusted binary hash (%02x%02x%02x%02x) is ignored"
+ " because it is on the distrusted list (dbx).\n",
+ binary_hash[0], binary_hash[1], binary_hash[2], binary_hash[3]);
+ grub_free (grub_platform_keystore.dbx[i].data);
+ grub_memset (&grub_platform_keystore.dbx[i], 0x00,
+ sizeof (grub_platform_keystore.dbx[i]));
+ return GRUB_ERR_BAD_SIGNATURE;
+ }
+ }
+
+ return GRUB_ERR_NONE;
+}
+
+/*
+ * extracts the binary hashes from the platform keystore buffer,
+ * and adds it to the trusted list if not exists in distrusted list.
+ */
+static grub_err_t
+grub_add_trusted_binary_hash (const grub_uint8_t **data, const grub_size_t data_size)
+{
+ grub_err_t rc = GRUB_ERR_NONE;
+
+ if (*data == NULL || data_size == 0)
+ return grub_error (GRUB_ERR_OUT_OF_RANGE, "trusted binary hash data/size is null");
+
+ rc = grub_is_distrusted_binary_hash (*data, data_size);
+ if (rc != GRUB_ERR_NONE)
+ return rc;
+
+ rc = grub_add_hash (data, data_size, &grub_db.signatures, &grub_db.signature_size,
+ &grub_db.signature_entries);
+ return rc;
+}
+
+static grub_err_t
+grub_is_hash (const grub_uuid_t *guid)
+{
+ /* GUID type of the binary hash */
+ if (grub_memcmp (guid, &GRUB_PKS_CERT_SHA256_GUID, GRUB_UUID_SIZE) == 0 ||
+ grub_memcmp (guid, &GRUB_PKS_CERT_SHA384_GUID, GRUB_UUID_SIZE) == 0 ||
+ grub_memcmp (guid, &GRUB_PKS_CERT_SHA512_GUID, GRUB_UUID_SIZE) == 0)
+ return GRUB_ERR_NONE;
+
+ /* GUID type of the certificate hash */
+ if (grub_memcmp (guid, &GRUB_PKS_CERT_X509_SHA256_GUID, GRUB_UUID_SIZE) == 0 ||
+ grub_memcmp (guid, &GRUB_PKS_CERT_X509_SHA384_GUID, GRUB_UUID_SIZE) == 0 ||
+ grub_memcmp (guid, &GRUB_PKS_CERT_X509_SHA512_GUID, GRUB_UUID_SIZE) == 0)
+ return GRUB_ERR_NONE;
+
+ return GRUB_ERR_UNKNOWN_COMMAND;
+}
+
+/*
+ * extracts the x509 certificates/binary hashes from the platform keystore buffer,
+ * parses it, and adds it to the trusted list.
+ */
+static grub_err_t
+grub_create_trusted_list (void)
+{
+ grub_err_t rc = GRUB_ERR_NONE;
+ grub_size_t i = 0;
+
+ for (i = 0; i < grub_platform_keystore.db_entries; i++)
+ {
+ if (grub_is_hash (&grub_platform_keystore.db[i].guid) == GRUB_ERR_NONE)
+ {
+ rc = grub_add_trusted_binary_hash ((const grub_uint8_t **)
+ &grub_platform_keystore.db[i].data,
+ grub_platform_keystore.db[i].data_size);
+ if (rc == GRUB_ERR_OUT_OF_MEMORY)
+ return rc;
+
+ continue;
+ }
+ else if (grub_is_x509 (&grub_platform_keystore.db[i].guid) == GRUB_ERR_NONE)
+ {
+
+ rc = grub_is_distrusted_cert_hash (grub_platform_keystore.db[i].data,
+ grub_platform_keystore.db[i].data_size);
+ if (rc != GRUB_ERR_NONE)
+ continue;
+
+ rc = grub_add_certificate (grub_platform_keystore.db[i].data,
+ grub_platform_keystore.db[i].data_size, &grub_db, 1);
+ if (rc == GRUB_ERR_OUT_OF_MEMORY)
+ return rc;
+ else if (rc != GRUB_ERR_NONE)
+ continue;
+ }
+ else
+ grub_printf ("Warning: unsupported signature data type and "
+ "skipping trusted data (%" PRIuGRUB_SIZE ")\n", i + 1);
+ }
+
+ return GRUB_ERR_NONE;
+}
+
+/*
+ * extracts the certificates, certificate/binary hashes out of the platform keystore buffer,
+ * and adds it to the distrusted list.
+ */
+static grub_err_t
+grub_create_distrusted_list (void)
+{
+ grub_err_t rc = GRUB_ERR_NONE;
+ grub_size_t i = 0;
+
+ for (i = 0; i < grub_platform_keystore.dbx_entries; i++)
+ {
+ if (grub_platform_keystore.dbx[i].data != NULL &&
+ grub_platform_keystore.dbx[i].data_size > 0)
+ {
+ if (grub_is_x509 (&grub_platform_keystore.dbx[i].guid))
+ {
+ rc = grub_add_certificate (grub_platform_keystore.dbx[i].data,
+ grub_platform_keystore.dbx[i].data_size, &grub_dbx, 0);
+ if (rc == GRUB_ERR_OUT_OF_MEMORY)
+ return rc;
+ }
+ else if (grub_is_hash (&grub_platform_keystore.dbx[i].guid) == GRUB_ERR_NONE)
+ {
+ rc = grub_add_hash ((const grub_uint8_t **) &grub_platform_keystore.dbx[i].data,
+ grub_platform_keystore.dbx[i].data_size,
+ &grub_dbx.signatures, &grub_dbx.signature_size,
+ &grub_dbx.signature_entries);
+ if (rc != GRUB_ERR_NONE)
+ return rc;
+ }
+ else
+ grub_printf ("Warning: unsupported signature data type and "
+ "skipping distrusted data (%" PRIuGRUB_SIZE ")\n", i + 1);
+ }
+ }
+
+ return rc;
+}
+
+/*
+ * extracts the x509 certificates from the ELF note header,
+ * parses it, and adds it to the trusted list.
+ */
+static grub_err_t
+grub_build_static_trusted_list (const struct grub_module_header *header, bool mode)
+{
+ grub_err_t err = GRUB_ERR_NONE;
+ struct grub_file pseudo_file;
+ grub_uint8_t *cert_data = NULL;
+ grub_ssize_t cert_data_size = 0;
+
+ grub_memset (&pseudo_file, 0, sizeof (pseudo_file));
+ pseudo_file.fs = &pseudo_fs;
+ pseudo_file.size = header->size - sizeof (struct grub_module_header);
+ pseudo_file.data = (char *) header + sizeof (struct grub_module_header);
+
+ grub_dprintf ("appendedsig", "found an x509 key, size=%" PRIuGRUB_UINT64_T "\n",
+ pseudo_file.size);
+
+ err = grub_read_file (&pseudo_file, &cert_data, &cert_data_size);
+ if (err != GRUB_ERR_NONE)
+ return err;
+
+ if (mode)
+ {
+ err = grub_is_distrusted_cert_hash (cert_data, cert_data_size);
+ if (err != GRUB_ERR_NONE)
+ return err;
+ }
+
+ err = grub_add_certificate (cert_data, cert_data_size, &grub_db, mode);
+ if (cert_data != NULL)
+ grub_free (cert_data);
+
+ return err;
+}
+
+/* releasing memory */
+static void
+grub_release_trusted_list (void)
+{
+ struct x509_certificate *cert;
+ grub_size_t i = 0;
+
+ while (grub_db.keys != NULL)
+ {
+ cert = grub_db.keys;
+ grub_db.keys = grub_db.keys->next;
+ certificate_release (cert);
+ grub_free (cert);
+ }
+
+ for (i = 0; i < grub_db.signature_entries; i++)
+ grub_free (grub_db.signatures[i]);
+
+ grub_free (grub_db.signatures);
+ grub_free (grub_db.signature_size);
+ grub_memset (&grub_db, 0x00, sizeof (grub_db));
+}
+
+/* releasing memory */
+static void
+grub_release_distrusted_list (void)
+{
+ struct x509_certificate *cert;
+ grub_size_t i = 0;
+
+ while (grub_dbx.keys != NULL)
+ {
+ cert = grub_dbx.keys;
+ grub_dbx.keys = grub_dbx.keys->next;
+ certificate_release (cert);
+ grub_free (cert);
+ }
+
+ for (i = 0; i < grub_dbx.signature_entries; i++)
+ grub_free (grub_dbx.signatures[i]);
+
+ grub_free (grub_dbx.signatures);
+ grub_free (grub_dbx.signature_size);
+ grub_memset (&grub_dbx, 0x00, sizeof (grub_dbx));
+}
+
+static grub_err_t
+grub_load_static_keys (struct grub_module_header *header, bool mode)
+{
+ int rc = GRUB_ERR_NONE;
+
+ FOR_MODULES (header)
+ {
+ /* Not an ELF module, skip. */
+ if (header->type != OBJ_TYPE_X509_PUBKEY)
+ continue;
+ rc = grub_build_static_trusted_list (header, mode);
+ }
+
+ return rc;
+}
+
static grub_command_t cmd_verify, cmd_list, cmd_distrust, cmd_trust;
GRUB_MOD_INIT (appendedsig)
@@ -588,10 +1148,7 @@ GRUB_MOD_INIT (appendedsig)
if (grub_is_lockdown () == GRUB_LOCKDOWN_ENABLED)
check_sigs = check_sigs_forced;
- grub_trusted_key = NULL;
-
- grub_register_variable_hook ("check_appended_signatures",
- grub_env_read_sec, grub_env_write_sec);
+ grub_register_variable_hook ("check_appended_signatures", grub_env_read_sec, grub_env_write_sec);
grub_env_export ("check_appended_signatures");
rc = asn1_init ();
@@ -599,40 +1156,52 @@ GRUB_MOD_INIT (appendedsig)
grub_fatal ("Error initing ASN.1 data structures: %d: %s\n", rc,
asn1_strerror (rc));
- FOR_MODULES (header)
- {
- struct grub_file pseudo_file;
- struct x509_certificate *pk = NULL;
- grub_err_t err;
-
- /* Not an ELF module, skip. */
- if (header->type != OBJ_TYPE_X509_PUBKEY)
- continue;
-
- grub_memset (&pseudo_file, 0, sizeof (pseudo_file));
- pseudo_file.fs = &pseudo_fs;
- pseudo_file.size = header->size - sizeof (struct grub_module_header);
- pseudo_file.data = (char *) header + sizeof (struct grub_module_header);
-
- grub_dprintf ("appendedsig",
- "Found an x509 key, size=%" PRIuGRUB_UINT64_T "\n",
- pseudo_file.size);
-
- pk = grub_zalloc (sizeof (struct x509_certificate));
- if (!pk)
- {
- grub_fatal ("Out of memory loading initial certificates");
- }
-
- err = read_cert_from_file (&pseudo_file, pk);
- if (err != GRUB_ERR_NONE)
- grub_fatal ("Error loading initial key: %s", grub_errmsg);
-
- grub_dprintf ("appendedsig", "loaded certificate CN='%s'\n", pk->subject);
-
- pk->next = grub_trusted_key;
- grub_trusted_key = pk;
- }
+ if (!grub_use_platform_keystore && check_sigs == check_sigs_forced)
+ {
+ rc = grub_load_static_keys (header, 0);
+ if (rc != GRUB_ERR_NONE)
+ {
+ grub_release_trusted_list ();
+ grub_error (rc, "static trusted list creation failed");
+ }
+ else
+ grub_printf ("appendedsig: the trusted list now has %" PRIuGRUB_SIZE " static keys\n",
+ grub_db.key_entries);
+ }
+ else if (grub_use_platform_keystore && check_sigs == check_sigs_forced)
+ {
+ if (grub_platform_keystore.use_static_keys == 1)
+ {
+ grub_printf ("Warning: db variable not available and using a static key"
+ "as a default key in trusted list");
+ rc = grub_load_static_keys (header, 1);
+ }
+ else
+ rc = grub_create_trusted_list ();
+
+ if (rc != GRUB_ERR_NONE)
+ {
+ grub_release_trusted_list ();
+ grub_error (rc, "trusted list creation failed");
+ }
+ else
+ {
+ rc = grub_create_distrusted_list ();
+ if (rc != GRUB_ERR_NONE)
+ {
+ grub_release_trusted_list ();
+ grub_release_distrusted_list ();
+ grub_error (rc, "distrusted list creation failed");
+ }
+ else
+ grub_printf ("appendedsig: the trusted list now has %" PRIuGRUB_SIZE " keys.\n"
+ "appendedsig: the distrusted list now has %" PRIuGRUB_SIZE " keys.\n",
+ grub_db.signature_entries + grub_db.key_entries,
+ grub_dbx.signature_entries);
+ }
+
+ grub_release_platform_keystore ();
+ }
cmd_trust =
grub_register_command ("trust_certificate", grub_cmd_trust,
--
2.47.0

View File

@ -0,0 +1,253 @@
From 5bff27911bb6575b80b5decf5364b7e6bde801d3 Mon Sep 17 00:00:00 2001
From: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
Date: Wed, 18 Jan 2023 23:04:38 +0530
Subject: [PATCH 4/8] appendedsig: While verifying the kernel, use trusted and
distrusted lists
To verify the kernel's, the trusted key will be used from
the trusted key list. If it fails, verify it against the list of hashes
that are distrusted and trusted.
Signed-off-by: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
Tested-by: Nageswara Sastry <rnsastry@linux.ibm.com>
---
grub-core/commands/appendedsig/appendedsig.c | 187 +++++++++++++------
1 file changed, 131 insertions(+), 56 deletions(-)
diff --git a/grub-core/commands/appendedsig/appendedsig.c b/grub-core/commands/appendedsig/appendedsig.c
index 5bb09e349..f9638220e 100644
--- a/grub-core/commands/appendedsig/appendedsig.c
+++ b/grub-core/commands/appendedsig/appendedsig.c
@@ -36,6 +36,10 @@
#include <grub/platform_keystore.h>
#include "appendedsig.h"
+#define SHA256_LEN 32
+#define SHA384_LEN 48
+#define SHA512_LEN 64
+
GRUB_MOD_LICENSE ("GPLv3+");
const char magic[] = "~Module signature appended~\n";
@@ -516,6 +520,80 @@ extract_appended_signature (const grub_uint8_t *buf, grub_size_t bufsize,
return GRUB_ERR_NONE;
}
+static grub_err_t
+grub_get_binary_hash (const grub_size_t binary_hash_size, const grub_uint8_t *data,
+ const grub_size_t data_size, grub_uint8_t *hash, grub_size_t *hash_size)
+{
+ grub_uuid_t guid = { 0 };
+
+ /* support SHA256, SHA384 and SHA512 for binary hash */
+ if (binary_hash_size == SHA256_LEN)
+ grub_memcpy (&guid, &GRUB_PKS_CERT_SHA256_GUID, GRUB_UUID_SIZE);
+ else if (binary_hash_size == SHA384_LEN)
+ grub_memcpy (&guid, &GRUB_PKS_CERT_SHA384_GUID, GRUB_UUID_SIZE);
+ else if (binary_hash_size == SHA512_LEN)
+ grub_memcpy (&guid, &GRUB_PKS_CERT_SHA512_GUID, GRUB_UUID_SIZE);
+ else
+ {
+ grub_dprintf ("appendedsig", "unsupported hash type (%" PRIuGRUB_SIZE ") and skipping binary hash\n",
+ binary_hash_size);
+ return GRUB_ERR_UNKNOWN_COMMAND;
+ }
+
+ return grub_get_hash (&guid, data, data_size, hash, hash_size);
+}
+
+/*
+ * verify binary hash against the list of binary hashes that are distrusted
+ * and trusted.
+ */
+static grub_err_t
+grub_verify_binary_hash (const grub_uint8_t *data, const grub_size_t data_size)
+{
+ grub_err_t rc = GRUB_ERR_NONE;
+ grub_size_t i = 0, hash_size = 0;
+ grub_uint8_t hash[GRUB_MAX_HASH_SIZE] = { 0 };
+
+ for (i = 0; i < grub_dbx.signature_entries; i++)
+ {
+ rc = grub_get_binary_hash (grub_dbx.signature_size[i], data, data_size,
+ hash, &hash_size);
+ if (rc != GRUB_ERR_NONE)
+ continue;
+
+ if (hash_size == grub_dbx.signature_size[i] &&
+ grub_memcmp (grub_dbx.signatures[i], hash, hash_size) == 0)
+ {
+ grub_dprintf ("appendedsig", "the binary hash (%02x%02x%02x%02x) was listed "
+ "as distrusted\n", hash[0], hash[1], hash[2], hash[3]);
+ return GRUB_ERR_BAD_SIGNATURE;
+ }
+ }
+
+ for (i = 0; i < grub_db.signature_entries; i++)
+ {
+ rc = grub_get_binary_hash (grub_db.signature_size[i], data, data_size,
+ hash, &hash_size);
+ if (rc != GRUB_ERR_NONE)
+ continue;
+
+ if (hash_size == grub_db.signature_size[i] &&
+ grub_memcmp (grub_db.signatures[i], hash, hash_size) == 0)
+ {
+ grub_dprintf ("appendedsig", "verified with a trusted binary hash "
+ "(%02x%02x%02x%02x)\n", hash[0], hash[1], hash[2], hash[3]);
+ return GRUB_ERR_NONE;
+ }
+ }
+
+ return GRUB_ERR_EOF;
+}
+
+/*
+ * verify the kernel's integrity, the trusted key will be used from
+ * the trusted key list. If it fails, verify it against the list of binary hashes
+ * that are distrusted and trusted.
+ */
static grub_err_t
grub_verify_appended_signature (const grub_uint8_t *buf, grub_size_t bufsize)
{
@@ -525,12 +603,12 @@ grub_verify_appended_signature (const grub_uint8_t *buf, grub_size_t bufsize)
unsigned char *hash;
gcry_mpi_t hashmpi;
gcry_err_code_t rc;
- struct x509_certificate *pk;
+ struct x509_certificate *cert;
struct grub_appended_signature sig;
struct pkcs7_signerInfo *si;
int i;
- if (!grub_db.key_entries)
+ if (!grub_db.key_entries && !grub_db.signature_entries)
return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("No trusted keys to verify against"));
err = extract_appended_signature (buf, bufsize, &sig);
@@ -538,70 +616,67 @@ grub_verify_appended_signature (const grub_uint8_t *buf, grub_size_t bufsize)
return err;
datasize = bufsize - sig.signature_len;
-
- for (i = 0; i < sig.pkcs7.signerInfo_count; i++)
+ /* checking kernel binary hash is presents in trusted list (db)/distrusted list (dbx) */
+ err = grub_verify_binary_hash (buf, datasize);
+ if (err == GRUB_ERR_EOF)
{
- /* This could be optimised in a couple of ways:
- - we could only compute hashes once per hash type
- - we could track signer information and only verify where IDs match
- For now we do the naive O(trusted keys * pkcs7 signers) approach.
- */
- si = &sig.pkcs7.signerInfos[i];
- context = grub_zalloc (si->hash->contextsize);
- if (!context)
- return grub_errno;
-
- si->hash->init (context);
- si->hash->write (context, buf, datasize);
- si->hash->final (context);
- hash = si->hash->read (context);
-
- grub_dprintf ("appendedsig",
- "data size %" PRIxGRUB_SIZE ", signer %d hash %02x%02x%02x%02x...\n",
- datasize, i, hash[0], hash[1], hash[2], hash[3]);
-
- err = GRUB_ERR_BAD_SIGNATURE;
- for (pk = grub_db.keys; pk; pk = pk->next)
+ /* verifying kernel binary signature using trusted keys from trusted list (db) */
+ for (i = 0; i < sig.pkcs7.signerInfo_count; i++)
{
- rc = grub_crypto_rsa_pad (&hashmpi, hash, si->hash, pk->mpis[0]);
- if (rc)
+ si = &sig.pkcs7.signerInfos[i];
+ context = grub_zalloc (si->hash->contextsize);
+ if (!context)
+ return grub_errno;
+
+ si->hash->init (context);
+ si->hash->write (context, buf, datasize);
+ si->hash->final (context);
+ hash = si->hash->read (context);
+
+ grub_dprintf ("appendedsig",
+ "data size %" PRIxGRUB_SIZE ", signer %d hash %02x%02x%02x%02x...\n",
+ datasize, i, hash[0], hash[1], hash[2], hash[3]);
+
+ err = GRUB_ERR_BAD_SIGNATURE;
+ for (cert = grub_db.keys; cert; cert = cert->next)
{
- err = grub_error (GRUB_ERR_BAD_SIGNATURE,
- N_("Error padding hash for RSA verification: %d"), rc);
- grub_free (context);
- goto cleanup;
+ rc = grub_crypto_rsa_pad (&hashmpi, hash, si->hash, cert->mpis[0]);
+ if (rc)
+ {
+ err = grub_error (GRUB_ERR_BAD_SIGNATURE,
+ N_("Error padding hash for RSA verification: %d"), rc);
+ grub_free (context);
+ pkcs7_signedData_release (&sig.pkcs7);
+ return err;
+ }
+
+ rc = _gcry_pubkey_spec_rsa.verify (0, hashmpi, &si->sig_mpi, cert->mpis, NULL, NULL);
+ gcry_mpi_release (hashmpi);
+
+ if (rc == 0)
+ {
+ grub_dprintf ("appendedsig", "verify signer %d with key '%s' succeeded\n",
+ i, cert->subject);
+ err = GRUB_ERR_NONE;
+ break;
+ }
+
+ grub_dprintf ("appendedsig", "verify signer %d with key '%s' failed with %d\n",
+ i, cert->subject, rc);
}
- rc = _gcry_pubkey_spec_rsa.verify (0, hashmpi, &si->sig_mpi,
- pk->mpis, NULL, NULL);
- gcry_mpi_release (hashmpi);
-
- if (rc == 0)
- {
- grub_dprintf ("appendedsig",
- "verify signer %d with key '%s' succeeded\n", i,
- pk->subject);
- err = GRUB_ERR_NONE;
- break;
- }
-
- grub_dprintf ("appendedsig",
- "verify signer %d with key '%s' failed with %d\n", i,
- pk->subject, rc);
- }
-
- grub_free (context);
+ grub_free (context);
- if (err == GRUB_ERR_NONE)
- break;
+ if (err == GRUB_ERR_NONE)
+ break;
+ }
}
- /* If we didn't verify, provide a neat message */
if (err != GRUB_ERR_NONE)
- err = grub_error (GRUB_ERR_BAD_SIGNATURE,
- N_("Failed to verify signature against a trusted key"));
+ grub_printf ("appendedsig: failed to verify signature with any trusted key\n");
+ else
+ grub_printf ("appendedsig: successfully verified the signature with a trusted key\n");
-cleanup:
pkcs7_signedData_release (&sig.pkcs7);
return err;
--
2.47.0

View File

@ -0,0 +1,684 @@
From f05acf089fb80fc44112a7feec3529af494a41f7 Mon Sep 17 00:00:00 2001
From: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
Date: Wed, 1 Feb 2023 21:42:36 +0530
Subject: [PATCH 5/8] appendedsig: The grub command's trusted and distrusted
support
To support the following trusted and distrusted commands
1. trusted_list:
It will show the list of trusted certificates and binary hashes
2. distrusted_list:
It will show the list of distrusted certificates and binary/certificate hashes
3. trusted_certificate:
It will add the trusted certificate to the trusted list
4. trusted_signature:
It will add the certificate/binary hash to the trusted list
5. distrusted_certificate:
It will remove the trusted certificate from trsuted list
6. distrusted_signature:
It will add the certificate/binary hash to the distrsuted list
Note:-
The addition/deletion of trusted certificates and binary hashes
are not allowed in grub command prompt while secure boot is enabled.
Signed-off-by: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
Tested-by: Nageswara Sastry <rnsastry@linux.ibm.com>
---
grub-core/commands/appendedsig/appendedsig.c | 547 ++++++++++++-------
1 file changed, 361 insertions(+), 186 deletions(-)
diff --git a/grub-core/commands/appendedsig/appendedsig.c b/grub-core/commands/appendedsig/appendedsig.c
index f9638220e..7d2bba079 100644
--- a/grub-core/commands/appendedsig/appendedsig.c
+++ b/grub-core/commands/appendedsig/appendedsig.c
@@ -123,6 +123,38 @@ static enum
check_sigs_forced = 2
} check_sigs = check_sigs_no;
+enum
+{
+ OPTION_BINARY_HASH = 0,
+ OPTION_CERT_HASH = 1
+};
+
+static const struct grub_arg_option options[] =
+{
+ {"binary-hash", 'b', 0, N_("hash file of the binary."), 0, ARG_TYPE_NONE},
+ {"cert-hash", 'c', 1, N_("hash file of the certificate."), 0, ARG_TYPE_NONE},
+ {0, 0, 0, 0, 0, 0}
+};
+
+static void
+grub_printhex (const grub_uint8_t *data, const grub_size_t length)
+{
+ grub_size_t i, count = 0;
+
+ for (i = 0; i < length-1; i++)
+ {
+ grub_printf ("%02x:", data[i]);
+ count++;
+ if (count == 16)
+ {
+ grub_printf ("\n\t ");
+ count = 0;
+ }
+ }
+
+ grub_printf ("%02x\n", data[i]);
+}
+
/*
* GUID can be used to determine the hashing function and
* generate the hash using determined hashing function.
@@ -396,75 +428,6 @@ grub_env_write_sec (struct grub_env_var *var __attribute__((unused)),
return grub_strdup (grub_env_read_sec (NULL, NULL));
}
-static grub_err_t
-file_read_all (grub_file_t file, grub_uint8_t **buf, grub_size_t *len)
-{
- grub_off_t full_file_size;
- grub_size_t file_size, total_read_size = 0;
- grub_ssize_t read_size;
-
- full_file_size = grub_file_size (file);
- if (full_file_size == GRUB_FILE_SIZE_UNKNOWN)
- return grub_error (GRUB_ERR_BAD_ARGUMENT,
- N_("Cannot read a file of unknown size into a buffer"));
-
- if (full_file_size > GRUB_SIZE_MAX)
- return grub_error (GRUB_ERR_OUT_OF_RANGE,
- N_("File is too large to read: %" PRIuGRUB_UINT64_T
- " bytes"), full_file_size);
-
- file_size = (grub_size_t) full_file_size;
-
- *buf = grub_malloc (file_size);
- if (!*buf)
- return grub_error (GRUB_ERR_OUT_OF_MEMORY,
- N_("Could not allocate file data buffer size %"
- PRIuGRUB_SIZE), file_size);
-
- while (total_read_size < file_size)
- {
- read_size = grub_file_read (file, *buf + total_read_size, file_size - total_read_size);
- if (read_size < 0)
- {
- grub_free (*buf);
- return grub_errno;
- }
- else if (read_size == 0)
- {
- grub_free (*buf);
- return grub_error (GRUB_ERR_IO,
- N_("Could not read full file size (%"
- PRIuGRUB_SIZE "), only %" PRIuGRUB_SIZE
- " bytes read"), file_size, total_read_size);
- }
-
- total_read_size += read_size;
- }
- *len = file_size;
- return GRUB_ERR_NONE;
-}
-
-static grub_err_t
-read_cert_from_file (grub_file_t f, struct x509_certificate *certificate)
-{
- grub_err_t err;
- grub_uint8_t *buf;
- grub_size_t file_size;
-
- err = file_read_all (f, &buf, &file_size);
- if (err != GRUB_ERR_NONE)
- return err;
-
- err = parse_x509_certificate (buf, file_size, certificate);
- if (err != GRUB_ERR_NONE)
- {
- grub_free (buf);
- return err;
- }
-
- return GRUB_ERR_NONE;
-}
-
static grub_err_t
extract_appended_signature (const grub_uint8_t *buf, grub_size_t bufsize,
struct grub_appended_signature *sig)
@@ -686,159 +649,357 @@ static grub_err_t
grub_cmd_verify_signature (grub_command_t cmd __attribute__((unused)),
int argc, char **args)
{
- grub_file_t f;
grub_err_t err = GRUB_ERR_NONE;
- grub_uint8_t *data;
- grub_size_t file_size;
+ grub_file_t signed_file = NULL;
+ grub_uint8_t *signed_data = NULL;
+ grub_ssize_t signed_data_size = 0;
+
+ if (argc != 1)
+ {
+ grub_printf (N_("a signed file is expected\n"
+ "Example:\n\tverify_appended <SIGNED FILE>\n"));
+ return GRUB_ERR_BAD_ARGUMENT;
+ }
- if (argc < 1)
- return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected"));
+ if (grub_strlen (args[0]) == 0)
+ return grub_error (GRUB_ERR_BAD_FILENAME, N_("missing signed file"));
grub_dprintf ("appendedsig", "verifying %s\n", args[0]);
- f = grub_file_open (args[0], GRUB_FILE_TYPE_VERIFY_SIGNATURE);
- if (!f)
+ signed_file = grub_file_open (args[0], GRUB_FILE_TYPE_VERIFY_SIGNATURE);
+ if (signed_file == NULL)
+ return grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("unable to open a signed file"));
+
+ err = grub_read_file (signed_file, &signed_data, &signed_data_size);
+ if (err != GRUB_ERR_NONE)
+ {
+ grub_file_close (signed_file);
+ return err;
+ }
+
+ grub_file_close (signed_file);
+ err = grub_verify_appended_signature (signed_data, signed_data_size);
+ grub_free (signed_data);
+
+ return err;
+}
+
+static grub_err_t
+grub_cmd_trusted_list (grub_command_t cmd __attribute__((unused)),
+ int argc __attribute__((unused)), char **args __attribute__((unused)))
+{
+ struct x509_certificate *cert = NULL;
+ grub_size_t i = 0, cert_num = 1;
+
+ for (cert = grub_db.keys; cert; cert = cert->next)
+ {
+ grub_printf (N_("trusted certificate %" PRIuGRUB_SIZE ":\n"), cert_num);
+ grub_printf (N_("\tserial: "));
+
+ for (i = 0; i < cert->serial_len - 1; i++)
+ grub_printf ("%02x:", cert->serial[i]);
+
+ grub_printf ("%02x\n", cert->serial[cert->serial_len - 1]);
+ grub_printf ("\tCN: %s\n\n", cert->subject);
+ cert_num++;
+
+ }
+
+ for (i = 0; i < grub_db.signature_entries; i++)
{
- err = grub_errno;
- goto cleanup;
+ grub_printf (N_("trusted binary hash %" PRIuGRUB_SIZE ":\n"), i+1);
+ grub_printf (N_("\thash: "));
+ grub_printhex (grub_db.signatures[i], grub_db.signature_size[i]);
}
- err = file_read_all (f, &data, &file_size);
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_cmd_distrusted_list (grub_command_t cmd __attribute__((unused)),
+ int argc __attribute__((unused)),
+ char **args __attribute__((unused)))
+{
+ struct x509_certificate *cert = NULL;
+ grub_size_t i = 0, cert_num = 1;
+
+ for (cert = grub_dbx.keys; cert; cert = cert->next)
+ {
+ grub_printf (N_("distrusted certificate %" PRIuGRUB_SIZE ":\n"), cert_num);
+ grub_printf (N_("\tserial: "));
+
+ for (i = 0; i < cert->serial_len - 1; i++)
+ grub_printf ("%02x:", cert->serial[i]);
+
+ grub_printf ("%02x\n", cert->serial[cert->serial_len - 1]);
+ grub_printf ("\tCN: %s\n\n", cert->subject);
+ cert_num++;
+ }
+
+ for (i = 0; i < grub_dbx.signature_entries; i++)
+ {
+ grub_printf (N_("distrusted certificate/binary hash %" PRIuGRUB_SIZE ":\n"), i+1);
+ grub_printf (N_("\thash: "));
+ grub_printhex (grub_dbx.signatures[i], grub_dbx.signature_size[i]);
+ }
+
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_cmd_trusted_cert (grub_command_t cmd __attribute__((unused)),
+ int argc, char **args)
+{
+ grub_err_t err = GRUB_ERR_NONE;
+ grub_file_t cert_file = NULL;
+ grub_uint8_t *cert_data = NULL;
+ grub_ssize_t cert_data_size = 0;
+
+ if (argc != 1)
+ {
+ grub_printf (N_("a trusted X.509 certificate file is expected\n"
+ "Example:\n\ttrusted_certificate <CERT FILE>\n"));
+ return GRUB_ERR_BAD_ARGUMENT;
+ }
+
+ if (check_sigs == check_sigs_forced)
+ {
+ grub_printf ("Warning: since secure boot is enabled, "
+ "adding of trusted X.509 certificate is not permitted!\n");
+ return grub_errno;
+ }
+
+ if (grub_strlen (args[0]) == 0)
+ return grub_error (GRUB_ERR_BAD_FILENAME,
+ N_("missing trusted X.509 certificate file"));
+
+ cert_file = grub_file_open (args[0], GRUB_FILE_TYPE_CERTIFICATE_TRUST |
+ GRUB_FILE_TYPE_NO_DECOMPRESS);
+ if (cert_file == NULL)
+ return grub_error (GRUB_ERR_FILE_NOT_FOUND,
+ N_("unable to open the trusted X.509 certificate file"));
+
+ err = grub_read_file (cert_file, &cert_data, &cert_data_size);
if (err != GRUB_ERR_NONE)
- goto cleanup;
+ {
+ grub_file_close (cert_file);
+ return err;
+ }
- err = grub_verify_appended_signature (data, file_size);
+ grub_file_close (cert_file);
+ err = grub_add_certificate (cert_data, cert_data_size, &grub_db, 1);
+ if (err != GRUB_ERR_NONE)
+ {
+ grub_release_trusted_list ();
+ grub_release_distrusted_list ();
+ grub_error (err, "adding of trusted certificate failed");
+ }
- grub_free (data);
+ grub_free (cert_data);
-cleanup:
- if (f)
- grub_file_close (f);
return err;
}
static grub_err_t
-grub_cmd_distrust (grub_command_t cmd __attribute__((unused)),
- int argc, char **args)
+grub_cmd_trusted_hash (grub_command_t cmd __attribute__((unused)), int argc, char**args)
{
- unsigned long cert_num, i;
- struct x509_certificate *cert, *prev;
+ grub_err_t rc = GRUB_ERR_NONE;
+ grub_file_t hash_file = NULL;
+ grub_uint8_t *hash_data = NULL;
+ grub_ssize_t hash_data_size = 0;
if (argc != 1)
- return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("One argument expected"));
+ {
+ grub_printf (N_("a trusted binary hash file is expected\n"
+ "Example:\n\ttrusted_signature <BINARY HASH FILE>\n"));
+ return GRUB_ERR_BAD_ARGUMENT;
+ }
- grub_errno = GRUB_ERR_NONE;
- cert_num = grub_strtoul (args[0], NULL, 10);
- if (grub_errno != GRUB_ERR_NONE)
- return grub_errno;
+ if (check_sigs == check_sigs_forced)
+ {
+ grub_printf ("Warning: since secure boot is enabled, "
+ "adding of trusted binary hash is not permitted!\n");
+ return grub_errno;
+ }
- if (cert_num < 1)
- return grub_error (GRUB_ERR_BAD_ARGUMENT,
- N_("Certificate number too small - numbers start at 1"));
+ if (grub_strlen (args[0]) == 0)
+ return grub_error (GRUB_ERR_BAD_FILENAME, N_("missing trusted binary hash file"));
- if (cert_num == 1)
- {
- cert = grub_db.keys;
- grub_db.keys = cert->next;
+ hash_file = grub_file_open (args[0], GRUB_FILE_TYPE_TO_HASH | GRUB_FILE_TYPE_NO_DECOMPRESS);
+ if (hash_file == NULL)
+ return grub_error (GRUB_ERR_FILE_NOT_FOUND,
+ N_("unable to open the trusted binary hash file"));
- certificate_release (cert);
- grub_free (cert);
- return GRUB_ERR_NONE;
+ rc = grub_read_file (hash_file, &hash_data, &hash_data_size);
+ if (rc != GRUB_ERR_NONE)
+ {
+ grub_file_close (hash_file);
+ return rc;
}
- i = 2;
- prev = grub_db.keys;
- cert = grub_db.keys->next;
- while (cert)
+
+ grub_file_close (hash_file);
+
+ grub_dprintf ("appendedsig", "adding a trusted binary hash %s\n with size of %" PRIdGRUB_SSIZE "\n",
+ hash_data, hash_data_size);
+
+ /* only accept SHA256, SHA384 and SHA512 binary hash */
+ if (hash_data_size != SHA256_LEN && hash_data_size != SHA384_LEN &&
+ hash_data_size != SHA512_LEN)
+ return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("unacceptable trusted binary hash type"));
+
+ rc = grub_add_hash ((const grub_uint8_t **) &hash_data, hash_data_size, &grub_db.signatures,
+ &grub_db.signature_size, &grub_db.signature_entries);
+ if (rc != GRUB_ERR_NONE)
{
- if (i == cert_num)
- {
- prev->next = cert->next;
- certificate_release (cert);
- grub_free (cert);
- return GRUB_ERR_NONE;
- }
- i++;
- prev = cert;
- cert = cert->next;
+ grub_release_trusted_list ();
+ grub_release_distrusted_list ();
+ grub_error (rc, "adding of trusted binary hash failed");
}
- return grub_error (GRUB_ERR_BAD_ARGUMENT,
- N_("No certificate number %lu found - only %lu certificates in the store"),
- cert_num, i - 1);
+ grub_free (hash_data);
+
+ return rc;
}
static grub_err_t
-grub_cmd_trust (grub_command_t cmd __attribute__((unused)),
- int argc, char **args)
+grub_cmd_distrusted_cert (grub_command_t cmd __attribute__((unused)), int argc, char **args)
{
- grub_file_t certf;
- struct x509_certificate *cert = NULL;
- grub_err_t err;
+ grub_size_t cert_num = 0, i = 1;
+ struct x509_certificate *current_cert = grub_db.keys;
+ struct x509_certificate *previous_cert = grub_db.keys;
if (argc != 1)
- return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected"));
+ {
+ grub_printf (N_("trusted certificate number is expected\n"
+ "Example:\n\tdistrusted_certificate <CERT_NUMER>\n"));
+ return GRUB_ERR_BAD_ARGUMENT;
+ }
- certf = grub_file_open (args[0],
- GRUB_FILE_TYPE_CERTIFICATE_TRUST
- | GRUB_FILE_TYPE_NO_DECOMPRESS);
- if (!certf)
- return grub_errno;
+ if (check_sigs == check_sigs_forced)
+ {
+ grub_printf ("Warning: since secure boot is enabled, "
+ "removing of trusted certificate is not permitted!\n");
+ return grub_errno;
+ }
+ cert_num = grub_strtoul (args[0], NULL, 10);
+ if (cert_num < 1)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT,
+ N_("trusted certificate number should to begin with 1"));
- cert = grub_zalloc (sizeof (struct x509_certificate));
- if (!cert)
- return grub_error (GRUB_ERR_OUT_OF_MEMORY,
- N_("Could not allocate memory for certificate"));
+ if (cert_num > grub_db.key_entries)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT,
+ N_("trusted certificate number should not exceed %" PRIuGRUB_SIZE),
+ grub_db.key_entries);
+ else if (cert_num < grub_db.key_entries)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT,
+ N_("there is no certificate on the trusted list. so, not permitted"));
- err = read_cert_from_file (certf, cert);
- grub_file_close (certf);
- if (err != GRUB_ERR_NONE)
+ for (i = 1; i < grub_db.key_entries; i++)
{
- grub_free (cert);
- return err;
+ if (cert_num == 1)
+ {
+ previous_cert = current_cert->next;
+ break;
+ }
+ else if (cert_num == i)
+ {
+ previous_cert->next = current_cert->next;
+ break;
+ }
+
+ previous_cert = current_cert;
+ current_cert = current_cert->next;
}
- grub_dprintf ("appendedsig", "Loaded certificate with CN: %s\n",
- cert->subject);
- cert->next = grub_db.keys;
- grub_db.keys = cert;
+ certificate_release (current_cert);
+ grub_free (current_cert);
return GRUB_ERR_NONE;
}
static grub_err_t
-grub_cmd_list (grub_command_t cmd __attribute__((unused)),
- int argc __attribute__((unused)),
- char **args __attribute__((unused)))
+grub_cmd_distrusted_hash (grub_extcmd_context_t ctxt, int argc, char **args)
{
- struct x509_certificate *cert;
- int cert_num = 1;
- grub_size_t i;
+ grub_err_t rc = GRUB_ERR_NONE;
+ grub_file_t hash_file = NULL;
+ grub_uint8_t *hash_data = NULL;
+ grub_ssize_t hash_data_size = 0;
- for (cert = grub_db.keys; cert; cert = cert->next)
+ if (argc != 2)
{
- grub_printf (N_("Certificate %d:\n"), cert_num);
+ grub_printf (N_("a distrusted certificate/binary hash file is expected\n"
+ "Example:\n\tdistrusted_signature [option] <FILE>\n"
+ "option:\n[-b|--binary-hash] FILE [BINARY HASH FILE]\n"
+ "[-c|--cert-hash] FILE [CERTFICATE HASH FILE]\n"));
+ return GRUB_ERR_BAD_ARGUMENT;
+ }
- grub_printf (N_("\tSerial: "));
- for (i = 0; i < cert->serial_len - 1; i++)
- {
- grub_printf ("%02x:", cert->serial[i]);
- }
- grub_printf ("%02x\n", cert->serial[cert->serial_len - 1]);
+ if (check_sigs == check_sigs_forced)
+ {
+ grub_printf ("Warning: since secure boot is enabled, "
+ "adding of distrusted certificate/binary hash is not permitted!\n");
+ return grub_errno;
+ }
- grub_printf ("\tCN: %s\n\n", cert->subject);
- cert_num++;
+ if (!ctxt->state[OPTION_BINARY_HASH].set && !ctxt->state[OPTION_CERT_HASH].set)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("missing options and use --help to konw"));
+
+ if (grub_strlen (args[1]) == 0)
+ return grub_error (GRUB_ERR_BAD_FILENAME,
+ N_("missing distrusted certificate/binary hash file"));
+
+ hash_file = grub_file_open (args[1], GRUB_FILE_TYPE_TO_HASH | GRUB_FILE_TYPE_NO_DECOMPRESS);
+ if (hash_file == NULL)
+ return grub_error (GRUB_ERR_FILE_NOT_FOUND,
+ N_("unable to open the distrusted certificate/binary hash file"));
+ rc = grub_read_file (hash_file, &hash_data, &hash_data_size);
+ if (rc != GRUB_ERR_NONE)
+ {
+ grub_file_close (hash_file);
+ return rc;
}
- return GRUB_ERR_NONE;
+ grub_file_close (hash_file);
+
+ grub_dprintf ("appendedsig", "adding a distrusted certificate/binary hash %s\n"
+ " with size of %" PRIdGRUB_SSIZE "\n", hash_data, hash_data_size);
+
+ if (ctxt->state[OPTION_BINARY_HASH].set)
+ {
+ /* only accept SHA256, SHA384 and SHA512 binary hash */
+ if (hash_data_size != SHA256_LEN && hash_data_size != SHA384_LEN &&
+ hash_data_size != SHA512_LEN)
+ return grub_error (GRUB_ERR_BAD_SIGNATURE,
+ N_("unacceptable distrusted binary hash type"));
+ }
+ else if (ctxt->state[OPTION_CERT_HASH].set)
+ {
+ /* only accept SHA256, SHA384 and SHA512 certificate hash */
+ if (hash_data_size != SHA256_LEN && hash_data_size != SHA384_LEN &&
+ hash_data_size != SHA512_LEN)
+ return grub_error (GRUB_ERR_BAD_SIGNATURE,
+ N_("unacceptable distrusted certificate hash type"));
+ }
+
+ rc = grub_add_hash ((const grub_uint8_t **) &hash_data, hash_data_size, &grub_dbx.signatures,
+ &grub_dbx.signature_size, &grub_dbx.signature_entries);
+ if (rc != GRUB_ERR_NONE)
+ {
+ grub_release_trusted_list ();
+ grub_release_distrusted_list ();
+ grub_error (rc, "adding of distrusted binary/certificate hash failed");
+ }
+
+ grub_free (hash_data);
+
+ return rc;
}
static grub_err_t
-appendedsig_init (grub_file_t io __attribute__((unused)),
- enum grub_file_type type,
- void **context __attribute__((unused)),
- enum grub_verify_flags *flags)
+appendedsig_init (grub_file_t io __attribute__ ((unused)), enum grub_file_type type,
+ void **context __attribute__ ((unused)), enum grub_verify_flags *flags)
{
if (check_sigs == check_sigs_no)
{
@@ -1212,7 +1373,9 @@ grub_load_static_keys (struct grub_module_header *header, bool mode)
return rc;
}
-static grub_command_t cmd_verify, cmd_list, cmd_distrust, cmd_trust;
+static grub_extcmd_t cmd_distrusted_hash;
+static grub_command_t cmd_verify, cmd_trusted_list, cmd_trusted_cert, cmd_trusted_hash,
+ cmd_distrusted_list, cmd_distrusted_cert;
GRUB_MOD_INIT (appendedsig)
{
@@ -1278,21 +1441,31 @@ GRUB_MOD_INIT (appendedsig)
grub_release_platform_keystore ();
}
- cmd_trust =
- grub_register_command ("trust_certificate", grub_cmd_trust,
- N_("X509_CERTIFICATE"),
- N_("Add X509_CERTIFICATE to trusted certificates."));
- cmd_list =
- grub_register_command ("list_certificates", grub_cmd_list, 0,
- N_("Show the list of trusted x509 certificates."));
- cmd_verify =
- grub_register_command ("verify_appended", grub_cmd_verify_signature,
- N_("FILE"),
- N_("Verify FILE against the trusted x509 certificates."));
- cmd_distrust =
- grub_register_command ("distrust_certificate", grub_cmd_distrust,
- N_("CERT_NUMBER"),
- N_("Remove CERT_NUMBER (as listed by list_certificates) from trusted certificates."));
+ cmd_trusted_cert = grub_register_command ("trusted_certificate", grub_cmd_trusted_cert,
+ N_("X509_CERTIFICATE"),
+ N_("Add X509_CERTIFICATE to trusted list."));
+ cmd_trusted_hash = grub_register_command ("trusted_signature", grub_cmd_trusted_hash,
+ N_("BINARY HASH FILE"),
+ N_("Add trusted BINARY HASH to trusted list."));
+ cmd_distrusted_cert = grub_register_command ("distrusted_certificate", grub_cmd_distrusted_cert,
+ N_("CERT_NUMBER"),
+ N_("Remove CERT_NUMBER (as listed by list_trusted)"
+ " from trusted list."));
+ cmd_distrusted_hash = grub_register_extcmd ("distrusted_signature", grub_cmd_distrusted_hash, 0,
+ N_("[-b|--binary-hash] FILE [BINARY HASH FILE]\n"
+ "[-c|--cert-hash] FILE [CERTFICATE HASH FILE]"),
+ N_("Add distrusted CERTFICATE/BINARY HASH "
+ "to distrusted list."),
+ options);
+ cmd_trusted_list = grub_register_command ("trusted_list", grub_cmd_trusted_list, 0,
+ N_("Show the list of trusted x509 certificates and"
+ " trusted binary hashes."));
+ cmd_distrusted_list = grub_register_command ("distrusted_list", grub_cmd_distrusted_list, 0,
+ N_("Show the list of distrusted certificates and"
+ " certificate/binary hashes"));
+ cmd_verify = grub_register_command ("verify_appended", grub_cmd_verify_signature, N_("FILE"),
+ N_("Verify FILE against the trusted x509 certificates/"
+ "trusted binary hashes."));
grub_verifier_register (&grub_appendedsig_verifier);
grub_dl_set_persistent (mod);
@@ -1304,10 +1477,12 @@ GRUB_MOD_FINI (appendedsig)
* grub_dl_set_persistent should prevent this from actually running, but
* it does still run under emu.
*/
-
grub_verifier_unregister (&grub_appendedsig_verifier);
grub_unregister_command (cmd_verify);
- grub_unregister_command (cmd_list);
- grub_unregister_command (cmd_trust);
- grub_unregister_command (cmd_distrust);
+ grub_unregister_command (cmd_trusted_list);
+ grub_unregister_command (cmd_distrusted_list);
+ grub_unregister_command (cmd_trusted_cert);
+ grub_unregister_command (cmd_distrusted_cert);
+ grub_unregister_command (cmd_trusted_hash);
+ grub_unregister_extcmd (cmd_distrusted_hash);
}
--
2.47.0

View File

@ -0,0 +1,223 @@
From 87831c6ce3536e5e2eeb3e2cd8a6184b9509ee04 Mon Sep 17 00:00:00 2001
From: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
Date: Wed, 17 Apr 2024 23:04:43 +0530
Subject: [PATCH 6/8] appendedsig: documentation
This explains appended signatures static key and dynamic key,
and documents the commands and variables introduced.
Signed-off-by: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
---
docs/grub.texi | 115 ++++++++++++++++++++++++++++++++++---------------
1 file changed, 80 insertions(+), 35 deletions(-)
diff --git a/docs/grub.texi b/docs/grub.texi
index 00c5fdc44..68d7cbb90 100644
--- a/docs/grub.texi
+++ b/docs/grub.texi
@@ -4373,7 +4373,9 @@ you forget a command, you can run the command @command{help}
* date:: Display or set current date and time
* devicetree:: Load a device tree blob
* distrust:: Remove a pubkey from trusted keys
-* distrust_certificate:: Remove a certificate from the list of trusted certificates
+* distrusted_certificate:: Remove a certificate from the trusted list
+* distrusted_list:: List distrusted certificates and binary/certificate hashes
+* distrusted_signature:: Add a binary hash to the distrusted list
* drivemap:: Map a drive to another
* echo:: Display a line of text
* efitextmode:: Set/Get text output mode resolution
@@ -4390,7 +4392,6 @@ you forget a command, you can run the command @command{help}
* hexdump:: Show raw contents of a file or memory
* insmod:: Insert a module
* keystatus:: Check key modifier status
-* list_certificates:: List trusted certificates
* list_env:: List variables in environment block
* list_trusted:: List trusted public keys
* load_env:: Load variables from environment block
@@ -4429,7 +4430,9 @@ you forget a command, you can run the command @command{help}
* test:: Check file types and compare values
* true:: Do nothing, successfully
* trust:: Add public key to list of trusted keys
-* trust_certificate:: Add an x509 certificate to the list of trusted certificates
+* trusted_certificate:: Add an x509 certificate to the trusted list
+* trusted_list:: List trusted certificates and binary hashes
+* trusted_signature:: Add a binary hash to the trusted list.
* unset:: Unset an environment variable
@comment * vbeinfo:: List available video modes
* verify_appended:: Verify appended digital signature
@@ -4776,15 +4779,15 @@ GPG-style digital signatures}, for more information.
@end deffn
-@node distrust_certificate
-@subsection distrust_certificate
+@node distrusted_certificate
+@subsection distrusted_certificate
-@deffn Command distrust_certificate cert_number
+@deffn Command distrusted_certificate cert_number
Remove the x509 certificate numbered @var{cert_number} from GRUB's keyring of
trusted x509 certificates for verifying appended signatures.
@var{cert_number} is the certificate number as listed by
-@command{list_certificates} (@pxref{list_certificates}).
+@command{trusted_list} (@pxref{trusted_list}).
These certificates are used to validate appended signatures when environment
variable @code{check_appended_signatures} is set to @code{enforce}
@@ -4793,6 +4796,27 @@ variable @code{check_appended_signatures} is set to @code{enforce}
information.
@end deffn
+@node distrusted_list
+@subsection distrusted_list
+
+@deffn Command distrusted_list
+List all the distrusted x509 certificates and binary/certificate hashes.
+The output is a numbered list of certificates and binary/certificate hashes,
+showing the certificate's serial number and Common Name.
+@end deffn
+
+@node distrusted_signature
+@subsection distrusted_signature
+
+@deffn Command distrusted_signature
+Read a binary hash from the file @var{binary hash file}
+and add it to GRUB's internal distrusted list. These hash are used to
+restrict validation of linux image integrity using trusted list if appended
+signatures validation failed when the environment variable
+@code{check_appended_signatures} is set to @code{enforce}.
+
+See @xref{Using appended signatures} for more information.
+@end deffn
@node drivemap
@subsection drivemap
@@ -5069,22 +5093,6 @@ without any options, the @command{keystatus} command returns true if and
only if checking key modifier status is supported.
@end deffn
-
-@node list_certificates
-@subsection list_certificates
-
-@deffn Command list_certificates
-List all x509 certificates trusted by GRUB for validating appended signatures.
-The output is a numbered list of certificates, showing the certificate's serial
-number and Common Name.
-
-The certificate number can be used as an argument to
-@command{distrust_certificate} (@pxref{distrust_certificate}).
-
-See @xref{Using appended signatures} for more information.
-@end deffn
-
-
@node list_env
@subsection list_env
@@ -5935,9 +5943,8 @@ and manual booting. @xref{Using GPG-style digital signatures}, for more
information.
@end deffn
-
-@node trust_certificate
-@subsection trust_certificate
+@node trusted_certificate
+@subsection trusted_certificate
@deffn Command trust_certificate x509_certificate
Read a DER-formatted x509 certificate from the file @var{x509_certificate}
@@ -5946,7 +5953,7 @@ certificates are used to validate appended signatures when the environment
variable @code{check_appended_signatures} is set to @code{enforce}.
Note that if @code{check_appended_signatures} is set to @code{enforce}
-when @command{trust_certificate} is executed, then @var{x509_certificate}
+when @command{trusted_certificate} is executed, then @var{x509_certificate}
must itself bear an appended signature. (It is not sufficient that
@var{x509_certificate} be signed by a trusted certificate according to the
x509 rules: grub does not include support for validating signatures within x509
@@ -5955,6 +5962,32 @@ certificates themselves.)
See @xref{Using appended signatures} for more information.
@end deffn
+@node trusted_list
+@subsection trusted_list
+
+@deffn Command trusted_list
+List all x509 certificates and binary hases trusted by GRUB for validating
+appended signatures. The output is a numbered list of certificates and binary
+hashes, showing the certificate's serial number and Common Name.
+
+The certificate number can be used as an argument to
+@command{distrusted_certificate} (@pxref{distrusted_certificate}).
+
+See @xref{Using appended signatures} for more information.
+@end deffn
+
+@node trusted_signature
+@subsection trusted_signature
+
+@deffn Command trust_signature
+Read a binary hash from the file @var{binary hash file}
+and add it to GRUB's internal trusted list. These binary hash are used to
+validate linux image integrity if appended signatures validation failed
+when the environment variable @code{check_appended_signatures} is set
+to @code{enforce}.
+
+See @xref{Using appended signatures} for more information.
+@end deffn
@node unset
@subsection unset
@@ -5979,8 +6012,8 @@ only on PC BIOS platforms.
@deffn Command verify_appended file
Verifies an appended signature on @var{file} against the trusted certificates
-known to GRUB (See @pxref{list_certificates}, @pxref{trust_certificate}, and
-@pxref{distrust_certificate}).
+known to GRUB (See @pxref{trusted_list}, @pxref{trusted_certificate}, and
+@pxref{distrusted_certificate}).
Exit code @code{$?} is set to 0 if the signature validates
successfully. If validation fails, it is set to a non-zero value.
@@ -6664,17 +6697,29 @@ with an appended signature ends with the magic string:
where @code{\n} represents the carriage-return character, @code{0x0a}.
To enable appended signature verification, load the appendedsig module and an
-x509 certificate for verification. Building the appendedsig module into the
+trusted keys for verification. Building the appendedsig module into the
core grub image is recommended.
-Certificates can be managed at boot time using the @pxref{trust_certificate},
-@pxref{distrust_certificate} and @pxref{list_certificates} commands.
-Certificates can also be built in to the core image using the @code{--x509}
-parameter to @command{grub-install} or @command{grub-mkimage}.
+For static key, Certificates will be built in to the core image using
+the @code{--x509} parameter to @command{grub-install} or @command{grub-mkimage}.
+it can allow to list the trusted certificates and binary hashes at boot time using
+@pxref{trusted_list} and list distrusted certificates and binary/certificate hashes
+at boot time using @pxref{distrusted_list} commands.
+
+For dynamic key, loads the signature database (DB) and forbidden
+signature database (DBX) from platform keystore (PKS) and it can allow to list
+the trusted certificates and binary hashes at boot time using @pxref{trusted_list}
+and list distrusted certificates and binary/certificate hashes at boot time using
+@pxref{distrusted_list} commands.
+
+Also, it will not allow to manage add/delete of certificates/signature at boot time using
+@pxref{trusted_certificate} and @pxref{trusted_signature}, @pxref{distrusted_certificate}
+and @pxref{distrusted_signature} commands when the environment variable
+@code{check_appended_signatures} is set to @code{enforce}.
A file can be explictly verified using the @pxref{verify_appended} command.
-Only signatures made with the SHA-256 or SHA-512 hash algorithm are supported,
+Only signatures made with the SHA-256, SH-384 and SHA-512 hash algorithm are supported,
and only RSA signatures are supported.
A file can be signed with the @command{sign-file} utility supplied with the
--
2.47.0

View File

@ -0,0 +1,189 @@
From 77316f09f133e9c7c5e1026b2b4f5749daac644a Mon Sep 17 00:00:00 2001
From: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
Date: Wed, 17 Apr 2024 23:48:51 +0530
Subject: [PATCH 7/8] mkimage: create new ELF Note for SBAT
we add a new ELF note for SBAT which store the SBAT data.
The name field of shall be the string "Secure-Boot-Advanced-Targeting", zero-padded
to 4 byte alignment. The type field shall be 0x41536967 (the ASCII values
for the string "sbat").
Signed-off-by: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
Co-authored-by: Daniel Axtens <dja@axtens.net>
---
include/grub/util/mkimage.h | 4 +-
util/grub-mkimagexx.c | 92 +++++++++++++++++++++++++++----------
2 files changed, 71 insertions(+), 25 deletions(-)
diff --git a/include/grub/util/mkimage.h b/include/grub/util/mkimage.h
index 6f1da89b9..881e3031f 100644
--- a/include/grub/util/mkimage.h
+++ b/include/grub/util/mkimage.h
@@ -51,12 +51,12 @@ grub_mkimage_load_image64 (const char *kernel_path,
const struct grub_install_image_target_desc *image_target);
void
grub_mkimage_generate_elf32 (const struct grub_install_image_target_desc *image_target,
- int note, size_t appsig_size, char **core_img, size_t *core_size,
+ int note, size_t appsig_size, char *sbat, char **core_img, size_t *core_size,
Elf32_Addr target_addr,
struct grub_mkimage_layout *layout);
void
grub_mkimage_generate_elf64 (const struct grub_install_image_target_desc *image_target,
- int note, size_t appsig_size, char **core_img, size_t *core_size,
+ int note, size_t appsig_size, char *sbat, char **core_img, size_t *core_size,
Elf64_Addr target_addr,
struct grub_mkimage_layout *layout);
diff --git a/util/grub-mkimagexx.c b/util/grub-mkimagexx.c
index 9488f0525..0041b2d0b 100644
--- a/util/grub-mkimagexx.c
+++ b/util/grub-mkimagexx.c
@@ -85,6 +85,14 @@ struct grub_ieee1275_note
struct grub_ieee1275_note_desc descriptor;
};
+#define GRUB_SBAT_NOTE_NAME "Secure-Boot-Advanced-Targeting"
+#define GRUB_SBAT_NOTE_TYPE 0x73626174 /* "sbat" */
+
+struct grub_sbat_note {
+ Elf32_Nhdr header;
+ char name[ALIGN_UP(sizeof(GRUB_SBAT_NOTE_NAME), 4)];
+};
+
#define GRUB_APPENDED_SIGNATURE_NOTE_NAME "Appended-Signature"
#define GRUB_APPENDED_SIGNATURE_NOTE_TYPE 0x41536967 /* "ASig" */
@@ -217,7 +225,7 @@ grub_arm_reloc_jump24 (grub_uint32_t *target, Elf32_Addr sym_addr)
void
SUFFIX (grub_mkimage_generate_elf) (const struct grub_install_image_target_desc *image_target,
- int note, size_t appsig_size, char **core_img, size_t *core_size,
+ int note, size_t appsig_size, char *sbat, char **core_img, size_t *core_size,
Elf_Addr target_addr,
struct grub_mkimage_layout *layout)
{
@@ -226,10 +234,17 @@ SUFFIX (grub_mkimage_generate_elf) (const struct grub_install_image_target_desc
Elf_Ehdr *ehdr;
Elf_Phdr *phdr;
Elf_Shdr *shdr;
- int header_size, footer_size = 0;
+ int header_size, footer_size = 0, footer_offset = 0;
int phnum = 1;
int shnum = 4;
int string_size = sizeof (".text") + sizeof ("mods") + 1;
+ char *footer;
+
+ if (sbat)
+ {
+ phnum++;
+ footer_size += ALIGN_UP (sizeof (struct grub_sbat_note) + layout->sbat_size, 4);
+ }
if (appsig_size)
{
@@ -263,6 +278,7 @@ SUFFIX (grub_mkimage_generate_elf) (const struct grub_install_image_target_desc
ehdr = (void *) elf_img;
phdr = (void *) (elf_img + sizeof (*ehdr));
shdr = (void *) (elf_img + sizeof (*ehdr) + phnum * sizeof (*phdr));
+ footer = elf_img + program_size + header_size;
memcpy (ehdr->e_ident, ELFMAG, SELFMAG);
ehdr->e_ident[EI_CLASS] = ELFCLASSXX;
if (!image_target->bigendian)
@@ -435,6 +451,8 @@ SUFFIX (grub_mkimage_generate_elf) (const struct grub_install_image_target_desc
phdr->p_filesz = grub_host_to_target32 (XEN_NOTE_SIZE);
phdr->p_memsz = 0;
phdr->p_offset = grub_host_to_target32 (header_size + program_size);
+ footer = ptr;
+ footer_offset = XEN_NOTE_SIZE;
}
if (image_target->id == IMAGE_XEN_PVH)
@@ -468,6 +486,8 @@ SUFFIX (grub_mkimage_generate_elf) (const struct grub_install_image_target_desc
phdr->p_filesz = grub_host_to_target32 (XEN_PVH_NOTE_SIZE);
phdr->p_memsz = 0;
phdr->p_offset = grub_host_to_target32 (header_size + program_size);
+ footer = ptr;
+ footer_offset = XEN_PVH_NOTE_SIZE;
}
if (note)
@@ -498,29 +518,55 @@ SUFFIX (grub_mkimage_generate_elf) (const struct grub_install_image_target_desc
phdr->p_filesz = grub_host_to_target32 (note_size);
phdr->p_memsz = 0;
phdr->p_offset = grub_host_to_target32 (header_size + program_size);
+ footer = (elf_img + program_size + header_size + note_size);
+ footer_offset += note_size;
}
- if (appsig_size) {
- int note_size = ALIGN_UP(sizeof (struct grub_appended_signature_note) + appsig_size, 4);
- struct grub_appended_signature_note *note_ptr = (struct grub_appended_signature_note *)
- (elf_img + program_size + header_size + (note ? sizeof (struct grub_ieee1275_note) : 0));
-
- note_ptr->header.n_namesz = grub_host_to_target32 (sizeof (GRUB_APPENDED_SIGNATURE_NOTE_NAME));
- /* needs to sit at the end, so we round this up and sign some zero padding */
- note_ptr->header.n_descsz = grub_host_to_target32 (ALIGN_UP(appsig_size, 4));
- note_ptr->header.n_type = grub_host_to_target32 (GRUB_APPENDED_SIGNATURE_NOTE_TYPE);
- strcpy (note_ptr->name, GRUB_APPENDED_SIGNATURE_NOTE_NAME);
-
- phdr++;
- phdr->p_type = grub_host_to_target32 (PT_NOTE);
- phdr->p_flags = grub_host_to_target32 (PF_R);
- phdr->p_align = grub_host_to_target32 (image_target->voidp_sizeof);
- phdr->p_vaddr = 0;
- phdr->p_paddr = 0;
- phdr->p_filesz = grub_host_to_target32 (note_size);
- phdr->p_memsz = 0;
- phdr->p_offset = grub_host_to_target32 (header_size + program_size + (note ? sizeof (struct grub_ieee1275_note) : 0));
- }
+ if (sbat)
+ {
+ int note_size = ALIGN_UP(sizeof (struct grub_sbat_note) + layout->sbat_size, 4);
+ struct grub_sbat_note *note_ptr = (struct grub_sbat_note *)footer;
+
+ note_ptr->header.n_namesz = grub_host_to_target32 (sizeof (GRUB_SBAT_NOTE_NAME));
+ note_ptr->header.n_descsz = grub_host_to_target32 (ALIGN_UP(layout->sbat_size, 4));
+ note_ptr->header.n_type = grub_host_to_target32 (GRUB_SBAT_NOTE_TYPE);
+ memcpy (note_ptr->name, GRUB_SBAT_NOTE_NAME, sizeof (GRUB_SBAT_NOTE_NAME));
+ memcpy ((char *)(note_ptr + 1), sbat, layout->sbat_size);
+
+ phdr++;
+ phdr->p_type = grub_host_to_target32 (PT_NOTE);
+ phdr->p_flags = grub_host_to_target32 (PF_R);
+ phdr->p_align = grub_host_to_target32 (image_target->voidp_sizeof);
+ phdr->p_vaddr = 0;
+ phdr->p_paddr = 0;
+ phdr->p_filesz = grub_host_to_target32 (note_size);
+ phdr->p_memsz = 0;
+ phdr->p_offset = grub_host_to_target32 (header_size + program_size + footer_offset);
+
+ footer += note_size;
+ footer_offset += note_size;
+ }
+
+ if (appsig_size)
+ {
+ int note_size = ALIGN_UP (sizeof (struct grub_appended_signature_note) + appsig_size, 4);
+ struct grub_appended_signature_note *note_ptr = (struct grub_appended_signature_note *)footer;
+ note_ptr->header.n_namesz = grub_host_to_target32 (sizeof (GRUB_APPENDED_SIGNATURE_NOTE_NAME));
+ /* needs to sit at the end, so we round this up and sign some zero padding */
+ note_ptr->header.n_descsz = grub_host_to_target32 (ALIGN_UP (appsig_size, 4));
+ note_ptr->header.n_type = grub_host_to_target32 (GRUB_APPENDED_SIGNATURE_NOTE_TYPE);
+ strcpy (note_ptr->name, GRUB_APPENDED_SIGNATURE_NOTE_NAME);
+
+ phdr++;
+ phdr->p_type = grub_host_to_target32 (PT_NOTE);
+ phdr->p_flags = grub_host_to_target32 (PF_R);
+ phdr->p_align = grub_host_to_target32 (image_target->voidp_sizeof);
+ phdr->p_vaddr = 0;
+ phdr->p_paddr = 0;
+ phdr->p_filesz = grub_host_to_target32 (note_size);
+ phdr->p_memsz = 0;
+ phdr->p_offset = grub_host_to_target32 (header_size + program_size + footer_offset);
+ }
{
char *str_start = (elf_img + sizeof (*ehdr) + phnum * sizeof (*phdr)
--
2.47.0

View File

@ -0,0 +1,66 @@
From 32d4823762e5a0e7f8bfc5a878d39e1a019392fe Mon Sep 17 00:00:00 2001
From: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
Date: Thu, 18 Apr 2024 00:00:55 +0530
Subject: [PATCH 8/8] mkimage: adding sbat data into sbat ELF Note on powerpc
it reads the SBAT data from sbat.csv and create the ELF Note for it then
store the SBAT data on it while generate image with -s option
Signed-off-by: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
Co-authored-by: Daniel Axtens <dja@axtens.net>
---
util/mkimage.c | 23 +++++++++++++++++------
1 file changed, 17 insertions(+), 6 deletions(-)
diff --git a/util/mkimage.c b/util/mkimage.c
index 0737935fd..136e4a90c 100644
--- a/util/mkimage.c
+++ b/util/mkimage.c
@@ -958,8 +958,9 @@ grub_install_generate_image (const char *dir, const char *prefix,
total_module_size += dtb_size + sizeof (struct grub_module_header);
}
- if (sbat_path != NULL && image_target->id != IMAGE_EFI)
- grub_util_error (_(".sbat section can be embedded into EFI images only"));
+ if (sbat_path != NULL && (image_target->id != IMAGE_EFI && image_target->id != IMAGE_PPC))
+ grub_util_error (_(".sbat section can be embedded into EFI images/"
+ "sbat ELF Note cab be added into powerpc-ieee1275 images only"));
if (disable_shim_lock)
total_module_size += sizeof (struct grub_module_header);
@@ -1835,6 +1836,16 @@ grub_install_generate_image (const char *dir, const char *prefix,
case IMAGE_I386_IEEE1275:
{
grub_uint64_t target_addr;
+ char *sbat = NULL;
+
+ if (sbat_path != NULL)
+ {
+ sbat_size = grub_util_get_image_size (sbat_path);
+ sbat = xmalloc (sbat_size);
+ grub_util_load_image (sbat_path, sbat);
+ layout.sbat_size = sbat_size;
+ }
+
if (image_target->id == IMAGE_LOONGSON_ELF)
{
if (comp == GRUB_COMPRESSION_NONE)
@@ -1846,11 +1857,11 @@ grub_install_generate_image (const char *dir, const char *prefix,
else
target_addr = image_target->link_addr;
if (image_target->voidp_sizeof == 4)
- grub_mkimage_generate_elf32 (image_target, note, appsig_size, &core_img,
- &core_size, target_addr, &layout);
+ grub_mkimage_generate_elf32 (image_target, note, appsig_size, sbat, &core_img, &core_size,
+ target_addr, &layout);
else
- grub_mkimage_generate_elf64 (image_target, note, appsig_size, &core_img,
- &core_size, target_addr, &layout);
+ grub_mkimage_generate_elf64 (image_target, note, appsig_size, sbat, &core_img, &core_size,
+ target_addr, &layout);
}
break;
}
--
2.47.0

View File

@ -21,6 +21,11 @@ v2 -> v3 (by fvogt@suse.de)
- make it a runtime decision (bsc#1164385)
v3 -> v4
- display the message only when necessary
- clear the screen to enhance visual comfort (bsc#1224465)
--- a/Makefile.util.def
+++ b/Makefile.util.def
@@ -552,6 +552,12 @@
@ -38,17 +43,25 @@ v2 -> v3 (by fvogt@suse.de)
name = grub-mkrescue;
--- a/util/grub.d/00_header.in
+++ b/util/grub.d/00_header.in
@@ -247,6 +247,10 @@
@@ -246,6 +246,18 @@
fi
fi
cat << EOF
+if echo "$GRUB_TERMINAL_OUTPUT" | grep -qwv console &&
+ ([ x"$GRUB_TIMEOUT_STYLE" = xmenu ] ||
+ ([ x"$GRUB_TIMEOUT_STYLE" = x ] &&
+ [ x"$GRUB_HIDDEN_TIMEOUT" = x -o x"$GRUB_HIDDEN_TIMEOUT" = x0 ])); then
+ cat <<EOF
+ if [ "\${grub_platform}" = "efi" ]; then
+ clear
+ echo "Please press 't' to show the boot menu on this console"
+ fi
+EOF
+fi
+
cat << EOF
set gfxmode=${GRUB_GFXMODE}
load_video
insmod gfxterm
--- /dev/null
+++ b/util/grub.d/95_textmode.in
@@ -0,0 +1,12 @@

View File

@ -22,17 +22,23 @@ minix.
[1] https://savannah.gnu.org/bugs/index.php?57652
[2] https://bugzilla.opensuse.org/attachment.cgi?id=828118
v2:
We are still encountering the error. Instead of ensuring ext[234] is tried
before minix, make sure everything is tried before minix unless its detection
issue can be properly addressed.
--- a/Makefile.am
+++ b/Makefile.am
@@ -51,8 +51,11 @@
@@ -51,8 +51,12 @@
-D'GRUB_MOD_INIT(x)=@MARKER@x@' $^ > $@ || (rm -f $@; exit 1)
CLEANFILES += libgrub.pp
+# the grep/sed ensures that ext2 gets initialized before minix*
+# the grep/sed ensures that every other file system gets tested before minix*"
+# see https://savannah.gnu.org/bugs/?57652
+# see https://bugzilla.suse.com/show_bug.cgi?id=1231604
libgrub_a_init.lst: libgrub.pp
cat $< | grep '^@MARKER@' | sed 's/@MARKER@\(.*\)@/\1/g' | sort -u > $@ || (rm -f $@; exit 1)
+ if grep ^ext2 $@ >/dev/null; then sed '/ext2/d;/newc/iext2' < $@ > $@.tmp && mv $@.tmp $@; fi
+ if grep ^minix $@ >/dev/null; then sed -n '/^minix/p;/^minix/!H;$${x;s/^\n//;p}' < $@ > $@.tmp && mv $@.tmp $@; fi
CLEANFILES += libgrub_a_init.lst
libgrub_a_init.c: libgrub_a_init.lst $(top_srcdir)/geninit.sh

View File

@ -1,3 +1,89 @@
-------------------------------------------------------------------
Wed Oct 30 00:44:41 UTC 2024 - Michael Chang <mchang@suse.com>
- Enable support of Radix, Xive and Radix_gtse on Power (jsc#PED-9881)
* 0001-kern-ieee1275-init-Add-IEEE-1275-Radix-support-for-K.patch
-------------------------------------------------------------------
Wed Oct 23 06:17:54 UTC 2024 - Michael Chang <mchang@suse.com>
- Fix error: /boot/grub2/x86_64-efi/bli.mod not found (bsc#1231591)
-------------------------------------------------------------------
Tue Oct 22 07:34:04 UTC 2024 - Michael Chang <mchang@suse.com>
- Keep grub packaging and dependencies in the SLE-12 and SLE-15 builds
-------------------------------------------------------------------
Fri Oct 18 07:42:27 UTC 2024 - Michael Chang <mchang@suse.com>
- Power guest secure boot with key management (jsc#PED-3520) (jsc#PED-9892)
* 0001-ieee1275-Platform-Keystore-PKS-Support.patch
* 0002-ieee1275-Read-the-DB-and-DBX-secure-boot-variables.patch
* 0003-appendedsig-The-creation-of-trusted-and-distrusted-l.patch
* 0004-appendedsig-While-verifying-the-kernel-use-trusted-a.patch
* 0005-appendedsig-The-grub-command-s-trusted-and-distruste.patch
* 0006-appendedsig-documentation.patch
* 0007-mkimage-create-new-ELF-Note-for-SBAT.patch
* 0008-mkimage-adding-sbat-data-into-sbat-ELF-Note-on-power.patch
* grub2.spec : Building signed grub.elf with SBAT metadata
- Support for NVMe multipath splitter (jsc#PED-10538)
* 0001-ieee1275-support-added-for-multiple-nvme-bootpaths.patch
- Deleted path (jsc#PED-10538)
* 0001-grub2-Can-t-setup-a-default-boot-device-correctly-on.patch
* 0001-grub2-Set-multiple-device-path-for-a-nvmf-boot-devic.patch
-------------------------------------------------------------------
Wed Oct 16 13:50:00 UTC 2024 - Michael Chang <mchang@suse.com>
- Fix not a directory error from the minix filesystem, as leftover data on disk
may contain its magic header so it gets misdetected (bsc#1231604)
* grub2-install-fix-not-a-directory-error.patch
-------------------------------------------------------------------
Fri Oct 4 06:58:06 UTC 2024 - Michael Chang <mchang@suse.com>
- Fix missng menu entry "Start bootloader from a read-only snapshot" by
ensuring grub2-snapper-plugin is installed when both snapper and grub2-common
are installed (bsc#1231271)
-------------------------------------------------------------------
Fri Oct 4 06:49:12 UTC 2024 - Michael Chang <mchang@suse.com>
- Fix OOM error in loading loopback file (bsc#1230840)
* 0001-tpm-Skip-loopback-image-measurement.patch
-------------------------------------------------------------------
Fri Oct 4 06:41:11 UTC 2024 - Michael Chang <mchang@suse.com>
- Fix UEFI PXE boot failure on tagged VLAN network (bsc#1230263)
* 0001-efinet-Skip-virtual-VLAN-devices-during-card-enumera.patch
-------------------------------------------------------------------
Thu Oct 3 08:25:57 UTC 2024 - Michael Chang <mchang@suse.com>
- Fix grub screen is filled with artifects from earlier post menu (bsc#1224465)
* grub2-SUSE-Add-the-t-hotkey.patch
* 0001-fix-grub-screen-filled-with-post-screen-artifects.patch
-------------------------------------------------------------------
Tue Aug 13 07:12:58 UTC 2024 - Michael Chang <mchang@suse.com>
- Introduces a new package, grub2-x86_64-efi-bls, which includes a
straightforward grubbls.efi file. This file can be copied to the EFI System
Partition (ESP) along with boot fragments in the Boot Loader Specification
(BLS) format
* 0001-Streamline-BLS-and-improve-PCR-stability.patch
- Fix crash in bli module (bsc#1226497)
* 0001-bli-Fix-crash-in-get_part_uuid.patch
-------------------------------------------------------------------
Tue Aug 13 02:42:42 UTC 2024 - Michael Chang <mchang@suse.com>
- Rework package dependencies: grub2-common now includes common userland
utilities and is required by grub2 platform packages. grub2 is now a meta
package that pulls in the default platform package.
-------------------------------------------------------------------
Fri Aug 2 08:44:40 UTC 2024 - Michael Chang <mchang@suse.com>

View File

@ -356,8 +356,6 @@ Patch164: 0003-ieee1275-change-the-logic-of-ieee1275_get_devargs.patch
Patch165: 0004-ofpath-controller-name-update.patch
Patch166: 0002-Mark-environmet-blocks-as-used-for-image-embedding.patch
Patch167: grub2-increase-crypttab-path-buffer.patch
Patch168: 0001-grub2-Set-multiple-device-path-for-a-nvmf-boot-devic.patch
Patch169: 0001-grub2-Can-t-setup-a-default-boot-device-correctly-on.patch
Patch170: 0001-tpm2-Support-authorized-policy.patch
Patch171: 0001-tpm2-Add-extra-RSA-SRK-types.patch
Patch174: 0001-clean-up-crypttab-and-linux-modules-dependency.patch
@ -406,7 +404,48 @@ Patch215: 0008-blscfg-reading-bls-fragments-if-boot-present.patch
Patch216: 0009-10_linux-Some-refinement-for-BLS.patch
Patch217: 0001-net-drivers-ieee1275-ofnet-Remove-200-ms-timeout-in-.patch
Patch218: grub2-s390x-set-hostonly.patch
Patch219: 0001-bli-Fix-crash-in-get_part_uuid.patch
Patch220: 0001-Streamline-BLS-and-improve-PCR-stability.patch
Patch221: 0001-fix-grub-screen-filled-with-post-screen-artifects.patch
Patch222: 0001-efinet-Skip-virtual-VLAN-devices-during-card-enumera.patch
Patch223: 0001-tpm-Skip-loopback-image-measurement.patch
Patch224: 0001-ieee1275-Platform-Keystore-PKS-Support.patch
Patch225: 0002-ieee1275-Read-the-DB-and-DBX-secure-boot-variables.patch
Patch226: 0003-appendedsig-The-creation-of-trusted-and-distrusted-l.patch
Patch227: 0004-appendedsig-While-verifying-the-kernel-use-trusted-a.patch
Patch228: 0005-appendedsig-The-grub-command-s-trusted-and-distruste.patch
Patch229: 0006-appendedsig-documentation.patch
Patch230: 0007-mkimage-create-new-ELF-Note-for-SBAT.patch
Patch231: 0008-mkimage-adding-sbat-data-into-sbat-ELF-Note-on-power.patch
Patch232: 0001-ieee1275-support-added-for-multiple-nvme-bootpaths.patch
Patch233: 0001-kern-ieee1275-init-Add-IEEE-1275-Radix-support-for-K.patch
%if 0%{?suse_version} > 1600
# Always requires a default cpu-platform package
Requires: grub2-%{grubarch} = %{version}-%{release}
%else
%if ! 0%{?only_efi:1}
Requires: grub2-%{grubarch} = %{version}-%{release}
%endif
%endif
%if 0%{?only_x86_64:1}
ExclusiveArch: x86_64
%else
ExclusiveArch: %{ix86} x86_64 ppc ppc64 ppc64le s390x aarch64 %{arm} riscv64
%endif
%description
This is the second version of the GRUB (Grand Unified Bootloader), a
highly configurable and customizable bootloader with modular
architecture. It support rich scale of kernel formats, file systems,
computer architectures and hardware devices.
%if 0%{?suse_version} > 1600
%package common
Summary: Utilies to manage grub
Group: System/Boot
%endif
Requires: gettext-runtime
%if 0%{?suse_version} >= 1140
%ifnarch s390x
@ -417,9 +456,6 @@ Recommends: os-prober
Suggests: libburnia-tools
Suggests: mtools
%endif
%if ! 0%{?only_efi:1}
Requires: grub2-%{grubarch} = %{version}-%{release}
%endif
%ifarch s390x
# required utilities by grub2-s390x-04-grub2-install.patch
# use 'showconsole' to determine console device. (bnc#876743)
@ -436,25 +472,21 @@ Requires: powerpc-utils
Recommends: memtest86+
%endif
%if 0%{?only_x86_64:1}
ExclusiveArch: x86_64
%else
ExclusiveArch: %{ix86} x86_64 ppc ppc64 ppc64le s390x aarch64 %{arm} riscv64
%endif
%description
This is the second version of the GRUB (Grand Unified Bootloader), a
highly configurable and customizable bootloader with modular
architecture. It support rich scale of kernel formats, file systems,
computer architectures and hardware devices.
%if 0%{?suse_version} > 1600
%description common
This package includes user space utlities to manage GRUB on your system.
%endif
%package branding-upstream
Summary: Upstream branding for GRUB2's graphical console
Group: System/Fhs
BuildArch: noarch
%if 0%{?suse_version} > 1600
Requires: %{name}-common = %{version}
%else
Requires: %{name} = %{version}
%endif
%description branding-upstream
Upstream branding for GRUB2's graphical console
@ -467,8 +499,13 @@ Group: System/Boot
%if "%{platform}" != "emu"
BuildArch: noarch
%endif
%if 0%{?suse_version} > 1600
Requires: %{name}-common = %{version}
Requires(post): %{name}-common = %{version}
%else
Requires: %{name} = %{version}
Requires(post): %{name} = %{version}
%endif
%{?update_bootloader_requires}
%description %{grubarch}
@ -516,8 +553,13 @@ BuildArch: noarch
# Without it grub-install is broken so break the package as well if unavailable
Requires: efibootmgr
Requires(post): efibootmgr
%if 0%{?suse_version} > 1600
Requires: %{name}-common = %{version}
Requires(post): %{name}-common = %{version}
%else
Requires: %{name} = %{version}
Requires(post): %{name} = %{version}
%endif
%{?update_bootloader_requires}
%{?fde_tpm_update_requires}
Provides: %{name}-efi = %{version}-%{release}
@ -529,6 +571,16 @@ bootloader with modular architecture. It supports rich variety of kernel format
file systems, computer architectures and hardware devices. This subpackage
provides support for EFI systems.
%if 0%{?suse_version} > 1600
%package %{grubefiarch}-bls
Summary: Image for Boot Loader Specification (BLS) support on %{grubefiarch}
Group: System/Boot
BuildArch: noarch
%description %{grubefiarch}-bls
Custom EFI build tailored for Boot Loader Specification (BLS) support.
%endif
%package %{grubefiarch}-extras
Summary: Unsupported modules for %{grubefiarch}
@ -592,9 +644,14 @@ Unsupported modules for %{name}-%{grubxenarch}
Summary: Grub2's snapper plugin
Group: System/Fhs
Requires: %{name} = %{version}
Requires: libxml2-tools
%if 0%{?suse_version} > 1600
Requires: (grub2 or grub2-common)
Supplements: ((grub2 or grub2-common) and snapper)
%else
Requires: %{name} = %{version}
Supplements: packageand(snapper:grub2)
%endif
BuildArch: noarch
%description snapper-plugin
@ -605,9 +662,14 @@ Grub2's snapper plugin for advanced btrfs snapshot boot menu management
Summary: Grub2's systemd-sleep plugin
Group: System/Fhs
Requires: grub2
Requires: util-linux
%if 0%{?suse_version} > 1600
Requires: (grub2 or grub2-common)
Supplements: ((grub2 or grub2-common) and systemd)
%else
Requires: grub2
Supplements: packageand(systemd:grub2)
%endif
BuildArch: noarch
%description systemd-sleep-plugin
@ -756,6 +818,59 @@ mksquashfs ./fonts memdisk.sqsh -keep-as-directory -comp xz -quiet -no-progress
./grub-mkimage -O %{grubefiarch} -o grub.efi --memdisk=./memdisk.sqsh --prefix= %{?sbat_generation:--sbat sbat.csv} \
-d grub-core ${GRUB_MODULES}
%if 0%{?suse_version} > 1600
rm memdisk.sqsh
# Building grubbls.efi
# FIXME: error out if theme_vendor missing
theme_vendor=$(find %{_datadir}/%{name}/themes -type f -name activate-theme -exec dirname {} \; -quit)
theme_vendor=${theme_vendor##*/}
# [ -n "$theme_vendor" ] || { echo "ERROR: no grub2 theme vendor found, missing branding package ??"; exit 1 }
mkdir -p ./boot/grub
cp -rf "%{_datadir}/%{name}/themes/$theme_vendor" ./boot/grub/themes
rm -f "./boot/grub/themes/activate-theme"
cat > ./grubbls.cfg <<'EOF'
regexp --set 1:root '\((.*)\)' "$cmdpath"
set timeout=8
set gfxmode=auto
set gfxpayload=keep
set enable_blscfg=1
terminal_input console
terminal_output console
terminal_output --append gfxterm
loadfont (memdisk)/boot/grub/themes/DejaVuSans-Bold14.pf2
loadfont (memdisk)/boot/grub/themes/DejaVuSans10.pf2
loadfont (memdisk)/boot/grub/themes/DejaVuSans12.pf2
loadfont (memdisk)/boot/grub/themes/ascii.pf2
set theme=(memdisk)/boot/grub/themes/theme.txt
export theme
EOF
%if 0%{?suse_version} > 1500
tar --sort=name -cf - ./boot | mksquashfs - memdisk.sqsh -tar -comp xz -quiet -no-progress
%else
mksquashfs ./boot memdisk.sqsh -keep-as-directory -comp xz -quiet -no-progress
%endif
./grub-mkimage -O %{grubefiarch} \
-o grubbls.efi \
--memdisk=./memdisk.sqsh \
-c ./grubbls.cfg \
%{?sbat_generation:--sbat sbat.csv} \
-d grub-core \
all_video boot font gfxmenu gfxterm gzio halt jpeg minicmd normal part_gpt png reboot video \
fat tpm tpm2 memdisk tar squash4 xzio blscfg linux bli regexp loadenv test echo true sleep
%endif
%ifarch x86_64 aarch64
if test -e %{_sourcedir}/_projectcert.crt ; then
prjsubject=$(openssl x509 -in %{_sourcedir}/_projectcert.crt -noout -subject_hash)
@ -786,6 +901,14 @@ cd ..
%if ! 0%{?only_efi:1}
cd build
%ifarch ppc ppc64 ppc64le
%if 0%{?sbat_generation}
echo "sbat,1,SBAT Version,sbat,1,https://github.com/rhboot/shim/blob/main/SBAT.md" > sbat.csv
echo "grub,%{sbat_generation_grub},Free Software Foundation,grub,%{version},https://www.gnu.org/software/grub/" >> sbat.csv
echo "grub.%{sbat_distro},%{sbat_generation},%{sbat_distro_summary},%{name},%{version},%{sbat_distro_url}" >> sbat.csv
%endif
%endif
%if "%{platform}" != "emu"
%define arch_specific --enable-device-mapper
TLFLAGS="-static"
@ -915,7 +1038,7 @@ fi
EOF
%{__tar} cvf memdisk.tar ./grub.cfg
./grub-mkimage -O %{grubarch} -o grub.elf -d grub-core -x grub.der -m memdisk.tar \
-c %{platform}-config --appended-signature-size %brp_pesign_reservation ${GRUB_MODULES}
-c %{platform}-config -s sbat.csv --appended-signature-size %brp_pesign_reservation ${GRUB_MODULES}
ls -l "grub.elf"
truncate -s -%brp_pesign_reservation "grub.elf"
fi
@ -947,6 +1070,9 @@ install -m 644 grub.efi %{buildroot}/%{_datadir}/%{name}/%{grubefiarch}/.
%ifarch x86_64
ln -srf %{buildroot}/%{_datadir}/%{name}/%{grubefiarch}/grub.efi %{buildroot}/%{_datadir}/%{name}/%{grubefiarch}/grub-tpm.efi
%endif
%if 0%{?suse_version} > 1600
install -m 644 grubbls.efi %{buildroot}/%{_datadir}/%{name}/%{grubefiarch}/.
%endif
# Create grub.efi link to system efi directory
# This is for tools like kiwi not fiddling with the path
@ -968,7 +1094,11 @@ EoM
%endif
%ifarch x86_64 aarch64
%if 0%{?suse_version} > 1600
export BRP_PESIGN_FILES="%{_datadir}/%{name}/%{grubefiarch}/grub.efi %{_datadir}/%{name}/%{grubefiarch}/grubbls.efi"
%else
export BRP_PESIGN_FILES="%{_datadir}/%{name}/%{grubefiarch}/grub.efi"
%endif
install -m 444 grub.der %{buildroot}/%{sysefidir}/
%endif
@ -1101,10 +1231,20 @@ grep -E ${EXTRA_PATTERN} %{grubarch}-mod-all.lst > %{grubarch}-mod-extras.lst
%fdupes %buildroot%{_libdir}
%fdupes %buildroot%{_datadir}
%if 0%{?suse_version} > 1600
%pre common
%else
%pre
%endif
%service_add_pre grub2-once.service
%if 0%{?suse_version} > 1600
%post common
%else
%post
%endif
%service_add_post grub2-once.service
%if ! 0%{?only_efi:1}
@ -1132,19 +1272,29 @@ grep -E ${EXTRA_PATTERN} %{grubarch}-mod-all.lst > %{grubarch}-mod-extras.lst
%endif
%if 0%{?suse_version} > 1600
%preun common
%else
%preun
%endif
%service_del_preun grub2-once.service
%if 0%{?suse_version} > 1600
%postun common
%else
%postun
%endif
%service_del_postun grub2-once.service
%files -f %{name}.lang
%defattr(-,root,root,-)
%if 0%{?suse_version} < 1500
%doc COPYING
%if 0%{?suse_version} > 1600
%files
%else
%license COPYING
%files -f %{name}.lang
%endif
%defattr(-,root,root,-)
%doc AUTHORS
%doc NEWS README
%doc THANKS TODO ChangeLog
@ -1152,6 +1302,16 @@ grep -E ${EXTRA_PATTERN} %{grubarch}-mod-all.lst > %{grubarch}-mod-extras.lst
%ifarch s390x
%doc README.ibm3215
%endif
%if 0%{?suse_version} > 1600
%files common -f %{name}.lang
%defattr(-,root,root,-)
%endif
%if 0%{?suse_version} < 1500
%doc COPYING
%else
%license COPYING
%endif
%dir /boot/%{name}
%ghost %attr(600, root, root) /boot/%{name}/grub.cfg
%{_datadir}/bash-completion/completions/grub*
@ -1162,7 +1322,14 @@ grep -E ${EXTRA_PATTERN} %{grubarch}-mod-all.lst > %{grubarch}-mod-extras.lst
%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/25_bli
# The bli.mod is enabled in grubbls.efi, which will mostly adhere to systemd
# standards. But it is not the case for grub.efi, as it serves no purpose
# there, among other considerations. Therefore, the 25_bli script that loads
# bli.mod as an external module should be disabled (by stripping off its
# executable bit) to prevent showing 'file not found' error. This is because
# grub.efi may intentionally lack access to external modules, as it is designed
# to be a drop-in file, requires no external dependency (boo#1231591)
%attr(0644, root, root) %config(noreplace) %{_sysconfdir}/grub.d/25_bli
%config(noreplace) %{_sysconfdir}/grub.d/30_uefi-firmware
%config(noreplace) %{_sysconfdir}/grub.d/40_custom
%config(noreplace) %{_sysconfdir}/grub.d/41_custom
@ -1333,6 +1500,12 @@ grep -E ${EXTRA_PATTERN} %{grubarch}-mod-all.lst > %{grubarch}-mod-extras.lst
%{sysefidir}/grub.der
%endif
%if 0%{?suse_version} > 1600
%files %{grubefiarch}-bls
%defattr(-,root,root,-)
%{_datadir}/%{name}/%{grubefiarch}/grubbls.efi
%endif
%files %{grubefiarch}-extras -f %{grubefiarch}-mod-extras.lst
%defattr(-,root,root,-)
%dir %{_datadir}/%{name}/%{grubefiarch}