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