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