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