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

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