Blame SOURCES/0179-Add-suport-for-signing-grub-with-an-appended-signatu.patch

5593c8
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
5593c8
From: Rashmica Gupta <rashmica.g@gmail.com>
5593c8
Date: Thu, 11 Jun 2020 11:26:23 +1000
5593c8
Subject: [PATCH] Add suport for signing grub with an appended signature
5593c8
5593c8
Add infrastructure to allow firmware to verify the integrity of grub
5593c8
by use of a Linux-kernel-module-style appended signature. We initially
5593c8
target powerpc-ieee1275, but the code should be extensible to other
5593c8
platforms.
5593c8
5593c8
Usually these signatures are appended to a file without modifying the
5593c8
ELF file itself. (This is what the 'sign-file' tool does, for example.)
5593c8
The verifier loads the signed file from the file system and looks at the
5593c8
end of the file for the appended signature. However, on powerpc-ieee1275
5593c8
platforms, the bootloader is often stored directly in the PReP partition
5593c8
as raw bytes without a file-system. This makes determining the location
5593c8
of an appended signature more difficult.
5593c8
5593c8
To address this, we add a new ELF note.
5593c8
5593c8
The name field of shall be the string "Appended-Signature", zero-padded
5593c8
to 4 byte alignment. The type field shall be 0x41536967 (the ASCII values
5593c8
for the string "ASig"). It must be the final section in the ELF binary.
5593c8
5593c8
The description shall contain the appended signature structure as defined
5593c8
by the Linux kernel. The description will also be padded to be a multiple
5593c8
of 4 bytes. The padding shall be added before the appended signature
5593c8
structure (not at the end) so that the final bytes of a signed ELF file
5593c8
are the appended signature magic.
5593c8
5593c8
A subsequent patch documents how to create a grub core.img validly signed
5593c8
under this scheme.
5593c8
5593c8
Signed-off-by: Daniel Axtens <dja@axtens.net>
5593c8
Signed-off-by: Rashmica Gupta <rashmica.g@gmail.com>
5593c8
5593c8
---
5593c8
5593c8
You can experiment with this code with a patched version of SLOF
5593c8
that verifies these signatures. You can find one at:
5593c8
   https://github.com/daxtens/SLOF
5593c8
5593c8
I will be proposing this for inclusion in a future Power Architecture
5593c8
Platform Reference (PAPR).
5593c8
---
5593c8
 util/grub-install-common.c  | 18 ++++++++++++++++--
5593c8
 util/grub-mkimage.c         | 15 +++++++++++++--
5593c8
 util/grub-mkimagexx.c       | 39 ++++++++++++++++++++++++++++++++++++++-
5593c8
 util/mkimage.c              | 13 +++++++------
5593c8
 include/grub/util/install.h |  8 ++++++--
5593c8
 include/grub/util/mkimage.h |  4 ++--
5593c8
 6 files changed, 82 insertions(+), 15 deletions(-)
5593c8
5593c8
diff --git a/util/grub-install-common.c b/util/grub-install-common.c
1c6ba0
index 4e212e690c..aab2a941f8 100644
5593c8
--- a/util/grub-install-common.c
5593c8
+++ b/util/grub-install-common.c
5593c8
@@ -461,10 +461,12 @@ static size_t npubkeys;
5593c8
 static char *sbat;
5593c8
 static int disable_shim_lock;
5593c8
 static grub_compression_t compression;
5593c8
+static size_t appsig_size;
5593c8
 
5593c8
 int
5593c8
 grub_install_parse (int key, char *arg)
5593c8
 {
5593c8
+  const char *end;
5593c8
   switch (key)
5593c8
     {
5593c8
     case 'C':
5593c8
@@ -562,6 +564,12 @@ grub_install_parse (int key, char *arg)
5593c8
       grub_util_error (_("Unrecognized compression `%s'"), arg);
5593c8
     case GRUB_INSTALL_OPTIONS_GRUB_MKIMAGE:
5593c8
       return 1;
5593c8
+    case GRUB_INSTALL_OPTIONS_APPENDED_SIGNATURE_SIZE:
5593c8
+      grub_errno = 0;
5593c8
+      appsig_size = grub_strtol(arg, &end, 10);
5593c8
+      if (grub_errno)
5593c8
+        return 0;
5593c8
+      return 1;
5593c8
     default:
5593c8
       return 0;
5593c8
     }
5593c8
@@ -665,7 +673,13 @@ grub_install_make_image_wrap_file (const char *dir, const char *prefix,
5593c8
 		  dir, prefix,
5593c8
 		  outname, dtb ? : "", sbat ? : "", mkimage_target,
5593c8
 		  compnames[compression], note ? "--note" : "",
5593c8
-		  disable_shim_lock ? "--disable-shim-lock" : "", s);
5593c8
+		  disable_shim_lock ? "--disable-shim-lock" : "",
5593c8
+		  "--format '%s' --compression '%s' "
5593c8
+		  "--appended-signature-size %zu %s %s\n",
5593c8
+		  dir, prefix,
5593c8
+		  outname, dtb ? : "", mkimage_target,
5593c8
+		  compnames[compression], appsig_size,
5593c8
+		  note ? "--note" : "", s);
5593c8
   free (s);
5593c8
 
5593c8
   tgt = grub_install_get_image_target (mkimage_target);
5593c8
@@ -675,7 +689,7 @@ grub_install_make_image_wrap_file (const char *dir, const char *prefix,
5593c8
   grub_install_generate_image (dir, prefix, fp, outname,
5593c8
 			       modules.entries, memdisk_path,
5593c8
 			       pubkeys, npubkeys, config_path, tgt,
5593c8
-			       note, compression, dtb, sbat,
5593c8
+			       note, appsig_size, compression, dtb, sbat,
5593c8
 			       disable_shim_lock);
5593c8
   while (dc--)
5593c8
     grub_install_pop_module ();
5593c8
diff --git a/util/grub-mkimage.c b/util/grub-mkimage.c
1c6ba0
index c0d5599370..8a53310548 100644
5593c8
--- a/util/grub-mkimage.c
5593c8
+++ b/util/grub-mkimage.c
5593c8
@@ -84,6 +84,7 @@ static struct argp_option options[] = {
5593c8
   {"sbat", 's', N_("FILE"), 0, N_("SBAT metadata"), 0},
5593c8
   {"disable-shim-lock", GRUB_INSTALL_OPTIONS_DISABLE_SHIM_LOCK, 0, 0, N_("disable shim_lock verifier"), 0},
5593c8
   {"verbose",     'v', 0,      0, N_("print verbose messages."), 0},
5593c8
+  {"appended-signature-size", 'S', N_("SIZE"), 0, N_("Add a note segment reserving SIZE bytes for an appended signature"), 0},
5593c8
   { 0, 0, 0, 0, 0, 0 }
5593c8
 };
5593c8
 
5593c8
@@ -128,6 +129,7 @@ struct arguments
5593c8
   char *sbat;
5593c8
   int note;
5593c8
   int disable_shim_lock;
5593c8
+  size_t appsig_size;
5593c8
   const struct grub_install_image_target_desc *image_target;
5593c8
   grub_compression_t comp;
5593c8
 };
5593c8
@@ -138,6 +140,7 @@ argp_parser (int key, char *arg, struct argp_state *state)
5593c8
   /* Get the input argument from argp_parse, which we
5593c8
      know is a pointer to our arguments structure. */
5593c8
   struct arguments *arguments = state->input;
5593c8
+  const char* end;
5593c8
 
5593c8
   switch (key)
5593c8
     {
5593c8
@@ -170,6 +173,13 @@ argp_parser (int key, char *arg, struct argp_state *state)
5593c8
       arguments->note = 1;
5593c8
       break;
5593c8
 
5593c8
+    case 'S':
5593c8
+      grub_errno = 0;
5593c8
+      arguments->appsig_size = grub_strtol(arg, &end, 10);
5593c8
+      if (grub_errno)
5593c8
+        return 0;
5593c8
+      break;
5593c8
+
5593c8
     case 'm':
5593c8
       if (arguments->memdisk)
5593c8
 	free (arguments->memdisk);
5593c8
@@ -324,8 +334,9 @@ main (int argc, char *argv[])
5593c8
 			       arguments.memdisk, arguments.pubkeys,
5593c8
 			       arguments.npubkeys, arguments.config,
5593c8
 			       arguments.image_target, arguments.note,
5593c8
-			       arguments.comp, arguments.dtb,
5593c8
-			       arguments.sbat, arguments.disable_shim_lock);
5593c8
+			       arguments.appsig_size, arguments.comp,
5593c8
+			       arguments.dtb, arguments.sbat,
5593c8
+			       arguments.disable_shim_lock);
5593c8
 
5593c8
   if (grub_util_file_sync (fp) < 0)
5593c8
     grub_util_error (_("cannot sync `%s': %s"), arguments.output ? : "stdout",
5593c8
diff --git a/util/grub-mkimagexx.c b/util/grub-mkimagexx.c
1c6ba0
index d78fa3e533..393119486d 100644
5593c8
--- a/util/grub-mkimagexx.c
5593c8
+++ b/util/grub-mkimagexx.c
5593c8
@@ -84,6 +84,15 @@ struct grub_ieee1275_note
5593c8
   struct grub_ieee1275_note_desc descriptor;
5593c8
 };
5593c8
 
5593c8
+#define GRUB_APPENDED_SIGNATURE_NOTE_NAME "Appended-Signature"
5593c8
+#define GRUB_APPENDED_SIGNATURE_NOTE_TYPE 0x41536967 /* "ASig" */
5593c8
+
5593c8
+struct grub_appended_signature_note
5593c8
+{
5593c8
+  Elf32_Nhdr header;
5593c8
+  char name[ALIGN_UP(sizeof (GRUB_APPENDED_SIGNATURE_NOTE_NAME), 4)];
5593c8
+};
5593c8
+
5593c8
 #define GRUB_XEN_NOTE_NAME "Xen"
5593c8
 
5593c8
 struct fixup_block_list
5593c8
@@ -207,7 +216,7 @@ grub_arm_reloc_jump24 (grub_uint32_t *target, Elf32_Addr sym_addr)
5593c8
 
5593c8
 void
5593c8
 SUFFIX (grub_mkimage_generate_elf) (const struct grub_install_image_target_desc *image_target,
5593c8
-				    int note, char **core_img, size_t *core_size,
5593c8
+				    int note, size_t appsig_size, char **core_img, size_t *core_size,
5593c8
 				    Elf_Addr target_addr,
5593c8
 				    struct grub_mkimage_layout *layout)
5593c8
 {
5593c8
@@ -221,6 +230,12 @@ SUFFIX (grub_mkimage_generate_elf) (const struct grub_install_image_target_desc
5593c8
   int shnum = 4;
5593c8
   int string_size = sizeof (".text") + sizeof ("mods") + 1;
5593c8
 
5593c8
+  if (appsig_size)
5593c8
+    {
5593c8
+      phnum++;
5593c8
+      footer_size += ALIGN_UP(sizeof (struct grub_appended_signature_note) + appsig_size, 4);
5593c8
+    }
5593c8
+
5593c8
   if (image_target->id != IMAGE_LOONGSON_ELF)
5593c8
     phnum += 2;
5593c8
 
5593c8
@@ -484,6 +499,28 @@ SUFFIX (grub_mkimage_generate_elf) (const struct grub_install_image_target_desc
5593c8
       phdr->p_offset = grub_host_to_target32 (header_size + program_size);
5593c8
     }
5593c8
 
5593c8
+  if (appsig_size) {
5593c8
+    int note_size = ALIGN_UP(sizeof (struct grub_appended_signature_note) + appsig_size, 4);
5593c8
+    struct grub_appended_signature_note *note_ptr = (struct grub_appended_signature_note *)
5593c8
+      (elf_img + program_size + header_size + (note ? sizeof (struct grub_ieee1275_note) : 0));
5593c8
+
5593c8
+    note_ptr->header.n_namesz = grub_host_to_target32 (sizeof (GRUB_APPENDED_SIGNATURE_NOTE_NAME));
5593c8
+    /* needs to sit at the end, so we round this up and sign some zero padding */
5593c8
+    note_ptr->header.n_descsz = grub_host_to_target32 (ALIGN_UP(appsig_size, 4));
5593c8
+    note_ptr->header.n_type = grub_host_to_target32 (GRUB_APPENDED_SIGNATURE_NOTE_TYPE);
5593c8
+    strcpy (note_ptr->name, GRUB_APPENDED_SIGNATURE_NOTE_NAME);
5593c8
+
5593c8
+    phdr++;
5593c8
+    phdr->p_type = grub_host_to_target32 (PT_NOTE);
5593c8
+    phdr->p_flags = grub_host_to_target32 (PF_R);
5593c8
+    phdr->p_align = grub_host_to_target32 (image_target->voidp_sizeof);
5593c8
+    phdr->p_vaddr = 0;
5593c8
+    phdr->p_paddr = 0;
5593c8
+    phdr->p_filesz = grub_host_to_target32 (note_size);
5593c8
+    phdr->p_memsz = 0;
5593c8
+    phdr->p_offset = grub_host_to_target32 (header_size + program_size + (note ? sizeof (struct grub_ieee1275_note) : 0));
5593c8
+  }
5593c8
+
5593c8
   {
5593c8
     char *str_start = (elf_img + sizeof (*ehdr) + phnum * sizeof (*phdr)
5593c8
 		       + shnum * sizeof (*shdr));
5593c8
diff --git a/util/mkimage.c b/util/mkimage.c
1c6ba0
index a26cf76f72..bab1227601 100644
5593c8
--- a/util/mkimage.c
5593c8
+++ b/util/mkimage.c
5593c8
@@ -869,8 +869,9 @@ grub_install_generate_image (const char *dir, const char *prefix,
5593c8
 			     char *memdisk_path, char **pubkey_paths,
5593c8
 			     size_t npubkeys, char *config_path,
5593c8
 			     const struct grub_install_image_target_desc *image_target,
5593c8
-			     int note, grub_compression_t comp, const char *dtb_path,
5593c8
-			     const char *sbat_path, int disable_shim_lock)
5593c8
+			     int note, size_t appsig_size, grub_compression_t comp,
5593c8
+			     const char *dtb_path, const char *sbat_path,
5593c8
+			     int disable_shim_lock)
5593c8
 {
5593c8
   char *kernel_img, *core_img;
5593c8
   size_t total_module_size, core_size;
5593c8
@@ -1773,11 +1774,11 @@ grub_install_generate_image (const char *dir, const char *prefix,
5593c8
 	else
5593c8
 	  target_addr = image_target->link_addr;
5593c8
 	if (image_target->voidp_sizeof == 4)
5593c8
-	  grub_mkimage_generate_elf32 (image_target, note, &core_img, &core_size,
5593c8
-				       target_addr, &layout);
5593c8
+	  grub_mkimage_generate_elf32 (image_target, note, appsig_size, &core_img,
5593c8
+				       &core_size, target_addr, &layout);
5593c8
 	else
5593c8
-	  grub_mkimage_generate_elf64 (image_target, note, &core_img, &core_size,
5593c8
-				       target_addr, &layout);
5593c8
+	  grub_mkimage_generate_elf64 (image_target, note, appsig_size, &core_img,
5593c8
+				       &core_size, target_addr, &layout);
5593c8
       }
5593c8
       break;
5593c8
     }
5593c8
diff --git a/include/grub/util/install.h b/include/grub/util/install.h
1c6ba0
index 7df3191f47..cf4531e02b 100644
5593c8
--- a/include/grub/util/install.h
5593c8
+++ b/include/grub/util/install.h
5593c8
@@ -67,6 +67,9 @@
5593c8
       N_("SBAT metadata"), 0 },						\
5593c8
   { "disable-shim-lock", GRUB_INSTALL_OPTIONS_DISABLE_SHIM_LOCK, 0, 0,	\
5593c8
       N_("disable shim_lock verifier"), 0 },				\
5593c8
+  { "appended-signature-size", GRUB_INSTALL_OPTIONS_APPENDED_SIGNATURE_SIZE,\
5593c8
+    "SIZE", 0, N_("Add a note segment reserving SIZE bytes for an appended signature"), \
5593c8
+    1},                                                                 \
5593c8
   { "verbose", 'v', 0, 0,						\
5593c8
     N_("print verbose messages."), 1 }
5593c8
 
5593c8
@@ -128,7 +131,8 @@ enum grub_install_options {
5593c8
   GRUB_INSTALL_OPTIONS_INSTALL_CORE_COMPRESS,
5593c8
   GRUB_INSTALL_OPTIONS_DTB,
5593c8
   GRUB_INSTALL_OPTIONS_SBAT,
5593c8
-  GRUB_INSTALL_OPTIONS_DISABLE_SHIM_LOCK
5593c8
+  GRUB_INSTALL_OPTIONS_DISABLE_SHIM_LOCK,
5593c8
+  GRUB_INSTALL_OPTIONS_APPENDED_SIGNATURE_SIZE
5593c8
 };
5593c8
 
5593c8
 extern char *grub_install_source_directory;
5593c8
@@ -188,7 +192,7 @@ grub_install_generate_image (const char *dir, const char *prefix,
5593c8
 			     size_t npubkeys,
5593c8
 			     char *config_path,
5593c8
 			     const struct grub_install_image_target_desc *image_target,
5593c8
-			     int note,
5593c8
+			     int note, size_t appsig_size,
5593c8
 			     grub_compression_t comp, const char *dtb_file,
5593c8
 			     const char *sbat_path, const int disable_shim_lock);
5593c8
 
5593c8
diff --git a/include/grub/util/mkimage.h b/include/grub/util/mkimage.h
1c6ba0
index 3819a67441..6f1da89b9b 100644
5593c8
--- a/include/grub/util/mkimage.h
5593c8
+++ b/include/grub/util/mkimage.h
5593c8
@@ -51,12 +51,12 @@ grub_mkimage_load_image64 (const char *kernel_path,
5593c8
 			   const struct grub_install_image_target_desc *image_target);
5593c8
 void
5593c8
 grub_mkimage_generate_elf32 (const struct grub_install_image_target_desc *image_target,
5593c8
-			     int note, char **core_img, size_t *core_size,
5593c8
+			     int note, size_t appsig_size, char **core_img, size_t *core_size,
5593c8
 			     Elf32_Addr target_addr,
5593c8
 			     struct grub_mkimage_layout *layout);
5593c8
 void
5593c8
 grub_mkimage_generate_elf64 (const struct grub_install_image_target_desc *image_target,
5593c8
-			     int note, char **core_img, size_t *core_size,
5593c8
+			     int note, size_t appsig_size, char **core_img, size_t *core_size,
5593c8
 			     Elf64_Addr target_addr,
5593c8
 			     struct grub_mkimage_layout *layout);
5593c8