diff --git a/0001-grub2-Can-t-setup-a-default-boot-device-correctly-on.patch b/0001-grub2-Can-t-setup-a-default-boot-device-correctly-on.patch deleted file mode 100644 index 7f40e4a..0000000 --- a/0001-grub2-Can-t-setup-a-default-boot-device-correctly-on.patch +++ /dev/null @@ -1,44 +0,0 @@ -From a59b58f6ae327a8f6949991cb5531db01e1ba14d Mon Sep 17 00:00:00 2001 -From: Wen Xiong -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 ---- - 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 - diff --git a/0001-grub2-Set-multiple-device-path-for-a-nvmf-boot-devic.patch b/0001-grub2-Set-multiple-device-path-for-a-nvmf-boot-devic.patch deleted file mode 100644 index 46f096a..0000000 --- a/0001-grub2-Set-multiple-device-path-for-a-nvmf-boot-devic.patch +++ /dev/null @@ -1,164 +0,0 @@ -From 3e77c5494fd06f430588ae9c304fea370439d531 Mon Sep 17 00:00:00 2001 -From: 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 ---- - 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 - - #include -+#include - #include - #include - #include -@@ -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 */ diff --git a/0001-ieee1275-Platform-Keystore-PKS-Support.patch b/0001-ieee1275-Platform-Keystore-PKS-Support.patch new file mode 100644 index 0000000..2d72035 --- /dev/null +++ b/0001-ieee1275-Platform-Keystore-PKS-Support.patch @@ -0,0 +1,171 @@ +From 04e8509f04a4cd123bc9f290e60f582d57b2f258 Mon Sep 17 00:00:00 2001 +From: Sudhakar Kuppusamy +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 +Reviewed-by: Stefan Berger +Tested-by: Nageswara Sastry +--- + 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 + diff --git a/0001-ieee1275-support-added-for-multiple-nvme-bootpaths.patch b/0001-ieee1275-support-added-for-multiple-nvme-bootpaths.patch new file mode 100644 index 0000000..18d0d5a --- /dev/null +++ b/0001-ieee1275-support-added-for-multiple-nvme-bootpaths.patch @@ -0,0 +1,170 @@ +From 219b06c69d38a10349183002efb82bfec3b7ff5b Mon Sep 17 00:00:00 2001 +From: Avnish Chouhan +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 +--- + 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 + #include + #include ++#include ++#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 + diff --git a/0002-ieee1275-Read-the-DB-and-DBX-secure-boot-variables.patch b/0002-ieee1275-Read-the-DB-and-DBX-secure-boot-variables.patch new file mode 100644 index 0000000..be6ecd8 --- /dev/null +++ b/0002-ieee1275-Read-the-DB-and-DBX-secure-boot-variables.patch @@ -0,0 +1,671 @@ +From 8ef821ea18ed35f5969b98f2df6a76fefb71b175 Mon Sep 17 00:00:00 2001 +From: Sudhakar Kuppusamy +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 +Reviewed-by: Stefan Berger +Tested-by: Nageswara Sastry +--- + 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 + #endif + #include ++#include + + /* 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 ++#include ++#include ++#include ++#include ++#include ++ ++#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 ++#include ++#include ++ ++#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 + diff --git a/0003-appendedsig-The-creation-of-trusted-and-distrusted-l.patch b/0003-appendedsig-The-creation-of-trusted-and-distrusted-l.patch new file mode 100644 index 0000000..34de6b8 --- /dev/null +++ b/0003-appendedsig-The-creation-of-trusted-and-distrusted-l.patch @@ -0,0 +1,831 @@ +From 350e8d823db1febc2c81635115ef3c4c0f41f3e7 Mon Sep 17 00:00:00 2001 +From: Sudhakar Kuppusamy +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 +Reviewed-by: Stefan Berger +Tested-by: Nageswara Sastry +--- + 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 + #include + #include +- ++#include + #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 + diff --git a/0004-appendedsig-While-verifying-the-kernel-use-trusted-a.patch b/0004-appendedsig-While-verifying-the-kernel-use-trusted-a.patch new file mode 100644 index 0000000..66c8b49 --- /dev/null +++ b/0004-appendedsig-While-verifying-the-kernel-use-trusted-a.patch @@ -0,0 +1,253 @@ +From 5bff27911bb6575b80b5decf5364b7e6bde801d3 Mon Sep 17 00:00:00 2001 +From: Sudhakar Kuppusamy +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 +Reviewed-by: Stefan Berger +Tested-by: Nageswara Sastry +--- + 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 + #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 + diff --git a/0005-appendedsig-The-grub-command-s-trusted-and-distruste.patch b/0005-appendedsig-The-grub-command-s-trusted-and-distruste.patch new file mode 100644 index 0000000..98682bd --- /dev/null +++ b/0005-appendedsig-The-grub-command-s-trusted-and-distruste.patch @@ -0,0 +1,684 @@ +From f05acf089fb80fc44112a7feec3529af494a41f7 Mon Sep 17 00:00:00 2001 +From: Sudhakar Kuppusamy +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 +Reviewed-by: Stefan Berger +Tested-by: Nageswara Sastry +--- + 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 \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 \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 \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 \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] \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 + diff --git a/0006-appendedsig-documentation.patch b/0006-appendedsig-documentation.patch new file mode 100644 index 0000000..4a2837d --- /dev/null +++ b/0006-appendedsig-documentation.patch @@ -0,0 +1,223 @@ +From 87831c6ce3536e5e2eeb3e2cd8a6184b9509ee04 Mon Sep 17 00:00:00 2001 +From: Sudhakar Kuppusamy +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 +Reviewed-by: Stefan Berger +--- + 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 + diff --git a/0007-mkimage-create-new-ELF-Note-for-SBAT.patch b/0007-mkimage-create-new-ELF-Note-for-SBAT.patch new file mode 100644 index 0000000..a161a77 --- /dev/null +++ b/0007-mkimage-create-new-ELF-Note-for-SBAT.patch @@ -0,0 +1,189 @@ +From 77316f09f133e9c7c5e1026b2b4f5749daac644a Mon Sep 17 00:00:00 2001 +From: Sudhakar Kuppusamy +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 +Co-authored-by: Daniel Axtens +--- + 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 + diff --git a/0008-mkimage-adding-sbat-data-into-sbat-ELF-Note-on-power.patch b/0008-mkimage-adding-sbat-data-into-sbat-ELF-Note-on-power.patch new file mode 100644 index 0000000..106fc16 --- /dev/null +++ b/0008-mkimage-adding-sbat-data-into-sbat-ELF-Note-on-power.patch @@ -0,0 +1,66 @@ +From 32d4823762e5a0e7f8bfc5a878d39e1a019392fe Mon Sep 17 00:00:00 2001 +From: Sudhakar Kuppusamy +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 +Co-authored-by: Daniel Axtens +--- + 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 + diff --git a/grub2-install-fix-not-a-directory-error.patch b/grub2-install-fix-not-a-directory-error.patch index d4ed8f1..63c7800 100644 --- a/grub2-install-fix-not-a-directory-error.patch +++ b/grub2-install-fix-not-a-directory-error.patch @@ -22,17 +22,23 @@ minix. [1] https://savannah.gnu.org/bugs/index.php?57652 [2] https://bugzilla.opensuse.org/attachment.cgi?id=828118 +v2: +We are still encountering the error. Instead of ensuring ext[234] is tried +before minix, make sure everything is tried before minix unless its detection +issue can be properly addressed. + --- a/Makefile.am +++ b/Makefile.am -@@ -51,8 +51,11 @@ +@@ -51,8 +51,12 @@ -D'GRUB_MOD_INIT(x)=@MARKER@x@' $^ > $@ || (rm -f $@; exit 1) CLEANFILES += libgrub.pp -+# the grep/sed ensures that ext2 gets initialized before minix* ++# the grep/sed ensures that every other file system gets tested before minix*" +# see https://savannah.gnu.org/bugs/?57652 ++# see https://bugzilla.suse.com/show_bug.cgi?id=1231604 libgrub_a_init.lst: libgrub.pp cat $< | grep '^@MARKER@' | sed 's/@MARKER@\(.*\)@/\1/g' | sort -u > $@ || (rm -f $@; exit 1) -+ if grep ^ext2 $@ >/dev/null; then sed '/ext2/d;/newc/iext2' < $@ > $@.tmp && mv $@.tmp $@; fi ++ if grep ^minix $@ >/dev/null; then sed -n '/^minix/p;/^minix/!H;$${x;s/^\n//;p}' < $@ > $@.tmp && mv $@.tmp $@; fi CLEANFILES += libgrub_a_init.lst libgrub_a_init.c: libgrub_a_init.lst $(top_srcdir)/geninit.sh diff --git a/grub2.changes b/grub2.changes index 5bde23a..78ddf6a 100644 --- a/grub2.changes +++ b/grub2.changes @@ -1,3 +1,39 @@ +------------------------------------------------------------------- +Wed Oct 23 06:17:54 UTC 2024 - Michael Chang + +- Fix error: /boot/grub2/x86_64-efi/bli.mod not found (bsc#1231591) + +------------------------------------------------------------------- +Tue Oct 22 07:34:04 UTC 2024 - Michael Chang + +- Keep grub packaging and dependencies in the SLE-12 and SLE-15 builds + +------------------------------------------------------------------- +Fri Oct 18 07:42:27 UTC 2024 - Michael Chang + +- 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 + +- 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 diff --git a/grub2.spec b/grub2.spec index 1af87a9..0240eee 100644 --- a/grub2.spec +++ b/grub2.spec @@ -356,8 +356,6 @@ Patch164: 0003-ieee1275-change-the-logic-of-ieee1275_get_devargs.patch Patch165: 0004-ofpath-controller-name-update.patch Patch166: 0002-Mark-environmet-blocks-as-used-for-image-embedding.patch Patch167: grub2-increase-crypttab-path-buffer.patch -Patch168: 0001-grub2-Set-multiple-device-path-for-a-nvmf-boot-devic.patch -Patch169: 0001-grub2-Can-t-setup-a-default-boot-device-correctly-on.patch Patch170: 0001-tpm2-Support-authorized-policy.patch Patch171: 0001-tpm2-Add-extra-RSA-SRK-types.patch Patch174: 0001-clean-up-crypttab-and-linux-modules-dependency.patch @@ -411,9 +409,24 @@ Patch220: 0001-Streamline-BLS-and-improve-PCR-stability.patch Patch221: 0001-fix-grub-screen-filled-with-post-screen-artifects.patch Patch222: 0001-efinet-Skip-virtual-VLAN-devices-during-card-enumera.patch Patch223: 0001-tpm-Skip-loopback-image-measurement.patch +Patch224: 0001-ieee1275-Platform-Keystore-PKS-Support.patch +Patch225: 0002-ieee1275-Read-the-DB-and-DBX-secure-boot-variables.patch +Patch226: 0003-appendedsig-The-creation-of-trusted-and-distrusted-l.patch +Patch227: 0004-appendedsig-While-verifying-the-kernel-use-trusted-a.patch +Patch228: 0005-appendedsig-The-grub-command-s-trusted-and-distruste.patch +Patch229: 0006-appendedsig-documentation.patch +Patch230: 0007-mkimage-create-new-ELF-Note-for-SBAT.patch +Patch231: 0008-mkimage-adding-sbat-data-into-sbat-ELF-Note-on-power.patch +Patch232: 0001-ieee1275-support-added-for-multiple-nvme-bootpaths.patch +%if 0%{?suse_version} > 1600 # Always requires a default cpu-platform package Requires: grub2-%{grubarch} = %{version}-%{release} +%else +%if ! 0%{?only_efi:1} +Requires: grub2-%{grubarch} = %{version}-%{release} +%endif +%endif %if 0%{?only_x86_64:1} ExclusiveArch: x86_64 @@ -427,9 +440,11 @@ highly configurable and customizable bootloader with modular architecture. It support rich scale of kernel formats, file systems, computer architectures and hardware devices. +%if 0%{?suse_version} > 1600 %package common Summary: Utilies to manage grub Group: System/Boot +%endif Requires: gettext-runtime %if 0%{?suse_version} >= 1140 %ifnarch s390x @@ -456,15 +471,21 @@ Requires: powerpc-utils Recommends: memtest86+ %endif +%if 0%{?suse_version} > 1600 %description common This package includes user space utlities to manage GRUB on your system. +%endif %package branding-upstream Summary: Upstream branding for GRUB2's graphical console Group: System/Fhs BuildArch: noarch +%if 0%{?suse_version} > 1600 Requires: %{name}-common = %{version} +%else +Requires: %{name} = %{version} +%endif %description branding-upstream Upstream branding for GRUB2's graphical console @@ -477,8 +498,13 @@ Group: System/Boot %if "%{platform}" != "emu" BuildArch: noarch %endif +%if 0%{?suse_version} > 1600 Requires: %{name}-common = %{version} Requires(post): %{name}-common = %{version} +%else +Requires: %{name} = %{version} +Requires(post): %{name} = %{version} +%endif %{?update_bootloader_requires} %description %{grubarch} @@ -526,8 +552,13 @@ BuildArch: noarch # Without it grub-install is broken so break the package as well if unavailable Requires: efibootmgr Requires(post): efibootmgr +%if 0%{?suse_version} > 1600 Requires: %{name}-common = %{version} Requires(post): %{name}-common = %{version} +%else +Requires: %{name} = %{version} +Requires(post): %{name} = %{version} +%endif %{?update_bootloader_requires} %{?fde_tpm_update_requires} Provides: %{name}-efi = %{version}-%{release} @@ -539,6 +570,7 @@ bootloader with modular architecture. It supports rich variety of kernel format file systems, computer architectures and hardware devices. This subpackage provides support for EFI systems. +%if 0%{?suse_version} > 1600 %package %{grubefiarch}-bls Summary: Image for Boot Loader Specification (BLS) support on %{grubefiarch} Group: System/Boot @@ -546,6 +578,7 @@ BuildArch: noarch %description %{grubefiarch}-bls Custom EFI build tailored for Boot Loader Specification (BLS) support. +%endif %package %{grubefiarch}-extras @@ -611,8 +644,13 @@ Unsupported modules for %{name}-%{grubxenarch} Summary: Grub2's snapper plugin Group: System/Fhs Requires: libxml2-tools +%if 0%{?suse_version} > 1600 Requires: (grub2 or grub2-common) Supplements: ((grub2 or grub2-common) and snapper) +%else +Requires: %{name} = %{version} +Supplements: packageand(snapper:grub2) +%endif BuildArch: noarch %description snapper-plugin @@ -624,8 +662,13 @@ Grub2's snapper plugin for advanced btrfs snapshot boot menu management Summary: Grub2's systemd-sleep plugin Group: System/Fhs Requires: util-linux +%if 0%{?suse_version} > 1600 Requires: (grub2 or grub2-common) Supplements: ((grub2 or grub2-common) and systemd) +%else +Requires: grub2 +Supplements: packageand(systemd:grub2) +%endif BuildArch: noarch %description systemd-sleep-plugin @@ -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} \ -d grub-core ${GRUB_MODULES} +%if 0%{?suse_version} > 1600 rm memdisk.sqsh # Building grubbls.efi @@ -824,6 +868,7 @@ mksquashfs ./boot memdisk.sqsh -keep-as-directory -comp xz -quiet -no-progress -d grub-core \ all_video boot font gfxmenu gfxterm gzio halt jpeg minicmd normal part_gpt png reboot video \ fat tpm tpm2 memdisk tar squash4 xzio blscfg linux bli regexp loadenv test echo true sleep +%endif %ifarch x86_64 aarch64 if test -e %{_sourcedir}/_projectcert.crt ; then @@ -855,6 +900,14 @@ cd .. %if ! 0%{?only_efi:1} cd build +%ifarch ppc ppc64 ppc64le +%if 0%{?sbat_generation} +echo "sbat,1,SBAT Version,sbat,1,https://github.com/rhboot/shim/blob/main/SBAT.md" > sbat.csv +echo "grub,%{sbat_generation_grub},Free Software Foundation,grub,%{version},https://www.gnu.org/software/grub/" >> sbat.csv +echo "grub.%{sbat_distro},%{sbat_generation},%{sbat_distro_summary},%{name},%{version},%{sbat_distro_url}" >> sbat.csv +%endif +%endif + %if "%{platform}" != "emu" %define arch_specific --enable-device-mapper TLFLAGS="-static" @@ -984,7 +1037,7 @@ fi EOF %{__tar} cvf memdisk.tar ./grub.cfg ./grub-mkimage -O %{grubarch} -o grub.elf -d grub-core -x grub.der -m memdisk.tar \ - -c %{platform}-config --appended-signature-size %brp_pesign_reservation ${GRUB_MODULES} + -c %{platform}-config -s sbat.csv --appended-signature-size %brp_pesign_reservation ${GRUB_MODULES} ls -l "grub.elf" truncate -s -%brp_pesign_reservation "grub.elf" fi @@ -1016,7 +1069,9 @@ install -m 644 grub.efi %{buildroot}/%{_datadir}/%{name}/%{grubefiarch}/. %ifarch x86_64 ln -srf %{buildroot}/%{_datadir}/%{name}/%{grubefiarch}/grub.efi %{buildroot}/%{_datadir}/%{name}/%{grubefiarch}/grub-tpm.efi %endif +%if 0%{?suse_version} > 1600 install -m 644 grubbls.efi %{buildroot}/%{_datadir}/%{name}/%{grubefiarch}/. +%endif # Create grub.efi link to system efi directory # This is for tools like kiwi not fiddling with the path @@ -1038,7 +1093,11 @@ EoM %endif %ifarch x86_64 aarch64 +%if 0%{?suse_version} > 1600 export BRP_PESIGN_FILES="%{_datadir}/%{name}/%{grubefiarch}/grub.efi %{_datadir}/%{name}/%{grubefiarch}/grubbls.efi" +%else +export BRP_PESIGN_FILES="%{_datadir}/%{name}/%{grubefiarch}/grub.efi" +%endif install -m 444 grub.der %{buildroot}/%{sysefidir}/ %endif @@ -1171,10 +1230,20 @@ grep -E ${EXTRA_PATTERN} %{grubarch}-mod-all.lst > %{grubarch}-mod-extras.lst %fdupes %buildroot%{_libdir} %fdupes %buildroot%{_datadir} +%if 0%{?suse_version} > 1600 %pre common +%else + +%pre +%endif %service_add_pre grub2-once.service +%if 0%{?suse_version} > 1600 %post common +%else + +%post +%endif %service_add_post grub2-once.service %if ! 0%{?only_efi:1} @@ -1202,13 +1271,28 @@ grep -E ${EXTRA_PATTERN} %{grubarch}-mod-all.lst > %{grubarch}-mod-extras.lst %endif +%if 0%{?suse_version} > 1600 %preun common +%else + +%preun +%endif %service_del_preun grub2-once.service +%if 0%{?suse_version} > 1600 %postun common +%else + +%postun +%endif %service_del_postun grub2-once.service +%if 0%{?suse_version} > 1600 %files +%else + +%files -f %{name}.lang +%endif %defattr(-,root,root,-) %doc AUTHORS %doc NEWS README @@ -1218,13 +1302,15 @@ grep -E ${EXTRA_PATTERN} %{grubarch}-mod-all.lst > %{grubarch}-mod-extras.lst %doc README.ibm3215 %endif +%if 0%{?suse_version} > 1600 %files common -f %{name}.lang +%defattr(-,root,root,-) +%endif %if 0%{?suse_version} < 1500 %doc COPYING %else %license COPYING %endif -%defattr(-,root,root,-) %dir /boot/%{name} %ghost %attr(600, root, root) /boot/%{name}/grub.cfg %{_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/10_linux %config(noreplace) %{_sysconfdir}/grub.d/20_linux_xen -%config(noreplace) %{_sysconfdir}/grub.d/25_bli +# The bli.mod is enabled in grubbls.efi, which will mostly adhere to systemd +# standards. But it is not the case for grub.efi, as it serves no purpose +# there, among other considerations. Therefore, the 25_bli script that loads +# bli.mod as an external module should be disabled (by stripping off its +# executable bit) to prevent showing 'file not found' error. This is because +# grub.efi may intentionally lack access to external modules, as it is designed +# to be a drop-in file, requires no external dependency (boo#1231591) +%attr(0644, root, root) %config(noreplace) %{_sysconfdir}/grub.d/25_bli %config(noreplace) %{_sysconfdir}/grub.d/30_uefi-firmware %config(noreplace) %{_sysconfdir}/grub.d/40_custom %config(noreplace) %{_sysconfdir}/grub.d/41_custom @@ -1406,9 +1499,11 @@ grep -E ${EXTRA_PATTERN} %{grubarch}-mod-all.lst > %{grubarch}-mod-extras.lst %{sysefidir}/grub.der %endif +%if 0%{?suse_version} > 1600 %files %{grubefiarch}-bls %defattr(-,root,root,-) %{_datadir}/%{name}/%{grubefiarch}/grubbls.efi +%endif %files %{grubefiarch}-extras -f %{grubefiarch}-mod-extras.lst %defattr(-,root,root,-)