Accepting request 1217306 from Base:System

OBS-URL: https://build.opensuse.org/request/show/1217306
OBS-URL: https://build.opensuse.org/package/show/openSUSE:Factory/grub2?expand=0&rev=337
This commit is contained in:
Ana Guerrero 2024-10-23 19:08:03 +00:00 committed by Git OBS Bridge
commit ab2369bc04
14 changed files with 3403 additions and 216 deletions

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,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

@ -22,17 +22,23 @@ minix.
[1] https://savannah.gnu.org/bugs/index.php?57652 [1] https://savannah.gnu.org/bugs/index.php?57652
[2] https://bugzilla.opensuse.org/attachment.cgi?id=828118 [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 --- a/Makefile.am
+++ b/Makefile.am +++ b/Makefile.am
@@ -51,8 +51,11 @@ @@ -51,8 +51,12 @@
-D'GRUB_MOD_INIT(x)=@MARKER@x@' $^ > $@ || (rm -f $@; exit 1) -D'GRUB_MOD_INIT(x)=@MARKER@x@' $^ > $@ || (rm -f $@; exit 1)
CLEANFILES += libgrub.pp 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://savannah.gnu.org/bugs/?57652
+# see https://bugzilla.suse.com/show_bug.cgi?id=1231604
libgrub_a_init.lst: libgrub.pp libgrub_a_init.lst: libgrub.pp
cat $< | grep '^@MARKER@' | sed 's/@MARKER@\(.*\)@/\1/g' | sort -u > $@ || (rm -f $@; exit 1) 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 CLEANFILES += libgrub_a_init.lst
libgrub_a_init.c: libgrub_a_init.lst $(top_srcdir)/geninit.sh libgrub_a_init.c: libgrub_a_init.lst $(top_srcdir)/geninit.sh

View File

@ -1,3 +1,39 @@
-------------------------------------------------------------------
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> Fri Oct 4 06:58:06 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 Patch165: 0004-ofpath-controller-name-update.patch
Patch166: 0002-Mark-environmet-blocks-as-used-for-image-embedding.patch Patch166: 0002-Mark-environmet-blocks-as-used-for-image-embedding.patch
Patch167: grub2-increase-crypttab-path-buffer.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 Patch170: 0001-tpm2-Support-authorized-policy.patch
Patch171: 0001-tpm2-Add-extra-RSA-SRK-types.patch Patch171: 0001-tpm2-Add-extra-RSA-SRK-types.patch
Patch174: 0001-clean-up-crypttab-and-linux-modules-dependency.patch Patch174: 0001-clean-up-crypttab-and-linux-modules-dependency.patch
@ -411,9 +409,24 @@ Patch220: 0001-Streamline-BLS-and-improve-PCR-stability.patch
Patch221: 0001-fix-grub-screen-filled-with-post-screen-artifects.patch Patch221: 0001-fix-grub-screen-filled-with-post-screen-artifects.patch
Patch222: 0001-efinet-Skip-virtual-VLAN-devices-during-card-enumera.patch Patch222: 0001-efinet-Skip-virtual-VLAN-devices-during-card-enumera.patch
Patch223: 0001-tpm-Skip-loopback-image-measurement.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
%if 0%{?suse_version} > 1600
# Always requires a default cpu-platform package # Always requires a default cpu-platform package
Requires: grub2-%{grubarch} = %{version}-%{release} Requires: grub2-%{grubarch} = %{version}-%{release}
%else
%if ! 0%{?only_efi:1}
Requires: grub2-%{grubarch} = %{version}-%{release}
%endif
%endif
%if 0%{?only_x86_64:1} %if 0%{?only_x86_64:1}
ExclusiveArch: x86_64 ExclusiveArch: x86_64
@ -427,9 +440,11 @@ highly configurable and customizable bootloader with modular
architecture. It support rich scale of kernel formats, file systems, architecture. It support rich scale of kernel formats, file systems,
computer architectures and hardware devices. computer architectures and hardware devices.
%if 0%{?suse_version} > 1600
%package common %package common
Summary: Utilies to manage grub Summary: Utilies to manage grub
Group: System/Boot Group: System/Boot
%endif
Requires: gettext-runtime Requires: gettext-runtime
%if 0%{?suse_version} >= 1140 %if 0%{?suse_version} >= 1140
%ifnarch s390x %ifnarch s390x
@ -456,15 +471,21 @@ Requires: powerpc-utils
Recommends: memtest86+ Recommends: memtest86+
%endif %endif
%if 0%{?suse_version} > 1600
%description common %description common
This package includes user space utlities to manage GRUB on your system. This package includes user space utlities to manage GRUB on your system.
%endif
%package branding-upstream %package branding-upstream
Summary: Upstream branding for GRUB2's graphical console Summary: Upstream branding for GRUB2's graphical console
Group: System/Fhs Group: System/Fhs
BuildArch: noarch BuildArch: noarch
%if 0%{?suse_version} > 1600
Requires: %{name}-common = %{version} Requires: %{name}-common = %{version}
%else
Requires: %{name} = %{version}
%endif
%description branding-upstream %description branding-upstream
Upstream branding for GRUB2's graphical console Upstream branding for GRUB2's graphical console
@ -477,8 +498,13 @@ Group: System/Boot
%if "%{platform}" != "emu" %if "%{platform}" != "emu"
BuildArch: noarch BuildArch: noarch
%endif %endif
%if 0%{?suse_version} > 1600
Requires: %{name}-common = %{version} Requires: %{name}-common = %{version}
Requires(post): %{name}-common = %{version} Requires(post): %{name}-common = %{version}
%else
Requires: %{name} = %{version}
Requires(post): %{name} = %{version}
%endif
%{?update_bootloader_requires} %{?update_bootloader_requires}
%description %{grubarch} %description %{grubarch}
@ -526,8 +552,13 @@ BuildArch: noarch
# Without it grub-install is broken so break the package as well if unavailable # Without it grub-install is broken so break the package as well if unavailable
Requires: efibootmgr Requires: efibootmgr
Requires(post): efibootmgr Requires(post): efibootmgr
%if 0%{?suse_version} > 1600
Requires: %{name}-common = %{version} Requires: %{name}-common = %{version}
Requires(post): %{name}-common = %{version} Requires(post): %{name}-common = %{version}
%else
Requires: %{name} = %{version}
Requires(post): %{name} = %{version}
%endif
%{?update_bootloader_requires} %{?update_bootloader_requires}
%{?fde_tpm_update_requires} %{?fde_tpm_update_requires}
Provides: %{name}-efi = %{version}-%{release} Provides: %{name}-efi = %{version}-%{release}
@ -539,6 +570,7 @@ bootloader with modular architecture. It supports rich variety of kernel format
file systems, computer architectures and hardware devices. This subpackage file systems, computer architectures and hardware devices. This subpackage
provides support for EFI systems. provides support for EFI systems.
%if 0%{?suse_version} > 1600
%package %{grubefiarch}-bls %package %{grubefiarch}-bls
Summary: Image for Boot Loader Specification (BLS) support on %{grubefiarch} Summary: Image for Boot Loader Specification (BLS) support on %{grubefiarch}
Group: System/Boot Group: System/Boot
@ -546,6 +578,7 @@ BuildArch: noarch
%description %{grubefiarch}-bls %description %{grubefiarch}-bls
Custom EFI build tailored for Boot Loader Specification (BLS) support. Custom EFI build tailored for Boot Loader Specification (BLS) support.
%endif
%package %{grubefiarch}-extras %package %{grubefiarch}-extras
@ -611,8 +644,13 @@ Unsupported modules for %{name}-%{grubxenarch}
Summary: Grub2's snapper plugin Summary: Grub2's snapper plugin
Group: System/Fhs Group: System/Fhs
Requires: libxml2-tools Requires: libxml2-tools
%if 0%{?suse_version} > 1600
Requires: (grub2 or grub2-common) Requires: (grub2 or grub2-common)
Supplements: ((grub2 or grub2-common) and snapper) Supplements: ((grub2 or grub2-common) and snapper)
%else
Requires: %{name} = %{version}
Supplements: packageand(snapper:grub2)
%endif
BuildArch: noarch BuildArch: noarch
%description snapper-plugin %description snapper-plugin
@ -624,8 +662,13 @@ Grub2's snapper plugin for advanced btrfs snapshot boot menu management
Summary: Grub2's systemd-sleep plugin Summary: Grub2's systemd-sleep plugin
Group: System/Fhs Group: System/Fhs
Requires: util-linux Requires: util-linux
%if 0%{?suse_version} > 1600
Requires: (grub2 or grub2-common) Requires: (grub2 or grub2-common)
Supplements: ((grub2 or grub2-common) and systemd) Supplements: ((grub2 or grub2-common) and systemd)
%else
Requires: grub2
Supplements: packageand(systemd:grub2)
%endif
BuildArch: noarch BuildArch: noarch
%description systemd-sleep-plugin %description systemd-sleep-plugin
@ -774,6 +817,7 @@ 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} \ ./grub-mkimage -O %{grubefiarch} -o grub.efi --memdisk=./memdisk.sqsh --prefix= %{?sbat_generation:--sbat sbat.csv} \
-d grub-core ${GRUB_MODULES} -d grub-core ${GRUB_MODULES}
%if 0%{?suse_version} > 1600
rm memdisk.sqsh rm memdisk.sqsh
# Building grubbls.efi # Building grubbls.efi
@ -824,6 +868,7 @@ mksquashfs ./boot memdisk.sqsh -keep-as-directory -comp xz -quiet -no-progress
-d grub-core \ -d grub-core \
all_video boot font gfxmenu gfxterm gzio halt jpeg minicmd normal part_gpt png reboot video \ 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 fat tpm tpm2 memdisk tar squash4 xzio blscfg linux bli regexp loadenv test echo true sleep
%endif
%ifarch x86_64 aarch64 %ifarch x86_64 aarch64
if test -e %{_sourcedir}/_projectcert.crt ; then if test -e %{_sourcedir}/_projectcert.crt ; then
@ -855,6 +900,14 @@ cd ..
%if ! 0%{?only_efi:1} %if ! 0%{?only_efi:1}
cd build 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" %if "%{platform}" != "emu"
%define arch_specific --enable-device-mapper %define arch_specific --enable-device-mapper
TLFLAGS="-static" TLFLAGS="-static"
@ -984,7 +1037,7 @@ fi
EOF EOF
%{__tar} cvf memdisk.tar ./grub.cfg %{__tar} cvf memdisk.tar ./grub.cfg
./grub-mkimage -O %{grubarch} -o grub.elf -d grub-core -x grub.der -m memdisk.tar \ ./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" ls -l "grub.elf"
truncate -s -%brp_pesign_reservation "grub.elf" truncate -s -%brp_pesign_reservation "grub.elf"
fi fi
@ -1016,7 +1069,9 @@ install -m 644 grub.efi %{buildroot}/%{_datadir}/%{name}/%{grubefiarch}/.
%ifarch x86_64 %ifarch x86_64
ln -srf %{buildroot}/%{_datadir}/%{name}/%{grubefiarch}/grub.efi %{buildroot}/%{_datadir}/%{name}/%{grubefiarch}/grub-tpm.efi ln -srf %{buildroot}/%{_datadir}/%{name}/%{grubefiarch}/grub.efi %{buildroot}/%{_datadir}/%{name}/%{grubefiarch}/grub-tpm.efi
%endif %endif
%if 0%{?suse_version} > 1600
install -m 644 grubbls.efi %{buildroot}/%{_datadir}/%{name}/%{grubefiarch}/. install -m 644 grubbls.efi %{buildroot}/%{_datadir}/%{name}/%{grubefiarch}/.
%endif
# Create grub.efi link to system efi directory # Create grub.efi link to system efi directory
# This is for tools like kiwi not fiddling with the path # This is for tools like kiwi not fiddling with the path
@ -1038,7 +1093,11 @@ EoM
%endif %endif
%ifarch x86_64 aarch64 %ifarch x86_64 aarch64
%if 0%{?suse_version} > 1600
export BRP_PESIGN_FILES="%{_datadir}/%{name}/%{grubefiarch}/grub.efi %{_datadir}/%{name}/%{grubefiarch}/grubbls.efi" 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}/ install -m 444 grub.der %{buildroot}/%{sysefidir}/
%endif %endif
@ -1171,10 +1230,20 @@ grep -E ${EXTRA_PATTERN} %{grubarch}-mod-all.lst > %{grubarch}-mod-extras.lst
%fdupes %buildroot%{_libdir} %fdupes %buildroot%{_libdir}
%fdupes %buildroot%{_datadir} %fdupes %buildroot%{_datadir}
%if 0%{?suse_version} > 1600
%pre common %pre common
%else
%pre
%endif
%service_add_pre grub2-once.service %service_add_pre grub2-once.service
%if 0%{?suse_version} > 1600
%post common %post common
%else
%post
%endif
%service_add_post grub2-once.service %service_add_post grub2-once.service
%if ! 0%{?only_efi:1} %if ! 0%{?only_efi:1}
@ -1202,13 +1271,28 @@ grep -E ${EXTRA_PATTERN} %{grubarch}-mod-all.lst > %{grubarch}-mod-extras.lst
%endif %endif
%if 0%{?suse_version} > 1600
%preun common %preun common
%else
%preun
%endif
%service_del_preun grub2-once.service %service_del_preun grub2-once.service
%if 0%{?suse_version} > 1600
%postun common %postun common
%else
%postun
%endif
%service_del_postun grub2-once.service %service_del_postun grub2-once.service
%if 0%{?suse_version} > 1600
%files %files
%else
%files -f %{name}.lang
%endif
%defattr(-,root,root,-) %defattr(-,root,root,-)
%doc AUTHORS %doc AUTHORS
%doc NEWS README %doc NEWS README
@ -1218,13 +1302,15 @@ grep -E ${EXTRA_PATTERN} %{grubarch}-mod-all.lst > %{grubarch}-mod-extras.lst
%doc README.ibm3215 %doc README.ibm3215
%endif %endif
%if 0%{?suse_version} > 1600
%files common -f %{name}.lang %files common -f %{name}.lang
%defattr(-,root,root,-)
%endif
%if 0%{?suse_version} < 1500 %if 0%{?suse_version} < 1500
%doc COPYING %doc COPYING
%else %else
%license COPYING %license COPYING
%endif %endif
%defattr(-,root,root,-)
%dir /boot/%{name} %dir /boot/%{name}
%ghost %attr(600, root, root) /boot/%{name}/grub.cfg %ghost %attr(600, root, root) /boot/%{name}/grub.cfg
%{_datadir}/bash-completion/completions/grub* %{_datadir}/bash-completion/completions/grub*
@ -1235,7 +1321,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/05_crypttab
%config(noreplace) %{_sysconfdir}/grub.d/10_linux %config(noreplace) %{_sysconfdir}/grub.d/10_linux
%config(noreplace) %{_sysconfdir}/grub.d/20_linux_xen %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/30_uefi-firmware
%config(noreplace) %{_sysconfdir}/grub.d/40_custom %config(noreplace) %{_sysconfdir}/grub.d/40_custom
%config(noreplace) %{_sysconfdir}/grub.d/41_custom %config(noreplace) %{_sysconfdir}/grub.d/41_custom
@ -1406,9 +1499,11 @@ grep -E ${EXTRA_PATTERN} %{grubarch}-mod-all.lst > %{grubarch}-mod-extras.lst
%{sysefidir}/grub.der %{sysefidir}/grub.der
%endif %endif
%if 0%{?suse_version} > 1600
%files %{grubefiarch}-bls %files %{grubefiarch}-bls
%defattr(-,root,root,-) %defattr(-,root,root,-)
%{_datadir}/%{name}/%{grubefiarch}/grubbls.efi %{_datadir}/%{name}/%{grubefiarch}/grubbls.efi
%endif
%files %{grubefiarch}-extras -f %{grubefiarch}-mod-extras.lst %files %{grubefiarch}-extras -f %{grubefiarch}-mod-extras.lst
%defattr(-,root,root,-) %defattr(-,root,root,-)