| From b11547137703bbc642114a816233a5b6fed61b06 Mon Sep 17 00:00:00 2001 |
| From: Peter Jones <pjones@redhat.com> |
| Date: Mon, 15 Feb 2021 17:07:00 +0100 |
| Subject: [PATCH] util/mkimage: Add an option to import SBAT metadata into a |
| .sbat section |
| |
| Add a --sbat option to the grub-mkimage tool which allows us to import |
| an SBAT metadata formatted as a CSV file into a .sbat section of the |
| EFI binary. |
| |
| Signed-off-by: Peter Jones <pjones@redhat.com> |
| Signed-off-by: Javier Martinez Canillas <javierm@redhat.com> |
| Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com> |
| Signed-off-by: Stefan SΓΈrensen <stefan.sorensen@spectralink.com> |
| --- |
| docs/grub.texi | 19 +++++++++++++++++++ |
| include/grub/util/install.h | 3 ++- |
| include/grub/util/mkimage.h | 1 + |
| util/grub-install-common.c | 2 +- |
| util/grub-mkimage.c | 15 ++++++++++++++- |
| util/mkimage.c | 43 ++++++++++++++++++++++++++++++++++++------- |
| 6 files changed, 73 insertions(+), 10 deletions(-) |
| |
| diff --git a/docs/grub.texi b/docs/grub.texi |
| index 8518cc0..bff6dfc 100644 |
| --- a/docs/grub.texi |
| +++ b/docs/grub.texi |
| @@ -5616,6 +5616,7 @@ environment variables and commands are listed in the same order. |
| * Authentication and authorisation:: Users and access control |
| * Using digital signatures:: Booting digitally signed code |
| * UEFI secure boot and shim:: Booting digitally signed PE files |
| +* Secure Boot Advanced Targeting:: Embedded information for generation number based revocation |
| * Measured Boot:: Measuring boot components |
| * Lockdown:: Lockdown when booting on a secure setup |
| @end menu |
| @@ -5795,6 +5796,24 @@ and @command{memrw} will not be available when the UEFI secure boot is enabled. |
| This is done for security reasons and are enforced by the GRUB Lockdown mechanism |
| (@pxref{Lockdown}). |
| |
| +@node Secure Boot Advanced Targeting |
| +@section Embedded information for generation number based revocation |
| + |
| +The Secure Boot Advanced Targeting (SBAT) is a mechanism to allow the revocation |
| +of components in the boot path by using generation numbers embedded into the EFI |
| +binaries. The SBAT metadata is located in an .sbat data section that has set of |
| +UTF-8 strings as comma-separated values (CSV). See |
| +@uref{https://github.com/rhboot/shim/blob/main/SBAT.md} for more details. |
| + |
| +To add a data section containing the SBAT information into the binary, the |
| +@option{--sbat} option of @command{grub-mkimage} command should be used. The content |
| +of a CSV file, encoded with UTF-8, is copied as is to the .sbat data section into |
| +the generated EFI binary. The CSV file can be stored anywhere on the file system. |
| + |
| +@example |
| +grub-mkimage -O x86_64-efi -o grubx64.efi -p '(tftp)/grub' --sbat sbat.csv efinet tftp |
| +@end example |
| + |
| @node Measured Boot |
| @section Measuring boot components |
| |
| diff --git a/include/grub/util/install.h b/include/grub/util/install.h |
| index 2631b10..c03befd 100644 |
| --- a/include/grub/util/install.h |
| +++ b/include/grub/util/install.h |
| @@ -183,7 +183,8 @@ grub_install_generate_image (const char *dir, const char *prefix, |
| char *config_path, |
| const struct grub_install_image_target_desc *image_target, |
| int note, |
| - grub_compression_t comp, const char *dtb_file); |
| + grub_compression_t comp, const char *dtb_file, |
| + const char *sbat_path); |
| |
| const struct grub_install_image_target_desc * |
| grub_install_get_image_target (const char *arg); |
| diff --git a/include/grub/util/mkimage.h b/include/grub/util/mkimage.h |
| index ba9f568..3819a67 100644 |
| --- a/include/grub/util/mkimage.h |
| +++ b/include/grub/util/mkimage.h |
| @@ -24,6 +24,7 @@ struct grub_mkimage_layout |
| size_t exec_size; |
| size_t kernel_size; |
| size_t bss_size; |
| + size_t sbat_size; |
| grub_uint64_t start_address; |
| void *reloc_section; |
| size_t reloc_size; |
| diff --git a/util/grub-install-common.c b/util/grub-install-common.c |
| index 0295d40..5d43ed1 100644 |
| --- a/util/grub-install-common.c |
| +++ b/util/grub-install-common.c |
| @@ -511,7 +511,7 @@ grub_install_make_image_wrap_file (const char *dir, const char *prefix, |
| grub_install_generate_image (dir, prefix, fp, outname, |
| modules.entries, memdisk_path, |
| pubkeys, npubkeys, config_path, tgt, |
| - note, compression, dtb); |
| + note, compression, dtb, NULL); |
| while (dc--) |
| grub_install_pop_module (); |
| } |
| diff --git a/util/grub-mkimage.c b/util/grub-mkimage.c |
| index 912564e..75b8847 100644 |
| --- a/util/grub-mkimage.c |
| +++ b/util/grub-mkimage.c |
| @@ -81,6 +81,7 @@ static struct argp_option options[] = { |
| {"output", 'o', N_("FILE"), 0, N_("output a generated image to FILE [default=stdout]"), 0}, |
| {"format", 'O', N_("FORMAT"), 0, 0, 0}, |
| {"compression", 'C', "(xz|none|auto)", 0, N_("choose the compression to use for core image"), 0}, |
| + {"sbat", 's', N_("FILE"), 0, N_("SBAT metadata"), 0}, |
| {"verbose", 'v', 0, 0, N_("print verbose messages."), 0}, |
| { 0, 0, 0, 0, 0, 0 } |
| }; |
| @@ -123,6 +124,7 @@ struct arguments |
| size_t npubkeys; |
| char *font; |
| char *config; |
| + char *sbat; |
| int note; |
| const struct grub_install_image_target_desc *image_target; |
| grub_compression_t comp; |
| @@ -224,6 +226,13 @@ argp_parser (int key, char *arg, struct argp_state *state) |
| arguments->prefix = xstrdup (arg); |
| break; |
| |
| + case 's': |
| + if (arguments->sbat) |
| + free (arguments->sbat); |
| + |
| + arguments->sbat = xstrdup (arg); |
| + break; |
| + |
| case 'v': |
| verbosity++; |
| break; |
| @@ -309,7 +318,8 @@ main (int argc, char *argv[]) |
| arguments.memdisk, arguments.pubkeys, |
| arguments.npubkeys, arguments.config, |
| arguments.image_target, arguments.note, |
| - arguments.comp, arguments.dtb); |
| + arguments.comp, arguments.dtb, |
| + arguments.sbat); |
| |
| if (grub_util_file_sync (fp) < 0) |
| grub_util_error (_("cannot sync `%s': %s"), arguments.output ? : "stdout", |
| @@ -328,5 +338,8 @@ main (int argc, char *argv[]) |
| if (arguments.output) |
| free (arguments.output); |
| |
| + if (arguments.sbat) |
| + free (arguments.sbat); |
| + |
| return 0; |
| } |
| diff --git a/util/mkimage.c b/util/mkimage.c |
| index 8b475a6..b354ec1 100644 |
| --- a/util/mkimage.c |
| +++ b/util/mkimage.c |
| @@ -869,12 +869,13 @@ grub_install_generate_image (const char *dir, const char *prefix, |
| char *memdisk_path, char **pubkey_paths, |
| size_t npubkeys, char *config_path, |
| const struct grub_install_image_target_desc *image_target, |
| - int note, grub_compression_t comp, const char *dtb_path) |
| + int note, grub_compression_t comp, const char *dtb_path, |
| + const char *sbat_path) |
| { |
| char *kernel_img, *core_img; |
| size_t total_module_size, core_size; |
| size_t memdisk_size = 0, config_size = 0; |
| - size_t prefix_size = 0, dtb_size = 0; |
| + size_t prefix_size = 0, dtb_size = 0, sbat_size = 0; |
| char *kernel_path; |
| size_t offset; |
| struct grub_util_path_list *path_list, *p; |
| @@ -925,6 +926,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 (config_path) |
| { |
| config_size = ALIGN_ADDR (grub_util_get_image_size (config_path) + 1); |
| @@ -1289,8 +1293,9 @@ grub_install_generate_image (const char *dir, const char *prefix, |
| break; |
| case IMAGE_EFI: |
| { |
| - char *pe_img, *header; |
| + char *pe_img, *pe_sbat, *header; |
| struct grub_pe32_section_table *section; |
| + size_t n_sections = 4; |
| size_t scn_size; |
| grub_uint32_t vma, raw_data; |
| size_t pe_size, header_size; |
| @@ -1305,8 +1310,15 @@ grub_install_generate_image (const char *dir, const char *prefix, |
| header_size = EFI64_HEADER_SIZE; |
| |
| vma = raw_data = header_size; |
| + |
| + if (sbat_path != NULL) |
| + { |
| + sbat_size = ALIGN_ADDR (grub_util_get_image_size (sbat_path)); |
| + sbat_size = ALIGN_UP (sbat_size, GRUB_PE32_FILE_ALIGNMENT); |
| + } |
| + |
| pe_size = ALIGN_UP (header_size + core_size, GRUB_PE32_FILE_ALIGNMENT) + |
| - ALIGN_UP (layout.reloc_size, GRUB_PE32_FILE_ALIGNMENT); |
| + ALIGN_UP (layout.reloc_size, GRUB_PE32_FILE_ALIGNMENT) + sbat_size; |
| header = pe_img = xcalloc (1, pe_size); |
| |
| memcpy (pe_img + raw_data, core_img, core_size); |
| @@ -1321,7 +1333,10 @@ grub_install_generate_image (const char *dir, const char *prefix, |
| + GRUB_PE32_SIGNATURE_SIZE); |
| c->machine = grub_host_to_target16 (image_target->pe_target); |
| |
| - c->num_sections = grub_host_to_target16 (4); |
| + if (sbat_path != NULL) |
| + n_sections++; |
| + |
| + c->num_sections = grub_host_to_target16 (n_sections); |
| c->time = grub_host_to_target32 (STABLE_EMBEDDING_TIMESTAMP); |
| c->characteristics = grub_host_to_target16 (GRUB_PE32_EXECUTABLE_IMAGE |
| | GRUB_PE32_LINE_NUMS_STRIPPED |
| @@ -1383,7 +1398,8 @@ grub_install_generate_image (const char *dir, const char *prefix, |
| GRUB_PE32_SCN_MEM_READ); |
| |
| scn_size = ALIGN_UP (layout.kernel_size - layout.exec_size, GRUB_PE32_FILE_ALIGNMENT); |
| - PE_OHDR (o32, o64, data_size) = grub_host_to_target32 (scn_size + |
| + /* ALIGN_UP (sbat_size, GRUB_PE32_FILE_ALIGNMENT) is done earlier. */ |
| + PE_OHDR (o32, o64, data_size) = grub_host_to_target32 (scn_size + sbat_size + |
| ALIGN_UP (total_module_size, |
| GRUB_PE32_FILE_ALIGNMENT)); |
| |
| @@ -1394,7 +1410,7 @@ grub_install_generate_image (const char *dir, const char *prefix, |
| GRUB_PE32_SCN_MEM_READ | |
| GRUB_PE32_SCN_MEM_WRITE); |
| |
| - scn_size = pe_size - layout.reloc_size - raw_data; |
| + scn_size = pe_size - layout.reloc_size - sbat_size - raw_data; |
| section = init_pe_section (image_target, section, "mods", |
| &vma, scn_size, image_target->section_align, |
| &raw_data, scn_size, |
| @@ -1402,6 +1418,19 @@ grub_install_generate_image (const char *dir, const char *prefix, |
| GRUB_PE32_SCN_MEM_READ | |
| GRUB_PE32_SCN_MEM_WRITE); |
| |
| + if (sbat_path != NULL) |
| + { |
| + pe_sbat = pe_img + raw_data; |
| + grub_util_load_image (sbat_path, pe_sbat); |
| + |
| + section = init_pe_section (image_target, section, ".sbat", |
| + &vma, sbat_size, |
| + image_target->section_align, |
| + &raw_data, sbat_size, |
| + GRUB_PE32_SCN_CNT_INITIALIZED_DATA | |
| + GRUB_PE32_SCN_MEM_READ); |
| + } |
| + |
| scn_size = layout.reloc_size; |
| PE_OHDR (o32, o64, base_relocation_table.rva) = grub_host_to_target32 (vma); |
| PE_OHDR (o32, o64, base_relocation_table.size) = grub_host_to_target32 (scn_size); |
| -- |
| 2.14.2 |
| |