bd7cb17
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
bd7cb17
From: Alastair D'Silva <alastair@d-silva.org>
bd7cb17
Date: Mon, 6 Jul 2020 13:33:04 +1000
bd7cb17
Subject: [PATCH] grub-install: support embedding x509 certificates
bd7cb17
bd7cb17
To support verification of appended signatures, we need a way to
bd7cb17
embed the necessary public keys. Existing appended signature schemes
bd7cb17
in the Linux kernel use X.509 certificates, so allow certificates to
bd7cb17
be embedded in the grub core image in the same way as PGP keys.
bd7cb17
bd7cb17
Signed-off-by: Alastair D'Silva <alastair@d-silva.org>
bd7cb17
Signed-off-by: Daniel Axtens <dja@axtens.net>
bd7cb17
---
bd7cb17
 grub-core/commands/pgp.c    |  2 +-
bd7cb17
 util/grub-install-common.c  | 22 +++++++++++++++++++++-
bd7cb17
 util/grub-mkimage.c         | 15 +++++++++++++--
bd7cb17
 util/mkimage.c              | 38 ++++++++++++++++++++++++++++++++++++--
bd7cb17
 include/grub/kernel.h       |  4 +++-
bd7cb17
 include/grub/util/install.h |  7 +++++--
bd7cb17
 6 files changed, 79 insertions(+), 9 deletions(-)
bd7cb17
bd7cb17
diff --git a/grub-core/commands/pgp.c b/grub-core/commands/pgp.c
bd7cb17
index 355a43844ac..b81ac0ae46c 100644
bd7cb17
--- a/grub-core/commands/pgp.c
bd7cb17
+++ b/grub-core/commands/pgp.c
bd7cb17
@@ -944,7 +944,7 @@ GRUB_MOD_INIT(pgp)
bd7cb17
     grub_memset (&pseudo_file, 0, sizeof (pseudo_file));
bd7cb17
 
bd7cb17
     /* Not an ELF module, skip.  */
bd7cb17
-    if (header->type != OBJ_TYPE_PUBKEY)
bd7cb17
+    if (header->type != OBJ_TYPE_GPG_PUBKEY)
bd7cb17
       continue;
bd7cb17
 
bd7cb17
     pseudo_file.fs = &pseudo_fs;
bd7cb17
diff --git a/util/grub-install-common.c b/util/grub-install-common.c
bd7cb17
index a53f0a5c496..917904ee73d 100644
bd7cb17
--- a/util/grub-install-common.c
bd7cb17
+++ b/util/grub-install-common.c
bd7cb17
@@ -334,6 +334,8 @@ static char **pubkeys;
bd7cb17
 static size_t npubkeys;
bd7cb17
 static char *sbat;
bd7cb17
 static int disable_shim_lock;
bd7cb17
+static char **x509keys;
bd7cb17
+static size_t nx509keys;
bd7cb17
 static grub_compression_t compression;
bd7cb17
 static size_t appsig_size;
bd7cb17
 
bd7cb17
@@ -374,6 +376,11 @@ grub_install_parse (int key, char *arg)
bd7cb17
       return 1;
bd7cb17
     case GRUB_INSTALL_OPTIONS_DISABLE_SHIM_LOCK:
bd7cb17
       disable_shim_lock = 1;
bd7cb17
+    case 'x':
bd7cb17
+      x509keys = xrealloc (x509keys,
bd7cb17
+			  sizeof (x509keys[0])
bd7cb17
+			  * (nx509keys + 1));
bd7cb17
+      x509keys[nx509keys++] = xstrdup (arg);
bd7cb17
       return 1;
bd7cb17
 
bd7cb17
     case GRUB_INSTALL_OPTIONS_VERBOSITY:
bd7cb17
@@ -501,6 +508,9 @@ grub_install_make_image_wrap_file (const char *dir, const char *prefix,
bd7cb17
   for (pk = pubkeys; pk < pubkeys + npubkeys; pk++)
bd7cb17
     slen += 20 + grub_strlen (*pk);
bd7cb17
 
bd7cb17
+  for (pk = x509keys; pk < x509keys + nx509keys; pk++)
bd7cb17
+    slen += 10 + grub_strlen (*pk);
bd7cb17
+
bd7cb17
   for (md = modules.entries; *md; md++)
bd7cb17
     {
bd7cb17
       slen += 10 + grub_strlen (*md);
bd7cb17
@@ -529,6 +539,14 @@ grub_install_make_image_wrap_file (const char *dir, const char *prefix,
bd7cb17
       *p++ = ' ';
bd7cb17
     }
bd7cb17
 
bd7cb17
+  for (pk = x509keys; pk < x509keys + nx509keys; pk++)
bd7cb17
+    {
bd7cb17
+      p = grub_stpcpy (p, "--x509 '");
bd7cb17
+      p = grub_stpcpy (p, *pk);
bd7cb17
+      *p++ = '\'';
bd7cb17
+      *p++ = ' ';
bd7cb17
+    }
bd7cb17
+
bd7cb17
   for (md = modules.entries; *md; md++)
bd7cb17
     {
bd7cb17
       *p++ = '\'';
bd7cb17
@@ -562,7 +580,9 @@ grub_install_make_image_wrap_file (const char *dir, const char *prefix,
bd7cb17
 
bd7cb17
   grub_install_generate_image (dir, prefix, fp, outname,
bd7cb17
 			       modules.entries, memdisk_path,
bd7cb17
-			       pubkeys, npubkeys, config_path, tgt,
bd7cb17
+			       pubkeys, npubkeys,
bd7cb17
+			       x509keys, nx509keys,
bd7cb17
+			       config_path, tgt,
bd7cb17
 			       note, appsig_size, compression, dtb, sbat,
bd7cb17
 			       disable_shim_lock);
bd7cb17
   while (dc--)
bd7cb17
diff --git a/util/grub-mkimage.c b/util/grub-mkimage.c
bd7cb17
index 26d1ecbf74e..c5cdda498eb 100644
bd7cb17
--- a/util/grub-mkimage.c
bd7cb17
+++ b/util/grub-mkimage.c
bd7cb17
@@ -75,7 +75,8 @@ static struct argp_option options[] = {
bd7cb17
    /* TRANSLATORS: "embed" is a verb (command description).  "*/
bd7cb17
   {"config",   'c', N_("FILE"), 0, N_("embed FILE as an early config"), 0},
bd7cb17
    /* TRANSLATORS: "embed" is a verb (command description).  "*/
bd7cb17
-  {"pubkey",   'k', N_("FILE"), 0, N_("embed FILE as public key for signature checking"), 0},
bd7cb17
+  {"pubkey",   'k', N_("FILE"), 0, N_("embed FILE as public key for PGP signature checking"), 0},
bd7cb17
+  {"x509",     'x', N_("FILE"), 0, N_("embed FILE as an x509 certificate for appended signature checking"), 0},
bd7cb17
   /* TRANSLATORS: NOTE is a name of segment.  */
bd7cb17
   {"note",   'n', 0, 0, N_("add NOTE segment for CHRP IEEE1275"), 0},
bd7cb17
   {"output",  'o', N_("FILE"), 0, N_("output a generated image to FILE [default=stdout]"), 0},
bd7cb17
@@ -124,6 +125,8 @@ struct arguments
bd7cb17
   char *dtb;
bd7cb17
   char **pubkeys;
bd7cb17
   size_t npubkeys;
bd7cb17
+  char **x509keys;
bd7cb17
+  size_t nx509keys;
bd7cb17
   char *font;
bd7cb17
   char *config;
bd7cb17
   char *sbat;
bd7cb17
@@ -206,6 +209,13 @@ argp_parser (int key, char *arg, struct argp_state *state)
bd7cb17
       arguments->pubkeys[arguments->npubkeys++] = xstrdup (arg);
bd7cb17
       break;
bd7cb17
 
bd7cb17
+    case 'x':
bd7cb17
+      arguments->x509keys = xrealloc (arguments->x509keys,
bd7cb17
+				      sizeof (arguments->x509keys[0])
bd7cb17
+				      * (arguments->nx509keys + 1));
bd7cb17
+      arguments->x509keys[arguments->nx509keys++] = xstrdup (arg);
bd7cb17
+      break;
bd7cb17
+
bd7cb17
     case 'c':
bd7cb17
       if (arguments->config)
bd7cb17
 	free (arguments->config);
bd7cb17
@@ -332,7 +342,8 @@ main (int argc, char *argv[])
bd7cb17
   grub_install_generate_image (arguments.dir, arguments.prefix, fp,
bd7cb17
 			       arguments.output, arguments.modules,
bd7cb17
 			       arguments.memdisk, arguments.pubkeys,
bd7cb17
-			       arguments.npubkeys, arguments.config,
bd7cb17
+			       arguments.npubkeys, arguments.x509keys,
bd7cb17
+			       arguments.nx509keys, arguments.config,
bd7cb17
 			       arguments.image_target, arguments.note,
bd7cb17
 
bd7cb17
 			       arguments.comp, arguments.appsig_size,
bd7cb17
diff --git a/util/mkimage.c b/util/mkimage.c
bd7cb17
index bab12276010..8319e8dfbde 100644
bd7cb17
--- a/util/mkimage.c
bd7cb17
+++ b/util/mkimage.c
bd7cb17
@@ -867,7 +867,8 @@ void
bd7cb17
 grub_install_generate_image (const char *dir, const char *prefix,
bd7cb17
 			     FILE *out, const char *outname, char *mods[],
bd7cb17
 			     char *memdisk_path, char **pubkey_paths,
bd7cb17
-			     size_t npubkeys, char *config_path,
bd7cb17
+			     size_t npubkeys, char **x509key_paths,
bd7cb17
+			     size_t nx509keys, char *config_path,
bd7cb17
 			     const struct grub_install_image_target_desc *image_target,
bd7cb17
 			     int note, size_t appsig_size, grub_compression_t comp,
bd7cb17
 			     const char *dtb_path, const char *sbat_path,
bd7cb17
@@ -913,6 +914,19 @@ grub_install_generate_image (const char *dir, const char *prefix,
bd7cb17
       }
bd7cb17
   }
bd7cb17
 
bd7cb17
+  {
bd7cb17
+    size_t i;
bd7cb17
+    for (i = 0; i < nx509keys; i++)
bd7cb17
+      {
bd7cb17
+	size_t curs;
bd7cb17
+	curs = ALIGN_ADDR (grub_util_get_image_size (x509key_paths[i]));
bd7cb17
+	grub_util_info ("the size of x509 public key %u is 0x%"
bd7cb17
+			GRUB_HOST_PRIxLONG_LONG,
bd7cb17
+			(unsigned) i, (unsigned long long) curs);
bd7cb17
+	total_module_size += curs + sizeof (struct grub_module_header);
bd7cb17
+      }
bd7cb17
+  }
bd7cb17
+
bd7cb17
   if (memdisk_path)
bd7cb17
     {
bd7cb17
       memdisk_size = ALIGN_UP(grub_util_get_image_size (memdisk_path), 512);
bd7cb17
@@ -1034,7 +1048,7 @@ grub_install_generate_image (const char *dir, const char *prefix,
bd7cb17
 	curs = grub_util_get_image_size (pubkey_paths[i]);
bd7cb17
 
bd7cb17
 	header = (struct grub_module_header *) (kernel_img + offset);
bd7cb17
-	header->type = grub_host_to_target32 (OBJ_TYPE_PUBKEY);
bd7cb17
+	header->type = grub_host_to_target32 (OBJ_TYPE_GPG_PUBKEY);
bd7cb17
 	header->size = grub_host_to_target32 (curs + sizeof (*header));
bd7cb17
 	offset += sizeof (*header);
bd7cb17
 
bd7cb17
@@ -1043,6 +1057,26 @@ grub_install_generate_image (const char *dir, const char *prefix,
bd7cb17
       }
bd7cb17
   }
bd7cb17
 
bd7cb17
+  {
bd7cb17
+    size_t i;
bd7cb17
+    for (i = 0; i < nx509keys; i++)
bd7cb17
+      {
bd7cb17
+	size_t curs;
bd7cb17
+	struct grub_module_header *header;
bd7cb17
+
bd7cb17
+	curs = grub_util_get_image_size (x509key_paths[i]);
bd7cb17
+
bd7cb17
+	header = (struct grub_module_header *) (kernel_img + offset);
bd7cb17
+	header->type = grub_host_to_target32 (OBJ_TYPE_X509_PUBKEY);
bd7cb17
+	header->size = grub_host_to_target32 (curs + sizeof (*header));
bd7cb17
+	offset += sizeof (*header);
bd7cb17
+
bd7cb17
+	grub_util_load_image (x509key_paths[i], kernel_img + offset);
bd7cb17
+	offset += ALIGN_ADDR (curs);
bd7cb17
+      }
bd7cb17
+  }
bd7cb17
+
bd7cb17
+
bd7cb17
   if (memdisk_path)
bd7cb17
     {
bd7cb17
       struct grub_module_header *header;
bd7cb17
diff --git a/include/grub/kernel.h b/include/grub/kernel.h
bd7cb17
index 55849777eaa..98edc0863f6 100644
bd7cb17
--- a/include/grub/kernel.h
bd7cb17
+++ b/include/grub/kernel.h
bd7cb17
@@ -30,7 +30,9 @@ enum
bd7cb17
   OBJ_TYPE_PREFIX,
bd7cb17
   OBJ_TYPE_PUBKEY,
bd7cb17
   OBJ_TYPE_DTB,
bd7cb17
-  OBJ_TYPE_DISABLE_SHIM_LOCK
bd7cb17
+  OBJ_TYPE_DISABLE_SHIM_LOCK,
bd7cb17
+  OBJ_TYPE_GPG_PUBKEY,
bd7cb17
+  OBJ_TYPE_X509_PUBKEY,
bd7cb17
 };
bd7cb17
 
bd7cb17
 /* The module header.  */
bd7cb17
diff --git a/include/grub/util/install.h b/include/grub/util/install.h
bd7cb17
index b3307fef9b4..faecf7b26e2 100644
bd7cb17
--- a/include/grub/util/install.h
bd7cb17
+++ b/include/grub/util/install.h
bd7cb17
@@ -67,6 +67,8 @@
bd7cb17
       N_("SBAT metadata"), 0 },						\
bd7cb17
   { "disable-shim-lock", GRUB_INSTALL_OPTIONS_DISABLE_SHIM_LOCK, 0, 0,	\
bd7cb17
       N_("disable shim_lock verifier"), 0 },				\
bd7cb17
+  { "x509key",   'x', N_("FILE"), 0,					\
bd7cb17
+      N_("embed FILE as an x509 certificate for signature checking"), 0}, \
bd7cb17
   { "appended-signature-size", GRUB_INSTALL_OPTIONS_APPENDED_SIGNATURE_SIZE,\
bd7cb17
     "SIZE", 0, N_("Add a note segment reserving SIZE bytes for an appended signature"), \
bd7cb17
     1},                                                                 \
bd7cb17
@@ -188,8 +190,9 @@ void
bd7cb17
 grub_install_generate_image (const char *dir, const char *prefix,
bd7cb17
 			     FILE *out,
bd7cb17
 			     const char *outname, char *mods[],
bd7cb17
-			     char *memdisk_path, char **pubkey_paths,
bd7cb17
-			     size_t npubkeys,
bd7cb17
+			     char *memdisk_path,
bd7cb17
+			     char **pubkey_paths, size_t npubkeys,
bd7cb17
+			     char **x509key_paths, size_t nx509keys,
bd7cb17
 			     char *config_path,
bd7cb17
 			     const struct grub_install_image_target_desc *image_target,
bd7cb17
 			     int note, size_t appsig_size,