346 lines
15 KiB
Diff
346 lines
15 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
|
|
Date: Mon, 6 Oct 2025 12:54:46 +0530
|
|
Subject: [PATCH] powerpc/ieee1275: Add support for signing GRUB with an
|
|
appended signature
|
|
|
|
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: Rashmica Gupta <rashmica.g@gmail.com>
|
|
Signed-off-by: Daniel Axtens <dja@axtens.net>
|
|
Signed-off-by: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
|
|
Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
|
|
Reviewed-by: Avnish Chouhan <avnish@linux.ibm.com>
|
|
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
|
---
|
|
include/grub/util/install.h | 2 +-
|
|
include/grub/util/mkimage.h | 4 +--
|
|
util/grub-install-common.c | 28 ++++++++++-----------
|
|
util/grub-mkimage.c | 19 +++++++-------
|
|
util/grub-mkimagexx.c | 61 +++++++++++++++++++++++----------------------
|
|
util/mkimage.c | 20 ++++++++-------
|
|
6 files changed, 68 insertions(+), 66 deletions(-)
|
|
|
|
diff --git a/include/grub/util/install.h b/include/grub/util/install.h
|
|
index 93c1f0e..14f4489 100644
|
|
--- a/include/grub/util/install.h
|
|
+++ b/include/grub/util/install.h
|
|
@@ -70,7 +70,7 @@
|
|
{ "disable-cli", GRUB_INSTALL_OPTIONS_DISABLE_CLI, 0, 0, \
|
|
N_("disabled command line interface access"), 0 }, \
|
|
{ "x509key", 'x', N_("FILE"), 0, \
|
|
- N_("embed FILE as an x509 certificate for appended signature checking"), 0}, \
|
|
+ N_("embed FILE as an x509 certificate for appended 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, \
|
|
diff --git a/include/grub/util/mkimage.h b/include/grub/util/mkimage.h
|
|
index 881e303..244e39d 100644
|
|
--- a/include/grub/util/mkimage.h
|
|
+++ b/include/grub/util/mkimage.h
|
|
@@ -51,12 +51,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, size_t appsig_size, char *sbat, char **core_img, size_t *core_size,
|
|
+ int note, char *sbat, 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, size_t appsig_size, char *sbat, char **core_img, size_t *core_size,
|
|
+ int note, char *sbat, 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 41251ce..c4b5cb3 100644
|
|
--- a/util/grub-install-common.c
|
|
+++ b/util/grub-install-common.c
|
|
@@ -475,6 +475,7 @@ int
|
|
grub_install_parse (int key, char *arg)
|
|
{
|
|
const char *end;
|
|
+
|
|
switch (key)
|
|
{
|
|
case GRUB_INSTALL_OPTIONS_INSTALL_CORE_COMPRESS:
|
|
@@ -580,10 +581,11 @@ grub_install_parse (int key, char *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;
|
|
+ appsig_size = grub_strtoul (arg, &end, 10);
|
|
+ if (*arg == '\0' || *end != '\0')
|
|
+ grub_util_error (_("non-numeric or invalid appended signature size `%s'"), arg);
|
|
+ else if (appsig_size == 0)
|
|
+ grub_util_error (_("appended signature size `%s', and it should not be zero"), arg);
|
|
return 1;
|
|
default:
|
|
return 0;
|
|
@@ -709,14 +711,12 @@ grub_install_make_image_wrap_file (const char *dir, const char *prefix,
|
|
|
|
grub_util_info ("grub-mkimage --directory '%s' --prefix '%s' --output '%s'"
|
|
" --format '%s' --compression '%s'"
|
|
- " --appended-signture-size %zu %s%s%s\n",
|
|
- " --format '%s' --compression '%s'%s%s%s%s\n",
|
|
- dir, prefix, outname,
|
|
- mkimage_target, compnames[compression],
|
|
- appsig_size,
|
|
- note ? " --note" : "",
|
|
- disable_shim_lock ? " --disable-shim-lock" : "",
|
|
- disable_cli ? " --disable-cli" : "", s);
|
|
+ " --appended-signature-size %zu %s %s %s %s\n",
|
|
+ dir, prefix, outname,
|
|
+ mkimage_target, compnames[compression], appsig_size,
|
|
+ note ? " --note" : "",
|
|
+ disable_shim_lock ? " --disable-shim-lock" : "",
|
|
+ disable_cli ? " --disable-cli" : "", s);
|
|
free (s);
|
|
|
|
tgt = grub_install_get_image_target (mkimage_target);
|
|
@@ -725,9 +725,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,
|
|
- x509keys, nx509keys,
|
|
- config_path, tgt,
|
|
+ pubkeys, npubkeys, x509keys, nx509keys, config_path, tgt,
|
|
note, appsig_size, compression, dtb, sbat,
|
|
disable_shim_lock, disable_cli);
|
|
while (dc--)
|
|
diff --git a/util/grub-mkimage.c b/util/grub-mkimage.c
|
|
index 89ca81c..e3511b0 100644
|
|
--- a/util/grub-mkimage.c
|
|
+++ b/util/grub-mkimage.c
|
|
@@ -85,8 +85,8 @@ static struct argp_option options[] = {
|
|
{"sbat", 's', N_("FILE"), 0, N_("SBAT metadata"), 0},
|
|
{"disable-shim-lock", GRUB_INSTALL_OPTIONS_DISABLE_SHIM_LOCK, 0, 0, N_("disable shim_lock verifier"), 0},
|
|
{"disable-cli", GRUB_INSTALL_OPTIONS_DISABLE_CLI, 0, 0, N_("disable command line interface access"), 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},
|
|
+ {"verbose", 'v', 0, 0, N_("print verbose messages."), 0},
|
|
{ 0, 0, 0, 0, 0, 0 }
|
|
};
|
|
|
|
@@ -133,8 +133,8 @@ struct arguments
|
|
char *sbat;
|
|
int note;
|
|
int disable_shim_lock;
|
|
- size_t appsig_size;
|
|
int disable_cli;
|
|
+ size_t appsig_size;
|
|
const struct grub_install_image_target_desc *image_target;
|
|
grub_compression_t comp;
|
|
};
|
|
@@ -179,10 +179,11 @@ argp_parser (int key, char *arg, struct argp_state *state)
|
|
break;
|
|
|
|
case 'S':
|
|
- grub_errno = 0;
|
|
- arguments->appsig_size = grub_strtol(arg, &end, 10);
|
|
- if (grub_errno)
|
|
- return 0;
|
|
+ arguments->appsig_size = grub_strtoul (arg, &end, 10);
|
|
+ if (*arg == '\0' || *end != '\0')
|
|
+ grub_util_error (_("non-numeric or invalid appended signature size `%s'"), arg);
|
|
+ else if (arguments->appsig_size == 0)
|
|
+ grub_util_error (_("appended signature size `%s', and it should not be zero"), arg);
|
|
break;
|
|
|
|
case 'm':
|
|
@@ -351,9 +352,9 @@ main (int argc, char *argv[])
|
|
arguments.npubkeys, arguments.x509keys,
|
|
arguments.nx509keys, arguments.config,
|
|
arguments.image_target, arguments.note,
|
|
- arguments.appsig_size, arguments.comp,
|
|
- arguments.dtb, arguments.sbat,
|
|
- arguments.disable_shim_lock,
|
|
+ arguments.appsig_size,
|
|
+ arguments.comp, arguments.dtb,
|
|
+ arguments.sbat, arguments.disable_shim_lock,
|
|
arguments.disable_cli);
|
|
|
|
if (grub_util_file_sync (fp) < 0)
|
|
diff --git a/util/grub-mkimagexx.c b/util/grub-mkimagexx.c
|
|
index b993054..d185246 100644
|
|
--- a/util/grub-mkimagexx.c
|
|
+++ b/util/grub-mkimagexx.c
|
|
@@ -85,15 +85,6 @@ 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
|
|
@@ -124,6 +115,14 @@ struct grub_sbat_note {
|
|
char name[ALIGN_UP(sizeof(GRUB_SBAT_NOTE_NAME), 4)];
|
|
};
|
|
|
|
+#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)];
|
|
+};
|
|
+
|
|
static int
|
|
is_relocatable (const struct grub_install_image_target_desc *image_target)
|
|
{
|
|
@@ -225,7 +224,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, size_t appsig_size, char *sbat, char **core_img, size_t *core_size,
|
|
+ int note, char *sbat, size_t appsig_size, char **core_img, size_t *core_size,
|
|
Elf_Addr target_addr,
|
|
struct grub_mkimage_layout *layout)
|
|
{
|
|
@@ -249,7 +248,7 @@ SUFFIX (grub_mkimage_generate_elf) (const struct grub_install_image_target_desc
|
|
if (appsig_size)
|
|
{
|
|
phnum++;
|
|
- footer_size += ALIGN_UP(sizeof (struct grub_appended_signature_note) + appsig_size, 4);
|
|
+ footer_size += ALIGN_UP (sizeof (struct grub_appended_signature_note), 4);
|
|
}
|
|
|
|
if (image_target->id != IMAGE_LOONGSON_ELF)
|
|
@@ -542,29 +541,31 @@ SUFFIX (grub_mkimage_generate_elf) (const struct grub_install_image_target_desc
|
|
phdr->p_filesz = grub_host_to_target32 (note_size);
|
|
phdr->p_memsz = 0;
|
|
phdr->p_offset = grub_host_to_target32 (header_size + program_size + footer_offset);
|
|
+ footer += note_size;
|
|
+ footer_offset += note_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));
|
|
+ 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 *) footer;
|
|
|
|
- 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);
|
|
+ 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));
|
|
- }
|
|
+ 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 + footer_offset);
|
|
+ }
|
|
|
|
{
|
|
char *str_start = (elf_img + sizeof (*ehdr) + phnum * sizeof (*phdr)
|
|
diff --git a/util/mkimage.c b/util/mkimage.c
|
|
index cc4c79d..15cfd4b 100644
|
|
--- a/util/mkimage.c
|
|
+++ b/util/mkimage.c
|
|
@@ -883,12 +883,11 @@ void
|
|
grub_install_generate_image (const char *dir, const char *prefix,
|
|
FILE *out, const char *outname, char *mods[],
|
|
char *memdisk_path, char **pubkey_paths,
|
|
- size_t npubkeys, char **x509key_paths,
|
|
- size_t nx509keys, char *config_path,
|
|
+ size_t npubkeys, char **x509key_paths, size_t nx509keys, char *config_path,
|
|
const struct grub_install_image_target_desc *image_target,
|
|
- int note, size_t appsig_size, grub_compression_t comp,
|
|
- const char *dtb_path, const char *sbat_path,
|
|
- int disable_shim_lock, int disable_cli)
|
|
+ int note, size_t appsig_size, grub_compression_t comp, const char *dtb_path,
|
|
+ const char *sbat_path, int disable_shim_lock,
|
|
+ int disable_cli)
|
|
{
|
|
char *kernel_img, *core_img;
|
|
size_t total_module_size, core_size;
|
|
@@ -978,6 +977,9 @@ grub_install_generate_image (const char *dir, const char *prefix,
|
|
if (sbat_path != NULL && (image_target->id != IMAGE_EFI && image_target->id != IMAGE_PPC))
|
|
grub_util_error (_("SBAT data can be added only to EFI or powerpc-ieee1275 images"));
|
|
|
|
+ if (appsig_size != 0 && image_target->id != IMAGE_PPC)
|
|
+ grub_util_error (_("appended signature can be support only to powerpc-ieee1275 images"));
|
|
+
|
|
if (disable_shim_lock)
|
|
total_module_size += sizeof (struct grub_module_header);
|
|
|
|
@@ -1884,11 +1886,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, appsig_size, sbat, &core_img,
|
|
- &core_size, target_addr, &layout);
|
|
+ grub_mkimage_generate_elf32 (image_target, note, sbat, appsig_size, &core_img, &core_size,
|
|
+ target_addr, &layout);
|
|
else
|
|
- grub_mkimage_generate_elf64 (image_target, note, appsig_size, sbat, &core_img,
|
|
- &core_size, target_addr, &layout);
|
|
+ grub_mkimage_generate_elf64 (image_target, note, sbat, appsig_size, &core_img, &core_size,
|
|
+ target_addr, &layout);
|
|
}
|
|
break;
|
|
}
|