Blame SOURCES/0364-grub-install-support-embedding-x509-certificates.patch

5975ab
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
5975ab
From: Alastair D'Silva <alastair@d-silva.org>
5975ab
Date: Mon, 6 Jul 2020 13:33:04 +1000
5975ab
Subject: [PATCH] grub-install: support embedding x509 certificates
5975ab
5975ab
To support verification of appended signatures, we need a way to
5975ab
embed the necessary public keys. Existing appended signature schemes
5975ab
in the Linux kernel use X.509 certificates, so allow certificates to
5975ab
be embedded in the grub core image in the same way as PGP keys.
5975ab
5975ab
Signed-off-by: Alastair D'Silva <alastair@d-silva.org>
5975ab
Signed-off-by: Daniel Axtens <dja@axtens.net>
5975ab
---
5975ab
 grub-core/commands/pgp.c    |  2 +-
5975ab
 util/grub-install-common.c  | 23 ++++++++++++++++++++++-
5975ab
 util/grub-mkimage.c         | 15 +++++++++++++--
5975ab
 util/mkimage.c              | 41 ++++++++++++++++++++++++++++++++++++++---
5975ab
 include/grub/kernel.h       |  3 ++-
5975ab
 include/grub/util/install.h |  7 +++++--
5975ab
 6 files changed, 81 insertions(+), 10 deletions(-)
5975ab
5975ab
diff --git a/grub-core/commands/pgp.c b/grub-core/commands/pgp.c
09e3cc
index 75de32c2a..55d354be0 100644
5975ab
--- a/grub-core/commands/pgp.c
5975ab
+++ b/grub-core/commands/pgp.c
5975ab
@@ -944,7 +944,7 @@ GRUB_MOD_INIT(pgp)
5975ab
     grub_memset (&pseudo_file, 0, sizeof (pseudo_file));
5975ab
 
5975ab
     /* Not an ELF module, skip.  */
5975ab
-    if (header->type != OBJ_TYPE_PUBKEY)
5975ab
+    if (header->type != OBJ_TYPE_GPG_PUBKEY)
5975ab
       continue;
5975ab
 
5975ab
     pseudo_file.fs = &pseudo_fs;
5975ab
diff --git a/util/grub-install-common.c b/util/grub-install-common.c
09e3cc
index 561e671ff..fa6b65347 100644
5975ab
--- a/util/grub-install-common.c
5975ab
+++ b/util/grub-install-common.c
5975ab
@@ -302,6 +302,8 @@ handle_install_list (struct install_list *il, const char *val,
5975ab
 
5975ab
 static char **pubkeys;
5975ab
 static size_t npubkeys;
5975ab
+static char **x509keys;
5975ab
+static size_t nx509keys;
5975ab
 static grub_compression_t compression;
5975ab
 static size_t appsig_size;
5975ab
 
5975ab
@@ -334,6 +336,12 @@ grub_install_parse (int key, char *arg)
5975ab
 			  * (npubkeys + 1));
5975ab
       pubkeys[npubkeys++] = xstrdup (arg);
5975ab
       return 1;
5975ab
+    case 'x':
5975ab
+      x509keys = xrealloc (x509keys,
5975ab
+			  sizeof (x509keys[0])
5975ab
+			  * (nx509keys + 1));
5975ab
+      x509keys[nx509keys++] = xstrdup (arg);
5975ab
+      return 1;
5975ab
 
5975ab
     case GRUB_INSTALL_OPTIONS_VERBOSITY:
5975ab
       verbosity++;
5975ab
@@ -460,6 +468,9 @@ grub_install_make_image_wrap_file (const char *dir, const char *prefix,
5975ab
   for (pk = pubkeys; pk < pubkeys + npubkeys; pk++)
5975ab
     slen += 20 + grub_strlen (*pk);
5975ab
 
5975ab
+  for (pk = x509keys; pk < x509keys + nx509keys; pk++)
5975ab
+    slen += 10 + grub_strlen (*pk);
5975ab
+
5975ab
   for (md = modules.entries; *md; md++)
5975ab
     {
5975ab
       slen += 10 + grub_strlen (*md);
5975ab
@@ -488,6 +499,14 @@ grub_install_make_image_wrap_file (const char *dir, const char *prefix,
5975ab
       *p++ = ' ';
5975ab
     }
5975ab
 
5975ab
+  for (pk = x509keys; pk < x509keys + nx509keys; pk++)
5975ab
+    {
5975ab
+      p = grub_stpcpy (p, "--x509 '");
5975ab
+      p = grub_stpcpy (p, *pk);
5975ab
+      *p++ = '\'';
5975ab
+      *p++ = ' ';
5975ab
+    }
5975ab
+
5975ab
   for (md = modules.entries; *md; md++)
5975ab
     {
5975ab
       *p++ = '\'';
5975ab
@@ -515,7 +534,9 @@ grub_install_make_image_wrap_file (const char *dir, const char *prefix,
5975ab
 
5975ab
   grub_install_generate_image (dir, prefix, fp, outname,
5975ab
 			       modules.entries, memdisk_path,
5975ab
-			       pubkeys, npubkeys, config_path, tgt,
5975ab
+			       pubkeys, npubkeys,
5975ab
+			       x509keys, nx509keys,
5975ab
+			       config_path, tgt,
5975ab
 			       note, appsig_size, compression, dtb);
5975ab
   while (dc--)
5975ab
     grub_install_pop_module ();
5975ab
diff --git a/util/grub-mkimage.c b/util/grub-mkimage.c
09e3cc
index 65a015d8a..394d2dc5f 100644
5975ab
--- a/util/grub-mkimage.c
5975ab
+++ b/util/grub-mkimage.c
5975ab
@@ -75,7 +75,8 @@ static struct argp_option options[] = {
5975ab
    /* TRANSLATORS: "embed" is a verb (command description).  "*/
5975ab
   {"config",   'c', N_("FILE"), 0, N_("embed FILE as an early config"), 0},
5975ab
    /* TRANSLATORS: "embed" is a verb (command description).  "*/
5975ab
-  {"pubkey",   'k', N_("FILE"), 0, N_("embed FILE as public key for signature checking"), 0},
5975ab
+  {"pubkey",   'k', N_("FILE"), 0, N_("embed FILE as public key for PGP signature checking"), 0},
5975ab
+  {"x509",     'x', N_("FILE"), 0, N_("embed FILE as an x509 certificate for appended signature checking"), 0},
5975ab
   /* TRANSLATORS: NOTE is a name of segment.  */
5975ab
   {"note",   'n', 0, 0, N_("add NOTE segment for CHRP IEEE1275"), 0},
5975ab
   {"output",  'o', N_("FILE"), 0, N_("output a generated image to FILE [default=stdout]"), 0},
5975ab
@@ -122,6 +123,8 @@ struct arguments
5975ab
   char *dtb;
5975ab
   char **pubkeys;
5975ab
   size_t npubkeys;
5975ab
+  char **x509keys;
5975ab
+  size_t nx509keys;
5975ab
   char *font;
5975ab
   char *config;
5975ab
   int note;
5975ab
@@ -202,6 +205,13 @@ argp_parser (int key, char *arg, struct argp_state *state)
5975ab
       arguments->pubkeys[arguments->npubkeys++] = xstrdup (arg);
5975ab
       break;
5975ab
 
5975ab
+    case 'x':
5975ab
+      arguments->x509keys = xrealloc (arguments->x509keys,
5975ab
+				      sizeof (arguments->x509keys[0])
5975ab
+				      * (arguments->nx509keys + 1));
5975ab
+      arguments->x509keys[arguments->nx509keys++] = xstrdup (arg);
5975ab
+      break;
5975ab
+
5975ab
     case 'c':
5975ab
       if (arguments->config)
5975ab
 	free (arguments->config);
5975ab
@@ -317,7 +327,8 @@ main (int argc, char *argv[])
5975ab
   grub_install_generate_image (arguments.dir, arguments.prefix, fp,
5975ab
 			       arguments.output, arguments.modules,
5975ab
 			       arguments.memdisk, arguments.pubkeys,
5975ab
-			       arguments.npubkeys, arguments.config,
5975ab
+			       arguments.npubkeys, arguments.x509keys,
5975ab
+			       arguments.nx509keys, arguments.config,
5975ab
 			       arguments.image_target, arguments.note,
5975ab
 			       arguments.appsig_size,
5975ab
 			       arguments.comp, arguments.dtb);
5975ab
diff --git a/util/mkimage.c b/util/mkimage.c
09e3cc
index a81120f26..2529de4bb 100644
5975ab
--- a/util/mkimage.c
5975ab
+++ b/util/mkimage.c
5975ab
@@ -774,8 +774,10 @@ grub_install_get_image_targets_string (void)
5975ab
 void
5975ab
 grub_install_generate_image (const char *dir, const char *prefix,
5975ab
 			     FILE *out, const char *outname, char *mods[],
5975ab
-			     char *memdisk_path, char **pubkey_paths,
5975ab
-			     size_t npubkeys, char *config_path,
5975ab
+			     char *memdisk_path,
5975ab
+			     char **pubkey_paths, size_t npubkeys,
5975ab
+			     char **x509key_paths, size_t nx509keys,
5975ab
+			     char *config_path,
5975ab
 			     const struct grub_install_image_target_desc *image_target,
5975ab
 			     int note, size_t appsig_size, grub_compression_t comp, const char *dtb_path)
5975ab
 {
5975ab
@@ -819,6 +821,19 @@ grub_install_generate_image (const char *dir, const char *prefix,
5975ab
       }
5975ab
   }
5975ab
 
5975ab
+  {
5975ab
+    size_t i;
5975ab
+    for (i = 0; i < nx509keys; i++)
5975ab
+      {
5975ab
+	size_t curs;
5975ab
+	curs = ALIGN_ADDR (grub_util_get_image_size (x509key_paths[i]));
5975ab
+	grub_util_info ("the size of x509 public key %u is 0x%"
5975ab
+			GRUB_HOST_PRIxLONG_LONG,
5975ab
+			(unsigned) i, (unsigned long long) curs);
5975ab
+	total_module_size += curs + sizeof (struct grub_module_header);
5975ab
+      }
5975ab
+  }
5975ab
+
5975ab
   if (memdisk_path)
5975ab
     {
5975ab
       memdisk_size = ALIGN_UP(grub_util_get_image_size (memdisk_path), 512);
5975ab
@@ -933,7 +948,7 @@ grub_install_generate_image (const char *dir, const char *prefix,
5975ab
 	curs = grub_util_get_image_size (pubkey_paths[i]);
5975ab
 
5975ab
 	header = (struct grub_module_header *) (kernel_img + offset);
5975ab
-	header->type = grub_host_to_target32 (OBJ_TYPE_PUBKEY);
5975ab
+	header->type = grub_host_to_target32 (OBJ_TYPE_GPG_PUBKEY);
5975ab
 	header->size = grub_host_to_target32 (curs + sizeof (*header));
5975ab
 	offset += sizeof (*header);
5975ab
 
5975ab
@@ -942,6 +957,26 @@ grub_install_generate_image (const char *dir, const char *prefix,
5975ab
       }
5975ab
   }
5975ab
 
5975ab
+  {
5975ab
+    size_t i;
5975ab
+    for (i = 0; i < nx509keys; i++)
5975ab
+      {
5975ab
+	size_t curs;
5975ab
+	struct grub_module_header *header;
5975ab
+
5975ab
+	curs = grub_util_get_image_size (x509key_paths[i]);
5975ab
+
5975ab
+	header = (struct grub_module_header *) (kernel_img + offset);
5975ab
+	header->type = grub_host_to_target32 (OBJ_TYPE_X509_PUBKEY);
5975ab
+	header->size = grub_host_to_target32 (curs + sizeof (*header));
5975ab
+	offset += sizeof (*header);
5975ab
+
5975ab
+	grub_util_load_image (x509key_paths[i], kernel_img + offset);
5975ab
+	offset += ALIGN_ADDR (curs);
5975ab
+      }
5975ab
+  }
5975ab
+
5975ab
+
5975ab
   if (memdisk_path)
5975ab
     {
5975ab
       struct grub_module_header *header;
5975ab
diff --git a/include/grub/kernel.h b/include/grub/kernel.h
09e3cc
index 9548d552a..75a057d46 100644
5975ab
--- a/include/grub/kernel.h
5975ab
+++ b/include/grub/kernel.h
5975ab
@@ -28,7 +28,8 @@ enum
5975ab
   OBJ_TYPE_MEMDISK,
5975ab
   OBJ_TYPE_CONFIG,
5975ab
   OBJ_TYPE_PREFIX,
5975ab
-  OBJ_TYPE_PUBKEY,
5975ab
+  OBJ_TYPE_GPG_PUBKEY,
5975ab
+  OBJ_TYPE_X509_PUBKEY,
5975ab
   OBJ_TYPE_DTB
5975ab
 };
5975ab
 
5975ab
diff --git a/include/grub/util/install.h b/include/grub/util/install.h
09e3cc
index ba5e6a2ea..95059285b 100644
5975ab
--- a/include/grub/util/install.h
5975ab
+++ b/include/grub/util/install.h
5975ab
@@ -63,6 +63,8 @@
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
+  { "x509key",   'x', N_("FILE"), 0,					\
5975ab
+      N_("embed FILE as an x509 certificate 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
@@ -179,8 +181,9 @@ void
5975ab
 grub_install_generate_image (const char *dir, const char *prefix,
5975ab
 			     FILE *out,
5975ab
 			     const char *outname, char *mods[],
5975ab
-			     char *memdisk_path, char **pubkey_paths,
5975ab
-			     size_t npubkeys,
5975ab
+			     char *memdisk_path,
5975ab
+			     char **pubkey_paths, size_t npubkeys,
5975ab
+			     char **x509key_paths, size_t nx509keys,
5975ab
 			     char *config_path,
5975ab
 			     const struct grub_install_image_target_desc *image_target,
5975ab
 			     int note, size_t appsig_size,