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

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