* [PATCH 0/3] Add support for signing grub with an appended signature
@ 2020-08-21 2:37 Daniel Axtens
2020-08-21 2:37 ` [PATCH 1/3] Add suport " Daniel Axtens
` (3 more replies)
0 siblings, 4 replies; 14+ messages in thread
From: Daniel Axtens @ 2020-08-21 2:37 UTC (permalink / raw)
To: grub-devel; +Cc: rashmica.g, alastair, Daniel Axtens
Part of a secure boot chain is allowing boot firmware to verify the
grub core.img. For UEFI platforms, this is done by signing the PE
binary with a tool like pesign or sb-sign. However, for platforms that
don't implement UEFI, an alternative scheme is required.
These patches provide some infrastructure and documentation for
signing grub's core.img with a Linux-kernel-module style appended
signature.
Because some platforms, such as powerpc-ieee1275, load grub from a raw
disk partition rather than a filesystem, we extend grub-install to add
an ELF note that allows us to specify the size and location of the
signature.
More details are in patch 1, including a link to an open-source firmware
capable of verifying a grub image signed this way.
Daniel Axtens (2):
docs/grub: Document signing grub under UEFI
docs/grub: Document signing grub with an appended signature
Rashmica Gupta (1):
Add suport for signing grub with an appended signature
docs/grub.texi | 64 ++++++++++++++++++++++++++++++++++++-
include/grub/util/install.h | 8 +++--
include/grub/util/mkimage.h | 4 +--
util/grub-install-common.c | 16 ++++++++--
util/grub-mkimage.c | 11 +++++++
util/grub-mkimagexx.c | 39 +++++++++++++++++++++-
util/mkimage.c | 10 +++---
7 files changed, 138 insertions(+), 14 deletions(-)
--
2.25.1
^ permalink raw reply [flat|nested] 14+ messages in thread* [PATCH 1/3] Add suport for signing grub with an appended signature 2020-08-21 2:37 [PATCH 0/3] Add support for signing grub with an appended signature Daniel Axtens @ 2020-08-21 2:37 ` Daniel Axtens 2020-08-21 2:37 ` [PATCH 2/3] docs/grub: Document signing grub under UEFI Daniel Axtens ` (2 subsequent siblings) 3 siblings, 0 replies; 14+ messages in thread From: Daniel Axtens @ 2020-08-21 2:37 UTC (permalink / raw) To: grub-devel; +Cc: rashmica.g, alastair, Daniel Axtens From: Rashmica Gupta <rashmica.g@gmail.com> 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: Daniel Axtens <dja@axtens.net> Signed-off-by: Rashmica Gupta <rashmica.g@gmail.com> --- You can experiment with this code with a patched version of SLOF that verifies these signatures. You can find one at: https://github.com/daxtens/SLOF I will be proposing the ELF note details for inclusion in a future Power Architecture Platform Reference (PAPR). --- include/grub/util/install.h | 8 ++++++-- include/grub/util/mkimage.h | 4 ++-- util/grub-install-common.c | 16 ++++++++++++--- util/grub-mkimage.c | 11 +++++++++++ util/grub-mkimagexx.c | 39 ++++++++++++++++++++++++++++++++++++- util/mkimage.c | 10 +++++----- 6 files changed, 75 insertions(+), 13 deletions(-) diff --git a/include/grub/util/install.h b/include/grub/util/install.h index 2631b1074513..eb1b83b6d946 100644 --- a/include/grub/util/install.h +++ b/include/grub/util/install.h @@ -63,6 +63,9 @@ /* TRANSLATORS: "embed" is a verb (command description). "*/ \ { "pubkey", 'k', N_("FILE"), 0, \ N_("embed FILE as public key for 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, \ N_("print verbose messages."), 1 } @@ -122,7 +125,8 @@ enum grub_install_options { GRUB_INSTALL_OPTIONS_THEMES_DIRECTORY, GRUB_INSTALL_OPTIONS_GRUB_MKIMAGE, GRUB_INSTALL_OPTIONS_INSTALL_CORE_COMPRESS, - GRUB_INSTALL_OPTIONS_DTB + GRUB_INSTALL_OPTIONS_DTB, + GRUB_INSTALL_OPTIONS_APPENDED_SIGNATURE_SIZE }; extern char *grub_install_source_directory; @@ -182,7 +186,7 @@ grub_install_generate_image (const char *dir, const char *prefix, size_t npubkeys, char *config_path, const struct grub_install_image_target_desc *image_target, - int note, + int note, size_t appsig_size, grub_compression_t comp, const char *dtb_file); const struct grub_install_image_target_desc * diff --git a/include/grub/util/mkimage.h b/include/grub/util/mkimage.h index ba9f568f6926..2000d6fbdf1e 100644 --- a/include/grub/util/mkimage.h +++ b/include/grub/util/mkimage.h @@ -50,12 +50,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, char **core_img, size_t *core_size, + int note, 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, char **core_img, size_t *core_size, + int note, 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 ca0ac612ac51..e9b75d6f1fcf 100644 --- a/util/grub-install-common.c +++ b/util/grub-install-common.c @@ -308,10 +308,12 @@ handle_install_list (struct install_list *il, const char *val, static char **pubkeys; static size_t npubkeys; static grub_compression_t compression; +static size_t appsig_size; int grub_install_parse (int key, char *arg) { + const char *end; switch (key) { case 'C': @@ -400,6 +402,12 @@ grub_install_parse (int key, char *arg) grub_util_error (_("Unrecognized compression `%s'"), 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; + return 1; default: return 0; } @@ -498,10 +506,12 @@ grub_install_make_image_wrap_file (const char *dir, const char *prefix, grub_util_info ("grub-mkimage --directory '%s' --prefix '%s'" " --output '%s' " " --dtb '%s' " - "--format '%s' --compression '%s' %s %s\n", + "--format '%s' --compression '%s' " + "--appended-signature-size %zu %s %s\n", dir, prefix, outname, dtb ? : "", mkimage_target, - compnames[compression], note ? "--note" : "", s); + compnames[compression], appsig_size, + note ? "--note" : "", s); free (s); tgt = grub_install_get_image_target (mkimage_target); @@ -511,7 +521,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, config_path, tgt, - note, compression, dtb); + note, appsig_size, compression, dtb); while (dc--) grub_install_pop_module (); } diff --git a/util/grub-mkimage.c b/util/grub-mkimage.c index 912564e3622f..c1e07c70dc7e 100644 --- a/util/grub-mkimage.c +++ b/util/grub-mkimage.c @@ -82,6 +82,7 @@ static struct argp_option options[] = { {"format", 'O', N_("FORMAT"), 0, 0, 0}, {"compression", 'C', "(xz|none|auto)", 0, N_("choose the compression to use for core image"), 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}, { 0, 0, 0, 0, 0, 0 } }; @@ -124,6 +125,7 @@ struct arguments char *font; char *config; int note; + size_t appsig_size; const struct grub_install_image_target_desc *image_target; grub_compression_t comp; }; @@ -134,6 +136,7 @@ argp_parser (int key, char *arg, struct argp_state *state) /* Get the input argument from argp_parse, which we know is a pointer to our arguments structure. */ struct arguments *arguments = state->input; + const char* end; switch (key) { @@ -166,6 +169,13 @@ argp_parser (int key, char *arg, struct argp_state *state) arguments->note = 1; break; + case 's': + grub_errno = 0; + arguments->appsig_size = grub_strtol(arg, &end, 10); + if (grub_errno) + return 0; + break; + case 'm': if (arguments->memdisk) free (arguments->memdisk); @@ -309,6 +319,7 @@ main (int argc, char *argv[]) arguments.memdisk, arguments.pubkeys, arguments.npubkeys, arguments.config, arguments.image_target, arguments.note, + arguments.appsig_size, arguments.comp, arguments.dtb); if (grub_util_file_sync (fp) < 0) diff --git a/util/grub-mkimagexx.c b/util/grub-mkimagexx.c index ab6dfab79242..3bfed4369fd3 100644 --- a/util/grub-mkimagexx.c +++ b/util/grub-mkimagexx.c @@ -84,6 +84,15 @@ 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 @@ -207,7 +216,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, char **core_img, size_t *core_size, + int note, size_t appsig_size, char **core_img, size_t *core_size, Elf_Addr target_addr, struct grub_mkimage_layout *layout) { @@ -221,6 +230,12 @@ SUFFIX (grub_mkimage_generate_elf) (const struct grub_install_image_target_desc int shnum = 4; int string_size = sizeof (".text") + sizeof ("mods") + 1; + if (appsig_size) + { + phnum++; + footer_size += ALIGN_UP(sizeof (struct grub_appended_signature_note) + appsig_size, 4); + } + if (image_target->id != IMAGE_LOONGSON_ELF) phnum += 2; @@ -484,6 +499,28 @@ SUFFIX (grub_mkimage_generate_elf) (const struct grub_install_image_target_desc phdr->p_offset = grub_host_to_target32 (header_size + program_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)); + + 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)); + } + { char *str_start = (elf_img + sizeof (*ehdr) + phnum * sizeof (*phdr) + shnum * sizeof (*shdr)); diff --git a/util/mkimage.c b/util/mkimage.c index 37d6249f16b3..bd06968deccb 100644 --- a/util/mkimage.c +++ b/util/mkimage.c @@ -822,7 +822,7 @@ grub_install_generate_image (const char *dir, const char *prefix, char *memdisk_path, char **pubkey_paths, size_t npubkeys, char *config_path, const struct grub_install_image_target_desc *image_target, - int note, grub_compression_t comp, const char *dtb_path) + int note, size_t appsig_size, grub_compression_t comp, const char *dtb_path) { char *kernel_img, *core_img; size_t total_module_size, core_size; @@ -1742,11 +1742,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, &core_img, &core_size, - target_addr, &layout); + grub_mkimage_generate_elf32 (image_target, note, appsig_size, &core_img, + &core_size, target_addr, &layout); else - grub_mkimage_generate_elf64 (image_target, note, &core_img, &core_size, - target_addr, &layout); + grub_mkimage_generate_elf64 (image_target, note, appsig_size, &core_img, + &core_size, target_addr, &layout); } break; } -- 2.25.1 ^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 2/3] docs/grub: Document signing grub under UEFI 2020-08-21 2:37 [PATCH 0/3] Add support for signing grub with an appended signature Daniel Axtens 2020-08-21 2:37 ` [PATCH 1/3] Add suport " Daniel Axtens @ 2020-08-21 2:37 ` Daniel Axtens 2020-08-21 2:37 ` [PATCH 3/3] docs/grub: Document signing grub with an appended signature Daniel Axtens 2020-09-23 15:11 ` [PATCH 0/3] Add support for " Daniel Axtens 3 siblings, 0 replies; 14+ messages in thread From: Daniel Axtens @ 2020-08-21 2:37 UTC (permalink / raw) To: grub-devel; +Cc: rashmica.g, alastair, Daniel Axtens Before adding information about how grub is signed with an appended signature scheme, it's worth adding some information about how it can currently be signed for UEFI. Signed-off-by: Daniel Axtens <dja@axtens.net> --- docs/grub.texi | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/docs/grub.texi b/docs/grub.texi index 1ce9993a53fc..35da48456d9e 100644 --- a/docs/grub.texi +++ b/docs/grub.texi @@ -5736,6 +5736,7 @@ environment variables and commands are listed in the same order. * Using digital signatures:: Booting digitally signed code * UEFI secure boot and shim:: Booting digitally signed PE files * Measured Boot:: Measuring boot components +* Signing GRUB itself:: Ensuring the integrity of the GRUB core image @end menu @node Authentication and authorisation @@ -5814,7 +5815,7 @@ commands. GRUB's @file{core.img} can optionally provide enforcement that all files subsequently read from disk are covered by a valid digital signature. -This document does @strong{not} cover how to ensure that your +This section does @strong{not} cover how to ensure that your platform's firmware (e.g., Coreboot) validates @file{core.img}. If environment variable @code{check_signatures} @@ -5950,6 +5951,25 @@ into @file{core.img} in order to avoid a potential gap in measurement between Measured boot is currently only supported on EFI platforms. +@node Signing GRUB itself +@section Signing GRUB itself + +To ensure a complete secure-boot chain, there must be a way for the code that +loads GRUB to verify the integrity of the core image. + +This is ultimately platform-specific and individual platforms can define their +own mechanisms. However, there are general-purpose mechanisms that can be used +with GRUB. + +@section Signing GRUB for UEFI secure boot + +On UEFI platforms, @file{core.img} is a PE binary. Therefore, it can be signed +with a tool such as @command{pesign} or @command{sbsign}. Refer to the +suggestions in @pxref{UEFI secure boot and shim} to ensure that the final +image works under UEFI secure boot and can maintain the secure-boot chain. It +will also be necessary to enrol the public key used into a relevant firmware +key database. + @node Platform limitations @chapter Platform limitations -- 2.25.1 ^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 3/3] docs/grub: Document signing grub with an appended signature 2020-08-21 2:37 [PATCH 0/3] Add support for signing grub with an appended signature Daniel Axtens 2020-08-21 2:37 ` [PATCH 1/3] Add suport " Daniel Axtens 2020-08-21 2:37 ` [PATCH 2/3] docs/grub: Document signing grub under UEFI Daniel Axtens @ 2020-08-21 2:37 ` Daniel Axtens 2020-10-20 3:54 ` Michael Chang 2020-09-23 15:11 ` [PATCH 0/3] Add support for " Daniel Axtens 3 siblings, 1 reply; 14+ messages in thread From: Daniel Axtens @ 2020-08-21 2:37 UTC (permalink / raw) To: grub-devel; +Cc: rashmica.g, alastair, Daniel Axtens Signing grub for firmware that verifies an appended signature is a bit fiddly. I don't want people to have to figure it out from scratch so document it here. Signed-off-by: Daniel Axtens <dja@axtens.net> --- docs/grub.texi | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/docs/grub.texi b/docs/grub.texi index 35da48456d9e..bbbe6c7e07bf 100644 --- a/docs/grub.texi +++ b/docs/grub.texi @@ -5970,6 +5970,48 @@ image works under UEFI secure boot and can maintain the secure-boot chain. It will also be necessary to enrol the public key used into a relevant firmware key database. +@section Signing GRUB with an appended signature + +The @file{core.img} itself can be signed with a Linux kernel module-style +appended signature. + +To support IEEE1275 platforms where the boot image is often loaded directly +from a disk partition rather than from a file system, the @file{core.img} +can specify the size and location of the appended signature with an ELF +note added by @command{grub-install}. + +An image can be signed this way using the @command{sign-file} command from +the Linux kernel: + +@example +@group +# grub.key is your private key and certificate.der is your public key + +# Determine the size of the appended signature. It depends on the signing +# certificate and the hash algorithm +touch empty +sign-file SHA256 grub.key certificate.der empty empty.sig +SIG_SIZE=`stat -c '%s' empty.sig` +rm empty empty.sig + +# Build a grub image with $SIG_SIZE reserved for the signature +grub-install --appended-signature-size $SIG_SIZE --modules="..." ... + +# Replace the reserved size with a signature: +# cut off the last $SIG_SIZE bytes with truncate's minus modifier +truncate -s -$SIG_SIZE /boot/grub/powerpc-ieee1275/core.elf core.elf.unsigned +# sign the trimmed file with an appended signature, restoring the correct size +sign-file SHA256 grub.key certificate.der core.elf.unsigned core.elf.signed + +# Don't forget to install the signed image as required +# (e.g. on powerpc-ieee1275, to the PReP partition) +@end group +@end example + +As with UEFI secure boot, it is necessary to build in the required modules, +or sign them separately. + + @node Platform limitations @chapter Platform limitations -- 2.25.1 ^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCH 3/3] docs/grub: Document signing grub with an appended signature 2020-08-21 2:37 ` [PATCH 3/3] docs/grub: Document signing grub with an appended signature Daniel Axtens @ 2020-10-20 3:54 ` Michael Chang 2020-10-20 4:51 ` Daniel Axtens 0 siblings, 1 reply; 14+ messages in thread From: Michael Chang @ 2020-10-20 3:54 UTC (permalink / raw) To: The development of GNU GRUB; +Cc: rashmica.g, alastair, Daniel Axtens On Fri, Aug 21, 2020 at 12:37:20PM +1000, Daniel Axtens wrote: > Signing grub for firmware that verifies an appended signature is a > bit fiddly. I don't want people to have to figure it out from scratch > so document it here. > > Signed-off-by: Daniel Axtens <dja@axtens.net> > --- > docs/grub.texi | 42 ++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 42 insertions(+) > > diff --git a/docs/grub.texi b/docs/grub.texi > index 35da48456d9e..bbbe6c7e07bf 100644 > --- a/docs/grub.texi > +++ b/docs/grub.texi > @@ -5970,6 +5970,48 @@ image works under UEFI secure boot and can maintain the secure-boot chain. It > will also be necessary to enrol the public key used into a relevant firmware > key database. > > +@section Signing GRUB with an appended signature > + > +The @file{core.img} itself can be signed with a Linux kernel module-style > +appended signature. > + > +To support IEEE1275 platforms where the boot image is often loaded directly > +from a disk partition rather than from a file system, the @file{core.img} Maybe `core.elf` should be used for embedded image on ieee1275 platform? The core.img is more pc bios specific IMHO, and hence would be edited on-the-fly during the grub-install/grub-bios-setup process for keeping or adding some records, making it not a good example to the proposed procedure here as the image on filesysetm and partition may differ. > +can specify the size and location of the appended signature with an ELF > +note added by @command{grub-install}. > + > +An image can be signed this way using the @command{sign-file} command from > +the Linux kernel: > + > +@example > +@group > +# grub.key is your private key and certificate.der is your public key > + > +# Determine the size of the appended signature. It depends on the signing > +# certificate and the hash algorithm > +touch empty > +sign-file SHA256 grub.key certificate.der empty empty.sig > +SIG_SIZE=`stat -c '%s' empty.sig` > +rm empty empty.sig > + > +# Build a grub image with $SIG_SIZE reserved for the signature > +grub-install --appended-signature-size $SIG_SIZE --modules="..." ... > + > +# Replace the reserved size with a signature: > +# cut off the last $SIG_SIZE bytes with truncate's minus modifier > +truncate -s -$SIG_SIZE /boot/grub/powerpc-ieee1275/core.elf core.elf.unsigned > +# sign the trimmed file with an appended signature, restoring the correct size > +sign-file SHA256 grub.key certificate.der core.elf.unsigned core.elf.signed > + > +# Don't forget to install the signed image as required > +# (e.g. on powerpc-ieee1275, to the PReP partition) Could you please provide more indication on how to install the signed image afterwards ? I suppose it is 'dd' for writing the core.elf.signed to the PReP partition but not really sure that is correct. It also looked to me that the entire process can be integrated to grub-install so the user can get less hassle to setting it up. For that matters we could work out new grub-install options to accept user's private key and public key certicate to compose signed image with appended signature and install it on the fly. Is there anything that I could have missed here ? Thanks, Michael > +@end group > +@end example > + > +As with UEFI secure boot, it is necessary to build in the required modules, > +or sign them separately. > + > + > @node Platform limitations > @chapter Platform limitations > > -- > 2.25.1 > > > _______________________________________________ > Grub-devel mailing list > Grub-devel@gnu.org > https://lists.gnu.org/mailman/listinfo/grub-devel ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 3/3] docs/grub: Document signing grub with an appended signature 2020-10-20 3:54 ` Michael Chang @ 2020-10-20 4:51 ` Daniel Axtens 2020-10-20 5:58 ` Michael Chang 0 siblings, 1 reply; 14+ messages in thread From: Daniel Axtens @ 2020-10-20 4:51 UTC (permalink / raw) To: Michael Chang, The development of GNU GRUB; +Cc: rashmica.g, alastair Hi Michael, >> +@section Signing GRUB with an appended signature >> + >> +The @file{core.img} itself can be signed with a Linux kernel module-style >> +appended signature. >> + >> +To support IEEE1275 platforms where the boot image is often loaded directly >> +from a disk partition rather than from a file system, the @file{core.img} > > Maybe `core.elf` should be used for embedded image on ieee1275 platform? > The core.img is more pc bios specific IMHO, and hence would be edited > on-the-fly during the grub-install/grub-bios-setup process for keeping > or adding some records, making it not a good example to the proposed > procedure here as the image on filesysetm and partition may differ. Sure, I will change this in v2. >> +can specify the size and location of the appended signature with an ELF >> +note added by @command{grub-install}. >> + >> +An image can be signed this way using the @command{sign-file} command from >> +the Linux kernel: >> + >> +@example >> +@group >> +# grub.key is your private key and certificate.der is your public key >> + >> +# Determine the size of the appended signature. It depends on the signing >> +# certificate and the hash algorithm >> +touch empty >> +sign-file SHA256 grub.key certificate.der empty empty.sig >> +SIG_SIZE=`stat -c '%s' empty.sig` >> +rm empty empty.sig >> + >> +# Build a grub image with $SIG_SIZE reserved for the signature >> +grub-install --appended-signature-size $SIG_SIZE --modules="..." ... >> + >> +# Replace the reserved size with a signature: >> +# cut off the last $SIG_SIZE bytes with truncate's minus modifier >> +truncate -s -$SIG_SIZE /boot/grub/powerpc-ieee1275/core.elf core.elf.unsigned >> +# sign the trimmed file with an appended signature, restoring the correct size >> +sign-file SHA256 grub.key certificate.der core.elf.unsigned core.elf.signed >> + >> +# Don't forget to install the signed image as required >> +# (e.g. on powerpc-ieee1275, to the PReP partition) > > Could you please provide more indication on how to install the signed > image afterwards ? I suppose it is 'dd' for writing the core.elf.signed > to the PReP partition but not really sure that is correct. At the moment, yes, dd. Firmware loads raw bytes off the PReP partition and expects them to be a 32-bit BE ELF binary. Therefore any method that can put raw bytes on disk will work, and dd is the classic tool for the job. I'll improve this for v2 on the basis of how the discussions on Michal's proposal to do away with the ELF note go. > It also looked to me that the entire process can be integrated to > grub-install so the user can get less hassle to setting it up. For that > matters we could work out new grub-install options to accept user's > private key and public key certicate to compose signed image with > appended signature and install it on the fly. Is there anything that > I could have missed here ? We'd need to add a dependency on OpenSSL (or maybe GNUTLS) to grub-install, as there's no support in grub to generate PKCS#7 messages. I don't know if that's acceptable? One of the reasons I didn't go down that road initially is that I imagine that most signed images are going to be signed by distros prior to installation. Maybe grub-mkimage would be a better place to add this feature. I think this is something we'll need to revisit once we resolve the discussion about the ELF note generally. Kind regards, Daniel > > Thanks, > Michael > >> +@end group >> +@end example >> + >> +As with UEFI secure boot, it is necessary to build in the required modules, >> +or sign them separately. >> + >> + >> @node Platform limitations >> @chapter Platform limitations >> >> -- >> 2.25.1 >> >> >> _______________________________________________ >> Grub-devel mailing list >> Grub-devel@gnu.org >> https://lists.gnu.org/mailman/listinfo/grub-devel ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 3/3] docs/grub: Document signing grub with an appended signature 2020-10-20 4:51 ` Daniel Axtens @ 2020-10-20 5:58 ` Michael Chang 0 siblings, 0 replies; 14+ messages in thread From: Michael Chang @ 2020-10-20 5:58 UTC (permalink / raw) To: Daniel Axtens; +Cc: The development of GNU GRUB, rashmica.g, alastair On Tue, Oct 20, 2020 at 03:51:11PM +1100, Daniel Axtens wrote: > Hi Michael, > > >> +@section Signing GRUB with an appended signature > >> + > >> +The @file{core.img} itself can be signed with a Linux kernel module-style > >> +appended signature. > >> + > >> +To support IEEE1275 platforms where the boot image is often loaded directly > >> +from a disk partition rather than from a file system, the @file{core.img} > > > > Maybe `core.elf` should be used for embedded image on ieee1275 platform? > > The core.img is more pc bios specific IMHO, and hence would be edited > > on-the-fly during the grub-install/grub-bios-setup process for keeping > > or adding some records, making it not a good example to the proposed > > procedure here as the image on filesysetm and partition may differ. > > Sure, I will change this in v2. > > >> +can specify the size and location of the appended signature with an ELF > >> +note added by @command{grub-install}. > >> + > >> +An image can be signed this way using the @command{sign-file} command from > >> +the Linux kernel: > >> + > >> +@example > >> +@group > >> +# grub.key is your private key and certificate.der is your public key > >> + > >> +# Determine the size of the appended signature. It depends on the signing > >> +# certificate and the hash algorithm > >> +touch empty > >> +sign-file SHA256 grub.key certificate.der empty empty.sig > >> +SIG_SIZE=`stat -c '%s' empty.sig` > >> +rm empty empty.sig > >> + > >> +# Build a grub image with $SIG_SIZE reserved for the signature > >> +grub-install --appended-signature-size $SIG_SIZE --modules="..." ... > >> + > >> +# Replace the reserved size with a signature: > >> +# cut off the last $SIG_SIZE bytes with truncate's minus modifier > >> +truncate -s -$SIG_SIZE /boot/grub/powerpc-ieee1275/core.elf core.elf.unsigned > >> +# sign the trimmed file with an appended signature, restoring the correct size > >> +sign-file SHA256 grub.key certificate.der core.elf.unsigned core.elf.signed > >> + > >> +# Don't forget to install the signed image as required > >> +# (e.g. on powerpc-ieee1275, to the PReP partition) > > > > Could you please provide more indication on how to install the signed > > image afterwards ? I suppose it is 'dd' for writing the core.elf.signed > > to the PReP partition but not really sure that is correct. > > At the moment, yes, dd. > > Firmware loads raw bytes off the PReP partition and expects them to be a > 32-bit BE ELF binary. Therefore any method that can put raw bytes on > disk will work, and dd is the classic tool for the job. > > I'll improve this for v2 on the basis of how the discussions on Michal's > proposal to do away with the ELF note go. > > > It also looked to me that the entire process can be integrated to > > grub-install so the user can get less hassle to setting it up. For that > > matters we could work out new grub-install options to accept user's > > private key and public key certicate to compose signed image with > > appended signature and install it on the fly. Is there anything that > > I could have missed here ? > > We'd need to add a dependency on OpenSSL (or maybe GNUTLS) to grub-install, > as there's no support in grub to generate PKCS#7 messages. I don't know > if that's acceptable? I think it is acceptable if we invoke utility like openssl in grub-install as there has been some utilities got invoked for different purpose. (Remember, grub-install used to be written as script :)) > One of the reasons I didn't go down that road initially is that I > imagine that most signed images are going to be signed by distros prior > to installation. Maybe grub-mkimage would be a better place to add this > feature. I think this is something we'll need to revisit once we resolve > the discussion about the ELF note generally. Yes. That sounds reasonable as long as the distro would have to work out the signed core.efi via grub-mkimage in a way that can handle different installation setup without resorting to any setup work performed by the user to the image itself (ie running grub-install). The `dd` should just work and the right thing to do so. Thanks, Michael > > Kind regards, > Daniel > > > > > Thanks, > > Michael > > > >> +@end group > >> +@end example > >> + > >> +As with UEFI secure boot, it is necessary to build in the required modules, > >> +or sign them separately. > >> + > >> + > >> @node Platform limitations > >> @chapter Platform limitations > >> > >> -- > >> 2.25.1 > >> > >> > >> _______________________________________________ > >> Grub-devel mailing list > >> Grub-devel@gnu.org > >> https://lists.gnu.org/mailman/listinfo/grub-devel > ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 0/3] Add support for signing grub with an appended signature 2020-08-21 2:37 [PATCH 0/3] Add support for signing grub with an appended signature Daniel Axtens ` (2 preceding siblings ...) 2020-08-21 2:37 ` [PATCH 3/3] docs/grub: Document signing grub with an appended signature Daniel Axtens @ 2020-09-23 15:11 ` Daniel Axtens 3 siblings, 0 replies; 14+ messages in thread From: Daniel Axtens @ 2020-09-23 15:11 UTC (permalink / raw) To: grub-devel, pjones, xnox; +Cc: rashmica.g, alastair Hi, > Part of a secure boot chain is allowing boot firmware to verify the > grub core.img. For UEFI platforms, this is done by signing the PE > binary with a tool like pesign or sb-sign. However, for platforms that > don't implement UEFI, an alternative scheme is required. > > These patches provide some infrastructure and documentation for > signing grub's core.img with a Linux-kernel-module style appended > signature. > > Because some platforms, such as powerpc-ieee1275, load grub from a raw > disk partition rather than a filesystem, we extend grub-install to add > an ELF note that allows us to specify the size and location of the > signature. This is following up on the discussion out of Linux Plumbers [1]. Hopefully I've got the main question-askers, apologies if I've missed anyone or sent emails to the wrong people. I'm also emailing grub-devel@ in hopes of catching anyone else who is interested. One of the big requirements I heard was a desire to support key rotation, for example by being able to embed multiple signatures in a single signed grub. I checked, and this is possible with appended signatures as I have proposed them, because the size of the full signature block is known when grub-mkimage is called. You do have to do a bit of magic with openssl and sign-file, but it's not particuarly bad. This demonstrates the openssl side and it's easy to integrate with grub-mkimage: # sign data/hello-world with both signing1 and signing2, placing just the # PKCS#7 message in out/double-sig.p7s openssl cms -sign -binary -in data/hello-world \ -signer signing1.pem -inkey signing1.key \ -signer signing2.pem -inkey signing2.key \ -out out/double-sig.p7s -outform DER -noattr -md sha512 # append it to data/hello-world using sign-file's -s option, creating # out/hello-world-sha512-2keys ../tools/sign-file -s out/double-sig.p7s sha512 /dev/null data/hello-world out/hello-world-sha512-2keys # to verify, extract the cryptographic message with # extract-module-sig.pl from the kernel source ./extract-module-sig.pl -s out/hello-world-sha512-2keys > out/hello-world-sha512-2keys.sig 2> /dev/null if ! cmp out/double-sig.p7s out/hello-world-sha512-2keys.sig ; then echo "Input signature and data from extract-module-sig.pl -s do not agree!" exit 1; fi # openssl's verify requires that _both_ signatures are made with # embedded certs which validate against a trusted CA openssl cms -verify -binary -in out/hello-world-sha512-2keys.sig -inform der \ -content hello-world -CAfile ca.pem -out /dev/null if [ $? -ne 0 ]; then echo "OpenSSL failed to verify with both keys" exit 1 fi For our application, firmware will allow a grub binary to boot if any of the signatures in the PKCS#7 message match a key that is trusted by firmware. This should allow keys to be rotated with firmware releases without breaking backwards compatibility. I've updated https://github.com/daxtens/SLOF to demonstrate this: if any signature can be validated by a built-in key, it will pass verification. Another thing that was raised was the ability to make multiple signatures separated in time, where the second signer didn't have access to the private keys for the first signer. The example given was for someone to sign a distro binary with a second set of keys (e.g. specific keys for a data center) - then the binary would be bootable on machines with distro keys, and also on machines that have only the second set of keys. This is not so easy. For grub, with the elf note, the data over which the signature is made contains the size of the signature. To add a signature would be to change the size of the signature stored in the signed data. That would either break the old signature, or we would need to make it not a true appended signature any more: rather than being a 'dumb' signature over everything before the start of the appended signature data, it'd be more complex. We'd need to teach the signer and verifier how to deal with that, and then we've thrown away the advantages of appended signatures and reinvented many of the complexities of Authenticode. One thing we could potentially do without going down that route is to include a quantity of 'blank space' for signatures - we could for example always allocate a few kilobytes for signatures. The distro signatures would take up the first part of the buffer, leaving space for some for 'user' signatures. We can get this to work with the appended-signature format "as is": we specify how big the PKCS#7 message is, and if the message happens to be smaller than the size we give, both openssl and mbedtls will just ignore any trailing data. This does at least kinda-sorta work, but OpenSSL's 'cms -resign' command only works if we include signed attributes and at the moment our mbedtls implementation cannot handle that. I don't think the PKCS#7 standard mandates that behaviour, so maybe we can hack around it with the OpenSSL C API. Or maybe we can extend mbedtls to handle signed attributes. (eek!) The concern I have is that this approach creates a big block of arbitrary unsigned data in the grub binary. An attacker under our threat model (root on the host) could put any data they like into that space. I worry that in combination with some other vulernability, this could be used to more easily pass useful data in to grub. However, maybe that's not that much of a win for the attacker: if they are root they also have complete control of grub.cfg and can instruct grub to do quite a bit as it is. I'm also not sure that the use-case is quite as likely with Power systems vs x86 systems. But if I'm overthinking the security implications of a blank space in the binary, it seems like we could get it to work and I'd be happy to chase it up further. Thoughts? (on or off-list is fine.) Kind regards, Daniel [1] https://linuxplumbersconf.org/event/7/contributions/738/ https://youtu.be/IJUNxHnopH4?t=537 > More details are in patch 1, including a link to an open-source firmware > capable of verifying a grub image signed this way. > > Daniel Axtens (2): > docs/grub: Document signing grub under UEFI > docs/grub: Document signing grub with an appended signature > > Rashmica Gupta (1): > Add suport for signing grub with an appended signature > > docs/grub.texi | 64 ++++++++++++++++++++++++++++++++++++- > include/grub/util/install.h | 8 +++-- > include/grub/util/mkimage.h | 4 +-- > util/grub-install-common.c | 16 ++++++++-- > util/grub-mkimage.c | 11 +++++++ > util/grub-mkimagexx.c | 39 +++++++++++++++++++++- > util/mkimage.c | 10 +++--- > 7 files changed, 138 insertions(+), 14 deletions(-) > > -- > 2.25.1 ^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 0/3] Add support for signing grub with an appended signature
@ 2020-10-16 11:20 Michal Suchánek
[not found] ` <871rhuwi80.fsf@dja-thinkpad.axtens.net>
0 siblings, 1 reply; 14+ messages in thread
From: Michal Suchánek @ 2020-10-16 11:20 UTC (permalink / raw)
To: dja, grub-devel
Hello,
It has been pointed out in the plumbers session that the ELF note will
cause problems when user wants to add additional signature.
The normal appended signature has only one size information - in the
footer at the end of the binary, and that is not part of the signed
data. So if you want to add additional signature it if possible to
expand the room for the signature data.
In contrast the ELF note size is present in the ELF header which is
also signed. This does not allow adjusting the size of the signature
data once the binary is signed.
A simpler scheme would be for grub-install to parse the signature
footer, split-off the signature, write the ELF binary at the start of
the PReP partition, and the signature at the end. Then the grub
signature can use exactly same format as the kernel and modules.
The disadvantage is that for signed grub dd is no longer an alternative
to grub-install.
There was also concern about distinguishing signed and un-signed grub.
That is that writing an un-signed grub might lease a stale signature
leading to an error.
However, secure boot is something that should be enabled or disabled in
firmware settings, and not triggered by the PPeP partition containing a
signature.
When secure boot is enabled checking the grub signature is required and
un-signed grub is invalid. When secure boot is disabled the signature
is irrelevant and stale signature should not cause any error.
grub-install can also remove the signature magic when installing
un-signed grub for consistency. Users using dd to install un-signed
grub might still have an old signature at the end of the partition.
Thanks
Michal
^ permalink raw reply [flat|nested] 14+ messages in thread[parent not found: <871rhuwi80.fsf@dja-thinkpad.axtens.net>]
* Re: [PATCH 0/3] Add support for signing grub with an appended signature [not found] ` <871rhuwi80.fsf@dja-thinkpad.axtens.net> @ 2020-10-19 23:18 ` Daniel Axtens 2020-10-22 4:25 ` Daniel Axtens 1 sibling, 0 replies; 14+ messages in thread From: Daniel Axtens @ 2020-10-19 23:18 UTC (permalink / raw) To: grub-devel [This bounced from the list for some reason, so I'm trying again.] Hi Michal, That's a really interesting proposal - thank you. I'm still thinking about it and experimenting with it in SLOF. Some thoughts: > It has been pointed out in the plumbers session that the ELF note will > cause problems when user wants to add additional signature. > > The normal appended signature has only one size information - in the > footer at the end of the binary, and that is not part of the signed > data. So if you want to add additional signature it if possible to > expand the room for the signature data. The appended signature metadata doesn't contain information about the size of the signed data. It contains the size of the PKCS#7/CMS signature block - because that can change in size based on the hash function and the identity of the signing certificate. Normally this doesn't matter: you can get a size of the whole file from the filesystem and then because you know the size of the appended signature data, you can work out the size of the signed data. > In contrast the ELF note size is present in the ELF header which is > also signed. This does not allow adjusting the size of the signature > data once the binary is signed. Correct. We could potentially allocate lots of space, but you are correct that the size of the ELF note is fixed by the signature. > A simpler scheme would be for grub-install to parse the signature > footer, split-off the signature, write the ELF binary at the start of > the PReP partition, and the signature at the end. Then the grub > signature can use exactly same format as the kernel and modules. I got part way through implementing this today in SLOF and realised that it's not immediately clear what the size of the signed data is for verifying the appended signature - that is, how much of the PReP partition should I be hashing? As I said, the appended signature metadata doesn't encode this particular size value. One thing that we might be able to do is to base the size of the verified data on a size calculated from the ELF header: basically figure out the maximum file offset + size for all the program headers, capped at (partition size - appended signature size), and hash that many bytes. If I understand correctly, and assuming grub-mkimage constructs valid ELF files, this should be correct. I'll give this a go in SLOF tomorrow, and I'll also need to confer with the team that develops the proprietary firmware used by PowerVM. > The disadvantage is that for signed grub dd is no longer an alternative > to grub-install. > > There was also concern about distinguishing signed and un-signed grub. > That is that writing an un-signed grub might lease a stale signature > leading to an error. > > However, secure boot is something that should be enabled or disabled in > firmware settings, and not triggered by the PPeP partition containing a > signature. > > When secure boot is enabled checking the grub signature is required and > un-signed grub is invalid. When secure boot is disabled the signature > is irrelevant and stale signature should not cause any error. What I'm concerned about here - and it's possible I explained it poorly at Plumbers - is how a systems administrator would distinguish between having accidentally installed an unsigned grub, and having installed a grub with a broken or untrusted signature. Having said that, ... > grub-install can also remove the signature magic when installing > un-signed grub for consistency. Users using dd to install un-signed > grub might still have an old signature at the end of the partition. if we make grub-install do the right thing, I think that sufficiently mitigates my concern. Thanks again, and I'll let you know how I get on shortly. Kind regards, Daniel ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 0/3] Add support for signing grub with an appended signature [not found] ` <871rhuwi80.fsf@dja-thinkpad.axtens.net> 2020-10-19 23:18 ` Daniel Axtens @ 2020-10-22 4:25 ` Daniel Axtens 2020-10-22 11:14 ` Michal Suchánek 1 sibling, 1 reply; 14+ messages in thread From: Daniel Axtens @ 2020-10-22 4:25 UTC (permalink / raw) To: Michal Suchánek, grub-devel Hi Michal, >> A simpler scheme would be for grub-install to parse the signature >> footer, split-off the signature, write the ELF binary at the start of >> the PReP partition, and the signature at the end. Then the grub >> signature can use exactly same format as the kernel and modules. > > I got part way through implementing this today in SLOF and realised that > it's not immediately clear what the size of the signed data is for > verifying the appended signature - that is, how much of the PReP > partition should I be hashing? As I said, the appended signature > metadata doesn't encode this particular size value. > > One thing that we might be able to do is to base the size of the > verified data on a size calculated from the ELF header: basically figure > out the maximum file offset + size for all the program headers, capped > at (partition size - appended signature size), and hash that many > bytes. If I understand correctly, and assuming grub-mkimage constructs > valid ELF files, this should be correct. > > I'll give this a go in SLOF tomorrow, and I'll also need to confer with > the team that develops the proprietary firmware used by PowerVM. > I talked to the firmware team this morning. So grub is usually loaded from the PReP partition if you are booting from disk. But, if you are booting from a CD/USB/etc, we first parse /ppc/boot-info.txt and then load whatever file it identifies. If you're netbooting we load the file we get from the network. One strength of the ELF-note based scheme is that verification of the appended signature is exactly the same in all these scenarios, and in each case it can live entirely in the ELF parsing and loading code. In contrast, if we don't have an elf note, we have to handle PReP partitions, CHRP boot-info.txt and netboot separately. At least in the PReP case we also have to do parse enough of the ELF header to determine how much data we need to be hashing for signature verification, and this crosses a couple of previously separate steps of the process. To illustrate from SLOF, currently the ELF note stuff lives almost entirely in elf32.c, but for the scheme you describe we need to patch load-from-dos-boot-partition, load-from-gpt-prep-partition, whatever code we use for where we boot a file directly from disk for CHRP boot-info.txt loading, and something somewhere in the netboot code. We can still support multiple signers disjoint in time with the scheme I suggest at https://lists.gnu.org/archive/html/grub-devel/2020-09/msg00081.html although I do agree it's ugly in its own separate way. Kind regards, Daniel >> The disadvantage is that for signed grub dd is no longer an alternative >> to grub-install. >> >> There was also concern about distinguishing signed and un-signed grub. >> That is that writing an un-signed grub might lease a stale signature >> leading to an error. >> >> However, secure boot is something that should be enabled or disabled in >> firmware settings, and not triggered by the PPeP partition containing a >> signature. >> >> When secure boot is enabled checking the grub signature is required and >> un-signed grub is invalid. When secure boot is disabled the signature >> is irrelevant and stale signature should not cause any error. > > What I'm concerned about here - and it's possible I explained it poorly > at Plumbers - is how a systems administrator would distinguish between > having accidentally installed an unsigned grub, and having installed a > grub with a broken or untrusted signature. > > Having said that, ... > >> grub-install can also remove the signature magic when installing >> un-signed grub for consistency. Users using dd to install un-signed >> grub might still have an old signature at the end of the partition. > > if we make grub-install do the right thing, I think that sufficiently > mitigates my concern. > > Thanks again, and I'll let you know how I get on shortly. > > Kind regards, > Daniel ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 0/3] Add support for signing grub with an appended signature 2020-10-22 4:25 ` Daniel Axtens @ 2020-10-22 11:14 ` Michal Suchánek 2020-10-23 5:33 ` Daniel Axtens 0 siblings, 1 reply; 14+ messages in thread From: Michal Suchánek @ 2020-10-22 11:14 UTC (permalink / raw) To: Daniel Axtens; +Cc: grub-devel Hello, thanks for looking into this On Thu, Oct 22, 2020 at 03:25:33PM +1100, Daniel Axtens wrote: > Hi Michal, > > >> A simpler scheme would be for grub-install to parse the signature > >> footer, split-off the signature, write the ELF binary at the start of > >> the PReP partition, and the signature at the end. Then the grub > >> signature can use exactly same format as the kernel and modules. > > > > I got part way through implementing this today in SLOF and realised that > > it's not immediately clear what the size of the signed data is for > > verifying the appended signature - that is, how much of the PReP > > partition should I be hashing? As I said, the appended signature > > metadata doesn't encode this particular size value. > > > > One thing that we might be able to do is to base the size of the > > verified data on a size calculated from the ELF header: basically figure > > out the maximum file offset + size for all the program headers, capped > > at (partition size - appended signature size), and hash that many > > bytes. If I understand correctly, and assuming grub-mkimage constructs > > valid ELF files, this should be correct. > > > > I'll give this a go in SLOF tomorrow, and I'll also need to confer with > > the team that develops the proprietary firmware used by PowerVM. > > > > I talked to the firmware team this morning. > > So grub is usually loaded from the PReP partition if you are booting > from disk. But, if you are booting from a CD/USB/etc, we first parse > /ppc/boot-info.txt and then load whatever file it identifies. If you're > netbooting we load the file we get from the network. > > One strength of the ELF-note based scheme is that verification of the > appended signature is exactly the same in all these scenarios, and in > each case it can live entirely in the ELF parsing and loading code. > > In contrast, if we don't have an elf note, we have to handle PReP > partitions, CHRP boot-info.txt and netboot separately. At least in the > PReP case we also have to do parse enough of the ELF header to determine > how much data we need to be hashing for signature verification, and this > crosses a couple of previously separate steps of the process. > > To illustrate from SLOF, currently the ELF note stuff lives almost > entirely in elf32.c, but for the scheme you describe we need to patch > load-from-dos-boot-partition, load-from-gpt-prep-partition, whatever > code we use for where we boot a file directly from disk for CHRP > boot-info.txt loading, and something somewhere in the netboot code. Why do you have to handle different boot media separately, though? There is this bug, supposedly in 'old firmware' that when the PReP partition is large (gigabytes in size) the firmware crashes trying to load the whole thing to memory and hand it over to the elf parser. If this is fixed today you need to parse the header anyway to know how much to load, or you need to just hand over some handle to the partition and let the elf parser do the reading. The appended signature format is exactly the same in each case: there is a container such as a partition, a file, or a block of memory that has an elf binary at the start, optional padding, and optinal signature at the end. There is nothing stopping the elf parser from parsing both the elf header and the signature footer when it gets the data. In the case of the partition containing the elf binary it is expected that the padding is non-zero, in the other cases having padding is suspicious. In the case of a partition you have to read the data in some device-specific sectors while files can be read at arbitrary sized chunks. If you choose to write separate code to fetch the elf binary from different media due to these differences then these separate code paths must be adjusted. However, that is inherent to lack of suitable abstraction in the code, and not the appended signature format. I think it is more productive to clean up the code to handle all media the same way rather than inventing new unique quirky and deficient signature format. Thanks Michal > > We can still support multiple signers disjoint in time with the scheme I > suggest at > https://lists.gnu.org/archive/html/grub-devel/2020-09/msg00081.html > although I do agree it's ugly in its own separate way. > > Kind regards, > Daniel > > >> The disadvantage is that for signed grub dd is no longer an alternative > >> to grub-install. > >> > >> There was also concern about distinguishing signed and un-signed grub. > >> That is that writing an un-signed grub might lease a stale signature > >> leading to an error. > >> > >> However, secure boot is something that should be enabled or disabled in > >> firmware settings, and not triggered by the PPeP partition containing a > >> signature. > >> > >> When secure boot is enabled checking the grub signature is required and > >> un-signed grub is invalid. When secure boot is disabled the signature > >> is irrelevant and stale signature should not cause any error. > > > > What I'm concerned about here - and it's possible I explained it poorly > > at Plumbers - is how a systems administrator would distinguish between > > having accidentally installed an unsigned grub, and having installed a > > grub with a broken or untrusted signature. > > > > Having said that, ... > > > >> grub-install can also remove the signature magic when installing > >> un-signed grub for consistency. Users using dd to install un-signed > >> grub might still have an old signature at the end of the partition. > > > > if we make grub-install do the right thing, I think that sufficiently > > mitigates my concern. > > > > Thanks again, and I'll let you know how I get on shortly. > > > > Kind regards, > > Daniel ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 0/3] Add support for signing grub with an appended signature 2020-10-22 11:14 ` Michal Suchánek @ 2020-10-23 5:33 ` Daniel Axtens 2020-11-04 18:04 ` Michal Suchánek 0 siblings, 1 reply; 14+ messages in thread From: Daniel Axtens @ 2020-10-23 5:33 UTC (permalink / raw) To: Michal Suchánek; +Cc: grub-devel Hi Michal, >> So grub is usually loaded from the PReP partition if you are booting >> from disk. But, if you are booting from a CD/USB/etc, we first parse >> /ppc/boot-info.txt and then load whatever file it identifies. If you're >> netbooting we load the file we get from the network. >> >> One strength of the ELF-note based scheme is that verification of the >> appended signature is exactly the same in all these scenarios, and in >> each case it can live entirely in the ELF parsing and loading code. >> >> In contrast, if we don't have an elf note, we have to handle PReP >> partitions, CHRP boot-info.txt and netboot separately. At least in the >> PReP case we also have to do parse enough of the ELF header to determine >> how much data we need to be hashing for signature verification, and this >> crosses a couple of previously separate steps of the process. >> >> To illustrate from SLOF, currently the ELF note stuff lives almost >> entirely in elf32.c, but for the scheme you describe we need to patch >> load-from-dos-boot-partition, load-from-gpt-prep-partition, whatever >> code we use for where we boot a file directly from disk for CHRP >> boot-info.txt loading, and something somewhere in the netboot code. > > Why do you have to handle different boot media separately, though? > > There is this bug, supposedly in 'old firmware' that when the PReP > partition is large (gigabytes in size) the firmware crashes trying to > load the whole thing to memory and hand it over to the elf parser. If > this is fixed today you need to parse the header anyway to know how much > to load, or you need to just hand over some handle to the partition and > let the elf parser do the reading. Hmm, I will pass this on to the enterprise/proprietary Partiton Firmware (PFW) team to confirm that it's been fixed. It won't affect (at least modern versions of) SLOF, as SLOF caps the amount of PReP partition that it reads at 32MB. It reads min(partition size, 32MB) and passes that to the ELF loader. (I suppose that will break if a bootloader ever grows to be > 32MB, but most distros only allocate something like 8MB to PReP today, so you'd hit partition size limits first anyway.) > The appended signature format is exactly the same in each case: there is > a container such as a partition, a file, or a block of memory that has > an elf binary at the start, optional padding, and optinal signature at > the end. There is nothing stopping the elf parser from parsing both > the elf header and the signature footer when it gets the data. Reflecting on it, the proposed new design is also pretty quirky. The existing appended signature format is: data || pkcs7 || metadata || magic If you strip off the signature, only the data remains, which you can immediately calculate the hash on and verify the signature. The ELF note format perserves this property. Moving the signature to the end of the PReP partition gives you: data || [padding] || pkcs7 || metadata || magic Once you've stripped off the signature, you now need an extra processing step to strip off the padding. And - unusually for appended signatures - you need to know about the format of the data to distinguish data from padding. > In the case of the partition containing the elf binary it is expected > that the padding is non-zero, in the other cases having padding is > suspicious. > > In the case of a partition you have to read the data in some > device-specific sectors while files can be read at arbitrary sized > chunks. > > If you choose to write separate code to fetch the elf binary from > different media due to these differences then these separate code paths > must be adjusted. However, that is inherent to lack of suitable > abstraction in the code, and not the appended signature format. > > I think it is more productive to clean up the code to handle all media > the same way rather than inventing new unique quirky and deficient > signature format. You would need to handle the new padding at some stage in the pipeline, and that pipeline stage needs to know how to read an ELF header. So I agree that it would be logical to put signature verification in the ELF parsing stage. However, if you want to flag the existence of padding in non-PReP cases - either to reject it or warn about it - then the signature verifier needs to know if it's parsing a PReP partition. If the signature validation lives in the ELF parser, you now need to tell the ELF parser that you are parsing a PReP partion. This seems like an abstraction or layering problem - the ELF parser shouldn't need to know or care where the ELF binary comes from. So I think that merely cleaning up the code wouldn't be sufficient. Kind regards, Daniel > > Thanks > > Michal > >> >> We can still support multiple signers disjoint in time with the scheme I >> suggest at >> https://lists.gnu.org/archive/html/grub-devel/2020-09/msg00081.html >> although I do agree it's ugly in its own separate way. >> >> Kind regards, >> Daniel >> >> >> The disadvantage is that for signed grub dd is no longer an alternative >> >> to grub-install. >> >> >> >> There was also concern about distinguishing signed and un-signed grub. >> >> That is that writing an un-signed grub might lease a stale signature >> >> leading to an error. >> >> >> >> However, secure boot is something that should be enabled or disabled in >> >> firmware settings, and not triggered by the PPeP partition containing a >> >> signature. >> >> >> >> When secure boot is enabled checking the grub signature is required and >> >> un-signed grub is invalid. When secure boot is disabled the signature >> >> is irrelevant and stale signature should not cause any error. >> > >> > What I'm concerned about here - and it's possible I explained it poorly >> > at Plumbers - is how a systems administrator would distinguish between >> > having accidentally installed an unsigned grub, and having installed a >> > grub with a broken or untrusted signature. >> > >> > Having said that, ... >> > >> >> grub-install can also remove the signature magic when installing >> >> un-signed grub for consistency. Users using dd to install un-signed >> >> grub might still have an old signature at the end of the partition. >> > >> > if we make grub-install do the right thing, I think that sufficiently >> > mitigates my concern. >> > >> > Thanks again, and I'll let you know how I get on shortly. >> > >> > Kind regards, >> > Daniel ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 0/3] Add support for signing grub with an appended signature 2020-10-23 5:33 ` Daniel Axtens @ 2020-11-04 18:04 ` Michal Suchánek 0 siblings, 0 replies; 14+ messages in thread From: Michal Suchánek @ 2020-11-04 18:04 UTC (permalink / raw) To: Daniel Axtens; +Cc: grub-devel On Fri, Oct 23, 2020 at 04:33:58PM +1100, Daniel Axtens wrote: > Hi Michal, > > >> So grub is usually loaded from the PReP partition if you are booting > >> from disk. But, if you are booting from a CD/USB/etc, we first parse > >> /ppc/boot-info.txt and then load whatever file it identifies. If you're > >> netbooting we load the file we get from the network. > >> > >> One strength of the ELF-note based scheme is that verification of the > >> appended signature is exactly the same in all these scenarios, and in > >> each case it can live entirely in the ELF parsing and loading code. > >> > >> In contrast, if we don't have an elf note, we have to handle PReP > >> partitions, CHRP boot-info.txt and netboot separately. At least in the > >> PReP case we also have to do parse enough of the ELF header to determine > >> how much data we need to be hashing for signature verification, and this > >> crosses a couple of previously separate steps of the process. > >> > >> To illustrate from SLOF, currently the ELF note stuff lives almost > >> entirely in elf32.c, but for the scheme you describe we need to patch > >> load-from-dos-boot-partition, load-from-gpt-prep-partition, whatever > >> code we use for where we boot a file directly from disk for CHRP > >> boot-info.txt loading, and something somewhere in the netboot code. > > > > Why do you have to handle different boot media separately, though? > > > > There is this bug, supposedly in 'old firmware' that when the PReP > > partition is large (gigabytes in size) the firmware crashes trying to > > load the whole thing to memory and hand it over to the elf parser. If > > this is fixed today you need to parse the header anyway to know how much > > to load, or you need to just hand over some handle to the partition and > > let the elf parser do the reading. > > Hmm, I will pass this on to the enterprise/proprietary Partiton Firmware > (PFW) team to confirm that it's been fixed. > > It won't affect (at least modern versions of) SLOF, as SLOF caps the > amount of PReP partition that it reads at 32MB. It reads min(partition > size, 32MB) and passes that to the ELF loader. (I suppose that will > break if a bootloader ever grows to be > 32MB, but most distros only > allocate something like 8MB to PReP today, so you'd hit partition size > limits first anyway.) > > > The appended signature format is exactly the same in each case: there is > > a container such as a partition, a file, or a block of memory that has > > an elf binary at the start, optional padding, and optinal signature at > > the end. There is nothing stopping the elf parser from parsing both > > the elf header and the signature footer when it gets the data. > > Reflecting on it, the proposed new design is also pretty quirky. > > The existing appended signature format is: > > data || pkcs7 || metadata || magic > > If you strip off the signature, only the data remains, which you can > immediately calculate the hash on and verify the signature. The ELF note > format perserves this property. > > Moving the signature to the end of the PReP partition gives you: > > data || [padding] || pkcs7 || metadata || magic > > Once you've stripped off the signature, you now need an extra processing > step to strip off the padding. And - unusually for appended signatures - > you need to know about the format of the data to distinguish data from > padding. And you need to know about the format of the data to make use of it - specifically to execute it as an ELF binary, anyway. > > > In the case of the partition containing the elf binary it is expected > > that the padding is non-zero, in the other cases having padding is > > suspicious. > > > > In the case of a partition you have to read the data in some > > device-specific sectors while files can be read at arbitrary sized > > chunks. > > > > If you choose to write separate code to fetch the elf binary from > > different media due to these differences then these separate code paths > > must be adjusted. However, that is inherent to lack of suitable > > abstraction in the code, and not the appended signature format. > > > > I think it is more productive to clean up the code to handle all media > > the same way rather than inventing new unique quirky and deficient > > signature format. > > You would need to handle the new padding at some stage in the pipeline, > and that pipeline stage needs to know how to read an ELF header. So I > agree that it would be logical to put signature verification in the ELF > parsing stage. > > However, if you want to flag the existence of padding in non-PReP cases > - either to reject it or warn about it - then the signature verifier > needs to know if it's parsing a PReP partition. If the signature > validation lives in the ELF parser, you now need to tell the ELF parser > that you are parsing a PReP partion. This seems like an abstraction or > layering problem - the ELF parser shouldn't need to know or care where > the ELF binary comes from. > > So I think that merely cleaning up the code wouldn't be sufficient. Adding the flag is something optional, and otherwise the data passed is the same. If you read PReP either pass the whole thing if it is smaller than 32MB or you pass the first 32MB and append the signature (if it exists), and there is quirky case when the signature crosses the boundary of your 'maximum binary size'. This quirky case is caused by another layering violation - the code is reading something it does not understand from the partition. Thanks Michal > > Kind regards, > Daniel > > > > > Thanks > > > > Michal > > > >> > >> We can still support multiple signers disjoint in time with the scheme I > >> suggest at > >> https://lists.gnu.org/archive/html/grub-devel/2020-09/msg00081.html > >> although I do agree it's ugly in its own separate way. > >> > >> Kind regards, > >> Daniel > >> > >> >> The disadvantage is that for signed grub dd is no longer an alternative > >> >> to grub-install. > >> >> > >> >> There was also concern about distinguishing signed and un-signed grub. > >> >> That is that writing an un-signed grub might lease a stale signature > >> >> leading to an error. > >> >> > >> >> However, secure boot is something that should be enabled or disabled in > >> >> firmware settings, and not triggered by the PPeP partition containing a > >> >> signature. > >> >> > >> >> When secure boot is enabled checking the grub signature is required and > >> >> un-signed grub is invalid. When secure boot is disabled the signature > >> >> is irrelevant and stale signature should not cause any error. > >> > > >> > What I'm concerned about here - and it's possible I explained it poorly > >> > at Plumbers - is how a systems administrator would distinguish between > >> > having accidentally installed an unsigned grub, and having installed a > >> > grub with a broken or untrusted signature. > >> > > >> > Having said that, ... > >> > > >> >> grub-install can also remove the signature magic when installing > >> >> un-signed grub for consistency. Users using dd to install un-signed > >> >> grub might still have an old signature at the end of the partition. > >> > > >> > if we make grub-install do the right thing, I think that sufficiently > >> > mitigates my concern. > >> > > >> > Thanks again, and I'll let you know how I get on shortly. > >> > > >> > Kind regards, > >> > Daniel ^ permalink raw reply [flat|nested] 14+ messages in thread
end of thread, other threads:[~2020-11-04 18:04 UTC | newest]
Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2020-08-21 2:37 [PATCH 0/3] Add support for signing grub with an appended signature Daniel Axtens
2020-08-21 2:37 ` [PATCH 1/3] Add suport " Daniel Axtens
2020-08-21 2:37 ` [PATCH 2/3] docs/grub: Document signing grub under UEFI Daniel Axtens
2020-08-21 2:37 ` [PATCH 3/3] docs/grub: Document signing grub with an appended signature Daniel Axtens
2020-10-20 3:54 ` Michael Chang
2020-10-20 4:51 ` Daniel Axtens
2020-10-20 5:58 ` Michael Chang
2020-09-23 15:11 ` [PATCH 0/3] Add support for " Daniel Axtens
-- strict thread matches above, loose matches on Subject: below --
2020-10-16 11:20 Michal Suchánek
[not found] ` <871rhuwi80.fsf@dja-thinkpad.axtens.net>
2020-10-19 23:18 ` Daniel Axtens
2020-10-22 4:25 ` Daniel Axtens
2020-10-22 11:14 ` Michal Suchánek
2020-10-23 5:33 ` Daniel Axtens
2020-11-04 18:04 ` Michal Suchánek
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox