diff --git a/include/grub/util/install.h b/include/grub/util/install.h index 5c0a52ca2..3aabc4285 100644 --- a/include/grub/util/install.h +++ b/include/grub/util/install.h @@ -69,6 +69,8 @@ N_("disable shim_lock verifier"), 0 }, \ { "disable-cli", GRUB_INSTALL_OPTIONS_DISABLE_CLI, 0, 0, \ N_("disabled command line interface access"), 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 } @@ -132,7 +134,8 @@ enum grub_install_options { GRUB_INSTALL_OPTIONS_DTB, GRUB_INSTALL_OPTIONS_SBAT, GRUB_INSTALL_OPTIONS_DISABLE_SHIM_LOCK, - GRUB_INSTALL_OPTIONS_DISABLE_CLI + GRUB_INSTALL_OPTIONS_DISABLE_CLI, + GRUB_INSTALL_OPTIONS_APPENDED_SIGNATURE_SIZE }; extern char *grub_install_source_directory; @@ -192,7 +195,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 char *sbat_path, const int disable_shim_lock, const int disable_cli); diff --git a/include/grub/util/mkimage.h b/include/grub/util/mkimage.h index 9d74f82c5..0d40383eb 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, 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, 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 22bccb6a3..102ab18b0 100644 --- a/util/grub-install-common.c +++ b/util/grub-install-common.c @@ -467,10 +467,13 @@ static char *sbat; static int disable_shim_lock; static grub_compression_t compression; static int disable_cli; +static size_t appsig_size; int grub_install_parse (int key, char *arg) { + const char *end; + switch (key) { case GRUB_INSTALL_OPTIONS_INSTALL_CORE_COMPRESS: @@ -571,6 +574,13 @@ 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: + 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; } @@ -683,9 +693,10 @@ grub_install_make_image_wrap_file (const char *dir, const char *prefix, *p = '\0'; grub_util_info ("grub-mkimage --directory '%s' --prefix '%s' --output '%s'" - " --format '%s' --compression '%s'%s%s%s%s\n", + " --format '%s' --compression '%s'" + " --appended-signature-size %zu %s %s %s %s\n", dir, prefix, outname, - mkimage_target, compnames[compression], + mkimage_target, compnames[compression], appsig_size, note ? " --note" : "", disable_shim_lock ? " --disable-shim-lock" : "", disable_cli ? " --disable-cli" : "", s); @@ -698,7 +709,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, sbat, + note, appsig_size, compression, dtb, sbat, disable_shim_lock, disable_cli); while (dc--) grub_install_pop_module (); diff --git a/util/grub-mkimage.c b/util/grub-mkimage.c index 547f7310f..d3a5aaa5f 100644 --- a/util/grub-mkimage.c +++ b/util/grub-mkimage.c @@ -84,6 +84,7 @@ 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}, + {"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 } }; @@ -130,6 +131,7 @@ struct arguments int note; int disable_shim_lock; int disable_cli; + size_t appsig_size; const struct grub_install_image_target_desc *image_target; grub_compression_t comp; }; @@ -140,6 +142,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) { @@ -172,6 +175,14 @@ argp_parser (int key, char *arg, struct argp_state *state) arguments->note = 1; break; + case 'S': + 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': if (arguments->memdisk) free (arguments->memdisk); @@ -330,6 +341,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, arguments.sbat, arguments.disable_shim_lock, arguments.disable_cli); diff --git a/util/grub-mkimagexx.c b/util/grub-mkimagexx.c index 45ac77558..7fe2e35e6 100644 --- a/util/grub-mkimagexx.c +++ b/util/grub-mkimagexx.c @@ -115,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) { @@ -216,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, 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) { @@ -237,6 +245,12 @@ SUFFIX (grub_mkimage_generate_elf) (const struct grub_install_image_target_desc footer_size += ALIGN_UP (sizeof (struct grub_sbat_note) + layout->sbat_size, 4); } + if (appsig_size) + { + phnum++; + footer_size += ALIGN_UP (sizeof (struct grub_appended_signature_note), 4); + } + if (image_target->id != IMAGE_LOONGSON_ELF) phnum += 2; @@ -518,6 +532,30 @@ SUFFIX (grub_mkimage_generate_elf) (const struct grub_install_image_target_desc memcpy (note_ptr->name, GRUB_SBAT_NOTE_NAME, sizeof (GRUB_SBAT_NOTE_NAME)); memcpy ((char *)(note_ptr + 1), sbat, layout->sbat_size); + 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); + 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 *) 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); + phdr++; phdr->p_type = grub_host_to_target32 (PT_NOTE); phdr->p_flags = grub_host_to_target32 (PF_R); diff --git a/util/mkimage.c b/util/mkimage.c index b46df2909..9618b37cf 100644 --- a/util/mkimage.c +++ b/util/mkimage.c @@ -885,7 +885,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, const char *sbat_path, int disable_shim_lock, int disable_cli) { @@ -946,6 +946,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); @@ -1833,10 +1836,10 @@ 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, sbat, &core_img, &core_size, + 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, sbat, &core_img, &core_size, + grub_mkimage_generate_elf64 (image_target, note, sbat, appsig_size, &core_img, &core_size, target_addr, &layout); } break;