All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/3] Add support for signing grub with an appended signature
@ 2020-08-21  2:37 Daniel Axtens
  2020-08-21  2:37 ` [PATCH 1/3] Add suport " Daniel Axtens
                   ` (3 more replies)
  0 siblings, 4 replies; 8+ messages in thread
From: Daniel Axtens @ 2020-08-21  2:37 UTC (permalink / raw)
  To: grub-devel; +Cc: rashmica.g, alastair, Daniel Axtens

Part of a secure boot chain is allowing boot firmware to verify the
grub core.img. For UEFI platforms, this is done by signing the PE
binary with a tool like pesign or sb-sign. However, for platforms that
don't implement UEFI, an alternative scheme is required.

These patches provide some infrastructure and documentation for
signing grub's core.img with a Linux-kernel-module style appended
signature.

Because some platforms, such as powerpc-ieee1275, load grub from a raw
disk partition rather than a filesystem, we extend grub-install to add
an ELF note that allows us to specify the size and location of the
signature.

More details are in patch 1, including a link to an open-source firmware
capable of verifying a grub image signed this way.

Daniel Axtens (2):
  docs/grub: Document signing grub under UEFI
  docs/grub: Document signing grub with an appended signature

Rashmica Gupta (1):
  Add suport for signing grub with an appended signature

 docs/grub.texi              | 64 ++++++++++++++++++++++++++++++++++++-
 include/grub/util/install.h |  8 +++--
 include/grub/util/mkimage.h |  4 +--
 util/grub-install-common.c  | 16 ++++++++--
 util/grub-mkimage.c         | 11 +++++++
 util/grub-mkimagexx.c       | 39 +++++++++++++++++++++-
 util/mkimage.c              | 10 +++---
 7 files changed, 138 insertions(+), 14 deletions(-)

-- 
2.25.1



^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH 1/3] Add suport for signing grub with an appended signature
  2020-08-21  2:37 [PATCH 0/3] Add support for signing grub with an appended signature Daniel Axtens
@ 2020-08-21  2:37 ` Daniel Axtens
  2020-08-21  2:37 ` [PATCH 2/3] docs/grub: Document signing grub under UEFI Daniel Axtens
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 8+ messages in thread
From: Daniel Axtens @ 2020-08-21  2:37 UTC (permalink / raw)
  To: grub-devel; +Cc: rashmica.g, alastair, Daniel Axtens

From: Rashmica Gupta <rashmica.g@gmail.com>

Add infrastructure to allow firmware to verify the integrity of grub
by use of a Linux-kernel-module-style appended signature. We initially
target powerpc-ieee1275, but the code should be extensible to other
platforms.

Usually these signatures are appended to a file without modifying the
ELF file itself. (This is what the 'sign-file' tool does, for example.)
The verifier loads the signed file from the file system and looks at the
end of the file for the appended signature. However, on powerpc-ieee1275
platforms, the bootloader is often stored directly in the PReP partition
as raw bytes without a file-system. This makes determining the location
of an appended signature more difficult.

To address this, we add a new ELF note.

The name field of shall be the string "Appended-Signature", zero-padded
to 4 byte alignment. The type field shall be 0x41536967 (the ASCII values
for the string "ASig"). It must be the final section in the ELF binary.

The description shall contain the appended signature structure as defined
by the Linux kernel. The description will also be padded to be a multiple
of 4 bytes. The padding shall be added before the appended signature
structure (not at the end) so that the final bytes of a signed ELF file
are the appended signature magic.

A subsequent patch documents how to create a grub core.img validly signed
under this scheme.

Signed-off-by: Daniel Axtens <dja@axtens.net>
Signed-off-by: Rashmica Gupta <rashmica.g@gmail.com>

---

You can experiment with this code with a patched version of SLOF
that verifies these signatures. You can find one at:
   https://github.com/daxtens/SLOF

I will be proposing the ELF note details for inclusion in a future
Power Architecture Platform Reference (PAPR).

---
 include/grub/util/install.h |  8 ++++++--
 include/grub/util/mkimage.h |  4 ++--
 util/grub-install-common.c  | 16 ++++++++++++---
 util/grub-mkimage.c         | 11 +++++++++++
 util/grub-mkimagexx.c       | 39 ++++++++++++++++++++++++++++++++++++-
 util/mkimage.c              | 10 +++++-----
 6 files changed, 75 insertions(+), 13 deletions(-)

diff --git a/include/grub/util/install.h b/include/grub/util/install.h
index 2631b1074513..eb1b83b6d946 100644
--- a/include/grub/util/install.h
+++ b/include/grub/util/install.h
@@ -63,6 +63,9 @@
     /* TRANSLATORS: "embed" is a verb (command description).  "*/	\
   { "pubkey",   'k', N_("FILE"), 0,					\
       N_("embed FILE as public key for signature checking"), 0},	\
+  { "appended-signature-size", GRUB_INSTALL_OPTIONS_APPENDED_SIGNATURE_SIZE,\
+    "SIZE", 0, N_("Add a note segment reserving SIZE bytes for an appended signature"), \
+    1},                                                                 \
   { "verbose", 'v', 0, 0,						\
     N_("print verbose messages."), 1 }
 
@@ -122,7 +125,8 @@ enum grub_install_options {
   GRUB_INSTALL_OPTIONS_THEMES_DIRECTORY,
   GRUB_INSTALL_OPTIONS_GRUB_MKIMAGE,
   GRUB_INSTALL_OPTIONS_INSTALL_CORE_COMPRESS,
-  GRUB_INSTALL_OPTIONS_DTB
+  GRUB_INSTALL_OPTIONS_DTB,
+  GRUB_INSTALL_OPTIONS_APPENDED_SIGNATURE_SIZE
 };
 
 extern char *grub_install_source_directory;
@@ -182,7 +186,7 @@ grub_install_generate_image (const char *dir, const char *prefix,
 			     size_t npubkeys,
 			     char *config_path,
 			     const struct grub_install_image_target_desc *image_target,
-			     int note,
+			     int note, size_t appsig_size,
 			     grub_compression_t comp, const char *dtb_file);
 
 const struct grub_install_image_target_desc *
diff --git a/include/grub/util/mkimage.h b/include/grub/util/mkimage.h
index ba9f568f6926..2000d6fbdf1e 100644
--- a/include/grub/util/mkimage.h
+++ b/include/grub/util/mkimage.h
@@ -50,12 +50,12 @@ grub_mkimage_load_image64 (const char *kernel_path,
 			   const struct grub_install_image_target_desc *image_target);
 void
 grub_mkimage_generate_elf32 (const struct grub_install_image_target_desc *image_target,
-			     int note, char **core_img, size_t *core_size,
+			     int note, size_t appsig_size, char **core_img, size_t *core_size,
 			     Elf32_Addr target_addr,
 			     struct grub_mkimage_layout *layout);
 void
 grub_mkimage_generate_elf64 (const struct grub_install_image_target_desc *image_target,
-			     int note, char **core_img, size_t *core_size,
+			     int note, size_t appsig_size, char **core_img, size_t *core_size,
 			     Elf64_Addr target_addr,
 			     struct grub_mkimage_layout *layout);
 
diff --git a/util/grub-install-common.c b/util/grub-install-common.c
index ca0ac612ac51..e9b75d6f1fcf 100644
--- a/util/grub-install-common.c
+++ b/util/grub-install-common.c
@@ -308,10 +308,12 @@ handle_install_list (struct install_list *il, const char *val,
 static char **pubkeys;
 static size_t npubkeys;
 static grub_compression_t compression;
+static size_t appsig_size;
 
 int
 grub_install_parse (int key, char *arg)
 {
+  const char *end;
   switch (key)
     {
     case 'C':
@@ -400,6 +402,12 @@ grub_install_parse (int key, char *arg)
       grub_util_error (_("Unrecognized compression `%s'"), arg);
     case GRUB_INSTALL_OPTIONS_GRUB_MKIMAGE:
       return 1;
+    case GRUB_INSTALL_OPTIONS_APPENDED_SIGNATURE_SIZE:
+      grub_errno = 0;
+      appsig_size = grub_strtol(arg, &end, 10);
+      if (grub_errno)
+        return 0;
+      return 1;
     default:
       return 0;
     }
@@ -498,10 +506,12 @@ grub_install_make_image_wrap_file (const char *dir, const char *prefix,
   grub_util_info ("grub-mkimage --directory '%s' --prefix '%s'"
 		  " --output '%s' "
 		  " --dtb '%s' "
-		  "--format '%s' --compression '%s' %s %s\n",
+		  "--format '%s' --compression '%s' "
+		  "--appended-signature-size %zu %s %s\n",
 		  dir, prefix,
 		  outname, dtb ? : "", mkimage_target,
-		  compnames[compression], note ? "--note" : "", s);
+		  compnames[compression], appsig_size,
+		  note ? "--note" : "", s);
   free (s);
 
   tgt = grub_install_get_image_target (mkimage_target);
@@ -511,7 +521,7 @@ grub_install_make_image_wrap_file (const char *dir, const char *prefix,
   grub_install_generate_image (dir, prefix, fp, outname,
 			       modules.entries, memdisk_path,
 			       pubkeys, npubkeys, config_path, tgt,
-			       note, compression, dtb);
+			       note, appsig_size, compression, dtb);
   while (dc--)
     grub_install_pop_module ();
 }
diff --git a/util/grub-mkimage.c b/util/grub-mkimage.c
index 912564e3622f..c1e07c70dc7e 100644
--- a/util/grub-mkimage.c
+++ b/util/grub-mkimage.c
@@ -82,6 +82,7 @@ static struct argp_option options[] = {
   {"format",  'O', N_("FORMAT"), 0, 0, 0},
   {"compression",  'C', "(xz|none|auto)", 0, N_("choose the compression to use for core image"), 0},
   {"verbose",     'v', 0,      0, N_("print verbose messages."), 0},
+  {"appended-signature-size", 's', N_("SIZE"), 0, N_("Add a note segment reserving SIZE bytes for an appended signature"), 0},
   { 0, 0, 0, 0, 0, 0 }
 };
 
@@ -124,6 +125,7 @@ struct arguments
   char *font;
   char *config;
   int note;
+  size_t appsig_size;
   const struct grub_install_image_target_desc *image_target;
   grub_compression_t comp;
 };
@@ -134,6 +136,7 @@ argp_parser (int key, char *arg, struct argp_state *state)
   /* Get the input argument from argp_parse, which we
      know is a pointer to our arguments structure. */
   struct arguments *arguments = state->input;
+  const char* end;
 
   switch (key)
     {
@@ -166,6 +169,13 @@ argp_parser (int key, char *arg, struct argp_state *state)
       arguments->note = 1;
       break;
 
+    case 's':
+      grub_errno = 0;
+      arguments->appsig_size = grub_strtol(arg, &end, 10);
+      if (grub_errno)
+        return 0;
+      break;
+
     case 'm':
       if (arguments->memdisk)
 	free (arguments->memdisk);
@@ -309,6 +319,7 @@ main (int argc, char *argv[])
 			       arguments.memdisk, arguments.pubkeys,
 			       arguments.npubkeys, arguments.config,
 			       arguments.image_target, arguments.note,
+			       arguments.appsig_size,
 			       arguments.comp, arguments.dtb);
 
   if (grub_util_file_sync (fp) < 0)
diff --git a/util/grub-mkimagexx.c b/util/grub-mkimagexx.c
index ab6dfab79242..3bfed4369fd3 100644
--- a/util/grub-mkimagexx.c
+++ b/util/grub-mkimagexx.c
@@ -84,6 +84,15 @@ struct grub_ieee1275_note
   struct grub_ieee1275_note_desc descriptor;
 };
 
+#define GRUB_APPENDED_SIGNATURE_NOTE_NAME "Appended-Signature"
+#define GRUB_APPENDED_SIGNATURE_NOTE_TYPE 0x41536967 /* "ASig" */
+
+struct grub_appended_signature_note
+{
+  Elf32_Nhdr header;
+  char name[ALIGN_UP(sizeof (GRUB_APPENDED_SIGNATURE_NOTE_NAME), 4)];
+};
+
 #define GRUB_XEN_NOTE_NAME "Xen"
 
 struct fixup_block_list
@@ -207,7 +216,7 @@ grub_arm_reloc_jump24 (grub_uint32_t *target, Elf32_Addr sym_addr)
 
 void
 SUFFIX (grub_mkimage_generate_elf) (const struct grub_install_image_target_desc *image_target,
-				    int note, char **core_img, size_t *core_size,
+				    int note, size_t appsig_size, char **core_img, size_t *core_size,
 				    Elf_Addr target_addr,
 				    struct grub_mkimage_layout *layout)
 {
@@ -221,6 +230,12 @@ SUFFIX (grub_mkimage_generate_elf) (const struct grub_install_image_target_desc
   int shnum = 4;
   int string_size = sizeof (".text") + sizeof ("mods") + 1;
 
+  if (appsig_size)
+    {
+      phnum++;
+      footer_size += ALIGN_UP(sizeof (struct grub_appended_signature_note) + appsig_size, 4);
+    }
+
   if (image_target->id != IMAGE_LOONGSON_ELF)
     phnum += 2;
 
@@ -484,6 +499,28 @@ SUFFIX (grub_mkimage_generate_elf) (const struct grub_install_image_target_desc
       phdr->p_offset = grub_host_to_target32 (header_size + program_size);
     }
 
+  if (appsig_size) {
+    int note_size = ALIGN_UP(sizeof (struct grub_appended_signature_note) + appsig_size, 4);
+    struct grub_appended_signature_note *note_ptr = (struct grub_appended_signature_note *)
+      (elf_img + program_size + header_size + (note ? sizeof (struct grub_ieee1275_note) : 0));
+
+    note_ptr->header.n_namesz = grub_host_to_target32 (sizeof (GRUB_APPENDED_SIGNATURE_NOTE_NAME));
+    /* needs to sit at the end, so we round this up and sign some zero padding */
+    note_ptr->header.n_descsz = grub_host_to_target32 (ALIGN_UP(appsig_size, 4));
+    note_ptr->header.n_type = grub_host_to_target32 (GRUB_APPENDED_SIGNATURE_NOTE_TYPE);
+    strcpy (note_ptr->name, GRUB_APPENDED_SIGNATURE_NOTE_NAME);
+
+    phdr++;
+    phdr->p_type = grub_host_to_target32 (PT_NOTE);
+    phdr->p_flags = grub_host_to_target32 (PF_R);
+    phdr->p_align = grub_host_to_target32 (image_target->voidp_sizeof);
+    phdr->p_vaddr = 0;
+    phdr->p_paddr = 0;
+    phdr->p_filesz = grub_host_to_target32 (note_size);
+    phdr->p_memsz = 0;
+    phdr->p_offset = grub_host_to_target32 (header_size + program_size + (note ? sizeof (struct grub_ieee1275_note) : 0));
+  }
+
   {
     char *str_start = (elf_img + sizeof (*ehdr) + phnum * sizeof (*phdr)
 		       + shnum * sizeof (*shdr));
diff --git a/util/mkimage.c b/util/mkimage.c
index 37d6249f16b3..bd06968deccb 100644
--- a/util/mkimage.c
+++ b/util/mkimage.c
@@ -822,7 +822,7 @@ grub_install_generate_image (const char *dir, const char *prefix,
 			     char *memdisk_path, char **pubkey_paths,
 			     size_t npubkeys, char *config_path,
 			     const struct grub_install_image_target_desc *image_target,
-			     int note, grub_compression_t comp, const char *dtb_path)
+			     int note, size_t appsig_size, grub_compression_t comp, const char *dtb_path)
 {
   char *kernel_img, *core_img;
   size_t total_module_size, core_size;
@@ -1742,11 +1742,11 @@ grub_install_generate_image (const char *dir, const char *prefix,
 	else
 	  target_addr = image_target->link_addr;
 	if (image_target->voidp_sizeof == 4)
-	  grub_mkimage_generate_elf32 (image_target, note, &core_img, &core_size,
-				       target_addr, &layout);
+	  grub_mkimage_generate_elf32 (image_target, note, appsig_size, &core_img,
+				       &core_size, target_addr, &layout);
 	else
-	  grub_mkimage_generate_elf64 (image_target, note, &core_img, &core_size,
-				       target_addr, &layout);
+	  grub_mkimage_generate_elf64 (image_target, note, appsig_size, &core_img,
+				       &core_size, target_addr, &layout);
       }
       break;
     }
-- 
2.25.1



^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 2/3] docs/grub: Document signing grub under UEFI
  2020-08-21  2:37 [PATCH 0/3] Add support for signing grub with an appended signature Daniel Axtens
  2020-08-21  2:37 ` [PATCH 1/3] Add suport " Daniel Axtens
@ 2020-08-21  2:37 ` Daniel Axtens
  2020-08-21  2:37 ` [PATCH 3/3] docs/grub: Document signing grub with an appended signature Daniel Axtens
  2020-09-23 15:11 ` [PATCH 0/3] Add support for " Daniel Axtens
  3 siblings, 0 replies; 8+ messages in thread
From: Daniel Axtens @ 2020-08-21  2:37 UTC (permalink / raw)
  To: grub-devel; +Cc: rashmica.g, alastair, Daniel Axtens

Before adding information about how grub is signed with an appended
signature scheme, it's worth adding some information about how it
can currently be signed for UEFI.

Signed-off-by: Daniel Axtens <dja@axtens.net>
---
 docs/grub.texi | 22 +++++++++++++++++++++-
 1 file changed, 21 insertions(+), 1 deletion(-)

diff --git a/docs/grub.texi b/docs/grub.texi
index 1ce9993a53fc..35da48456d9e 100644
--- a/docs/grub.texi
+++ b/docs/grub.texi
@@ -5736,6 +5736,7 @@ environment variables and commands are listed in the same order.
 * Using digital signatures::         Booting digitally signed code
 * UEFI secure boot and shim::        Booting digitally signed PE files
 * Measured Boot::                    Measuring boot components
+* Signing GRUB itself::              Ensuring the integrity of the GRUB core image
 @end menu
 
 @node Authentication and authorisation
@@ -5814,7 +5815,7 @@ commands.
 
 GRUB's @file{core.img} can optionally provide enforcement that all files
 subsequently read from disk are covered by a valid digital signature.
-This document does @strong{not} cover how to ensure that your
+This section does @strong{not} cover how to ensure that your
 platform's firmware (e.g., Coreboot) validates @file{core.img}.
 
 If environment variable @code{check_signatures}
@@ -5950,6 +5951,25 @@ into @file{core.img} in order to avoid a potential gap in measurement between
 
 Measured boot is currently only supported on EFI platforms.
 
+@node Signing GRUB itself
+@section Signing GRUB itself
+
+To ensure a complete secure-boot chain, there must be a way for the code that
+loads GRUB to verify the integrity of the core image.
+
+This is ultimately platform-specific and individual platforms can define their
+own mechanisms. However, there are general-purpose mechanisms that can be used
+with GRUB.
+
+@section Signing GRUB for UEFI secure boot
+
+On UEFI platforms, @file{core.img} is a PE binary. Therefore, it can be signed
+with a tool such as @command{pesign} or @command{sbsign}. Refer to the
+suggestions in @pxref{UEFI secure boot and shim} to ensure that the final
+image works under UEFI secure boot and can maintain the secure-boot chain. It
+will also be necessary to enrol the public key used into a relevant firmware
+key database.
+
 @node Platform limitations
 @chapter Platform limitations
 
-- 
2.25.1



^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 3/3] docs/grub: Document signing grub with an appended signature
  2020-08-21  2:37 [PATCH 0/3] Add support for signing grub with an appended signature Daniel Axtens
  2020-08-21  2:37 ` [PATCH 1/3] Add suport " Daniel Axtens
  2020-08-21  2:37 ` [PATCH 2/3] docs/grub: Document signing grub under UEFI Daniel Axtens
@ 2020-08-21  2:37 ` Daniel Axtens
  2020-10-20  3:54   ` Michael Chang
  2020-09-23 15:11 ` [PATCH 0/3] Add support for " Daniel Axtens
  3 siblings, 1 reply; 8+ messages in thread
From: Daniel Axtens @ 2020-08-21  2:37 UTC (permalink / raw)
  To: grub-devel; +Cc: rashmica.g, alastair, Daniel Axtens

Signing grub for firmware that verifies an appended signature is a
bit fiddly. I don't want people to have to figure it out from scratch
so document it here.

Signed-off-by: Daniel Axtens <dja@axtens.net>
---
 docs/grub.texi | 42 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 42 insertions(+)

diff --git a/docs/grub.texi b/docs/grub.texi
index 35da48456d9e..bbbe6c7e07bf 100644
--- a/docs/grub.texi
+++ b/docs/grub.texi
@@ -5970,6 +5970,48 @@ image works under UEFI secure boot and can maintain the secure-boot chain. It
 will also be necessary to enrol the public key used into a relevant firmware
 key database.
 
+@section Signing GRUB with an appended signature
+
+The @file{core.img} itself can be signed with a Linux kernel module-style
+appended signature.
+
+To support IEEE1275 platforms where the boot image is often loaded directly
+from a disk partition rather than from a file system, the @file{core.img}
+can specify the size and location of the appended signature with an ELF
+note added by @command{grub-install}.
+
+An image can be signed this way using the @command{sign-file} command from
+the Linux kernel:
+
+@example
+@group
+# grub.key is your private key and certificate.der is your public key
+
+# Determine the size of the appended signature. It depends on the signing
+# certificate and the hash algorithm
+touch empty
+sign-file SHA256 grub.key certificate.der empty empty.sig
+SIG_SIZE=`stat -c '%s' empty.sig`
+rm empty empty.sig
+
+# Build a grub image with $SIG_SIZE reserved for the signature
+grub-install --appended-signature-size $SIG_SIZE --modules="..." ...
+
+# Replace the reserved size with a signature:
+# cut off the last $SIG_SIZE bytes with truncate's minus modifier
+truncate -s -$SIG_SIZE /boot/grub/powerpc-ieee1275/core.elf core.elf.unsigned
+# sign the trimmed file with an appended signature, restoring the correct size
+sign-file SHA256 grub.key certificate.der core.elf.unsigned core.elf.signed
+
+# Don't forget to install the signed image as required
+# (e.g. on powerpc-ieee1275, to the PReP partition)
+@end group
+@end example
+
+As with UEFI secure boot, it is necessary to build in the required modules,
+or sign them separately.
+
+
 @node Platform limitations
 @chapter Platform limitations
 
-- 
2.25.1



^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [PATCH 0/3] Add support for signing grub with an appended signature
  2020-08-21  2:37 [PATCH 0/3] Add support for signing grub with an appended signature Daniel Axtens
                   ` (2 preceding siblings ...)
  2020-08-21  2:37 ` [PATCH 3/3] docs/grub: Document signing grub with an appended signature Daniel Axtens
@ 2020-09-23 15:11 ` Daniel Axtens
  3 siblings, 0 replies; 8+ messages in thread
From: Daniel Axtens @ 2020-09-23 15:11 UTC (permalink / raw)
  To: grub-devel, pjones, xnox; +Cc: rashmica.g, alastair

Hi,

> Part of a secure boot chain is allowing boot firmware to verify the
> grub core.img. For UEFI platforms, this is done by signing the PE
> binary with a tool like pesign or sb-sign. However, for platforms that
> don't implement UEFI, an alternative scheme is required.
>
> These patches provide some infrastructure and documentation for
> signing grub's core.img with a Linux-kernel-module style appended
> signature.
>
> Because some platforms, such as powerpc-ieee1275, load grub from a raw
> disk partition rather than a filesystem, we extend grub-install to add
> an ELF note that allows us to specify the size and location of the
> signature.

This is following up on the discussion out of Linux Plumbers [1].
Hopefully I've got the main question-askers, apologies if I've missed
anyone or sent emails to the wrong people. I'm also emailing grub-devel@
in hopes of catching anyone else who is interested.

One of the big requirements I heard was a desire to support key
rotation, for example by being able to embed multiple signatures in a
single signed grub.

I checked, and this is possible with appended signatures as I have
proposed them, because the size of the full signature block is known
when grub-mkimage is called.

You do have to do a bit of magic with openssl and sign-file, but it's
not particuarly bad. This demonstrates the openssl side and it's easy
to integrate with grub-mkimage:

# sign data/hello-world with both signing1 and signing2, placing just the
# PKCS#7 message in out/double-sig.p7s
openssl cms -sign -binary -in data/hello-world \
    -signer signing1.pem -inkey signing1.key \
    -signer signing2.pem -inkey signing2.key \
    -out out/double-sig.p7s -outform DER -noattr -md sha512

# append it to data/hello-world using sign-file's -s option, creating
# out/hello-world-sha512-2keys
../tools/sign-file -s out/double-sig.p7s sha512 /dev/null data/hello-world out/hello-world-sha512-2keys

# to verify, extract the cryptographic message with
# extract-module-sig.pl from the kernel source

./extract-module-sig.pl -s out/hello-world-sha512-2keys > out/hello-world-sha512-2keys.sig 2> /dev/null
if ! cmp out/double-sig.p7s out/hello-world-sha512-2keys.sig ; then
	echo "Input signature and data from extract-module-sig.pl -s do not agree!"
	exit 1;
fi

# openssl's verify requires that _both_ signatures are made with
# embedded certs which validate against a trusted CA
openssl cms -verify -binary -in out/hello-world-sha512-2keys.sig -inform der \
            -content hello-world -CAfile ca.pem -out /dev/null
if [ $? -ne 0 ]; then
	echo "OpenSSL failed to verify with both keys"
	exit 1
fi

For our application, firmware will allow a grub binary to boot if any
of the signatures in the PKCS#7 message match a key that is trusted by
firmware. This should allow keys to be rotated with firmware releases
without breaking backwards compatibility.

I've updated https://github.com/daxtens/SLOF to demonstrate this: if
any signature can be validated by a built-in key, it will pass
verification.



Another thing that was raised was the ability to make multiple
signatures separated in time, where the second signer didn't have
access to the private keys for the first signer. The example given was
for someone to sign a distro binary with a second set of keys
(e.g. specific keys for a data center) - then the binary would be
bootable on machines with distro keys, and also on machines that have
only the second set of keys.

This is not so easy. For grub, with the elf note, the data over which
the signature is made contains the size of the signature. To add a
signature would be to change the size of the signature stored in the
signed data. That would either break the old signature, or we would need
to make it not a true appended signature any more: rather than being a
'dumb' signature over everything before the start of the appended
signature data, it'd be more complex. We'd need to teach the signer and
verifier how to deal with that, and then we've thrown away the
advantages of appended signatures and reinvented many of the
complexities of Authenticode.

One thing we could potentially do without going down that route is to
include a quantity of 'blank space' for signatures - we could for
example always allocate a few kilobytes for signatures. The distro
signatures would take up the first part of the buffer, leaving space
for some for 'user' signatures.

We can get this to work with the appended-signature format "as is": we
specify how big the PKCS#7 message is, and if the message happens to be
smaller than the size we give, both openssl and mbedtls will just ignore
any trailing data.

This does at least kinda-sorta work, but OpenSSL's 'cms -resign' command
only works if we include signed attributes and at the moment our mbedtls
implementation cannot handle that. I don't think the PKCS#7 standard
mandates that behaviour, so maybe we can hack around it with the OpenSSL
C API. Or maybe we can extend mbedtls to handle signed
attributes. (eek!)

The concern I have is that this approach creates a big block of
arbitrary unsigned data in the grub binary. An attacker under our threat
model (root on the host) could put any data they like into that space. I
worry that in combination with some other vulernability, this could be
used to more easily pass useful data in to grub. However, maybe that's
not that much of a win for the attacker: if they are root they also have
complete control of grub.cfg and can instruct grub to do quite a bit as
it is.

I'm also not sure that the use-case is quite as likely with Power
systems vs x86 systems. But if I'm overthinking the security
implications of a blank space in the binary, it seems like we could get
it to work and I'd be happy to chase it up further.

Thoughts? (on or off-list is fine.)

Kind regards,
Daniel

[1] https://linuxplumbersconf.org/event/7/contributions/738/
    https://youtu.be/IJUNxHnopH4?t=537

> More details are in patch 1, including a link to an open-source firmware
> capable of verifying a grub image signed this way.
>
> Daniel Axtens (2):
>   docs/grub: Document signing grub under UEFI
>   docs/grub: Document signing grub with an appended signature
>
> Rashmica Gupta (1):
>   Add suport for signing grub with an appended signature
>
>  docs/grub.texi              | 64 ++++++++++++++++++++++++++++++++++++-
>  include/grub/util/install.h |  8 +++--
>  include/grub/util/mkimage.h |  4 +--
>  util/grub-install-common.c  | 16 ++++++++--
>  util/grub-mkimage.c         | 11 +++++++
>  util/grub-mkimagexx.c       | 39 +++++++++++++++++++++-
>  util/mkimage.c              | 10 +++---
>  7 files changed, 138 insertions(+), 14 deletions(-)
>
> -- 
> 2.25.1


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH 3/3] docs/grub: Document signing grub with an appended signature
  2020-08-21  2:37 ` [PATCH 3/3] docs/grub: Document signing grub with an appended signature Daniel Axtens
@ 2020-10-20  3:54   ` Michael Chang
  2020-10-20  4:51     ` Daniel Axtens
  0 siblings, 1 reply; 8+ messages in thread
From: Michael Chang @ 2020-10-20  3:54 UTC (permalink / raw)
  To: The development of GNU GRUB; +Cc: rashmica.g, alastair, Daniel Axtens

On Fri, Aug 21, 2020 at 12:37:20PM +1000, Daniel Axtens wrote:
> Signing grub for firmware that verifies an appended signature is a
> bit fiddly. I don't want people to have to figure it out from scratch
> so document it here.
> 
> Signed-off-by: Daniel Axtens <dja@axtens.net>
> ---
>  docs/grub.texi | 42 ++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 42 insertions(+)
> 
> diff --git a/docs/grub.texi b/docs/grub.texi
> index 35da48456d9e..bbbe6c7e07bf 100644
> --- a/docs/grub.texi
> +++ b/docs/grub.texi
> @@ -5970,6 +5970,48 @@ image works under UEFI secure boot and can maintain the secure-boot chain. It
>  will also be necessary to enrol the public key used into a relevant firmware
>  key database.
>  
> +@section Signing GRUB with an appended signature
> +
> +The @file{core.img} itself can be signed with a Linux kernel module-style
> +appended signature.
> +
> +To support IEEE1275 platforms where the boot image is often loaded directly
> +from a disk partition rather than from a file system, the @file{core.img}

Maybe `core.elf` should be used for embedded image on ieee1275 platform?
The core.img is more pc bios specific IMHO, and hence would be edited
on-the-fly during the grub-install/grub-bios-setup process for keeping
or adding some records, making it not a good example to the proposed
procedure here as the image on filesysetm and partition may differ.

> +can specify the size and location of the appended signature with an ELF
> +note added by @command{grub-install}.
> +
> +An image can be signed this way using the @command{sign-file} command from
> +the Linux kernel:
> +
> +@example
> +@group
> +# grub.key is your private key and certificate.der is your public key
> +
> +# Determine the size of the appended signature. It depends on the signing
> +# certificate and the hash algorithm
> +touch empty
> +sign-file SHA256 grub.key certificate.der empty empty.sig
> +SIG_SIZE=`stat -c '%s' empty.sig`
> +rm empty empty.sig
> +
> +# Build a grub image with $SIG_SIZE reserved for the signature
> +grub-install --appended-signature-size $SIG_SIZE --modules="..." ...
> +
> +# Replace the reserved size with a signature:
> +# cut off the last $SIG_SIZE bytes with truncate's minus modifier
> +truncate -s -$SIG_SIZE /boot/grub/powerpc-ieee1275/core.elf core.elf.unsigned
> +# sign the trimmed file with an appended signature, restoring the correct size
> +sign-file SHA256 grub.key certificate.der core.elf.unsigned core.elf.signed
> +
> +# Don't forget to install the signed image as required
> +# (e.g. on powerpc-ieee1275, to the PReP partition)

Could you please provide more indication on how to install the signed
image afterwards ? I suppose it is 'dd' for writing the core.elf.signed
to the PReP partition but not really sure that is correct.

It also looked to me that the entire process can be integrated to
grub-install so the user can get less hassle to setting it up. For that
matters we could work out new grub-install options to accept user's
private key and public key certicate to compose signed image with
appended signature and install it on the fly. Is there anything that
I could have missed here ?

Thanks,
Michael

> +@end group
> +@end example
> +
> +As with UEFI secure boot, it is necessary to build in the required modules,
> +or sign them separately.
> +
> +
>  @node Platform limitations
>  @chapter Platform limitations
>  
> -- 
> 2.25.1
> 
> 
> _______________________________________________
> Grub-devel mailing list
> Grub-devel@gnu.org
> https://lists.gnu.org/mailman/listinfo/grub-devel



^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH 3/3] docs/grub: Document signing grub with an appended signature
  2020-10-20  3:54   ` Michael Chang
@ 2020-10-20  4:51     ` Daniel Axtens
  2020-10-20  5:58       ` Michael Chang
  0 siblings, 1 reply; 8+ messages in thread
From: Daniel Axtens @ 2020-10-20  4:51 UTC (permalink / raw)
  To: Michael Chang, The development of GNU GRUB; +Cc: rashmica.g, alastair

Hi Michael,

>> +@section Signing GRUB with an appended signature
>> +
>> +The @file{core.img} itself can be signed with a Linux kernel module-style
>> +appended signature.
>> +
>> +To support IEEE1275 platforms where the boot image is often loaded directly
>> +from a disk partition rather than from a file system, the @file{core.img}
>
> Maybe `core.elf` should be used for embedded image on ieee1275 platform?
> The core.img is more pc bios specific IMHO, and hence would be edited
> on-the-fly during the grub-install/grub-bios-setup process for keeping
> or adding some records, making it not a good example to the proposed
> procedure here as the image on filesysetm and partition may differ.

Sure, I will change this in v2.

>> +can specify the size and location of the appended signature with an ELF
>> +note added by @command{grub-install}.
>> +
>> +An image can be signed this way using the @command{sign-file} command from
>> +the Linux kernel:
>> +
>> +@example
>> +@group
>> +# grub.key is your private key and certificate.der is your public key
>> +
>> +# Determine the size of the appended signature. It depends on the signing
>> +# certificate and the hash algorithm
>> +touch empty
>> +sign-file SHA256 grub.key certificate.der empty empty.sig
>> +SIG_SIZE=`stat -c '%s' empty.sig`
>> +rm empty empty.sig
>> +
>> +# Build a grub image with $SIG_SIZE reserved for the signature
>> +grub-install --appended-signature-size $SIG_SIZE --modules="..." ...
>> +
>> +# Replace the reserved size with a signature:
>> +# cut off the last $SIG_SIZE bytes with truncate's minus modifier
>> +truncate -s -$SIG_SIZE /boot/grub/powerpc-ieee1275/core.elf core.elf.unsigned
>> +# sign the trimmed file with an appended signature, restoring the correct size
>> +sign-file SHA256 grub.key certificate.der core.elf.unsigned core.elf.signed
>> +
>> +# Don't forget to install the signed image as required
>> +# (e.g. on powerpc-ieee1275, to the PReP partition)
>
> Could you please provide more indication on how to install the signed
> image afterwards ? I suppose it is 'dd' for writing the core.elf.signed
> to the PReP partition but not really sure that is correct.

At the moment, yes, dd.

Firmware loads raw bytes off the PReP partition and expects them to be a
32-bit BE ELF binary. Therefore any method that can put raw bytes on
disk will work, and dd is the classic tool for the job.

I'll improve this for v2 on the basis of how the discussions on Michal's
proposal to do away with the ELF note go.

> It also looked to me that the entire process can be integrated to
> grub-install so the user can get less hassle to setting it up. For that
> matters we could work out new grub-install options to accept user's
> private key and public key certicate to compose signed image with
> appended signature and install it on the fly. Is there anything that
> I could have missed here ?

We'd need to add a dependency on OpenSSL (or maybe GNUTLS) to grub-install,
as there's no support in grub to generate PKCS#7 messages. I don't know
if that's acceptable?

One of the reasons I didn't go down that road initially is that I
imagine that most signed images are going to be signed by distros prior
to installation. Maybe grub-mkimage would be a better place to add this
feature. I think this is something we'll need to revisit once we resolve
the discussion about the ELF note generally.

Kind regards,
Daniel

>
> Thanks,
> Michael
>
>> +@end group
>> +@end example
>> +
>> +As with UEFI secure boot, it is necessary to build in the required modules,
>> +or sign them separately.
>> +
>> +
>>  @node Platform limitations
>>  @chapter Platform limitations
>>  
>> -- 
>> 2.25.1
>> 
>> 
>> _______________________________________________
>> Grub-devel mailing list
>> Grub-devel@gnu.org
>> https://lists.gnu.org/mailman/listinfo/grub-devel


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH 3/3] docs/grub: Document signing grub with an appended signature
  2020-10-20  4:51     ` Daniel Axtens
@ 2020-10-20  5:58       ` Michael Chang
  0 siblings, 0 replies; 8+ messages in thread
From: Michael Chang @ 2020-10-20  5:58 UTC (permalink / raw)
  To: Daniel Axtens; +Cc: The development of GNU GRUB, rashmica.g, alastair

On Tue, Oct 20, 2020 at 03:51:11PM +1100, Daniel Axtens wrote:
> Hi Michael,
> 
> >> +@section Signing GRUB with an appended signature
> >> +
> >> +The @file{core.img} itself can be signed with a Linux kernel module-style
> >> +appended signature.
> >> +
> >> +To support IEEE1275 platforms where the boot image is often loaded directly
> >> +from a disk partition rather than from a file system, the @file{core.img}
> >
> > Maybe `core.elf` should be used for embedded image on ieee1275 platform?
> > The core.img is more pc bios specific IMHO, and hence would be edited
> > on-the-fly during the grub-install/grub-bios-setup process for keeping
> > or adding some records, making it not a good example to the proposed
> > procedure here as the image on filesysetm and partition may differ.
> 
> Sure, I will change this in v2.
> 
> >> +can specify the size and location of the appended signature with an ELF
> >> +note added by @command{grub-install}.
> >> +
> >> +An image can be signed this way using the @command{sign-file} command from
> >> +the Linux kernel:
> >> +
> >> +@example
> >> +@group
> >> +# grub.key is your private key and certificate.der is your public key
> >> +
> >> +# Determine the size of the appended signature. It depends on the signing
> >> +# certificate and the hash algorithm
> >> +touch empty
> >> +sign-file SHA256 grub.key certificate.der empty empty.sig
> >> +SIG_SIZE=`stat -c '%s' empty.sig`
> >> +rm empty empty.sig
> >> +
> >> +# Build a grub image with $SIG_SIZE reserved for the signature
> >> +grub-install --appended-signature-size $SIG_SIZE --modules="..." ...
> >> +
> >> +# Replace the reserved size with a signature:
> >> +# cut off the last $SIG_SIZE bytes with truncate's minus modifier
> >> +truncate -s -$SIG_SIZE /boot/grub/powerpc-ieee1275/core.elf core.elf.unsigned
> >> +# sign the trimmed file with an appended signature, restoring the correct size
> >> +sign-file SHA256 grub.key certificate.der core.elf.unsigned core.elf.signed
> >> +
> >> +# Don't forget to install the signed image as required
> >> +# (e.g. on powerpc-ieee1275, to the PReP partition)
> >
> > Could you please provide more indication on how to install the signed
> > image afterwards ? I suppose it is 'dd' for writing the core.elf.signed
> > to the PReP partition but not really sure that is correct.
> 
> At the moment, yes, dd.
> 
> Firmware loads raw bytes off the PReP partition and expects them to be a
> 32-bit BE ELF binary. Therefore any method that can put raw bytes on
> disk will work, and dd is the classic tool for the job.
> 
> I'll improve this for v2 on the basis of how the discussions on Michal's
> proposal to do away with the ELF note go.
> 
> > It also looked to me that the entire process can be integrated to
> > grub-install so the user can get less hassle to setting it up. For that
> > matters we could work out new grub-install options to accept user's
> > private key and public key certicate to compose signed image with
> > appended signature and install it on the fly. Is there anything that
> > I could have missed here ?
> 
> We'd need to add a dependency on OpenSSL (or maybe GNUTLS) to grub-install,
> as there's no support in grub to generate PKCS#7 messages. I don't know
> if that's acceptable?

I think it is acceptable if we invoke utility like openssl in
grub-install as there has been some utilities got invoked for different
purpose. (Remember, grub-install used to be written as script :))

> One of the reasons I didn't go down that road initially is that I
> imagine that most signed images are going to be signed by distros prior
> to installation. Maybe grub-mkimage would be a better place to add this
> feature. I think this is something we'll need to revisit once we resolve
> the discussion about the ELF note generally.

Yes. That sounds reasonable as long as the distro would have to work out
the signed core.efi via grub-mkimage in a way that can handle different
installation setup without resorting to any setup work performed by the
user to the image itself (ie running grub-install). The `dd` should just
work and the right thing to do so.

Thanks,
Michael

> 
> Kind regards,
> Daniel
> 
> >
> > Thanks,
> > Michael
> >
> >> +@end group
> >> +@end example
> >> +
> >> +As with UEFI secure boot, it is necessary to build in the required modules,
> >> +or sign them separately.
> >> +
> >> +
> >>  @node Platform limitations
> >>  @chapter Platform limitations
> >>  
> >> -- 
> >> 2.25.1
> >> 
> >> 
> >> _______________________________________________
> >> Grub-devel mailing list
> >> Grub-devel@gnu.org
> >> https://lists.gnu.org/mailman/listinfo/grub-devel
> 



^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2020-10-20  5:59 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-08-21  2:37 [PATCH 0/3] Add support for signing grub with an appended signature Daniel Axtens
2020-08-21  2:37 ` [PATCH 1/3] Add suport " Daniel Axtens
2020-08-21  2:37 ` [PATCH 2/3] docs/grub: Document signing grub under UEFI Daniel Axtens
2020-08-21  2:37 ` [PATCH 3/3] docs/grub: Document signing grub with an appended signature Daniel Axtens
2020-10-20  3:54   ` Michael Chang
2020-10-20  4:51     ` Daniel Axtens
2020-10-20  5:58       ` Michael Chang
2020-09-23 15:11 ` [PATCH 0/3] Add support for " Daniel Axtens

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.