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

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