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

3efed6
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
3efed6
From: Rashmica Gupta <rashmica.g@gmail.com>
3efed6
Date: Thu, 11 Jun 2020 11:26:23 +1000
3efed6
Subject: [PATCH] Add suport for signing grub with an appended signature
3efed6
3efed6
Add infrastructure to allow firmware to verify the integrity of grub
3efed6
by use of a Linux-kernel-module-style appended signature. We initially
3efed6
target powerpc-ieee1275, but the code should be extensible to other
3efed6
platforms.
3efed6
3efed6
Usually these signatures are appended to a file without modifying the
3efed6
ELF file itself. (This is what the 'sign-file' tool does, for example.)
3efed6
The verifier loads the signed file from the file system and looks at the
3efed6
end of the file for the appended signature. However, on powerpc-ieee1275
3efed6
platforms, the bootloader is often stored directly in the PReP partition
3efed6
as raw bytes without a file-system. This makes determining the location
3efed6
of an appended signature more difficult.
3efed6
3efed6
To address this, we add a new ELF note.
3efed6
3efed6
The name field of shall be the string "Appended-Signature", zero-padded
3efed6
to 4 byte alignment. The type field shall be 0x41536967 (the ASCII values
3efed6
for the string "ASig"). It must be the final section in the ELF binary.
3efed6
3efed6
The description shall contain the appended signature structure as defined
3efed6
by the Linux kernel. The description will also be padded to be a multiple
3efed6
of 4 bytes. The padding shall be added before the appended signature
3efed6
structure (not at the end) so that the final bytes of a signed ELF file
3efed6
are the appended signature magic.
3efed6
3efed6
A subsequent patch documents how to create a grub core.img validly signed
3efed6
under this scheme.
3efed6
3efed6
Signed-off-by: Daniel Axtens <dja@axtens.net>
3efed6
Signed-off-by: Rashmica Gupta <rashmica.g@gmail.com>
3efed6
3efed6
---
3efed6
3efed6
You can experiment with this code with a patched version of SLOF
3efed6
that verifies these signatures. You can find one at:
3efed6
   https://github.com/daxtens/SLOF
3efed6
3efed6
I will be proposing this for inclusion in a future Power Architecture
3efed6
Platform Reference (PAPR).
3efed6
---
3efed6
 util/grub-install-common.c  | 16 +++++++++++++---
3efed6
 util/grub-mkimage.c         | 11 +++++++++++
3efed6
 util/grub-mkimagexx.c       | 39 ++++++++++++++++++++++++++++++++++++++-
3efed6
 util/mkimage.c              | 10 +++++-----
3efed6
 include/grub/util/install.h |  8 ++++++--
3efed6
 include/grub/util/mkimage.h |  4 ++--
3efed6
 6 files changed, 75 insertions(+), 13 deletions(-)
3efed6
3efed6
diff --git a/util/grub-install-common.c b/util/grub-install-common.c
3efed6
index cf993c059ad..561e671ff34 100644
3efed6
--- a/util/grub-install-common.c
3efed6
+++ b/util/grub-install-common.c
3efed6
@@ -303,10 +303,12 @@ handle_install_list (struct install_list *il, const char *val,
3efed6
 static char **pubkeys;
3efed6
 static size_t npubkeys;
3efed6
 static grub_compression_t compression;
3efed6
+static size_t appsig_size;
3efed6
 
3efed6
 int
3efed6
 grub_install_parse (int key, char *arg)
3efed6
 {
3efed6
+  const char *end;
3efed6
   switch (key)
3efed6
     {
3efed6
     case 'C':
3efed6
@@ -395,6 +397,12 @@ grub_install_parse (int key, char *arg)
3efed6
       grub_util_error (_("Unrecognized compression `%s'"), arg);
3efed6
     case GRUB_INSTALL_OPTIONS_GRUB_MKIMAGE:
3efed6
       return 1;
3efed6
+    case GRUB_INSTALL_OPTIONS_APPENDED_SIGNATURE_SIZE:
3efed6
+      grub_errno = 0;
3efed6
+      appsig_size = grub_strtol(arg, &end, 10);
3efed6
+      if (grub_errno)
3efed6
+        return 0;
3efed6
+      return 1;
3efed6
     default:
3efed6
       return 0;
3efed6
     }
3efed6
@@ -493,10 +501,12 @@ grub_install_make_image_wrap_file (const char *dir, const char *prefix,
3efed6
   grub_util_info ("grub-mkimage --directory '%s' --prefix '%s'"
3efed6
 		  " --output '%s' "
3efed6
 		  " --dtb '%s' "
3efed6
-		  "--format '%s' --compression '%s' %s %s\n",
3efed6
+		  "--format '%s' --compression '%s' "
3efed6
+		  "--appended-signature-size %zu %s %s\n",
3efed6
 		  dir, prefix,
3efed6
 		  outname, dtb ? : "", mkimage_target,
3efed6
-		  compnames[compression], note ? "--note" : "", s);
3efed6
+		  compnames[compression], appsig_size,
3efed6
+		  note ? "--note" : "", s);
3efed6
   free (s);
3efed6
 
3efed6
   tgt = grub_install_get_image_target (mkimage_target);
3efed6
@@ -506,7 +516,7 @@ grub_install_make_image_wrap_file (const char *dir, const char *prefix,
3efed6
   grub_install_generate_image (dir, prefix, fp, outname,
3efed6
 			       modules.entries, memdisk_path,
3efed6
 			       pubkeys, npubkeys, config_path, tgt,
3efed6
-			       note, compression, dtb);
3efed6
+			       note, appsig_size, compression, dtb);
3efed6
   while (dc--)
3efed6
     grub_install_pop_module ();
3efed6
 }
3efed6
diff --git a/util/grub-mkimage.c b/util/grub-mkimage.c
3efed6
index 98d24cc06ea..65a015d8a04 100644
3efed6
--- a/util/grub-mkimage.c
3efed6
+++ b/util/grub-mkimage.c
3efed6
@@ -82,6 +82,7 @@ static struct argp_option options[] = {
3efed6
   {"format",  'O', N_("FORMAT"), 0, 0, 0},
3efed6
   {"compression",  'C', "(xz|none|auto)", 0, N_("choose the compression to use for core image"), 0},
3efed6
   {"verbose",     'v', 0,      0, N_("print verbose messages."), 0},
3efed6
+  {"appended-signature-size", 'S', N_("SIZE"), 0, N_("Add a note segment reserving SIZE bytes for an appended signature"), 0},
3efed6
   { 0, 0, 0, 0, 0, 0 }
3efed6
 };
3efed6
 
3efed6
@@ -124,6 +125,7 @@ struct arguments
3efed6
   char *font;
3efed6
   char *config;
3efed6
   int note;
3efed6
+  size_t appsig_size;
3efed6
   const struct grub_install_image_target_desc *image_target;
3efed6
   grub_compression_t comp;
3efed6
 };
3efed6
@@ -134,6 +136,7 @@ argp_parser (int key, char *arg, struct argp_state *state)
3efed6
   /* Get the input argument from argp_parse, which we
3efed6
      know is a pointer to our arguments structure. */
3efed6
   struct arguments *arguments = state->input;
3efed6
+  const char* end;
3efed6
 
3efed6
   switch (key)
3efed6
     {
3efed6
@@ -166,6 +169,13 @@ argp_parser (int key, char *arg, struct argp_state *state)
3efed6
       arguments->note = 1;
3efed6
       break;
3efed6
 
3efed6
+    case 'S':
3efed6
+      grub_errno = 0;
3efed6
+      arguments->appsig_size = grub_strtol(arg, &end, 10);
3efed6
+      if (grub_errno)
3efed6
+        return 0;
3efed6
+      break;
3efed6
+
3efed6
     case 'm':
3efed6
       if (arguments->memdisk)
3efed6
 	free (arguments->memdisk);
3efed6
@@ -309,6 +319,7 @@ main (int argc, char *argv[])
3efed6
 			       arguments.memdisk, arguments.pubkeys,
3efed6
 			       arguments.npubkeys, arguments.config,
3efed6
 			       arguments.image_target, arguments.note,
3efed6
+			       arguments.appsig_size,
3efed6
 			       arguments.comp, arguments.dtb);
3efed6
 
3efed6
   grub_util_file_sync  (fp);
3efed6
diff --git a/util/grub-mkimagexx.c b/util/grub-mkimagexx.c
3efed6
index f9aa1a033b5..1bb5eb84c14 100644
3efed6
--- a/util/grub-mkimagexx.c
3efed6
+++ b/util/grub-mkimagexx.c
3efed6
@@ -82,6 +82,15 @@ struct grub_ieee1275_note
3efed6
   struct grub_ieee1275_note_desc descriptor;
3efed6
 };
3efed6
 
3efed6
+#define GRUB_APPENDED_SIGNATURE_NOTE_NAME "Appended-Signature"
3efed6
+#define GRUB_APPENDED_SIGNATURE_NOTE_TYPE 0x41536967 /* "ASig" */
3efed6
+
3efed6
+struct grub_appended_signature_note
3efed6
+{
3efed6
+  Elf32_Nhdr header;
3efed6
+  char name[ALIGN_UP(sizeof (GRUB_APPENDED_SIGNATURE_NOTE_NAME), 4)];
3efed6
+};
3efed6
+
3efed6
 #define GRUB_XEN_NOTE_NAME "Xen"
3efed6
 
3efed6
 struct fixup_block_list
3efed6
@@ -205,7 +214,7 @@ grub_arm_reloc_jump24 (grub_uint32_t *target, Elf32_Addr sym_addr)
3efed6
 
3efed6
 void
3efed6
 SUFFIX (grub_mkimage_generate_elf) (const struct grub_install_image_target_desc *image_target,
3efed6
-				    int note, char **core_img, size_t *core_size,
3efed6
+				    int note, size_t appsig_size, char **core_img, size_t *core_size,
3efed6
 				    Elf_Addr target_addr,
3efed6
 				    struct grub_mkimage_layout *layout)
3efed6
 {
3efed6
@@ -219,6 +228,12 @@ SUFFIX (grub_mkimage_generate_elf) (const struct grub_install_image_target_desc
3efed6
   int shnum = 4;
3efed6
   int string_size = sizeof (".text") + sizeof ("mods") + 1;
3efed6
 
3efed6
+  if (appsig_size)
3efed6
+    {
3efed6
+      phnum++;
3efed6
+      footer_size += ALIGN_UP(sizeof (struct grub_appended_signature_note) + appsig_size, 4);
3efed6
+    }
3efed6
+
3efed6
   if (image_target->id != IMAGE_LOONGSON_ELF)
3efed6
     phnum += 2;
3efed6
 
3efed6
@@ -449,6 +464,28 @@ SUFFIX (grub_mkimage_generate_elf) (const struct grub_install_image_target_desc
3efed6
       phdr->p_offset = grub_host_to_target32 (header_size + program_size);
3efed6
     }
3efed6
 
3efed6
+  if (appsig_size) {
3efed6
+    int note_size = ALIGN_UP(sizeof (struct grub_appended_signature_note) + appsig_size, 4);
3efed6
+    struct grub_appended_signature_note *note_ptr = (struct grub_appended_signature_note *)
3efed6
+      (elf_img + program_size + header_size + (note ? sizeof (struct grub_ieee1275_note) : 0));
3efed6
+
3efed6
+    note_ptr->header.n_namesz = grub_host_to_target32 (sizeof (GRUB_APPENDED_SIGNATURE_NOTE_NAME));
3efed6
+    /* needs to sit at the end, so we round this up and sign some zero padding */
3efed6
+    note_ptr->header.n_descsz = grub_host_to_target32 (ALIGN_UP(appsig_size, 4));
3efed6
+    note_ptr->header.n_type = grub_host_to_target32 (GRUB_APPENDED_SIGNATURE_NOTE_TYPE);
3efed6
+    strcpy (note_ptr->name, GRUB_APPENDED_SIGNATURE_NOTE_NAME);
3efed6
+
3efed6
+    phdr++;
3efed6
+    phdr->p_type = grub_host_to_target32 (PT_NOTE);
3efed6
+    phdr->p_flags = grub_host_to_target32 (PF_R);
3efed6
+    phdr->p_align = grub_host_to_target32 (image_target->voidp_sizeof);
3efed6
+    phdr->p_vaddr = 0;
3efed6
+    phdr->p_paddr = 0;
3efed6
+    phdr->p_filesz = grub_host_to_target32 (note_size);
3efed6
+    phdr->p_memsz = 0;
3efed6
+    phdr->p_offset = grub_host_to_target32 (header_size + program_size + (note ? sizeof (struct grub_ieee1275_note) : 0));
3efed6
+  }
3efed6
+
3efed6
   {
3efed6
     char *str_start = (elf_img + sizeof (*ehdr) + phnum * sizeof (*phdr)
3efed6
 		       + shnum * sizeof (*shdr));
3efed6
diff --git a/util/mkimage.c b/util/mkimage.c
3efed6
index e22d82afa61..a81120f26be 100644
3efed6
--- a/util/mkimage.c
3efed6
+++ b/util/mkimage.c
3efed6
@@ -777,7 +777,7 @@ grub_install_generate_image (const char *dir, const char *prefix,
3efed6
 			     char *memdisk_path, char **pubkey_paths,
3efed6
 			     size_t npubkeys, char *config_path,
3efed6
 			     const struct grub_install_image_target_desc *image_target,
3efed6
-			     int note, grub_compression_t comp, const char *dtb_path)
3efed6
+			     int note, size_t appsig_size, grub_compression_t comp, const char *dtb_path)
3efed6
 {
3efed6
   char *kernel_img, *core_img;
3efed6
   size_t total_module_size, core_size;
3efed6
@@ -1694,11 +1694,11 @@ grub_install_generate_image (const char *dir, const char *prefix,
3efed6
 	else
3efed6
 	  target_addr = image_target->link_addr;
3efed6
 	if (image_target->voidp_sizeof == 4)
3efed6
-	  grub_mkimage_generate_elf32 (image_target, note, &core_img, &core_size,
3efed6
-				       target_addr, &layout);
3efed6
+	  grub_mkimage_generate_elf32 (image_target, note, appsig_size, &core_img,
3efed6
+				       &core_size, target_addr, &layout);
3efed6
 	else
3efed6
-	  grub_mkimage_generate_elf64 (image_target, note, &core_img, &core_size,
3efed6
-				       target_addr, &layout);
3efed6
+	  grub_mkimage_generate_elf64 (image_target, note, appsig_size, &core_img,
3efed6
+				       &core_size, target_addr, &layout);
3efed6
       }
3efed6
       break;
3efed6
     }
3efed6
diff --git a/include/grub/util/install.h b/include/grub/util/install.h
3efed6
index 0dba8b67f93..ba5e6a2ea8f 100644
3efed6
--- a/include/grub/util/install.h
3efed6
+++ b/include/grub/util/install.h
3efed6
@@ -63,6 +63,9 @@
3efed6
     /* TRANSLATORS: "embed" is a verb (command description).  "*/	\
3efed6
   { "pubkey",   'k', N_("FILE"), 0,					\
3efed6
       N_("embed FILE as public key for signature checking"), 0},	\
3efed6
+  { "appended-signature-size", GRUB_INSTALL_OPTIONS_APPENDED_SIGNATURE_SIZE,\
3efed6
+    "SIZE", 0, N_("Add a note segment reserving SIZE bytes for an appended signature"), \
3efed6
+    1},                                                                 \
3efed6
   { "verbose", 'v', 0, 0,						\
3efed6
     N_("print verbose messages."), 1 }
3efed6
 
3efed6
@@ -119,7 +122,8 @@ enum grub_install_options {
3efed6
   GRUB_INSTALL_OPTIONS_THEMES_DIRECTORY,
3efed6
   GRUB_INSTALL_OPTIONS_GRUB_MKIMAGE,
3efed6
   GRUB_INSTALL_OPTIONS_INSTALL_CORE_COMPRESS,
3efed6
-  GRUB_INSTALL_OPTIONS_DTB
3efed6
+  GRUB_INSTALL_OPTIONS_DTB,
3efed6
+  GRUB_INSTALL_OPTIONS_APPENDED_SIGNATURE_SIZE
3efed6
 };
3efed6
 
3efed6
 extern char *grub_install_source_directory;
3efed6
@@ -179,7 +183,7 @@ grub_install_generate_image (const char *dir, const char *prefix,
3efed6
 			     size_t npubkeys,
3efed6
 			     char *config_path,
3efed6
 			     const struct grub_install_image_target_desc *image_target,
3efed6
-			     int note,
3efed6
+			     int note, size_t appsig_size,
3efed6
 			     grub_compression_t comp, const char *dtb_file);
3efed6
 
3efed6
 const struct grub_install_image_target_desc *
3efed6
diff --git a/include/grub/util/mkimage.h b/include/grub/util/mkimage.h
3efed6
index b3a5ca132bc..cef7fffa7ae 100644
3efed6
--- a/include/grub/util/mkimage.h
3efed6
+++ b/include/grub/util/mkimage.h
3efed6
@@ -50,12 +50,12 @@ grub_mkimage_load_image64 (const char *kernel_path,
3efed6
 			   const struct grub_install_image_target_desc *image_target);
3efed6
 void
3efed6
 grub_mkimage_generate_elf32 (const struct grub_install_image_target_desc *image_target,
3efed6
-			     int note, char **core_img, size_t *core_size,
3efed6
+			     int note, size_t appsig_size, char **core_img, size_t *core_size,
3efed6
 			     Elf32_Addr target_addr,
3efed6
 			     struct grub_mkimage_layout *layout);
3efed6
 void
3efed6
 grub_mkimage_generate_elf64 (const struct grub_install_image_target_desc *image_target,
3efed6
-			     int note, char **core_img, size_t *core_size,
3efed6
+			     int note, size_t appsig_size, char **core_img, size_t *core_size,
3efed6
 			     Elf64_Addr target_addr,
3efed6
 			     struct grub_mkimage_layout *layout);
3efed6