1From b11547137703bbc642114a816233a5b6fed61b06 Mon Sep 17 00:00:00 2001 2From: Peter Jones <pjones@redhat.com> 3Date: Mon, 15 Feb 2021 17:07:00 +0100 4Subject: [PATCH] util/mkimage: Add an option to import SBAT metadata into a 5 .sbat section 6 7Add a --sbat option to the grub-mkimage tool which allows us to import 8an SBAT metadata formatted as a CSV file into a .sbat section of the 9EFI binary. 10 11Signed-off-by: Peter Jones <pjones@redhat.com> 12Signed-off-by: Javier Martinez Canillas <javierm@redhat.com> 13Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com> 14Signed-off-by: Stefan Sørensen <stefan.sorensen@spectralink.com> 15--- 16 docs/grub.texi | 19 +++++++++++++++++++ 17 include/grub/util/install.h | 3 ++- 18 include/grub/util/mkimage.h | 1 + 19 util/grub-install-common.c | 2 +- 20 util/grub-mkimage.c | 15 ++++++++++++++- 21 util/mkimage.c | 43 ++++++++++++++++++++++++++++++++++++------- 22 6 files changed, 73 insertions(+), 10 deletions(-) 23 24diff --git a/docs/grub.texi b/docs/grub.texi 25index 8518cc0..bff6dfc 100644 26--- a/docs/grub.texi 27+++ b/docs/grub.texi 28@@ -5616,6 +5616,7 @@ environment variables and commands are listed in the same order. 29 * Authentication and authorisation:: Users and access control 30 * Using digital signatures:: Booting digitally signed code 31 * UEFI secure boot and shim:: Booting digitally signed PE files 32+* Secure Boot Advanced Targeting:: Embedded information for generation number based revocation 33 * Measured Boot:: Measuring boot components 34 * Lockdown:: Lockdown when booting on a secure setup 35 @end menu 36@@ -5795,6 +5796,24 @@ and @command{memrw} will not be available when the UEFI secure boot is enabled. 37 This is done for security reasons and are enforced by the GRUB Lockdown mechanism 38 (@pxref{Lockdown}). 39 40+@node Secure Boot Advanced Targeting 41+@section Embedded information for generation number based revocation 42+ 43+The Secure Boot Advanced Targeting (SBAT) is a mechanism to allow the revocation 44+of components in the boot path by using generation numbers embedded into the EFI 45+binaries. The SBAT metadata is located in an .sbat data section that has set of 46+UTF-8 strings as comma-separated values (CSV). See 47+@uref{https://github.com/rhboot/shim/blob/main/SBAT.md} for more details. 48+ 49+To add a data section containing the SBAT information into the binary, the 50+@option{--sbat} option of @command{grub-mkimage} command should be used. The content 51+of a CSV file, encoded with UTF-8, is copied as is to the .sbat data section into 52+the generated EFI binary. The CSV file can be stored anywhere on the file system. 53+ 54+@example 55+grub-mkimage -O x86_64-efi -o grubx64.efi -p '(tftp)/grub' --sbat sbat.csv efinet tftp 56+@end example 57+ 58 @node Measured Boot 59 @section Measuring boot components 60 61diff --git a/include/grub/util/install.h b/include/grub/util/install.h 62index 2631b10..c03befd 100644 63--- a/include/grub/util/install.h 64+++ b/include/grub/util/install.h 65@@ -183,7 +183,8 @@ grub_install_generate_image (const char *dir, const char *prefix, 66 char *config_path, 67 const struct grub_install_image_target_desc *image_target, 68 int note, 69- grub_compression_t comp, const char *dtb_file); 70+ grub_compression_t comp, const char *dtb_file, 71+ const char *sbat_path); 72 73 const struct grub_install_image_target_desc * 74 grub_install_get_image_target (const char *arg); 75diff --git a/include/grub/util/mkimage.h b/include/grub/util/mkimage.h 76index ba9f568..3819a67 100644 77--- a/include/grub/util/mkimage.h 78+++ b/include/grub/util/mkimage.h 79@@ -24,6 +24,7 @@ struct grub_mkimage_layout 80 size_t exec_size; 81 size_t kernel_size; 82 size_t bss_size; 83+ size_t sbat_size; 84 grub_uint64_t start_address; 85 void *reloc_section; 86 size_t reloc_size; 87diff --git a/util/grub-install-common.c b/util/grub-install-common.c 88index 0295d40..5d43ed1 100644 89--- a/util/grub-install-common.c 90+++ b/util/grub-install-common.c 91@@ -511,7 +511,7 @@ grub_install_make_image_wrap_file (const char *dir, const char *prefix, 92 grub_install_generate_image (dir, prefix, fp, outname, 93 modules.entries, memdisk_path, 94 pubkeys, npubkeys, config_path, tgt, 95- note, compression, dtb); 96+ note, compression, dtb, NULL); 97 while (dc--) 98 grub_install_pop_module (); 99 } 100diff --git a/util/grub-mkimage.c b/util/grub-mkimage.c 101index 912564e..75b8847 100644 102--- a/util/grub-mkimage.c 103+++ b/util/grub-mkimage.c 104@@ -81,6 +81,7 @@ static struct argp_option options[] = { 105 {"output", 'o', N_("FILE"), 0, N_("output a generated image to FILE [default=stdout]"), 0}, 106 {"format", 'O', N_("FORMAT"), 0, 0, 0}, 107 {"compression", 'C', "(xz|none|auto)", 0, N_("choose the compression to use for core image"), 0}, 108+ {"sbat", 's', N_("FILE"), 0, N_("SBAT metadata"), 0}, 109 {"verbose", 'v', 0, 0, N_("print verbose messages."), 0}, 110 { 0, 0, 0, 0, 0, 0 } 111 }; 112@@ -123,6 +124,7 @@ struct arguments 113 size_t npubkeys; 114 char *font; 115 char *config; 116+ char *sbat; 117 int note; 118 const struct grub_install_image_target_desc *image_target; 119 grub_compression_t comp; 120@@ -224,6 +226,13 @@ argp_parser (int key, char *arg, struct argp_state *state) 121 arguments->prefix = xstrdup (arg); 122 break; 123 124+ case 's': 125+ if (arguments->sbat) 126+ free (arguments->sbat); 127+ 128+ arguments->sbat = xstrdup (arg); 129+ break; 130+ 131 case 'v': 132 verbosity++; 133 break; 134@@ -309,7 +318,8 @@ main (int argc, char *argv[]) 135 arguments.memdisk, arguments.pubkeys, 136 arguments.npubkeys, arguments.config, 137 arguments.image_target, arguments.note, 138- arguments.comp, arguments.dtb); 139+ arguments.comp, arguments.dtb, 140+ arguments.sbat); 141 142 if (grub_util_file_sync (fp) < 0) 143 grub_util_error (_("cannot sync `%s': %s"), arguments.output ? : "stdout", 144@@ -328,5 +338,8 @@ main (int argc, char *argv[]) 145 if (arguments.output) 146 free (arguments.output); 147 148+ if (arguments.sbat) 149+ free (arguments.sbat); 150+ 151 return 0; 152 } 153diff --git a/util/mkimage.c b/util/mkimage.c 154index 8b475a6..b354ec1 100644 155--- a/util/mkimage.c 156+++ b/util/mkimage.c 157@@ -869,12 +869,13 @@ grub_install_generate_image (const char *dir, const char *prefix, 158 char *memdisk_path, char **pubkey_paths, 159 size_t npubkeys, char *config_path, 160 const struct grub_install_image_target_desc *image_target, 161- int note, grub_compression_t comp, const char *dtb_path) 162+ int note, grub_compression_t comp, const char *dtb_path, 163+ const char *sbat_path) 164 { 165 char *kernel_img, *core_img; 166 size_t total_module_size, core_size; 167 size_t memdisk_size = 0, config_size = 0; 168- size_t prefix_size = 0, dtb_size = 0; 169+ size_t prefix_size = 0, dtb_size = 0, sbat_size = 0; 170 char *kernel_path; 171 size_t offset; 172 struct grub_util_path_list *path_list, *p; 173@@ -925,6 +926,9 @@ grub_install_generate_image (const char *dir, const char *prefix, 174 total_module_size += dtb_size + sizeof (struct grub_module_header); 175 } 176 177+ if (sbat_path != NULL && image_target->id != IMAGE_EFI) 178+ grub_util_error (_(".sbat section can be embedded into EFI images only")); 179+ 180 if (config_path) 181 { 182 config_size = ALIGN_ADDR (grub_util_get_image_size (config_path) + 1); 183@@ -1289,8 +1293,9 @@ grub_install_generate_image (const char *dir, const char *prefix, 184 break; 185 case IMAGE_EFI: 186 { 187- char *pe_img, *header; 188+ char *pe_img, *pe_sbat, *header; 189 struct grub_pe32_section_table *section; 190+ size_t n_sections = 4; 191 size_t scn_size; 192 grub_uint32_t vma, raw_data; 193 size_t pe_size, header_size; 194@@ -1305,8 +1310,15 @@ grub_install_generate_image (const char *dir, const char *prefix, 195 header_size = EFI64_HEADER_SIZE; 196 197 vma = raw_data = header_size; 198+ 199+ if (sbat_path != NULL) 200+ { 201+ sbat_size = ALIGN_ADDR (grub_util_get_image_size (sbat_path)); 202+ sbat_size = ALIGN_UP (sbat_size, GRUB_PE32_FILE_ALIGNMENT); 203+ } 204+ 205 pe_size = ALIGN_UP (header_size + core_size, GRUB_PE32_FILE_ALIGNMENT) + 206- ALIGN_UP (layout.reloc_size, GRUB_PE32_FILE_ALIGNMENT); 207+ ALIGN_UP (layout.reloc_size, GRUB_PE32_FILE_ALIGNMENT) + sbat_size; 208 header = pe_img = xcalloc (1, pe_size); 209 210 memcpy (pe_img + raw_data, core_img, core_size); 211@@ -1321,7 +1333,10 @@ grub_install_generate_image (const char *dir, const char *prefix, 212 + GRUB_PE32_SIGNATURE_SIZE); 213 c->machine = grub_host_to_target16 (image_target->pe_target); 214 215- c->num_sections = grub_host_to_target16 (4); 216+ if (sbat_path != NULL) 217+ n_sections++; 218+ 219+ c->num_sections = grub_host_to_target16 (n_sections); 220 c->time = grub_host_to_target32 (STABLE_EMBEDDING_TIMESTAMP); 221 c->characteristics = grub_host_to_target16 (GRUB_PE32_EXECUTABLE_IMAGE 222 | GRUB_PE32_LINE_NUMS_STRIPPED 223@@ -1383,7 +1398,8 @@ grub_install_generate_image (const char *dir, const char *prefix, 224 GRUB_PE32_SCN_MEM_READ); 225 226 scn_size = ALIGN_UP (layout.kernel_size - layout.exec_size, GRUB_PE32_FILE_ALIGNMENT); 227- PE_OHDR (o32, o64, data_size) = grub_host_to_target32 (scn_size + 228+ /* ALIGN_UP (sbat_size, GRUB_PE32_FILE_ALIGNMENT) is done earlier. */ 229+ PE_OHDR (o32, o64, data_size) = grub_host_to_target32 (scn_size + sbat_size + 230 ALIGN_UP (total_module_size, 231 GRUB_PE32_FILE_ALIGNMENT)); 232 233@@ -1394,7 +1410,7 @@ grub_install_generate_image (const char *dir, const char *prefix, 234 GRUB_PE32_SCN_MEM_READ | 235 GRUB_PE32_SCN_MEM_WRITE); 236 237- scn_size = pe_size - layout.reloc_size - raw_data; 238+ scn_size = pe_size - layout.reloc_size - sbat_size - raw_data; 239 section = init_pe_section (image_target, section, "mods", 240 &vma, scn_size, image_target->section_align, 241 &raw_data, scn_size, 242@@ -1402,6 +1418,19 @@ grub_install_generate_image (const char *dir, const char *prefix, 243 GRUB_PE32_SCN_MEM_READ | 244 GRUB_PE32_SCN_MEM_WRITE); 245 246+ if (sbat_path != NULL) 247+ { 248+ pe_sbat = pe_img + raw_data; 249+ grub_util_load_image (sbat_path, pe_sbat); 250+ 251+ section = init_pe_section (image_target, section, ".sbat", 252+ &vma, sbat_size, 253+ image_target->section_align, 254+ &raw_data, sbat_size, 255+ GRUB_PE32_SCN_CNT_INITIALIZED_DATA | 256+ GRUB_PE32_SCN_MEM_READ); 257+ } 258+ 259 scn_size = layout.reloc_size; 260 PE_OHDR (o32, o64, base_relocation_table.rva) = grub_host_to_target32 (vma); 261 PE_OHDR (o32, o64, base_relocation_table.size) = grub_host_to_target32 (scn_size); 262-- 2632.14.2 264 265