* [PATCH v13 00/20] Appended Signature Secure Boot Support for PowerPC
@ 2025-09-30 11:39 Sudhakar Kuppusamy
2025-09-30 11:39 ` [PATCH v13 01/20] powerpc-ieee1275: Add support for signing GRUB with an appended signature Sudhakar Kuppusamy
` (20 more replies)
0 siblings, 21 replies; 25+ messages in thread
From: Sudhakar Kuppusamy @ 2025-09-30 11:39 UTC (permalink / raw)
To: grub-devel
Cc: dja, jan.setjeeilers, julian.klode, mate.kukri, pjones, msuchanek,
mlewando, stefanb, avnish, nayna, ssrish, Sudhakar Kuppusamy,
sridharm
This patch set contains v13 the consolidated version of the patch
sets for secure boot using appended signatures on powerpc,
rebased on top of git HEAD.
The v12 series is at
https://lists.gnu.org/archive/html/grub-devel/2025-09/msg00197.html
Changes since v12:
- Daniel Kiper review comments addressed:
- v13 patch 11: changed the function name from grub_pks_tmp_free to
grub_pks_free_data, corrected the typo error.
- v13 patch 12 - 20: Addressed all comments.
- v13: Removed the patch 16 and patch 17 from v12.
Linux on Power LPAR secure boot ensures the integrity of the Linux boot
stack. The hypervisor and partition firmware are part of the core root of
trust. The partition firmware verifies the signature on the GRUB image
before handing control to GRUB. Similarly, GRUB verifies the signature on
the kernel image before booting the OS. This ensures that every image
running at the boot time is verified and trusted. UEFI platforms relies
on PECOFF based signature scheme. Since Power is not a UEFI platform, an
alternative mechanism is needed. Power already uses appended signatures
on the Linux Kernel, and is now extended to sign the grub as well.
Linux on Power also allows multiple signers, and if any one of the
signature passes, then the image passes the validation. Appended signature
scheme uses CMS structure to contain signatures. On Power, the multiple
signature support relies on the multiple signers features already supported
by CMS standards. It does require that all the signers should sign at the
same time and are not allowed to add or remove the signatures randomly.
By default, Linux LPAR secure boot uses static key management[1]. This means
that each image embeds the keys it needs to verify the image it loads.
For example, the keys used to verify the GRUB image are built into the
firmware image. Similarly, the keys used for verifying the kernel image
are built into the GRUB image. These are pre-defined keys and they cannot
be modified at runtime. The drawback of this approach is that key rotations
results in both firmware and OS updates. This is where dynamic key
management is useful.
An admin can switch from static keys to dynamic keys by coordinating with
Hardware Management Console(HMC) admin and enabling the required flags
for the given LPAR.
The dynamic key management relies on the Platform KeyStore(PKS)[2] storage
allocation for each LPAR with individually managed access controls to
store sensitive information securely. Once switched to dynamic keys, HMC
advertises this flag to the PowerVM, which then initializes the PKS
with the default secvars. It also creates a variable SB_VERSION that
represents the secure boot key management mode. The default secvars are
used by Partition firmware, grub and the linux kernel to reads keys for
verification. These secvars can be managed by user interface exposed via
linux kernel. The linux kernel already supports this interface and
it is available in the upstream kernel.
This patchset adds the appended signature support both for signing and
verification and the key management to the grub component. The whole
patchset can be split into following four main parts:
The series has following four main parts:
1.) Sign grub.elf with an appended signature. (Patches 1, 18, 19)
These patches provide some infrastructure and documentation for
signing grub's core.elf with a Linux-kernel-module style appended
signature.
An appended signature is a 'dumb' signature over the contents of a
file. (It is distinct from schemes like Authenticode that are aware of
the structure of the file and only sign certain parts.) The signature
is wrapped in a PKCS#7 message, and is appended to the signed file
along with some metadata and a magic string. The signatures are
validated against a public key which is usually provided as an x509
certificate.
Because some platforms, such as powerpc-ieee1275, may 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.
2.) Enable lockdown if secure boot is enabled (Patch 9)
Read secure boot mode from 'ibm,secure-boot' property and
If the 'ibm,secure-boot' property of the root node is 2,
enter lockdown. Else it is considered as disabled.
There are three secure boot modes. They are
0 - disabled
No signature verification is performed. This is the default.
1 - audit
Signature verification is performed and if signature verification
fails, post the errors and allow the boot to continue.
2 - enforce
Lockdown the GRUB. Signature verification is performed and
If signature verification fails, post the errors and stop the boot.
Now, only support disabled and enforce.
3.) Enable appended signature verification using builtin keys (Patches 2 - 8
and 10).
Part of a secure boot chain is allowing grub to verify the boot
kernel. For UEFI platforms, this is usually delegated to the
shim. However, for platforms that do not implement UEFI, an
alternative scheme is required.
This part teaches grub how to verify Linux kernel-style appended
signatures. Kernels on powerpc are already signed with this scheme and
can be verified by IMA for kexec.
As PKCS#7 messages and x509 certificates are both based on ASN.1, we
import libtasn1 to parse them. Because ASN.1 isn't self-documenting,
we import from GNUTLS the information we need to navigate their
structure.
This section is composed of the following patches:
- patches 2 and 3 are small refactorings.
- patch 4 allows x509 certificates to be built in to the grub core
in much the same way as PGP keys.
- patch 5 brings in the code from GNUTLS that allows us to parse
PKCS#7 and x509 with libtasn1.
- patch 6, 7 and 8 is our ASN1 node, PKCS#7 and x509 parser. They're minimal
and fairly strict parsers that extract only the bits we need to verify the
signatures.
- patch 10 is the guts of the appended signature verifier.
4.) Enable accessing keys dynamically from Platform KeyStore (Patch 11 - 16)
This part teaches grub how to read db and dbx variables from platform keystore
using client interface call then load keys from those two variable, and use it
to verify Linux kernel.
This section is composed of the following patches:
- patch 11 is an exposes an interface in ieee1275 for reading secure boot
variable db and dbx from Platform Keystore. Read secure boot variables
such as db and dbx from PKS and extract certificates from ESL.
- patch 12 is introducing key management environment variable.
- patch 13 is create the db and dbx lists from PKS.
- patch 14 is verify the kernel using db and dbx lists
- patch 15 is GRUB commands to manage the certificates
- patch 16 adds GRUB commands to access db and dbx.
5.) patch 17 adds unit test and 20 adds GRUB commands and an appended signatures
documentation.
Thanks to Daniel Kiper for providing review comments.
I've pushed this all to
https://github.com/SudhakarKuppusamy1/grub/tree/appendedsig-2.13
[1]https://www.ibm.com/docs/en/linux-on-systems?topic=servers-guest-secure-boot-static-keys
[2]https://community.ibm.com/community/user/power/blogs/chris-engel1/2020/11/20/powervm-introduces-the-platform-keystore
Daniel Axtens (2):
crypto: Move storage for grub_crypto_pk_* to crypto.c
docs/grub: Document signing GRUB under UEFI
Sudhakar Kuppusamy (18):
powerpc-ieee1275: Add support for signing GRUB with an appended
signature
pgp: Rename OBJ_TYPE_PUBKEY to OBJ_TYPE_GPG_PUBKEY
grub-install: Support embedding x509 certificates
appended signatures: Import GNUTLS's ASN.1 description files
appended signatures: Parse ASN1 node
appended signatures: Parse PKCS#7 signed data
appended signatures: Parse X.509 certificates
powerpc_ieee1275: Enter lockdown based on /ibm,secure-boot
appended signatures: Support verifying appended signatures
powerpc_ieee1275: Read the db and dbx secure boot variables
appended signatures: Introducing key management environment variable
appended signatures: Create db and dbx lists
appended signatures: Using db and dbx lists for signature verification
appended signatures: GRUB commands to manage the certificates
appended signatures: GRUB commands to manage the hashes
appended signatures: Verification tests
docs/grub: Document signing GRUB with an appended signature
docs/grub: Document appended signature
docs/grub.texi | 475 ++++-
grub-core/Makefile.am | 2 +
grub-core/Makefile.core.def | 26 +
grub-core/commands/appendedsig/appendedsig.c | 1723 +++++++++++++++++
grub-core/commands/appendedsig/appendedsig.h | 133 ++
grub-core/commands/appendedsig/asn1util.c | 99 +
.../commands/appendedsig/gnutls_asn1_tab.c | 148 ++
grub-core/commands/appendedsig/pkcs7.c | 452 +++++
.../commands/appendedsig/pkix_asn1_tab.c | 485 +++++
grub-core/commands/appendedsig/x509.c | 970 ++++++++++
grub-core/commands/pgp.c | 6 +-
grub-core/kern/ieee1275/ieee1275.c | 1 -
grub-core/kern/ieee1275/init.c | 58 +
grub-core/kern/powerpc/ieee1275/ieee1275.c | 137 ++
.../kern/powerpc/ieee1275/platform_keystore.c | 344 ++++
grub-core/lib/crypto.c | 4 +
grub-core/tests/appended_signature_test.c | 348 ++++
grub-core/tests/appended_signatures.h | 975 ++++++++++
grub-core/tests/lib/functional_test.c | 1 +
include/grub/crypto.h | 1 +
include/grub/efi/pks.h | 112 ++
include/grub/err.h | 3 +-
include/grub/file.h | 4 +
include/grub/ieee1275/ieee1275.h | 3 +
include/grub/kernel.h | 3 +-
include/grub/lockdown.h | 3 +-
include/grub/powerpc/ieee1275/ieee1275.h | 18 +
.../grub/powerpc/ieee1275/platform_keystore.h | 122 ++
include/grub/types.h | 4 +
include/grub/util/install.h | 10 +-
include/grub/util/mkimage.h | 4 +-
util/grub-install-common.c | 36 +-
util/grub-mkimage.c | 26 +-
util/grub-mkimagexx.c | 40 +-
util/mkimage.c | 50 +-
35 files changed, 6782 insertions(+), 44 deletions(-)
create mode 100644 grub-core/commands/appendedsig/appendedsig.c
create mode 100644 grub-core/commands/appendedsig/appendedsig.h
create mode 100644 grub-core/commands/appendedsig/asn1util.c
create mode 100644 grub-core/commands/appendedsig/gnutls_asn1_tab.c
create mode 100644 grub-core/commands/appendedsig/pkcs7.c
create mode 100644 grub-core/commands/appendedsig/pkix_asn1_tab.c
create mode 100644 grub-core/commands/appendedsig/x509.c
create mode 100644 grub-core/kern/powerpc/ieee1275/ieee1275.c
create mode 100644 grub-core/kern/powerpc/ieee1275/platform_keystore.c
create mode 100644 grub-core/tests/appended_signature_test.c
create mode 100644 grub-core/tests/appended_signatures.h
create mode 100644 include/grub/efi/pks.h
create mode 100644 include/grub/powerpc/ieee1275/platform_keystore.h
--
2.50.1 (Apple Git-155)
_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel
^ permalink raw reply [flat|nested] 25+ messages in thread* [PATCH v13 01/20] powerpc-ieee1275: Add support for signing GRUB with an appended signature 2025-09-30 11:39 [PATCH v13 00/20] Appended Signature Secure Boot Support for PowerPC Sudhakar Kuppusamy @ 2025-09-30 11:39 ` Sudhakar Kuppusamy 2025-09-30 11:39 ` [PATCH v13 02/20] crypto: Move storage for grub_crypto_pk_* to crypto.c Sudhakar Kuppusamy ` (19 subsequent siblings) 20 siblings, 0 replies; 25+ messages in thread From: Sudhakar Kuppusamy @ 2025-09-30 11:39 UTC (permalink / raw) To: grub-devel Cc: dja, jan.setjeeilers, julian.klode, mate.kukri, pjones, msuchanek, mlewando, stefanb, avnish, nayna, ssrish, Sudhakar Kuppusamy, sridharm, Rashmica Gupta, Daniel Kiper 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 | 7 +++++-- include/grub/util/mkimage.h | 4 ++-- util/grub-install-common.c | 17 +++++++++++++--- util/grub-mkimage.c | 12 +++++++++++ util/grub-mkimagexx.c | 40 ++++++++++++++++++++++++++++++++++++- util/mkimage.c | 9 ++++++--- 6 files changed, 78 insertions(+), 11 deletions(-) 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; -- 2.50.1 (Apple Git-155) _______________________________________________ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel ^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH v13 02/20] crypto: Move storage for grub_crypto_pk_* to crypto.c 2025-09-30 11:39 [PATCH v13 00/20] Appended Signature Secure Boot Support for PowerPC Sudhakar Kuppusamy 2025-09-30 11:39 ` [PATCH v13 01/20] powerpc-ieee1275: Add support for signing GRUB with an appended signature Sudhakar Kuppusamy @ 2025-09-30 11:39 ` Sudhakar Kuppusamy 2025-09-30 11:39 ` [PATCH v13 03/20] pgp: Rename OBJ_TYPE_PUBKEY to OBJ_TYPE_GPG_PUBKEY Sudhakar Kuppusamy ` (18 subsequent siblings) 20 siblings, 0 replies; 25+ messages in thread From: Sudhakar Kuppusamy @ 2025-09-30 11:39 UTC (permalink / raw) To: grub-devel Cc: dja, jan.setjeeilers, julian.klode, mate.kukri, pjones, msuchanek, mlewando, stefanb, avnish, nayna, ssrish, sridharm, Sudhakar Kuppusamy, Vladimir Serbinenko, Daniel Kiper From: Daniel Axtens <dja@axtens.net> The way gcry_rsa and friends (the asymmetric ciphers) are loaded for the pgp module is a bit quirky. include/grub/crypto.h contains: extern struct gcry_pk_spec *grub_crypto_pk_rsa; commands/pgp.c contains the actual storage: struct gcry_pk_spec *grub_crypto_pk_rsa; And the module itself saves to the storage in pgp.c: GRUB_MOD_INIT(gcry_rsa) { grub_crypto_pk_rsa = &_gcry_pubkey_spec_rsa; } This is annoying: gcry_rsa now has a dependency on pgp! We want to be able to bring in gcry_rsa without bringing in PGP, so move the storage to crypto.c. Previously, gcry_rsa depended on pgp and mpi. Now it depends on crypto and mpi. As pgp depends on crypto, this doesn't add any new module dependencies using the PGP verfier. [FWIW, the story is different for the symmetric ciphers. cryptodisk and friends (zfs encryption etc) use grub_crypto_lookup_cipher_by_name() to get a cipher handle. That depends on grub_ciphers being populated by people calling grub_cipher_register. import_gcry.py ensures that the symmetric ciphers call it.] 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: Vladimir Serbinenko <phcoder@gmail.com> Reviewed-by: Avnish Chouhan <avnish@linux.ibm.com> Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com> --- grub-core/commands/pgp.c | 4 ---- grub-core/lib/crypto.c | 4 ++++ 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/grub-core/commands/pgp.c b/grub-core/commands/pgp.c index e61887862..251ed1b06 100644 --- a/grub-core/commands/pgp.c +++ b/grub-core/commands/pgp.c @@ -136,10 +136,6 @@ struct signature_v4_header grub_uint16_t hashed_sub; } GRUB_PACKED; -struct gcry_pk_spec *grub_crypto_pk_dsa; -struct gcry_pk_spec *grub_crypto_pk_ecdsa; -struct gcry_pk_spec *grub_crypto_pk_rsa; - struct { const char *name; diff --git a/grub-core/lib/crypto.c b/grub-core/lib/crypto.c index dd60dd4ac..292b747b2 100644 --- a/grub-core/lib/crypto.c +++ b/grub-core/lib/crypto.c @@ -170,6 +170,10 @@ grub_md_unregister (gcry_md_spec_t *cipher) } } +struct gcry_pk_spec *grub_crypto_pk_dsa; +struct gcry_pk_spec *grub_crypto_pk_ecdsa; +struct gcry_pk_spec *grub_crypto_pk_rsa; + void grub_crypto_hash (const gcry_md_spec_t *hash, void *out, const void *in, grub_size_t inlen) -- 2.50.1 (Apple Git-155) _______________________________________________ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel ^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH v13 03/20] pgp: Rename OBJ_TYPE_PUBKEY to OBJ_TYPE_GPG_PUBKEY 2025-09-30 11:39 [PATCH v13 00/20] Appended Signature Secure Boot Support for PowerPC Sudhakar Kuppusamy 2025-09-30 11:39 ` [PATCH v13 01/20] powerpc-ieee1275: Add support for signing GRUB with an appended signature Sudhakar Kuppusamy 2025-09-30 11:39 ` [PATCH v13 02/20] crypto: Move storage for grub_crypto_pk_* to crypto.c Sudhakar Kuppusamy @ 2025-09-30 11:39 ` Sudhakar Kuppusamy 2025-09-30 11:39 ` [PATCH v13 04/20] grub-install: Support embedding x509 certificates Sudhakar Kuppusamy ` (17 subsequent siblings) 20 siblings, 0 replies; 25+ messages in thread From: Sudhakar Kuppusamy @ 2025-09-30 11:39 UTC (permalink / raw) To: grub-devel Cc: dja, jan.setjeeilers, julian.klode, mate.kukri, pjones, msuchanek, mlewando, stefanb, avnish, nayna, ssrish, Sudhakar Kuppusamy, sridharm, Alastair D'Silva, Daniel Kiper Prior to the addition of the X.509 public key support for appended signature, current PGP signature relied on the GPG public key. Changing the enum name from "OBJ_TYPE_PUBKEY" to "OBJ_TYPE_GPG_PUBKEY" to differentiate between x509 certificate based appended signature and GPG certificate based PGP signature. Signed-off-by: Alastair D'Silva <alastair@d-silva.org> Signed-off-by: Daniel Axtens <dja@axtens.net> Signed-off-by: Sudhakar Kuppusamy <sudhakar@linux.ibm.com> Reviewed-by: Avnish Chouhan <avnish@linux.ibm.com> Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com> --- docs/grub.texi | 34 +++++++++++++++++----------------- grub-core/commands/pgp.c | 2 +- include/grub/kernel.h | 2 +- util/grub-mkimage.c | 2 +- util/mkimage.c | 2 +- 5 files changed, 21 insertions(+), 21 deletions(-) diff --git a/docs/grub.texi b/docs/grub.texi index b81eb1d93..37297fc2c 100644 --- a/docs/grub.texi +++ b/docs/grub.texi @@ -3357,8 +3357,8 @@ entry when selected. @node check_signatures @subsection check_signatures -This variable controls whether GRUB enforces digital signature -validation on loaded files. @xref{Using digital signatures}. +This variable controls whether GRUB enforces GPG-style digital signature +validation on loaded files. @xref{Using GPG-style digital signatures}. @node chosen @subsection chosen @@ -7054,7 +7054,7 @@ These keys are used to validate signatures when environment variable @code{check_signatures} is set to @code{enforce} (@pxref{check_signatures}), and by some invocations of @command{verify_detached} (@pxref{verify_detached}). @xref{Using -digital signatures}, for more information. +GPG-style digital signatures}, for more information. @end deffn @node drivemap @@ -7470,7 +7470,7 @@ The output is in GPG's v4 key fingerprint format (i.e., the output of @code{gpg --fingerprint}). The least significant four bytes (last eight hexadecimal digits) can be used as an argument to @command{distrust} (@pxref{distrust}). -@xref{Using digital signatures}, for more information about uses for +@xref{Using GPG-style digital signatures}, for more information about uses for these keys. @end deffn @@ -7505,7 +7505,7 @@ When used with care, @option{--skip-sig} and the whitelist enable an administrator to configure a system to boot only signed configurations, but to allow the user to select from among multiple configurations, and to enable ``one-shot'' boot attempts and -``savedefault'' behavior. @xref{Using digital signatures}, for more +``savedefault'' behavior. @xref{Using GPG-style digital signatures}, for more information. @end deffn @@ -7877,7 +7877,7 @@ read. It is possible to modify a digitally signed environment block file from within GRUB using this command, such that its signature will no longer be valid on subsequent boots. Care should be taken in such advanced configurations to avoid rendering the system -unbootable. @xref{Using digital signatures}, for more information. +unbootable. @xref{Using GPG-style digital signatures}, for more information. @end deffn @@ -8367,7 +8367,7 @@ signatures when environment variable @code{check_signatures} is set to must itself be properly signed. The @option{--skip-sig} option can be used to disable signature-checking when reading @var{pubkey_file} itself. It is expected that @option{--skip-sig} is useful for testing -and manual booting. @xref{Using digital signatures}, for more +and manual booting. @xref{Using GPG-style digital signatures}, for more information. @end deffn @@ -8440,7 +8440,7 @@ tried. Exit code @code{$?} is set to 0 if the signature validates successfully. If validation fails, it is set to a non-zero value. -@xref{Using digital signatures}, for more information. +@xref{Using GPG-style digital signatures}, for more information. @end deffn @node videoinfo @@ -8900,13 +8900,13 @@ environment variables and commands are listed in the same order. @chapter Security @menu -* Authentication and authorisation:: Users and access control -* Using digital signatures:: Booting digitally signed code -* UEFI secure boot and shim:: Booting digitally signed PE files -* Secure Boot Advanced Targeting:: Embedded information for generation number based revocation -* Measured Boot:: Measuring boot components -* Lockdown:: Lockdown when booting on a secure setup -* TPM2 key protector:: Managing disk key with TPM2 key protector +* Authentication and authorisation:: Users and access control +* Using GPG-style digital signatures:: Booting digitally signed code +* UEFI secure boot and shim:: Booting digitally signed PE files +* Secure Boot Advanced Targeting:: Embedded information for generation number based revocation +* Measured Boot:: Measuring boot components +* Lockdown:: Lockdown when booting on a secure setup +* TPM2 key protector:: Managing disk key with TPM2 key protector @end menu @node Authentication and authorisation @@ -8982,8 +8982,8 @@ generating configuration files with authentication. You can use adding @kbd{set superusers=} and @kbd{password} or @kbd{password_pbkdf2} commands. -@node Using digital signatures -@section Using digital signatures in GRUB +@node Using GPG-style digital signatures +@section Using GPG-style digital signatures in GRUB GRUB's @file{core.img} can optionally provide enforcement that all files subsequently read from disk are covered by a valid digital signature. diff --git a/grub-core/commands/pgp.c b/grub-core/commands/pgp.c index 251ed1b06..a2549f9fd 100644 --- a/grub-core/commands/pgp.c +++ b/grub-core/commands/pgp.c @@ -920,7 +920,7 @@ GRUB_MOD_INIT(pgp) grub_memset (&pseudo_file, 0, sizeof (pseudo_file)); /* Not an ELF module, skip. */ - if (header->type != OBJ_TYPE_PUBKEY) + if (header->type != OBJ_TYPE_GPG_PUBKEY) continue; pseudo_file.fs = &pseudo_fs; diff --git a/include/grub/kernel.h b/include/grub/kernel.h index 6121c1e66..885289f5d 100644 --- a/include/grub/kernel.h +++ b/include/grub/kernel.h @@ -28,7 +28,7 @@ enum OBJ_TYPE_MEMDISK, OBJ_TYPE_CONFIG, OBJ_TYPE_PREFIX, - OBJ_TYPE_PUBKEY, + OBJ_TYPE_GPG_PUBKEY, OBJ_TYPE_DTB, OBJ_TYPE_DISABLE_SHIM_LOCK, OBJ_TYPE_DISABLE_CLI diff --git a/util/grub-mkimage.c b/util/grub-mkimage.c index d3a5aaa5f..9370e609f 100644 --- a/util/grub-mkimage.c +++ b/util/grub-mkimage.c @@ -75,7 +75,7 @@ static struct argp_option options[] = { /* TRANSLATORS: "embed" is a verb (command description). "*/ {"config", 'c', N_("FILE"), 0, N_("embed FILE as an early config"), 0}, /* TRANSLATORS: "embed" is a verb (command description). "*/ - {"pubkey", 'k', N_("FILE"), 0, N_("embed FILE as public key for signature checking"), 0}, + {"pubkey", 'k', N_("FILE"), 0, N_("embed FILE as public key for PGP signature checking"), 0}, /* TRANSLATORS: NOTE is a name of segment. */ {"note", 'n', 0, 0, N_("add NOTE segment for CHRP IEEE1275"), 0}, {"output", 'o', N_("FILE"), 0, N_("output a generated image to FILE [default=stdout]"), 0}, diff --git a/util/mkimage.c b/util/mkimage.c index 9618b37cf..61c4e78e2 100644 --- a/util/mkimage.c +++ b/util/mkimage.c @@ -1056,7 +1056,7 @@ grub_install_generate_image (const char *dir, const char *prefix, curs = grub_util_get_image_size (pubkey_paths[i]); header = (struct grub_module_header *) (kernel_img + offset); - header->type = grub_host_to_target32 (OBJ_TYPE_PUBKEY); + header->type = grub_host_to_target32 (OBJ_TYPE_GPG_PUBKEY); header->size = grub_host_to_target32 (curs + sizeof (*header)); offset += sizeof (*header); -- 2.50.1 (Apple Git-155) _______________________________________________ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel ^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH v13 04/20] grub-install: Support embedding x509 certificates 2025-09-30 11:39 [PATCH v13 00/20] Appended Signature Secure Boot Support for PowerPC Sudhakar Kuppusamy ` (2 preceding siblings ...) 2025-09-30 11:39 ` [PATCH v13 03/20] pgp: Rename OBJ_TYPE_PUBKEY to OBJ_TYPE_GPG_PUBKEY Sudhakar Kuppusamy @ 2025-09-30 11:39 ` Sudhakar Kuppusamy 2025-09-30 11:39 ` [PATCH v13 05/20] appended signatures: Import GNUTLS's ASN.1 description files Sudhakar Kuppusamy ` (16 subsequent siblings) 20 siblings, 0 replies; 25+ messages in thread From: Sudhakar Kuppusamy @ 2025-09-30 11:39 UTC (permalink / raw) To: grub-devel Cc: dja, jan.setjeeilers, julian.klode, mate.kukri, pjones, msuchanek, mlewando, stefanb, avnish, nayna, ssrish, Sudhakar Kuppusamy, sridharm, Alastair D'Silva, Daniel Kiper To support verification of appended signatures, we need a way to embed the necessary public keys. Existing appended signature schemes in the Linux kernel use X.509 certificates, so allow certificates to be embedded in the GRUB core image in the same way as PGP keys. Signed-off-by: Alastair D'Silva <alastair@d-silva.org> 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/kernel.h | 1 + include/grub/util/install.h | 3 +++ util/grub-install-common.c | 19 +++++++++++++++++- util/grub-mkimage.c | 12 +++++++++++- util/mkimage.c | 39 ++++++++++++++++++++++++++++++++++++- 5 files changed, 71 insertions(+), 3 deletions(-) diff --git a/include/grub/kernel.h b/include/grub/kernel.h index 885289f5d..9f3e2031f 100644 --- a/include/grub/kernel.h +++ b/include/grub/kernel.h @@ -29,6 +29,7 @@ enum OBJ_TYPE_CONFIG, OBJ_TYPE_PREFIX, OBJ_TYPE_GPG_PUBKEY, + OBJ_TYPE_X509_PUBKEY, OBJ_TYPE_DTB, OBJ_TYPE_DISABLE_SHIM_LOCK, OBJ_TYPE_DISABLE_CLI diff --git a/include/grub/util/install.h b/include/grub/util/install.h index 3aabc4285..6f27e2e42 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 }, \ + { "x509key", 'x', N_("FILE"), 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, \ @@ -193,6 +195,7 @@ grub_install_generate_image (const char *dir, const char *prefix, const char *outname, char *mods[], char *memdisk_path, char **pubkey_paths, 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, diff --git a/util/grub-install-common.c b/util/grub-install-common.c index 102ab18b0..a913ee61c 100644 --- a/util/grub-install-common.c +++ b/util/grub-install-common.c @@ -463,6 +463,8 @@ handle_install_list (struct install_list *il, const char *val, static char **pubkeys; static size_t npubkeys; +static char **x509keys; +static size_t nx509keys; static char *sbat; static int disable_shim_lock; static grub_compression_t compression; @@ -511,6 +513,10 @@ grub_install_parse (int key, char *arg) case GRUB_INSTALL_OPTIONS_DISABLE_CLI: disable_cli = 1; return 1; + case 'x': + x509keys = xrealloc (x509keys, sizeof (x509keys[0]) * (nx509keys + 1)); + x509keys[nx509keys++] = xstrdup (arg); + return 1; case GRUB_INSTALL_OPTIONS_VERBOSITY: verbosity++; @@ -642,6 +648,9 @@ grub_install_make_image_wrap_file (const char *dir, const char *prefix, for (pk = pubkeys; pk < pubkeys + npubkeys; pk++) slen += sizeof (" --pubkey ''") + grub_strlen (*pk); + for (pk = x509keys; pk < x509keys + nx509keys; pk++) + slen += sizeof (" --x509key ''") + grub_strlen (*pk); + for (md = modules.entries; *md; md++) slen += sizeof (" ''") + grub_strlen (*md); @@ -682,6 +691,14 @@ grub_install_make_image_wrap_file (const char *dir, const char *prefix, *p++ = '\''; } + for (pk = x509keys; pk < x509keys + nx509keys; pk++) + { + p = grub_stpcpy (p, "--x509key '"); + p = grub_stpcpy (p, *pk); + *p++ = '\''; + *p++ = ' '; + } + for (md = modules.entries; *md; md++) { *p++ = ' '; @@ -708,7 +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, 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 9370e609f..fb14aa731 100644 --- a/util/grub-mkimage.c +++ b/util/grub-mkimage.c @@ -76,6 +76,7 @@ static struct argp_option options[] = { {"config", 'c', N_("FILE"), 0, N_("embed FILE as an early config"), 0}, /* TRANSLATORS: "embed" is a verb (command description). "*/ {"pubkey", 'k', N_("FILE"), 0, N_("embed FILE as public key for PGP signature checking"), 0}, + {"x509key", 'x', N_("FILE"), 0, N_("embed FILE as an x509 certificate for appended signature checking"), 0}, /* TRANSLATORS: NOTE is a name of segment. */ {"note", 'n', 0, 0, N_("add NOTE segment for CHRP IEEE1275"), 0}, {"output", 'o', N_("FILE"), 0, N_("output a generated image to FILE [default=stdout]"), 0}, @@ -125,6 +126,8 @@ struct arguments char *dtb; char **pubkeys; size_t npubkeys; + char **x509keys; + size_t nx509keys; char *font; char *config; char *sbat; @@ -209,6 +212,12 @@ argp_parser (int key, char *arg, struct argp_state *state) arguments->pubkeys[arguments->npubkeys++] = xstrdup (arg); break; + case 'x': + arguments->x509keys = xrealloc (arguments->x509keys, + sizeof (arguments->x509keys[0]) * (arguments->nx509keys + 1)); + arguments->x509keys[arguments->nx509keys++] = xstrdup (arg); + break; + case 'c': if (arguments->config) free (arguments->config); @@ -339,7 +348,8 @@ main (int argc, char *argv[]) grub_install_generate_image (arguments.dir, arguments.prefix, fp, arguments.output, arguments.modules, arguments.memdisk, arguments.pubkeys, - arguments.npubkeys, arguments.config, + arguments.npubkeys, arguments.x509keys, + arguments.nx509keys, arguments.config, arguments.image_target, arguments.note, arguments.appsig_size, arguments.comp, arguments.dtb, diff --git a/util/mkimage.c b/util/mkimage.c index 61c4e78e2..f364a5718 100644 --- a/util/mkimage.c +++ b/util/mkimage.c @@ -883,7 +883,7 @@ 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 *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, @@ -929,6 +929,24 @@ grub_install_generate_image (const char *dir, const char *prefix, } } + if (nx509keys != 0 && image_target->id != IMAGE_PPC) + grub_util_error (_("x509 public key can be support only to appended signature" + " with powerpc-ieee1275 images")); + + { + size_t i; + + for (i = 0; i < nx509keys; i++) + { + size_t curs; + + curs = ALIGN_ADDR (grub_util_get_image_size (x509key_paths[i])); + grub_util_info ("the size of x509 public key %u is 0x%" GRUB_HOST_PRIxLONG_LONG, + (unsigned) i, (unsigned long long) curs); + total_module_size += curs + sizeof (struct grub_module_header); + } + } + if (memdisk_path) { memdisk_size = ALIGN_UP(grub_util_get_image_size (memdisk_path), 512); @@ -1065,6 +1083,25 @@ grub_install_generate_image (const char *dir, const char *prefix, } } + { + size_t i; + + for (i = 0; i < nx509keys; i++) + { + size_t curs; + struct grub_module_header *header; + + curs = grub_util_get_image_size (x509key_paths[i]); + header = (struct grub_module_header *) (kernel_img + offset); + header->type = grub_host_to_target32 (OBJ_TYPE_X509_PUBKEY); + header->size = grub_host_to_target32 (curs + sizeof (*header)); + + offset += sizeof (*header); + grub_util_load_image (x509key_paths[i], kernel_img + offset); + offset += ALIGN_ADDR (curs); + } + } + if (memdisk_path) { struct grub_module_header *header; -- 2.50.1 (Apple Git-155) _______________________________________________ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel ^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH v13 05/20] appended signatures: Import GNUTLS's ASN.1 description files 2025-09-30 11:39 [PATCH v13 00/20] Appended Signature Secure Boot Support for PowerPC Sudhakar Kuppusamy ` (3 preceding siblings ...) 2025-09-30 11:39 ` [PATCH v13 04/20] grub-install: Support embedding x509 certificates Sudhakar Kuppusamy @ 2025-09-30 11:39 ` Sudhakar Kuppusamy 2025-09-30 11:40 ` [PATCH v13 06/20] appended signatures: Parse ASN1 node Sudhakar Kuppusamy ` (15 subsequent siblings) 20 siblings, 0 replies; 25+ messages in thread From: Sudhakar Kuppusamy @ 2025-09-30 11:39 UTC (permalink / raw) To: grub-devel Cc: dja, jan.setjeeilers, julian.klode, mate.kukri, pjones, msuchanek, mlewando, stefanb, avnish, nayna, ssrish, Sudhakar Kuppusamy, sridharm, Daniel Kiper In order to parse PKCS#7 messages and X.509 certificates with libtasn1, we need some information about how they are encoded. We get these from GNUTLS, which has the benefit that they support the features we need and are well tested. The GNUTLS files are from: - https://github.com/gnutls/gnutls/blob/master/lib/gnutls.asn - https://github.com/gnutls/gnutls/blob/master/lib/pkix.asn The GNUTLS license is LGPLv2.1+, which is GPLv3 compatible, allowing us to import it without issue. 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> --- .../commands/appendedsig/gnutls_asn1_tab.c | 148 ++++++ .../commands/appendedsig/pkix_asn1_tab.c | 485 ++++++++++++++++++ 2 files changed, 633 insertions(+) create mode 100644 grub-core/commands/appendedsig/gnutls_asn1_tab.c create mode 100644 grub-core/commands/appendedsig/pkix_asn1_tab.c diff --git a/grub-core/commands/appendedsig/gnutls_asn1_tab.c b/grub-core/commands/appendedsig/gnutls_asn1_tab.c new file mode 100644 index 000000000..efc0c145a --- /dev/null +++ b/grub-core/commands/appendedsig/gnutls_asn1_tab.c @@ -0,0 +1,148 @@ +#include <grub/mm.h> +#include <libtasn1.h> + +/* + * Imported from gnutls.asn. + * https://github.com/gnutls/gnutls/blob/master/lib/gnutls.asn + */ +const asn1_static_node grub_gnutls_asn1_tab[] = { + { "GNUTLS", 536872976, NULL }, + { NULL, 1073741836, NULL }, + { "RSAPublicKey", 1610612741, NULL }, + { "modulus", 1073741827, NULL }, + { "publicExponent", 3, NULL }, + { "RSAPrivateKey", 1610612741, NULL }, + { "version", 1073741827, NULL }, + { "modulus", 1073741827, NULL }, + { "publicExponent", 1073741827, NULL }, + { "privateExponent", 1073741827, NULL }, + { "prime1", 1073741827, NULL }, + { "prime2", 1073741827, NULL }, + { "exponent1", 1073741827, NULL }, + { "exponent2", 1073741827, NULL }, + { "coefficient", 1073741827, NULL }, + { "otherPrimeInfos", 16386, "OtherPrimeInfos"}, + { "ProvableSeed", 1610612741, NULL }, + { "algorithm", 1073741836, NULL }, + { "seed", 7, NULL }, + { "OtherPrimeInfos", 1612709899, NULL }, + { "MAX", 1074266122, "1"}, + { NULL, 2, "OtherPrimeInfo"}, + { "OtherPrimeInfo", 1610612741, NULL }, + { "prime", 1073741827, NULL }, + { "exponent", 1073741827, NULL }, + { "coefficient", 3, NULL }, + { "AlgorithmIdentifier", 1610612741, NULL }, + { "algorithm", 1073741836, NULL }, + { "parameters", 541081613, NULL }, + { "algorithm", 1, NULL }, + { "DigestInfo", 1610612741, NULL }, + { "digestAlgorithm", 1073741826, "DigestAlgorithmIdentifier"}, + { "digest", 7, NULL }, + { "DigestAlgorithmIdentifier", 1073741826, "AlgorithmIdentifier"}, + { "DSAPublicKey", 1073741827, NULL }, + { "DSAParameters", 1610612741, NULL }, + { "p", 1073741827, NULL }, + { "q", 1073741827, NULL }, + { "g", 3, NULL }, + { "DSASignatureValue", 1610612741, NULL }, + { "r", 1073741827, NULL }, + { "s", 3, NULL }, + { "DSAPrivateKey", 1610612741, NULL }, + { "version", 1073741827, NULL }, + { "p", 1073741827, NULL }, + { "q", 1073741827, NULL }, + { "g", 1073741827, NULL }, + { "Y", 1073741827, NULL }, + { "priv", 3, NULL }, + { "DHParameter", 1610612741, NULL }, + { "prime", 1073741827, NULL }, + { "base", 1073741827, NULL }, + { "privateValueLength", 16387, NULL }, + { "pkcs-11-ec-Parameters", 1610612754, NULL }, + { "oId", 1073741836, NULL }, + { "curveName", 31, NULL }, + { "ECParameters", 1610612754, NULL }, + { "namedCurve", 12, NULL }, + { "ECPrivateKey", 1610612741, NULL }, + { "Version", 1073741827, NULL }, + { "privateKey", 1073741831, NULL }, + { "parameters", 1610637314, "ECParameters"}, + { NULL, 2056, "0"}, + { "publicKey", 536895494, NULL }, + { NULL, 2056, "1"}, + { "PrincipalName", 1610612741, NULL }, + { "name-type", 1610620931, NULL }, + { NULL, 2056, "0"}, + { "name-string", 536879115, NULL }, + { NULL, 1073743880, "1"}, + { NULL, 27, NULL }, + { "KRB5PrincipalName", 1610612741, NULL }, + { "realm", 1610620955, NULL }, + { NULL, 2056, "0"}, + { "principalName", 536879106, "PrincipalName"}, + { NULL, 2056, "1"}, + { "RSAPSSParameters", 1610612741, NULL }, + { "hashAlgorithm", 1610637314, "AlgorithmIdentifier"}, + { NULL, 2056, "0"}, + { "maskGenAlgorithm", 1610637314, "AlgorithmIdentifier"}, + { NULL, 2056, "1"}, + { "saltLength", 1610653699, NULL }, + { NULL, 1073741833, "20"}, + { NULL, 2056, "2"}, + { "trailerField", 536911875, NULL }, + { NULL, 1073741833, "1"}, + { NULL, 2056, "3"}, + { "RSAOAEPParameters", 1610612741, NULL }, + { "hashAlgorithm", 1610637314, "AlgorithmIdentifier"}, + { NULL, 2056, "0"}, + { "maskGenAlgorithm", 1610637314, "AlgorithmIdentifier"}, + { NULL, 2056, "1"}, + { "pSourceFunc", 536895490, "AlgorithmIdentifier"}, + { NULL, 2056, "2"}, + { "GOSTParameters", 1610612741, NULL }, + { "publicKeyParamSet", 1073741836, NULL }, + { "digestParamSet", 16396, NULL }, + { "GOSTParametersOld", 1610612741, NULL }, + { "publicKeyParamSet", 1073741836, NULL }, + { "digestParamSet", 1073741836, NULL }, + { "encryptionParamSet", 16396, NULL }, + { "GOSTPrivateKey", 1073741831, NULL }, + { "GOSTPrivateKeyOld", 1073741827, NULL }, + { "IssuerSignTool", 1610612741, NULL }, + { "signTool", 1073741858, NULL }, + { "cATool", 1073741858, NULL }, + { "signToolCert", 1073741858, NULL }, + { "cAToolCert", 34, NULL }, + { "Gost28147-89-EncryptedKey", 1610612741, NULL }, + { "encryptedKey", 1073741831, NULL }, + { "maskKey", 1610637319, NULL }, + { NULL, 4104, "0"}, + { "macKey", 7, NULL }, + { "SubjectPublicKeyInfo", 1610612741, NULL }, + { "algorithm", 1073741826, "AlgorithmIdentifier"}, + { "subjectPublicKey", 6, NULL }, + { "GostR3410-TransportParameters", 1610612741, NULL }, + { "encryptionParamSet", 1073741836, NULL }, + { "ephemeralPublicKey", 1610637314, "SubjectPublicKeyInfo"}, + { NULL, 4104, "0"}, + { "ukm", 7, NULL }, + { "GostR3410-KeyTransport", 1610612741, NULL }, + { "sessionEncryptedKey", 1073741826, "Gost28147-89-EncryptedKey"}, + { "transportParameters", 536895490, "GostR3410-TransportParameters"}, + { NULL, 4104, "0"}, + { "TPMKey", 1610612741, NULL }, + { "type", 1073741836, NULL }, + { "emptyAuth", 1610637316, NULL }, + { NULL, 2056, "0"}, + { "parent", 1073741827, NULL }, + { "pubkey", 1073741831, NULL }, + { "privkey", 7, NULL }, + { "MLDSAPrivateKey", 536870917, NULL }, + { "version", 1073741827, NULL }, + { "privateKeyAlgorithm", 1073741826, "AlgorithmIdentifier"}, + { "privateKey", 1073741831, NULL }, + { "publicKey", 536895495, NULL }, + { NULL, 2056, "1"}, + { NULL, 0, NULL } +}; diff --git a/grub-core/commands/appendedsig/pkix_asn1_tab.c b/grub-core/commands/appendedsig/pkix_asn1_tab.c new file mode 100644 index 000000000..ec5f87bfd --- /dev/null +++ b/grub-core/commands/appendedsig/pkix_asn1_tab.c @@ -0,0 +1,485 @@ +#include <grub/mm.h> +#include <libtasn1.h> + +/* + * Imported from pkix.asn. + * https://github.com/gnutls/gnutls/blob/master/lib/pkix.asn + */ +const asn1_static_node grub_pkix_asn1_tab[] = { + { "PKIX1", 536875024, NULL }, + { NULL, 1073741836, NULL }, + { "PrivateKeyUsagePeriod", 1610612741, NULL }, + { "notBefore", 1610637349, NULL }, + { NULL, 4104, "0"}, + { "notAfter", 536895525, NULL }, + { NULL, 4104, "1"}, + { "AuthorityKeyIdentifier", 1610612741, NULL }, + { "keyIdentifier", 1610637319, NULL }, + { NULL, 4104, "0"}, + { "authorityCertIssuer", 1610637314, "GeneralNames"}, + { NULL, 4104, "1"}, + { "authorityCertSerialNumber", 536895490, "CertificateSerialNumber"}, + { NULL, 4104, "2"}, + { "SubjectKeyIdentifier", 1073741831, NULL }, + { "KeyUsage", 1073741830, NULL }, + { "DirectoryString", 1610612754, NULL }, + { "teletexString", 1612709918, NULL }, + { "MAX", 524298, "1"}, + { "printableString", 1612709919, NULL }, + { "MAX", 524298, "1"}, + { "universalString", 1612709920, NULL }, + { "MAX", 524298, "1"}, + { "utf8String", 1612709922, NULL }, + { "MAX", 524298, "1"}, + { "bmpString", 538968097, NULL }, + { "MAX", 524298, "1"}, + { "SubjectAltName", 1073741826, "GeneralNames"}, + { "GeneralNames", 1612709899, NULL }, + { "MAX", 1074266122, "1"}, + { NULL, 2, "GeneralName"}, + { "GeneralName", 1610612754, NULL }, + { "otherName", 1610620930, "AnotherName"}, + { NULL, 4104, "0"}, + { "rfc822Name", 1610620957, NULL }, + { NULL, 4104, "1"}, + { "dNSName", 1610620957, NULL }, + { NULL, 4104, "2"}, + { "x400Address", 1610620941, NULL }, + { NULL, 4104, "3"}, + { "directoryName", 1610620939, NULL }, + { NULL, 1073743880, "4"}, + { NULL, 2, "RelativeDistinguishedName"}, + { "ediPartyName", 1610620941, NULL }, + { NULL, 4104, "5"}, + { "uniformResourceIdentifier", 1610620957, NULL }, + { NULL, 4104, "6"}, + { "iPAddress", 1610620935, NULL }, + { NULL, 4104, "7"}, + { "registeredID", 536879116, NULL }, + { NULL, 4104, "8"}, + { "AnotherName", 1610612741, NULL }, + { "type-id", 1073741836, NULL }, + { "value", 541073421, NULL }, + { NULL, 1073743880, "0"}, + { "type-id", 1, NULL }, + { "IssuerAltName", 1073741826, "GeneralNames"}, + { "BasicConstraints", 1610612741, NULL }, + { "cA", 1610645508, NULL }, + { NULL, 131081, NULL }, + { "pathLenConstraint", 16387, NULL }, + { "CRLDistributionPoints", 1612709899, NULL }, + { "MAX", 1074266122, "1"}, + { NULL, 2, "DistributionPoint"}, + { "DistributionPoint", 1610612741, NULL }, + { "distributionPoint", 1610637314, "DistributionPointName"}, + { NULL, 2056, "0"}, + { "reasons", 1610637314, "ReasonFlags"}, + { NULL, 4104, "1"}, + { "cRLIssuer", 536895490, "GeneralNames"}, + { NULL, 4104, "2"}, + { "DistributionPointName", 1610612754, NULL }, + { "fullName", 1610620930, "GeneralNames"}, + { NULL, 4104, "0"}, + { "nameRelativeToCRLIssuer", 536879106, "RelativeDistinguishedName"}, + { NULL, 4104, "1"}, + { "ReasonFlags", 1073741830, NULL }, + { "ExtKeyUsageSyntax", 1612709899, NULL }, + { "MAX", 1074266122, "1"}, + { NULL, 12, NULL }, + { "AuthorityInfoAccessSyntax", 1612709899, NULL }, + { "MAX", 1074266122, "1"}, + { NULL, 2, "AccessDescription"}, + { "AccessDescription", 1610612741, NULL }, + { "accessMethod", 1073741836, NULL }, + { "accessLocation", 2, "GeneralName"}, + { "Attribute", 1610612741, NULL }, + { "type", 1073741836, NULL }, + { "values", 536870927, NULL }, + { NULL, 13, NULL }, + { "AttributeTypeAndValue", 1610612741, NULL }, + { "type", 1073741836, NULL }, + { "value", 13, NULL }, + { "Name", 1610612754, NULL }, + { "rdnSequence", 536870923, NULL }, + { NULL, 2, "RelativeDistinguishedName"}, + { "DistinguishedName", 1610612747, NULL }, + { NULL, 2, "RelativeDistinguishedName"}, + { "RelativeDistinguishedName", 1612709903, NULL }, + { "MAX", 1074266122, "1"}, + { NULL, 2, "AttributeTypeAndValue"}, + { "Certificate", 1610612741, NULL }, + { "tbsCertificate", 1073741826, "TBSCertificate"}, + { "signatureAlgorithm", 1073741826, "AlgorithmIdentifier"}, + { "signature", 6, NULL }, + { "TBSCertificate", 1610612741, NULL }, + { "version", 1610653699, NULL }, + { NULL, 1073741833, "0"}, + { NULL, 2056, "0"}, + { "serialNumber", 1073741826, "CertificateSerialNumber"}, + { "signature", 1073741826, "AlgorithmIdentifier"}, + { "issuer", 1073741826, "Name"}, + { "validity", 1073741826, "Validity"}, + { "subject", 1073741826, "Name"}, + { "subjectPublicKeyInfo", 1073741826, "SubjectPublicKeyInfo"}, + { "issuerUniqueID", 1610637314, "UniqueIdentifier"}, + { NULL, 4104, "1"}, + { "subjectUniqueID", 1610637314, "UniqueIdentifier"}, + { NULL, 4104, "2"}, + { "extensions", 536895490, "Extensions"}, + { NULL, 2056, "3"}, + { "CertificateSerialNumber", 1073741827, NULL }, + { "Validity", 1610612741, NULL }, + { "notBefore", 1073741826, "Time"}, + { "notAfter", 2, "Time"}, + { "Time", 1610612754, NULL }, + { "utcTime", 1073741860, NULL }, + { "generalTime", 37, NULL }, + { "UniqueIdentifier", 1073741830, NULL }, + { "SubjectPublicKeyInfo", 1610612741, NULL }, + { "algorithm", 1073741826, "AlgorithmIdentifier"}, + { "subjectPublicKey", 6, NULL }, + { "Extensions", 1612709899, NULL }, + { "MAX", 1074266122, "1"}, + { NULL, 2, "Extension"}, + { "Extension", 1610612741, NULL }, + { "extnID", 1073741836, NULL }, + { "critical", 1610645508, NULL }, + { NULL, 131081, NULL }, + { "extnValue", 7, NULL }, + { "CertificateList", 1610612741, NULL }, + { "tbsCertList", 1073741826, "TBSCertList"}, + { "signatureAlgorithm", 1073741826, "AlgorithmIdentifier"}, + { "signature", 6, NULL }, + { "TBSCertList", 1610612741, NULL }, + { "version", 1073758211, NULL }, + { "signature", 1073741826, "AlgorithmIdentifier"}, + { "issuer", 1073741826, "Name"}, + { "thisUpdate", 1073741826, "Time"}, + { "nextUpdate", 1073758210, "Time"}, + { "revokedCertificates", 1610629131, NULL }, + { NULL, 536870917, NULL }, + { "userCertificate", 1073741826, "CertificateSerialNumber"}, + { "revocationDate", 1073741826, "Time"}, + { "crlEntryExtensions", 16386, "Extensions"}, + { "crlExtensions", 536895490, "Extensions"}, + { NULL, 2056, "0"}, + { "AlgorithmIdentifier", 1610612741, NULL }, + { "algorithm", 1073741836, NULL }, + { "parameters", 541081613, NULL }, + { "algorithm", 1, NULL }, + { "Dss-Sig-Value", 1610612741, NULL }, + { "r", 1073741827, NULL }, + { "s", 3, NULL }, + { "Dss-Parms", 1610612741, NULL }, + { "p", 1073741827, NULL }, + { "q", 1073741827, NULL }, + { "g", 3, NULL }, + { "pkcs-7-ContentInfo", 1610612741, NULL }, + { "contentType", 1073741836, NULL }, + { "content", 541073421, NULL }, + { NULL, 1073743880, "0"}, + { "contentType", 1, NULL }, + { "pkcs-7-DigestInfo", 1610612741, NULL }, + { "digestAlgorithm", 1073741826, "AlgorithmIdentifier"}, + { "digest", 7, NULL }, + { "pkcs-7-SignedData", 1610612741, NULL }, + { "version", 1073741827, NULL }, + { "digestAlgorithms", 1073741826, "pkcs-7-DigestAlgorithmIdentifiers"}, + { "encapContentInfo", 1073741826, "pkcs-7-EncapsulatedContentInfo"}, + { "certificates", 1610637314, "pkcs-7-CertificateSet"}, + { NULL, 4104, "0"}, + { "crls", 1610637314, "pkcs-7-CertificateRevocationLists"}, + { NULL, 4104, "1"}, + { "signerInfos", 2, "pkcs-7-SignerInfos"}, + { "pkcs-7-DigestAlgorithmIdentifiers", 1610612751, NULL }, + { NULL, 2, "AlgorithmIdentifier"}, + { "pkcs-7-EncapsulatedContentInfo", 1610612741, NULL }, + { "eContentType", 1073741836, NULL }, + { "eContent", 536895501, NULL }, + { NULL, 2056, "0"}, + { "pkcs-7-CertificateRevocationLists", 1610612751, NULL }, + { NULL, 13, NULL }, + { "pkcs-7-CertificateChoices", 1610612754, NULL }, + { "certificate", 13, NULL }, + { "pkcs-7-CertificateSet", 1610612751, NULL }, + { NULL, 2, "pkcs-7-CertificateChoices"}, + { "IssuerAndSerialNumber", 1610612741, NULL }, + { "issuer", 1073741826, "Name"}, + { "serialNumber", 2, "CertificateSerialNumber"}, + { "pkcs-7-SignerInfo", 1610612741, NULL }, + { "version", 1073741827, NULL }, + { "sid", 1073741826, "SignerIdentifier"}, + { "digestAlgorithm", 1073741826, "AlgorithmIdentifier"}, + { "signedAttrs", 1610637314, "SignedAttributes"}, + { NULL, 4104, "0"}, + { "signatureAlgorithm", 1073741826, "AlgorithmIdentifier"}, + { "signature", 1073741831, NULL }, + { "unsignedAttrs", 536895490, "SignedAttributes"}, + { NULL, 4104, "1"}, + { "SignedAttributes", 1612709903, NULL }, + { "MAX", 1074266122, "1"}, + { NULL, 2, "Attribute"}, + { "SignerIdentifier", 1610612754, NULL }, + { "issuerAndSerialNumber", 1073741826, "IssuerAndSerialNumber"}, + { "subjectKeyIdentifier", 536879111, NULL }, + { NULL, 4104, "0"}, + { "pkcs-7-SignerInfos", 1610612751, NULL }, + { NULL, 2, "pkcs-7-SignerInfo"}, + { "pkcs-10-CertificationRequestInfo", 1610612741, NULL }, + { "version", 1073741827, NULL }, + { "subject", 1073741826, "Name"}, + { "subjectPKInfo", 1073741826, "SubjectPublicKeyInfo"}, + { "attributes", 536879106, "Attributes"}, + { NULL, 4104, "0"}, + { "Attributes", 1610612751, NULL }, + { NULL, 2, "Attribute"}, + { "pkcs-10-CertificationRequest", 1610612741, NULL }, + { "certificationRequestInfo", 1073741826, "pkcs-10-CertificationRequestInfo"}, + { "signatureAlgorithm", 1073741826, "AlgorithmIdentifier"}, + { "signature", 6, NULL }, + { "pkcs-9-at-challengePassword", 1879048204, NULL }, + { "iso", 1073741825, "1"}, + { "member-body", 1073741825, "2"}, + { "us", 1073741825, "840"}, + { "rsadsi", 1073741825, "113549"}, + { "pkcs", 1073741825, "1"}, + { NULL, 1073741825, "9"}, + { NULL, 1, "7"}, + { "pkcs-9-challengePassword", 1610612754, NULL }, + { "printableString", 1073741855, NULL }, + { "utf8String", 34, NULL }, + { "pkcs-9-localKeyId", 1073741831, NULL }, + { "pkcs-8-PrivateKeyInfo", 1610612741, NULL }, + { "version", 1073741827, NULL }, + { "privateKeyAlgorithm", 1073741826, "AlgorithmIdentifier"}, + { "privateKey", 1073741831, NULL }, + { "attributes", 536895490, "Attributes"}, + { NULL, 4104, "0"}, + { "pkcs-8-EncryptedPrivateKeyInfo", 1610612741, NULL }, + { "encryptionAlgorithm", 1073741826, "AlgorithmIdentifier"}, + { "encryptedData", 2, "pkcs-8-EncryptedData"}, + { "pkcs-8-EncryptedData", 1073741831, NULL }, + { "pkcs-5-des-CBC-params", 1612709895, NULL }, + { NULL, 1048586, "8"}, + { "pkcs-5-des-EDE3-CBC-params", 1612709895, NULL }, + { NULL, 1048586, "8"}, + { "pkcs-5-aes128-CBC-params", 1612709895, NULL }, + { NULL, 1048586, "16"}, + { "pkcs-5-aes192-CBC-params", 1612709895, NULL }, + { NULL, 1048586, "16"}, + { "pkcs-5-aes256-CBC-params", 1612709895, NULL }, + { NULL, 1048586, "16"}, + { "Gost28147-89-Parameters", 1610612741, NULL }, + { "iv", 1073741831, NULL }, + { "encryptionParamSet", 12, NULL }, + { "pkcs-5-PBE-params", 1610612741, NULL }, + { "salt", 1073741831, NULL }, + { "iterationCount", 3, NULL }, + { "pkcs-5-PBES2-params", 1610612741, NULL }, + { "keyDerivationFunc", 1073741826, "AlgorithmIdentifier"}, + { "encryptionScheme", 2, "AlgorithmIdentifier"}, + { "pkcs-5-PBMAC1-params", 1610612741, NULL }, + { "keyDerivationFunc", 1073741826, "AlgorithmIdentifier"}, + { "messageAuthScheme", 2, "AlgorithmIdentifier"}, + { "pkcs-5-PBKDF2-params", 1610612741, NULL }, + { "salt", 1610612754, NULL }, + { "specified", 1073741831, NULL }, + { "otherSource", 2, "AlgorithmIdentifier"}, + { "iterationCount", 1073741827, NULL }, + { "keyLength", 1073758211, NULL }, + { "prf", 16386, "AlgorithmIdentifier"}, + { "pkcs-12-PFX", 1610612741, NULL }, + { "version", 1610874883, NULL }, + { "v3", 1, "3"}, + { "authSafe", 1073741826, "pkcs-7-ContentInfo"}, + { "macData", 16386, "pkcs-12-MacData"}, + { "pkcs-12-PbeParams", 1610612741, NULL }, + { "salt", 1073741831, NULL }, + { "iterations", 3, NULL }, + { "pkcs-12-MacData", 1610612741, NULL }, + { "mac", 1073741826, "pkcs-7-DigestInfo"}, + { "macSalt", 1073741831, NULL }, + { "iterations", 536903683, NULL }, + { NULL, 9, "1"}, + { "pkcs-12-AuthenticatedSafe", 1610612747, NULL }, + { NULL, 2, "pkcs-7-ContentInfo"}, + { "pkcs-12-SafeContents", 1610612747, NULL }, + { NULL, 2, "pkcs-12-SafeBag"}, + { "pkcs-12-SafeBag", 1610612741, NULL }, + { "bagId", 1073741836, NULL }, + { "bagValue", 1614815245, NULL }, + { NULL, 1073743880, "0"}, + { "badId", 1, NULL }, + { "bagAttributes", 536887311, NULL }, + { NULL, 2, "Attribute"}, + { "pkcs-12-CertBag", 1610612741, NULL }, + { "certId", 1073741836, NULL }, + { "certValue", 541073421, NULL }, + { NULL, 1073743880, "0"}, + { "certId", 1, NULL }, + { "pkcs-12-CRLBag", 1610612741, NULL }, + { "crlId", 1073741836, NULL }, + { "crlValue", 541073421, NULL }, + { NULL, 1073743880, "0"}, + { "crlId", 1, NULL }, + { "pkcs-12-SecretBag", 1610612741, NULL }, + { "secretTypeId", 1073741836, NULL }, + { "secretValue", 541073421, NULL }, + { NULL, 1073743880, "0"}, + { "secretTypeId", 1, NULL }, + { "pkcs-7-Data", 1073741831, NULL }, + { "pkcs-7-EncryptedData", 1610612741, NULL }, + { "version", 1073741827, NULL }, + { "encryptedContentInfo", 1073741826, "pkcs-7-EncryptedContentInfo"}, + { "unprotectedAttrs", 536895490, "pkcs-7-UnprotectedAttributes"}, + { NULL, 4104, "1"}, + { "pkcs-7-EncryptedContentInfo", 1610612741, NULL }, + { "contentType", 1073741836, NULL }, + { "contentEncryptionAlgorithm", 1073741826, "pkcs-7-ContentEncryptionAlgorithmIdentifier"}, + { "encryptedContent", 536895495, NULL }, + { NULL, 4104, "0"}, + { "pkcs-7-ContentEncryptionAlgorithmIdentifier", 1073741826, "AlgorithmIdentifier"}, + { "pkcs-7-UnprotectedAttributes", 1612709903, NULL }, + { "MAX", 1074266122, "1"}, + { NULL, 2, "Attribute"}, + { "ProxyCertInfo", 1610612741, NULL }, + { "pCPathLenConstraint", 1073758211, NULL }, + { "proxyPolicy", 2, "ProxyPolicy"}, + { "ProxyPolicy", 1610612741, NULL }, + { "policyLanguage", 1073741836, NULL }, + { "policy", 16391, NULL }, + { "certificatePolicies", 1612709899, NULL }, + { "MAX", 1074266122, "1"}, + { NULL, 2, "PolicyInformation"}, + { "PolicyInformation", 1610612741, NULL }, + { "policyIdentifier", 1073741836, NULL }, + { "policyQualifiers", 538984459, NULL }, + { "MAX", 1074266122, "1"}, + { NULL, 2, "PolicyQualifierInfo"}, + { "PolicyQualifierInfo", 1610612741, NULL }, + { "policyQualifierId", 1073741836, NULL }, + { "qualifier", 541065229, NULL }, + { "policyQualifierId", 1, NULL }, + { "CPSuri", 1073741853, NULL }, + { "UserNotice", 1610612741, NULL }, + { "noticeRef", 1073758210, "NoticeReference"}, + { "explicitText", 16386, "DisplayText"}, + { "NoticeReference", 1610612741, NULL }, + { "organization", 1073741826, "DisplayText"}, + { "noticeNumbers", 536870923, NULL }, + { NULL, 3, NULL }, + { "DisplayText", 1610612754, NULL }, + { "ia5String", 1612709917, NULL }, + { "200", 524298, "1"}, + { "visibleString", 1612709923, NULL }, + { "200", 524298, "1"}, + { "bmpString", 1612709921, NULL }, + { "200", 524298, "1"}, + { "utf8String", 538968098, NULL }, + { "200", 524298, "1"}, + { "OCSPRequest", 1610612741, NULL }, + { "tbsRequest", 1073741826, "TBSRequest"}, + { "optionalSignature", 536895490, "Signature"}, + { NULL, 2056, "0"}, + { "TBSRequest", 1610612741, NULL }, + { "version", 1610653699, NULL }, + { NULL, 1073741833, "0"}, + { NULL, 2056, "0"}, + { "requestorName", 1610637314, "GeneralName"}, + { NULL, 2056, "1"}, + { "requestList", 1610612747, NULL }, + { NULL, 2, "Request"}, + { "requestExtensions", 536895490, "Extensions"}, + { NULL, 2056, "2"}, + { "Signature", 1610612741, NULL }, + { "signatureAlgorithm", 1073741826, "AlgorithmIdentifier"}, + { "signature", 1073741830, NULL }, + { "certs", 536895499, NULL }, + { NULL, 1073743880, "0"}, + { NULL, 2, "Certificate"}, + { "Request", 1610612741, NULL }, + { "reqCert", 1073741826, "CertID"}, + { "singleRequestExtensions", 536895490, "Extensions"}, + { NULL, 2056, "0"}, + { "CertID", 1610612741, NULL }, + { "hashAlgorithm", 1073741826, "AlgorithmIdentifier"}, + { "issuerNameHash", 1073741831, NULL }, + { "issuerKeyHash", 1073741831, NULL }, + { "serialNumber", 2, "CertificateSerialNumber"}, + { "OCSPResponse", 1610612741, NULL }, + { "responseStatus", 1073741826, "OCSPResponseStatus"}, + { "responseBytes", 536895490, "ResponseBytes"}, + { NULL, 2056, "0"}, + { "OCSPResponseStatus", 1610874901, NULL }, + { "successful", 1073741825, "0"}, + { "malformedRequest", 1073741825, "1"}, + { "internalError", 1073741825, "2"}, + { "tryLater", 1073741825, "3"}, + { "sigRequired", 1073741825, "5"}, + { "unauthorized", 1, "6"}, + { "ResponseBytes", 1610612741, NULL }, + { "responseType", 1073741836, NULL }, + { "response", 7, NULL }, + { "BasicOCSPResponse", 1610612741, NULL }, + { "tbsResponseData", 1073741826, "ResponseData"}, + { "signatureAlgorithm", 1073741826, "AlgorithmIdentifier"}, + { "signature", 1073741830, NULL }, + { "certs", 536895499, NULL }, + { NULL, 1073743880, "0"}, + { NULL, 2, "Certificate"}, + { "ResponseData", 1610612741, NULL }, + { "version", 1610653699, NULL }, + { NULL, 1073741833, "0"}, + { NULL, 2056, "0"}, + { "responderID", 1073741826, "ResponderID"}, + { "producedAt", 1073741861, NULL }, + { "responses", 1610612747, NULL }, + { NULL, 2, "SingleResponse"}, + { "responseExtensions", 536895490, "Extensions"}, + { NULL, 2056, "1"}, + { "ResponderID", 1610612754, NULL }, + { "byName", 1610620939, NULL }, + { NULL, 1073743880, "1"}, + { NULL, 2, "RelativeDistinguishedName"}, + { "byKey", 536879111, NULL }, + { NULL, 2056, "2"}, + { "SingleResponse", 1610612741, NULL }, + { "certID", 1073741826, "CertID"}, + { "certStatus", 1073741826, "CertStatus"}, + { "thisUpdate", 1073741861, NULL }, + { "nextUpdate", 1610637349, NULL }, + { NULL, 2056, "0"}, + { "singleExtensions", 536895490, "Extensions"}, + { NULL, 2056, "1"}, + { "CertStatus", 1610612754, NULL }, + { "good", 1610620948, NULL }, + { NULL, 4104, "0"}, + { "revoked", 1610620930, "RevokedInfo"}, + { NULL, 4104, "1"}, + { "unknown", 536879106, "UnknownInfo"}, + { NULL, 4104, "2"}, + { "RevokedInfo", 1610612741, NULL }, + { "revocationTime", 1073741861, NULL }, + { "revocationReason", 537157653, NULL }, + { NULL, 1073743880, "0"}, + { "unspecified", 1, "0"}, + { "UnknownInfo", 1073741844, NULL }, + { "NameConstraints", 1610612741, NULL }, + { "permittedSubtrees", 1610637314, "GeneralSubtrees"}, + { NULL, 4104, "0"}, + { "excludedSubtrees", 536895490, "GeneralSubtrees"}, + { NULL, 4104, "1"}, + { "GeneralSubtrees", 1612709899, NULL }, + { "MAX", 1074266122, "1"}, + { NULL, 2, "GeneralSubtree"}, + { "GeneralSubtree", 1610612741, NULL }, + { "base", 1073741826, "GeneralName"}, + { "minimum", 1610653699, NULL }, + { NULL, 1073741833, "0"}, + { NULL, 4104, "0"}, + { "maximum", 536895491, NULL }, + { NULL, 4104, "1"}, + { "TlsFeatures", 536870923, NULL }, + { NULL, 3, NULL }, + { NULL, 0, NULL } +}; -- 2.50.1 (Apple Git-155) _______________________________________________ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel ^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH v13 06/20] appended signatures: Parse ASN1 node 2025-09-30 11:39 [PATCH v13 00/20] Appended Signature Secure Boot Support for PowerPC Sudhakar Kuppusamy ` (4 preceding siblings ...) 2025-09-30 11:39 ` [PATCH v13 05/20] appended signatures: Import GNUTLS's ASN.1 description files Sudhakar Kuppusamy @ 2025-09-30 11:40 ` Sudhakar Kuppusamy 2025-09-30 11:40 ` [PATCH v13 07/20] appended signatures: Parse PKCS#7 signed data Sudhakar Kuppusamy ` (14 subsequent siblings) 20 siblings, 0 replies; 25+ messages in thread From: Sudhakar Kuppusamy @ 2025-09-30 11:40 UTC (permalink / raw) To: grub-devel Cc: dja, jan.setjeeilers, julian.klode, mate.kukri, pjones, msuchanek, mlewando, stefanb, avnish, nayna, ssrish, Sudhakar Kuppusamy, sridharm, Daniel Kiper This code allows us to parse ASN1 node and allocating memory to store it. It will work for anything where the size libtasn1 returns is right: - Integers - Octet strings - DER encoding of other structures It will _not_ work for things where libtasn1 size requires adjustment: - Strings that require an extra NULL byte at the end - Bit strings because libtasn1 returns the length in bits, not bytes. If the function returns a non-NULL value, the caller must free it. 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> --- grub-core/commands/appendedsig/appendedsig.h | 44 +++++++++ grub-core/commands/appendedsig/asn1util.c | 99 ++++++++++++++++++++ 2 files changed, 143 insertions(+) create mode 100644 grub-core/commands/appendedsig/appendedsig.h create mode 100644 grub-core/commands/appendedsig/asn1util.c diff --git a/grub-core/commands/appendedsig/appendedsig.h b/grub-core/commands/appendedsig/appendedsig.h new file mode 100644 index 000000000..601d6164f --- /dev/null +++ b/grub-core/commands/appendedsig/appendedsig.h @@ -0,0 +1,44 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2020, 2022 Free Software Foundation, Inc. + * Copyright (C) 2020, 2022, 2025 IBM Corporation + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <libtasn1.h> + +extern asn1_node grub_gnutls_gnutls_asn; +extern asn1_node grub_gnutls_pkix_asn; + +/* Do libtasn1 init. */ +extern int +grub_asn1_init (void); + +/* + * Read a value from an ASN1 node, allocating memory to store it. It will work + * for anything where the size libtasn1 returns is right: + * - Integers + * - Octet strings + * - DER encoding of other structures + * + * It will _not_ work for things where libtasn1 size requires adjustment: + * - Strings that require an extra null byte at the end + * - Bit strings because libtasn1 returns the length in bits, not bytes. + * + * If the function returns a non-NULL value, the caller must free it. + */ +extern void * +grub_asn1_allocate_and_read (asn1_node node, const char *name, const char *friendly_name, + grub_int32_t *content_size); diff --git a/grub-core/commands/appendedsig/asn1util.c b/grub-core/commands/appendedsig/asn1util.c new file mode 100644 index 000000000..9dd7898ea --- /dev/null +++ b/grub-core/commands/appendedsig/asn1util.c @@ -0,0 +1,99 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2020, 2022 Free Software Foundation, Inc. + * Copyright (C) 2020, 2022, 2025 IBM Corporation + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <libtasn1.h> +#include <grub/types.h> +#include <grub/err.h> +#include <grub/mm.h> +#include <grub/crypto.h> +#include <grub/misc.h> +#include <grub/gcrypt/gcrypt.h> + +#include "appendedsig.h" + +asn1_node grub_gnutls_gnutls_asn = NULL; +asn1_node grub_gnutls_pkix_asn = NULL; + +extern const asn1_static_node grub_gnutls_asn1_tab[]; +extern const asn1_static_node grub_pkix_asn1_tab[]; + +/* + * Read a value from an ASN1 node, allocating memory to store it. It will work + * for anything where the size libtasn1 returns is right: + * - Integers + * - Octet strings + * - DER encoding of other structures + * + * It will _not_ work for things where libtasn1 size requires adjustment: + * - Strings that require an extra NULL byte at the end + * - Bit strings because libtasn1 returns the length in bits, not bytes. + * + * If the function returns a non-NULL value, the caller must free it. + */ +void * +grub_asn1_allocate_and_read (asn1_node node, const char *name, const char *friendly_name, + grub_int32_t *content_size) +{ + grub_int32_t result; + grub_uint8_t *tmpstr = NULL; + grub_int32_t tmpstr_size = 0; + + result = asn1_read_value (node, name, NULL, &tmpstr_size); + if (result != ASN1_MEM_ERROR) + { + grub_error (GRUB_ERR_BAD_FILE_TYPE, "reading size of %s did not return expected status: %s", + friendly_name, asn1_strerror (result)) ; + return NULL; + } + + tmpstr = grub_malloc (tmpstr_size); + if (tmpstr == NULL) + { + grub_error (GRUB_ERR_OUT_OF_MEMORY, "could not allocate memory to store %s", + friendly_name) ; + return NULL; + } + + result = asn1_read_value (node, name, tmpstr, &tmpstr_size); + if (result != ASN1_SUCCESS) + { + grub_free (tmpstr); + grub_error (GRUB_ERR_BAD_FILE_TYPE, "error reading %s: %s", friendly_name, + asn1_strerror (result)) ; + return NULL; + } + + *content_size = tmpstr_size; + + return tmpstr; +} + +int +grub_asn1_init (void) +{ + int res; + + res = asn1_array2tree (grub_gnutls_asn1_tab, &grub_gnutls_gnutls_asn, NULL); + if (res != ASN1_SUCCESS) + return res; + + res = asn1_array2tree (grub_pkix_asn1_tab, &grub_gnutls_pkix_asn, NULL); + + return res; +} -- 2.50.1 (Apple Git-155) _______________________________________________ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel ^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH v13 07/20] appended signatures: Parse PKCS#7 signed data 2025-09-30 11:39 [PATCH v13 00/20] Appended Signature Secure Boot Support for PowerPC Sudhakar Kuppusamy ` (5 preceding siblings ...) 2025-09-30 11:40 ` [PATCH v13 06/20] appended signatures: Parse ASN1 node Sudhakar Kuppusamy @ 2025-09-30 11:40 ` Sudhakar Kuppusamy 2025-09-30 11:40 ` [PATCH v13 08/20] appended signatures: Parse X.509 certificates Sudhakar Kuppusamy ` (13 subsequent siblings) 20 siblings, 0 replies; 25+ messages in thread From: Sudhakar Kuppusamy @ 2025-09-30 11:40 UTC (permalink / raw) To: grub-devel Cc: dja, jan.setjeeilers, julian.klode, mate.kukri, pjones, msuchanek, mlewando, stefanb, avnish, nayna, ssrish, Sudhakar Kuppusamy, sridharm, Daniel Kiper This code allows us to parse: - PKCS#7 signed data messages. Only a single signer info is supported, which is all that the Linux sign-file utility supports creating out-of-the-box. Only RSA, SHA-256 and SHA-512 are supported. Any certificate embedded in the PKCS#7 message will be ignored. 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> --- grub-core/commands/appendedsig/appendedsig.h | 37 ++ grub-core/commands/appendedsig/pkcs7.c | 452 +++++++++++++++++++ 2 files changed, 489 insertions(+) create mode 100644 grub-core/commands/appendedsig/pkcs7.c diff --git a/grub-core/commands/appendedsig/appendedsig.h b/grub-core/commands/appendedsig/appendedsig.h index 601d6164f..b0beb8935 100644 --- a/grub-core/commands/appendedsig/appendedsig.h +++ b/grub-core/commands/appendedsig/appendedsig.h @@ -17,11 +17,48 @@ * along with GRUB. If not, see <http://www.gnu.org/licenses/>. */ +#include <grub/crypto.h> #include <libtasn1.h> extern asn1_node grub_gnutls_gnutls_asn; extern asn1_node grub_gnutls_pkix_asn; +#define GRUB_MAX_OID_LEN 32 + +/* A PKCS#7 signed data signer info. */ +struct pkcs7_signer +{ + const gcry_md_spec_t *hash; + gcry_mpi_t sig_mpi; +}; +typedef struct pkcs7_signer grub_pkcs7_signer_t; + +/* + * A PKCS#7 signed data message. We make no attempt to match intelligently, so + * we don't save any info about the signer. + */ +struct pkcs7_data +{ + grub_int32_t signer_count; + grub_pkcs7_signer_t *signers; +}; +typedef struct pkcs7_data grub_pkcs7_data_t; + +/* + * Parse a PKCS#7 message, which must be a signed data message. The message must + * be in 'sigbuf' and of size 'data_size'. The result is placed in 'msg', which + * must already be allocated. + */ +extern grub_err_t +grub_pkcs7_data_parse (const void *sigbuf, grub_size_t data_size, grub_pkcs7_data_t *msg); + +/* + * Release all the storage associated with the PKCS#7 message. If the caller + * dynamically allocated the message, it must free it. + */ +extern void +grub_pkcs7_data_release (grub_pkcs7_data_t *msg); + /* Do libtasn1 init. */ extern int grub_asn1_init (void); diff --git a/grub-core/commands/appendedsig/pkcs7.c b/grub-core/commands/appendedsig/pkcs7.c new file mode 100644 index 000000000..b8e272047 --- /dev/null +++ b/grub-core/commands/appendedsig/pkcs7.c @@ -0,0 +1,452 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2020, 2022 Free Software Foundation, Inc. + * Copyright (C) 2020, 2022, 2025 IBM Corporation + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "appendedsig.h" +#include <grub/misc.h> +#include <grub/crypto.h> +#include <grub/gcrypt/gcrypt.h> +#include <sys/types.h> + +static char asn1_error[ASN1_MAX_ERROR_DESCRIPTION_SIZE]; + +/* RFC 5652 s 5.1. */ +static const char *signedData_oid = "1.2.840.113549.1.7.2"; + +/* RFC 4055 s 2.1. */ +static const char *sha256_oid = "2.16.840.1.101.3.4.2.1"; +static const char *sha512_oid = "2.16.840.1.101.3.4.2.3"; + +static grub_err_t +process_content (grub_uint8_t *content, grub_int32_t size, grub_pkcs7_data_t *msg) +{ + grub_int32_t res; + asn1_node signed_part; + grub_err_t err = GRUB_ERR_NONE; + char algo_oid[GRUB_MAX_OID_LEN]; + grub_int32_t algo_oid_size; + grub_int32_t algo_count; + grub_int32_t signer_count; + grub_int32_t i; + char version; + grub_int32_t version_size = sizeof (version); + grub_uint8_t *result_buf; + grub_int32_t result_size = 0; + grub_int32_t crls_size = 0; + gcry_error_t gcry_err; + bool sha256_in_da, sha256_in_si, sha512_in_da, sha512_in_si; + char *da_path; + char *si_sig_path; + char *si_da_path; + + res = asn1_create_element (grub_gnutls_pkix_asn, "PKIX1.pkcs-7-SignedData", &signed_part); + if (res != ASN1_SUCCESS) + return grub_error (GRUB_ERR_OUT_OF_MEMORY, + "could not create ASN.1 structure for PKCS#7 signed part"); + + res = asn1_der_decoding2 (&signed_part, content, &size, + ASN1_DECODE_FLAG_STRICT_DER, asn1_error); + if (res != ASN1_SUCCESS) + { + err = grub_error (GRUB_ERR_BAD_SIGNATURE, + "error reading PKCS#7 signed data: %s", asn1_error); + goto cleanup_signed_part; + } + + /* + * SignedData ::= SEQUENCE { + * version CMSVersion, + * digestAlgorithms DigestAlgorithmIdentifiers, + * encapContentInfo EncapsulatedContentInfo, + * certificates [0] IMPLICIT CertificateSet OPTIONAL, + * crls [1] IMPLICIT RevocationInfoChoices OPTIONAL, + * signerInfos SignerInfos } + */ + + res = asn1_read_value (signed_part, "version", &version, &version_size); + if (res != ASN1_SUCCESS) + { + err = grub_error (GRUB_ERR_BAD_SIGNATURE, "error reading signedData version: %s", + asn1_strerror (res)); + goto cleanup_signed_part; + } + + /* Signature version must be 1 because appended signature only support v1. */ + if (version != 1) + { + err = grub_error (GRUB_ERR_BAD_SIGNATURE, + "unexpected signature version v%d, only v1 supported", version); + goto cleanup_signed_part; + } + + /* + * digestAlgorithms DigestAlgorithmIdentifiers + * + * DigestAlgorithmIdentifiers ::= SET OF DigestAlgorithmIdentifier + * DigestAlgorithmIdentifer is an X.509 AlgorithmIdentifier (10.1.1) + * + * RFC 4055 s 2.1: + * sha256Identifier AlgorithmIdentifier ::= { id-sha256, NULL } + * sha512Identifier AlgorithmIdentifier ::= { id-sha512, NULL } + * + * We only support 1 element in the set, and we do not check parameters atm. + */ + res = asn1_number_of_elements (signed_part, "digestAlgorithms", &algo_count); + if (res != ASN1_SUCCESS) + { + err = grub_error (GRUB_ERR_BAD_SIGNATURE, "error counting number of digest algorithms: %s", + asn1_strerror (res)); + goto cleanup_signed_part; + } + + if (algo_count <= 0) + { + err = grub_error (GRUB_ERR_BAD_SIGNATURE, "a minimum of 1 digest algorithm is required"); + goto cleanup_signed_part; + } + + if (algo_count > 2) + { + err = grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "a maximum of 2 digest algorithms is supported"); + goto cleanup_signed_part; + } + + sha256_in_da = false; + sha512_in_da = false; + + for (i = 0; i < algo_count; i++) + { + da_path = grub_xasprintf ("digestAlgorithms.?%d.algorithm", i + 1); + if (da_path == NULL) + { + err = grub_error (GRUB_ERR_OUT_OF_MEMORY, + "could not allocate path for digest algorithm parsing path"); + goto cleanup_signed_part; + } + + algo_oid_size = sizeof (algo_oid); + res = asn1_read_value (signed_part, da_path, algo_oid, &algo_oid_size); + if (res != ASN1_SUCCESS) + { + err = grub_error (GRUB_ERR_BAD_SIGNATURE, "error reading digest algorithm: %s", + asn1_strerror (res)); + grub_free (da_path); + goto cleanup_signed_part; + } + + if (grub_strncmp (sha512_oid, algo_oid, algo_oid_size) == 0) + { + if (sha512_in_da == false) + sha512_in_da = true; + else + { + err = grub_error (GRUB_ERR_BAD_SIGNATURE, + "SHA-512 specified twice in digest algorithm list"); + grub_free (da_path); + goto cleanup_signed_part; + } + } + else if (grub_strncmp (sha256_oid, algo_oid, algo_oid_size) == 0) + { + if (sha256_in_da == false) + sha256_in_da = true; + else + { + err = grub_error (GRUB_ERR_BAD_SIGNATURE, + "SHA-256 specified twice in digest algorithm list"); + grub_free (da_path); + goto cleanup_signed_part; + } + } + else + { + err = grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + "only SHA-256 and SHA-512 hashes are supported, found OID %s", + algo_oid); + grub_free (da_path); + goto cleanup_signed_part; + } + + grub_free (da_path); + } + + /* At this point, at least one of sha{256,512}_in_da must be true. */ + + /* + * We ignore the certificates, but we don't permit CRLs. A CRL entry might be + * revoking the certificate we're using, and we have no way of dealing with + * that at the moment. + */ + res = asn1_read_value (signed_part, "crls", NULL, &crls_size); + if (res != ASN1_ELEMENT_NOT_FOUND) + { + err = grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + "PKCS#7 messages with embedded CRLs are not supported"); + goto cleanup_signed_part; + } + + /* Read the signatures */ + res = asn1_number_of_elements (signed_part, "signerInfos", &signer_count); + if (res != ASN1_SUCCESS) + { + err = grub_error (GRUB_ERR_BAD_SIGNATURE, "error counting number of signers: %s", + asn1_strerror (res)); + goto cleanup_signed_part; + } + + if (signer_count <= 0) + { + err = grub_error (GRUB_ERR_BAD_SIGNATURE, "a minimum of 1 signer is required"); + goto cleanup_signed_part; + } + + msg->signers = grub_calloc (signer_count, sizeof (grub_pkcs7_signer_t)); + if (msg->signers == NULL) + { + err = grub_error (GRUB_ERR_OUT_OF_MEMORY, + "could not allocate space for %d signers", signer_count); + goto cleanup_signed_part; + } + + msg->signer_count = 0; + for (i = 0; i < signer_count; i++) + { + si_da_path = grub_xasprintf ("signerInfos.?%d.digestAlgorithm.algorithm", i + 1); + if (si_da_path == NULL) + { + err = grub_error (GRUB_ERR_OUT_OF_MEMORY, + "could not allocate path for signer %d's digest algorithm parsing path", + i); + goto cleanup_signerInfos; + } + + algo_oid_size = sizeof (algo_oid); + res = asn1_read_value (signed_part, si_da_path, algo_oid, &algo_oid_size); + if (res != ASN1_SUCCESS) + { + err = grub_error (GRUB_ERR_BAD_SIGNATURE, + "error reading signer %d's digest algorithm: %s", i, asn1_strerror (res)); + grub_free (si_da_path); + goto cleanup_signerInfos; + } + + grub_free (si_da_path); + + if (grub_strncmp (sha512_oid, algo_oid, algo_oid_size) == 0) + { + if (sha512_in_da == false) + { + err = grub_error (GRUB_ERR_BAD_SIGNATURE, + "signer %d claims a SHA-512 signature which was not " + "specified in the outer DigestAlgorithms", i); + goto cleanup_signerInfos; + } + else + { + sha512_in_si = true; + msg->signers[i].hash = grub_crypto_lookup_md_by_name ("sha512"); + } + } + else if (grub_strncmp (sha256_oid, algo_oid, algo_oid_size) == 0) + { + if (sha256_in_da == false) + { + err = grub_error (GRUB_ERR_BAD_SIGNATURE, + "signer %d claims a SHA-256 signature which was not " + "specified in the outer DigestAlgorithms", i); + goto cleanup_signerInfos; + } + else + { + sha256_in_si = true; + msg->signers[i].hash = grub_crypto_lookup_md_by_name ("sha256"); + } + } + else + { + err = grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + "only SHA-256 and SHA-512 hashes are supported, found OID %s", + algo_oid); + goto cleanup_signerInfos; + } + + if (msg->signers[i].hash == NULL) + { + err = grub_error (GRUB_ERR_BAD_SIGNATURE, + "Hash algorithm for signer %d (OID %s) not loaded", i, algo_oid); + goto cleanup_signerInfos; + } + + si_sig_path = grub_xasprintf ("signerInfos.?%d.signature", i + 1); + if (si_sig_path == NULL) + { + err = grub_error (GRUB_ERR_OUT_OF_MEMORY, + "could not allocate path for signer %d's signature parsing path", i); + goto cleanup_signerInfos; + } + + result_buf = grub_asn1_allocate_and_read (signed_part, si_sig_path, "signature data", &result_size); + grub_free (si_sig_path); + + if (result_buf == NULL) + { + err = grub_errno; + goto cleanup_signerInfos; + } + + gcry_err = _gcry_mpi_scan (&(msg->signers[i].sig_mpi), GCRYMPI_FMT_USG, + result_buf, result_size, NULL); + grub_free (result_buf); + + if (gcry_err != GPG_ERR_NO_ERROR) + { + err = grub_error (GRUB_ERR_BAD_SIGNATURE, + "error loading signature %d into MPI structure: %d", + i, gcry_err); + goto cleanup_signerInfos; + } + + /* + * Use msg->signer_count to track fully populated signerInfos so we know + * how many we need to clean up. + */ + msg->signer_count++; + } + + /* + * Final consistency check of signerInfo.*.digestAlgorithm vs digestAlgorithms + * .*.algorithm. An algorithm must be present in both digestAlgorithms and + * signerInfo or in neither. We have already checked for an algorithm in + * signerInfo that is not in digestAlgorithms, here we check for algorithms in + * digestAlgorithms but not in signerInfos. + */ + if (sha512_in_da == true && sha512_in_si == false) + { + err = grub_error (GRUB_ERR_BAD_SIGNATURE, + "SHA-512 specified in DigestAlgorithms but did not appear in SignerInfos"); + goto cleanup_signerInfos; + } + + if (sha256_in_da == true && sha256_in_si == false) + { + err = grub_error (GRUB_ERR_BAD_SIGNATURE, + "SHA-256 specified in DigestAlgorithms but did not appear in SignerInfos"); + goto cleanup_signerInfos; + } + + asn1_delete_structure (&signed_part); + + return GRUB_ERR_NONE; + + cleanup_signerInfos: + for (i = 0; i < msg->signer_count; i++) + _gcry_mpi_release (msg->signers[i].sig_mpi); + + grub_free (msg->signers); + + cleanup_signed_part: + asn1_delete_structure (&signed_part); + + return err; +} + +grub_err_t +grub_pkcs7_data_parse (const void *sigbuf, grub_size_t data_size, grub_pkcs7_data_t *msg) +{ + grub_int32_t res; + asn1_node content_info; + grub_err_t err = GRUB_ERR_NONE; + char content_oid[GRUB_MAX_OID_LEN]; + grub_uint8_t *content; + grub_int32_t content_size; + grub_int32_t content_oid_size = sizeof (content_oid); + grub_int32_t size = (grub_int32_t) data_size; + + if (data_size > GRUB_UINT_MAX) + return grub_error (GRUB_ERR_OUT_OF_RANGE, + "cannot parse a PKCS#7 message where data size > GRUB_UINT_MAX"); + + res = asn1_create_element (grub_gnutls_pkix_asn, "PKIX1.pkcs-7-ContentInfo", &content_info); + if (res != ASN1_SUCCESS) + return grub_error (GRUB_ERR_OUT_OF_MEMORY, + "could not create ASN.1 structure for PKCS#7 data: %s", + asn1_strerror (res)); + + res = asn1_der_decoding2 (&content_info, sigbuf, &size, + ASN1_DECODE_FLAG_STRICT_DER | ASN1_DECODE_FLAG_ALLOW_PADDING, + asn1_error); + if (res != ASN1_SUCCESS) + { + err = grub_error (GRUB_ERR_BAD_SIGNATURE, + "error decoding PKCS#7 message DER: %s", asn1_error); + goto cleanup; + } + + /* + * ContentInfo ::= SEQUENCE { + * contentType ContentType, + * content [0] EXPLICIT ANY DEFINED BY contentType } + * + * ContentType ::= OBJECT IDENTIFIER + */ + res = asn1_read_value (content_info, "contentType", content_oid, &content_oid_size); + if (res != ASN1_SUCCESS) + { + err = grub_error (GRUB_ERR_BAD_SIGNATURE, "error reading PKCS#7 content type: %s", + asn1_strerror (res)); + goto cleanup; + } + + /* OID for SignedData defined in 5.1. */ + if (grub_strncmp (signedData_oid, content_oid, content_oid_size) != 0) + { + err = grub_error (GRUB_ERR_BAD_SIGNATURE, + "unexpected content type in PKCS#7 message: OID %s", content_oid); + goto cleanup; + } + + content = grub_asn1_allocate_and_read (content_info, "content", "PKCS#7 message content", &content_size); + if (content == NULL) + { + err = grub_errno; + goto cleanup; + } + + err = process_content (content, content_size, msg); + grub_free (content); + + cleanup: + asn1_delete_structure (&content_info); + + return err; +} + +/* + * Release all the storage associated with the PKCS#7 message. If the caller + * dynamically allocated the message, it must free it. + */ +void +grub_pkcs7_data_release (grub_pkcs7_data_t *msg) +{ + grub_int32_t i; + + for (i = 0; i < msg->signer_count; i++) + _gcry_mpi_release (msg->signers[i].sig_mpi); + + grub_free (msg->signers); +} -- 2.50.1 (Apple Git-155) _______________________________________________ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel ^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH v13 08/20] appended signatures: Parse X.509 certificates 2025-09-30 11:39 [PATCH v13 00/20] Appended Signature Secure Boot Support for PowerPC Sudhakar Kuppusamy ` (6 preceding siblings ...) 2025-09-30 11:40 ` [PATCH v13 07/20] appended signatures: Parse PKCS#7 signed data Sudhakar Kuppusamy @ 2025-09-30 11:40 ` Sudhakar Kuppusamy 2025-09-30 11:40 ` [PATCH v13 09/20] powerpc_ieee1275: Enter lockdown based on /ibm, secure-boot Sudhakar Kuppusamy ` (12 subsequent siblings) 20 siblings, 0 replies; 25+ messages in thread From: Sudhakar Kuppusamy @ 2025-09-30 11:40 UTC (permalink / raw) To: grub-devel Cc: dja, jan.setjeeilers, julian.klode, mate.kukri, pjones, msuchanek, mlewando, stefanb, avnish, nayna, ssrish, Sudhakar Kuppusamy, sridharm, Javier Martinez Canillas, Daniel Kiper This code allows us to parse: - X.509 certificates: at least enough to verify the signatures on the PKCS#7 messages. We expect that the certificates embedded in GRUB will be leaf certificates, not CA certificates. The parser enforces this. - X.509 certificates support the Extended Key Usage extension and handle it by verifying that the certificate has a Code Signing usage. Signed-off-by: Javier Martinez Canillas <javierm@redhat.com> # EKU support Reported-by: Michal Suchanek <msuchanek@suse.com> # key usage issue 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> --- grub-core/commands/appendedsig/appendedsig.h | 52 + grub-core/commands/appendedsig/x509.c | 970 +++++++++++++++++++ include/grub/crypto.h | 1 + 3 files changed, 1023 insertions(+) create mode 100644 grub-core/commands/appendedsig/x509.c diff --git a/grub-core/commands/appendedsig/appendedsig.h b/grub-core/commands/appendedsig/appendedsig.h index b0beb8935..c8746544e 100644 --- a/grub-core/commands/appendedsig/appendedsig.h +++ b/grub-core/commands/appendedsig/appendedsig.h @@ -25,6 +25,43 @@ extern asn1_node grub_gnutls_pkix_asn; #define GRUB_MAX_OID_LEN 32 +/* RSA public key. */ +#define GRUB_MAX_MPI 2 +#define GRUB_RSA_PK_MODULUS 0 +#define GRUB_RSA_PK_EXPONENT 1 + +/* Certificate fingerprint. */ +#define GRUB_MAX_FINGERPRINT 3 +#define GRUB_FINGERPRINT_SHA256 0 +#define GRUB_FINGERPRINT_SHA384 1 +#define GRUB_FINGERPRINT_SHA512 2 + +/* Max size of hash data. */ +#define GRUB_MAX_HASH_LEN 64 + +/* + * One or more x509 certificates. We do limited parsing: + * extracting only the version, serial, issuer, subject, RSA public key + * and key size. + * Also, hold the sha256, sha384, and sha512 fingerprint of the certificate. + */ +struct x509_certificate +{ + struct x509_certificate *next; + grub_uint8_t version; + grub_uint8_t *serial; + grub_size_t serial_len; + char *issuer; + grub_size_t issuer_len; + char *subject; + grub_size_t subject_len; + /* We only support RSA public keys. This encodes [modulus, publicExponent]. */ + gcry_mpi_t mpis[GRUB_MAX_MPI]; + grub_int32_t modulus_size; + grub_uint8_t fingerprint[GRUB_MAX_FINGERPRINT][GRUB_MAX_HASH_LEN]; +}; +typedef struct x509_certificate grub_x509_cert_t; + /* A PKCS#7 signed data signer info. */ struct pkcs7_signer { @@ -44,6 +81,21 @@ struct pkcs7_data }; typedef struct pkcs7_data grub_pkcs7_data_t; +/* + * Import a DER-encoded certificate at 'data', of size 'size'. Place the results + * into 'results', which must be already allocated. + */ +extern grub_err_t +grub_x509_cert_parse (const void *data, grub_size_t size, grub_x509_cert_t *results); + +/* + * Release all the storage associated with the x509 certificate. If the caller + * dynamically allocated the certificate, it must free it. The caller is also + * responsible for maintenance of the linked list. + */ +extern void +grub_x509_cert_release (grub_x509_cert_t *cert); + /* * Parse a PKCS#7 message, which must be a signed data message. The message must * be in 'sigbuf' and of size 'data_size'. The result is placed in 'msg', which diff --git a/grub-core/commands/appendedsig/x509.c b/grub-core/commands/appendedsig/x509.c new file mode 100644 index 000000000..bc152663a --- /dev/null +++ b/grub-core/commands/appendedsig/x509.c @@ -0,0 +1,970 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2020, 2022 Free Software Foundation, Inc. + * Copyright (C) 2020, 2022, 2025 IBM Corporation + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <libtasn1.h> +#include <grub/types.h> +#include <grub/err.h> +#include <grub/mm.h> +#include <grub/crypto.h> +#include <grub/misc.h> +#include <grub/gcrypt/gcrypt.h> + +#include "appendedsig.h" + +static char asn1_error[ASN1_MAX_ERROR_DESCRIPTION_SIZE]; + + +/* RFC 3279 2.3.1 RSA Keys. */ +static const char *rsaEncryption_oid = "1.2.840.113549.1.1.1"; + +/* RFC 5280 Appendix A. */ +static const char *commonName_oid = "2.5.4.3"; + +/* RFC 5280 4.2.1.3 Key Usage. */ +static const char *keyUsage_oid = "2.5.29.15"; + +static const grub_uint8_t digitalSignatureUsage = 0x80; + +/* RFC 5280 4.2.1.9 Basic Constraints. */ +static const char *basicConstraints_oid = "2.5.29.19"; + +/* RFC 5280 4.2.1.12 Extended Key Usage. */ +static const char *extendedKeyUsage_oid = "2.5.29.37"; +static const char *codeSigningUsage_oid = "1.3.6.1.5.5.7.3.3"; + +/* + * RFC 3279 2.3.1 + * + * The RSA public key MUST be encoded using the ASN.1 type RSAPublicKey: + * + * RSAPublicKey ::= SEQUENCE { + * modulus INTEGER, -- n + * publicExponent INTEGER } -- e + * + * where modulus is the modulus n, and publicExponent is the public exponent e. + */ +static grub_err_t +grub_parse_rsa_pubkey (grub_uint8_t *der, grub_int32_t dersize, grub_x509_cert_t *certificate) +{ + grub_int32_t result; + asn1_node spk = NULL; + grub_uint8_t *m_data, *e_data; + grub_int32_t m_size, e_size; + grub_err_t err = GRUB_ERR_NONE; + gcry_error_t gcry_err; + + result = asn1_create_element (grub_gnutls_gnutls_asn, "GNUTLS.RSAPublicKey", &spk); + if (result != ASN1_SUCCESS) + return grub_error (GRUB_ERR_OUT_OF_MEMORY, + "cannot create storage for public key ASN.1 data"); + + result = asn1_der_decoding2 (&spk, der, &dersize, ASN1_DECODE_FLAG_STRICT_DER, asn1_error); + if (result != ASN1_SUCCESS) + { + err = grub_error (GRUB_ERR_BAD_FILE_TYPE, + "cannot decode certificate public key DER: %s", asn1_error); + goto cleanup; + } + + m_data = grub_asn1_allocate_and_read (spk, "modulus", "RSA modulus", &m_size); + if (m_data == NULL) + { + err = grub_errno; + goto cleanup; + } + + e_data = grub_asn1_allocate_and_read (spk, "publicExponent", "RSA public exponent", &e_size); + if (e_data == NULL) + { + err = grub_errno; + goto cleanup_m_data; + } + + /* + * Convert m, e to mpi + * + * nscanned is not set for FMT_USG, it's only set for FMT_PGP, so we can't + * verify it. + */ + gcry_err = _gcry_mpi_scan (&certificate->mpis[0], GCRYMPI_FMT_USG, m_data, m_size, NULL); + if (gcry_err != GPG_ERR_NO_ERROR) + { + err = grub_error (GRUB_ERR_BAD_FILE_TYPE, + "error loading RSA modulus into MPI structure: %d", gcry_err); + goto cleanup_e_data; + } + + gcry_err = _gcry_mpi_scan (&certificate->mpis[1], GCRYMPI_FMT_USG, e_data, e_size, NULL); + if (gcry_err != GPG_ERR_NO_ERROR) + { + err = grub_error (GRUB_ERR_BAD_FILE_TYPE, + "error loading RSA exponent into MPI structure: %d", gcry_err); + goto cleanup_m_mpi; + } + + /* RSA key size in bits. */ + certificate->modulus_size = (m_size * 8) - 8; + + grub_free (e_data); + grub_free (m_data); + asn1_delete_structure (&spk); + + return GRUB_ERR_NONE; + + cleanup_m_mpi: + _gcry_mpi_release (certificate->mpis[0]); + cleanup_e_data: + grub_free (e_data); + cleanup_m_data: + grub_free (m_data); + cleanup: + asn1_delete_structure (&spk); + + return err; +} + +/* + * RFC 5280: + * SubjectPublicKeyInfo ::= SEQUENCE { + * algorithm AlgorithmIdentifier, + * subjectPublicKey BIT STRING } + * + * AlgorithmIdentifiers come from RFC 3279, we are not strictly compilant as we + * only support RSA Encryption. + */ +static grub_err_t +grub_x509_read_subject_public_key (asn1_node asn, grub_x509_cert_t *results) +{ + grub_int32_t result; + grub_err_t err; + const char *algo_name = "tbsCertificate.subjectPublicKeyInfo.algorithm.algorithm"; + const char *params_name = "tbsCertificate.subjectPublicKeyInfo.algorithm.parameters"; + const char *pk_name = "tbsCertificate.subjectPublicKeyInfo.subjectPublicKey"; + char algo_oid[GRUB_MAX_OID_LEN]; + grub_int32_t algo_size = sizeof (algo_oid); + char params_value[2]; + grub_int32_t params_size = sizeof (params_value); + grub_uint8_t *key_data = NULL; + grub_int32_t key_size = 0; + grub_uint32_t key_type; + + /* Algorithm: see notes for rsaEncryption_oid. */ + result = asn1_read_value (asn, algo_name, algo_oid, &algo_size); + if (result != ASN1_SUCCESS) + return grub_error (GRUB_ERR_BAD_FILE_TYPE, "error reading x509 public key algorithm: %s", + asn1_strerror (result)); + + if (grub_strncmp (algo_oid, rsaEncryption_oid, sizeof (rsaEncryption_oid)) != 0) + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + "unsupported x509 public key algorithm: %s", algo_oid); + + /* + * RFC 3279 2.3.1 : The rsaEncryption OID is intended to be used in the + * algorithm field of a value of type AlgorithmIdentifier. The parameters + * field MUST have ASN.1 type NULL for this algorithm identifier. + */ + result = asn1_read_value (asn, params_name, params_value, ¶ms_size); + if (result != ASN1_SUCCESS) + return grub_error (GRUB_ERR_BAD_FILE_TYPE, "error reading x509 public key parameters: %s", + asn1_strerror (result)); + + if (params_value[0] != ASN1_TAG_NULL) + return grub_error (GRUB_ERR_BAD_FILE_TYPE, + "invalid x509 public key parameters: expected NULL"); + + /* + * RFC 3279 2.3.1: The DER encoded RSAPublicKey is the value of the BIT + * STRING subjectPublicKey. + */ + result = asn1_read_value_type (asn, pk_name, NULL, &key_size, &key_type); + if (result != ASN1_MEM_ERROR) + return grub_error (GRUB_ERR_BAD_FILE_TYPE, "error reading size of x509 public key: %s", + asn1_strerror (result)); + if (key_type != ASN1_ETYPE_BIT_STRING) + return grub_error (GRUB_ERR_BAD_FILE_TYPE, "unexpected ASN.1 type when reading x509 public key: %x", + key_type); + + /* Length is in bits. */ + key_size = (key_size + 7) / 8; + + key_data = grub_malloc (key_size); + if (key_data == NULL) + return grub_error (GRUB_ERR_OUT_OF_MEMORY, "out of memory for x509 public key"); + + result = asn1_read_value (asn, pk_name, key_data, &key_size); + if (result != ASN1_SUCCESS) + { + grub_free (key_data); + return grub_error (GRUB_ERR_BAD_FILE_TYPE, "error reading public key data"); + } + + key_size = (key_size + 7) / 8; + err = grub_parse_rsa_pubkey (key_data, key_size, results); + grub_free (key_data); + + return err; +} + +/* Decode a string as defined in Appendix A. */ +static grub_err_t +decode_string (char *der, grub_int32_t der_size, char **string, grub_size_t *string_size) +{ + asn1_node strasn; + grub_int32_t result; + char *choice; + grub_int32_t choice_size = 0; + grub_int32_t tmp_size = 0; + grub_err_t err = GRUB_ERR_NONE; + + result = asn1_create_element (grub_gnutls_pkix_asn, "PKIX1.DirectoryString", &strasn); + if (result != ASN1_SUCCESS) + return grub_error (GRUB_ERR_OUT_OF_MEMORY, + "could not create ASN.1 structure for certificate: %s", + asn1_strerror (result)); + + result = asn1_der_decoding2 (&strasn, der, &der_size, ASN1_DECODE_FLAG_STRICT_DER, asn1_error); + if (result != ASN1_SUCCESS) + { + err = grub_error (GRUB_ERR_BAD_FILE_TYPE, + "could not parse DER for DirectoryString: %s", asn1_error); + goto cleanup; + } + + choice = grub_asn1_allocate_and_read (strasn, "", "DirectoryString choice", &choice_size); + if (choice == NULL) + { + err = grub_errno; + goto cleanup; + } + + if (grub_strncmp ("utf8String", choice, choice_size) == 0) + { + result = asn1_read_value (strasn, "utf8String", NULL, &tmp_size); + if (result != ASN1_MEM_ERROR) + { + err = grub_error (GRUB_ERR_BAD_FILE_TYPE, "error reading size of UTF-8 string: %s", + asn1_strerror (result)); + goto cleanup_choice; + } + } + else if (grub_strncmp ("printableString", choice, choice_size) == 0) + { + result = asn1_read_value (strasn, "printableString", NULL, &tmp_size); + if (result != ASN1_MEM_ERROR) + { + err = grub_error (GRUB_ERR_BAD_FILE_TYPE, "error reading size of printableString: %s", + asn1_strerror (result)); + goto cleanup_choice; + } + } + else + { + err = grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + "only UTF-8 and printable DirectoryStrings are supported, got %s", + choice); + goto cleanup_choice; + } + + /* Read size does not include trailing NUL. */ + tmp_size++; + + *string = grub_malloc (tmp_size); + if (*string == NULL) + { + err = grub_error (GRUB_ERR_OUT_OF_MEMORY, + "cannot allocate memory for DirectoryString contents"); + goto cleanup_choice; + } + + result = asn1_read_value (strasn, choice, *string, &tmp_size); + if (result != ASN1_SUCCESS) + { + err = grub_error (GRUB_ERR_BAD_FILE_TYPE, "error reading out %s in DirectoryString: %s", + choice, asn1_strerror (result)); + grub_free (*string); + *string = NULL; + goto cleanup_choice; + } + + *string_size = tmp_size + 1; + (*string)[tmp_size] = '\0'; + + cleanup_choice: + grub_free (choice); + cleanup: + asn1_delete_structure (&strasn); + + return err; +} + +/* + * TBSCertificate ::= SEQUENCE { + * version [0] EXPLICIT Version DEFAULT v1, + * ... + * + * Version ::= INTEGER { v1(0), v2(1), v3(2) } + */ +static grub_err_t +check_version (asn1_node certificate, grub_x509_cert_t *results) +{ + grub_int32_t rc; + const char *name = "tbsCertificate.version"; + grub_uint8_t version; + grub_int32_t len = sizeof (version); + + rc = asn1_read_value (certificate, name, &version, &len); + + /* Require version 3. */ + if (rc != ASN1_SUCCESS || len != 1) + return grub_error (GRUB_ERR_BAD_FILE_TYPE, "error reading certificate version"); + + if (version != 0x02) + return grub_error (GRUB_ERR_BAD_FILE_TYPE, + "invalid x509 certificate version, expected v3 (0x02), got 0x%02x.", + version); + + results->version = version; + + return GRUB_ERR_NONE; +} + +/* we extract only the CN and issuer. */ +static grub_err_t +read_name (asn1_node asn, const char *name_path, char **name, grub_size_t *name_size) +{ + grub_int32_t seq_components, set_components; + grub_int32_t result; + grub_int32_t i, j; + char *top_path, *set_path, *type_path, *val_path; + char type[GRUB_MAX_OID_LEN]; + grub_int32_t type_len = sizeof (type); + grub_int32_t string_size = 0; + char *string_der; + grub_err_t err; + + *name = NULL; + + top_path = grub_xasprintf ("%s.rdnSequence", name_path); + if (top_path == NULL) + return grub_error (GRUB_ERR_OUT_OF_MEMORY, + "could not allocate memory for %s name parsing path", name_path); + + result = asn1_number_of_elements (asn, top_path, &seq_components); + if (result != ASN1_SUCCESS) + { + err = grub_error (GRUB_ERR_BAD_FILE_TYPE, "error counting name components: %s", + asn1_strerror (result)); + goto cleanup; + } + + for (i = 1; i <= seq_components; i++) + { + set_path = grub_xasprintf ("%s.?%d", top_path, i); + if (set_path == NULL) + { + err = grub_error (GRUB_ERR_OUT_OF_MEMORY, + "could not allocate memory for %s name set parsing path", + name_path); + goto cleanup_set; + } + /* This brings us, hopefully, to a set. */ + result = asn1_number_of_elements (asn, set_path, &set_components); + if (result != ASN1_SUCCESS) + { + err = grub_error (GRUB_ERR_BAD_FILE_TYPE, + "error counting name sub-components components (element %d): %s", + i, asn1_strerror (result)); + goto cleanup_set; + } + for (j = 1; j <= set_components; j++) + { + type_path = grub_xasprintf ("%s.?%d.?%d.type", top_path, i, j); + if (type_path == NULL) + { + err = grub_error (GRUB_ERR_OUT_OF_MEMORY, + "could not allocate memory for %s name component type path", + name_path); + goto cleanup_set; + } + type_len = sizeof (type); + result = asn1_read_value (asn, type_path, type, &type_len); + if (result != ASN1_SUCCESS) + { + err = grub_error (GRUB_ERR_BAD_FILE_TYPE, "error reading %s name component type: %s", + name_path, asn1_strerror (result)); + goto cleanup_type; + } + + if (grub_strncmp (type, commonName_oid, type_len) != 0) + { + grub_free (type_path); + continue; + } + + val_path = grub_xasprintf ("%s.?%d.?%d.value", top_path, i, j); + if (val_path == NULL) + { + err = grub_error (GRUB_ERR_OUT_OF_MEMORY, + "could not allocate memory for %s name component value path", + name_path); + goto cleanup_type; + } + + string_der = grub_asn1_allocate_and_read (asn, val_path, name_path, &string_size); + if (string_der == NULL) + { + err = grub_errno; + goto cleanup_val_path; + } + + err = decode_string (string_der, string_size, name, name_size); + if (err) + goto cleanup_string; + + grub_free (string_der); + grub_free (type_path); + grub_free (val_path); + break; + } + + grub_free (set_path); + if (*name) + break; + } + + grub_free (top_path); + + return GRUB_ERR_NONE; + + cleanup_string: + grub_free (string_der); + cleanup_val_path: + grub_free (val_path); + cleanup_type: + grub_free (type_path); + cleanup_set: + grub_free (set_path); + cleanup: + grub_free (top_path); + + return err; +} + +/* Verify the Key Usage extension. We require the Digital Signature usage. */ +static grub_err_t +verify_key_usage (grub_uint8_t *value, grub_int32_t value_size) +{ + asn1_node usageasn; + grub_int32_t result; + grub_err_t err = GRUB_ERR_NONE; + grub_uint8_t usage = 0xff; + grub_int32_t usage_size = sizeof (usage_size); + + result = asn1_create_element (grub_gnutls_pkix_asn, "PKIX1.KeyUsage", &usageasn); + if (result != ASN1_SUCCESS) + return grub_error (GRUB_ERR_OUT_OF_MEMORY, + "could not create ASN.1 structure for key usage"); + + result = asn1_der_decoding2 (&usageasn, value, &value_size, + ASN1_DECODE_FLAG_STRICT_DER, asn1_error); + if (result != ASN1_SUCCESS) + { + err = grub_error (GRUB_ERR_BAD_FILE_TYPE, + "error parsing DER for Key Usage: %s", asn1_error); + goto cleanup; + } + + result = asn1_read_value (usageasn, "", &usage, &usage_size); + if (result != ASN1_SUCCESS) + { + err = grub_error (GRUB_ERR_BAD_FILE_TYPE, "error reading Key Usage value: %s", + asn1_strerror (result)); + goto cleanup; + } + + if (!(usage & digitalSignatureUsage)) + { + err = grub_error (GRUB_ERR_BAD_FILE_TYPE, + "key usage (0x%x) missing Digital Signature usage", usage); + goto cleanup; + } + + cleanup: + asn1_delete_structure (&usageasn); + + return err; +} + +/* + * BasicConstraints ::= SEQUENCE { + * cA BOOLEAN DEFAULT FALSE, + * pathLenConstraint INTEGER (0..MAX) OPTIONAL } + */ +static grub_err_t +verify_basic_constraints (grub_uint8_t *value, grub_int32_t value_size) +{ + asn1_node basicasn; + grub_int32_t result; + grub_err_t err = GRUB_ERR_NONE; + char cA[6]; /* FALSE or TRUE. */ + grub_int32_t cA_size = sizeof (cA); + + result = asn1_create_element (grub_gnutls_pkix_asn, "PKIX1.BasicConstraints", &basicasn); + if (result != ASN1_SUCCESS) + return grub_error (GRUB_ERR_OUT_OF_MEMORY, + "could not create ASN.1 structure for Basic Constraints"); + + result = asn1_der_decoding2 (&basicasn, value, &value_size, + ASN1_DECODE_FLAG_STRICT_DER, asn1_error); + if (result != ASN1_SUCCESS) + { + err = grub_error (GRUB_ERR_BAD_FILE_TYPE, + "error parsing DER for Basic Constraints: %s", asn1_error); + goto cleanup; + } + + result = asn1_read_value (basicasn, "cA", cA, &cA_size); + if (result == ASN1_ELEMENT_NOT_FOUND) + { + /* Not present, default is False, so this is OK. */ + err = GRUB_ERR_NONE; + goto cleanup; + } + else if (result != ASN1_SUCCESS) + { + err = grub_error (GRUB_ERR_BAD_FILE_TYPE, "error reading Basic Constraints cA value: %s", + asn1_strerror (result)); + goto cleanup; + } + + /* The certificate must not be a CA certificate. */ + if (grub_strncmp ("FALSE", cA, cA_size) != 0) + { + err = grub_error (GRUB_ERR_BAD_FILE_TYPE, "unexpected CA value: %s", cA); + goto cleanup; + } + + cleanup: + asn1_delete_structure (&basicasn); + + return err; +} + +/* + * Verify the Extended Key Usage extension. We require the Code Signing usage. + * + * ExtKeyUsageSyntax ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId + * + * KeyPurposeId ::= OBJECT IDENTIFIER + */ +static grub_err_t +verify_extended_key_usage (grub_uint8_t *value, grub_int32_t value_size) +{ + asn1_node extendedasn; + grub_int32_t result, count, i = 0; + grub_err_t err = GRUB_ERR_NONE; + char usage[GRUB_MAX_OID_LEN], name[3]; + grub_int32_t usage_size = sizeof (usage); + + result = asn1_create_element (grub_gnutls_pkix_asn, "PKIX1.ExtKeyUsageSyntax", &extendedasn); + if (result != ASN1_SUCCESS) + return grub_error (GRUB_ERR_OUT_OF_MEMORY, + "could not create ASN.1 structure for Extended Key Usage"); + + result = asn1_der_decoding2 (&extendedasn, value, &value_size, + ASN1_DECODE_FLAG_STRICT_DER, asn1_error); + if (result != ASN1_SUCCESS) + { + err = grub_error (GRUB_ERR_BAD_FILE_TYPE, + "error parsing DER for Extended Key Usage: %s", asn1_error); + goto cleanup; + } + + /* If EKUs are present, it checks the presents of Code Signing usage. */ + result = asn1_number_of_elements (extendedasn, "", &count); + if (result != ASN1_SUCCESS) + { + err = grub_error (GRUB_ERR_BAD_FILE_TYPE, "error counting number of Extended Key Usages: %s", + asn1_strerror (result)); + goto cleanup; + } + + for (i = 1; i < count + 1; i++) + { + grub_memset (name, 0, sizeof (name)); + grub_snprintf (name, sizeof (name), "?%d", i); + result = asn1_read_value (extendedasn, name, usage, &usage_size); + if (result != ASN1_SUCCESS) + { + err = grub_error (GRUB_ERR_BAD_FILE_TYPE, "error reading Extended Key Usage: %s", + asn1_strerror (result)); + goto cleanup; + } + + if (grub_strncmp (codeSigningUsage_oid, usage, usage_size) == 0) + goto cleanup; + } + + err = grub_error (GRUB_ERR_BAD_FILE_TYPE, "extended key usage missing Code Signing usage"); + + cleanup: + asn1_delete_structure (&extendedasn); + + return err; +} + +/* + * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension + * + * Extension ::= SEQUENCE { + * extnID OBJECT IDENTIFIER, + * critical BOOLEAN DEFAULT FALSE, + * extnValue OCTET STRING + * -- contains the DER encoding of an ASN.1 value + * -- corresponding to the extension type identified + * -- by extnID + * } + * + * A certificate must: + * - contain the Digital Signature usage + * - not be a CA + * - contain no extended usages, or contain the Code Signing extended usage + * - not contain any other critical extensions (RFC 5280 s 4.2) + */ +static grub_err_t +verify_extensions (asn1_node cert) +{ + grub_int32_t result; + grub_int32_t ext, num_extensions = 0; + grub_int32_t usage_present = 0, constraints_present = 0, extended_usage_present = 0; + char *oid_path, *critical_path, *value_path; + char extnID[GRUB_MAX_OID_LEN]; + grub_int32_t extnID_size; + grub_err_t err; + char critical[6]; /* We get either "TRUE" or "FALSE". */ + grub_int32_t critical_size; + grub_uint8_t *value; + grub_int32_t value_size; + + result = asn1_number_of_elements (cert, "tbsCertificate.extensions", &num_extensions); + if (result != ASN1_SUCCESS) + return grub_error (GRUB_ERR_BAD_FILE_TYPE, "error counting number of extensions: %s", + asn1_strerror (result)); + + if (num_extensions < 2) + return grub_error (GRUB_ERR_BAD_FILE_TYPE, + "insufficient number of extensions for certificate, need at least 2, got %d", + num_extensions); + + for (ext = 1; ext <= num_extensions; ext++) + { + oid_path = grub_xasprintf ("tbsCertificate.extensions.?%d.extnID", ext); + if (oid_path == NULL) + { + err = grub_error (GRUB_ERR_BAD_FILE_TYPE, "error extension OID path is empty"); + return err; + } + + extnID_size = sizeof (extnID); + result = asn1_read_value (cert, oid_path, extnID, &extnID_size); + if (result != ASN1_SUCCESS) + { + err = grub_error (GRUB_ERR_BAD_FILE_TYPE, "error reading extension OID: %s", + asn1_strerror (result)); + goto cleanup_oid_path; + } + + critical_path = grub_xasprintf ("tbsCertificate.extensions.?%d.critical", ext); + if (critical_path == NULL) + { + err = grub_error (GRUB_ERR_BAD_FILE_TYPE, "error critical path is empty"); + goto cleanup_oid_path; + } + + critical_size = sizeof (critical); + result = asn1_read_value (cert, critical_path, critical, &critical_size); + if (result == ASN1_ELEMENT_NOT_FOUND) + critical[0] = '\0'; + else if (result != ASN1_SUCCESS) + { + err = grub_error (GRUB_ERR_BAD_FILE_TYPE, "error reading extension criticality: %s", + asn1_strerror (result)); + goto cleanup_critical_path; + } + + value_path = grub_xasprintf ("tbsCertificate.extensions.?%d.extnValue", ext); + if (value_path == NULL) + { + err = grub_error (GRUB_ERR_BAD_FILE_TYPE, "error extnValue path is empty"); + goto cleanup_critical_path; + } + + value = grub_asn1_allocate_and_read (cert, value_path, + "certificate extension value", &value_size); + if (value == NULL) + { + err = grub_errno; + goto cleanup_value_path; + } + + /* + * Now we must see if we recognise the OID. If we have an unrecognised + * critical extension we MUST bail. + */ + if (grub_strncmp (keyUsage_oid, extnID, extnID_size) == 0) + { + err = verify_key_usage (value, value_size); + if (err != GRUB_ERR_NONE) + goto cleanup_value; + + usage_present++; + } + else if (grub_strncmp (basicConstraints_oid, extnID, extnID_size) == 0) + { + err = verify_basic_constraints (value, value_size); + if (err != GRUB_ERR_NONE) + goto cleanup_value; + + constraints_present++; + } + else if (grub_strncmp (extendedKeyUsage_oid, extnID, extnID_size) == 0) + { + err = verify_extended_key_usage (value, value_size); + if (err != GRUB_ERR_NONE) + goto cleanup_value; + + extended_usage_present++; + } + else if (grub_strncmp ("TRUE", critical, critical_size) == 0) + { + /* + * Per the RFC, we must not process a certificate with a critical + * extension we do not understand. + */ + err = grub_error (GRUB_ERR_BAD_FILE_TYPE, + "unhandled critical x509 extension with OID %s", extnID); + goto cleanup_value; + } + + grub_free (value); + grub_free (value_path); + grub_free (critical_path); + grub_free (oid_path); + } + + if (usage_present != 1) + return grub_error (GRUB_ERR_BAD_FILE_TYPE, + "unexpected number of Key Usage extensions - expected 1, got %d", + usage_present); + + if (constraints_present != 1) + return grub_error (GRUB_ERR_BAD_FILE_TYPE, + "unexpected number of basic constraints extensions - expected 1, got %d", + constraints_present); + + if (extended_usage_present > 1) + return grub_error (GRUB_ERR_BAD_FILE_TYPE, + "unexpected number of Extended Key Usage extensions - expected 0 or 1, got %d", + extended_usage_present); + + return GRUB_ERR_NONE; + + cleanup_value: + grub_free (value); + cleanup_value_path: + grub_free (value_path); + cleanup_critical_path: + grub_free (critical_path); + cleanup_oid_path: + grub_free (oid_path); + + return err; +} + +static void +add_cert_fingerprint (const void *data, const grub_size_t data_size, + grub_x509_cert_t *const cert) +{ + /* Add SHA256 hash of certificate. */ + grub_crypto_hash ((gcry_md_spec_t *) &_gcry_digest_spec_sha256, + &cert->fingerprint[GRUB_FINGERPRINT_SHA256], data, data_size); + /* Add SHA384 hash of certificate. */ + grub_crypto_hash ((gcry_md_spec_t *) &_gcry_digest_spec_sha384, + &cert->fingerprint[GRUB_FINGERPRINT_SHA384], data, data_size); + /* Add SHA512 hash of certificate. */ + grub_crypto_hash ((gcry_md_spec_t *) &_gcry_digest_spec_sha512, + &cert->fingerprint[GRUB_FINGERPRINT_SHA512], data, data_size); +} + +/* + * Parse a certificate whose DER-encoded form is in @data, of size @data_size. + * Return the results in @results, which must point to an allocated x509 + * certificate. + */ +grub_err_t +grub_x509_cert_parse (const void *data, grub_size_t data_size, grub_x509_cert_t *results) +{ + grub_int32_t result = 0; + asn1_node cert; + grub_err_t err; + grub_int32_t tmp_size; + grub_int32_t size = (grub_int32_t) data_size; + + if (data_size > GRUB_UINT_MAX) + return grub_error (GRUB_ERR_OUT_OF_RANGE, + "cannot parse a certificate where data size > GRUB_UINT_MAX"); + + result = asn1_create_element (grub_gnutls_pkix_asn, "PKIX1.Certificate", &cert); + if (result != ASN1_SUCCESS) + return grub_error (GRUB_ERR_OUT_OF_MEMORY, + "could not create ASN.1 structure for certificate: %s", + asn1_strerror (result)); + + result = asn1_der_decoding2 (&cert, data, &size, ASN1_DECODE_FLAG_STRICT_DER, asn1_error); + if (result != ASN1_SUCCESS) + { + err = grub_error (GRUB_ERR_BAD_FILE_TYPE, + "could not parse DER for certificate: %s", asn1_error); + goto cleanup; + } + + /* + * TBSCertificate ::= SEQUENCE { + * version [0] EXPLICIT Version DEFAULT v1 + */ + err = check_version (cert, results); + if (err != GRUB_ERR_NONE) + goto cleanup; + + /* + * serialNumber CertificateSerialNumber, + * + * CertificateSerialNumber ::= INTEGER + */ + results->serial = grub_asn1_allocate_and_read (cert, "tbsCertificate.serialNumber", + "certificate serial number", &tmp_size); + if (results->serial == NULL) + { + err = grub_errno; + goto cleanup; + } + /* + * It's safe to cast the signed int to an unsigned here, we know + * length is non-negative. + */ + results->serial_len = tmp_size; + + /* + * signature AlgorithmIdentifier, + * + * We don't load the signature or issuer at the moment, + * as we don't attempt x509 verification. + */ + + /* + * validity Validity, + * + * Validity ::= SEQUENCE { + * notBefore Time, + * notAfter Time } + * + * We can't validate this reasonably, we have no true time source on several + * platforms. For now we do not parse them. + */ + + /* + * issuer Name, + * + * This is an X501 name, we parse out just the issuer. + */ + err = read_name (cert, "tbsCertificate.issuer", &results->issuer, &results->issuer_len); + if (err != GRUB_ERR_NONE) + goto cleanup_serial; + + /* + * subject Name, + * + * This is an X501 name, we parse out just the CN. + */ + err = read_name (cert, "tbsCertificate.subject", &results->subject, &results->subject_len); + if (err != GRUB_ERR_NONE) + goto cleanup_issuer; + + /* + * TBSCertificate ::= SEQUENCE { + * ... + * subjectPublicKeyInfo SubjectPublicKeyInfo, + * ... + */ + err = grub_x509_read_subject_public_key (cert, results); + if (err != GRUB_ERR_NONE) + goto cleanup_name; + + /* + * TBSCertificate ::= SEQUENCE { + * ... + * extensions [3] EXPLICIT Extensions OPTIONAL + * -- If present, version MUST be v3 + * } + */ + err = verify_extensions (cert); + if (err != GRUB_ERR_NONE) + goto cleanup_mpis; + + /* + * We do not read or check the signature on the certificate: + * as discussed we do not try to validate the certificate but trust + * it implictly. + */ + asn1_delete_structure (&cert); + + /* Add the fingerprint of the certificate. */ + add_cert_fingerprint (data, data_size, results); + + return GRUB_ERR_NONE; + + cleanup_mpis: + _gcry_mpi_release (results->mpis[GRUB_RSA_PK_MODULUS]); + _gcry_mpi_release (results->mpis[GRUB_RSA_PK_EXPONENT]); + cleanup_name: + grub_free (results->subject); + cleanup_issuer: + grub_free (results->issuer); + cleanup_serial: + grub_free (results->serial); + cleanup: + asn1_delete_structure (&cert); + + return err; +} + +/* + * Release all the storage associated with the x509 certificate. If the caller + * dynamically allocated the certificate, it must free it. The caller is also + * responsible for maintenance of the linked list. + */ +void +grub_x509_cert_release (grub_x509_cert_t *cert) +{ + grub_free (cert->issuer); + grub_free (cert->subject); + grub_free (cert->serial); + _gcry_mpi_release (cert->mpis[GRUB_RSA_PK_MODULUS]); + _gcry_mpi_release (cert->mpis[GRUB_RSA_PK_EXPONENT]); +} diff --git a/include/grub/crypto.h b/include/grub/crypto.h index 6ab021cb8..e4e2bd1a7 100644 --- a/include/grub/crypto.h +++ b/include/grub/crypto.h @@ -518,6 +518,7 @@ grub_crypto_hmac_buffer (const struct gcry_md_spec *md, extern gcry_md_spec_t _gcry_digest_spec_md5; extern gcry_md_spec_t _gcry_digest_spec_sha1; extern gcry_md_spec_t _gcry_digest_spec_sha256; +extern gcry_md_spec_t _gcry_digest_spec_sha384; extern gcry_md_spec_t _gcry_digest_spec_sha512; extern gcry_md_spec_t _gcry_digest_spec_crc32; extern gcry_cipher_spec_t _gcry_cipher_spec_aes; -- 2.50.1 (Apple Git-155) _______________________________________________ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel ^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH v13 09/20] powerpc_ieee1275: Enter lockdown based on /ibm, secure-boot 2025-09-30 11:39 [PATCH v13 00/20] Appended Signature Secure Boot Support for PowerPC Sudhakar Kuppusamy ` (7 preceding siblings ...) 2025-09-30 11:40 ` [PATCH v13 08/20] appended signatures: Parse X.509 certificates Sudhakar Kuppusamy @ 2025-09-30 11:40 ` Sudhakar Kuppusamy 2025-09-30 11:40 ` [PATCH v13 10/20] appended signatures: Support verifying appended signatures Sudhakar Kuppusamy ` (11 subsequent siblings) 20 siblings, 0 replies; 25+ messages in thread From: Sudhakar Kuppusamy @ 2025-09-30 11:40 UTC (permalink / raw) To: grub-devel Cc: dja, jan.setjeeilers, julian.klode, mate.kukri, pjones, msuchanek, mlewando, stefanb, avnish, nayna, ssrish, Sudhakar Kuppusamy, sridharm, Daniel Kiper Read secure boot mode from 'ibm,secure-boot' property and if the secure boot mode is set to 2 (enforce), enter lockdown. Else it is considered as disabled. There are three secure boot modes. They are 0 - disabled No signature verification is performed. This is the default. 1 - audit Signature verification is performed and if signature verification fails, post the errors and allow the boot to continue. 2 - enforce Lockdown the GRUB. Signature verification is performed and If signature verification fails, post the errors and stop the boot. Now, only support disabled and enforce. 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> --- docs/grub.texi | 2 +- grub-core/Makefile.core.def | 1 + grub-core/kern/ieee1275/init.c | 54 ++++++++++++++++++++++++++++++++++ include/grub/lockdown.h | 3 +- 4 files changed, 58 insertions(+), 2 deletions(-) diff --git a/docs/grub.texi b/docs/grub.texi index 37297fc2c..8a23c29a3 100644 --- a/docs/grub.texi +++ b/docs/grub.texi @@ -9144,7 +9144,7 @@ platforms. @section Lockdown when booting on a secure setup The GRUB can be locked down when booted on a secure boot environment, for example -if the UEFI secure boot is enabled. On a locked down configuration, the GRUB will +if the UEFI or Power secure boot is enabled. On a locked down configuration, the GRUB will be restricted and some operations/commands cannot be executed. This also includes limiting which filesystems are supported to those thought to be more robust and widely used within GRUB. diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index 0fcf67f9d..8e3929710 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -333,6 +333,7 @@ kernel = { powerpc_ieee1275 = kern/powerpc/cache.S; powerpc_ieee1275 = kern/powerpc/dl.c; powerpc_ieee1275 = kern/powerpc/compiler-rt.S; + powerpc_ieee1275 = kern/lockdown.c; sparc64_ieee1275 = kern/sparc64/cache.S; sparc64_ieee1275 = kern/sparc64/dl.c; diff --git a/grub-core/kern/ieee1275/init.c b/grub-core/kern/ieee1275/init.c index a5586f85b..a81a36f57 100644 --- a/grub-core/kern/ieee1275/init.c +++ b/grub-core/kern/ieee1275/init.c @@ -49,6 +49,14 @@ #if defined(__powerpc__) || defined(__i386__) #include <grub/ieee1275/alloc.h> #endif +#if defined(__powerpc__) +#include <grub/lockdown.h> +#endif + +#ifdef __powerpc__ +#define GRUB_SB_DISABLED ((grub_uint32_t) 0) +#define GRUB_SB_ENFORCE ((grub_uint32_t) 2) +#endif /* The maximum heap size we're going to claim at boot. Not used by sparc. */ #ifdef __i386__ @@ -994,7 +1002,49 @@ grub_parse_cmdline (void) } } } +#ifdef __powerpc__ +static void +grub_ieee1275_get_secure_boot (void) +{ + grub_ieee1275_phandle_t root; + grub_uint32_t sb_mode = GRUB_SB_DISABLED; + grub_int32_t rc; + + rc = grub_ieee1275_finddevice ("/", &root); + if (rc != 0) + { + grub_error (GRUB_ERR_UNKNOWN_DEVICE, "couldn't find / node"); + return; + } + rc = grub_ieee1275_get_integer_property (root, "ibm,secure-boot", &sb_mode, sizeof (sb_mode), 0); + if (rc != 0) + { + grub_error (GRUB_ERR_UNKNOWN_DEVICE, "couldn't examine /ibm,secure-boot property"); + return; + } + /* + * Secure Boot Mode: + * 0 - disabled + * No signature verification is performed. This is the default. + * 1 - audit + * Signature verification is performed and if signature verification + * fails, post the errors and allow the boot to continue. + * 2 - enforce + * Lockdown the GRUB. Signature verification is performed and If + * signature verification fails, post the errors and stop the boot. + * + * Now, only support disabled and enforce. + */ + if (sb_mode == GRUB_SB_ENFORCE) + { + grub_dprintf ("ieee1275", "Secure Boot Enabled\n"); + grub_lockdown (); + } + else + grub_dprintf ("ieee1275", "Secure Boot Disabled\n"); +} +#endif /* __powerpc__ */ grub_addr_t grub_modbase; void @@ -1020,6 +1070,10 @@ grub_machine_init (void) #else grub_install_get_time_ms (grub_rtc_get_time_ms); #endif + +#ifdef __powerpc__ + grub_ieee1275_get_secure_boot (); +#endif } void diff --git a/include/grub/lockdown.h b/include/grub/lockdown.h index 40531fa82..ebfee4bf0 100644 --- a/include/grub/lockdown.h +++ b/include/grub/lockdown.h @@ -24,7 +24,8 @@ #define GRUB_LOCKDOWN_DISABLED 0 #define GRUB_LOCKDOWN_ENABLED 1 -#ifdef GRUB_MACHINE_EFI +#if defined(GRUB_MACHINE_EFI) || \ + (defined(__powerpc__) && defined(GRUB_MACHINE_IEEE1275)) extern void EXPORT_FUNC (grub_lockdown) (void); extern int -- 2.50.1 (Apple Git-155) _______________________________________________ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel ^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH v13 10/20] appended signatures: Support verifying appended signatures 2025-09-30 11:39 [PATCH v13 00/20] Appended Signature Secure Boot Support for PowerPC Sudhakar Kuppusamy ` (8 preceding siblings ...) 2025-09-30 11:40 ` [PATCH v13 09/20] powerpc_ieee1275: Enter lockdown based on /ibm, secure-boot Sudhakar Kuppusamy @ 2025-09-30 11:40 ` Sudhakar Kuppusamy 2025-09-30 11:40 ` [PATCH v13 11/20] powerpc_ieee1275: Read the db and dbx secure boot variables Sudhakar Kuppusamy ` (10 subsequent siblings) 20 siblings, 0 replies; 25+ messages in thread From: Sudhakar Kuppusamy @ 2025-09-30 11:40 UTC (permalink / raw) To: grub-devel Cc: dja, jan.setjeeilers, julian.klode, mate.kukri, pjones, msuchanek, mlewando, stefanb, avnish, nayna, ssrish, Sudhakar Kuppusamy, sridharm, Daniel Kiper [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #1: Type: text/plain; charset=y, Size: 22318 bytes --] Building on the parsers and the ability to embed X.509 certificates, as well as the existing gcrypt functionality, add a module for verifying appended signatures. This includes a signature verifier that requires that the Linux kernel and GRUB modules have appended signatures for verification. Signature verification must be enabled by setting check_appended_signatures. If secure boot is enabled with enforce mode when the appendedsig module is loaded, signature verification will be enabled, and trusted keys will be extracted from the GRUB ELF Note and stored in the db and locked automatically. Signed-off-by: Daniel Axtens <dja@axtens.net> Signed-off-by: Sudhakar Kuppusamy <sudhakar@linux.ibm.com> Reviewed-by: Avnish Chouhan <avnish@linux.ibm.com> Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com> --- grub-core/Makefile.core.def | 15 + grub-core/commands/appendedsig/appendedsig.c | 581 +++++++++++++++++++ include/grub/err.h | 3 +- include/grub/file.h | 2 + 4 files changed, 600 insertions(+), 1 deletion(-) create mode 100644 grub-core/commands/appendedsig/appendedsig.c diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index 8e3929710..6824a0ee4 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -997,6 +997,21 @@ module = { cppflags = '$(CPPFLAGS_GCRY)'; }; +module = { + name = appendedsig; + common = commands/appendedsig/appendedsig.c; + common = commands/appendedsig/x509.c; + common = commands/appendedsig/pkcs7.c; + common = commands/appendedsig/asn1util.c; + common = commands/appendedsig/gnutls_asn1_tab.c; + common = commands/appendedsig/pkix_asn1_tab.c; + enable = emu; + enable = powerpc_ieee1275; + cflags = '$(CFLAGS_GCRY) -Wno-redundant-decls'; + cppflags = '$(CPPFLAGS_GCRY) -I$(srcdir)/lib/libtasn1-grub'; + depends = crypto, gcry_rsa, gcry_sha256, gcry_sha512, mpi, asn1; +}; + module = { name = hdparm; common = commands/hdparm.c; diff --git a/grub-core/commands/appendedsig/appendedsig.c b/grub-core/commands/appendedsig/appendedsig.c new file mode 100644 index 000000000..e53efd2da --- /dev/null +++ b/grub-core/commands/appendedsig/appendedsig.c @@ -0,0 +1,581 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2020, 2021, 2022 Free Software Foundation, Inc. + * Copyright (C) 2020, 2021, 2022, 2025 IBM Corporation + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <grub/types.h> +#include <grub/misc.h> +#include <grub/mm.h> +#include <grub/err.h> +#include <grub/dl.h> +#include <grub/file.h> +#include <grub/command.h> +#include <grub/crypto.h> +#include <grub/i18n.h> +#include <grub/gcrypt/gcrypt.h> +#include <grub/kernel.h> +#include <grub/extcmd.h> +#include <grub/verify.h> +#include <libtasn1.h> +#include <grub/env.h> +#include <grub/lockdown.h> + +#include "appendedsig.h" + +GRUB_MOD_LICENSE ("GPLv3+"); + +/* Public key type. */ +#define PKEY_ID_PKCS7 2 + +/* Appended signature magic string and size. */ +#define SIG_MAGIC "~Module signature appended~\n" +#define SIG_MAGIC_SIZE ((sizeof(SIG_MAGIC) - 1)) + +/* + * This structure is extracted from scripts/sign-file.c in the linux kernel + * source. It was licensed as LGPLv2.1+, which is GPLv3+ compatible. + */ +struct module_signature +{ + grub_uint8_t algo; /* Public-key crypto algorithm [0]. */ + grub_uint8_t hash; /* Digest algorithm [0]. */ + grub_uint8_t id_type; /* Key identifier type [PKEY_ID_PKCS7]. */ + grub_uint8_t signer_len; /* Length of signer's name [0]. */ + grub_uint8_t key_id_len; /* Length of key identifier [0]. */ + grub_uint8_t __pad[3]; + grub_uint32_t sig_len; /* Length of signature data. */ +} GRUB_PACKED; + +#define SIG_METADATA_SIZE (sizeof (struct module_signature)) +#define APPENDED_SIG_SIZE(pkcs7_data_size) \ + (pkcs7_data_size + SIG_MAGIC_SIZE + SIG_METADATA_SIZE) + +/* This represents an entire, parsed, appended signature. */ +struct appended_signature +{ + struct module_signature sig_metadata; /* Module signature metadata. */ + grub_pkcs7_data_t pkcs7; /* Parsed PKCS#7 data. */ + grub_size_t signature_len; /* Length of PKCS#7 data + metadata + magic. */ +}; +typedef struct appended_signature sb_appendedsig_t; + +/* This represents a trusted certificates. */ +struct sb_database +{ + grub_x509_cert_t *certs; /* Certificates. */ + grub_uint32_t cert_entries; /* Number of certificates. */ +}; +typedef struct sb_database sb_database_t; + +/* The db list is used to validate appended signatures. */ +static sb_database_t db = {.certs = NULL, .cert_entries = 0}; + +/* + * Signature verification flag (check_sigs). + * check_sigs: false + * - No signature verification. This is the default. + * check_sigs: true + * - Enforce signature verification, and if signature verification fails, post + * the errors and stop the boot. + */ +static bool check_sigs = false; + +static grub_ssize_t +pseudo_read (struct grub_file *file, char *buf, grub_size_t len) +{ + grub_memcpy (buf, (grub_uint8_t *) file->data + file->offset, len); + return len; +} + +/* Filesystem descriptor. */ +static struct grub_fs pseudo_fs = { + .name = "pseudo", + .fs_read = pseudo_read +}; + +static bool +is_cert_match (const grub_x509_cert_t *cert1, const grub_x509_cert_t *cert2) +{ + if (grub_memcmp (cert1->subject, cert2->subject, cert2->subject_len) == 0 + && grub_memcmp (cert1->issuer, cert2->issuer, cert2->issuer_len) == 0 + && grub_memcmp (cert1->serial, cert2->serial, cert2->serial_len) == 0 + && grub_memcmp (cert1->mpis[GRUB_RSA_PK_MODULUS], cert2->mpis[GRUB_RSA_PK_MODULUS], + sizeof (cert2->mpis[GRUB_RSA_PK_MODULUS])) == 0 + && grub_memcmp (cert1->mpis[GRUB_RSA_PK_EXPONENT], cert2->mpis[GRUB_RSA_PK_EXPONENT], + sizeof (cert2->mpis[GRUB_RSA_PK_EXPONENT])) == 0 + && grub_memcmp (cert1->fingerprint[GRUB_FINGERPRINT_SHA256], + cert2->fingerprint[GRUB_FINGERPRINT_SHA256], + grub_strlen ((char *) cert2->fingerprint[GRUB_FINGERPRINT_SHA256])) == 0) + return true; + + return false; +} + +/* Check the certificate presence in the db list. */ +static bool +check_cert_presence (const grub_x509_cert_t *cert_in, const sb_database_t *sb_database) +{ + grub_x509_cert_t *cert; + + for (cert = sb_database->certs; cert != NULL; cert = cert->next) + if (is_cert_match (cert, cert_in) == true) + return true; + + return false; +} + +/* Add the certificate into the db list */ +static grub_err_t +add_certificate (const grub_uint8_t *data, const grub_size_t data_size, + sb_database_t *sb_database) +{ + grub_err_t rc; + grub_x509_cert_t *cert; + + if (data == NULL || data_size == 0) + return grub_error (GRUB_ERR_OUT_OF_RANGE, "certificate data or size is not available"); + + cert = grub_zalloc (sizeof (grub_x509_cert_t)); + if (cert == NULL) + return grub_error (GRUB_ERR_OUT_OF_MEMORY, "out of memory"); + + rc = grub_x509_cert_parse (data, data_size, cert); + if (rc != GRUB_ERR_NONE) + { + grub_dprintf ("appendedsig", "cannot add a certificate CN='%s' to the db list\n", + cert->subject); + grub_free (cert); + return rc; + } + + if (check_cert_presence (cert, sb_database) == true) + { + grub_dprintf ("appendedsig", + "cannot add a certificate CN='%s', as it is present in the db list", + cert->subject); + grub_x509_cert_release (cert); + grub_free (cert); + + return GRUB_ERR_EXISTS; + } + + grub_dprintf ("appendedsig", "added a certificate CN='%s' to the db list\n", + cert->subject); + + cert->next = sb_database->certs; + sb_database->certs = cert; + sb_database->cert_entries++; + + return rc; +} + +static grub_err_t +file_read_whole (grub_file_t file, grub_uint8_t **buf, grub_size_t *len) +{ + grub_off_t full_file_size; + grub_size_t file_size, total_read_size = 0; + grub_ssize_t read_size; + + full_file_size = grub_file_size (file); + if (full_file_size == GRUB_FILE_SIZE_UNKNOWN) + return grub_error (GRUB_ERR_BAD_ARGUMENT, + "cannot read a file of unknown size into a buffer"); + + if (full_file_size > GRUB_SIZE_MAX) + return grub_error (GRUB_ERR_OUT_OF_RANGE, + "file is too large to read: %" PRIuGRUB_OFFSET " bytes", + full_file_size); + + file_size = (grub_size_t) full_file_size; + *buf = grub_malloc (file_size); + if (*buf == NULL) + return grub_error (GRUB_ERR_OUT_OF_MEMORY, + "could not allocate file data buffer size %" PRIuGRUB_SIZE, + file_size); + + while (total_read_size < file_size) + { + read_size = grub_file_read (file, *buf + total_read_size, file_size - total_read_size); + if (read_size < 0) + { + grub_free (*buf); + return grub_errno; + } + else if (read_size == 0) + { + grub_free (*buf); + return grub_error (GRUB_ERR_IO, + "could not read full file size " + "(%" PRIuGRUB_SIZE "), only %" PRIuGRUB_SIZE " bytes read", + file_size, total_read_size); + } + + total_read_size += read_size; + } + + *len = file_size; + + return GRUB_ERR_NONE; +} + +static grub_err_t +extract_appended_signature (const grub_uint8_t *buf, grub_size_t bufsize, + sb_appendedsig_t *sig) +{ + grub_size_t appendedsig_pkcs7_size; + grub_size_t signed_data_size = bufsize; + const grub_uint8_t *signed_data = buf; + + if (signed_data_size < SIG_MAGIC_SIZE) + return grub_error (GRUB_ERR_BAD_SIGNATURE, "file too short for signature magic"); + + /* Fast-forwarding pointer and get signature magic string. */ + signed_data += signed_data_size - SIG_MAGIC_SIZE; + if (grub_strncmp ((const char *) signed_data, SIG_MAGIC, SIG_MAGIC_SIZE)) + return grub_error (GRUB_ERR_BAD_SIGNATURE, "missing or invalid signature magic"); + + signed_data_size -= SIG_MAGIC_SIZE; + if (signed_data_size < SIG_METADATA_SIZE) + return grub_error (GRUB_ERR_BAD_SIGNATURE, "file too short for signature metadata"); + + /* Rewind pointer and extract signature metadata. */ + signed_data -= SIG_METADATA_SIZE; + grub_memcpy (&(sig->sig_metadata), signed_data, SIG_METADATA_SIZE); + + if (sig->sig_metadata.id_type != PKEY_ID_PKCS7) + return grub_error (GRUB_ERR_BAD_SIGNATURE, "wrong signature type"); + + appendedsig_pkcs7_size = grub_be_to_cpu32 (sig->sig_metadata.sig_len); + + signed_data_size -= SIG_METADATA_SIZE; + if (appendedsig_pkcs7_size > signed_data_size) + return grub_error (GRUB_ERR_BAD_SIGNATURE, "file too short for PKCS#7 message"); + + grub_dprintf ("appendedsig", "sig len %" PRIuGRUB_SIZE "\n", appendedsig_pkcs7_size); + + /* Appended signature size. */ + sig->signature_len = APPENDED_SIG_SIZE (appendedsig_pkcs7_size); + /* Rewind pointer and parse appended pkcs7 data. */ + signed_data -= appendedsig_pkcs7_size; + + return grub_pkcs7_data_parse (signed_data, appendedsig_pkcs7_size, &sig->pkcs7); +} + +/* + * Given a hash value 'hval', of hash specification 'hash', prepare the + * S-expressions (sexp) and perform the signature verification. + */ +static grub_err_t +verify_signature (const gcry_mpi_t *pkmpi, const gcry_mpi_t hmpi, + const gcry_md_spec_t *hash, const grub_uint8_t *hval) +{ + gcry_sexp_t hsexp, pubkey, sig; + grub_size_t errof; + + if (_gcry_sexp_build (&hsexp, &errof, "(data (flags %s) (hash %s %b))", "pkcs1", + hash->name, hash->mdlen, hval) != GPG_ERR_NO_ERROR) + return GRUB_ERR_BAD_SIGNATURE; + + if (_gcry_sexp_build (&pubkey, &errof, "(public-key (dsa (n %M) (e %M)))", + pkmpi[0], pkmpi[1]) != GPG_ERR_NO_ERROR) + return GRUB_ERR_BAD_SIGNATURE; + + if (_gcry_sexp_build (&sig, &errof, "(sig-val (rsa (s %M)))", hmpi) != GPG_ERR_NO_ERROR) + return GRUB_ERR_BAD_SIGNATURE; + + _gcry_sexp_dump (sig); + _gcry_sexp_dump (hsexp); + _gcry_sexp_dump (pubkey); + + if (grub_crypto_pk_rsa->verify (sig, hsexp, pubkey) != GPG_ERR_NO_ERROR) + return GRUB_ERR_BAD_SIGNATURE; + + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_verify_appended_signature (const grub_uint8_t *buf, grub_size_t bufsize) +{ + grub_err_t err; + grub_size_t datasize; + void *context; + grub_uint8_t *hash; + grub_x509_cert_t *pk; + sb_appendedsig_t sig; + grub_pkcs7_signer_t *si; + grub_int32_t i; + + if (!db.cert_entries) + return grub_error (GRUB_ERR_BAD_SIGNATURE, "no trusted keys to verify against"); + + err = extract_appended_signature (buf, bufsize, &sig); + if (err != GRUB_ERR_NONE) + return err; + + datasize = bufsize - sig.signature_len; + + /* Verify signature using trusted keys from db list. */ + for (i = 0; i < sig.pkcs7.signer_count; i++) + { + si = &sig.pkcs7.signers[i]; + context = grub_zalloc (si->hash->contextsize); + if (context == NULL) + return grub_errno; + + si->hash->init (context, 0); + si->hash->write (context, buf, datasize); + si->hash->final (context); + hash = si->hash->read (context); + + grub_dprintf ("appendedsig", "data size %" PRIuGRUB_SIZE ", signer %d hash %02x%02x%02x%02x...\n", + datasize, i, hash[0], hash[1], hash[2], hash[3]); + + for (pk = db.certs; pk != NULL; pk = pk->next) + { + err = verify_signature (pk->mpis, si->sig_mpi, si->hash, hash); + if (err == GRUB_ERR_NONE) + { + grub_dprintf ("appendedsig", "verify signer %d with key '%s' succeeded\n", + i, pk->subject); + break; + } + + grub_dprintf ("appendedsig", "verify signer %d with key '%s' failed\n", + i, pk->subject); + } + + grub_free (context); + if (err == GRUB_ERR_NONE) + break; + } + + grub_pkcs7_data_release (&sig.pkcs7); + + if (err != GRUB_ERR_NONE) + return grub_error (err, "failed to verify signature against a trusted key"); + + return err; +} + +/* + * Extract the X.509 certificates from the ELF Note header, parse it, and add + * it to the db list. + */ +static void +load_elf2db (void) +{ + grub_err_t err; + struct grub_module_header *header; + struct grub_file pseudo_file; + grub_uint8_t *cert_data = NULL; + grub_size_t cert_data_size = 0; + + FOR_MODULES (header) + { + /* Not an X.509 certificate, skip. */ + if (header->type != OBJ_TYPE_X509_PUBKEY) + continue; + + grub_memset (&pseudo_file, 0, sizeof (pseudo_file)); + pseudo_file.fs = &pseudo_fs; + pseudo_file.size = header->size - sizeof (struct grub_module_header); + pseudo_file.data = (char *) header + sizeof (struct grub_module_header); + + grub_dprintf ("appendedsig", "found an X.509 certificate, size=%" PRIuGRUB_UINT64_T "\n", + pseudo_file.size); + + err = file_read_whole (&pseudo_file, &cert_data, &cert_data_size); + if (err == GRUB_ERR_OUT_OF_MEMORY) + return; + else if (err != GRUB_ERR_NONE) + continue; + + err = add_certificate (cert_data, cert_data_size, &db); + grub_free (cert_data); + if (err == GRUB_ERR_OUT_OF_MEMORY) + return; + } +} + +/* Free db list memory */ +static void +free_db_list (void) +{ + grub_x509_cert_t *cert; + + while (db.certs != NULL) + { + cert = db.certs; + db.certs = db.certs->next; + grub_x509_cert_release (cert); + grub_free (cert); + } + + grub_memset (&db, 0, sizeof (sb_database_t)); +} + +static const char * +grub_env_read_sec (struct grub_env_var *var __attribute__ ((unused)), + const char *val __attribute__ ((unused))) +{ + if (check_sigs == true) + return "yes"; + + return "no"; +} + +static char * +grub_env_write_sec (struct grub_env_var *var __attribute__ ((unused)), const char *val) +{ + char *ret; + + /* + * Do not allow the value to be changed if signature verification is enabled + * (check_sigs is set to true) and GRUB is locked down. + */ + if (check_sigs == true && grub_is_lockdown () == GRUB_LOCKDOWN_ENABLED) + { + ret = grub_strdup ("yes"); + if (ret == NULL) + grub_error (GRUB_ERR_OUT_OF_MEMORY, "could not duplicate a string enforce"); + + return ret; + } + + if (grub_strcmp (val, "yes") == 0) + check_sigs = true; + else if (grub_strcmp (val, "no") == 0) + check_sigs = false; + + ret = grub_strdup (grub_env_read_sec (NULL, NULL)); + if (ret == NULL) + grub_error (GRUB_ERR_OUT_OF_MEMORY, "could not duplicate a string %s", + grub_env_read_sec (NULL, NULL)); + + return ret; +} + +static grub_err_t +appendedsig_init (grub_file_t io __attribute__ ((unused)), enum grub_file_type type, + void **context __attribute__ ((unused)), enum grub_verify_flags *flags) +{ + if (check_sigs == false) + { + *flags = GRUB_VERIFY_FLAGS_SKIP_VERIFICATION; + return GRUB_ERR_NONE; + } + + switch (type & GRUB_FILE_TYPE_MASK) + { + case GRUB_FILE_TYPE_CERTIFICATE_TRUST: + /* + * This is a certificate to add to trusted keychain. + * + * This needs to be verified or blocked. Ideally we'd write an x509 + * verifier, but we lack the hubris required to take this on. Instead, + * require that it have an appended signature. + */ + case GRUB_FILE_TYPE_LINUX_KERNEL: + case GRUB_FILE_TYPE_GRUB_MODULE: + /* + * Appended signatures are only defined for ELF binaries. Out of an + * abundance of caution, we only verify Linux kernels and GRUB modules + * at this point. + */ + *flags = GRUB_VERIFY_FLAGS_SINGLE_CHUNK; + return GRUB_ERR_NONE; + + case GRUB_FILE_TYPE_ACPI_TABLE: + case GRUB_FILE_TYPE_DEVICE_TREE_IMAGE: + /* + * It is possible to use appended signature verification without + * lockdown - like the PGP verifier. When combined with an embedded + * config file in a signed GRUB binary, this could still be a meaningful + * secure-boot chain - so long as it isn't subverted by something like a + * rouge ACPI table or DT image. Defer them explicitly. + */ + *flags = GRUB_VERIFY_FLAGS_DEFER_AUTH; + return GRUB_ERR_NONE; + + default: + *flags = GRUB_VERIFY_FLAGS_SKIP_VERIFICATION; + return GRUB_ERR_NONE; + } +} + +static grub_err_t +appendedsig_write (void *ctxt __attribute__ ((unused)), void *buf, grub_size_t size) +{ + return grub_verify_appended_signature (buf, size); +} + +struct grub_file_verifier grub_appendedsig_verifier = { + .name = "appendedsig", + .init = appendedsig_init, + .write = appendedsig_write, +}; + +GRUB_MOD_INIT (appendedsig) +{ + grub_int32_t rc; + + /* + * If secure boot is enabled with enforce mode and GRUB is locked down, enable + * signature verification. + */ + if (grub_is_lockdown () == GRUB_LOCKDOWN_ENABLED) + check_sigs = true; + + /* + * This is appended signature verification environment variable. It is + * automatically set to either "no" or "yes" based on the ’ibm,secure-boot’ + * device tree property. + * + * "no": No signature verification. This is the default. + * + * "yes": Enforce signature verification. When GRUB is locked down, user cannot + * change the value by setting the check_appended_signatures variable + * back to ‘no’ + */ + grub_register_variable_hook ("check_appended_signatures", grub_env_read_sec, grub_env_write_sec); + grub_env_export ("check_appended_signatures"); + + rc = grub_asn1_init (); + if (rc != ASN1_SUCCESS) + grub_fatal ("error initing ASN.1 data structures: %d: %s\n", rc, asn1_strerror (rc)); + + /* Extract trusted keys from ELF Note and store them in the db. */ + load_elf2db (); + grub_dprintf ("appendedsig", "the db list now has %u static keys\n", + db.cert_entries); + + grub_verifier_register (&grub_appendedsig_verifier); + grub_dl_set_persistent (mod); +} + +GRUB_MOD_FINI (appendedsig) +{ + /* + * grub_dl_set_persistent should prevent this from actually running, but it + * does still run under emu. + */ + + free_db_list (); + grub_register_variable_hook ("check_appended_signatures", NULL, NULL); + grub_env_unset ("check_appended_signatures"); + grub_verifier_unregister (&grub_appendedsig_verifier); +} diff --git a/include/grub/err.h b/include/grub/err.h index 202fa8a7a..6ab905c93 100644 --- a/include/grub/err.h +++ b/include/grub/err.h @@ -75,7 +75,8 @@ typedef enum GRUB_ERR_BAD_SIGNATURE, GRUB_ERR_BAD_FIRMWARE, GRUB_ERR_STILL_REFERENCED, - GRUB_ERR_RECURSION_DEPTH + GRUB_ERR_RECURSION_DEPTH, + GRUB_ERR_EXISTS } grub_err_t; diff --git a/include/grub/file.h b/include/grub/file.h index a5bf3a792..d678de063 100644 --- a/include/grub/file.h +++ b/include/grub/file.h @@ -80,6 +80,8 @@ enum grub_file_type GRUB_FILE_TYPE_PUBLIC_KEY, /* File holding public key to add to trused keys. */ GRUB_FILE_TYPE_PUBLIC_KEY_TRUST, + /* File holding x509 certificiate to add to trusted keys. */ + GRUB_FILE_TYPE_CERTIFICATE_TRUST, /* File of which we intend to print a blocklist to the user. */ GRUB_FILE_TYPE_PRINT_BLOCKLIST, /* File we intend to use for test loading or testing speed. */ -- 2.50.1 (Apple Git-155) [-- Attachment #2: Type: text/plain, Size: 141 bytes --] _______________________________________________ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel ^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH v13 11/20] powerpc_ieee1275: Read the db and dbx secure boot variables 2025-09-30 11:39 [PATCH v13 00/20] Appended Signature Secure Boot Support for PowerPC Sudhakar Kuppusamy ` (9 preceding siblings ...) 2025-09-30 11:40 ` [PATCH v13 10/20] appended signatures: Support verifying appended signatures Sudhakar Kuppusamy @ 2025-09-30 11:40 ` Sudhakar Kuppusamy 2025-10-01 15:52 ` Daniel Kiper 2025-09-30 11:40 ` [PATCH v13 12/20] appended signatures: Introducing key management environment variable Sudhakar Kuppusamy ` (9 subsequent siblings) 20 siblings, 1 reply; 25+ messages in thread From: Sudhakar Kuppusamy @ 2025-09-30 11:40 UTC (permalink / raw) To: grub-devel Cc: dja, jan.setjeeilers, julian.klode, mate.kukri, pjones, msuchanek, mlewando, stefanb, avnish, nayna, ssrish, Sudhakar Kuppusamy, sridharm Enhancing the infrastructure to enable the Platform Keystore (PKS) feature, which provides access to the SB_VERSION, db, and dbx secure boot variables from PKS. If PKS is enabled, it will read secure boot variables such as db and dbx from PKS and extract EFI Signature List (ESL) from it. The ESLs would be saved in the Platform Keystore buffer, and the appendedsig module would read it later to extract the certificate's details from ESL. In the following scenarios, static key management mode will be activated: 1. When Secure Boot is enabled with static key management mode 2. When SB_VERSION is unavailable but Secure Boot is enabled 3. When PKS support is unavailable but Secure Boot is enabled Note:- SB_VERSION: Key Management Mode 1 - Enable dynamic key management mode. Read the db and dbx variables from PKS, and use them for signature verification. 0 - Enable static key management mode. Read keys from the GRUB ELF Note and use it for signature verification. Signed-off-by: Sudhakar Kuppusamy <sudhakar@linux.ibm.com> --- grub-core/Makefile.am | 2 + grub-core/Makefile.core.def | 2 + grub-core/kern/ieee1275/ieee1275.c | 1 - grub-core/kern/ieee1275/init.c | 4 + grub-core/kern/powerpc/ieee1275/ieee1275.c | 137 +++++++ .../kern/powerpc/ieee1275/platform_keystore.c | 344 ++++++++++++++++++ include/grub/ieee1275/ieee1275.h | 3 + include/grub/powerpc/ieee1275/ieee1275.h | 18 + .../grub/powerpc/ieee1275/platform_keystore.h | 122 +++++++ 9 files changed, 632 insertions(+), 1 deletion(-) create mode 100644 grub-core/kern/powerpc/ieee1275/ieee1275.c create mode 100644 grub-core/kern/powerpc/ieee1275/platform_keystore.c create mode 100644 include/grub/powerpc/ieee1275/platform_keystore.h diff --git a/grub-core/Makefile.am b/grub-core/Makefile.am index e50db8106..8577462d5 100644 --- a/grub-core/Makefile.am +++ b/grub-core/Makefile.am @@ -246,6 +246,8 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/ieee1275/alloc.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/terminfo.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/extcmd.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/lib/arg.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/powerpc/ieee1275/ieee1275.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/powerpc/ieee1275/platform_keystore.h endif if COND_sparc64_ieee1275 diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index 6824a0ee4..853d879a4 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -334,6 +334,8 @@ kernel = { powerpc_ieee1275 = kern/powerpc/dl.c; powerpc_ieee1275 = kern/powerpc/compiler-rt.S; powerpc_ieee1275 = kern/lockdown.c; + powerpc_ieee1275 = kern/powerpc/ieee1275/ieee1275.c; + powerpc_ieee1275 = kern/powerpc/ieee1275/platform_keystore.c; sparc64_ieee1275 = kern/sparc64/cache.S; sparc64_ieee1275 = kern/sparc64/dl.c; diff --git a/grub-core/kern/ieee1275/ieee1275.c b/grub-core/kern/ieee1275/ieee1275.c index 36ca2dbfc..afa37a9f0 100644 --- a/grub-core/kern/ieee1275/ieee1275.c +++ b/grub-core/kern/ieee1275/ieee1275.c @@ -23,7 +23,6 @@ #define IEEE1275_PHANDLE_INVALID ((grub_ieee1275_cell_t) -1) #define IEEE1275_IHANDLE_INVALID ((grub_ieee1275_cell_t) 0) -#define IEEE1275_CELL_INVALID ((grub_ieee1275_cell_t) -1) \f diff --git a/grub-core/kern/ieee1275/init.c b/grub-core/kern/ieee1275/init.c index a81a36f57..c46624f39 100644 --- a/grub-core/kern/ieee1275/init.c +++ b/grub-core/kern/ieee1275/init.c @@ -51,6 +51,8 @@ #endif #if defined(__powerpc__) #include <grub/lockdown.h> +#include <grub/powerpc/ieee1275/ieee1275.h> +#include <grub/powerpc/ieee1275/platform_keystore.h> #endif #ifdef __powerpc__ @@ -1043,6 +1045,8 @@ grub_ieee1275_get_secure_boot (void) } else grub_dprintf ("ieee1275", "Secure Boot Disabled\n"); + + grub_pks_keystore_init (); } #endif /* __powerpc__ */ grub_addr_t grub_modbase; diff --git a/grub-core/kern/powerpc/ieee1275/ieee1275.c b/grub-core/kern/powerpc/ieee1275/ieee1275.c new file mode 100644 index 000000000..38cfe4d8d --- /dev/null +++ b/grub-core/kern/powerpc/ieee1275/ieee1275.c @@ -0,0 +1,137 @@ +/* ieee1275.c - Access the Open Firmware client interface. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2003,2004,2005,2007,2008,2009 Free Software Foundation, Inc. + * Copyright (C) 2020, 2021, 2022, 2023, 2024, 2025 IBM Corporation + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ +#include <grub/ieee1275/ieee1275.h> +#include <grub/powerpc/ieee1275/ieee1275.h> +#include <grub/misc.h> + +grub_int32_t +grub_ieee1275_test (const char *name) +{ + struct test_args + { + struct grub_ieee1275_common_hdr common;/* The header information like interface name, number of inputs and outputs. */ + grub_ieee1275_cell_t name; /* The interface name. */ + grub_ieee1275_cell_t missing; + } args; + + INIT_IEEE1275_COMMON (&args.common, "test", 1, 1); + args.name = (grub_ieee1275_cell_t) name; + + if (IEEE1275_CALL_ENTRY_FN (&args) == -1) + return -1; + + if (args.missing == IEEE1275_CELL_INVALID) + return -1; + + return 0; +} + +grub_int32_t +grub_ieee1275_pks_max_object_size (grub_uint32_t *result) +{ + struct mos_args + { + struct grub_ieee1275_common_hdr common;/* The header information like interface name, number of inputs and outputs. */ + grub_ieee1275_cell_t size; /* The maximum object size for a PKS object. */ + } args; + + INIT_IEEE1275_COMMON (&args.common, "pks-max-object-size", 0, 1); + + if (IEEE1275_CALL_ENTRY_FN (&args) == -1) + return -1; + + if (args.size == IEEE1275_CELL_INVALID) + return -1; + + *result = args.size; + + return 0; +} + +grub_int32_t +grub_ieee1275_pks_read_object (const grub_uint32_t consumer, const char *label, + const grub_uint32_t label_len, const grub_uint32_t buffer_len, + grub_uint8_t *buffer, grub_uint32_t *data_len, + grub_uint32_t *policies) +{ + struct pks_read_args + { + struct grub_ieee1275_common_hdr common; /* The header information like interface name, number of inputs and outputs. */ + grub_ieee1275_cell_t consumer; /* The object belonging to consumer with the label. */ + grub_ieee1275_cell_t label; /* Object label buffer logical real address. */ + grub_ieee1275_cell_t label_len; /* The byte length of the object label. */ + grub_ieee1275_cell_t buffer; /* Output buffer logical real address. */ + grub_ieee1275_cell_t buffer_len; /* Length of the output buffer. */ + grub_ieee1275_cell_t data_len; /* The number of bytes copied to the output buffer. */ + grub_ieee1275_cell_t policies; /* The object policies. */ + grub_int32_t rc; /* The return code. */ + } args; + + INIT_IEEE1275_COMMON (&args.common, "pks-read-object", 5, 3); + args.consumer = consumer; + args.label_len = label_len; + args.buffer_len = buffer_len; + args.label = (grub_ieee1275_cell_t) label; + args.buffer = (grub_ieee1275_cell_t) buffer; + + if (IEEE1275_CALL_ENTRY_FN (&args) == -1) + return -1; + + if (args.data_len == IEEE1275_CELL_INVALID) + return -1; + + *data_len = args.data_len; + *policies = args.policies; + + return args.rc; +} + +grub_int32_t +grub_ieee1275_pks_read_sbvar (const grub_uint32_t sbvar_flags, const grub_uint32_t sbvar_type, + const grub_uint32_t buffer_len, grub_uint8_t *buffer, + grub_size_t *data_len) +{ + struct pks_read_sbvar_args + { + struct grub_ieee1275_common_hdr common; /* The header information like interface name, number of inputs and outputs. */ + grub_ieee1275_cell_t sbvar_flags; /* The sbvar operation flags. */ + grub_ieee1275_cell_t sbvar_type; /* The sbvar being requested. */ + grub_ieee1275_cell_t buffer; /* Output buffer logical real address. */ + grub_ieee1275_cell_t buffer_len; /* Length of the Output buffer. */ + grub_ieee1275_cell_t data_len; /* The number of bytes copied to the output buffer. */ + grub_int32_t rc; /* The return code. */ + } args; + + INIT_IEEE1275_COMMON (&args.common, "pks-read-sbvar", 4, 2); + args.sbvar_flags = sbvar_flags; + args.sbvar_type = sbvar_type; + args.buffer_len = buffer_len; + args.buffer = (grub_ieee1275_cell_t) buffer; + + if (IEEE1275_CALL_ENTRY_FN (&args) == -1) + return -1; + + if (args.data_len == IEEE1275_CELL_INVALID) + return -1; + + *data_len = args.data_len; + + return args.rc; +} diff --git a/grub-core/kern/powerpc/ieee1275/platform_keystore.c b/grub-core/kern/powerpc/ieee1275/platform_keystore.c new file mode 100644 index 000000000..715587cde --- /dev/null +++ b/grub-core/kern/powerpc/ieee1275/platform_keystore.c @@ -0,0 +1,344 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2024 Free Software Foundation, Inc. + * Copyright (C) 2022, 2023, 2024, 2025 IBM Corporation + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <grub/mm.h> +#include <grub/types.h> +#include <grub/misc.h> +#include <grub/lockdown.h> +#include <grub/ieee1275/ieee1275.h> +#include <grub/powerpc/ieee1275/ieee1275.h> +#include <grub/powerpc/ieee1275/platform_keystore.h> + +/* PKS consumer type for firmware. */ +#define PKS_CONSUMER_FW ((grub_uint32_t) 1) + +/* The maximum object size interface name for a PKS object. */ +#define PKS_MAX_OBJ_SIZE "pks-max-object-size" + +/* PKS read object label for secure boot version. */ +#define SB_VERSION_KEY_NAME "SB_VERSION" +#define SB_VERSION_KEY_LEN (sizeof (SB_VERSION_KEY_NAME) - 1) + +/* PKS read secure boot variable request type for db and dbx. */ +#define PKS_SBVAR_DB ((grub_uint32_t) 1) +#define PKS_SBVAR_DBX ((grub_uint32_t) 2) + +static grub_uint32_t pks_max_object_size = 0; + +/* Platform KeyStore db and dbx. */ +static grub_pks_t pks_keystore = { .db = NULL, .dbx = NULL, .db_entries = 0, + .dbx_entries = 0}; +/* + * pks_use_keystore: Key Management Modes + * False: Static key management (use built-in Keys). This is default. + * True: Dynamic key management (use Platform KeySotre). + */ +static bool pks_use_keystore = false; + +/* + * Reads the Globally Unique Identifier (GUID), EFI Signature Database (ESD), + * and its size from the Platform KeyStore EFI Signature List (ESL), then + * stores them into the PKS Signature Database (SD) (i.e., pks_sd buffer + * and pks_sd entries) in the GRUB. + */ +static grub_err_t +_esl_to_esd (const grub_uint8_t *esl_data, grub_size_t esl_size, + const grub_size_t signature_size, const grub_packed_guid_t *guid, + grub_pks_sd_t **pks_sd, grub_uint32_t *pks_sd_entries) +{ + grub_esd_t *esd; + grub_pks_sd_t *signature = *pks_sd; + grub_uint32_t entries = *pks_sd_entries; + grub_size_t data_size, offset = 0; + + /* Reads the ESD from ESL. */ + while (esl_size > 0) + { + esd = (grub_esd_t *) (esl_data + offset); + data_size = signature_size - sizeof (grub_esd_t); + + signature = grub_realloc (signature, (entries + 1) * sizeof (grub_pks_sd_t)); + if (signature == NULL) + return grub_error (GRUB_ERR_OUT_OF_MEMORY, "out of memory"); + + signature[entries].data = grub_malloc (data_size * sizeof (grub_uint8_t)); + if (signature[entries].data == NULL) + { + /* Allocated memory will be freed by grub_pks_free_data(). */ + *pks_sd = signature; + *pks_sd_entries = entries + 1; + return grub_error (GRUB_ERR_OUT_OF_MEMORY, "out of memory"); + } + + grub_memcpy (signature[entries].data, esd->signature_data, data_size); + signature[entries].data_size = data_size; + signature[entries].guid = *guid; + entries++; + esl_size -= signature_size; + offset += signature_size; + } + + *pks_sd = signature; + *pks_sd_entries = entries; + + return GRUB_ERR_NONE; +} + +/* Extract the ESD after removing the ESL header from ESL. */ +static grub_err_t +esl_to_esd (const grub_uint8_t *esl_data, grub_size_t *next_esl, + grub_pks_sd_t **pks_sd, grub_uint32_t *pks_sd_entries) +{ + grub_packed_guid_t guid; + grub_esl_t *esl; + grub_size_t offset, esl_size, signature_size, signature_header_size; + + /* Convert the ESL data into the ESL. */ + esl = (grub_esl_t *) esl_data; + if (*next_esl < sizeof (grub_esl_t) || esl == NULL) + return grub_error (GRUB_ERR_BUG, "invalid ESL"); + + esl_size = grub_le_to_cpu32 (esl->signature_list_size); + signature_header_size = grub_le_to_cpu32 (esl->signature_header_size); + signature_size = grub_le_to_cpu32 (esl->signature_size); + grub_memcpy (&guid, &esl->signature_type, sizeof (grub_packed_guid_t)); + + if (esl_size < sizeof (grub_esl_t) || esl_size > *next_esl) + return grub_error (GRUB_ERR_BUG, "invalid ESL size (%u)\n", esl_size); + + *next_esl = esl_size; + offset = sizeof (grub_esl_t) + signature_header_size; + esl_size = esl_size - offset; + + return _esl_to_esd (esl_data + offset, esl_size, signature_size, &guid, + pks_sd, pks_sd_entries); +} + +/* + * Import the EFI Signature Database (ESD) and the number of ESD from the ESL + * into the pks_sd buffer and pks_sd entries. + */ +static grub_err_t +pks_sd_from_esl (const grub_uint8_t *esl_data, grub_size_t esl_size, + grub_pks_sd_t **pks_sd, grub_uint32_t *pks_sd_entries) +{ + grub_err_t rc; + grub_size_t next_esl = esl_size; + + do + { + rc = esl_to_esd (esl_data, &next_esl, pks_sd, pks_sd_entries); + if (rc != GRUB_ERR_NONE) + break; + + esl_data += next_esl; + esl_size -= next_esl; + next_esl = esl_size; + } + while (esl_size > 0); + + return rc; +} + +/* Read the secure boot version from PKS as an object. Caller must free result. */ +static grub_err_t +read_sbversion_from_pks (grub_uint8_t **out) +{ + grub_int32_t rc; + grub_uint32_t outlen = 0, policy = 0; + + *out = grub_malloc (pks_max_object_size); + if (*out == NULL) + return grub_error (GRUB_ERR_OUT_OF_MEMORY, "out of memory"); + + rc = grub_ieee1275_pks_read_object (PKS_CONSUMER_FW, SB_VERSION_KEY_NAME, + SB_VERSION_KEY_LEN, pks_max_object_size, *out, + &outlen, &policy); + if (rc < 0) + { + grub_free (*out); + return grub_error (GRUB_ERR_READ_ERROR, "SB version read failed (%d)\n", rc); + } + + if (outlen != 1 || (**out >= 2)) + { + grub_free (*out); + return grub_error (GRUB_ERR_BAD_NUMBER, "found unexpected SB version: %u\n", **out); + } + + return GRUB_ERR_NONE; +} + +/* + * Reads the secure boot variable from PKS, unpacks it, read the ESD from ESL, + * and store the information in the pks_sd buffer. + */ +static grub_err_t +read_sbvar_from_pks (const grub_uint32_t sbvarflags, const grub_uint32_t sbvartype, + grub_pks_sd_t **pks_sd, grub_uint32_t *pks_sd_entries) +{ + grub_int32_t rc; + grub_err_t err = GRUB_ERR_NONE; + grub_uint8_t *esl_data = NULL; + grub_size_t esl_data_size = 0; + + esl_data = grub_malloc (pks_max_object_size); + if (esl_data == NULL) + return grub_error (GRUB_ERR_OUT_OF_MEMORY, "out of memory"); + + rc = grub_ieee1275_pks_read_sbvar (sbvarflags, sbvartype, pks_max_object_size, + esl_data, &esl_data_size); + if (rc == IEEE1275_CELL_NOT_FOUND) + { + err = grub_error (GRUB_ERR_FILE_NOT_FOUND, "secure boot variable %s not found (%d)", + (sbvartype == PKS_SBVAR_DB) ? "db" : "dbx", rc); + goto fail; + } + else if (rc < 0) + { + err = grub_error (GRUB_ERR_READ_ERROR, "secure boot variable %s reading (%d)", + (sbvartype == PKS_SBVAR_DB) ? "db" : "dbx", rc); + goto fail; + } + + if (esl_data_size > 0) + err = pks_sd_from_esl (esl_data, esl_data_size, pks_sd, pks_sd_entries); + else + err = GRUB_ERR_BAD_NUMBER; + + fail: + grub_free (esl_data); + + return err; +} + +/* + * Test the availability of PKS support. If PKS support is avaialble and objects + * present, it reads the secure boot version (SB_VERSION) from PKS. + * + * SB_VERSION: Key Management Mode + * 1 - Enable dynamic key management mode. Read the db and dbx variables from PKS, + * and use them for signature verification. + * 0 - Enable static key management mode. Read keys from the GRUB ELF Note and use + * it for signature verification. + */ +static bool +is_pks_present (void) +{ + grub_err_t err; + grub_int32_t rc; + grub_uint8_t *data = NULL; + bool ret = false; + + rc = grub_ieee1275_test (PKS_MAX_OBJ_SIZE); + if (rc < 0) + { + grub_error (GRUB_ERR_BAD_FIRMWARE, "firmware doesn't have PKS support\n"); + return ret; + } + else + { + rc = grub_ieee1275_pks_max_object_size (&pks_max_object_size); + if (rc < 0) + { + grub_error (GRUB_ERR_BAD_NUMBER, "PKS support is there but it has zero objects\n"); + return ret; + } + } + + err = read_sbversion_from_pks (&data); + if (err != GRUB_ERR_NONE) + return ret; + + /* + * If *data == 1, use dynamic key management and read the keys from the PKS. + * Else, use static key management and read the keys from the GRUB ELF Note. + */ + ret = ((*data == 1) ? true : false); + + grub_free (data); + + return ret; +} + +/* Free allocated memory. */ +void +grub_pks_free_data (void) +{ + grub_size_t i; + + for (i = 0; i < pks_keystore.db_entries; i++) + grub_free (pks_keystore.db[i].data); + + for (i = 0; i < pks_keystore.dbx_entries; i++) + grub_free (pks_keystore.dbx[i].data); + + grub_free (pks_keystore.db); + grub_free (pks_keystore.dbx); + grub_memset (&pks_keystore, 0, sizeof (grub_pks_t)); +} + +grub_pks_t * +grub_pks_get_keystore (void) +{ + return (pks_use_keystore == true) ? &pks_keystore : NULL; +} + +/* Initialization of the Platform KeyStore. */ +void +grub_pks_keystore_init (void) +{ + grub_err_t rc_dbx; + + grub_dprintf ("ieee1275", "trying to load Platform KeyStore\n"); + + if (is_pks_present () == false) + { + grub_dprintf ("ieee1275", "Platform PKS is not available\n"); + return; + } + + /* + * When Read db from PKS, there are three scenarios + * 1. db fully loaded from PKS + * 2. db partially loaded from PKS + * 3. no keys are loaded from db (read error or empty db state), default to + * built-in keys (static keys) + * each of these scenarios, the db keys are checked against dbx. + */ + read_sbvar_from_pks (0, PKS_SBVAR_DB, &pks_keystore.db, &pks_keystore.db_entries); + + /* + * Read dbx from PKS. If dbx is not completely loaded from PKS, then this + * could lead to the loading of vulnerable GRUB modules and kernel binaries. + * So, this should be prevented by freeing up loaded dbx and db. + */ + rc_dbx = read_sbvar_from_pks (0, PKS_SBVAR_DBX, &pks_keystore.dbx, &pks_keystore.dbx_entries); + if (rc_dbx == GRUB_ERR_FILE_NOT_FOUND || rc_dbx == GRUB_ERR_BAD_NUMBER) + rc_dbx = GRUB_ERR_NONE; + + if (rc_dbx != GRUB_ERR_NONE) + grub_pks_free_data (); + + /* + * At this point, it's evident that PKS infrastructure exists, so the PKS + * keystore must be used for validating appended signatures. + */ + pks_use_keystore = true; +} diff --git a/include/grub/ieee1275/ieee1275.h b/include/grub/ieee1275/ieee1275.h index c445d0499..157ed57be 100644 --- a/include/grub/ieee1275/ieee1275.h +++ b/include/grub/ieee1275/ieee1275.h @@ -24,6 +24,9 @@ #include <grub/types.h> #include <grub/machine/ieee1275.h> +#define IEEE1275_CELL_INVALID ((grub_ieee1275_cell_t) -1) +#define IEEE1275_CELL_NOT_FOUND ((grub_int32_t) -7) + #define GRUB_IEEE1275_CELL_FALSE ((grub_ieee1275_cell_t) 0) #define GRUB_IEEE1275_CELL_TRUE ((grub_ieee1275_cell_t) -1) diff --git a/include/grub/powerpc/ieee1275/ieee1275.h b/include/grub/powerpc/ieee1275/ieee1275.h index 4eb207018..756896ab7 100644 --- a/include/grub/powerpc/ieee1275/ieee1275.h +++ b/include/grub/powerpc/ieee1275/ieee1275.h @@ -28,4 +28,22 @@ typedef grub_uint32_t grub_ieee1275_cell_t; #define PRIxGRUB_IEEE1275_CELL_T PRIxGRUB_UINT32_T #define PRIuGRUB_IEEE1275_CELL_T PRIuGRUB_UINT32_T +#ifdef __powerpc__ +extern grub_int32_t +grub_ieee1275_test (const char *name); + +extern grub_int32_t +grub_ieee1275_pks_max_object_size (grub_uint32_t *result); + +extern grub_int32_t +grub_ieee1275_pks_read_object (const grub_uint32_t consumer, const char *label, + const grub_uint32_t label_len, const grub_uint32_t buffer_len, + grub_uint8_t *buffer, grub_uint32_t *data_len, + grub_uint32_t *policies); + +extern grub_int32_t +grub_ieee1275_pks_read_sbvar (const grub_uint32_t sbvar_flags, const grub_uint32_t sbvar_type, + const grub_uint32_t buffer_len, grub_uint8_t *buffer, + grub_size_t *data_len); +#endif /* __powerpc__ */ #endif /* ! GRUB_IEEE1275_MACHINE_HEADER */ diff --git a/include/grub/powerpc/ieee1275/platform_keystore.h b/include/grub/powerpc/ieee1275/platform_keystore.h new file mode 100644 index 000000000..2e6c0ab2f --- /dev/null +++ b/include/grub/powerpc/ieee1275/platform_keystore.h @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved. This + * program and the accompanying materials are licensed and made available + * under the terms and conditions of the 2-Clause BSD License which + * accompanies this distribution. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * https://github.com/tianocore/edk2-staging (edk2-staging repo of tianocore), + * the ImageAuthentication.h file under it, and here's the copyright and license. + * + * MdePkg/Include/Guid/ImageAuthentication.h + * + * Copyright 2022, 2023, 2024, 2025 IBM Corp. + */ + +#ifndef PLATFORM_KEYSTORE_HEADER +#define PLATFORM_KEYSTORE_HEADER 1 + +#include <grub/symbol.h> +#include <grub/mm.h> +#include <grub/types.h> + +/* + * It is derived from EFI_SIGNATURE_DATA + * https://github.com/tianocore/edk2-staging/blob/master/MdePkg/Include/Guid/ImageAuthentication.h + * + * The structure of an EFI Signature Database (ESD). */ +struct grub_esd +{ + /* + * An identifier which identifies the agent which added the signature to + * the list. + */ + grub_packed_guid_t signature_owner; + /* The format of the signature is defined by the SignatureType. */ + grub_uint8_t signature_data[]; +} GRUB_PACKED; +typedef struct grub_esd grub_esd_t; + +/* + * It is derived from EFI_SIGNATURE_LIST + * https://github.com/tianocore/edk2-staging/blob/master/MdePkg/Include/Guid/ImageAuthentication.h + * + * The structure of an EFI Signature List (ESL). */ +struct grub_esl +{ + /* Type of the signature. GUID signature types are defined in below. */ + grub_packed_guid_t signature_type; + /* Total size of the signature list, including this header. */ + grub_uint32_t signature_list_size; + /* Size of the signature header which precedes the array of signatures. */ + grub_uint32_t signature_header_size; + /* Size of each signature.*/ + grub_uint32_t signature_size; +} GRUB_PACKED; +typedef struct grub_esl grub_esl_t; + +/* The structure of a PKS Signature Database (SD). */ +struct grub_pks_sd +{ + grub_packed_guid_t guid; /* Signature type. */ + grub_uint8_t *data; /* Signature data. */ + grub_size_t data_size; /* Size of signature data. */ +} GRUB_PACKED; +typedef struct grub_pks_sd grub_pks_sd_t; + +/* The structure of a Platform KeyStore (PKS). */ +struct grub_pks +{ + grub_pks_sd_t *db; /* Signature database. */ + grub_pks_sd_t *dbx; /* Forbidden signature database. */ + grub_uint32_t db_entries; /* Size of signature database. */ + grub_uint32_t dbx_entries;/* Size of forbidden signature database. */ +}; +typedef struct grub_pks grub_pks_t; + +#if defined(__powerpc__) +/* Initialization of the Platform Keystore. */ +extern void +grub_pks_keystore_init (void); + +/* Platform KeyStore db and dbx. */ +extern grub_pks_t * +EXPORT_FUNC (grub_pks_get_keystore) (void); + +/* Free allocated memory. */ +extern void +EXPORT_FUNC (grub_pks_free_data) (void); +#else +static inline grub_pks_t * +grub_pks_get_keystore (void) +{ + return NULL; +} + +static inline void +grub_pks_free_data (void) +{ +} +#endif /* __powerpc__ */ +#endif -- 2.50.1 (Apple Git-155) _______________________________________________ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel ^ permalink raw reply related [flat|nested] 25+ messages in thread
* Re: [PATCH v13 11/20] powerpc_ieee1275: Read the db and dbx secure boot variables 2025-09-30 11:40 ` [PATCH v13 11/20] powerpc_ieee1275: Read the db and dbx secure boot variables Sudhakar Kuppusamy @ 2025-10-01 15:52 ` Daniel Kiper 0 siblings, 0 replies; 25+ messages in thread From: Daniel Kiper @ 2025-10-01 15:52 UTC (permalink / raw) To: Sudhakar Kuppusamy Cc: grub-devel, dja, jan.setjeeilers, julian.klode, mate.kukri, pjones, msuchanek, mlewando, stefanb, avnish, nayna, ssrish, sridharm On Tue, Sep 30, 2025 at 05:10:05PM +0530, Sudhakar Kuppusamy wrote: > Enhancing the infrastructure to enable the Platform Keystore (PKS) feature, > which provides access to the SB_VERSION, db, and dbx secure boot variables > from PKS. > > If PKS is enabled, it will read secure boot variables such as db and dbx > from PKS and extract EFI Signature List (ESL) from it. The ESLs would be > saved in the Platform Keystore buffer, and the appendedsig module would > read it later to extract the certificate's details from ESL. > > In the following scenarios, static key management mode will be activated: > 1. When Secure Boot is enabled with static key management mode > 2. When SB_VERSION is unavailable but Secure Boot is enabled > 3. When PKS support is unavailable but Secure Boot is enabled > > Note:- > > SB_VERSION: Key Management Mode > 1 - Enable dynamic key management mode. Read the db and dbx variables from PKS, > and use them for signature verification. > 0 - Enable static key management mode. Read keys from the GRUB ELF Note and > use it for signature verification. > > Signed-off-by: Sudhakar Kuppusamy <sudhakar@linux.ibm.com> > --- > grub-core/Makefile.am | 2 + > grub-core/Makefile.core.def | 2 + > grub-core/kern/ieee1275/ieee1275.c | 1 - > grub-core/kern/ieee1275/init.c | 4 + > grub-core/kern/powerpc/ieee1275/ieee1275.c | 137 +++++++ > .../kern/powerpc/ieee1275/platform_keystore.c | 344 ++++++++++++++++++ > include/grub/ieee1275/ieee1275.h | 3 + > include/grub/powerpc/ieee1275/ieee1275.h | 18 + > .../grub/powerpc/ieee1275/platform_keystore.h | 122 +++++++ > 9 files changed, 632 insertions(+), 1 deletion(-) > create mode 100644 grub-core/kern/powerpc/ieee1275/ieee1275.c > create mode 100644 grub-core/kern/powerpc/ieee1275/platform_keystore.c > create mode 100644 include/grub/powerpc/ieee1275/platform_keystore.h > > diff --git a/grub-core/Makefile.am b/grub-core/Makefile.am > index e50db8106..8577462d5 100644 > --- a/grub-core/Makefile.am > +++ b/grub-core/Makefile.am > @@ -246,6 +246,8 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/ieee1275/alloc.h > KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/terminfo.h > KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/extcmd.h > KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/lib/arg.h > +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/powerpc/ieee1275/ieee1275.h > +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/powerpc/ieee1275/platform_keystore.h > endif > > if COND_sparc64_ieee1275 > diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def > index 6824a0ee4..853d879a4 100644 > --- a/grub-core/Makefile.core.def > +++ b/grub-core/Makefile.core.def > @@ -334,6 +334,8 @@ kernel = { > powerpc_ieee1275 = kern/powerpc/dl.c; > powerpc_ieee1275 = kern/powerpc/compiler-rt.S; > powerpc_ieee1275 = kern/lockdown.c; > + powerpc_ieee1275 = kern/powerpc/ieee1275/ieee1275.c; > + powerpc_ieee1275 = kern/powerpc/ieee1275/platform_keystore.c; > > sparc64_ieee1275 = kern/sparc64/cache.S; > sparc64_ieee1275 = kern/sparc64/dl.c; > diff --git a/grub-core/kern/ieee1275/ieee1275.c b/grub-core/kern/ieee1275/ieee1275.c > index 36ca2dbfc..afa37a9f0 100644 > --- a/grub-core/kern/ieee1275/ieee1275.c > +++ b/grub-core/kern/ieee1275/ieee1275.c > @@ -23,7 +23,6 @@ > > #define IEEE1275_PHANDLE_INVALID ((grub_ieee1275_cell_t) -1) > #define IEEE1275_IHANDLE_INVALID ((grub_ieee1275_cell_t) 0) > -#define IEEE1275_CELL_INVALID ((grub_ieee1275_cell_t) -1) > > \f > > diff --git a/grub-core/kern/ieee1275/init.c b/grub-core/kern/ieee1275/init.c > index a81a36f57..c46624f39 100644 > --- a/grub-core/kern/ieee1275/init.c > +++ b/grub-core/kern/ieee1275/init.c > @@ -51,6 +51,8 @@ > #endif > #if defined(__powerpc__) > #include <grub/lockdown.h> > +#include <grub/powerpc/ieee1275/ieee1275.h> > +#include <grub/powerpc/ieee1275/platform_keystore.h> > #endif > > #ifdef __powerpc__ > @@ -1043,6 +1045,8 @@ grub_ieee1275_get_secure_boot (void) > } > else > grub_dprintf ("ieee1275", "Secure Boot Disabled\n"); > + > + grub_pks_keystore_init (); > } > #endif /* __powerpc__ */ > grub_addr_t grub_modbase; > diff --git a/grub-core/kern/powerpc/ieee1275/ieee1275.c b/grub-core/kern/powerpc/ieee1275/ieee1275.c > new file mode 100644 > index 000000000..38cfe4d8d > --- /dev/null > +++ b/grub-core/kern/powerpc/ieee1275/ieee1275.c > @@ -0,0 +1,137 @@ > +/* ieee1275.c - Access the Open Firmware client interface. */ > +/* > + * GRUB -- GRand Unified Bootloader > + * Copyright (C) 2003,2004,2005,2007,2008,2009 Free Software Foundation, Inc. > + * Copyright (C) 2020, 2021, 2022, 2023, 2024, 2025 IBM Corporation > + * > + * GRUB is free software: you can redistribute it and/or modify > + * it under the terms of the GNU General Public License as published by > + * the Free Software Foundation, either version 3 of the License, or > + * (at your option) any later version. > + * > + * GRUB is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + * > + * You should have received a copy of the GNU General Public License > + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. > + */ > +#include <grub/ieee1275/ieee1275.h> > +#include <grub/powerpc/ieee1275/ieee1275.h> > +#include <grub/misc.h> > + > +grub_int32_t > +grub_ieee1275_test (const char *name) > +{ > + struct test_args > + { > + struct grub_ieee1275_common_hdr common;/* The header information like interface name, number of inputs and outputs. */ > + grub_ieee1275_cell_t name; /* The interface name. */ > + grub_ieee1275_cell_t missing; > + } args; > + > + INIT_IEEE1275_COMMON (&args.common, "test", 1, 1); > + args.name = (grub_ieee1275_cell_t) name; > + > + if (IEEE1275_CALL_ENTRY_FN (&args) == -1) > + return -1; > + > + if (args.missing == IEEE1275_CELL_INVALID) > + return -1; > + > + return 0; > +} > + > +grub_int32_t > +grub_ieee1275_pks_max_object_size (grub_uint32_t *result) > +{ > + struct mos_args > + { > + struct grub_ieee1275_common_hdr common;/* The header information like interface name, number of inputs and outputs. */ > + grub_ieee1275_cell_t size; /* The maximum object size for a PKS object. */ > + } args; > + > + INIT_IEEE1275_COMMON (&args.common, "pks-max-object-size", 0, 1); > + > + if (IEEE1275_CALL_ENTRY_FN (&args) == -1) > + return -1; > + > + if (args.size == IEEE1275_CELL_INVALID) > + return -1; > + > + *result = args.size; I can imagine the buggy firmware may return 0 here and later you will call grub_malloc() with this value. And grub_malloc() may not return NULL in such case... So, I think it would be good if you identify a minimal value which should be returned by this function. Smaller values should be treated as an error and the function should return -1. > + return 0; > +} > + > +grub_int32_t > +grub_ieee1275_pks_read_object (const grub_uint32_t consumer, const char *label, > + const grub_uint32_t label_len, const grub_uint32_t buffer_len, > + grub_uint8_t *buffer, grub_uint32_t *data_len, > + grub_uint32_t *policies) > +{ > + struct pks_read_args > + { > + struct grub_ieee1275_common_hdr common; /* The header information like interface name, number of inputs and outputs. */ > + grub_ieee1275_cell_t consumer; /* The object belonging to consumer with the label. */ > + grub_ieee1275_cell_t label; /* Object label buffer logical real address. */ > + grub_ieee1275_cell_t label_len; /* The byte length of the object label. */ > + grub_ieee1275_cell_t buffer; /* Output buffer logical real address. */ > + grub_ieee1275_cell_t buffer_len; /* Length of the output buffer. */ > + grub_ieee1275_cell_t data_len; /* The number of bytes copied to the output buffer. */ > + grub_ieee1275_cell_t policies; /* The object policies. */ > + grub_int32_t rc; /* The return code. */ > + } args; > + > + INIT_IEEE1275_COMMON (&args.common, "pks-read-object", 5, 3); > + args.consumer = consumer; > + args.label_len = label_len; > + args.buffer_len = buffer_len; > + args.label = (grub_ieee1275_cell_t) label; > + args.buffer = (grub_ieee1275_cell_t) buffer; > + > + if (IEEE1275_CALL_ENTRY_FN (&args) == -1) > + return -1; > + > + if (args.data_len == IEEE1275_CELL_INVALID) > + return -1; > + > + *data_len = args.data_len; > + *policies = args.policies; > + > + return args.rc; > +} > + > +grub_int32_t > +grub_ieee1275_pks_read_sbvar (const grub_uint32_t sbvar_flags, const grub_uint32_t sbvar_type, > + const grub_uint32_t buffer_len, grub_uint8_t *buffer, > + grub_size_t *data_len) > +{ > + struct pks_read_sbvar_args > + { > + struct grub_ieee1275_common_hdr common; /* The header information like interface name, number of inputs and outputs. */ > + grub_ieee1275_cell_t sbvar_flags; /* The sbvar operation flags. */ > + grub_ieee1275_cell_t sbvar_type; /* The sbvar being requested. */ > + grub_ieee1275_cell_t buffer; /* Output buffer logical real address. */ > + grub_ieee1275_cell_t buffer_len; /* Length of the Output buffer. */ > + grub_ieee1275_cell_t data_len; /* The number of bytes copied to the output buffer. */ > + grub_int32_t rc; /* The return code. */ > + } args; > + > + INIT_IEEE1275_COMMON (&args.common, "pks-read-sbvar", 4, 2); > + args.sbvar_flags = sbvar_flags; > + args.sbvar_type = sbvar_type; > + args.buffer_len = buffer_len; > + args.buffer = (grub_ieee1275_cell_t) buffer; > + > + if (IEEE1275_CALL_ENTRY_FN (&args) == -1) > + return -1; > + > + if (args.data_len == IEEE1275_CELL_INVALID) > + return -1; > + > + *data_len = args.data_len; > + > + return args.rc; > +} > diff --git a/grub-core/kern/powerpc/ieee1275/platform_keystore.c b/grub-core/kern/powerpc/ieee1275/platform_keystore.c > new file mode 100644 > index 000000000..715587cde > --- /dev/null > +++ b/grub-core/kern/powerpc/ieee1275/platform_keystore.c > @@ -0,0 +1,344 @@ > +/* > + * GRUB -- GRand Unified Bootloader > + * Copyright (C) 2024 Free Software Foundation, Inc. > + * Copyright (C) 2022, 2023, 2024, 2025 IBM Corporation > + * > + * GRUB is free software: you can redistribute it and/or modify > + * it under the terms of the GNU General Public License as published by > + * the Free Software Foundation, either version 3 of the License, or > + * (at your option) any later version. > + * > + * GRUB is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + * > + * You should have received a copy of the GNU General Public License > + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. > + */ > + > +#include <grub/mm.h> > +#include <grub/types.h> > +#include <grub/misc.h> > +#include <grub/lockdown.h> > +#include <grub/ieee1275/ieee1275.h> > +#include <grub/powerpc/ieee1275/ieee1275.h> > +#include <grub/powerpc/ieee1275/platform_keystore.h> > + > +/* PKS consumer type for firmware. */ > +#define PKS_CONSUMER_FW ((grub_uint32_t) 1) > + > +/* The maximum object size interface name for a PKS object. */ > +#define PKS_MAX_OBJ_SIZE "pks-max-object-size" You define a constant here and you use it partially in this patch. I think at least some of these constants above and below should be moved to a header which declares functions using them. > +/* PKS read object label for secure boot version. */ > +#define SB_VERSION_KEY_NAME "SB_VERSION" > +#define SB_VERSION_KEY_LEN (sizeof (SB_VERSION_KEY_NAME) - 1) > + > +/* PKS read secure boot variable request type for db and dbx. */ > +#define PKS_SBVAR_DB ((grub_uint32_t) 1) > +#define PKS_SBVAR_DBX ((grub_uint32_t) 2) When you fix these two issues you can add my RB to this patch. Additionally, as I can see many RBs left as is in many patches regardless of significant amount of changes to them. So, I need confirmation from all folks which gave RBs earlier before I will push the patches as such... Daniel _______________________________________________ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel ^ permalink raw reply [flat|nested] 25+ messages in thread
* [PATCH v13 12/20] appended signatures: Introducing key management environment variable 2025-09-30 11:39 [PATCH v13 00/20] Appended Signature Secure Boot Support for PowerPC Sudhakar Kuppusamy ` (10 preceding siblings ...) 2025-09-30 11:40 ` [PATCH v13 11/20] powerpc_ieee1275: Read the db and dbx secure boot variables Sudhakar Kuppusamy @ 2025-09-30 11:40 ` Sudhakar Kuppusamy 2025-09-30 11:40 ` [PATCH v13 13/20] appended signatures: Create db and dbx lists Sudhakar Kuppusamy ` (8 subsequent siblings) 20 siblings, 0 replies; 25+ messages in thread From: Sudhakar Kuppusamy @ 2025-09-30 11:40 UTC (permalink / raw) To: grub-devel Cc: dja, jan.setjeeilers, julian.klode, mate.kukri, pjones, msuchanek, mlewando, stefanb, avnish, nayna, ssrish, Sudhakar Kuppusamy, sridharm, Daniel Kiper [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #1: Type: text/plain; charset=y, Size: 5205 bytes --] Introducing the appended signature key management environment variable. It is automatically set to either "static" or "dynamic" based on the Platform KeyStore. "static": Enforce static key management signature verification. This is the default. When the GRUB is locked down, user cannot change the value by setting the appendedsig_key_mgmt variable back to "dynamic". "dynamic": Enforce dynamic key management signature verification. When the GRUB is locked down, user cannot change the value by setting the appendedsig_key_mgmt variable back to "static". Signed-off-by: Sudhakar Kuppusamy <sudhakar@linux.ibm.com> Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com> --- grub-core/commands/appendedsig/appendedsig.c | 75 ++++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/grub-core/commands/appendedsig/appendedsig.c b/grub-core/commands/appendedsig/appendedsig.c index e53efd2da..ca54c90fa 100644 --- a/grub-core/commands/appendedsig/appendedsig.c +++ b/grub-core/commands/appendedsig/appendedsig.c @@ -33,6 +33,7 @@ #include <libtasn1.h> #include <grub/env.h> #include <grub/lockdown.h> +#include <grub/powerpc/ieee1275/platform_keystore.h> #include "appendedsig.h" @@ -94,6 +95,16 @@ static sb_database_t db = {.certs = NULL, .cert_entries = 0}; */ static bool check_sigs = false; +/* + * append_key_mgmt: Key Management Modes + * False: Static key management (use built-in Keys). This is default. + * True: Dynamic key management (use Platform KeySotre). + */ +static bool append_key_mgmt = false; + +/* Platform KeyStore db and dbx. */ +static grub_pks_t *pks_keystore; + static grub_ssize_t pseudo_read (struct grub_file *file, char *buf, grub_size_t len) { @@ -469,6 +480,46 @@ grub_env_write_sec (struct grub_env_var *var __attribute__ ((unused)), const cha return ret; } +static const char * +grub_env_read_key_mgmt (struct grub_env_var *var __attribute__ ((unused)), + const char *val __attribute__ ((unused))) +{ + if (append_key_mgmt == true) + return "dynamic"; + + return "static"; +} + +static char * +grub_env_write_key_mgmt (struct grub_env_var *var __attribute__ ((unused)), const char *val) +{ + char *ret; + + /* + * Do not allow the value to be changed if signature verification is enabled + * (check_sigs is set to true) and GRUB is locked down. + */ + if (check_sigs == true && grub_is_lockdown () == GRUB_LOCKDOWN_ENABLED) + { + ret = grub_strdup (grub_env_read_key_mgmt (NULL, NULL)); + if (ret == NULL) + grub_error (GRUB_ERR_OUT_OF_MEMORY, "out of memory"); + + return ret; + } + + if (grub_strcmp (val, "dynamic") == 0) + append_key_mgmt = true; + else if (grub_strcmp (val, "static") == 0) + append_key_mgmt = false; + + ret = grub_strdup (grub_env_read_key_mgmt (NULL, NULL)); + if (ret == NULL) + grub_error (GRUB_ERR_OUT_OF_MEMORY, "out of memory"); + + return ret; +} + static grub_err_t appendedsig_init (grub_file_t io __attribute__ ((unused)), enum grub_file_type type, void **context __attribute__ ((unused)), enum grub_verify_flags *flags) @@ -540,6 +591,11 @@ GRUB_MOD_INIT (appendedsig) if (grub_is_lockdown () == GRUB_LOCKDOWN_ENABLED) check_sigs = true; + /* If PKS keystore is available, use dynamic key management. */ + pks_keystore = grub_pks_get_keystore (); + if (pks_keystore != NULL) + append_key_mgmt = true; + /* * This is appended signature verification environment variable. It is * automatically set to either "no" or "yes" based on the ’ibm,secure-boot’ @@ -554,6 +610,23 @@ GRUB_MOD_INIT (appendedsig) grub_register_variable_hook ("check_appended_signatures", grub_env_read_sec, grub_env_write_sec); grub_env_export ("check_appended_signatures"); + /* + * This is appended signature key management environment variable. It is + * automatically set to either "static" or "dynamic" based on the + * Platform KeyStore. + * + * "static": Enforce static key management signature verification. This is + * the default. When the GRUB is locked down, user cannot change + * the value by setting the appendedsig_key_mgmt variable back to + * "dynamic". + * + * "dynamic": Enforce dynamic key management signature verification. When the + * GRUB is locked down, user cannot change the value by setting the + * appendedsig_key_mgmt variable back to "static". + */ + grub_register_variable_hook ("appendedsig_key_mgmt", grub_env_read_key_mgmt, grub_env_write_key_mgmt); + grub_env_export ("appendedsig_key_mgmt"); + rc = grub_asn1_init (); if (rc != ASN1_SUCCESS) grub_fatal ("error initing ASN.1 data structures: %d: %s\n", rc, asn1_strerror (rc)); @@ -577,5 +650,7 @@ GRUB_MOD_FINI (appendedsig) free_db_list (); grub_register_variable_hook ("check_appended_signatures", NULL, NULL); grub_env_unset ("check_appended_signatures"); + grub_register_variable_hook ("appendedsig_key_mgmt", NULL, NULL); + grub_env_unset ("appendedsig_key_mgmt"); grub_verifier_unregister (&grub_appendedsig_verifier); } -- 2.50.1 (Apple Git-155) [-- Attachment #2: Type: text/plain, Size: 141 bytes --] _______________________________________________ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel ^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH v13 13/20] appended signatures: Create db and dbx lists 2025-09-30 11:39 [PATCH v13 00/20] Appended Signature Secure Boot Support for PowerPC Sudhakar Kuppusamy ` (11 preceding siblings ...) 2025-09-30 11:40 ` [PATCH v13 12/20] appended signatures: Introducing key management environment variable Sudhakar Kuppusamy @ 2025-09-30 11:40 ` Sudhakar Kuppusamy 2025-09-30 11:40 ` [PATCH v13 14/20] appended signatures: Using db and dbx lists for signature verification Sudhakar Kuppusamy ` (7 subsequent siblings) 20 siblings, 0 replies; 25+ messages in thread From: Sudhakar Kuppusamy @ 2025-09-30 11:40 UTC (permalink / raw) To: grub-devel Cc: dja, jan.setjeeilers, julian.klode, mate.kukri, pjones, msuchanek, mlewando, stefanb, avnish, nayna, ssrish, Sudhakar Kuppusamy, sridharm, Daniel Kiper If secure boot is enabled with static key management mode, the trusted certificates will be extracted from the GRUB ELF Note and added to db list. If secure boot is enabled with dynamic key management mode, the trusted certificates and certificate/binary hash will be extracted from the PKS and added to db list. The distrusted certificates, certificate/binary hash are read from the PKS and added to dbx list. Both dbx and db lists usage is added by a subsequent patch. Note: If the certificate or the certificate hash exists in the dbx list, then do not add that certificate/certificate hash to the db list. 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> --- grub-core/commands/appendedsig/appendedsig.c | 408 ++++++++++++++++++- include/grub/efi/pks.h | 112 +++++ include/grub/types.h | 4 + 3 files changed, 507 insertions(+), 17 deletions(-) create mode 100644 include/grub/efi/pks.h diff --git a/grub-core/commands/appendedsig/appendedsig.c b/grub-core/commands/appendedsig/appendedsig.c index ca54c90fa..bfa5f332e 100644 --- a/grub-core/commands/appendedsig/appendedsig.c +++ b/grub-core/commands/appendedsig/appendedsig.c @@ -34,6 +34,7 @@ #include <grub/env.h> #include <grub/lockdown.h> #include <grub/powerpc/ieee1275/platform_keystore.h> +#include <grub/efi/pks.h> #include "appendedsig.h" @@ -46,6 +47,11 @@ GRUB_MOD_LICENSE ("GPLv3+"); #define SIG_MAGIC "~Module signature appended~\n" #define SIG_MAGIC_SIZE ((sizeof(SIG_MAGIC) - 1)) +/* SHA256, SHA384 and SHA512 hash sizes. */ +#define SHA256_HASH_SIZE 32 +#define SHA384_HASH_SIZE 48 +#define SHA512_HASH_SIZE 64 + /* * This structure is extracted from scripts/sign-file.c in the linux kernel * source. It was licensed as LGPLv2.1+, which is GPLv3+ compatible. @@ -79,11 +85,23 @@ struct sb_database { grub_x509_cert_t *certs; /* Certificates. */ grub_uint32_t cert_entries; /* Number of certificates. */ + grub_uint8_t **hashes; /* Certificate/binary hashes. */ + grub_size_t *hash_sizes; /* Sizes of certificate/binary hashes. */ + grub_uint32_t hash_entries; /* Number of certificate/binary hashes. */ + bool is_db; /* Flag to indicate the db/dbx list. */ }; typedef struct sb_database sb_database_t; /* The db list is used to validate appended signatures. */ -static sb_database_t db = {.certs = NULL, .cert_entries = 0}; +static sb_database_t db = {.certs = NULL, .cert_entries = 0, .hashes = NULL, + .hash_sizes = NULL, .hash_entries = 0, .is_db = true}; +/* + * The dbx list is used to ensure that the distrusted certificates or GRUB + * modules/kernel binaries are rejected during appended signatures/hashes + * validation. + */ +static sb_database_t dbx = {.certs = NULL, .cert_entries = 0, .hashes = NULL, + .hash_sizes = NULL, .hash_entries = 0, .is_db = false}; /* * Signature verification flag (check_sigs). @@ -118,6 +136,169 @@ static struct grub_fs pseudo_fs = { .fs_read = pseudo_read }; +/* + * GUID can be used to determine the hashing function and generate the hash using + * determined hashing function. + */ +static grub_err_t +get_hash (const grub_packed_guid_t *guid, const grub_uint8_t *data, const grub_size_t data_size, + grub_uint8_t *hash, grub_size_t *hash_size) +{ + gcry_md_spec_t *hash_func = NULL; + + if (guid == NULL) + return grub_error (GRUB_ERR_OUT_OF_RANGE, "GUID is not available"); + + if (grub_memcmp (guid, &GRUB_PKS_CERT_SHA256_GUID, GRUB_PACKED_GUID_SIZE) == 0 || + grub_memcmp (guid, &GRUB_PKS_CERT_X509_SHA256_GUID, GRUB_PACKED_GUID_SIZE) == 0) + hash_func = &_gcry_digest_spec_sha256; + else if (grub_memcmp (guid, &GRUB_PKS_CERT_SHA384_GUID, GRUB_PACKED_GUID_SIZE) == 0 || + grub_memcmp (guid, &GRUB_PKS_CERT_X509_SHA384_GUID, GRUB_PACKED_GUID_SIZE) == 0) + hash_func = &_gcry_digest_spec_sha384; + else if (grub_memcmp (guid, &GRUB_PKS_CERT_SHA512_GUID, GRUB_PACKED_GUID_SIZE) == 0 || + grub_memcmp (guid, &GRUB_PKS_CERT_X509_SHA512_GUID, GRUB_PACKED_GUID_SIZE) == 0) + hash_func = &_gcry_digest_spec_sha512; + else + return grub_error (GRUB_ERR_OUT_OF_RANGE, "unsupported GUID hash"); + + grub_crypto_hash (hash_func, hash, data, data_size); + *hash_size = hash_func->mdlen; + + return GRUB_ERR_NONE; +} + +static grub_err_t +generate_cert_hash (const grub_size_t cert_hash_size, const grub_uint8_t *data, + const grub_size_t data_size, grub_uint8_t *hash, grub_size_t *hash_size) +{ + grub_packed_guid_t guid = { 0 }; + + /* support SHA256, SHA384 and SHA512 for certificate hash */ + if (cert_hash_size == SHA256_HASH_SIZE) + grub_memcpy (&guid, &GRUB_PKS_CERT_X509_SHA256_GUID, GRUB_PACKED_GUID_SIZE); + else if (cert_hash_size == SHA384_HASH_SIZE) + grub_memcpy (&guid, &GRUB_PKS_CERT_X509_SHA384_GUID, GRUB_PACKED_GUID_SIZE); + else if (cert_hash_size == SHA512_HASH_SIZE) + grub_memcpy (&guid, &GRUB_PKS_CERT_X509_SHA512_GUID, GRUB_PACKED_GUID_SIZE); + else + { + grub_dprintf ("appendedsig", "unsupported hash type (%" PRIuGRUB_SIZE ") and " + "skipped\n", cert_hash_size); + return GRUB_ERR_UNKNOWN_COMMAND; + } + + return get_hash (&guid, data, data_size, hash, hash_size); +} + +/* Check the hash presence in the db/dbx list. */ +static bool +check_hash_presence (grub_uint8_t *const hash, const grub_size_t hash_size, + const sb_database_t *sb_database) +{ + grub_uint32_t i; + + for (i = 0; i < sb_database->hash_entries; i++) + { + if (sb_database->hashes[i] == NULL) + continue; + + if (hash_size == sb_database->hash_sizes[i] && + grub_memcmp (sb_database->hashes[i], hash, hash_size) == 0) + return true; + } + + return false; +} + +/* Add the certificate/binary hash into the db/dbx list. */ +static grub_err_t +add_hash (grub_uint8_t *const data, const grub_size_t data_size, sb_database_t *sb_database) +{ + grub_uint8_t **hashes; + grub_size_t *hash_sizes; + + if (data == NULL || data_size == 0) + return grub_error (GRUB_ERR_OUT_OF_RANGE, "certificate/binary-hash data or size is not available"); + + if (sb_database->is_db == true) + { + if (check_hash_presence (data, data_size, &dbx) == true) + { + grub_dprintf ("appendedsig", + "cannot add a hash (%02x%02x%02x%02x), as it is present in the dbx list\n", + data[0], data[1], data[2], data[3]); + return GRUB_ERR_ACCESS_DENIED; + } + } + + if (check_hash_presence (data, data_size, sb_database) == true) + { + grub_dprintf ("appendedsig", + "cannot add a hash (%02x%02x%02x%02x), as it is present in the %s list\n", + data[0], data[1], data[2], data[3], ((sb_database->is_db == true) ? "db" : "dbx")); + return GRUB_ERR_EXISTS; + } + + hashes = grub_realloc (sb_database->hashes, sizeof (grub_uint8_t *) * (sb_database->hash_entries + 1)); + if (hashes == NULL) + return grub_error (GRUB_ERR_OUT_OF_MEMORY, "out of memory"); + + hash_sizes = grub_realloc (sb_database->hash_sizes, sizeof (grub_size_t) * (sb_database->hash_entries + 1)); + if (hash_sizes == NULL) + { + /* Allocated memory will be freed by free_db_list()/free_dbx_list(). */ + hashes[sb_database->hash_entries] = NULL; + sb_database->hashes = hashes; + sb_database->hash_entries++; + + return grub_error (GRUB_ERR_OUT_OF_MEMORY, "out of memory"); + } + + hashes[sb_database->hash_entries] = grub_malloc (data_size); + if (hashes[sb_database->hash_entries] == NULL) + return grub_error (GRUB_ERR_OUT_OF_MEMORY, "out of memory"); + + grub_dprintf ("appendedsig", + "added the hash %02x%02x%02x%02x... with size of %" PRIuGRUB_SIZE " to the %s list\n", + data[0], data[1], data[2], data[3], data_size, + ((sb_database->is_db == true) ? "db" : "dbx")); + + grub_memcpy (hashes[sb_database->hash_entries], data, data_size); + hash_sizes[sb_database->hash_entries] = data_size; + sb_database->hash_sizes = hash_sizes; + sb_database->hashes = hashes; + sb_database->hash_entries++; + + return GRUB_ERR_NONE; +} + +static bool +is_hash (const grub_packed_guid_t *guid) +{ + /* GUID type of the binary hash. */ + if (grub_memcmp (guid, &GRUB_PKS_CERT_SHA256_GUID, GRUB_PACKED_GUID_SIZE) == 0 || + grub_memcmp (guid, &GRUB_PKS_CERT_SHA384_GUID, GRUB_PACKED_GUID_SIZE) == 0 || + grub_memcmp (guid, &GRUB_PKS_CERT_SHA512_GUID, GRUB_PACKED_GUID_SIZE) == 0) + return true; + + /* GUID type of the certificate hash. */ + if (grub_memcmp (guid, &GRUB_PKS_CERT_X509_SHA256_GUID, GRUB_PACKED_GUID_SIZE) == 0 || + grub_memcmp (guid, &GRUB_PKS_CERT_X509_SHA384_GUID, GRUB_PACKED_GUID_SIZE) == 0 || + grub_memcmp (guid, &GRUB_PKS_CERT_X509_SHA512_GUID, GRUB_PACKED_GUID_SIZE) == 0) + return true; + + return false; +} + +static bool +is_x509 (const grub_packed_guid_t *guid) +{ + if (grub_memcmp (guid, &GRUB_PKS_CERT_X509_GUID, GRUB_PACKED_GUID_SIZE) == 0) + return true; + + return false; +} + static bool is_cert_match (const grub_x509_cert_t *cert1, const grub_x509_cert_t *cert2) { @@ -136,7 +317,33 @@ is_cert_match (const grub_x509_cert_t *cert1, const grub_x509_cert_t *cert2) return false; } -/* Check the certificate presence in the db list. */ +/* Check the certificate hash presence in the dbx list. */ +static bool +is_cert_hash_present_in_dbx (const grub_uint8_t *data, const grub_size_t data_size) +{ + grub_err_t rc; + grub_uint32_t i; + grub_size_t cert_hash_size = 0; + grub_uint8_t cert_hash[GRUB_MAX_HASH_LEN] = { 0 }; + + for (i = 0; i < dbx.hash_entries; i++) + { + if (dbx.hashes[i] == NULL) + continue; + + rc = generate_cert_hash (dbx.hash_sizes[i], data, data_size, cert_hash, &cert_hash_size); + if (rc != GRUB_ERR_NONE) + continue; + + if (cert_hash_size == dbx.hash_sizes[i] && + grub_memcmp (dbx.hashes[i], cert_hash, cert_hash_size) == 0) + return true; + } + + return false; +} + +/* Check the certificate presence in the db/dbx list. */ static bool check_cert_presence (const grub_x509_cert_t *cert_in, const sb_database_t *sb_database) { @@ -149,7 +356,11 @@ check_cert_presence (const grub_x509_cert_t *cert_in, const sb_database_t *sb_da return false; } -/* Add the certificate into the db list */ +/* + * Add the certificate into the db list if it is not present in the dbx and db + * list when is_db is true. Add the certificate into the dbx list when is_db is + * false. + */ static grub_err_t add_certificate (const grub_uint8_t *data, const grub_size_t data_size, sb_database_t *sb_database) @@ -167,30 +378,54 @@ add_certificate (const grub_uint8_t *data, const grub_size_t data_size, rc = grub_x509_cert_parse (data, data_size, cert); if (rc != GRUB_ERR_NONE) { - grub_dprintf ("appendedsig", "cannot add a certificate CN='%s' to the db list\n", - cert->subject); + grub_dprintf ("appendedsig", "cannot add a certificate CN='%s' to the %s list\n", + cert->subject, (sb_database->is_db == true) ? "db" : "dbx"); grub_free (cert); return rc; } + /* + * Only checks the certificate against dbx if is_db is true when dynamic key + * management is enabled. + */ + if (append_key_mgmt == true) + { + if (sb_database->is_db == true) + { + if (is_cert_hash_present_in_dbx (data, data_size) == true || + check_cert_presence (cert, &dbx) == true) + { + grub_dprintf ("appendedsig", + "cannot add a certificate CN='%s', as it is present in the dbx list", + cert->subject); + rc = GRUB_ERR_ACCESS_DENIED; + goto fail; + } + } + } + if (check_cert_presence (cert, sb_database) == true) { grub_dprintf ("appendedsig", - "cannot add a certificate CN='%s', as it is present in the db list", - cert->subject); - grub_x509_cert_release (cert); - grub_free (cert); - - return GRUB_ERR_EXISTS; + "cannot add a certificate CN='%s', as it is present in the %s list", + cert->subject, ((sb_database->is_db == true) ? "db" : "dbx")); + rc = GRUB_ERR_EXISTS; + goto fail; } - grub_dprintf ("appendedsig", "added a certificate CN='%s' to the db list\n", - cert->subject); + grub_dprintf ("appendedsig", "added a certificate CN='%s' to the %s list\n", + cert->subject, ((sb_database->is_db == true) ? "db" : "dbx")); cert->next = sb_database->certs; sb_database->certs = cert; sb_database->cert_entries++; + return rc; + + fail: + grub_x509_cert_release (cert); + grub_free (cert); + return rc; } @@ -382,6 +617,68 @@ grub_verify_appended_signature (const grub_uint8_t *buf, grub_size_t bufsize) return err; } +/* Add the X.509 certificates/binary hash to the db list from PKS. */ +static grub_err_t +load_pks2db (void) +{ + grub_err_t rc; + grub_uint32_t i; + + for (i = 0; i < pks_keystore->db_entries; i++) + { + if (is_hash (&pks_keystore->db[i].guid) == true) + { + rc = add_hash (pks_keystore->db[i].data, + pks_keystore->db[i].data_size, &db); + if (rc == GRUB_ERR_OUT_OF_MEMORY) + return rc; + } + else if (is_x509 (&pks_keystore->db[i].guid) == true) + { + rc = add_certificate (pks_keystore->db[i].data, + pks_keystore->db[i].data_size, &db); + if (rc == GRUB_ERR_OUT_OF_MEMORY) + return rc; + } + else + grub_dprintf ("appendedsig", "unsupported signature data type and " + "skipped (%u)\n", i + 1); + } + + return GRUB_ERR_NONE; +} + +/* Add the certificates and certificate/binary hash to the dbx list from PKS. */ +static grub_err_t +load_pks2dbx (void) +{ + grub_err_t rc; + grub_uint32_t i; + + for (i = 0; i < pks_keystore->dbx_entries; i++) + { + if (is_x509 (&pks_keystore->dbx[i].guid) == true) + { + rc = add_certificate (pks_keystore->dbx[i].data, + pks_keystore->dbx[i].data_size, &dbx); + if (rc == GRUB_ERR_OUT_OF_MEMORY) + return rc; + } + else if (is_hash (&pks_keystore->dbx[i].guid) == true) + { + rc = add_hash (pks_keystore->dbx[i].data, + pks_keystore->dbx[i].data_size, &dbx); + if (rc != GRUB_ERR_NONE) + return rc; + } + else + grub_dprintf ("appendedsig", "unsupported signature data type and " + "skipped (%u)\n", i + 1); + } + + return GRUB_ERR_NONE; +} + /* * Extract the X.509 certificates from the ELF Note header, parse it, and add * it to the db list. @@ -422,11 +719,46 @@ load_elf2db (void) } } +/* + * Extract trusted and distrusted keys from PKS and store them in the db and + * dbx list. + */ +static void +create_dbs_from_pks (void) +{ + grub_err_t err; + + err = load_pks2dbx (); + if (err != GRUB_ERR_NONE) + grub_printf ("warning: dbx list might not be fully populated\n"); + + /* + * If the db variable is not present or empty in the PKS storage, then read + * the static keys as a db default keys from the GRUB ELF Note and add them + * into the db list. + */ + if (pks_keystore->db == NULL) + load_elf2db (); + else + { + err = load_pks2db (); + if (err != GRUB_ERR_NONE) + grub_printf ("warning: db list might not be fully populated\n"); + } + + grub_pks_free_data (); + grub_dprintf ("appendedsig", "the db list now has %u keys\n" + "the dbx list now has %u keys\n", + db.hash_entries + db.cert_entries, + dbx.hash_entries + dbx.cert_entries); +} + /* Free db list memory */ static void free_db_list (void) { grub_x509_cert_t *cert; + grub_uint32_t i; while (db.certs != NULL) { @@ -436,9 +768,37 @@ free_db_list (void) grub_free (cert); } + for (i = 0; i < db.hash_entries; i++) + grub_free (db.hashes[i]); + + grub_free (db.hashes); + grub_free (db.hash_sizes); grub_memset (&db, 0, sizeof (sb_database_t)); } +/* Free dbx list memory */ +static void +free_dbx_list (void) +{ + grub_x509_cert_t *cert; + grub_uint32_t i; + + while (dbx.certs != NULL) + { + cert = dbx.certs; + dbx.certs = dbx.certs->next; + grub_x509_cert_release (cert); + grub_free (cert); + } + + for (i = 0; i < dbx.hash_entries; i++) + grub_free (dbx.hashes[i]); + + grub_free (dbx.hashes); + grub_free (dbx.hash_sizes); + grub_memset (&dbx, 0, sizeof (sb_database_t)); +} + static const char * grub_env_read_sec (struct grub_env_var *var __attribute__ ((unused)), const char *val __attribute__ ((unused))) @@ -631,10 +991,23 @@ GRUB_MOD_INIT (appendedsig) if (rc != ASN1_SUCCESS) grub_fatal ("error initing ASN.1 data structures: %d: %s\n", rc, asn1_strerror (rc)); - /* Extract trusted keys from ELF Note and store them in the db. */ - load_elf2db (); - grub_dprintf ("appendedsig", "the db list now has %u static keys\n", - db.cert_entries); + /* + * If signature verification is enabled with the dynamic key management, + * extract trusted and distrusted keys from PKS and store them in the db + * and dbx list. + */ + if (append_key_mgmt == true) + create_dbs_from_pks (); + /* + * If signature verification is enabled with the static key management, + * extract trusted keys from ELF Note and store them in the db list. + */ + else + { + load_elf2db (); + grub_dprintf ("appendedsig", "the db list now has %u static keys\n", + db.cert_entries); + } grub_verifier_register (&grub_appendedsig_verifier); grub_dl_set_persistent (mod); @@ -648,6 +1021,7 @@ GRUB_MOD_FINI (appendedsig) */ free_db_list (); + free_dbx_list (); grub_register_variable_hook ("check_appended_signatures", NULL, NULL); grub_env_unset ("check_appended_signatures"); grub_register_variable_hook ("appendedsig_key_mgmt", NULL, NULL); diff --git a/include/grub/efi/pks.h b/include/grub/efi/pks.h new file mode 100644 index 000000000..ff306f591 --- /dev/null +++ b/include/grub/efi/pks.h @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved. This + * program and the accompanying materials are licensed and made available + * under the terms and conditions of the 2-Clause BSD License which + * accompanies this distribution. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * https://github.com/tianocore/edk2-staging (edk2-staging repo of tianocore), + * the ImageAuthentication.h file under it, and here's the copyright and license. + * + * MdePkg/Include/Guid/ImageAuthentication.h + * + * Copyright 2022, 2023, 2024, 2025 IBM Corp. + */ + +#ifndef PKS_HEADER +#define PKS_HEADER 1 + +#include <grub/types.h> + +/* + * It is derived from EFI_CERT_X509_GUID. + * https://github.com/tianocore/edk2-staging/blob/master/MdePkg/Include/Guid/ImageAuthentication.h + */ +#define GRUB_PKS_CERT_X509_GUID \ + (grub_guid_t) \ + { 0xa159c0a5, 0xe494, 0xa74a, \ + { 0x87, 0xb5, 0xab, 0x15, 0x5c, 0x2b, 0xf0, 0x72 } \ + } + +/* + * It is derived from EFI_CERT_SHA256_GUID. + * https://github.com/tianocore/edk2-staging/blob/master/MdePkg/Include/Guid/ImageAuthentication.h + */ +#define GRUB_PKS_CERT_SHA256_GUID \ + (grub_guid_t) \ + { 0x2616c4c1, 0x4c50, 0x9240, \ + { 0xac, 0xa9, 0x41, 0xf9, 0x36, 0x93, 0x43, 0x28 } \ + } + +/* + * It is derived from EFI_CERT_SHA384_GUID. + * https://github.com/tianocore/edk2-staging/blob/master/MdePkg/Include/Guid/ImageAuthentication.h + */ +#define GRUB_PKS_CERT_SHA384_GUID \ + (grub_guid_t) \ + { 0x07533eff, 0xd09f, 0xc948, \ + { 0x85, 0xf1, 0x8a, 0xd5, 0x6c, 0x70, 0x1e, 0x1 } \ + } + +/* + * It is derived from EFI_CERT_SHA512_GUID. + * https://github.com/tianocore/edk2-staging/blob/master/MdePkg/Include/Guid/ImageAuthentication.h + */ +#define GRUB_PKS_CERT_SHA512_GUID \ + (grub_guid_t) \ + { 0xae0f3e09, 0xc4a6, 0x504f, \ + { 0x9f, 0x1b, 0xd4, 0x1e, 0x2b, 0x89, 0xc1, 0x9a } \ + } + +/* + * It is derived from EFI_CERT_X509_SHA256_GUID. + * https://github.com/tianocore/edk2-staging/blob/master/MdePkg/Include/Guid/ImageAuthentication.h + */ +#define GRUB_PKS_CERT_X509_SHA256_GUID \ + (grub_guid_t) \ + { 0x92a4d23b, 0xc096, 0x7940, \ + { 0xb4, 0x20, 0xfc, 0xf9, 0x8e, 0xf1, 0x03, 0xed } \ + } + +/* + * It is derived from EFI_CERT_X509_SHA384_GUID. + * https://github.com/tianocore/edk2-staging/blob/master/MdePkg/Include/Guid/ImageAuthentication.h + */ +#define GRUB_PKS_CERT_X509_SHA384_GUID \ + (grub_guid_t) \ + { 0x6e877670, 0xc280, 0xe64e, \ + { 0xaa, 0xd2, 0x28, 0xb3, 0x49, 0xa6, 0x86, 0x5b } \ + } + +/* + * It is derived from EFI_CERT_X509_SHA512_GUID. + * https://github.com/tianocore/edk2-staging/blob/master/MdePkg/Include/Guid/ImageAuthentication.h + */ +#define GRUB_PKS_CERT_X509_SHA512_GUID \ + (grub_guid_t) \ + { 0x63bf6d44, 0x0225, 0xda4c, \ + { 0xbc, 0xfa, 0x24, 0x65, 0xd2, 0xb0, 0xfe, 0x9d } \ + } + +#endif diff --git a/include/grub/types.h b/include/grub/types.h index 45079bf65..b3ba762fc 100644 --- a/include/grub/types.h +++ b/include/grub/types.h @@ -379,6 +379,8 @@ struct grub_guid } __attribute__ ((aligned(4))); typedef struct grub_guid grub_guid_t; +#define GRUB_GUID_SIZE (sizeof (grub_guid_t)) + struct grub_packed_guid { grub_uint32_t data1; @@ -388,4 +390,6 @@ struct grub_packed_guid } GRUB_PACKED; typedef struct grub_packed_guid grub_packed_guid_t; +#define GRUB_PACKED_GUID_SIZE (sizeof (grub_packed_guid_t)) + #endif /* ! GRUB_TYPES_HEADER */ -- 2.50.1 (Apple Git-155) _______________________________________________ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel ^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH v13 14/20] appended signatures: Using db and dbx lists for signature verification 2025-09-30 11:39 [PATCH v13 00/20] Appended Signature Secure Boot Support for PowerPC Sudhakar Kuppusamy ` (12 preceding siblings ...) 2025-09-30 11:40 ` [PATCH v13 13/20] appended signatures: Create db and dbx lists Sudhakar Kuppusamy @ 2025-09-30 11:40 ` Sudhakar Kuppusamy 2025-09-30 11:40 ` [PATCH v13 15/20] appended signatures: GRUB commands to manage the certificates Sudhakar Kuppusamy ` (6 subsequent siblings) 20 siblings, 0 replies; 25+ messages in thread From: Sudhakar Kuppusamy @ 2025-09-30 11:40 UTC (permalink / raw) To: grub-devel Cc: dja, jan.setjeeilers, julian.klode, mate.kukri, pjones, msuchanek, mlewando, stefanb, avnish, nayna, ssrish, Sudhakar Kuppusamy, sridharm, Daniel Kiper Signature verification: verify the kernel against lists of hashes that are either in dbx or db list. If it is not in the dbx list then the trusted keys from the db list are used to verify the signature. 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> --- grub-core/commands/appendedsig/appendedsig.c | 94 +++++++++++++++++++- 1 file changed, 93 insertions(+), 1 deletion(-) diff --git a/grub-core/commands/appendedsig/appendedsig.c b/grub-core/commands/appendedsig/appendedsig.c index bfa5f332e..b4b9e4cd3 100644 --- a/grub-core/commands/appendedsig/appendedsig.c +++ b/grub-core/commands/appendedsig/appendedsig.c @@ -521,6 +521,83 @@ extract_appended_signature (const grub_uint8_t *buf, grub_size_t bufsize, return grub_pkcs7_data_parse (signed_data, appendedsig_pkcs7_size, &sig->pkcs7); } +static grub_err_t +get_binary_hash (const grub_size_t binary_hash_size, const grub_uint8_t *data, + const grub_size_t data_size, grub_uint8_t *hash, grub_size_t *hash_size) +{ + grub_packed_guid_t guid = { 0 }; + + /* support SHA256, SHA384 and SHA512 for binary hash */ + if (binary_hash_size == SHA256_HASH_SIZE) + grub_memcpy (&guid, &GRUB_PKS_CERT_SHA256_GUID, GRUB_PACKED_GUID_SIZE); + else if (binary_hash_size == SHA384_HASH_SIZE) + grub_memcpy (&guid, &GRUB_PKS_CERT_SHA384_GUID, GRUB_PACKED_GUID_SIZE); + else if (binary_hash_size == SHA512_HASH_SIZE) + grub_memcpy (&guid, &GRUB_PKS_CERT_SHA512_GUID, GRUB_PACKED_GUID_SIZE); + else + { + grub_dprintf ("appendedsig", "unsupported hash type (%" PRIuGRUB_SIZE ") and " + "skipped\n", binary_hash_size); + return GRUB_ERR_UNKNOWN_COMMAND; + } + + return get_hash (&guid, data, data_size, hash, hash_size); +} + +/* + * Verify binary hash against the db and dbx list. + * The following errors can occur: + * - GRUB_ERR_BAD_SIGNATURE: indicates that the hash is in dbx list. + * - GRUB_ERR_EOF: the hash could not be found in the db and dbx list. + * - GRUB_ERR_NONE: the hash is found in db list. + */ +static grub_err_t +verify_binary_hash (const grub_uint8_t *data, const grub_size_t data_size) +{ + grub_err_t rc = GRUB_ERR_NONE; + grub_uint32_t i; + grub_size_t hash_size = 0; + grub_uint8_t hash[GRUB_MAX_HASH_LEN] = { 0 }; + + for (i = 0; i < dbx.hash_entries; i++) + { + if (dbx.hashes[i] == NULL) + continue; + + rc = get_binary_hash (dbx.hash_sizes[i], data, data_size, hash, &hash_size); + if (rc != GRUB_ERR_NONE) + continue; + + if (hash_size == dbx.hash_sizes[i] && + grub_memcmp (dbx.hashes[i], hash, hash_size) == 0) + { + grub_dprintf ("appendedsig", "the hash (%02x%02x%02x%02x) is present in the dbx list\n", + hash[0], hash[1], hash[2], hash[3]); + return GRUB_ERR_BAD_SIGNATURE; + } + } + + for (i = 0; i < db.hash_entries; i++) + { + if (db.hashes[i] == NULL) + continue; + + rc = get_binary_hash (db.hash_sizes[i], data, data_size, hash, &hash_size); + if (rc != GRUB_ERR_NONE) + continue; + + if (hash_size == db.hash_sizes[i] && + grub_memcmp (db.hashes[i], hash, hash_size) == 0) + { + grub_dprintf ("appendedsig", "verified with a trusted hash (%02x%02x%02x%02x)\n", + hash[0], hash[1], hash[2], hash[3]); + return GRUB_ERR_NONE; + } + } + + return GRUB_ERR_EOF; +} + /* * Given a hash value 'hval', of hash specification 'hash', prepare the * S-expressions (sexp) and perform the signature verification. @@ -565,7 +642,7 @@ grub_verify_appended_signature (const grub_uint8_t *buf, grub_size_t bufsize) grub_pkcs7_signer_t *si; grub_int32_t i; - if (!db.cert_entries) + if (!db.cert_entries && !db.hash_entries) return grub_error (GRUB_ERR_BAD_SIGNATURE, "no trusted keys to verify against"); err = extract_appended_signature (buf, bufsize, &sig); @@ -574,6 +651,21 @@ grub_verify_appended_signature (const grub_uint8_t *buf, grub_size_t bufsize) datasize = bufsize - sig.signature_len; + /* + * If signature verification is enabled with dynamic key management mode, + * Verify binary hash against the db and dbx list. + */ + if (append_key_mgmt == true) + { + err = verify_binary_hash (buf, datasize); + if (err == GRUB_ERR_BAD_SIGNATURE) + { + grub_pkcs7_data_release (&sig.pkcs7); + return grub_error (err, + "failed to verify the binary hash against a trusted binary hash"); + } + } + /* Verify signature using trusted keys from db list. */ for (i = 0; i < sig.pkcs7.signer_count; i++) { -- 2.50.1 (Apple Git-155) _______________________________________________ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel ^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH v13 15/20] appended signatures: GRUB commands to manage the certificates 2025-09-30 11:39 [PATCH v13 00/20] Appended Signature Secure Boot Support for PowerPC Sudhakar Kuppusamy ` (13 preceding siblings ...) 2025-09-30 11:40 ` [PATCH v13 14/20] appended signatures: Using db and dbx lists for signature verification Sudhakar Kuppusamy @ 2025-09-30 11:40 ` Sudhakar Kuppusamy 2025-10-01 9:10 ` Sridhar Markonda 2025-09-30 11:40 ` [PATCH v13 16/20] appended signatures: GRUB commands to manage the hashes Sudhakar Kuppusamy ` (5 subsequent siblings) 20 siblings, 1 reply; 25+ messages in thread From: Sudhakar Kuppusamy @ 2025-09-30 11:40 UTC (permalink / raw) To: grub-devel Cc: dja, jan.setjeeilers, julian.klode, mate.kukri, pjones, msuchanek, mlewando, stefanb, avnish, nayna, ssrish, Sudhakar Kuppusamy, sridharm, Daniel Kiper Introducing the following GRUB commands to manage the certificates. 1. append_list_db: Show the list of trusted certificates from the db list 2. append_add_db_cert: Add the trusted certificate to the db list 3. append_add_dbx_cert: Add the distrusted certificate to the dbx list 4. append_verify: Verify the signed file using db list Note that if signature verification (check_appended_signatures) is set to yes, the append_add_db_cert and append_add_dbx_cert commands only accept the file ‘X509_certificate’ that is signed with an appended signature. Signed-off-by: Daniel Axtens <dja@axtens.net> Signed-off-by: Sudhakar Kuppusamy <sudhakar@linux.ibm.com> Reviewed-by: Avnish Chouhan <avnish@linux.ibm.com> Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com> --- grub-core/commands/appendedsig/appendedsig.c | 320 +++++++++++++++++++ 1 file changed, 320 insertions(+) diff --git a/grub-core/commands/appendedsig/appendedsig.c b/grub-core/commands/appendedsig/appendedsig.c index b4b9e4cd3..d04aaf1e2 100644 --- a/grub-core/commands/appendedsig/appendedsig.c +++ b/grub-core/commands/appendedsig/appendedsig.c @@ -123,6 +123,9 @@ static bool append_key_mgmt = false; /* Platform KeyStore db and dbx. */ static grub_pks_t *pks_keystore; +/* Appended signature size. */ +static grub_size_t append_sig_len = 0; + static grub_ssize_t pseudo_read (struct grub_file *file, char *buf, grub_size_t len) { @@ -136,6 +139,65 @@ static struct grub_fs pseudo_fs = { .fs_read = pseudo_read }; +/* + * We cannot use hexdump() to display hash data because it is typically displayed + * in hexadecimal format, along with an ASCII representation of the same data. + * + * Example: sha256 hash data + * 00000000 52 b5 90 49 64 de 22 d7 4e 5f 4f b4 1b 51 9c 34 |R..Id.".N_O..Q.4| + * 00000010 b1 96 21 7c 91 78 a5 0d 20 8c e9 5c 22 54 53 f7 |..!|.x.. ..\"TS.| + * + * An appended signature only required to display the hexadecimal of the hash data + * by separating each byte with ":". So, we introduced a new method hexdump_colon + * to display it. + * + * Example: Sha256 hash data + * 52:b5:90:49:64:de:22:d7:4e:5f:4f:b4:1b:51:9c:34: + * b1:96:21:7c:91:78:a5:0d:20:8c:e9:5c:22:54:53:f7 + */ +static void +hexdump_colon (const grub_uint8_t *data, const grub_size_t length) +{ + grub_size_t i, count = 0; + + for (i = 0; i < length - 1; i++) + { + grub_printf ("%02x:", data[i]); + count++; + if (count == 16) + { + grub_printf ("\n "); + count = 0; + } + } + + grub_printf ("%02x\n", data[i]); +} + +static void +print_certificate (const grub_x509_cert_t *cert, const grub_uint32_t cert_num) +{ + grub_uint32_t i; + + grub_printf ("\nCertificate: %u\n", cert_num); + grub_printf (" Data:\n"); + grub_printf (" Version: %u (0x%u)\n", cert->version + 1, cert->version); + grub_printf (" Serial Number:\n "); + + for (i = 0; i < cert->serial_len - 1; i++) + grub_printf ("%02x:", cert->serial[i]); + + grub_printf ("%02x\n", cert->serial[cert->serial_len - 1]); + grub_printf (" Issuer: %s\n", cert->issuer); + grub_printf (" Subject: %s\n", cert->subject); + grub_printf (" Subject Public Key Info:\n"); + grub_printf (" Public Key Algorithm: rsaEncryption\n"); + grub_printf (" RSA Public-Key: (%d bit)\n", cert->modulus_size); + grub_printf (" Fingerprint: sha256\n "); + hexdump_colon (&cert->fingerprint[GRUB_FINGERPRINT_SHA256][0], + grub_strlen ((char *) cert->fingerprint[GRUB_FINGERPRINT_SHA256])); +} + /* * GUID can be used to determine the hashing function and generate the hash using * determined hashing function. @@ -429,6 +491,61 @@ add_certificate (const grub_uint8_t *data, const grub_size_t data_size, return rc; } +static void +_remove_cert_from_db (const grub_x509_cert_t *cert) +{ + grub_uint32_t i = 1; + grub_x509_cert_t *curr_cert, *prev_cert; + + for (curr_cert = prev_cert = db.certs; curr_cert != NULL; curr_cert = curr_cert->next, i++) + { + if (is_cert_match (curr_cert, cert) == true) + { + if (i == 1) /* Match with first certificate in the db list. */ + db.certs = curr_cert->next; + else + prev_cert->next = curr_cert->next; + + grub_dprintf ("appendedsig", + "removed distrusted certificate with CN: %s from the db list\n", + curr_cert->subject); + curr_cert->next = NULL; + grub_x509_cert_release (curr_cert); + grub_free (curr_cert); + break; + } + else + prev_cert = curr_cert; + } +} + +static grub_err_t +remove_cert_from_db (const grub_uint8_t *data, const grub_size_t data_size) +{ + grub_err_t rc; + grub_x509_cert_t *cert; + + if (data == NULL || data_size == 0) + return grub_error (GRUB_ERR_OUT_OF_RANGE, "certificate data or size is not available"); + + cert = grub_zalloc (sizeof (grub_x509_cert_t)); + if (cert == NULL) + return grub_error (GRUB_ERR_OUT_OF_MEMORY, "out of memory"); + + rc = grub_x509_cert_parse (data, data_size, cert); + if (rc != GRUB_ERR_NONE) + { + grub_dprintf ("appendedsig", "cannot remove an invalid certificate from the db list\n"); + grub_free (cert); + return rc; + } + + /* Remove certificate from the db list. */ + _remove_cert_from_db (cert); + + return rc; +} + static grub_err_t file_read_whole (grub_file_t file, grub_uint8_t **buf, grub_size_t *len) { @@ -649,6 +766,7 @@ grub_verify_appended_signature (const grub_uint8_t *buf, grub_size_t bufsize) if (err != GRUB_ERR_NONE) return err; + append_sig_len = sig.signature_len; datasize = bufsize - sig.signature_len; /* @@ -709,6 +827,193 @@ grub_verify_appended_signature (const grub_uint8_t *buf, grub_size_t bufsize) return err; } +static grub_err_t +grub_cmd_verify_signature (grub_command_t cmd __attribute__ ((unused)), int argc, char **args) +{ + grub_file_t signed_file; + grub_err_t err; + grub_uint8_t *signed_data = NULL; + grub_size_t signed_data_size = 0; + + if (argc != 1) + return grub_error (GRUB_ERR_BAD_ARGUMENT, + "a signed file is expected\nExample:\n\tappend_verify <SIGNED FILE>\n"); + + if (!grub_strlen (args[0])) + return grub_error (GRUB_ERR_BAD_FILENAME, "missing signed file"); + + grub_dprintf ("appendedsig", "verifying %s\n", args[0]); + + signed_file = grub_file_open (args[0], GRUB_FILE_TYPE_VERIFY_SIGNATURE); + if (signed_file == NULL) + return grub_error (GRUB_ERR_FILE_NOT_FOUND, "could not open %s file", args[0]); + + err = file_read_whole (signed_file, &signed_data, &signed_data_size); + if (err == GRUB_ERR_NONE) + err = grub_verify_appended_signature (signed_data, signed_data_size); + + grub_file_close (signed_file); + grub_free (signed_data); + + return err; +} + +/* + * Checks the trusted certificate against dbx list if dynamic key management is + * enabled. And add it to the db list if it is not already present. + * + * Note: When signature verification is enabled, this command only accepts the + * trusted certificate that is signed with an appended signature. + * The signature is verified by the appendedsig module. If verification succeeds, + * the certificate is added to the db list. Otherwise, an error is posted and + * the certificate is not added. + * When signature verification is disabled, it accepts the trusted certificate + * without an appended signature and add it to the db list. + * + * Also, note that the adding of the trusted certificate using this command does + * not persist across reboots. + */ +static grub_err_t +grub_cmd_db_cert (grub_command_t cmd __attribute__ ((unused)), int argc, char **args) +{ + grub_err_t err; + grub_file_t cert_file; + grub_uint8_t *cert_data = NULL; + grub_size_t cert_data_size = 0; + + if (argc != 1) + return grub_error (GRUB_ERR_BAD_ARGUMENT, + "a trusted X.509 certificate file is expected in DER format\n" + "Example:\n\tappend_add_db_cert <X509_CERTIFICATE>\n"); + + if (!grub_strlen (args[0])) + return grub_error (GRUB_ERR_BAD_FILENAME, "missing trusted X.509 certificate file"); + + cert_file = grub_file_open (args[0], + GRUB_FILE_TYPE_CERTIFICATE_TRUST | GRUB_FILE_TYPE_NO_DECOMPRESS); + if (cert_file == NULL) + return grub_error (GRUB_ERR_BAD_FILE_TYPE, "could not open %s file", args[0]); + + err = file_read_whole (cert_file, &cert_data, &cert_data_size); + grub_file_close (cert_file); + if (err != GRUB_ERR_NONE) + return err; + + /* + * If signature verification is enabled (check_sigs is set to true), obtain + * the actual certificate size by subtracting the appended signature size from + * the certificate size because the certificate has an appended signature, and + * this actual certificate size is used to get the X.509 certificate. + */ + if (check_sigs == true) + cert_data_size -= append_sig_len; + + err = add_certificate (cert_data, cert_data_size, &db); + grub_free (cert_data); + if (err != GRUB_ERR_NONE) + return err; + + return GRUB_ERR_NONE; +} + +/* + * Remove the distrusted certificate from the db list if it is already present. + * And add it to the dbx list if not present when dynamic key management is + * enabled. + * + * Note: When signature verification is enabled, this command only accepts the + * distrusted certificate that is signed with an appended signature. + * The signature is verified by the appended sig module. If verification + * succeeds, the certificate is removed from the db list. Otherwise, an error + * is posted and the certificate is not removed. + * When signature verification is disabled, it accepts the distrusted certificate + * without an appended signature and removes it from the db list. + * + * Also, note that the removal of the distrusted certificate using this command + * does not persist across reboots. + */ +static grub_err_t +grub_cmd_dbx_cert (grub_command_t cmd __attribute__ ((unused)), int argc, char **args) +{ + grub_err_t err; + grub_file_t cert_file; + grub_uint8_t *cert_data = NULL; + grub_size_t cert_data_size = 0; + + if (argc != 1) + return grub_error (GRUB_ERR_BAD_ARGUMENT, + "a distrusted X.509 certificate file is expected in DER format\n" + "Example:\n\tappend_add_dbx_cert <X509_CERTIFICATE>\n"); + + if (!grub_strlen (args[0])) + return grub_error (GRUB_ERR_BAD_FILENAME, "missing distrusted X.509 certificate file"); + + cert_file = grub_file_open (args[0], + GRUB_FILE_TYPE_CERTIFICATE_TRUST | GRUB_FILE_TYPE_NO_DECOMPRESS); + if (cert_file == NULL) + return grub_error (GRUB_ERR_BAD_FILE_TYPE, "could not open %s file", args[0]); + + err = file_read_whole (cert_file, &cert_data, &cert_data_size); + grub_file_close (cert_file); + if (err != GRUB_ERR_NONE) + return err; + + /* + * If signature verification is enabled (check_sigs is set to true), obtain + * the actual certificate size by subtracting the appended signature size from + * the certificate size because the certificate has an appended signature, and + * this actual certificate size is used to get the X.509 certificate. + */ + if (check_sigs == true) + cert_data_size -= append_sig_len; + + /* Remove distrusted certificate from the db list if present. */ + err = remove_cert_from_db (cert_data, cert_data_size); + if (err != GRUB_ERR_NONE) + { + grub_free (cert_data); + return err; + } + + /* Only add the certificate to the dbx list if dynamic key management is enabled. */ + if (append_key_mgmt == true) + { + err = add_certificate (cert_data, cert_data_size, &dbx); + if (err != GRUB_ERR_NONE) + return err; + } + + grub_free (cert_data); + + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_cmd_list_db (grub_command_t cmd __attribute__ ((unused)), int argc __attribute__ ((unused)), + char **args __attribute__ ((unused))) +{ + struct x509_certificate *cert; + grub_uint32_t i, cert_num = 1; + + for (cert = db.certs; cert != NULL; cert = cert->next, cert_num++) + print_certificate (cert, cert_num); + + if (append_key_mgmt == false) + return GRUB_ERR_NONE; + + for (i = 0; i < db.hash_entries; i++) + { + if (db.hashes[i] != NULL) + { + grub_printf ("\nBinary hash: %u\n", i + 1); + grub_printf (" Hash: sha%" PRIuGRUB_SIZE "\n ", db.hash_sizes[i] * 8); + hexdump_colon (db.hashes[i], db.hash_sizes[i]); + } + } + + return GRUB_ERR_NONE; +} + /* Add the X.509 certificates/binary hash to the db list from PKS. */ static grub_err_t load_pks2db (void) @@ -1032,6 +1337,8 @@ struct grub_file_verifier grub_appendedsig_verifier = { .write = appendedsig_write, }; +static grub_command_t cmd_verify, cmd_list_db, cmd_dbx_cert, cmd_db_cert; + GRUB_MOD_INIT (appendedsig) { grub_int32_t rc; @@ -1101,6 +1408,15 @@ GRUB_MOD_INIT (appendedsig) db.cert_entries); } + cmd_verify = grub_register_command ("append_verify", grub_cmd_verify_signature, N_("<SIGNED_FILE>"), + N_("Verify SIGNED_FILE against the trusted X.509 certificates in the db list")); + cmd_list_db = grub_register_command ("append_list_db", grub_cmd_list_db, 0, + N_("Show the list of trusted X.509 certificates from the db list")); + cmd_db_cert = grub_register_command ("append_add_db_cert", grub_cmd_db_cert, N_("<X509_CERTIFICATE>"), + N_("Add trusted X509_CERTIFICATE to the db list")); + cmd_dbx_cert = grub_register_command ("append_add_dbx_cert", grub_cmd_dbx_cert, N_("<X509_CERTIFICATE>"), + N_("Add distrusted X509_CERTIFICATE to the dbx list")); + grub_verifier_register (&grub_appendedsig_verifier); grub_dl_set_persistent (mod); } @@ -1119,4 +1435,8 @@ GRUB_MOD_FINI (appendedsig) grub_register_variable_hook ("appendedsig_key_mgmt", NULL, NULL); grub_env_unset ("appendedsig_key_mgmt"); grub_verifier_unregister (&grub_appendedsig_verifier); + grub_unregister_command (cmd_verify); + grub_unregister_command (cmd_list_db); + grub_unregister_command (cmd_db_cert); + grub_unregister_command (cmd_dbx_cert); } -- 2.50.1 (Apple Git-155) _______________________________________________ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel ^ permalink raw reply related [flat|nested] 25+ messages in thread
* Re: [PATCH v13 15/20] appended signatures: GRUB commands to manage the certificates 2025-09-30 11:40 ` [PATCH v13 15/20] appended signatures: GRUB commands to manage the certificates Sudhakar Kuppusamy @ 2025-10-01 9:10 ` Sridhar Markonda 0 siblings, 0 replies; 25+ messages in thread From: Sridhar Markonda @ 2025-10-01 9:10 UTC (permalink / raw) To: Sudhakar Kuppusamy, grub-devel Cc: dja, jan.setjeeilers, julian.klode, mate.kukri, pjones, msuchanek, mlewando, stefanb, avnish, nayna, ssrish, Daniel Kiper On 30/09/25 5:10 pm, Sudhakar Kuppusamy wrote: > Introducing the following GRUB commands to manage the certificates. > > 1. append_list_db: > Show the list of trusted certificates from the db list > 2. append_add_db_cert: > Add the trusted certificate to the db list > 3. append_add_dbx_cert: > Add the distrusted certificate to the dbx list > 4. append_verify: > Verify the signed file using db list > > Note that if signature verification (check_appended_signatures) is set to yes, > the append_add_db_cert and append_add_dbx_cert commands only accept the file > ‘X509_certificate’ that is signed with an appended signature. > > Signed-off-by: Daniel Axtens <dja@axtens.net> > Signed-off-by: Sudhakar Kuppusamy <sudhakar@linux.ibm.com> > Reviewed-by: Avnish Chouhan <avnish@linux.ibm.com> > Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com> > --- > grub-core/commands/appendedsig/appendedsig.c | 320 +++++++++++++++++++ > 1 file changed, 320 insertions(+) > > diff --git a/grub-core/commands/appendedsig/appendedsig.c b/grub-core/commands/appendedsig/appendedsig.c > index b4b9e4cd3..d04aaf1e2 100644 > --- a/grub-core/commands/appendedsig/appendedsig.c > +++ b/grub-core/commands/appendedsig/appendedsig.c > @@ -123,6 +123,9 @@ static bool append_key_mgmt = false; > /* Platform KeyStore db and dbx. */ > static grub_pks_t *pks_keystore; > > +/* Appended signature size. */ > +static grub_size_t append_sig_len = 0; > + > static grub_ssize_t > pseudo_read (struct grub_file *file, char *buf, grub_size_t len) > { > @@ -136,6 +139,65 @@ static struct grub_fs pseudo_fs = { > .fs_read = pseudo_read > }; > > +/* > + * We cannot use hexdump() to display hash data because it is typically displayed > + * in hexadecimal format, along with an ASCII representation of the same data. > + * > + * Example: sha256 hash data > + * 00000000 52 b5 90 49 64 de 22 d7 4e 5f 4f b4 1b 51 9c 34 |R..Id.".N_O..Q.4| > + * 00000010 b1 96 21 7c 91 78 a5 0d 20 8c e9 5c 22 54 53 f7 |..!|.x.. ..\"TS.| > + * > + * An appended signature only required to display the hexadecimal of the hash data > + * by separating each byte with ":". So, we introduced a new method hexdump_colon > + * to display it. > + * > + * Example: Sha256 hash data > + * 52:b5:90:49:64:de:22:d7:4e:5f:4f:b4:1b:51:9c:34: > + * b1:96:21:7c:91:78:a5:0d:20:8c:e9:5c:22:54:53:f7 > + */ > +static void > +hexdump_colon (const grub_uint8_t *data, const grub_size_t length) > +{ > + grub_size_t i, count = 0; > + > + for (i = 0; i < length - 1; i++) > + { > + grub_printf ("%02x:", data[i]); > + count++; > + if (count == 16) > + { > + grub_printf ("\n "); > + count = 0; > + } > + } > + > + grub_printf ("%02x\n", data[i]); > +} > + > +static void > +print_certificate (const grub_x509_cert_t *cert, const grub_uint32_t cert_num) > +{ > + grub_uint32_t i; > + > + grub_printf ("\nCertificate: %u\n", cert_num); > + grub_printf (" Data:\n"); > + grub_printf (" Version: %u (0x%u)\n", cert->version + 1, cert->version); > + grub_printf (" Serial Number:\n "); > + > + for (i = 0; i < cert->serial_len - 1; i++) > + grub_printf ("%02x:", cert->serial[i]); > + > + grub_printf ("%02x\n", cert->serial[cert->serial_len - 1]); > + grub_printf (" Issuer: %s\n", cert->issuer); > + grub_printf (" Subject: %s\n", cert->subject); > + grub_printf (" Subject Public Key Info:\n"); > + grub_printf (" Public Key Algorithm: rsaEncryption\n"); > + grub_printf (" RSA Public-Key: (%d bit)\n", cert->modulus_size); > + grub_printf (" Fingerprint: sha256\n "); > + hexdump_colon (&cert->fingerprint[GRUB_FINGERPRINT_SHA256][0], > + grub_strlen ((char *) cert->fingerprint[GRUB_FINGERPRINT_SHA256])); > +} > + > /* > * GUID can be used to determine the hashing function and generate the hash using > * determined hashing function. > @@ -429,6 +491,61 @@ add_certificate (const grub_uint8_t *data, const grub_size_t data_size, > return rc; > } > > +static void > +_remove_cert_from_db (const grub_x509_cert_t *cert) > +{ > + grub_uint32_t i = 1; > + grub_x509_cert_t *curr_cert, *prev_cert; > + > + for (curr_cert = prev_cert = db.certs; curr_cert != NULL; curr_cert = curr_cert->next, i++) > + { > + if (is_cert_match (curr_cert, cert) == true) > + { > + if (i == 1) /* Match with first certificate in the db list. */ > + db.certs = curr_cert->next; > + else > + prev_cert->next = curr_cert->next; > + > + grub_dprintf ("appendedsig", > + "removed distrusted certificate with CN: %s from the db list\n", > + curr_cert->subject); > + curr_cert->next = NULL; > + grub_x509_cert_release (curr_cert); > + grub_free (curr_cert); > + break; > + } > + else > + prev_cert = curr_cert; > + } > +} > + > +static grub_err_t > +remove_cert_from_db (const grub_uint8_t *data, const grub_size_t data_size) > +{ > + grub_err_t rc; > + grub_x509_cert_t *cert; > + > + if (data == NULL || data_size == 0) > + return grub_error (GRUB_ERR_OUT_OF_RANGE, "certificate data or size is not available"); > + > + cert = grub_zalloc (sizeof (grub_x509_cert_t)); > + if (cert == NULL) > + return grub_error (GRUB_ERR_OUT_OF_MEMORY, "out of memory"); > + > + rc = grub_x509_cert_parse (data, data_size, cert); > + if (rc != GRUB_ERR_NONE) > + { > + grub_dprintf ("appendedsig", "cannot remove an invalid certificate from the db list\n"); > + grub_free (cert); > + return rc; > + } > + > + /* Remove certificate from the db list. */ > + _remove_cert_from_db (cert); > + > + return rc; > +} > + > static grub_err_t > file_read_whole (grub_file_t file, grub_uint8_t **buf, grub_size_t *len) > { > @@ -649,6 +766,7 @@ grub_verify_appended_signature (const grub_uint8_t *buf, grub_size_t bufsize) > if (err != GRUB_ERR_NONE) > return err; > > + append_sig_len = sig.signature_len; > datasize = bufsize - sig.signature_len; > > /* > @@ -709,6 +827,193 @@ grub_verify_appended_signature (const grub_uint8_t *buf, grub_size_t bufsize) > return err; > } > > +static grub_err_t > +grub_cmd_verify_signature (grub_command_t cmd __attribute__ ((unused)), int argc, char **args) > +{ > + grub_file_t signed_file; > + grub_err_t err; > + grub_uint8_t *signed_data = NULL; > + grub_size_t signed_data_size = 0; > + > + if (argc != 1) > + return grub_error (GRUB_ERR_BAD_ARGUMENT, > + "a signed file is expected\nExample:\n\tappend_verify <SIGNED FILE>\n"); > + > + if (!grub_strlen (args[0])) > + return grub_error (GRUB_ERR_BAD_FILENAME, "missing signed file"); > + > + grub_dprintf ("appendedsig", "verifying %s\n", args[0]); > + > + signed_file = grub_file_open (args[0], GRUB_FILE_TYPE_VERIFY_SIGNATURE); > + if (signed_file == NULL) > + return grub_error (GRUB_ERR_FILE_NOT_FOUND, "could not open %s file", args[0]); > + > + err = file_read_whole (signed_file, &signed_data, &signed_data_size); > + if (err == GRUB_ERR_NONE) > + err = grub_verify_appended_signature (signed_data, signed_data_size); > + > + grub_file_close (signed_file); > + grub_free (signed_data); > + > + return err; > +} > + > +/* > + * Checks the trusted certificate against dbx list if dynamic key management is > + * enabled. And add it to the db list if it is not already present. > + * > + * Note: When signature verification is enabled, this command only accepts the > + * trusted certificate that is signed with an appended signature. > + * The signature is verified by the appendedsig module. If verification succeeds, > + * the certificate is added to the db list. Otherwise, an error is posted and > + * the certificate is not added. > + * When signature verification is disabled, it accepts the trusted certificate > + * without an appended signature and add it to the db list. > + * > + * Also, note that the adding of the trusted certificate using this command does > + * not persist across reboots. > + */ > +static grub_err_t > +grub_cmd_db_cert (grub_command_t cmd __attribute__ ((unused)), int argc, char **args) > +{ > + grub_err_t err; > + grub_file_t cert_file; > + grub_uint8_t *cert_data = NULL; > + grub_size_t cert_data_size = 0; > + > + if (argc != 1) > + return grub_error (GRUB_ERR_BAD_ARGUMENT, > + "a trusted X.509 certificate file is expected in DER format\n" > + "Example:\n\tappend_add_db_cert <X509_CERTIFICATE>\n"); > + > + if (!grub_strlen (args[0])) > + return grub_error (GRUB_ERR_BAD_FILENAME, "missing trusted X.509 certificate file"); > + > + cert_file = grub_file_open (args[0], > + GRUB_FILE_TYPE_CERTIFICATE_TRUST | GRUB_FILE_TYPE_NO_DECOMPRESS); > + if (cert_file == NULL) > + return grub_error (GRUB_ERR_BAD_FILE_TYPE, "could not open %s file", args[0]); > + > + err = file_read_whole (cert_file, &cert_data, &cert_data_size); > + grub_file_close (cert_file); > + if (err != GRUB_ERR_NONE) > + return err; > + > + /* > + * If signature verification is enabled (check_sigs is set to true), obtain > + * the actual certificate size by subtracting the appended signature size from > + * the certificate size because the certificate has an appended signature, and > + * this actual certificate size is used to get the X.509 certificate. > + */ > + if (check_sigs == true) > + cert_data_size -= append_sig_len; > + > + err = add_certificate (cert_data, cert_data_size, &db); > + grub_free (cert_data); > + if (err != GRUB_ERR_NONE) > + return err; > + > + return GRUB_ERR_NONE; > +} > + > +/* > + * Remove the distrusted certificate from the db list if it is already present. > + * And add it to the dbx list if not present when dynamic key management is > + * enabled. > + * > + * Note: When signature verification is enabled, this command only accepts the > + * distrusted certificate that is signed with an appended signature. > + * The signature is verified by the appended sig module. If verification > + * succeeds, the certificate is removed from the db list. Otherwise, an error > + * is posted and the certificate is not removed. > + * When signature verification is disabled, it accepts the distrusted certificate > + * without an appended signature and removes it from the db list. > + * > + * Also, note that the removal of the distrusted certificate using this command > + * does not persist across reboots. > + */ > +static grub_err_t > +grub_cmd_dbx_cert (grub_command_t cmd __attribute__ ((unused)), int argc, char **args) > +{ > + grub_err_t err; > + grub_file_t cert_file; > + grub_uint8_t *cert_data = NULL; > + grub_size_t cert_data_size = 0; > + > + if (argc != 1) > + return grub_error (GRUB_ERR_BAD_ARGUMENT, > + "a distrusted X.509 certificate file is expected in DER format\n" > + "Example:\n\tappend_add_dbx_cert <X509_CERTIFICATE>\n"); > + > + if (!grub_strlen (args[0])) > + return grub_error (GRUB_ERR_BAD_FILENAME, "missing distrusted X.509 certificate file"); > + > + cert_file = grub_file_open (args[0], > + GRUB_FILE_TYPE_CERTIFICATE_TRUST | GRUB_FILE_TYPE_NO_DECOMPRESS); > + if (cert_file == NULL) > + return grub_error (GRUB_ERR_BAD_FILE_TYPE, "could not open %s file", args[0]); > + > + err = file_read_whole (cert_file, &cert_data, &cert_data_size); > + grub_file_close (cert_file); > + if (err != GRUB_ERR_NONE) > + return err; > + > + /* > + * If signature verification is enabled (check_sigs is set to true), obtain > + * the actual certificate size by subtracting the appended signature size from > + * the certificate size because the certificate has an appended signature, and > + * this actual certificate size is used to get the X.509 certificate. > + */ > + if (check_sigs == true) > + cert_data_size -= append_sig_len; > + > + /* Remove distrusted certificate from the db list if present. */ > + err = remove_cert_from_db (cert_data, cert_data_size); > + if (err != GRUB_ERR_NONE) > + { > + grub_free (cert_data); > + return err; > + } > + > + /* Only add the certificate to the dbx list if dynamic key management is enabled. */ > + if (append_key_mgmt == true) > + { > + err = add_certificate (cert_data, cert_data_size, &dbx); > + if (err != GRUB_ERR_NONE) > + return err; > + } > + > + grub_free (cert_data); > + > + return GRUB_ERR_NONE; > +} > + > +static grub_err_t > +grub_cmd_list_db (grub_command_t cmd __attribute__ ((unused)), int argc __attribute__ ((unused)), > + char **args __attribute__ ((unused))) > +{ > + struct x509_certificate *cert; > + grub_uint32_t i, cert_num = 1; > + > + for (cert = db.certs; cert != NULL; cert = cert->next, cert_num++) > + print_certificate (cert, cert_num); > + > + if (append_key_mgmt == false) > + return GRUB_ERR_NONE; > + > + for (i = 0; i < db.hash_entries; i++) > + { > + if (db.hashes[i] != NULL) > + { > + grub_printf ("\nBinary hash: %u\n", i + 1); > + grub_printf (" Hash: sha%" PRIuGRUB_SIZE "\n ", db.hash_sizes[i] * 8); > + hexdump_colon (db.hashes[i], db.hash_sizes[i]); > + } > + } > + > + return GRUB_ERR_NONE; > +} > + > /* Add the X.509 certificates/binary hash to the db list from PKS. */ > static grub_err_t > load_pks2db (void) > @@ -1032,6 +1337,8 @@ struct grub_file_verifier grub_appendedsig_verifier = { > .write = appendedsig_write, > }; > > +static grub_command_t cmd_verify, cmd_list_db, cmd_dbx_cert, cmd_db_cert; > + > GRUB_MOD_INIT (appendedsig) > { > grub_int32_t rc; > @@ -1101,6 +1408,15 @@ GRUB_MOD_INIT (appendedsig) > db.cert_entries); > } > > + cmd_verify = grub_register_command ("append_verify", grub_cmd_verify_signature, N_("<SIGNED_FILE>"), > + N_("Verify SIGNED_FILE against the trusted X.509 certificates in the db list")); > + cmd_list_db = grub_register_command ("append_list_db", grub_cmd_list_db, 0, > + N_("Show the list of trusted X.509 certificates from the db list")); > + cmd_db_cert = grub_register_command ("append_add_db_cert", grub_cmd_db_cert, N_("<X509_CERTIFICATE>"), > + N_("Add trusted X509_CERTIFICATE to the db list")); > + cmd_dbx_cert = grub_register_command ("append_add_dbx_cert", grub_cmd_dbx_cert, N_("<X509_CERTIFICATE>"), > + N_("Add distrusted X509_CERTIFICATE to the dbx list")); > + > grub_verifier_register (&grub_appendedsig_verifier); > grub_dl_set_persistent (mod); > } > @@ -1119,4 +1435,8 @@ GRUB_MOD_FINI (appendedsig) > grub_register_variable_hook ("appendedsig_key_mgmt", NULL, NULL); > grub_env_unset ("appendedsig_key_mgmt"); > grub_verifier_unregister (&grub_appendedsig_verifier); > + grub_unregister_command (cmd_verify); > + grub_unregister_command (cmd_list_db); > + grub_unregister_command (cmd_db_cert); > + grub_unregister_command (cmd_dbx_cert); > } Tested-by: Sridhar Markonda <sridharm@linux.ibm.com> _______________________________________________ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel ^ permalink raw reply [flat|nested] 25+ messages in thread
* [PATCH v13 16/20] appended signatures: GRUB commands to manage the hashes 2025-09-30 11:39 [PATCH v13 00/20] Appended Signature Secure Boot Support for PowerPC Sudhakar Kuppusamy ` (14 preceding siblings ...) 2025-09-30 11:40 ` [PATCH v13 15/20] appended signatures: GRUB commands to manage the certificates Sudhakar Kuppusamy @ 2025-09-30 11:40 ` Sudhakar Kuppusamy 2025-10-01 9:09 ` Sridhar Markonda 2025-09-30 11:40 ` [PATCH v13 17/20] appended signatures: Verification tests Sudhakar Kuppusamy ` (4 subsequent siblings) 20 siblings, 1 reply; 25+ messages in thread From: Sudhakar Kuppusamy @ 2025-09-30 11:40 UTC (permalink / raw) To: grub-devel Cc: dja, jan.setjeeilers, julian.klode, mate.kukri, pjones, msuchanek, mlewando, stefanb, avnish, nayna, ssrish, Sudhakar Kuppusamy, sridharm, Daniel Kiper Introducing the following GRUB commands to manage certificate/binary hashes. 1. append_list_dbx: Show the list of distrusted certificates and binary/certificate hashes from the dbx list. 2. append_add_db_hash: Add the trusted binary hash to the db list. 3. append_add_dbx_hash: Add the distrusted certificate/binary hash to the dbx list. Note that if signature verification (check_appended_signatures) is set to yes, the append_add_db_hash and append_add_dbx_hash commands only accept the file ‘hash_file’ that is signed with an appended signature. Signed-off-by: Sudhakar Kuppusamy <sudhakar@linux.ibm.com> Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com> --- grub-core/commands/appendedsig/appendedsig.c | 281 +++++++++++++++++++ include/grub/file.h | 2 + 2 files changed, 283 insertions(+) diff --git a/grub-core/commands/appendedsig/appendedsig.c b/grub-core/commands/appendedsig/appendedsig.c index d04aaf1e2..7f4676022 100644 --- a/grub-core/commands/appendedsig/appendedsig.c +++ b/grub-core/commands/appendedsig/appendedsig.c @@ -52,6 +52,9 @@ GRUB_MOD_LICENSE ("GPLv3+"); #define SHA384_HASH_SIZE 48 #define SHA512_HASH_SIZE 64 +#define OPTION_BINARY_HASH 0 +#define OPTION_CERT_HASH 1 + /* * This structure is extracted from scripts/sign-file.c in the linux kernel * source. It was licensed as LGPLv2.1+, which is GPLv3+ compatible. @@ -126,6 +129,13 @@ static grub_pks_t *pks_keystore; /* Appended signature size. */ static grub_size_t append_sig_len = 0; +static const struct grub_arg_option options[] = +{ + {"binary-hash", 'b', 0, N_("hash file of the binary."), 0, ARG_TYPE_PATHNAME}, + {"cert-hash", 'c', 1, N_("hash file of the certificate."), 0, ARG_TYPE_PATHNAME}, + {0, 0, 0, 0, 0, 0} +}; + static grub_ssize_t pseudo_read (struct grub_file *file, char *buf, grub_size_t len) { @@ -546,6 +556,69 @@ remove_cert_from_db (const grub_uint8_t *data, const grub_size_t data_size) return rc; } +static bool +cert_fingerprint_match (const grub_uint8_t *hash_data, const grub_size_t hash_data_size, + const grub_x509_cert_t *cert) +{ + grub_int32_t type; + + if (hash_data_size == SHA256_HASH_SIZE) + type = GRUB_FINGERPRINT_SHA256; + else if (hash_data_size == SHA384_HASH_SIZE) + type = GRUB_FINGERPRINT_SHA384; + else if (hash_data_size == SHA512_HASH_SIZE) + type = GRUB_FINGERPRINT_SHA512; + else + { + grub_dprintf ("appendedsig", "unsupported fingerprint hash type " + "(%" PRIuGRUB_SIZE ") \n", hash_data_size); + return false; + } + + if (grub_memcmp (cert->fingerprint[type], hash_data, hash_data_size) == 0) + return true; + + return false; +} + +static void +remove_hash_from_db (const grub_uint8_t *hash_data, const grub_size_t hash_data_size, + const bool bin_hash) +{ + grub_uint32_t i; + grub_x509_cert_t *cert; + + if (bin_hash == true) + { + for (i = 0; i < db.hash_entries; i++) + { + if (db.hashes[i] == NULL) + continue; + + if (grub_memcmp (db.hashes[i], hash_data, hash_data_size) == 0) + { + grub_dprintf ("appendedsig", "removed distrusted hash %02x%02x%02x%02x.. from the db list\n", + db.hashes[i][0], db.hashes[i][1], db.hashes[i][2], db.hashes[i][3]); + grub_free (db.hashes[i]); + db.hashes[i] = NULL; + db.hash_sizes[i] = 0; + break; + } + } + } + else + { + for (cert = db.certs; cert != NULL; cert = cert->next) + { + if (cert_fingerprint_match (hash_data, hash_data_size, cert) == true) + { + _remove_cert_from_db (cert); + break; + } + } + } +} + static grub_err_t file_read_whole (grub_file_t file, grub_uint8_t **buf, grub_size_t *len) { @@ -1014,6 +1087,194 @@ grub_cmd_list_db (grub_command_t cmd __attribute__ ((unused)), int argc __attrib return GRUB_ERR_NONE; } +static grub_err_t +grub_cmd_list_dbx (grub_command_t cmd __attribute__((unused)), + int argc __attribute__((unused)), char **args __attribute__((unused))) +{ + struct x509_certificate *cert; + grub_uint32_t i, cert_num = 1; + + if (append_key_mgmt == false) + return grub_error (GRUB_ERR_ACCESS_DENIED, + "append_list_dbx command is unsupported in static key mode"); + + for (cert = dbx.certs; cert != NULL; cert = cert->next, cert_num++) + print_certificate (cert, cert_num); + + for (i = 0; i < dbx.hash_entries; i++) + { + if (dbx.hashes[i] != NULL) + { + grub_printf ("\nCertificate/Binary hash: %u\n", i + 1); + grub_printf (" Hash: sha%" PRIuGRUB_SIZE "\n ", dbx.hash_sizes[i] * 8); + hexdump_colon (dbx.hashes[i], dbx.hash_sizes[i]); + } + } + + return GRUB_ERR_NONE; +} + +/* + * Remove the trusted binary hash from the dbx list if present. And add them to + * the db list if it is not already present. + * + * Note: When signature verification is enabled, this command only accepts the + * binary hash file that is signed with an appended signature. The signature is + * verified by the appendedsig module. If verification succeeds, the binary hash + * is added to the db list. Otherwise, an error is posted and the binary hash is + * not added. + * When signature verification is disabled, it accepts the binary hash file + * without an appended signature and adds it to the db list. + * + * Also, note that the adding of the trusted binary hash using this command does + * not persist across reboots. + */ +static grub_err_t +grub_cmd_add_db_hash (grub_command_t cmd __attribute__((unused)), int argc, char**args) +{ + grub_err_t rc; + grub_file_t hash_file; + grub_uint8_t *hash_data = NULL; + grub_size_t hash_data_size = 0; + + if (append_key_mgmt == false) + return grub_error (GRUB_ERR_ACCESS_DENIED, + "append_add_db_hash command is unsupported in static key mode"); + + if (argc != 1) + return grub_error (GRUB_ERR_BAD_ARGUMENT, + "a trusted binary hash file is expected in binary format\n" + "Example:\n\tappend_add_db_hash <BINARY HASH FILE>\n"); + + if (!grub_strlen (args[0])) + return grub_error (GRUB_ERR_BAD_FILENAME, "missing trusted binary hash file"); + + hash_file = grub_file_open (args[0], GRUB_FILE_TYPE_HASH_TRUST | GRUB_FILE_TYPE_NO_DECOMPRESS); + if (hash_file == NULL) + return grub_error (GRUB_ERR_FILE_NOT_FOUND, "unable to open %s file", args[0]); + + rc = file_read_whole (hash_file, &hash_data, &hash_data_size); + grub_file_close (hash_file); + if (rc != GRUB_ERR_NONE) + return rc; + + /* + * If signature verification is enabled (check_sigs is set to true), obtain + * the actual hash data size by subtracting the appended signature size from + * the hash data size because the hash has an appended signature, and this + * actual hash data size is used to get the hash data. + */ + if (check_sigs == true) + hash_data_size -= append_sig_len; + + grub_dprintf ("appendedsig", + "adding a trusted binary hash %02x%02x%02x%02x... with size of %" PRIuGRUB_SIZE "\n", + hash_data[0], hash_data[1], hash_data[2], hash_data[3], hash_data_size); + + /* Only accept SHA256, SHA384 and SHA512 binary hash */ + if (hash_data_size != SHA256_HASH_SIZE && hash_data_size != SHA384_HASH_SIZE && + hash_data_size != SHA512_HASH_SIZE) + { + grub_free (hash_data); + return grub_error (GRUB_ERR_BAD_SIGNATURE, "unacceptable trusted binary hash type"); + } + + rc = add_hash (hash_data, hash_data_size, &db); + + grub_free (hash_data); + + return rc; +} + +/* + * Remove the distrusted binary/certificate hash from the db list if present. + * And add them to the dbx list if it is not already present. + * + * Note: When signature verification is enabled, this command only accepts the + * binary/certificate hash file that is signed with an appended signature. The + * signature is verified by the appendedsig module. If verification succeeds, + * the binary/certificate hash is added to the dbx list. Otherwise, an error is + * posted and the binary/certificate hash is not added. + * When signature verification is disabled, it accepts the binary/certificate + * hash file without an appended signature and adds it to the dbx list. + * + * Also, note that the adding of the distrusted binary/certificate hash using + * this command does not persist across reboots. + */ +static grub_err_t +grub_cmd_add_dbx_hash (grub_extcmd_context_t ctxt, int argc __attribute__ ((unused)), + char **args __attribute__ ((unused))) +{ + grub_err_t rc; + grub_file_t hash_file; + grub_uint8_t *hash_data = NULL; + grub_size_t hash_data_size = 0; + char *file_path; + + if (append_key_mgmt == false) + return grub_error (GRUB_ERR_ACCESS_DENIED, + "append_add_dbx_hash command is unsupported in static key mode"); + + if (!ctxt->state[OPTION_BINARY_HASH].set && !ctxt->state[OPTION_CERT_HASH].set) + return grub_error (GRUB_ERR_BAD_ARGUMENT, + "a distrusted certificate/binary hash file is expected in binary format\n" + "Example:\n\tappend_add_dbx_hash [option] <FILE>\n" + "option:\n[-b|--binary-hash] FILE [BINARY HASH FILE]\n" + "[-c|--cert-hash] FILE [CERTFICATE HASH FILE]\n"); + + if (ctxt->state[OPTION_BINARY_HASH].arg == NULL && ctxt->state[OPTION_CERT_HASH].arg == NULL) + return grub_error (GRUB_ERR_BAD_FILENAME, "missing distrusted certificate/binary hash file"); + + if (ctxt->state[OPTION_BINARY_HASH].arg != NULL) + file_path = ctxt->state[OPTION_BINARY_HASH].arg; + else + file_path = ctxt->state[OPTION_CERT_HASH].arg; + + hash_file = grub_file_open (file_path, GRUB_FILE_TYPE_HASH_TRUST | GRUB_FILE_TYPE_NO_DECOMPRESS); + if (hash_file == NULL) + return grub_error (GRUB_ERR_FILE_NOT_FOUND, "unable to open %s file", file_path); + + rc = file_read_whole (hash_file, &hash_data, &hash_data_size); + grub_file_close (hash_file); + if (rc != GRUB_ERR_NONE) + return rc; + + /* + * If signature verification is enabled (check_sigs is set to true), obtain + * the actual hash data size by subtracting the appended signature size from + * the hash data size because the hash has an appended signature, and this + * actual hash data size is used to get the hash data. + */ + if (check_sigs == true) + hash_data_size -= append_sig_len; + + grub_dprintf ("appendedsig", + "adding a distrusted certificate/binary hash %02x%02x%02x%02x..." + " with size of %" PRIuGRUB_SIZE "\n", hash_data[0], hash_data[1], + hash_data[2], hash_data[3], hash_data_size); + + if (ctxt->state[OPTION_BINARY_HASH].set || ctxt->state[OPTION_CERT_HASH].set) + { + /* Only accept SHA256, SHA384 and SHA512 certificate/binary hash */ + if (hash_data_size != SHA256_HASH_SIZE && hash_data_size != SHA384_HASH_SIZE && + hash_data_size != SHA512_HASH_SIZE) + { + grub_free (hash_data); + return grub_error (GRUB_ERR_BAD_SIGNATURE, + "unacceptable distrusted certificate/binary hash type"); + } + } + + /* Remove distrusted binary hash/certificate from the db list if present. */ + remove_hash_from_db (hash_data, hash_data_size, + ((ctxt->state[OPTION_BINARY_HASH].set) ? true : false)); + rc = add_hash (hash_data, hash_data_size, &dbx); + + grub_free (hash_data); + + return rc; +} + /* Add the X.509 certificates/binary hash to the db list from PKS. */ static grub_err_t load_pks2db (void) @@ -1297,6 +1558,11 @@ appendedsig_init (grub_file_t io __attribute__ ((unused)), enum grub_file_type t * verifier, but we lack the hubris required to take this on. Instead, * require that it have an appended signature. */ + case GRUB_FILE_TYPE_HASH_TRUST: + /* + * This is a certificate/binary hash to add to db/dbx. This needs to be + * verified or blocked. + */ case GRUB_FILE_TYPE_LINUX_KERNEL: case GRUB_FILE_TYPE_GRUB_MODULE: /* @@ -1338,6 +1604,8 @@ struct grub_file_verifier grub_appendedsig_verifier = { }; static grub_command_t cmd_verify, cmd_list_db, cmd_dbx_cert, cmd_db_cert; +static grub_command_t cmd_list_dbx, cmd_db_hash; +static grub_extcmd_t cmd_dbx_hash; GRUB_MOD_INIT (appendedsig) { @@ -1417,6 +1685,16 @@ GRUB_MOD_INIT (appendedsig) cmd_dbx_cert = grub_register_command ("append_add_dbx_cert", grub_cmd_dbx_cert, N_("<X509_CERTIFICATE>"), N_("Add distrusted X509_CERTIFICATE to the dbx list")); + cmd_list_dbx = grub_register_command ("append_list_dbx", grub_cmd_list_dbx, 0, + N_("Show the list of distrusted certificates and" + " certificate/binary hashes from the dbx list")); + cmd_db_hash = grub_register_command ("append_add_db_hash", grub_cmd_add_db_hash, N_("BINARY HASH FILE"), + N_("Add trusted BINARY HASH to the db list.")); + cmd_dbx_hash = grub_register_extcmd ("append_add_dbx_hash", grub_cmd_add_dbx_hash, 0, + N_("[-b|--binary-hash] FILE [BINARY HASH FILE]\n" + "[-c|--cert-hash] FILE [CERTFICATE HASH FILE]"), + N_("Add distrusted CERTFICATE/BINARY HASH to the dbx list."), options); + grub_verifier_register (&grub_appendedsig_verifier); grub_dl_set_persistent (mod); } @@ -1439,4 +1717,7 @@ GRUB_MOD_FINI (appendedsig) grub_unregister_command (cmd_list_db); grub_unregister_command (cmd_db_cert); grub_unregister_command (cmd_dbx_cert); + grub_unregister_command (cmd_list_dbx); + grub_unregister_command (cmd_db_hash); + grub_unregister_extcmd (cmd_dbx_hash); } diff --git a/include/grub/file.h b/include/grub/file.h index d678de063..16a4b7d26 100644 --- a/include/grub/file.h +++ b/include/grub/file.h @@ -115,6 +115,8 @@ enum grub_file_type GRUB_FILE_TYPE_HASHLIST, /* File hashed by hashsum. */ GRUB_FILE_TYPE_TO_HASH, + /* File holding certificiate/binary hash to add to db/dbx. */ + GRUB_FILE_TYPE_HASH_TRUST, /* Keyboard layout. */ GRUB_FILE_TYPE_KEYBOARD_LAYOUT, /* Picture file. */ -- 2.50.1 (Apple Git-155) _______________________________________________ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel ^ permalink raw reply related [flat|nested] 25+ messages in thread
* Re: [PATCH v13 16/20] appended signatures: GRUB commands to manage the hashes 2025-09-30 11:40 ` [PATCH v13 16/20] appended signatures: GRUB commands to manage the hashes Sudhakar Kuppusamy @ 2025-10-01 9:09 ` Sridhar Markonda 0 siblings, 0 replies; 25+ messages in thread From: Sridhar Markonda @ 2025-10-01 9:09 UTC (permalink / raw) To: Sudhakar Kuppusamy, grub-devel Cc: dja, jan.setjeeilers, julian.klode, mate.kukri, pjones, msuchanek, mlewando, stefanb, avnish, nayna, ssrish, Daniel Kiper On 30/09/25 5:10 pm, Sudhakar Kuppusamy wrote: > Introducing the following GRUB commands to manage certificate/binary > hashes. > > 1. append_list_dbx: > Show the list of distrusted certificates and binary/certificate > hashes from the dbx list. > 2. append_add_db_hash: > Add the trusted binary hash to the db list. > 3. append_add_dbx_hash: > Add the distrusted certificate/binary hash to the dbx list. > > Note that if signature verification (check_appended_signatures) is set to yes, > the append_add_db_hash and append_add_dbx_hash commands only accept the file > ‘hash_file’ that is signed with an appended signature. > > Signed-off-by: Sudhakar Kuppusamy <sudhakar@linux.ibm.com> > Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com> > --- > grub-core/commands/appendedsig/appendedsig.c | 281 +++++++++++++++++++ > include/grub/file.h | 2 + > 2 files changed, 283 insertions(+) > > diff --git a/grub-core/commands/appendedsig/appendedsig.c b/grub-core/commands/appendedsig/appendedsig.c > index d04aaf1e2..7f4676022 100644 > --- a/grub-core/commands/appendedsig/appendedsig.c > +++ b/grub-core/commands/appendedsig/appendedsig.c > @@ -52,6 +52,9 @@ GRUB_MOD_LICENSE ("GPLv3+"); > #define SHA384_HASH_SIZE 48 > #define SHA512_HASH_SIZE 64 > > +#define OPTION_BINARY_HASH 0 > +#define OPTION_CERT_HASH 1 > + > /* > * This structure is extracted from scripts/sign-file.c in the linux kernel > * source. It was licensed as LGPLv2.1+, which is GPLv3+ compatible. > @@ -126,6 +129,13 @@ static grub_pks_t *pks_keystore; > /* Appended signature size. */ > static grub_size_t append_sig_len = 0; > > +static const struct grub_arg_option options[] = > +{ > + {"binary-hash", 'b', 0, N_("hash file of the binary."), 0, ARG_TYPE_PATHNAME}, > + {"cert-hash", 'c', 1, N_("hash file of the certificate."), 0, ARG_TYPE_PATHNAME}, > + {0, 0, 0, 0, 0, 0} > +}; > + > static grub_ssize_t > pseudo_read (struct grub_file *file, char *buf, grub_size_t len) > { > @@ -546,6 +556,69 @@ remove_cert_from_db (const grub_uint8_t *data, const grub_size_t data_size) > return rc; > } > > +static bool > +cert_fingerprint_match (const grub_uint8_t *hash_data, const grub_size_t hash_data_size, > + const grub_x509_cert_t *cert) > +{ > + grub_int32_t type; > + > + if (hash_data_size == SHA256_HASH_SIZE) > + type = GRUB_FINGERPRINT_SHA256; > + else if (hash_data_size == SHA384_HASH_SIZE) > + type = GRUB_FINGERPRINT_SHA384; > + else if (hash_data_size == SHA512_HASH_SIZE) > + type = GRUB_FINGERPRINT_SHA512; > + else > + { > + grub_dprintf ("appendedsig", "unsupported fingerprint hash type " > + "(%" PRIuGRUB_SIZE ") \n", hash_data_size); > + return false; > + } > + > + if (grub_memcmp (cert->fingerprint[type], hash_data, hash_data_size) == 0) > + return true; > + > + return false; > +} > + > +static void > +remove_hash_from_db (const grub_uint8_t *hash_data, const grub_size_t hash_data_size, > + const bool bin_hash) > +{ > + grub_uint32_t i; > + grub_x509_cert_t *cert; > + > + if (bin_hash == true) > + { > + for (i = 0; i < db.hash_entries; i++) > + { > + if (db.hashes[i] == NULL) > + continue; > + > + if (grub_memcmp (db.hashes[i], hash_data, hash_data_size) == 0) > + { > + grub_dprintf ("appendedsig", "removed distrusted hash %02x%02x%02x%02x.. from the db list\n", > + db.hashes[i][0], db.hashes[i][1], db.hashes[i][2], db.hashes[i][3]); > + grub_free (db.hashes[i]); > + db.hashes[i] = NULL; > + db.hash_sizes[i] = 0; > + break; > + } > + } > + } > + else > + { > + for (cert = db.certs; cert != NULL; cert = cert->next) > + { > + if (cert_fingerprint_match (hash_data, hash_data_size, cert) == true) > + { > + _remove_cert_from_db (cert); > + break; > + } > + } > + } > +} > + > static grub_err_t > file_read_whole (grub_file_t file, grub_uint8_t **buf, grub_size_t *len) > { > @@ -1014,6 +1087,194 @@ grub_cmd_list_db (grub_command_t cmd __attribute__ ((unused)), int argc __attrib > return GRUB_ERR_NONE; > } > > +static grub_err_t > +grub_cmd_list_dbx (grub_command_t cmd __attribute__((unused)), > + int argc __attribute__((unused)), char **args __attribute__((unused))) > +{ > + struct x509_certificate *cert; > + grub_uint32_t i, cert_num = 1; > + > + if (append_key_mgmt == false) > + return grub_error (GRUB_ERR_ACCESS_DENIED, > + "append_list_dbx command is unsupported in static key mode"); > + > + for (cert = dbx.certs; cert != NULL; cert = cert->next, cert_num++) > + print_certificate (cert, cert_num); > + > + for (i = 0; i < dbx.hash_entries; i++) > + { > + if (dbx.hashes[i] != NULL) > + { > + grub_printf ("\nCertificate/Binary hash: %u\n", i + 1); > + grub_printf (" Hash: sha%" PRIuGRUB_SIZE "\n ", dbx.hash_sizes[i] * 8); > + hexdump_colon (dbx.hashes[i], dbx.hash_sizes[i]); > + } > + } > + > + return GRUB_ERR_NONE; > +} > + > +/* > + * Remove the trusted binary hash from the dbx list if present. And add them to > + * the db list if it is not already present. > + * > + * Note: When signature verification is enabled, this command only accepts the > + * binary hash file that is signed with an appended signature. The signature is > + * verified by the appendedsig module. If verification succeeds, the binary hash > + * is added to the db list. Otherwise, an error is posted and the binary hash is > + * not added. > + * When signature verification is disabled, it accepts the binary hash file > + * without an appended signature and adds it to the db list. > + * > + * Also, note that the adding of the trusted binary hash using this command does > + * not persist across reboots. > + */ > +static grub_err_t > +grub_cmd_add_db_hash (grub_command_t cmd __attribute__((unused)), int argc, char**args) > +{ > + grub_err_t rc; > + grub_file_t hash_file; > + grub_uint8_t *hash_data = NULL; > + grub_size_t hash_data_size = 0; > + > + if (append_key_mgmt == false) > + return grub_error (GRUB_ERR_ACCESS_DENIED, > + "append_add_db_hash command is unsupported in static key mode"); > + > + if (argc != 1) > + return grub_error (GRUB_ERR_BAD_ARGUMENT, > + "a trusted binary hash file is expected in binary format\n" > + "Example:\n\tappend_add_db_hash <BINARY HASH FILE>\n"); > + > + if (!grub_strlen (args[0])) > + return grub_error (GRUB_ERR_BAD_FILENAME, "missing trusted binary hash file"); > + > + hash_file = grub_file_open (args[0], GRUB_FILE_TYPE_HASH_TRUST | GRUB_FILE_TYPE_NO_DECOMPRESS); > + if (hash_file == NULL) > + return grub_error (GRUB_ERR_FILE_NOT_FOUND, "unable to open %s file", args[0]); > + > + rc = file_read_whole (hash_file, &hash_data, &hash_data_size); > + grub_file_close (hash_file); > + if (rc != GRUB_ERR_NONE) > + return rc; > + > + /* > + * If signature verification is enabled (check_sigs is set to true), obtain > + * the actual hash data size by subtracting the appended signature size from > + * the hash data size because the hash has an appended signature, and this > + * actual hash data size is used to get the hash data. > + */ > + if (check_sigs == true) > + hash_data_size -= append_sig_len; > + > + grub_dprintf ("appendedsig", > + "adding a trusted binary hash %02x%02x%02x%02x... with size of %" PRIuGRUB_SIZE "\n", > + hash_data[0], hash_data[1], hash_data[2], hash_data[3], hash_data_size); > + > + /* Only accept SHA256, SHA384 and SHA512 binary hash */ > + if (hash_data_size != SHA256_HASH_SIZE && hash_data_size != SHA384_HASH_SIZE && > + hash_data_size != SHA512_HASH_SIZE) > + { > + grub_free (hash_data); > + return grub_error (GRUB_ERR_BAD_SIGNATURE, "unacceptable trusted binary hash type"); > + } > + > + rc = add_hash (hash_data, hash_data_size, &db); > + > + grub_free (hash_data); > + > + return rc; > +} > + > +/* > + * Remove the distrusted binary/certificate hash from the db list if present. > + * And add them to the dbx list if it is not already present. > + * > + * Note: When signature verification is enabled, this command only accepts the > + * binary/certificate hash file that is signed with an appended signature. The > + * signature is verified by the appendedsig module. If verification succeeds, > + * the binary/certificate hash is added to the dbx list. Otherwise, an error is > + * posted and the binary/certificate hash is not added. > + * When signature verification is disabled, it accepts the binary/certificate > + * hash file without an appended signature and adds it to the dbx list. > + * > + * Also, note that the adding of the distrusted binary/certificate hash using > + * this command does not persist across reboots. > + */ > +static grub_err_t > +grub_cmd_add_dbx_hash (grub_extcmd_context_t ctxt, int argc __attribute__ ((unused)), > + char **args __attribute__ ((unused))) > +{ > + grub_err_t rc; > + grub_file_t hash_file; > + grub_uint8_t *hash_data = NULL; > + grub_size_t hash_data_size = 0; > + char *file_path; > + > + if (append_key_mgmt == false) > + return grub_error (GRUB_ERR_ACCESS_DENIED, > + "append_add_dbx_hash command is unsupported in static key mode"); > + > + if (!ctxt->state[OPTION_BINARY_HASH].set && !ctxt->state[OPTION_CERT_HASH].set) > + return grub_error (GRUB_ERR_BAD_ARGUMENT, > + "a distrusted certificate/binary hash file is expected in binary format\n" > + "Example:\n\tappend_add_dbx_hash [option] <FILE>\n" > + "option:\n[-b|--binary-hash] FILE [BINARY HASH FILE]\n" > + "[-c|--cert-hash] FILE [CERTFICATE HASH FILE]\n"); > + > + if (ctxt->state[OPTION_BINARY_HASH].arg == NULL && ctxt->state[OPTION_CERT_HASH].arg == NULL) > + return grub_error (GRUB_ERR_BAD_FILENAME, "missing distrusted certificate/binary hash file"); > + > + if (ctxt->state[OPTION_BINARY_HASH].arg != NULL) > + file_path = ctxt->state[OPTION_BINARY_HASH].arg; > + else > + file_path = ctxt->state[OPTION_CERT_HASH].arg; > + > + hash_file = grub_file_open (file_path, GRUB_FILE_TYPE_HASH_TRUST | GRUB_FILE_TYPE_NO_DECOMPRESS); > + if (hash_file == NULL) > + return grub_error (GRUB_ERR_FILE_NOT_FOUND, "unable to open %s file", file_path); > + > + rc = file_read_whole (hash_file, &hash_data, &hash_data_size); > + grub_file_close (hash_file); > + if (rc != GRUB_ERR_NONE) > + return rc; > + > + /* > + * If signature verification is enabled (check_sigs is set to true), obtain > + * the actual hash data size by subtracting the appended signature size from > + * the hash data size because the hash has an appended signature, and this > + * actual hash data size is used to get the hash data. > + */ > + if (check_sigs == true) > + hash_data_size -= append_sig_len; > + > + grub_dprintf ("appendedsig", > + "adding a distrusted certificate/binary hash %02x%02x%02x%02x..." > + " with size of %" PRIuGRUB_SIZE "\n", hash_data[0], hash_data[1], > + hash_data[2], hash_data[3], hash_data_size); > + > + if (ctxt->state[OPTION_BINARY_HASH].set || ctxt->state[OPTION_CERT_HASH].set) > + { > + /* Only accept SHA256, SHA384 and SHA512 certificate/binary hash */ > + if (hash_data_size != SHA256_HASH_SIZE && hash_data_size != SHA384_HASH_SIZE && > + hash_data_size != SHA512_HASH_SIZE) > + { > + grub_free (hash_data); > + return grub_error (GRUB_ERR_BAD_SIGNATURE, > + "unacceptable distrusted certificate/binary hash type"); > + } > + } > + > + /* Remove distrusted binary hash/certificate from the db list if present. */ > + remove_hash_from_db (hash_data, hash_data_size, > + ((ctxt->state[OPTION_BINARY_HASH].set) ? true : false)); > + rc = add_hash (hash_data, hash_data_size, &dbx); > + > + grub_free (hash_data); > + > + return rc; > +} > + > /* Add the X.509 certificates/binary hash to the db list from PKS. */ > static grub_err_t > load_pks2db (void) > @@ -1297,6 +1558,11 @@ appendedsig_init (grub_file_t io __attribute__ ((unused)), enum grub_file_type t > * verifier, but we lack the hubris required to take this on. Instead, > * require that it have an appended signature. > */ > + case GRUB_FILE_TYPE_HASH_TRUST: > + /* > + * This is a certificate/binary hash to add to db/dbx. This needs to be > + * verified or blocked. > + */ > case GRUB_FILE_TYPE_LINUX_KERNEL: > case GRUB_FILE_TYPE_GRUB_MODULE: > /* > @@ -1338,6 +1604,8 @@ struct grub_file_verifier grub_appendedsig_verifier = { > }; > > static grub_command_t cmd_verify, cmd_list_db, cmd_dbx_cert, cmd_db_cert; > +static grub_command_t cmd_list_dbx, cmd_db_hash; > +static grub_extcmd_t cmd_dbx_hash; > > GRUB_MOD_INIT (appendedsig) > { > @@ -1417,6 +1685,16 @@ GRUB_MOD_INIT (appendedsig) > cmd_dbx_cert = grub_register_command ("append_add_dbx_cert", grub_cmd_dbx_cert, N_("<X509_CERTIFICATE>"), > N_("Add distrusted X509_CERTIFICATE to the dbx list")); > > + cmd_list_dbx = grub_register_command ("append_list_dbx", grub_cmd_list_dbx, 0, > + N_("Show the list of distrusted certificates and" > + " certificate/binary hashes from the dbx list")); > + cmd_db_hash = grub_register_command ("append_add_db_hash", grub_cmd_add_db_hash, N_("BINARY HASH FILE"), > + N_("Add trusted BINARY HASH to the db list.")); > + cmd_dbx_hash = grub_register_extcmd ("append_add_dbx_hash", grub_cmd_add_dbx_hash, 0, > + N_("[-b|--binary-hash] FILE [BINARY HASH FILE]\n" > + "[-c|--cert-hash] FILE [CERTFICATE HASH FILE]"), > + N_("Add distrusted CERTFICATE/BINARY HASH to the dbx list."), options); > + > grub_verifier_register (&grub_appendedsig_verifier); > grub_dl_set_persistent (mod); > } > @@ -1439,4 +1717,7 @@ GRUB_MOD_FINI (appendedsig) > grub_unregister_command (cmd_list_db); > grub_unregister_command (cmd_db_cert); > grub_unregister_command (cmd_dbx_cert); > + grub_unregister_command (cmd_list_dbx); > + grub_unregister_command (cmd_db_hash); > + grub_unregister_extcmd (cmd_dbx_hash); > } > diff --git a/include/grub/file.h b/include/grub/file.h > index d678de063..16a4b7d26 100644 > --- a/include/grub/file.h > +++ b/include/grub/file.h > @@ -115,6 +115,8 @@ enum grub_file_type > GRUB_FILE_TYPE_HASHLIST, > /* File hashed by hashsum. */ > GRUB_FILE_TYPE_TO_HASH, > + /* File holding certificiate/binary hash to add to db/dbx. */ > + GRUB_FILE_TYPE_HASH_TRUST, > /* Keyboard layout. */ > GRUB_FILE_TYPE_KEYBOARD_LAYOUT, > /* Picture file. */ Tested-by: Sridhar Markonda <sridharm@linux.ibm.com> _______________________________________________ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel ^ permalink raw reply [flat|nested] 25+ messages in thread
* [PATCH v13 17/20] appended signatures: Verification tests 2025-09-30 11:39 [PATCH v13 00/20] Appended Signature Secure Boot Support for PowerPC Sudhakar Kuppusamy ` (15 preceding siblings ...) 2025-09-30 11:40 ` [PATCH v13 16/20] appended signatures: GRUB commands to manage the hashes Sudhakar Kuppusamy @ 2025-09-30 11:40 ` Sudhakar Kuppusamy 2025-09-30 11:40 ` [PATCH v13 18/20] docs/grub: Document signing GRUB under UEFI Sudhakar Kuppusamy ` (3 subsequent siblings) 20 siblings, 0 replies; 25+ messages in thread From: Sudhakar Kuppusamy @ 2025-09-30 11:40 UTC (permalink / raw) To: grub-devel Cc: dja, jan.setjeeilers, julian.klode, mate.kukri, pjones, msuchanek, mlewando, stefanb, avnish, nayna, ssrish, Sudhakar Kuppusamy, sridharm, Daniel Kiper These tests are run through all_functional_test and test a range of commands and behaviours. 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> --- grub-core/Makefile.core.def | 8 + grub-core/tests/appended_signature_test.c | 348 ++++++++ grub-core/tests/appended_signatures.h | 975 ++++++++++++++++++++++ grub-core/tests/lib/functional_test.c | 1 + 4 files changed, 1332 insertions(+) create mode 100644 grub-core/tests/appended_signature_test.c create mode 100644 grub-core/tests/appended_signatures.h diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index 853d879a4..a729cb6a8 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -2231,6 +2231,14 @@ module = { cppflags = '$(CPPFLAGS_GCRY)'; }; +module = { + name = appended_signature_test; + common = tests/appended_signature_test.c; + common = tests/appended_signatures.h; + enable = emu; + enable = powerpc_ieee1275; +}; + module = { name = signature_test; common = tests/signature_test.c; diff --git a/grub-core/tests/appended_signature_test.c b/grub-core/tests/appended_signature_test.c new file mode 100644 index 000000000..2130008bc --- /dev/null +++ b/grub-core/tests/appended_signature_test.c @@ -0,0 +1,348 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2020, 2022 Free Software Foundation, Inc. + * Copyright (C) 2020, 2022, 2025 IBM Corporation + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <grub/time.h> +#include <grub/misc.h> +#include <grub/dl.h> +#include <grub/command.h> +#include <grub/env.h> +#include <grub/test.h> +#include <grub/mm.h> +#include <grub/procfs.h> +#include <grub/file.h> + +#include "appended_signatures.h" + +GRUB_MOD_LICENSE ("GPLv3+"); + +#define PROC_FILE(identifier, file_name) \ + static char *get_##identifier (grub_size_t *sz) \ + { \ + char *ret; \ + \ + *sz = identifier##_len; \ + ret = grub_malloc (*sz); \ + if (ret != NULL) \ + grub_memcpy (ret, identifier, *sz); \ + return ret; \ + } \ + \ + static struct grub_procfs_entry identifier##_entry = { .name = file_name, \ + .get_contents = get_##identifier }; + +#define DEFINE_TEST_CASE(case_name) PROC_FILE (case_name, #case_name) + +#define DO_TEST(case_name, is_valid) \ + { \ + grub_procfs_register (#case_name, &case_name##_entry); \ + do_verify ("(proc)/" #case_name, is_valid); \ + grub_procfs_unregister (&case_name##_entry); \ + } + +DEFINE_TEST_CASE (hi_signed); +DEFINE_TEST_CASE (hi_signed_sha256); +DEFINE_TEST_CASE (hj_signed); +DEFINE_TEST_CASE (short_msg); +DEFINE_TEST_CASE (unsigned_msg); +DEFINE_TEST_CASE (hi_signed_2nd); +DEFINE_TEST_CASE (hi_double); +DEFINE_TEST_CASE (hi_double_extended); + +PROC_FILE (certificate_der, "certificate.der") +PROC_FILE (certificate2_der, "certificate2.der") +PROC_FILE (certificate_printable_der, "certificate_printable.der") +PROC_FILE (certificate_eku_der, "certificate_eku.der") + +static void +do_verify (const char *f, int is_valid) +{ + grub_command_t cmd; + char *args[] = { (char *) f, NULL }; + grub_err_t err; + + cmd = grub_command_find ("append_verify"); + if (cmd == NULL) + { + grub_test_assert (0, "can't find command `%s'", "append_verify"); + return; + } + + err = (cmd->func) (cmd, 1, args); + if (is_valid) + { + grub_test_assert (err == GRUB_ERR_NONE, "verification of %s failed: %d: %s", + f, grub_errno, grub_errmsg); + } + else + { + grub_test_assert (err != GRUB_ERR_NONE, + "verification of %s unexpectedly succeeded", f); + } +} + +static void +appended_signature_test (void) +{ + grub_command_t cmd_trust, cmd_distrust; + char *trust_args[] = { (char *) "(proc)/certificate.der", NULL }; + char *trust_args2[] = { (char *) "(proc)/certificate2.der", NULL }; + char *trust_args_printable[] = { (char *) "(proc)/certificate_printable.der", NULL }; + char *trust_args_eku[] = { (char *) "(proc)/certificate_eku.der", NULL }; + const char *key_mgmt; + grub_err_t err; + + grub_procfs_register ("certificate.der", &certificate_der_entry); + grub_procfs_register ("certificate2.der", &certificate2_der_entry); + grub_procfs_register ("certificate_printable.der", &certificate_printable_der_entry); + grub_procfs_register ("certificate_eku.der", &certificate_eku_der_entry); + + /* Set appended signature key managment to static. */ + err = grub_env_set ("appendedsig_key_mgmt", "static"); + grub_test_assert (err == GRUB_ERR_NONE, "set of key management is failed: %d: %s", + grub_errno, grub_errmsg); + + /* Get appended signatures key management. */ + key_mgmt = grub_env_get ("appendedsig_key_mgmt"); + grub_test_assert (grub_strncmp (key_mgmt, "static", grub_strlen(key_mgmt)) == 0, + "getting unexpected key management: %d: %s", + grub_errno, grub_errmsg); + + cmd_trust = grub_command_find ("append_add_db_cert"); + if (cmd_trust == NULL) + { + grub_test_assert (0, "can't find command `%s'", "append_add_db_cert"); + return; + } + + grub_errno = GRUB_ERR_NONE; + err = (cmd_trust->func) (cmd_trust, 1, trust_args); + grub_test_assert (err == GRUB_ERR_NONE, "loading certificate failed: %d: %s", + grub_errno, grub_errmsg); + /* If we have no certificate the remainder of the tests are meaningless. */ + if (err != GRUB_ERR_NONE) + return; + + /* + * Reload the command: this works around some 'interesting' behaviour in the + * dynamic command dispatcher. The first time you call cmd->func you get a + * dispatcher that loads the module, finds the real cmd, calls it, and then + * releases some internal storage. This means it's not safe to call a second + * time and we need to reload it. + */ + cmd_trust = grub_command_find ("append_add_db_cert"); + + /* The hi, signed with key 1, SHA-512. */ + DO_TEST (hi_signed, 1); + + /* The hi, signed with key 1, SHA-256. */ + DO_TEST (hi_signed_sha256, 1); + + /* The hi, key 1, SHA-512, second byte corrupted. */ + DO_TEST (hj_signed, 0); + + /* Message too short for a signature. */ + DO_TEST (short_msg, 0); + + /* Lorem ipsum. */ + DO_TEST (unsigned_msg, 0); + + /* The hi, signed with both keys, SHA-512. */ + DO_TEST (hi_double, 1); + + /* + * The hi, signed with both keys and with empty space to test we haven't + * broken support for adding more signatures after the fact. + */ + DO_TEST (hi_double_extended, 1); + + /* + * In enforcing mode, we shouldn't be able to load a certificate that isn't + * signed by an existing trusted key. + * + * However, procfs files automatically skip the verification test, so we can't + * easily test this. + */ + + /* Verify that testing with 2 trusted certs works. */ + DO_TEST (hi_signed_2nd, 0); + + err = (cmd_trust->func) (cmd_trust, 1, trust_args); + grub_test_assert (err != GRUB_ERR_NONE, "unexpectedly reloaded certificate 1: %d: %s", + grub_errno, grub_errmsg); + + err = (cmd_trust->func) (cmd_trust, 1, trust_args2); + grub_test_assert (err == GRUB_ERR_NONE, "loading certificate 2 failed: %d: %s", + grub_errno, grub_errmsg); + if (err != GRUB_ERR_NONE) + return; + + DO_TEST (hi_signed_2nd, 1); + DO_TEST (hi_signed, 1); + DO_TEST (hi_double, 1); + DO_TEST (hi_double_extended, 1); + + /* + * Check certificate removal. They're added to the _top_ of the db list and + * removed by position in the list. Current the list looks like [#2, #1]. + */ + cmd_distrust = grub_command_find ("append_add_dbx_cert"); + if (cmd_distrust == NULL) + { + grub_test_assert (0, "can't find command `%s'", "append_add_dbx_cert"); + return; + } + + /* Remove the certificate #1. */ + err = (cmd_distrust->func) (cmd_distrust, 1, trust_args); + grub_test_assert (err == GRUB_ERR_NONE, "distrusting certificate 1 failed: %d: %s", + grub_errno, grub_errmsg); + DO_TEST (hi_signed_2nd, 1); + DO_TEST (hi_signed, 0); + DO_TEST (hi_double, 1); + + /* Now reload certificate #1. */ + err = (cmd_trust->func) (cmd_trust, 1, trust_args); + grub_test_assert (err == GRUB_ERR_NONE, "reloading certificate 1 failed: %d: %s", + grub_errno, grub_errmsg); + DO_TEST (hi_signed_2nd, 1); + DO_TEST (hi_signed, 1); + DO_TEST (hi_double, 1); + + /* Remove the certificate #2. */ + err = (cmd_distrust->func) (cmd_distrust, 1, trust_args2); + grub_test_assert (err == GRUB_ERR_NONE, "distrusting certificate 2 failed: %d: %s", + grub_errno, grub_errmsg); + DO_TEST (hi_signed_2nd, 0); + DO_TEST (hi_signed, 1); + DO_TEST (hi_double, 1); + + /* Now reload certificate #2. */ + err = (cmd_trust->func) (cmd_trust, 1, trust_args2); + grub_test_assert (err == GRUB_ERR_NONE, "reloading certificate 2 failed: %d: %s", + grub_errno, grub_errmsg); + DO_TEST (hi_signed_2nd, 1); + DO_TEST (hi_signed, 1); + DO_TEST (hi_double, 1); + + /* Remove the certificate #1. */ + err = (cmd_distrust->func) (cmd_distrust, 1, trust_args); + grub_test_assert (err == GRUB_ERR_NONE, "distrusting certificate 1 failed: %d: %s", + grub_errno, grub_errmsg); + + /* Remove the certificate #2. */ + err = (cmd_distrust->func) (cmd_distrust, 1, trust_args2); + grub_test_assert (err == GRUB_ERR_NONE, "distrusting certificate 2 failed: %d: %s", + grub_errno, grub_errmsg); + + /* Set appended signature key managment to dynamic. */ + err = grub_env_set ("appendedsig_key_mgmt", "dynamic"); + grub_test_assert (err == GRUB_ERR_NONE, "set of key management is failed: %d: %s", + grub_errno, grub_errmsg); + + /* Get appended signatures key management. */ + key_mgmt = grub_env_get ("appendedsig_key_mgmt"); + grub_test_assert (grub_strncmp (key_mgmt, "dynamic", grub_strlen(key_mgmt)) == 0, + "getting unexpected key management: %d: %s", + grub_errno, grub_errmsg); + + cmd_trust = grub_command_find ("append_add_db_cert"); + err = (cmd_trust->func) (cmd_trust, 1, trust_args); + grub_test_assert ((err == GRUB_ERR_NONE || err == GRUB_ERR_EXISTS || GRUB_ERR_ACCESS_DENIED), + "loading certificate 1 failed: %d: %s", + grub_errno, grub_errmsg); + if (err != GRUB_ERR_NONE) + return; + + DO_TEST (hi_signed, 1); + DO_TEST (hi_double, 1); + DO_TEST (hi_double_extended, 1); + + err = (cmd_trust->func) (cmd_trust, 1, trust_args2); + grub_test_assert ((err == GRUB_ERR_NONE || err == GRUB_ERR_EXISTS || GRUB_ERR_ACCESS_DENIED), + "loading certificate 2 failed: %d: %s", + grub_errno, grub_errmsg); + if (err != GRUB_ERR_NONE) + return; + + DO_TEST (hi_signed_2nd, 1); + DO_TEST (hi_signed, 1); + DO_TEST (hi_double, 1); + DO_TEST (hi_double_extended, 1); + + cmd_distrust = grub_command_find ("append_add_dbx_cert"); + if (cmd_distrust == NULL) + { + grub_test_assert (0, "can't find command `%s'", "append_add_dbx_cert"); + return; + } + + /* Now remove certificate #1. */ + err = (cmd_distrust->func) (cmd_distrust, 1, trust_args); + grub_test_assert ((err == GRUB_ERR_NONE || err == GRUB_ERR_EXISTS), + "distrusting certificate 1 failed: %d: %s", + grub_errno, grub_errmsg); + DO_TEST (hi_signed_2nd, 1); + DO_TEST (hi_signed, 0); + DO_TEST (hi_double, 1); + + /* Now reload certificate #1. */ + err = (cmd_trust->func) (cmd_trust, 1, trust_args); + grub_test_assert (err != GRUB_ERR_NONE, "unexpectedly reloaded certificate 1: %d: %s", + grub_errno, grub_errmsg); + DO_TEST (hi_signed_2nd, 1); + DO_TEST (hi_signed, 0); + DO_TEST (hi_double, 1); + + /* Remove the certificate #2. */ + err = (cmd_distrust->func) (cmd_distrust, 1, trust_args2); + grub_test_assert ((err == GRUB_ERR_NONE || err == GRUB_ERR_EXISTS), + "distrusting certificate 2 failed: %d: %s", + grub_errno, grub_errmsg); + DO_TEST (hi_signed_2nd, 0); + DO_TEST (hi_signed, 0); + DO_TEST (hi_double, 0); + + /* Now reload certificate #2. */ + err = (cmd_trust->func) (cmd_trust, 1, trust_args2); + grub_test_assert (err != GRUB_ERR_NONE, "unexpectedly reloaded certificate 2: %d: %s", + grub_errno, grub_errmsg); + DO_TEST (hi_signed_2nd, 0); + DO_TEST (hi_signed, 0); + DO_TEST (hi_double, 0); + + /* + * Lastly, check a certificate that uses printableString rather than utf8String + * loads properly, and that a certificate with an appropriate extended key usage + * loads. + */ + err = (cmd_trust->func) (cmd_trust, 1, trust_args_printable); + grub_test_assert (err == GRUB_ERR_NONE, "trusting printable certificate failed: %d: %s", + grub_errno, grub_errmsg); + + err = (cmd_trust->func) (cmd_trust, 1, trust_args_eku); + grub_test_assert (err == GRUB_ERR_NONE, "trusting certificate with extended key usage failed: %d: %s", + grub_errno, grub_errmsg); + + grub_procfs_unregister (&certificate_der_entry); + grub_procfs_unregister (&certificate2_der_entry); + grub_procfs_unregister (&certificate_printable_der_entry); + grub_procfs_unregister (&certificate_eku_der_entry); +} + +GRUB_FUNCTIONAL_TEST (appended_signature_test, appended_signature_test); diff --git a/grub-core/tests/appended_signatures.h b/grub-core/tests/appended_signatures.h new file mode 100644 index 000000000..c6aa12d86 --- /dev/null +++ b/grub-core/tests/appended_signatures.h @@ -0,0 +1,975 @@ +unsigned char certificate_der[] = { + 0x30, 0x82, 0x05, 0x5d, 0x30, 0x82, 0x03, 0x45, 0xa0, 0x03, 0x02, 0x01, + 0x02, 0x02, 0x14, 0x5b, 0x5e, 0x59, 0xf2, 0x5f, 0x75, 0x4c, 0x8e, 0xc5, + 0x3a, 0x91, 0x07, 0xe9, 0xe7, 0x6d, 0x3c, 0xd0, 0x7f, 0x92, 0x03, 0x30, + 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, + 0x05, 0x00, 0x30, 0x3d, 0x31, 0x3b, 0x30, 0x39, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x0c, 0x32, 0x47, 0x72, 0x75, 0x62, 0x20, 0x41, 0x70, 0x70, 0x65, + 0x6e, 0x64, 0x65, 0x64, 0x20, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, + 0x72, 0x65, 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, + 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, 0x68, + 0x6f, 0x72, 0x69, 0x74, 0x79, 0x30, 0x20, 0x17, 0x0d, 0x32, 0x31, 0x30, + 0x36, 0x32, 0x39, 0x30, 0x38, 0x33, 0x36, 0x31, 0x33, 0x5a, 0x18, 0x0f, + 0x32, 0x31, 0x32, 0x31, 0x30, 0x36, 0x30, 0x35, 0x30, 0x38, 0x33, 0x36, + 0x31, 0x33, 0x5a, 0x30, 0x33, 0x31, 0x31, 0x30, 0x2f, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x0c, 0x28, 0x47, 0x72, 0x75, 0x62, 0x20, 0x41, 0x70, 0x70, + 0x65, 0x6e, 0x64, 0x65, 0x64, 0x20, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, + 0x75, 0x72, 0x65, 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x53, 0x69, 0x67, + 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x4b, 0x65, 0x79, 0x30, 0x82, 0x02, 0x22, + 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, + 0x01, 0x05, 0x00, 0x03, 0x82, 0x02, 0x0f, 0x00, 0x30, 0x82, 0x02, 0x0a, + 0x02, 0x82, 0x02, 0x01, 0x00, 0xb9, 0x09, 0xb2, 0xf6, 0x24, 0x34, 0xdc, + 0x62, 0xe6, 0x4e, 0xee, 0x04, 0xdb, 0x29, 0xdc, 0x94, 0xcc, 0xee, 0x8a, + 0x5b, 0xc3, 0x9e, 0x06, 0xba, 0xa7, 0x9b, 0xa4, 0x5f, 0x15, 0x59, 0x8e, + 0xb8, 0x6e, 0x3c, 0xeb, 0x2e, 0xf2, 0xac, 0x21, 0x42, 0xbd, 0x30, 0xa1, + 0x39, 0xe5, 0xb9, 0x4f, 0xa0, 0x53, 0xd5, 0x42, 0xdc, 0x8a, 0x87, 0x30, + 0x38, 0x93, 0x44, 0x80, 0x3b, 0x1a, 0x7e, 0x9e, 0x8e, 0x3e, 0xea, 0x45, + 0xa0, 0x11, 0x8b, 0xfb, 0x78, 0xe4, 0xbc, 0x65, 0x6b, 0x73, 0xea, 0x6e, + 0xdf, 0x7c, 0x5b, 0x63, 0x7e, 0x5b, 0x0a, 0x1c, 0xe6, 0x76, 0x19, 0xb5, + 0x01, 0xde, 0xf6, 0x65, 0x51, 0x30, 0x0a, 0x56, 0x69, 0x69, 0xe8, 0x20, + 0xf9, 0x13, 0xf1, 0xbf, 0x6f, 0xdd, 0xce, 0x94, 0x96, 0x6e, 0x63, 0xd6, + 0xfa, 0xa4, 0x91, 0x5f, 0xb3, 0x9c, 0xc7, 0xfa, 0xa9, 0xff, 0x66, 0x5f, + 0xf3, 0xab, 0x5e, 0xdf, 0x4e, 0xca, 0x11, 0xcf, 0xbf, 0xf8, 0xad, 0x65, + 0xb1, 0x49, 0x8b, 0xe9, 0x2a, 0xad, 0x7d, 0xf3, 0x0b, 0xfa, 0x5b, 0x6a, + 0x6a, 0x20, 0x12, 0x77, 0xef, 0x4b, 0xb6, 0xbe, 0x92, 0xba, 0x14, 0x9c, + 0x5e, 0xea, 0xdc, 0x56, 0x6d, 0x92, 0xd3, 0x64, 0x22, 0xf6, 0x12, 0xe8, + 0x7d, 0x5e, 0x9c, 0xd6, 0xf9, 0x75, 0x68, 0x7f, 0x8f, 0xd3, 0x6e, 0x05, + 0x94, 0x91, 0x4f, 0xa1, 0xd6, 0x50, 0x72, 0x3b, 0x11, 0x1f, 0x28, 0x13, + 0xe8, 0x25, 0x6b, 0xdf, 0xff, 0x72, 0x46, 0x25, 0xe9, 0x05, 0x6f, 0x02, + 0xc7, 0x1e, 0xc9, 0xcf, 0x99, 0xe9, 0xa7, 0xe2, 0xae, 0xbc, 0xc1, 0x22, + 0x32, 0x73, 0x2d, 0xa3, 0x70, 0x8f, 0xa7, 0x8d, 0xbf, 0x5f, 0x74, 0x05, + 0x1b, 0x5e, 0xfe, 0x97, 0x3c, 0xe7, 0x3b, 0x86, 0x0d, 0xf6, 0x38, 0xdb, + 0xd2, 0x39, 0x47, 0x82, 0x00, 0x44, 0x6c, 0x7b, 0x40, 0x24, 0x0b, 0x3a, + 0xd4, 0x19, 0x31, 0xba, 0x4e, 0x8e, 0xa3, 0x33, 0xa6, 0x78, 0xef, 0x72, + 0x9f, 0x06, 0x37, 0x01, 0x9b, 0x79, 0x0d, 0x04, 0xbf, 0xba, 0xd5, 0x1f, + 0x27, 0xdc, 0x85, 0xbb, 0xef, 0xd2, 0x60, 0xda, 0xa0, 0x3f, 0x66, 0xce, + 0x9f, 0xa2, 0x7e, 0xa8, 0x8d, 0xee, 0x14, 0x4b, 0xcb, 0x93, 0xf1, 0x38, + 0xac, 0x4f, 0xd8, 0x29, 0xf3, 0x6f, 0xd4, 0xfd, 0x4d, 0x34, 0x77, 0x58, + 0x99, 0xdb, 0x16, 0xc1, 0xd0, 0xc7, 0x43, 0x41, 0x70, 0xc4, 0xad, 0x01, + 0x29, 0x65, 0x22, 0x43, 0x00, 0x6f, 0xb3, 0x00, 0x27, 0x38, 0xc1, 0x4f, + 0xda, 0x28, 0x96, 0x42, 0xdc, 0xbc, 0x3e, 0x34, 0x8e, 0x14, 0xb8, 0xf3, + 0x86, 0x4a, 0xea, 0x16, 0x90, 0xf9, 0x0e, 0x9e, 0x8f, 0x66, 0x0c, 0xbf, + 0x29, 0xd3, 0x8f, 0xfc, 0x4d, 0x38, 0x68, 0xe2, 0xe7, 0x64, 0x32, 0x47, + 0xdd, 0x56, 0xc9, 0xe4, 0x47, 0x9f, 0x18, 0x89, 0xfc, 0x30, 0x7a, 0xae, + 0x63, 0xe4, 0xec, 0x93, 0x04, 0xd4, 0x61, 0xe7, 0xbf, 0x0a, 0x06, 0x29, + 0xc2, 0xa6, 0xd5, 0x53, 0x5d, 0x65, 0x6d, 0x4a, 0xd0, 0xb7, 0x68, 0x4d, + 0x46, 0x0a, 0xb5, 0xff, 0x52, 0x5e, 0x92, 0x7e, 0x75, 0x08, 0xa4, 0x63, + 0x0a, 0x6c, 0x31, 0x7a, 0xaa, 0x0c, 0x52, 0xf4, 0x2e, 0xcd, 0x08, 0xeb, + 0xb3, 0xbd, 0xad, 0x8b, 0x8b, 0x9b, 0x8d, 0x71, 0x42, 0x30, 0x8e, 0xc7, + 0xfd, 0xec, 0xb7, 0xe6, 0x26, 0x96, 0xf2, 0x74, 0x1b, 0x78, 0x95, 0x22, + 0x14, 0xf3, 0xc9, 0xd3, 0x79, 0x11, 0xd9, 0xb7, 0x4d, 0x0d, 0x61, 0x60, + 0x5c, 0x47, 0x50, 0xf3, 0xca, 0x84, 0x4c, 0x5c, 0x30, 0x2c, 0x6a, 0x18, + 0x26, 0xb0, 0xf3, 0xd1, 0x15, 0x19, 0x39, 0xc3, 0x23, 0x13, 0x0f, 0x9c, + 0x97, 0x2b, 0x97, 0x93, 0xf9, 0xf8, 0x18, 0x9b, 0x4a, 0x4d, 0xd6, 0xd3, + 0xf5, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x5d, 0x30, 0x5b, 0x30, 0x0c, + 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x02, 0x30, 0x00, + 0x30, 0x0b, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x07, + 0x80, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, + 0x8f, 0xba, 0x8b, 0xf5, 0xf4, 0x77, 0xb2, 0xa4, 0x19, 0xef, 0x43, 0xb1, + 0x8b, 0x03, 0x4b, 0x45, 0x47, 0xb5, 0x2a, 0x48, 0x30, 0x1f, 0x06, 0x03, + 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x59, 0x1c, 0xb5, + 0x52, 0x62, 0x83, 0x05, 0x3b, 0x41, 0x4c, 0x63, 0x4d, 0x5b, 0xf4, 0x8c, + 0xe6, 0xd7, 0xda, 0x87, 0x54, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, + 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x02, 0x01, + 0x00, 0x36, 0x2d, 0x0a, 0xcb, 0x49, 0x54, 0x75, 0xd7, 0xca, 0x21, 0x86, + 0xae, 0x40, 0x0f, 0x63, 0x10, 0x35, 0xfd, 0xbc, 0xba, 0x28, 0x31, 0x33, + 0x07, 0x08, 0x64, 0x03, 0x6c, 0xd3, 0xd5, 0xf7, 0xb7, 0x79, 0x11, 0x0c, + 0xa8, 0x9e, 0xfd, 0x34, 0xa2, 0xba, 0x77, 0x15, 0x15, 0x2d, 0x2c, 0x96, + 0xae, 0x47, 0xbb, 0x82, 0x89, 0x09, 0x7f, 0xd1, 0x95, 0x69, 0x9b, 0xfe, + 0xd7, 0x6f, 0x4e, 0x68, 0xf6, 0xe7, 0x5f, 0x54, 0xa1, 0x3a, 0xeb, 0xa4, + 0xbf, 0x7a, 0xb6, 0x7f, 0xaa, 0xd8, 0xd7, 0x99, 0xcb, 0xae, 0x88, 0x6d, + 0x7a, 0xf3, 0xfa, 0x9e, 0x44, 0x2f, 0x30, 0xa8, 0xe6, 0xb9, 0x75, 0xa0, + 0x82, 0xd6, 0xb0, 0xe3, 0x03, 0xb3, 0x12, 0xa3, 0xdc, 0xb9, 0x4d, 0x93, + 0xd4, 0x30, 0xea, 0xce, 0x96, 0x92, 0x07, 0xf8, 0xba, 0xe4, 0x0f, 0x41, + 0xe3, 0x04, 0xaa, 0x8c, 0x07, 0x1a, 0x34, 0x60, 0xfc, 0xc0, 0x05, 0xd2, + 0x5a, 0xa8, 0x66, 0xef, 0xe0, 0x94, 0xc5, 0x2f, 0x0f, 0xff, 0xdc, 0x70, + 0xfb, 0xe2, 0x9d, 0x61, 0x51, 0x25, 0x02, 0xff, 0x4b, 0x69, 0xfd, 0x66, + 0xb9, 0xeb, 0x0c, 0xc8, 0x50, 0xd3, 0xb1, 0x08, 0x1e, 0x09, 0x54, 0x87, + 0xe8, 0xa3, 0x4b, 0xef, 0x0c, 0x32, 0x0a, 0x6c, 0xec, 0x27, 0x22, 0xba, + 0x7f, 0xdc, 0x52, 0x27, 0x31, 0x14, 0x9a, 0xa8, 0xf7, 0xf9, 0xeb, 0xc8, + 0xb5, 0x8d, 0x12, 0xed, 0x94, 0xab, 0x3d, 0x9a, 0xfb, 0x4e, 0x04, 0x05, + 0xd2, 0x3c, 0x7c, 0x8a, 0xed, 0x46, 0x1b, 0x7c, 0xb5, 0x6c, 0x40, 0xb8, + 0xc1, 0xbf, 0xb0, 0xd2, 0x93, 0x8e, 0xa8, 0x0f, 0xde, 0x78, 0xf3, 0x8c, + 0xd8, 0x9f, 0xf8, 0xdc, 0xa1, 0x23, 0x20, 0x40, 0x17, 0xb4, 0xdb, 0xb7, + 0x09, 0x74, 0xa7, 0x80, 0xc2, 0x12, 0xd9, 0x76, 0x79, 0x5b, 0x71, 0xa9, + 0x6c, 0xd4, 0x57, 0x48, 0xe8, 0xfe, 0xc5, 0xc2, 0x6e, 0xe7, 0x83, 0x5a, + 0x07, 0xf0, 0x33, 0xc1, 0xc1, 0x1d, 0x34, 0xd4, 0xc8, 0xb0, 0xb7, 0xdb, + 0xeb, 0xe9, 0xe3, 0x59, 0xdc, 0x7f, 0x36, 0x58, 0xa9, 0xb8, 0x52, 0xdd, + 0xf9, 0xfd, 0x1c, 0x22, 0x2f, 0x93, 0x3d, 0x53, 0x89, 0x80, 0xde, 0xa2, + 0xb5, 0xa5, 0x36, 0xbd, 0xc3, 0x92, 0x03, 0xf3, 0x93, 0xc8, 0xc7, 0x4a, + 0x0b, 0x8b, 0x62, 0xfe, 0xd0, 0xf8, 0x0d, 0x7a, 0x32, 0xb4, 0x39, 0x1a, + 0xb7, 0x4e, 0xaa, 0xc4, 0x33, 0x32, 0x90, 0x8c, 0xab, 0xd4, 0xae, 0xa5, + 0xa4, 0x85, 0xcf, 0xba, 0xe1, 0x1b, 0x26, 0x7f, 0x74, 0x02, 0x12, 0x09, + 0x89, 0x56, 0xe4, 0xe7, 0x9d, 0x91, 0xde, 0x88, 0xe7, 0x1c, 0xed, 0x80, + 0x05, 0xa8, 0x58, 0x9a, 0x3e, 0x16, 0x97, 0xd5, 0xbc, 0x54, 0xcc, 0xf0, + 0x32, 0xf2, 0x93, 0x09, 0x94, 0x9f, 0x3c, 0xd9, 0x58, 0xca, 0x68, 0x0b, + 0xde, 0x3f, 0x73, 0x64, 0xb7, 0xf4, 0xd7, 0x5f, 0x2b, 0xe7, 0x7b, 0x06, + 0xca, 0xb1, 0x3e, 0xed, 0xd2, 0xb9, 0x29, 0xc1, 0x95, 0x87, 0xad, 0xd6, + 0x63, 0x69, 0xb8, 0x1f, 0x70, 0xdb, 0xeb, 0xc7, 0x11, 0x7d, 0xe2, 0x99, + 0x64, 0x6a, 0xf5, 0x3f, 0x30, 0x74, 0x5f, 0x2a, 0x21, 0xda, 0xef, 0x44, + 0x1d, 0xad, 0x97, 0xa1, 0xfe, 0x14, 0xa7, 0x88, 0x99, 0xd0, 0x1e, 0xb0, + 0x61, 0x88, 0x09, 0xc9, 0xfa, 0xd1, 0xb3, 0xcb, 0x1d, 0x76, 0x04, 0xbe, + 0x06, 0x44, 0xd2, 0x30, 0x5e, 0x95, 0x4b, 0x96, 0xc0, 0xd6, 0xbe, 0xd0, + 0x4d, 0xf2, 0xf4, 0x71, 0x72, 0xa9, 0xbd, 0x07, 0x4f, 0xbc, 0xb3, 0x78, + 0xb4, 0x8a, 0x44, 0xbd, 0x58, 0xd5, 0x21, 0xb6, 0x47, 0x9c, 0x88, 0x1f, + 0xbc, 0xbd, 0x54, 0xfa, 0x1d, 0x49, 0xec, 0x51, 0xd9, 0x43, 0x49, 0x9c, + 0x0c, 0xfa, 0x18, 0xdb, 0xeb, 0x05, 0x77, 0xa2, 0x9a +}; +unsigned int certificate_der_len = 1377; + +unsigned char hi_signed[] = { + 0x68, 0x69, 0x0a, 0x30, 0x82, 0x02, 0xb4, 0x06, 0x09, 0x2a, 0x86, 0x48, + 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x02, 0xa0, 0x82, 0x02, 0xa5, 0x30, 0x82, + 0x02, 0xa1, 0x02, 0x01, 0x01, 0x31, 0x0d, 0x30, 0x0b, 0x06, 0x09, 0x60, + 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x30, 0x0b, 0x06, 0x09, + 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0x31, 0x82, 0x02, + 0x7e, 0x30, 0x82, 0x02, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x55, 0x30, 0x3d, + 0x31, 0x3b, 0x30, 0x39, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x32, 0x47, + 0x72, 0x75, 0x62, 0x20, 0x41, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x64, + 0x20, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x20, 0x54, + 0x65, 0x73, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, + 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, + 0x79, 0x02, 0x14, 0x5b, 0x5e, 0x59, 0xf2, 0x5f, 0x75, 0x4c, 0x8e, 0xc5, + 0x3a, 0x91, 0x07, 0xe9, 0xe7, 0x6d, 0x3c, 0xd0, 0x7f, 0x92, 0x03, 0x30, + 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, + 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, + 0x01, 0x05, 0x00, 0x04, 0x82, 0x02, 0x00, 0xa0, 0x83, 0x3f, 0xac, 0x77, + 0x97, 0x74, 0x9b, 0x4b, 0x25, 0xa1, 0x64, 0x09, 0x8d, 0x53, 0xa6, 0x03, + 0xdf, 0x9a, 0x10, 0x52, 0xe5, 0x3f, 0xd4, 0x72, 0x75, 0x30, 0xd4, 0x6e, + 0x77, 0x32, 0x49, 0x84, 0xe2, 0xbe, 0xef, 0xe4, 0xf3, 0xac, 0xb0, 0x52, + 0x55, 0xbf, 0xa9, 0x57, 0x12, 0x08, 0x7d, 0xb0, 0x86, 0xc0, 0x9d, 0x01, + 0xc2, 0x1a, 0x4a, 0x2e, 0x3d, 0xd5, 0xc8, 0x56, 0xac, 0xd1, 0x83, 0x75, + 0x88, 0xd4, 0xcc, 0x9f, 0x0d, 0xcf, 0xd3, 0xa6, 0x91, 0xb6, 0xb6, 0xb1, + 0xd1, 0x24, 0x9c, 0xd0, 0x13, 0xe8, 0x6b, 0x15, 0x9c, 0x62, 0x33, 0x8d, + 0xe3, 0x67, 0x9b, 0xb1, 0x8a, 0x72, 0x38, 0xf7, 0x48, 0x32, 0x2f, 0x1e, + 0x45, 0xa8, 0xc4, 0xa5, 0xae, 0xb1, 0xfc, 0x35, 0x25, 0xb5, 0xf9, 0x7f, + 0x86, 0xef, 0xa2, 0x6d, 0x78, 0xcc, 0xfd, 0x0c, 0xca, 0x8a, 0xe1, 0xae, + 0xcd, 0x0f, 0x58, 0x69, 0xf1, 0x8b, 0xcc, 0x22, 0x35, 0x6d, 0x1f, 0xd5, + 0x27, 0x87, 0x39, 0x62, 0x3f, 0xb2, 0x17, 0x3d, 0x5e, 0xb1, 0x32, 0x7a, + 0xf1, 0x70, 0xce, 0xfa, 0xab, 0x1c, 0x92, 0xa8, 0xe1, 0xc4, 0xb2, 0x33, + 0x1a, 0x16, 0xf3, 0x60, 0x39, 0xdf, 0xb8, 0x85, 0xe7, 0x5d, 0x4d, 0xc2, + 0x8d, 0x55, 0x00, 0x49, 0x94, 0x04, 0x17, 0x88, 0x7c, 0xf4, 0xac, 0xa9, + 0xc5, 0x3a, 0x09, 0xc4, 0xc2, 0xcd, 0x3d, 0xc3, 0xfc, 0x4e, 0xf3, 0x70, + 0xa1, 0xc1, 0x54, 0x36, 0x1f, 0x38, 0x6d, 0x7a, 0x6b, 0x6a, 0xd3, 0x67, + 0x04, 0xd5, 0x53, 0xd4, 0xa5, 0xad, 0x63, 0x55, 0x0e, 0x06, 0x06, 0x3a, + 0x9a, 0xc5, 0xfe, 0x38, 0xc9, 0xb0, 0x69, 0x42, 0x90, 0x35, 0x1f, 0xe3, + 0x1c, 0x57, 0xea, 0xdb, 0x51, 0x35, 0x53, 0xd3, 0x94, 0xfe, 0x72, 0x33, + 0xd6, 0x8a, 0x46, 0x74, 0xf9, 0x6e, 0x94, 0x40, 0x2f, 0xba, 0xa2, 0xc4, + 0xe9, 0xc9, 0x8a, 0xf4, 0xda, 0xe2, 0xca, 0x3e, 0x98, 0x85, 0xa5, 0xd1, + 0x60, 0x94, 0xc8, 0xdf, 0x82, 0xee, 0x5c, 0x0d, 0x2a, 0xa9, 0x8e, 0x26, + 0x83, 0x3f, 0x02, 0xa2, 0xaf, 0xb8, 0x3b, 0x83, 0xf2, 0x44, 0x46, 0x41, + 0xd7, 0x5c, 0xa1, 0x42, 0x17, 0xa2, 0xd0, 0x50, 0x42, 0xef, 0x66, 0xda, + 0x35, 0x03, 0xd1, 0x8e, 0x77, 0x22, 0x7d, 0x4e, 0xf7, 0x4e, 0x04, 0xe3, + 0x0f, 0x98, 0x7d, 0xaa, 0x58, 0xba, 0xef, 0x9a, 0xd0, 0x88, 0x7c, 0x98, + 0xa0, 0xc2, 0xff, 0xa6, 0xb1, 0xec, 0xbe, 0x6e, 0xb0, 0x7e, 0xc6, 0xe5, + 0xaa, 0xcf, 0x10, 0x73, 0xc9, 0x13, 0x1a, 0x20, 0x12, 0x5c, 0xd2, 0x0e, + 0xe2, 0x60, 0x17, 0xdf, 0x4a, 0x44, 0x08, 0x22, 0xbc, 0xcd, 0x75, 0xbe, + 0xc3, 0x7a, 0x12, 0x90, 0x90, 0xc7, 0x94, 0x4c, 0x98, 0x45, 0x02, 0x5c, + 0x24, 0xae, 0x82, 0x2f, 0xcd, 0x30, 0xa6, 0xf5, 0x3f, 0xd3, 0xa7, 0xa6, + 0xe6, 0xea, 0x11, 0x4e, 0x45, 0xb7, 0xc0, 0xe6, 0x24, 0x8b, 0x76, 0xc5, + 0x5e, 0xc1, 0xd8, 0x07, 0x1e, 0x26, 0x94, 0x7a, 0x80, 0xc6, 0x3b, 0x1f, + 0x74, 0xe6, 0xae, 0x43, 0x2d, 0x11, 0xee, 0x96, 0x56, 0x6c, 0xff, 0xcb, + 0x3b, 0xde, 0xcc, 0xb3, 0x7b, 0x08, 0xf5, 0x3e, 0x6e, 0x51, 0x71, 0xe0, + 0x8a, 0xfa, 0xdd, 0x19, 0x39, 0xcf, 0x3f, 0x29, 0x4f, 0x2d, 0xd2, 0xd4, + 0xdc, 0x5c, 0xc4, 0xd1, 0xa7, 0xf5, 0xbf, 0x4a, 0xc0, 0x9b, 0xb4, 0x2b, + 0x83, 0x7a, 0x63, 0x4d, 0x20, 0x40, 0x8b, 0x11, 0x5c, 0x53, 0xd4, 0x52, + 0x21, 0xe7, 0xe4, 0x1f, 0x01, 0xf6, 0xd1, 0x25, 0x28, 0xba, 0x51, 0x6f, + 0x51, 0x69, 0xf4, 0x41, 0x45, 0x75, 0x23, 0x25, 0x77, 0xef, 0xa8, 0x1c, + 0x19, 0x8a, 0x66, 0x8c, 0x61, 0x13, 0x37, 0x4f, 0xa3, 0xa1, 0x83, 0x17, + 0x35, 0x23, 0x2d, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x02, 0xb8, 0x7e, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x20, 0x73, + 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x20, 0x61, 0x70, 0x70, + 0x65, 0x6e, 0x64, 0x65, 0x64, 0x7e, 0x0a +}; +unsigned int hi_signed_len = 739; + +unsigned char hj_signed[] = { + 0x68, 0x6a, 0x0a, 0x30, 0x82, 0x02, 0xb4, 0x06, 0x09, 0x2a, 0x86, 0x48, + 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x02, 0xa0, 0x82, 0x02, 0xa5, 0x30, 0x82, + 0x02, 0xa1, 0x02, 0x01, 0x01, 0x31, 0x0d, 0x30, 0x0b, 0x06, 0x09, 0x60, + 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x30, 0x0b, 0x06, 0x09, + 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0x31, 0x82, 0x02, + 0x7e, 0x30, 0x82, 0x02, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x55, 0x30, 0x3d, + 0x31, 0x3b, 0x30, 0x39, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x32, 0x47, + 0x72, 0x75, 0x62, 0x20, 0x41, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x64, + 0x20, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x20, 0x54, + 0x65, 0x73, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, + 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, + 0x79, 0x02, 0x14, 0x5b, 0x5e, 0x59, 0xf2, 0x5f, 0x75, 0x4c, 0x8e, 0xc5, + 0x3a, 0x91, 0x07, 0xe9, 0xe7, 0x6d, 0x3c, 0xd0, 0x7f, 0x92, 0x03, 0x30, + 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, + 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, + 0x01, 0x05, 0x00, 0x04, 0x82, 0x02, 0x00, 0xa0, 0x83, 0x3f, 0xac, 0x77, + 0x97, 0x74, 0x9b, 0x4b, 0x25, 0xa1, 0x64, 0x09, 0x8d, 0x53, 0xa6, 0x03, + 0xdf, 0x9a, 0x10, 0x52, 0xe5, 0x3f, 0xd4, 0x72, 0x75, 0x30, 0xd4, 0x6e, + 0x77, 0x32, 0x49, 0x84, 0xe2, 0xbe, 0xef, 0xe4, 0xf3, 0xac, 0xb0, 0x52, + 0x55, 0xbf, 0xa9, 0x57, 0x12, 0x08, 0x7d, 0xb0, 0x86, 0xc0, 0x9d, 0x01, + 0xc2, 0x1a, 0x4a, 0x2e, 0x3d, 0xd5, 0xc8, 0x56, 0xac, 0xd1, 0x83, 0x75, + 0x88, 0xd4, 0xcc, 0x9f, 0x0d, 0xcf, 0xd3, 0xa6, 0x91, 0xb6, 0xb6, 0xb1, + 0xd1, 0x24, 0x9c, 0xd0, 0x13, 0xe8, 0x6b, 0x15, 0x9c, 0x62, 0x33, 0x8d, + 0xe3, 0x67, 0x9b, 0xb1, 0x8a, 0x72, 0x38, 0xf7, 0x48, 0x32, 0x2f, 0x1e, + 0x45, 0xa8, 0xc4, 0xa5, 0xae, 0xb1, 0xfc, 0x35, 0x25, 0xb5, 0xf9, 0x7f, + 0x86, 0xef, 0xa2, 0x6d, 0x78, 0xcc, 0xfd, 0x0c, 0xca, 0x8a, 0xe1, 0xae, + 0xcd, 0x0f, 0x58, 0x69, 0xf1, 0x8b, 0xcc, 0x22, 0x35, 0x6d, 0x1f, 0xd5, + 0x27, 0x87, 0x39, 0x62, 0x3f, 0xb2, 0x17, 0x3d, 0x5e, 0xb1, 0x32, 0x7a, + 0xf1, 0x70, 0xce, 0xfa, 0xab, 0x1c, 0x92, 0xa8, 0xe1, 0xc4, 0xb2, 0x33, + 0x1a, 0x16, 0xf3, 0x60, 0x39, 0xdf, 0xb8, 0x85, 0xe7, 0x5d, 0x4d, 0xc2, + 0x8d, 0x55, 0x00, 0x49, 0x94, 0x04, 0x17, 0x88, 0x7c, 0xf4, 0xac, 0xa9, + 0xc5, 0x3a, 0x09, 0xc4, 0xc2, 0xcd, 0x3d, 0xc3, 0xfc, 0x4e, 0xf3, 0x70, + 0xa1, 0xc1, 0x54, 0x36, 0x1f, 0x38, 0x6d, 0x7a, 0x6b, 0x6a, 0xd3, 0x67, + 0x04, 0xd5, 0x53, 0xd4, 0xa5, 0xad, 0x63, 0x55, 0x0e, 0x06, 0x06, 0x3a, + 0x9a, 0xc5, 0xfe, 0x38, 0xc9, 0xb0, 0x69, 0x42, 0x90, 0x35, 0x1f, 0xe3, + 0x1c, 0x57, 0xea, 0xdb, 0x51, 0x35, 0x53, 0xd3, 0x94, 0xfe, 0x72, 0x33, + 0xd6, 0x8a, 0x46, 0x74, 0xf9, 0x6e, 0x94, 0x40, 0x2f, 0xba, 0xa2, 0xc4, + 0xe9, 0xc9, 0x8a, 0xf4, 0xda, 0xe2, 0xca, 0x3e, 0x98, 0x85, 0xa5, 0xd1, + 0x60, 0x94, 0xc8, 0xdf, 0x82, 0xee, 0x5c, 0x0d, 0x2a, 0xa9, 0x8e, 0x26, + 0x83, 0x3f, 0x02, 0xa2, 0xaf, 0xb8, 0x3b, 0x83, 0xf2, 0x44, 0x46, 0x41, + 0xd7, 0x5c, 0xa1, 0x42, 0x17, 0xa2, 0xd0, 0x50, 0x42, 0xef, 0x66, 0xda, + 0x35, 0x03, 0xd1, 0x8e, 0x77, 0x22, 0x7d, 0x4e, 0xf7, 0x4e, 0x04, 0xe3, + 0x0f, 0x98, 0x7d, 0xaa, 0x58, 0xba, 0xef, 0x9a, 0xd0, 0x88, 0x7c, 0x98, + 0xa0, 0xc2, 0xff, 0xa6, 0xb1, 0xec, 0xbe, 0x6e, 0xb0, 0x7e, 0xc6, 0xe5, + 0xaa, 0xcf, 0x10, 0x73, 0xc9, 0x13, 0x1a, 0x20, 0x12, 0x5c, 0xd2, 0x0e, + 0xe2, 0x60, 0x17, 0xdf, 0x4a, 0x44, 0x08, 0x22, 0xbc, 0xcd, 0x75, 0xbe, + 0xc3, 0x7a, 0x12, 0x90, 0x90, 0xc7, 0x94, 0x4c, 0x98, 0x45, 0x02, 0x5c, + 0x24, 0xae, 0x82, 0x2f, 0xcd, 0x30, 0xa6, 0xf5, 0x3f, 0xd3, 0xa7, 0xa6, + 0xe6, 0xea, 0x11, 0x4e, 0x45, 0xb7, 0xc0, 0xe6, 0x24, 0x8b, 0x76, 0xc5, + 0x5e, 0xc1, 0xd8, 0x07, 0x1e, 0x26, 0x94, 0x7a, 0x80, 0xc6, 0x3b, 0x1f, + 0x74, 0xe6, 0xae, 0x43, 0x2d, 0x11, 0xee, 0x96, 0x56, 0x6c, 0xff, 0xcb, + 0x3b, 0xde, 0xcc, 0xb3, 0x7b, 0x08, 0xf5, 0x3e, 0x6e, 0x51, 0x71, 0xe0, + 0x8a, 0xfa, 0xdd, 0x19, 0x39, 0xcf, 0x3f, 0x29, 0x4f, 0x2d, 0xd2, 0xd4, + 0xdc, 0x5c, 0xc4, 0xd1, 0xa7, 0xf5, 0xbf, 0x4a, 0xc0, 0x9b, 0xb4, 0x2b, + 0x83, 0x7a, 0x63, 0x4d, 0x20, 0x40, 0x8b, 0x11, 0x5c, 0x53, 0xd4, 0x52, + 0x21, 0xe7, 0xe4, 0x1f, 0x01, 0xf6, 0xd1, 0x25, 0x28, 0xba, 0x51, 0x6f, + 0x51, 0x69, 0xf4, 0x41, 0x45, 0x75, 0x23, 0x25, 0x77, 0xef, 0xa8, 0x1c, + 0x19, 0x8a, 0x66, 0x8c, 0x61, 0x13, 0x37, 0x4f, 0xa3, 0xa1, 0x83, 0x17, + 0x35, 0x23, 0x2d, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x02, 0xb8, 0x7e, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x20, 0x73, + 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x20, 0x61, 0x70, 0x70, + 0x65, 0x6e, 0x64, 0x65, 0x64, 0x7e, 0x0a +}; +unsigned int hj_signed_len = 739; + +unsigned char hi_signed_sha256[] = { + 0x68, 0x69, 0x0a, 0x30, 0x82, 0x02, 0xb4, 0x06, 0x09, 0x2a, 0x86, 0x48, + 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x02, 0xa0, 0x82, 0x02, 0xa5, 0x30, 0x82, + 0x02, 0xa1, 0x02, 0x01, 0x01, 0x31, 0x0d, 0x30, 0x0b, 0x06, 0x09, 0x60, + 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x30, 0x0b, 0x06, 0x09, + 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0x31, 0x82, 0x02, + 0x7e, 0x30, 0x82, 0x02, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x55, 0x30, 0x3d, + 0x31, 0x3b, 0x30, 0x39, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x32, 0x47, + 0x72, 0x75, 0x62, 0x20, 0x41, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x64, + 0x20, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x20, 0x54, + 0x65, 0x73, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, + 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, + 0x79, 0x02, 0x14, 0x5b, 0x5e, 0x59, 0xf2, 0x5f, 0x75, 0x4c, 0x8e, 0xc5, + 0x3a, 0x91, 0x07, 0xe9, 0xe7, 0x6d, 0x3c, 0xd0, 0x7f, 0x92, 0x03, 0x30, + 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, + 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, + 0x01, 0x05, 0x00, 0x04, 0x82, 0x02, 0x00, 0x96, 0x02, 0x7b, 0xa4, 0x07, + 0xa7, 0x39, 0x8d, 0xa6, 0x0b, 0xde, 0x33, 0xdd, 0xf8, 0xec, 0x24, 0x5d, + 0x06, 0x81, 0xe7, 0x3c, 0x2d, 0x0c, 0x53, 0xfb, 0x7e, 0x5a, 0xf3, 0xee, + 0xe5, 0x4c, 0x7c, 0xf7, 0xe7, 0x8f, 0x36, 0x62, 0x35, 0xb8, 0x99, 0xc3, + 0xeb, 0x85, 0x1d, 0x2e, 0x40, 0x6e, 0x2a, 0xb4, 0x3a, 0x76, 0x48, 0x4f, + 0x8b, 0x29, 0xd4, 0x9e, 0x5c, 0xd2, 0x41, 0x4d, 0xc1, 0x72, 0x0f, 0x97, + 0xe0, 0x7d, 0x88, 0xed, 0x1a, 0xb0, 0xde, 0x1b, 0x21, 0xa6, 0x0c, 0x19, + 0xd8, 0xb0, 0x12, 0x54, 0x7b, 0xd8, 0x19, 0x03, 0xbd, 0x77, 0x83, 0x23, + 0xeb, 0xeb, 0x68, 0x0a, 0x7b, 0x3a, 0x4d, 0x25, 0x44, 0xe1, 0x64, 0x8d, + 0x43, 0x5a, 0x1c, 0x9f, 0x74, 0x79, 0x31, 0x3f, 0xc7, 0x8e, 0xae, 0xe1, + 0xf9, 0x1e, 0x54, 0x12, 0x36, 0x85, 0xf2, 0x55, 0xba, 0x42, 0x60, 0x64, + 0x25, 0x9f, 0x73, 0x62, 0x42, 0xd2, 0x1c, 0x5e, 0x39, 0x4f, 0x7d, 0x91, + 0xb8, 0xf9, 0x59, 0x3c, 0x13, 0x6b, 0x84, 0x76, 0x6d, 0x8a, 0xc3, 0xcb, + 0x2d, 0x14, 0x27, 0x16, 0xdc, 0x20, 0x2c, 0xbc, 0x6b, 0xc9, 0xda, 0x9f, + 0xef, 0xe2, 0x2d, 0xc3, 0x83, 0xd8, 0xf9, 0x94, 0x18, 0xbc, 0xfe, 0x8f, + 0xa9, 0x44, 0xad, 0xff, 0x1b, 0xcb, 0x86, 0x30, 0x96, 0xa8, 0x3c, 0x7a, + 0x4b, 0x73, 0x1b, 0xa9, 0xc3, 0x3b, 0xaa, 0xd7, 0x44, 0xa8, 0x4d, 0xd6, + 0x92, 0xb6, 0x00, 0x04, 0x09, 0x05, 0x4a, 0x95, 0x02, 0x90, 0x19, 0x8c, + 0x9a, 0xa5, 0xee, 0x58, 0x24, 0xb0, 0xca, 0x5e, 0x6f, 0x73, 0xdb, 0xf5, + 0xa1, 0xf4, 0xf0, 0xa9, 0xeb, 0xe4, 0xdc, 0x55, 0x9f, 0x8f, 0x7a, 0xd0, + 0xf7, 0xb6, 0xaa, 0xa6, 0xb5, 0xb4, 0xab, 0xb8, 0x65, 0xad, 0x12, 0x32, + 0x1c, 0xe6, 0x99, 0x71, 0x93, 0xe8, 0xb4, 0x1e, 0x21, 0x27, 0x52, 0xea, + 0x8c, 0xc8, 0x79, 0x96, 0x2e, 0x48, 0x60, 0x57, 0x1c, 0x7d, 0x8c, 0x0d, + 0x07, 0xa7, 0x12, 0x83, 0x0a, 0x76, 0x6a, 0x64, 0xed, 0xbe, 0x8d, 0xaf, + 0xdf, 0x51, 0x05, 0xdd, 0xf2, 0xd3, 0xb8, 0x93, 0xa9, 0x13, 0xa5, 0x96, + 0xe8, 0xfa, 0x82, 0x02, 0x18, 0x71, 0x7a, 0x71, 0xbb, 0x39, 0x6f, 0x85, + 0xee, 0x16, 0x82, 0x27, 0x42, 0x9f, 0x83, 0xc8, 0xab, 0x6a, 0x3b, 0x99, + 0xba, 0x38, 0x92, 0x38, 0xae, 0x59, 0xfa, 0xaa, 0x40, 0x2b, 0x52, 0x95, + 0xca, 0x5e, 0xe1, 0x9b, 0x00, 0xbd, 0xb9, 0x63, 0x25, 0x8d, 0xc7, 0x22, + 0xaf, 0xe5, 0x67, 0x76, 0x91, 0xf4, 0xda, 0xc9, 0x7e, 0x9e, 0xec, 0x9b, + 0x1f, 0x7d, 0x3b, 0xfe, 0xa1, 0x20, 0x52, 0xac, 0xd0, 0xe5, 0xa6, 0xf1, + 0xfd, 0x4c, 0x08, 0x59, 0x7d, 0x50, 0xbb, 0x0c, 0xcf, 0xd8, 0xb6, 0x0f, + 0xc7, 0x19, 0xcb, 0x7a, 0x96, 0x6f, 0x0f, 0x6c, 0x71, 0x56, 0x72, 0xd1, + 0x06, 0x29, 0x0f, 0x08, 0xa2, 0x46, 0x3e, 0x58, 0x42, 0xc4, 0x8c, 0xe0, + 0x6e, 0xe9, 0x37, 0xd5, 0x2f, 0x74, 0x36, 0x1d, 0x14, 0xcb, 0x10, 0x0e, + 0x7d, 0x67, 0xbd, 0x38, 0x0e, 0xa4, 0x27, 0x1d, 0x3c, 0x78, 0x4d, 0x0d, + 0x15, 0x42, 0x70, 0x20, 0xe0, 0x1d, 0x83, 0x6c, 0x4d, 0xf1, 0x02, 0xa1, + 0x51, 0xc4, 0xc5, 0x5d, 0x69, 0x90, 0x58, 0x82, 0x94, 0x50, 0x36, 0x22, + 0xb3, 0xa4, 0x15, 0x77, 0xdc, 0x44, 0xb0, 0x50, 0xa2, 0x3f, 0xd0, 0x0e, + 0x1b, 0xfc, 0xf4, 0x5b, 0x3b, 0x7d, 0x63, 0x94, 0x22, 0xf3, 0x87, 0x0a, + 0x41, 0x8a, 0x27, 0x48, 0xcb, 0x6c, 0xfd, 0x70, 0x66, 0x5f, 0x11, 0x6f, + 0x74, 0x2c, 0x42, 0xaf, 0x74, 0x45, 0x3f, 0x0c, 0x03, 0xc8, 0x80, 0xe2, + 0x71, 0x08, 0x93, 0xbd, 0x4d, 0x18, 0x78, 0x1e, 0x8e, 0xb9, 0x3a, 0xd6, + 0x1a, 0xde, 0xf9, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x02, 0xb8, 0x7e, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x20, 0x73, + 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x20, 0x61, 0x70, 0x70, + 0x65, 0x6e, 0x64, 0x65, 0x64, 0x7e, 0x0a +}; +unsigned int hi_signed_sha256_len = 739; + +unsigned char short_msg[] = { + 0x68, 0x69, 0x0a +}; +unsigned int short_msg_len = 3; + +unsigned char unsigned_msg[] = { + 0x53, 0x65, 0x64, 0x20, 0x75, 0x74, 0x20, 0x70, 0x65, 0x72, 0x73, 0x70, + 0x69, 0x63, 0x69, 0x61, 0x74, 0x69, 0x73, 0x20, 0x75, 0x6e, 0x64, 0x65, + 0x20, 0x6f, 0x6d, 0x6e, 0x69, 0x73, 0x20, 0x69, 0x73, 0x74, 0x65, 0x20, + 0x6e, 0x61, 0x74, 0x75, 0x73, 0x20, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x20, + 0x73, 0x69, 0x74, 0x20, 0x76, 0x6f, 0x6c, 0x75, 0x70, 0x74, 0x61, 0x74, + 0x65, 0x6d, 0x20, 0x61, 0x63, 0x63, 0x75, 0x73, 0x61, 0x6e, 0x74, 0x69, + 0x75, 0x6d, 0x20, 0x64, 0x6f, 0x6c, 0x6f, 0x72, 0x65, 0x6d, 0x71, 0x75, + 0x65, 0x20, 0x6c, 0x61, 0x75, 0x64, 0x61, 0x6e, 0x74, 0x69, 0x75, 0x6d, + 0x2c, 0x20, 0x74, 0x6f, 0x74, 0x61, 0x6d, 0x20, 0x72, 0x65, 0x6d, 0x20, + 0x61, 0x70, 0x65, 0x72, 0x69, 0x61, 0x6d, 0x2c, 0x20, 0x65, 0x61, 0x71, + 0x75, 0x65, 0x20, 0x69, 0x70, 0x73, 0x61, 0x20, 0x71, 0x75, 0x61, 0x65, + 0x20, 0x61, 0x62, 0x20, 0x69, 0x6c, 0x6c, 0x6f, 0x20, 0x69, 0x6e, 0x76, + 0x65, 0x6e, 0x74, 0x6f, 0x72, 0x65, 0x20, 0x76, 0x65, 0x72, 0x69, 0x74, + 0x61, 0x74, 0x69, 0x73, 0x20, 0x65, 0x74, 0x20, 0x71, 0x75, 0x61, 0x73, + 0x69, 0x20, 0x61, 0x72, 0x63, 0x68, 0x69, 0x74, 0x65, 0x63, 0x74, 0x6f, + 0x20, 0x62, 0x65, 0x61, 0x74, 0x61, 0x65, 0x20, 0x76, 0x69, 0x74, 0x61, + 0x65, 0x20, 0x64, 0x69, 0x63, 0x74, 0x61, 0x20, 0x73, 0x75, 0x6e, 0x74, + 0x20, 0x65, 0x78, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x62, 0x6f, 0x2e, 0x20, + 0x4e, 0x65, 0x6d, 0x6f, 0x20, 0x65, 0x6e, 0x69, 0x6d, 0x20, 0x69, 0x70, + 0x73, 0x61, 0x6d, 0x20, 0x76, 0x6f, 0x6c, 0x75, 0x70, 0x74, 0x61, 0x74, + 0x65, 0x6d, 0x20, 0x71, 0x75, 0x69, 0x61, 0x20, 0x76, 0x6f, 0x6c, 0x75, + 0x70, 0x74, 0x61, 0x73, 0x20, 0x73, 0x69, 0x74, 0x20, 0x61, 0x73, 0x70, + 0x65, 0x72, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x20, 0x61, 0x75, 0x74, 0x20, + 0x6f, 0x64, 0x69, 0x74, 0x20, 0x61, 0x75, 0x74, 0x20, 0x66, 0x75, 0x67, + 0x69, 0x74, 0x2c, 0x20, 0x73, 0x65, 0x64, 0x20, 0x71, 0x75, 0x69, 0x61, + 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x71, 0x75, 0x75, 0x6e, 0x74, 0x75, + 0x72, 0x20, 0x6d, 0x61, 0x67, 0x6e, 0x69, 0x20, 0x64, 0x6f, 0x6c, 0x6f, + 0x72, 0x65, 0x73, 0x20, 0x65, 0x6f, 0x73, 0x20, 0x71, 0x75, 0x69, 0x20, + 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x65, 0x20, 0x76, 0x6f, 0x6c, 0x75, + 0x70, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x20, 0x73, 0x65, 0x71, 0x75, 0x69, + 0x20, 0x6e, 0x65, 0x73, 0x63, 0x69, 0x75, 0x6e, 0x74, 0x2e, 0x20, 0x4e, + 0x65, 0x71, 0x75, 0x65, 0x20, 0x70, 0x6f, 0x72, 0x72, 0x6f, 0x20, 0x71, + 0x75, 0x69, 0x73, 0x71, 0x75, 0x61, 0x6d, 0x20, 0x65, 0x73, 0x74, 0x2c, + 0x20, 0x71, 0x75, 0x69, 0x20, 0x64, 0x6f, 0x6c, 0x6f, 0x72, 0x65, 0x6d, + 0x20, 0x69, 0x70, 0x73, 0x75, 0x6d, 0x20, 0x71, 0x75, 0x69, 0x61, 0x20, + 0x64, 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x73, 0x69, 0x74, 0x20, 0x61, 0x6d, + 0x65, 0x74, 0x2c, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x63, 0x74, 0x65, + 0x74, 0x75, 0x72, 0x2c, 0x20, 0x61, 0x64, 0x69, 0x70, 0x69, 0x73, 0x63, + 0x69, 0x20, 0x76, 0x65, 0x6c, 0x69, 0x74, 0x2c, 0x20, 0x73, 0x65, 0x64, + 0x20, 0x71, 0x75, 0x69, 0x61, 0x20, 0x6e, 0x6f, 0x6e, 0x20, 0x6e, 0x75, + 0x6d, 0x71, 0x75, 0x61, 0x6d, 0x20, 0x65, 0x69, 0x75, 0x73, 0x20, 0x6d, + 0x6f, 0x64, 0x69, 0x20, 0x74, 0x65, 0x6d, 0x70, 0x6f, 0x72, 0x61, 0x20, + 0x69, 0x6e, 0x63, 0x69, 0x64, 0x75, 0x6e, 0x74, 0x20, 0x75, 0x74, 0x20, + 0x6c, 0x61, 0x62, 0x6f, 0x72, 0x65, 0x20, 0x65, 0x74, 0x20, 0x64, 0x6f, + 0x6c, 0x6f, 0x72, 0x65, 0x20, 0x6d, 0x61, 0x67, 0x6e, 0x61, 0x6d, 0x20, + 0x61, 0x6c, 0x69, 0x71, 0x75, 0x61, 0x6d, 0x20, 0x71, 0x75, 0x61, 0x65, + 0x72, 0x61, 0x74, 0x20, 0x76, 0x6f, 0x6c, 0x75, 0x70, 0x74, 0x61, 0x74, + 0x65, 0x6d, 0x2e, 0x20, 0x55, 0x74, 0x20, 0x65, 0x6e, 0x69, 0x6d, 0x20, + 0x61, 0x64, 0x20, 0x6d, 0x69, 0x6e, 0x69, 0x6d, 0x61, 0x20, 0x76, 0x65, + 0x6e, 0x69, 0x61, 0x6d, 0x2c, 0x20, 0x71, 0x75, 0x69, 0x73, 0x20, 0x6e, + 0x6f, 0x73, 0x74, 0x72, 0x75, 0x6d, 0x20, 0x65, 0x78, 0x65, 0x72, 0x63, + 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x65, 0x6d, 0x20, 0x75, 0x6c, + 0x6c, 0x61, 0x6d, 0x20, 0x63, 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x69, 0x73, + 0x20, 0x73, 0x75, 0x73, 0x63, 0x69, 0x70, 0x69, 0x74, 0x20, 0x6c, 0x61, + 0x62, 0x6f, 0x72, 0x69, 0x6f, 0x73, 0x61, 0x6d, 0x2c, 0x20, 0x6e, 0x69, + 0x73, 0x69, 0x20, 0x75, 0x74, 0x20, 0x61, 0x6c, 0x69, 0x71, 0x75, 0x69, + 0x64, 0x20, 0x65, 0x78, 0x20, 0x65, 0x61, 0x20, 0x63, 0x6f, 0x6d, 0x6d, + 0x6f, 0x64, 0x69, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x71, 0x75, 0x61, + 0x74, 0x75, 0x72, 0x3f, 0x20, 0x51, 0x75, 0x69, 0x73, 0x20, 0x61, 0x75, + 0x74, 0x65, 0x6d, 0x20, 0x76, 0x65, 0x6c, 0x20, 0x65, 0x75, 0x6d, 0x20, + 0x69, 0x75, 0x72, 0x65, 0x20, 0x72, 0x65, 0x70, 0x72, 0x65, 0x68, 0x65, + 0x6e, 0x64, 0x65, 0x72, 0x69, 0x74, 0x20, 0x71, 0x75, 0x69, 0x20, 0x69, + 0x6e, 0x20, 0x65, 0x61, 0x20, 0x76, 0x6f, 0x6c, 0x75, 0x70, 0x74, 0x61, + 0x74, 0x65, 0x20, 0x76, 0x65, 0x6c, 0x69, 0x74, 0x20, 0x65, 0x73, 0x73, + 0x65, 0x20, 0x71, 0x75, 0x61, 0x6d, 0x20, 0x6e, 0x69, 0x68, 0x69, 0x6c, + 0x20, 0x6d, 0x6f, 0x6c, 0x65, 0x73, 0x74, 0x69, 0x61, 0x65, 0x20, 0x63, + 0x6f, 0x6e, 0x73, 0x65, 0x71, 0x75, 0x61, 0x74, 0x75, 0x72, 0x2c, 0x20, + 0x76, 0x65, 0x6c, 0x20, 0x69, 0x6c, 0x6c, 0x75, 0x6d, 0x20, 0x71, 0x75, + 0x69, 0x20, 0x64, 0x6f, 0x6c, 0x6f, 0x72, 0x65, 0x6d, 0x20, 0x65, 0x75, + 0x6d, 0x20, 0x66, 0x75, 0x67, 0x69, 0x61, 0x74, 0x20, 0x71, 0x75, 0x6f, + 0x20, 0x76, 0x6f, 0x6c, 0x75, 0x70, 0x74, 0x61, 0x73, 0x20, 0x6e, 0x75, + 0x6c, 0x6c, 0x61, 0x20, 0x70, 0x61, 0x72, 0x69, 0x61, 0x74, 0x75, 0x72, + 0x3f, 0x0a +}; +unsigned int unsigned_msg_len = 866; + +unsigned char certificate2_der[] = { + 0x30, 0x82, 0x05, 0x52, 0x30, 0x82, 0x03, 0x3a, 0xa0, 0x03, 0x02, 0x01, + 0x02, 0x02, 0x14, 0x5b, 0x5e, 0x59, 0xf2, 0x5f, 0x75, 0x4c, 0x8e, 0xc5, + 0x3a, 0x91, 0x07, 0xe9, 0xe7, 0x6d, 0x3c, 0xd0, 0x7f, 0x91, 0xff, 0x30, + 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, + 0x05, 0x00, 0x30, 0x3a, 0x31, 0x38, 0x30, 0x36, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x0c, 0x2f, 0x47, 0x72, 0x75, 0x62, 0x20, 0x32, 0x6e, 0x64, 0x20, + 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, + 0x54, 0x65, 0x73, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, + 0x63, 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, + 0x74, 0x79, 0x30, 0x20, 0x17, 0x0d, 0x32, 0x30, 0x30, 0x37, 0x32, 0x38, + 0x31, 0x33, 0x32, 0x34, 0x32, 0x39, 0x5a, 0x18, 0x0f, 0x32, 0x31, 0x32, + 0x30, 0x30, 0x37, 0x30, 0x34, 0x31, 0x33, 0x32, 0x34, 0x32, 0x39, 0x5a, + 0x30, 0x2b, 0x31, 0x29, 0x30, 0x27, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, + 0x20, 0x47, 0x72, 0x75, 0x62, 0x20, 0x32, 0x6e, 0x64, 0x20, 0x43, 0x65, + 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x53, 0x69, + 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x4b, 0x65, 0x79, 0x30, 0x82, 0x02, + 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, + 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x02, 0x0f, 0x00, 0x30, 0x82, 0x02, + 0x0a, 0x02, 0x82, 0x02, 0x01, 0x00, 0xb0, 0x2f, 0x50, 0x01, 0x9c, 0x0e, + 0xd6, 0x8c, 0x07, 0xca, 0xc1, 0xcf, 0xbc, 0x03, 0xdd, 0xd3, 0xfa, 0xe3, + 0x4f, 0x71, 0xc1, 0x30, 0xaa, 0x09, 0x96, 0xe4, 0xd0, 0x6c, 0x42, 0x93, + 0xdb, 0x35, 0xf6, 0x7e, 0x1b, 0x67, 0xc0, 0xc2, 0x2d, 0x5b, 0xec, 0xca, + 0x35, 0x06, 0x32, 0x6c, 0x7b, 0x2c, 0xd3, 0x71, 0x2b, 0xe9, 0x7a, 0x19, + 0xd1, 0xf2, 0xa0, 0x7f, 0xd7, 0x4d, 0x6e, 0x28, 0xbb, 0xae, 0x49, 0x4a, + 0xbc, 0xea, 0x47, 0x67, 0xb8, 0x36, 0xa6, 0xf5, 0x0d, 0x0e, 0x20, 0x14, + 0x0c, 0x66, 0x67, 0x28, 0xb5, 0x97, 0x8b, 0x1f, 0x5e, 0x32, 0x06, 0x29, + 0x9c, 0x99, 0x92, 0x0f, 0x73, 0xac, 0xfd, 0xd2, 0x1d, 0xf2, 0xa8, 0x55, + 0x9d, 0x1b, 0xd8, 0x3d, 0xb0, 0x76, 0x9a, 0xb6, 0x6c, 0x9f, 0x62, 0x37, + 0x2f, 0xc0, 0xef, 0x44, 0xb3, 0x0d, 0x4a, 0x3e, 0x4f, 0x7d, 0xbd, 0xdb, + 0xd8, 0x75, 0x5f, 0x68, 0xe3, 0xf0, 0xec, 0x82, 0x66, 0x7c, 0x31, 0x70, + 0xa9, 0xa1, 0x6f, 0x38, 0x9f, 0xdf, 0xf5, 0xf0, 0x7d, 0x23, 0x9d, 0x34, + 0xa5, 0x85, 0xd3, 0xdf, 0x68, 0x41, 0xfc, 0x4f, 0x89, 0x45, 0x3c, 0x24, + 0x81, 0xa6, 0xf2, 0x3c, 0x02, 0x26, 0x09, 0x48, 0xdd, 0xfe, 0x4b, 0xb6, + 0x66, 0xbf, 0x8f, 0xe5, 0x5f, 0xf0, 0x5d, 0x8a, 0x61, 0x2e, 0x5f, 0x9f, + 0x80, 0xd9, 0xd5, 0xe6, 0x41, 0xd8, 0x10, 0x5e, 0x7a, 0xc6, 0xdb, 0x89, + 0xc7, 0xca, 0x6c, 0x5b, 0xb1, 0x4e, 0x7d, 0x0c, 0x03, 0xfd, 0x50, 0xca, + 0xbf, 0xbb, 0xe2, 0x69, 0x4b, 0x4e, 0xc2, 0x3d, 0x75, 0xfa, 0xd1, 0xcc, + 0xd6, 0xf9, 0x39, 0xb9, 0xdc, 0x53, 0xad, 0x62, 0xfb, 0x1b, 0x94, 0x26, + 0x7f, 0x21, 0x54, 0x5c, 0xb7, 0xdc, 0xe7, 0x96, 0x8c, 0xce, 0x75, 0xe0, + 0x17, 0x01, 0x3a, 0x3c, 0x77, 0x6e, 0xa4, 0x8b, 0x7a, 0x83, 0x28, 0x7a, + 0xf7, 0xb0, 0x5f, 0xfc, 0x7f, 0x2d, 0x2e, 0xec, 0xf5, 0xeb, 0x9c, 0x63, + 0x74, 0xd0, 0xe5, 0xdc, 0x19, 0xe4, 0x71, 0xc5, 0x4a, 0x8a, 0x54, 0xa4, + 0xe0, 0x7d, 0x4e, 0xbf, 0x53, 0x30, 0xaf, 0xd0, 0xeb, 0x96, 0xc3, 0xbb, + 0x65, 0xf7, 0x67, 0xf5, 0xae, 0xd3, 0x96, 0xf2, 0x63, 0xc8, 0x69, 0xf7, + 0x47, 0xcb, 0x27, 0x79, 0xe1, 0xff, 0x2f, 0x68, 0xdf, 0x1e, 0xb3, 0xb8, + 0x0c, 0xc5, 0x58, 0x73, 0xcc, 0xfe, 0x8c, 0xda, 0x4e, 0x3b, 0x01, 0x04, + 0xcd, 0xcb, 0xb8, 0x3e, 0x06, 0xfd, 0x4c, 0x0a, 0x9f, 0x5e, 0x76, 0x8c, + 0x0c, 0x83, 0x75, 0x09, 0x08, 0xb2, 0xdb, 0xf4, 0x49, 0x4e, 0xa0, 0xf2, + 0x0c, 0x7b, 0x87, 0x38, 0x9e, 0x22, 0x67, 0xbd, 0xd1, 0x97, 0x57, 0x24, + 0xf1, 0x46, 0x07, 0xf9, 0xd2, 0x1b, 0xec, 0x25, 0x5e, 0x67, 0xd9, 0x66, + 0x23, 0x1b, 0xd3, 0xe4, 0xaa, 0xec, 0x88, 0xf0, 0x7e, 0x15, 0x83, 0x51, + 0x31, 0x67, 0x51, 0x76, 0x5f, 0x55, 0xd7, 0x36, 0xdf, 0x4a, 0x84, 0x0b, + 0x6f, 0x5c, 0xbb, 0x5b, 0x8f, 0x37, 0x23, 0x7f, 0xf8, 0x17, 0x84, 0xa2, + 0x70, 0x20, 0x07, 0x0c, 0x90, 0x3a, 0x04, 0xfd, 0xf0, 0x08, 0x4a, 0xb1, + 0x16, 0x0f, 0xe6, 0xf6, 0x40, 0x51, 0x83, 0xd2, 0x87, 0x40, 0x9c, 0x1c, + 0x9f, 0x13, 0x38, 0x17, 0xd3, 0x34, 0x58, 0xad, 0x05, 0x71, 0xa0, 0x73, + 0xca, 0x40, 0xa6, 0xa4, 0x81, 0x02, 0xee, 0xa8, 0x72, 0x41, 0xa1, 0x41, + 0x18, 0x64, 0x8a, 0x86, 0x8a, 0x5d, 0xe6, 0x4f, 0x0a, 0xc5, 0x95, 0x98, + 0xf9, 0x78, 0xfe, 0x19, 0x0d, 0xc9, 0xb3, 0x89, 0xc1, 0x2b, 0x09, 0xbe, + 0xf1, 0xd2, 0x04, 0x5d, 0xcc, 0x28, 0xf5, 0x4b, 0xd2, 0x20, 0x4f, 0xc5, + 0x41, 0x9d, 0x8c, 0x85, 0xd8, 0xb0, 0x68, 0x5e, 0xc1, 0x0c, 0xb7, 0x24, + 0x4d, 0x67, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x5d, 0x30, 0x5b, 0x30, + 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x02, 0x30, + 0x00, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, + 0x07, 0x80, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, + 0x14, 0xac, 0xf5, 0x47, 0x17, 0xd9, 0x7d, 0xc1, 0xb1, 0xc4, 0x41, 0xe1, + 0x41, 0x60, 0xcb, 0x37, 0x11, 0x60, 0x28, 0x78, 0x5f, 0x30, 0x1f, 0x06, + 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x21, 0x94, + 0xfb, 0xf9, 0xb2, 0x43, 0xe9, 0x33, 0xd7, 0x50, 0x7d, 0xc7, 0x37, 0xdb, + 0xd5, 0x82, 0x5a, 0x4e, 0xbe, 0x1b, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, + 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x02, + 0x01, 0x00, 0x96, 0x70, 0x65, 0x26, 0x42, 0xf8, 0xdc, 0x69, 0xde, 0xcf, + 0x41, 0x3a, 0x2e, 0x7f, 0x5b, 0xf1, 0xf9, 0x3b, 0x9b, 0xd2, 0x4e, 0x64, + 0x48, 0x81, 0xe4, 0x5d, 0x1e, 0x22, 0xce, 0x68, 0x63, 0x62, 0xe5, 0x1b, + 0x9b, 0xf2, 0xc7, 0x12, 0xda, 0x1e, 0x9b, 0x90, 0x84, 0x79, 0x48, 0x12, + 0xe6, 0x21, 0x6f, 0x2f, 0x7e, 0x18, 0x77, 0xdb, 0x8c, 0xc4, 0xd1, 0x0d, + 0x91, 0xbf, 0x39, 0x22, 0x0f, 0x64, 0xcf, 0x25, 0x2e, 0x8c, 0x1f, 0x91, + 0x81, 0xb5, 0xe9, 0x6c, 0x02, 0x3a, 0xf8, 0x07, 0xa2, 0x6f, 0x46, 0x5d, + 0x7b, 0xfd, 0x43, 0xff, 0x41, 0x0f, 0xe2, 0x57, 0x1c, 0xbd, 0x48, 0x60, + 0x53, 0x11, 0x48, 0x87, 0x88, 0x9d, 0x13, 0x82, 0x40, 0x68, 0x44, 0x2c, + 0xc6, 0xc8, 0x95, 0x27, 0x4f, 0xb6, 0xb9, 0x4a, 0x22, 0x0a, 0xfd, 0xe4, + 0x46, 0x8f, 0x35, 0x12, 0x98, 0x5a, 0x34, 0x6f, 0x2b, 0x57, 0x62, 0xa1, + 0x4d, 0x8d, 0x79, 0x37, 0xe4, 0x6b, 0x8a, 0x32, 0x5b, 0xcb, 0xef, 0x79, + 0x11, 0xed, 0xa7, 0xf8, 0x7a, 0x1c, 0xbd, 0x86, 0xdc, 0x0e, 0x2e, 0xfd, + 0xd3, 0x51, 0xbb, 0x73, 0xad, 0x00, 0xa0, 0x1b, 0xf9, 0x1d, 0xd1, 0x4a, + 0xe4, 0xd4, 0x02, 0x63, 0x2b, 0x39, 0x5f, 0x18, 0x08, 0x2f, 0x42, 0xb7, + 0x23, 0x4b, 0x48, 0x46, 0x1f, 0x63, 0x87, 0xae, 0x6d, 0xd5, 0xdb, 0x60, + 0xf8, 0x5f, 0xd3, 0x13, 0xec, 0xca, 0xdd, 0x60, 0x60, 0x79, 0x52, 0x70, + 0x47, 0xae, 0x1d, 0x38, 0x78, 0x71, 0xcf, 0xb3, 0x04, 0x03, 0xbe, 0xba, + 0x81, 0xba, 0x74, 0xb1, 0x30, 0x35, 0xdc, 0xea, 0x21, 0x4a, 0x9b, 0x70, + 0xfb, 0xd6, 0x60, 0x59, 0x78, 0x0c, 0x4d, 0x39, 0x19, 0x1d, 0xe5, 0x75, + 0xba, 0x07, 0xf4, 0x22, 0x37, 0x64, 0xb7, 0xf2, 0x9a, 0xc9, 0x11, 0x2d, + 0x8e, 0x58, 0xa6, 0xcf, 0x83, 0xf1, 0xcb, 0x6c, 0x7f, 0x02, 0xbd, 0xda, + 0x03, 0x92, 0xa9, 0x45, 0x24, 0x56, 0xc5, 0xbd, 0x41, 0xd1, 0x20, 0x86, + 0xc0, 0xb6, 0xb7, 0xe8, 0xa7, 0xb2, 0x46, 0xf7, 0x8e, 0xa9, 0x38, 0x0e, + 0x23, 0x77, 0x3c, 0x0d, 0x66, 0x83, 0x6a, 0x1a, 0x6b, 0x7f, 0x54, 0x11, + 0x58, 0x0d, 0x4a, 0xb5, 0x74, 0x60, 0xca, 0xed, 0xff, 0x91, 0x47, 0xd9, + 0x29, 0xe0, 0xaa, 0x8c, 0xa8, 0x8f, 0x10, 0x4c, 0x15, 0x7d, 0xce, 0x95, + 0xf9, 0x87, 0x1e, 0x18, 0x38, 0x18, 0xfc, 0xcc, 0xaf, 0x91, 0x17, 0x3f, + 0xfa, 0xf0, 0x8a, 0x09, 0x6f, 0xba, 0x4e, 0x53, 0xf7, 0xfa, 0x4f, 0x20, + 0xa3, 0xf4, 0x4a, 0x5a, 0xde, 0x17, 0x1c, 0x29, 0x6a, 0x6f, 0x03, 0x48, + 0xdf, 0xad, 0x4f, 0xe4, 0xbc, 0x71, 0xc4, 0x72, 0x32, 0x11, 0x84, 0xac, + 0x09, 0xd2, 0x18, 0x44, 0x35, 0xf1, 0xcd, 0xaf, 0xa8, 0x98, 0xe0, 0x8b, + 0xec, 0xa0, 0x83, 0x37, 0xc3, 0x35, 0x85, 0xd6, 0xd8, 0x1b, 0xe0, 0x75, + 0xdc, 0xfd, 0xde, 0xc9, 0xeb, 0xd5, 0x18, 0x0f, 0xd3, 0x4c, 0x2f, 0x71, + 0xdc, 0x48, 0xe3, 0x14, 0xeb, 0xda, 0x00, 0x24, 0x24, 0x9e, 0xa3, 0x8e, + 0x3e, 0x08, 0x6f, 0x22, 0x24, 0xd6, 0xc4, 0x85, 0x8f, 0x68, 0x00, 0x4a, + 0x82, 0x4c, 0x33, 0x6e, 0xa5, 0x35, 0x7b, 0xeb, 0x4b, 0xdc, 0xa0, 0xa6, + 0x65, 0x6f, 0x5a, 0x7a, 0xdf, 0x8a, 0x01, 0x52, 0xa1, 0x6c, 0xff, 0x59, + 0x22, 0x7f, 0xe1, 0x96, 0x1b, 0x19, 0xb8, 0xf9, 0x5d, 0x44, 0x9f, 0x91, + 0x03, 0x3c, 0x3d, 0xa1, 0x2a, 0xb6, 0x5a, 0x51, 0xa0, 0xce, 0x4a, 0x88, + 0x22, 0x72, 0x9c, 0xdc, 0xc0, 0x47, 0x76, 0x35, 0x84, 0x75, 0x9b, 0x87, + 0x5c, 0xd3, 0xcf, 0xe7, 0xdd, 0xa3, 0x57, 0x14, 0xdf, 0x00, 0xfd, 0x19, + 0x2a, 0x7d, 0x89, 0x27, 0x1c, 0x78, 0x97, 0x04, 0x58, 0x48 +}; +unsigned int certificate2_der_len = 1366; + +unsigned char hi_signed_2nd[] = { + 0x68, 0x69, 0x0a, 0x30, 0x82, 0x02, 0xb1, 0x06, 0x09, 0x2a, 0x86, 0x48, + 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x02, 0xa0, 0x82, 0x02, 0xa2, 0x30, 0x82, + 0x02, 0x9e, 0x02, 0x01, 0x01, 0x31, 0x0d, 0x30, 0x0b, 0x06, 0x09, 0x60, + 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x30, 0x0b, 0x06, 0x09, + 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0x31, 0x82, 0x02, + 0x7b, 0x30, 0x82, 0x02, 0x77, 0x02, 0x01, 0x01, 0x30, 0x52, 0x30, 0x3a, + 0x31, 0x38, 0x30, 0x36, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x2f, 0x47, + 0x72, 0x75, 0x62, 0x20, 0x32, 0x6e, 0x64, 0x20, 0x43, 0x65, 0x72, 0x74, + 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x54, 0x65, 0x73, 0x74, + 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, + 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x02, 0x14, + 0x5b, 0x5e, 0x59, 0xf2, 0x5f, 0x75, 0x4c, 0x8e, 0xc5, 0x3a, 0x91, 0x07, + 0xe9, 0xe7, 0x6d, 0x3c, 0xd0, 0x7f, 0x91, 0xff, 0x30, 0x0b, 0x06, 0x09, + 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x30, 0x0d, 0x06, + 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, + 0x04, 0x82, 0x02, 0x00, 0x0e, 0xc2, 0x30, 0x38, 0x81, 0x23, 0x68, 0x90, + 0xae, 0x5f, 0xce, 0xf7, 0x27, 0xb1, 0x8c, 0x2e, 0x12, 0x10, 0xc6, 0x99, + 0xdc, 0x4d, 0x4b, 0x79, 0xda, 0xe4, 0x32, 0x10, 0x46, 0x1c, 0x16, 0x07, + 0x87, 0x66, 0x55, 0xff, 0x64, 0x1c, 0x61, 0x25, 0xd5, 0xb9, 0xe1, 0xfe, + 0xea, 0x5a, 0xcd, 0x56, 0xa5, 0xc3, 0xbe, 0xb1, 0x61, 0xc7, 0x6f, 0x5f, + 0x69, 0x20, 0x64, 0x50, 0x6f, 0x12, 0x78, 0xb6, 0x0c, 0x72, 0x44, 0x4f, + 0x60, 0x0f, 0x9f, 0xa2, 0x83, 0x3b, 0xc2, 0x83, 0xd5, 0x14, 0x1f, 0x6f, + 0x3e, 0xb2, 0x47, 0xb5, 0x58, 0xc5, 0xa7, 0xb4, 0x82, 0x53, 0x2e, 0x53, + 0x95, 0x4e, 0x3d, 0xe4, 0x62, 0xe8, 0xa1, 0xaf, 0xae, 0xbf, 0xa9, 0xd2, + 0x22, 0x07, 0xbe, 0x71, 0x37, 0x2c, 0x5a, 0xa7, 0x6c, 0xaf, 0x14, 0xc0, + 0x6c, 0x2f, 0xbf, 0x4f, 0x15, 0xc2, 0x0f, 0x8b, 0xdc, 0x68, 0x45, 0xdf, + 0xf3, 0xa5, 0x7f, 0x11, 0x6a, 0x54, 0xcd, 0x67, 0xb9, 0x2e, 0x7d, 0x05, + 0xe3, 0x1c, 0x1d, 0xcc, 0x77, 0x8e, 0x97, 0xb1, 0xa0, 0x11, 0x09, 0x3d, + 0x90, 0x54, 0xfc, 0x7e, 0xbb, 0xbb, 0x21, 0x23, 0x03, 0x44, 0xbf, 0x7d, + 0x2c, 0xc9, 0x15, 0x42, 0xe5, 0xa0, 0x3b, 0xa2, 0xd1, 0x5b, 0x73, 0x81, + 0xff, 0xfa, 0x90, 0xfc, 0x27, 0x7b, 0x2f, 0x86, 0x9c, 0x1d, 0x14, 0x36, + 0x94, 0xa2, 0x6e, 0xe8, 0x9d, 0xa0, 0x5f, 0xfc, 0x5a, 0x0d, 0xa4, 0xd5, + 0x2f, 0x8d, 0xd6, 0x00, 0xfa, 0x93, 0x5b, 0x09, 0x7f, 0x42, 0x78, 0xcc, + 0x8c, 0x49, 0xda, 0xd9, 0xf6, 0x43, 0xe7, 0xe1, 0x3c, 0xa2, 0xe2, 0x70, + 0xe2, 0x6a, 0x99, 0xc5, 0xd6, 0xa2, 0xe3, 0x0b, 0xd4, 0x09, 0xac, 0x94, + 0xaf, 0xb7, 0xf0, 0xb3, 0x0c, 0x1e, 0xf5, 0x16, 0x4f, 0x53, 0x9a, 0xe3, + 0xcc, 0xe2, 0x0c, 0x4a, 0xb9, 0xe6, 0x06, 0xbb, 0xf7, 0x41, 0x43, 0x20, + 0x04, 0xee, 0x99, 0x2f, 0xd8, 0x9f, 0xda, 0x3f, 0xfd, 0x49, 0xb8, 0xc2, + 0xbd, 0xd9, 0xc5, 0x72, 0xfd, 0xe3, 0xce, 0x1c, 0xbc, 0xe4, 0x39, 0xac, + 0x2a, 0x99, 0xe9, 0xb4, 0x3e, 0x74, 0x10, 0xeb, 0xd5, 0x14, 0xcc, 0xdb, + 0xf1, 0x04, 0x63, 0x36, 0xfb, 0x1f, 0x2b, 0xe2, 0x73, 0xd4, 0xd8, 0x49, + 0x31, 0xa8, 0x55, 0xcc, 0xa7, 0x76, 0x36, 0x6e, 0x18, 0xdc, 0xb9, 0xb0, + 0x29, 0x99, 0xcf, 0x49, 0xbf, 0xf9, 0xdb, 0x7f, 0x24, 0x42, 0x02, 0xcb, + 0xc1, 0xaa, 0xcb, 0xba, 0x18, 0x85, 0x86, 0xc7, 0xf4, 0x1c, 0x62, 0x76, + 0xbc, 0x73, 0xfb, 0xe4, 0x15, 0xb8, 0xdd, 0x5d, 0xa6, 0x68, 0x39, 0xa5, + 0x3d, 0x33, 0xaf, 0xd5, 0x92, 0x4d, 0x48, 0xdb, 0x22, 0xc0, 0xdc, 0x49, + 0x5f, 0x7b, 0xa8, 0xd2, 0x62, 0x2d, 0xa7, 0x39, 0x93, 0x48, 0xe7, 0x6b, + 0x23, 0xba, 0xd4, 0xe0, 0xc1, 0x29, 0x55, 0xc4, 0x34, 0xe3, 0xac, 0x25, + 0xa7, 0x15, 0xad, 0xab, 0xb3, 0xb7, 0x25, 0xca, 0x37, 0x88, 0x40, 0x2e, + 0x47, 0x6e, 0x92, 0x20, 0x09, 0x2e, 0x5a, 0xec, 0xf2, 0xfb, 0xb3, 0xa0, + 0x16, 0xb6, 0x93, 0xf2, 0xf5, 0x8b, 0xfe, 0xaf, 0x25, 0xee, 0x2e, 0x98, + 0x6c, 0x0a, 0xfe, 0xae, 0x0b, 0x57, 0xf5, 0x9f, 0x3c, 0x80, 0xe9, 0x8b, + 0xaf, 0x92, 0x8a, 0xad, 0xe7, 0xa0, 0xe4, 0xe6, 0x0a, 0xa0, 0xc7, 0x83, + 0xb5, 0x48, 0x58, 0x5f, 0x55, 0x9e, 0x9b, 0x27, 0xcd, 0x31, 0x1f, 0x3e, + 0x50, 0x5a, 0x91, 0xad, 0x21, 0x1b, 0x97, 0x5b, 0xe8, 0xfa, 0x29, 0x8a, + 0xa4, 0x17, 0xe8, 0xab, 0x87, 0x02, 0xd6, 0x18, 0x8c, 0x9f, 0x65, 0xb7, + 0x2a, 0xfa, 0xde, 0x5f, 0x77, 0x30, 0x6c, 0x04, 0x22, 0xe6, 0x58, 0x26, + 0x14, 0x0d, 0x9c, 0x41, 0x0a, 0x82, 0x77, 0xdb, 0x40, 0xa1, 0x58, 0xac, + 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xb5, + 0x7e, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x20, 0x73, 0x69, 0x67, 0x6e, + 0x61, 0x74, 0x75, 0x72, 0x65, 0x20, 0x61, 0x70, 0x70, 0x65, 0x6e, 0x64, + 0x65, 0x64, 0x7e, 0x0a +}; +unsigned int hi_signed_2nd_len = 736; + +unsigned char hi_double[] = { + 0x68, 0x69, 0x0a, 0x30, 0x82, 0x05, 0x2f, 0x06, 0x09, 0x2a, 0x86, 0x48, + 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x02, 0xa0, 0x82, 0x05, 0x20, 0x30, 0x82, + 0x05, 0x1c, 0x02, 0x01, 0x01, 0x31, 0x0d, 0x30, 0x0b, 0x06, 0x09, 0x60, + 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x30, 0x0b, 0x06, 0x09, + 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0x31, 0x82, 0x04, + 0xf9, 0x30, 0x82, 0x02, 0x77, 0x02, 0x01, 0x01, 0x30, 0x52, 0x30, 0x3a, + 0x31, 0x38, 0x30, 0x36, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x2f, 0x47, + 0x72, 0x75, 0x62, 0x20, 0x32, 0x6e, 0x64, 0x20, 0x43, 0x65, 0x72, 0x74, + 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x54, 0x65, 0x73, 0x74, + 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, + 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x02, 0x14, + 0x5b, 0x5e, 0x59, 0xf2, 0x5f, 0x75, 0x4c, 0x8e, 0xc5, 0x3a, 0x91, 0x07, + 0xe9, 0xe7, 0x6d, 0x3c, 0xd0, 0x7f, 0x91, 0xff, 0x30, 0x0b, 0x06, 0x09, + 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x30, 0x0d, 0x06, + 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, + 0x04, 0x82, 0x02, 0x00, 0x0e, 0xc2, 0x30, 0x38, 0x81, 0x23, 0x68, 0x90, + 0xae, 0x5f, 0xce, 0xf7, 0x27, 0xb1, 0x8c, 0x2e, 0x12, 0x10, 0xc6, 0x99, + 0xdc, 0x4d, 0x4b, 0x79, 0xda, 0xe4, 0x32, 0x10, 0x46, 0x1c, 0x16, 0x07, + 0x87, 0x66, 0x55, 0xff, 0x64, 0x1c, 0x61, 0x25, 0xd5, 0xb9, 0xe1, 0xfe, + 0xea, 0x5a, 0xcd, 0x56, 0xa5, 0xc3, 0xbe, 0xb1, 0x61, 0xc7, 0x6f, 0x5f, + 0x69, 0x20, 0x64, 0x50, 0x6f, 0x12, 0x78, 0xb6, 0x0c, 0x72, 0x44, 0x4f, + 0x60, 0x0f, 0x9f, 0xa2, 0x83, 0x3b, 0xc2, 0x83, 0xd5, 0x14, 0x1f, 0x6f, + 0x3e, 0xb2, 0x47, 0xb5, 0x58, 0xc5, 0xa7, 0xb4, 0x82, 0x53, 0x2e, 0x53, + 0x95, 0x4e, 0x3d, 0xe4, 0x62, 0xe8, 0xa1, 0xaf, 0xae, 0xbf, 0xa9, 0xd2, + 0x22, 0x07, 0xbe, 0x71, 0x37, 0x2c, 0x5a, 0xa7, 0x6c, 0xaf, 0x14, 0xc0, + 0x6c, 0x2f, 0xbf, 0x4f, 0x15, 0xc2, 0x0f, 0x8b, 0xdc, 0x68, 0x45, 0xdf, + 0xf3, 0xa5, 0x7f, 0x11, 0x6a, 0x54, 0xcd, 0x67, 0xb9, 0x2e, 0x7d, 0x05, + 0xe3, 0x1c, 0x1d, 0xcc, 0x77, 0x8e, 0x97, 0xb1, 0xa0, 0x11, 0x09, 0x3d, + 0x90, 0x54, 0xfc, 0x7e, 0xbb, 0xbb, 0x21, 0x23, 0x03, 0x44, 0xbf, 0x7d, + 0x2c, 0xc9, 0x15, 0x42, 0xe5, 0xa0, 0x3b, 0xa2, 0xd1, 0x5b, 0x73, 0x81, + 0xff, 0xfa, 0x90, 0xfc, 0x27, 0x7b, 0x2f, 0x86, 0x9c, 0x1d, 0x14, 0x36, + 0x94, 0xa2, 0x6e, 0xe8, 0x9d, 0xa0, 0x5f, 0xfc, 0x5a, 0x0d, 0xa4, 0xd5, + 0x2f, 0x8d, 0xd6, 0x00, 0xfa, 0x93, 0x5b, 0x09, 0x7f, 0x42, 0x78, 0xcc, + 0x8c, 0x49, 0xda, 0xd9, 0xf6, 0x43, 0xe7, 0xe1, 0x3c, 0xa2, 0xe2, 0x70, + 0xe2, 0x6a, 0x99, 0xc5, 0xd6, 0xa2, 0xe3, 0x0b, 0xd4, 0x09, 0xac, 0x94, + 0xaf, 0xb7, 0xf0, 0xb3, 0x0c, 0x1e, 0xf5, 0x16, 0x4f, 0x53, 0x9a, 0xe3, + 0xcc, 0xe2, 0x0c, 0x4a, 0xb9, 0xe6, 0x06, 0xbb, 0xf7, 0x41, 0x43, 0x20, + 0x04, 0xee, 0x99, 0x2f, 0xd8, 0x9f, 0xda, 0x3f, 0xfd, 0x49, 0xb8, 0xc2, + 0xbd, 0xd9, 0xc5, 0x72, 0xfd, 0xe3, 0xce, 0x1c, 0xbc, 0xe4, 0x39, 0xac, + 0x2a, 0x99, 0xe9, 0xb4, 0x3e, 0x74, 0x10, 0xeb, 0xd5, 0x14, 0xcc, 0xdb, + 0xf1, 0x04, 0x63, 0x36, 0xfb, 0x1f, 0x2b, 0xe2, 0x73, 0xd4, 0xd8, 0x49, + 0x31, 0xa8, 0x55, 0xcc, 0xa7, 0x76, 0x36, 0x6e, 0x18, 0xdc, 0xb9, 0xb0, + 0x29, 0x99, 0xcf, 0x49, 0xbf, 0xf9, 0xdb, 0x7f, 0x24, 0x42, 0x02, 0xcb, + 0xc1, 0xaa, 0xcb, 0xba, 0x18, 0x85, 0x86, 0xc7, 0xf4, 0x1c, 0x62, 0x76, + 0xbc, 0x73, 0xfb, 0xe4, 0x15, 0xb8, 0xdd, 0x5d, 0xa6, 0x68, 0x39, 0xa5, + 0x3d, 0x33, 0xaf, 0xd5, 0x92, 0x4d, 0x48, 0xdb, 0x22, 0xc0, 0xdc, 0x49, + 0x5f, 0x7b, 0xa8, 0xd2, 0x62, 0x2d, 0xa7, 0x39, 0x93, 0x48, 0xe7, 0x6b, + 0x23, 0xba, 0xd4, 0xe0, 0xc1, 0x29, 0x55, 0xc4, 0x34, 0xe3, 0xac, 0x25, + 0xa7, 0x15, 0xad, 0xab, 0xb3, 0xb7, 0x25, 0xca, 0x37, 0x88, 0x40, 0x2e, + 0x47, 0x6e, 0x92, 0x20, 0x09, 0x2e, 0x5a, 0xec, 0xf2, 0xfb, 0xb3, 0xa0, + 0x16, 0xb6, 0x93, 0xf2, 0xf5, 0x8b, 0xfe, 0xaf, 0x25, 0xee, 0x2e, 0x98, + 0x6c, 0x0a, 0xfe, 0xae, 0x0b, 0x57, 0xf5, 0x9f, 0x3c, 0x80, 0xe9, 0x8b, + 0xaf, 0x92, 0x8a, 0xad, 0xe7, 0xa0, 0xe4, 0xe6, 0x0a, 0xa0, 0xc7, 0x83, + 0xb5, 0x48, 0x58, 0x5f, 0x55, 0x9e, 0x9b, 0x27, 0xcd, 0x31, 0x1f, 0x3e, + 0x50, 0x5a, 0x91, 0xad, 0x21, 0x1b, 0x97, 0x5b, 0xe8, 0xfa, 0x29, 0x8a, + 0xa4, 0x17, 0xe8, 0xab, 0x87, 0x02, 0xd6, 0x18, 0x8c, 0x9f, 0x65, 0xb7, + 0x2a, 0xfa, 0xde, 0x5f, 0x77, 0x30, 0x6c, 0x04, 0x22, 0xe6, 0x58, 0x26, + 0x14, 0x0d, 0x9c, 0x41, 0x0a, 0x82, 0x77, 0xdb, 0x40, 0xa1, 0x58, 0xac, + 0x30, 0x82, 0x02, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x55, 0x30, 0x3d, 0x31, + 0x3b, 0x30, 0x39, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x32, 0x47, 0x72, + 0x75, 0x62, 0x20, 0x41, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x64, 0x20, + 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x20, 0x54, 0x65, + 0x73, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, + 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, + 0x02, 0x14, 0x5b, 0x5e, 0x59, 0xf2, 0x5f, 0x75, 0x4c, 0x8e, 0xc5, 0x3a, + 0x91, 0x07, 0xe9, 0xe7, 0x6d, 0x3c, 0xd0, 0x7f, 0x92, 0x03, 0x30, 0x0b, + 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x30, + 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, + 0x05, 0x00, 0x04, 0x82, 0x02, 0x00, 0xa0, 0x83, 0x3f, 0xac, 0x77, 0x97, + 0x74, 0x9b, 0x4b, 0x25, 0xa1, 0x64, 0x09, 0x8d, 0x53, 0xa6, 0x03, 0xdf, + 0x9a, 0x10, 0x52, 0xe5, 0x3f, 0xd4, 0x72, 0x75, 0x30, 0xd4, 0x6e, 0x77, + 0x32, 0x49, 0x84, 0xe2, 0xbe, 0xef, 0xe4, 0xf3, 0xac, 0xb0, 0x52, 0x55, + 0xbf, 0xa9, 0x57, 0x12, 0x08, 0x7d, 0xb0, 0x86, 0xc0, 0x9d, 0x01, 0xc2, + 0x1a, 0x4a, 0x2e, 0x3d, 0xd5, 0xc8, 0x56, 0xac, 0xd1, 0x83, 0x75, 0x88, + 0xd4, 0xcc, 0x9f, 0x0d, 0xcf, 0xd3, 0xa6, 0x91, 0xb6, 0xb6, 0xb1, 0xd1, + 0x24, 0x9c, 0xd0, 0x13, 0xe8, 0x6b, 0x15, 0x9c, 0x62, 0x33, 0x8d, 0xe3, + 0x67, 0x9b, 0xb1, 0x8a, 0x72, 0x38, 0xf7, 0x48, 0x32, 0x2f, 0x1e, 0x45, + 0xa8, 0xc4, 0xa5, 0xae, 0xb1, 0xfc, 0x35, 0x25, 0xb5, 0xf9, 0x7f, 0x86, + 0xef, 0xa2, 0x6d, 0x78, 0xcc, 0xfd, 0x0c, 0xca, 0x8a, 0xe1, 0xae, 0xcd, + 0x0f, 0x58, 0x69, 0xf1, 0x8b, 0xcc, 0x22, 0x35, 0x6d, 0x1f, 0xd5, 0x27, + 0x87, 0x39, 0x62, 0x3f, 0xb2, 0x17, 0x3d, 0x5e, 0xb1, 0x32, 0x7a, 0xf1, + 0x70, 0xce, 0xfa, 0xab, 0x1c, 0x92, 0xa8, 0xe1, 0xc4, 0xb2, 0x33, 0x1a, + 0x16, 0xf3, 0x60, 0x39, 0xdf, 0xb8, 0x85, 0xe7, 0x5d, 0x4d, 0xc2, 0x8d, + 0x55, 0x00, 0x49, 0x94, 0x04, 0x17, 0x88, 0x7c, 0xf4, 0xac, 0xa9, 0xc5, + 0x3a, 0x09, 0xc4, 0xc2, 0xcd, 0x3d, 0xc3, 0xfc, 0x4e, 0xf3, 0x70, 0xa1, + 0xc1, 0x54, 0x36, 0x1f, 0x38, 0x6d, 0x7a, 0x6b, 0x6a, 0xd3, 0x67, 0x04, + 0xd5, 0x53, 0xd4, 0xa5, 0xad, 0x63, 0x55, 0x0e, 0x06, 0x06, 0x3a, 0x9a, + 0xc5, 0xfe, 0x38, 0xc9, 0xb0, 0x69, 0x42, 0x90, 0x35, 0x1f, 0xe3, 0x1c, + 0x57, 0xea, 0xdb, 0x51, 0x35, 0x53, 0xd3, 0x94, 0xfe, 0x72, 0x33, 0xd6, + 0x8a, 0x46, 0x74, 0xf9, 0x6e, 0x94, 0x40, 0x2f, 0xba, 0xa2, 0xc4, 0xe9, + 0xc9, 0x8a, 0xf4, 0xda, 0xe2, 0xca, 0x3e, 0x98, 0x85, 0xa5, 0xd1, 0x60, + 0x94, 0xc8, 0xdf, 0x82, 0xee, 0x5c, 0x0d, 0x2a, 0xa9, 0x8e, 0x26, 0x83, + 0x3f, 0x02, 0xa2, 0xaf, 0xb8, 0x3b, 0x83, 0xf2, 0x44, 0x46, 0x41, 0xd7, + 0x5c, 0xa1, 0x42, 0x17, 0xa2, 0xd0, 0x50, 0x42, 0xef, 0x66, 0xda, 0x35, + 0x03, 0xd1, 0x8e, 0x77, 0x22, 0x7d, 0x4e, 0xf7, 0x4e, 0x04, 0xe3, 0x0f, + 0x98, 0x7d, 0xaa, 0x58, 0xba, 0xef, 0x9a, 0xd0, 0x88, 0x7c, 0x98, 0xa0, + 0xc2, 0xff, 0xa6, 0xb1, 0xec, 0xbe, 0x6e, 0xb0, 0x7e, 0xc6, 0xe5, 0xaa, + 0xcf, 0x10, 0x73, 0xc9, 0x13, 0x1a, 0x20, 0x12, 0x5c, 0xd2, 0x0e, 0xe2, + 0x60, 0x17, 0xdf, 0x4a, 0x44, 0x08, 0x22, 0xbc, 0xcd, 0x75, 0xbe, 0xc3, + 0x7a, 0x12, 0x90, 0x90, 0xc7, 0x94, 0x4c, 0x98, 0x45, 0x02, 0x5c, 0x24, + 0xae, 0x82, 0x2f, 0xcd, 0x30, 0xa6, 0xf5, 0x3f, 0xd3, 0xa7, 0xa6, 0xe6, + 0xea, 0x11, 0x4e, 0x45, 0xb7, 0xc0, 0xe6, 0x24, 0x8b, 0x76, 0xc5, 0x5e, + 0xc1, 0xd8, 0x07, 0x1e, 0x26, 0x94, 0x7a, 0x80, 0xc6, 0x3b, 0x1f, 0x74, + 0xe6, 0xae, 0x43, 0x2d, 0x11, 0xee, 0x96, 0x56, 0x6c, 0xff, 0xcb, 0x3b, + 0xde, 0xcc, 0xb3, 0x7b, 0x08, 0xf5, 0x3e, 0x6e, 0x51, 0x71, 0xe0, 0x8a, + 0xfa, 0xdd, 0x19, 0x39, 0xcf, 0x3f, 0x29, 0x4f, 0x2d, 0xd2, 0xd4, 0xdc, + 0x5c, 0xc4, 0xd1, 0xa7, 0xf5, 0xbf, 0x4a, 0xc0, 0x9b, 0xb4, 0x2b, 0x83, + 0x7a, 0x63, 0x4d, 0x20, 0x40, 0x8b, 0x11, 0x5c, 0x53, 0xd4, 0x52, 0x21, + 0xe7, 0xe4, 0x1f, 0x01, 0xf6, 0xd1, 0x25, 0x28, 0xba, 0x51, 0x6f, 0x51, + 0x69, 0xf4, 0x41, 0x45, 0x75, 0x23, 0x25, 0x77, 0xef, 0xa8, 0x1c, 0x19, + 0x8a, 0x66, 0x8c, 0x61, 0x13, 0x37, 0x4f, 0xa3, 0xa1, 0x83, 0x17, 0x35, + 0x23, 0x2d, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x05, 0x33, 0x7e, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x20, 0x73, 0x69, + 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x20, 0x61, 0x70, 0x70, 0x65, + 0x6e, 0x64, 0x65, 0x64, 0x7e, 0x0a +}; +unsigned int hi_double_len = 1374; + +unsigned char hi_double_extended[] = { + 0x68, 0x69, 0x0a, 0x30, 0x82, 0x05, 0x2f, 0x06, 0x09, 0x2a, 0x86, 0x48, + 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x02, 0xa0, 0x82, 0x05, 0x20, 0x30, 0x82, + 0x05, 0x1c, 0x02, 0x01, 0x01, 0x31, 0x0d, 0x30, 0x0b, 0x06, 0x09, 0x60, + 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x30, 0x0b, 0x06, 0x09, + 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0x31, 0x82, 0x04, + 0xf9, 0x30, 0x82, 0x02, 0x77, 0x02, 0x01, 0x01, 0x30, 0x52, 0x30, 0x3a, + 0x31, 0x38, 0x30, 0x36, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x2f, 0x47, + 0x72, 0x75, 0x62, 0x20, 0x32, 0x6e, 0x64, 0x20, 0x43, 0x65, 0x72, 0x74, + 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x54, 0x65, 0x73, 0x74, + 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, + 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x02, 0x14, + 0x5b, 0x5e, 0x59, 0xf2, 0x5f, 0x75, 0x4c, 0x8e, 0xc5, 0x3a, 0x91, 0x07, + 0xe9, 0xe7, 0x6d, 0x3c, 0xd0, 0x7f, 0x91, 0xff, 0x30, 0x0b, 0x06, 0x09, + 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x30, 0x0d, 0x06, + 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, + 0x04, 0x82, 0x02, 0x00, 0x0e, 0xc2, 0x30, 0x38, 0x81, 0x23, 0x68, 0x90, + 0xae, 0x5f, 0xce, 0xf7, 0x27, 0xb1, 0x8c, 0x2e, 0x12, 0x10, 0xc6, 0x99, + 0xdc, 0x4d, 0x4b, 0x79, 0xda, 0xe4, 0x32, 0x10, 0x46, 0x1c, 0x16, 0x07, + 0x87, 0x66, 0x55, 0xff, 0x64, 0x1c, 0x61, 0x25, 0xd5, 0xb9, 0xe1, 0xfe, + 0xea, 0x5a, 0xcd, 0x56, 0xa5, 0xc3, 0xbe, 0xb1, 0x61, 0xc7, 0x6f, 0x5f, + 0x69, 0x20, 0x64, 0x50, 0x6f, 0x12, 0x78, 0xb6, 0x0c, 0x72, 0x44, 0x4f, + 0x60, 0x0f, 0x9f, 0xa2, 0x83, 0x3b, 0xc2, 0x83, 0xd5, 0x14, 0x1f, 0x6f, + 0x3e, 0xb2, 0x47, 0xb5, 0x58, 0xc5, 0xa7, 0xb4, 0x82, 0x53, 0x2e, 0x53, + 0x95, 0x4e, 0x3d, 0xe4, 0x62, 0xe8, 0xa1, 0xaf, 0xae, 0xbf, 0xa9, 0xd2, + 0x22, 0x07, 0xbe, 0x71, 0x37, 0x2c, 0x5a, 0xa7, 0x6c, 0xaf, 0x14, 0xc0, + 0x6c, 0x2f, 0xbf, 0x4f, 0x15, 0xc2, 0x0f, 0x8b, 0xdc, 0x68, 0x45, 0xdf, + 0xf3, 0xa5, 0x7f, 0x11, 0x6a, 0x54, 0xcd, 0x67, 0xb9, 0x2e, 0x7d, 0x05, + 0xe3, 0x1c, 0x1d, 0xcc, 0x77, 0x8e, 0x97, 0xb1, 0xa0, 0x11, 0x09, 0x3d, + 0x90, 0x54, 0xfc, 0x7e, 0xbb, 0xbb, 0x21, 0x23, 0x03, 0x44, 0xbf, 0x7d, + 0x2c, 0xc9, 0x15, 0x42, 0xe5, 0xa0, 0x3b, 0xa2, 0xd1, 0x5b, 0x73, 0x81, + 0xff, 0xfa, 0x90, 0xfc, 0x27, 0x7b, 0x2f, 0x86, 0x9c, 0x1d, 0x14, 0x36, + 0x94, 0xa2, 0x6e, 0xe8, 0x9d, 0xa0, 0x5f, 0xfc, 0x5a, 0x0d, 0xa4, 0xd5, + 0x2f, 0x8d, 0xd6, 0x00, 0xfa, 0x93, 0x5b, 0x09, 0x7f, 0x42, 0x78, 0xcc, + 0x8c, 0x49, 0xda, 0xd9, 0xf6, 0x43, 0xe7, 0xe1, 0x3c, 0xa2, 0xe2, 0x70, + 0xe2, 0x6a, 0x99, 0xc5, 0xd6, 0xa2, 0xe3, 0x0b, 0xd4, 0x09, 0xac, 0x94, + 0xaf, 0xb7, 0xf0, 0xb3, 0x0c, 0x1e, 0xf5, 0x16, 0x4f, 0x53, 0x9a, 0xe3, + 0xcc, 0xe2, 0x0c, 0x4a, 0xb9, 0xe6, 0x06, 0xbb, 0xf7, 0x41, 0x43, 0x20, + 0x04, 0xee, 0x99, 0x2f, 0xd8, 0x9f, 0xda, 0x3f, 0xfd, 0x49, 0xb8, 0xc2, + 0xbd, 0xd9, 0xc5, 0x72, 0xfd, 0xe3, 0xce, 0x1c, 0xbc, 0xe4, 0x39, 0xac, + 0x2a, 0x99, 0xe9, 0xb4, 0x3e, 0x74, 0x10, 0xeb, 0xd5, 0x14, 0xcc, 0xdb, + 0xf1, 0x04, 0x63, 0x36, 0xfb, 0x1f, 0x2b, 0xe2, 0x73, 0xd4, 0xd8, 0x49, + 0x31, 0xa8, 0x55, 0xcc, 0xa7, 0x76, 0x36, 0x6e, 0x18, 0xdc, 0xb9, 0xb0, + 0x29, 0x99, 0xcf, 0x49, 0xbf, 0xf9, 0xdb, 0x7f, 0x24, 0x42, 0x02, 0xcb, + 0xc1, 0xaa, 0xcb, 0xba, 0x18, 0x85, 0x86, 0xc7, 0xf4, 0x1c, 0x62, 0x76, + 0xbc, 0x73, 0xfb, 0xe4, 0x15, 0xb8, 0xdd, 0x5d, 0xa6, 0x68, 0x39, 0xa5, + 0x3d, 0x33, 0xaf, 0xd5, 0x92, 0x4d, 0x48, 0xdb, 0x22, 0xc0, 0xdc, 0x49, + 0x5f, 0x7b, 0xa8, 0xd2, 0x62, 0x2d, 0xa7, 0x39, 0x93, 0x48, 0xe7, 0x6b, + 0x23, 0xba, 0xd4, 0xe0, 0xc1, 0x29, 0x55, 0xc4, 0x34, 0xe3, 0xac, 0x25, + 0xa7, 0x15, 0xad, 0xab, 0xb3, 0xb7, 0x25, 0xca, 0x37, 0x88, 0x40, 0x2e, + 0x47, 0x6e, 0x92, 0x20, 0x09, 0x2e, 0x5a, 0xec, 0xf2, 0xfb, 0xb3, 0xa0, + 0x16, 0xb6, 0x93, 0xf2, 0xf5, 0x8b, 0xfe, 0xaf, 0x25, 0xee, 0x2e, 0x98, + 0x6c, 0x0a, 0xfe, 0xae, 0x0b, 0x57, 0xf5, 0x9f, 0x3c, 0x80, 0xe9, 0x8b, + 0xaf, 0x92, 0x8a, 0xad, 0xe7, 0xa0, 0xe4, 0xe6, 0x0a, 0xa0, 0xc7, 0x83, + 0xb5, 0x48, 0x58, 0x5f, 0x55, 0x9e, 0x9b, 0x27, 0xcd, 0x31, 0x1f, 0x3e, + 0x50, 0x5a, 0x91, 0xad, 0x21, 0x1b, 0x97, 0x5b, 0xe8, 0xfa, 0x29, 0x8a, + 0xa4, 0x17, 0xe8, 0xab, 0x87, 0x02, 0xd6, 0x18, 0x8c, 0x9f, 0x65, 0xb7, + 0x2a, 0xfa, 0xde, 0x5f, 0x77, 0x30, 0x6c, 0x04, 0x22, 0xe6, 0x58, 0x26, + 0x14, 0x0d, 0x9c, 0x41, 0x0a, 0x82, 0x77, 0xdb, 0x40, 0xa1, 0x58, 0xac, + 0x30, 0x82, 0x02, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x55, 0x30, 0x3d, 0x31, + 0x3b, 0x30, 0x39, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x32, 0x47, 0x72, + 0x75, 0x62, 0x20, 0x41, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x64, 0x20, + 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x20, 0x54, 0x65, + 0x73, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, + 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, + 0x02, 0x14, 0x5b, 0x5e, 0x59, 0xf2, 0x5f, 0x75, 0x4c, 0x8e, 0xc5, 0x3a, + 0x91, 0x07, 0xe9, 0xe7, 0x6d, 0x3c, 0xd0, 0x7f, 0x92, 0x03, 0x30, 0x0b, + 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x30, + 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, + 0x05, 0x00, 0x04, 0x82, 0x02, 0x00, 0xa0, 0x83, 0x3f, 0xac, 0x77, 0x97, + 0x74, 0x9b, 0x4b, 0x25, 0xa1, 0x64, 0x09, 0x8d, 0x53, 0xa6, 0x03, 0xdf, + 0x9a, 0x10, 0x52, 0xe5, 0x3f, 0xd4, 0x72, 0x75, 0x30, 0xd4, 0x6e, 0x77, + 0x32, 0x49, 0x84, 0xe2, 0xbe, 0xef, 0xe4, 0xf3, 0xac, 0xb0, 0x52, 0x55, + 0xbf, 0xa9, 0x57, 0x12, 0x08, 0x7d, 0xb0, 0x86, 0xc0, 0x9d, 0x01, 0xc2, + 0x1a, 0x4a, 0x2e, 0x3d, 0xd5, 0xc8, 0x56, 0xac, 0xd1, 0x83, 0x75, 0x88, + 0xd4, 0xcc, 0x9f, 0x0d, 0xcf, 0xd3, 0xa6, 0x91, 0xb6, 0xb6, 0xb1, 0xd1, + 0x24, 0x9c, 0xd0, 0x13, 0xe8, 0x6b, 0x15, 0x9c, 0x62, 0x33, 0x8d, 0xe3, + 0x67, 0x9b, 0xb1, 0x8a, 0x72, 0x38, 0xf7, 0x48, 0x32, 0x2f, 0x1e, 0x45, + 0xa8, 0xc4, 0xa5, 0xae, 0xb1, 0xfc, 0x35, 0x25, 0xb5, 0xf9, 0x7f, 0x86, + 0xef, 0xa2, 0x6d, 0x78, 0xcc, 0xfd, 0x0c, 0xca, 0x8a, 0xe1, 0xae, 0xcd, + 0x0f, 0x58, 0x69, 0xf1, 0x8b, 0xcc, 0x22, 0x35, 0x6d, 0x1f, 0xd5, 0x27, + 0x87, 0x39, 0x62, 0x3f, 0xb2, 0x17, 0x3d, 0x5e, 0xb1, 0x32, 0x7a, 0xf1, + 0x70, 0xce, 0xfa, 0xab, 0x1c, 0x92, 0xa8, 0xe1, 0xc4, 0xb2, 0x33, 0x1a, + 0x16, 0xf3, 0x60, 0x39, 0xdf, 0xb8, 0x85, 0xe7, 0x5d, 0x4d, 0xc2, 0x8d, + 0x55, 0x00, 0x49, 0x94, 0x04, 0x17, 0x88, 0x7c, 0xf4, 0xac, 0xa9, 0xc5, + 0x3a, 0x09, 0xc4, 0xc2, 0xcd, 0x3d, 0xc3, 0xfc, 0x4e, 0xf3, 0x70, 0xa1, + 0xc1, 0x54, 0x36, 0x1f, 0x38, 0x6d, 0x7a, 0x6b, 0x6a, 0xd3, 0x67, 0x04, + 0xd5, 0x53, 0xd4, 0xa5, 0xad, 0x63, 0x55, 0x0e, 0x06, 0x06, 0x3a, 0x9a, + 0xc5, 0xfe, 0x38, 0xc9, 0xb0, 0x69, 0x42, 0x90, 0x35, 0x1f, 0xe3, 0x1c, + 0x57, 0xea, 0xdb, 0x51, 0x35, 0x53, 0xd3, 0x94, 0xfe, 0x72, 0x33, 0xd6, + 0x8a, 0x46, 0x74, 0xf9, 0x6e, 0x94, 0x40, 0x2f, 0xba, 0xa2, 0xc4, 0xe9, + 0xc9, 0x8a, 0xf4, 0xda, 0xe2, 0xca, 0x3e, 0x98, 0x85, 0xa5, 0xd1, 0x60, + 0x94, 0xc8, 0xdf, 0x82, 0xee, 0x5c, 0x0d, 0x2a, 0xa9, 0x8e, 0x26, 0x83, + 0x3f, 0x02, 0xa2, 0xaf, 0xb8, 0x3b, 0x83, 0xf2, 0x44, 0x46, 0x41, 0xd7, + 0x5c, 0xa1, 0x42, 0x17, 0xa2, 0xd0, 0x50, 0x42, 0xef, 0x66, 0xda, 0x35, + 0x03, 0xd1, 0x8e, 0x77, 0x22, 0x7d, 0x4e, 0xf7, 0x4e, 0x04, 0xe3, 0x0f, + 0x98, 0x7d, 0xaa, 0x58, 0xba, 0xef, 0x9a, 0xd0, 0x88, 0x7c, 0x98, 0xa0, + 0xc2, 0xff, 0xa6, 0xb1, 0xec, 0xbe, 0x6e, 0xb0, 0x7e, 0xc6, 0xe5, 0xaa, + 0xcf, 0x10, 0x73, 0xc9, 0x13, 0x1a, 0x20, 0x12, 0x5c, 0xd2, 0x0e, 0xe2, + 0x60, 0x17, 0xdf, 0x4a, 0x44, 0x08, 0x22, 0xbc, 0xcd, 0x75, 0xbe, 0xc3, + 0x7a, 0x12, 0x90, 0x90, 0xc7, 0x94, 0x4c, 0x98, 0x45, 0x02, 0x5c, 0x24, + 0xae, 0x82, 0x2f, 0xcd, 0x30, 0xa6, 0xf5, 0x3f, 0xd3, 0xa7, 0xa6, 0xe6, + 0xea, 0x11, 0x4e, 0x45, 0xb7, 0xc0, 0xe6, 0x24, 0x8b, 0x76, 0xc5, 0x5e, + 0xc1, 0xd8, 0x07, 0x1e, 0x26, 0x94, 0x7a, 0x80, 0xc6, 0x3b, 0x1f, 0x74, + 0xe6, 0xae, 0x43, 0x2d, 0x11, 0xee, 0x96, 0x56, 0x6c, 0xff, 0xcb, 0x3b, + 0xde, 0xcc, 0xb3, 0x7b, 0x08, 0xf5, 0x3e, 0x6e, 0x51, 0x71, 0xe0, 0x8a, + 0xfa, 0xdd, 0x19, 0x39, 0xcf, 0x3f, 0x29, 0x4f, 0x2d, 0xd2, 0xd4, 0xdc, + 0x5c, 0xc4, 0xd1, 0xa7, 0xf5, 0xbf, 0x4a, 0xc0, 0x9b, 0xb4, 0x2b, 0x83, + 0x7a, 0x63, 0x4d, 0x20, 0x40, 0x8b, 0x11, 0x5c, 0x53, 0xd4, 0x52, 0x21, + 0xe7, 0xe4, 0x1f, 0x01, 0xf6, 0xd1, 0x25, 0x28, 0xba, 0x51, 0x6f, 0x51, + 0x69, 0xf4, 0x41, 0x45, 0x75, 0x23, 0x25, 0x77, 0xef, 0xa8, 0x1c, 0x19, + 0x8a, 0x66, 0x8c, 0x61, 0x13, 0x37, 0x4f, 0xa3, 0xa1, 0x83, 0x17, 0x35, + 0x23, 0x2d, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x05, 0x34, 0x7e, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x20, 0x73, + 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x20, 0x61, 0x70, 0x70, + 0x65, 0x6e, 0x64, 0x65, 0x64, 0x7e, 0x0a +}; +unsigned int hi_double_extended_len = 1375; + +unsigned char certificate_printable_der[] = { + 0x30, 0x82, 0x03, 0x39, 0x30, 0x82, 0x02, 0x21, 0xa0, 0x03, 0x02, 0x01, + 0x02, 0x02, 0x09, 0x00, 0xde, 0xf6, 0x22, 0xc4, 0xf2, 0xf1, 0x86, 0x02, + 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, + 0x0b, 0x05, 0x00, 0x30, 0x2a, 0x31, 0x28, 0x30, 0x26, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x1f, 0x52, 0x65, 0x64, 0x20, 0x48, 0x61, 0x74, 0x20, + 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x20, 0x42, 0x6f, 0x6f, 0x74, 0x20, + 0x43, 0x41, 0x20, 0x32, 0x20, 0x28, 0x62, 0x65, 0x74, 0x61, 0x29, 0x30, + 0x1e, 0x17, 0x0d, 0x31, 0x34, 0x31, 0x30, 0x33, 0x31, 0x31, 0x34, 0x31, + 0x39, 0x32, 0x33, 0x5a, 0x17, 0x0d, 0x33, 0x37, 0x31, 0x30, 0x32, 0x35, + 0x31, 0x34, 0x31, 0x39, 0x32, 0x33, 0x5a, 0x30, 0x2f, 0x31, 0x2d, 0x30, + 0x2b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x24, 0x52, 0x65, 0x64, 0x20, + 0x48, 0x61, 0x74, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x20, 0x42, + 0x6f, 0x6f, 0x74, 0x20, 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x20, + 0x33, 0x20, 0x28, 0x62, 0x65, 0x74, 0x61, 0x29, 0x30, 0x82, 0x01, 0x22, + 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, + 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, + 0x02, 0x82, 0x01, 0x01, 0x00, 0xbd, 0xda, 0xa1, 0xed, 0x8d, 0x8e, 0x15, + 0x5c, 0xf8, 0x01, 0x77, 0x48, 0x4a, 0x60, 0x96, 0xf9, 0x27, 0xfa, 0xe2, + 0xb1, 0x69, 0x0f, 0x51, 0x19, 0x52, 0x7e, 0xc4, 0x34, 0x8e, 0xe1, 0x9b, + 0x9c, 0xa4, 0xb1, 0x5c, 0xd6, 0x81, 0x98, 0x78, 0xfe, 0xa9, 0xe5, 0x0b, + 0x00, 0xba, 0x9c, 0x64, 0x7e, 0xc7, 0xcc, 0x72, 0xb1, 0x73, 0x4b, 0x11, + 0x07, 0x52, 0xf0, 0x20, 0x96, 0x8b, 0x99, 0x39, 0xde, 0xdb, 0xfa, 0x3d, + 0x45, 0xe2, 0x98, 0x7b, 0x0c, 0x41, 0xe4, 0x0c, 0xb5, 0x5d, 0x92, 0x74, + 0x39, 0x96, 0xe1, 0x97, 0x97, 0xa1, 0xad, 0x2e, 0xcc, 0xd0, 0x1b, 0x4d, + 0x9d, 0xbd, 0x3e, 0xa9, 0x36, 0x8e, 0xcc, 0xc7, 0x5f, 0x6a, 0x7d, 0x39, + 0x5e, 0x0b, 0x8d, 0xca, 0xe4, 0x83, 0xe9, 0x3b, 0x5c, 0x86, 0x47, 0xd4, + 0xba, 0x7d, 0x98, 0x26, 0xa1, 0xf4, 0xe8, 0x90, 0x6b, 0x0f, 0xf1, 0x6b, + 0x8c, 0xe3, 0xa2, 0x80, 0x3c, 0x96, 0xf1, 0x0a, 0xb6, 0x66, 0xc0, 0x4b, + 0x61, 0xf7, 0x74, 0xcd, 0xd3, 0x7b, 0x8e, 0x5e, 0x39, 0xda, 0x99, 0x20, + 0x33, 0x93, 0xd3, 0xf0, 0x7f, 0xad, 0x35, 0xe9, 0x88, 0x8d, 0x9c, 0xbf, + 0x65, 0xf1, 0x47, 0x02, 0xf9, 0x7c, 0xed, 0x27, 0x5f, 0x4a, 0x65, 0x3c, + 0xcf, 0x5f, 0x0e, 0x88, 0x95, 0x74, 0xde, 0xfb, 0x9e, 0x2e, 0x91, 0x9b, + 0x45, 0x37, 0xc8, 0x85, 0xff, 0xe3, 0x41, 0x70, 0xfe, 0xd5, 0xef, 0x0e, + 0x82, 0x22, 0x08, 0xb7, 0x3b, 0x44, 0x3e, 0xdc, 0x5b, 0x7f, 0xba, 0xbf, + 0xe6, 0x58, 0x9d, 0x02, 0x6e, 0x75, 0xbf, 0x50, 0xec, 0xcf, 0x3f, 0xa5, + 0x91, 0x0a, 0xe2, 0x59, 0x2c, 0xc3, 0xe7, 0x05, 0x03, 0xe8, 0xf2, 0x6f, + 0x2a, 0x04, 0x68, 0x9a, 0x31, 0x32, 0x8f, 0x04, 0x35, 0xcd, 0x1f, 0x34, + 0xcc, 0x4f, 0x79, 0x5a, 0x99, 0x8d, 0x9d, 0x5c, 0xf5, 0x02, 0x03, 0x01, + 0x00, 0x01, 0xa3, 0x5d, 0x30, 0x5b, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, + 0x13, 0x01, 0x01, 0xff, 0x04, 0x02, 0x30, 0x00, 0x30, 0x0b, 0x06, 0x03, + 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x07, 0x80, 0x30, 0x1d, 0x06, + 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x65, 0xc5, 0xbe, 0xca, + 0xe6, 0x59, 0x6a, 0xfd, 0x6c, 0x71, 0xc4, 0xa7, 0x98, 0xc6, 0x25, 0x8d, + 0x7b, 0x67, 0x05, 0xd0, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, + 0x18, 0x30, 0x16, 0x80, 0x14, 0x81, 0xf8, 0xee, 0x47, 0x5c, 0x3e, 0xed, + 0xfb, 0xce, 0xa5, 0x84, 0xbe, 0xd7, 0xae, 0xdb, 0xd3, 0x7d, 0x64, 0xb3, + 0x2a, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, + 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x66, 0x1e, 0x3d, + 0x1d, 0x53, 0x33, 0xde, 0x4e, 0xc7, 0xc4, 0xf4, 0xdf, 0xda, 0x18, 0x19, + 0x8a, 0xa9, 0xff, 0xe2, 0x63, 0x2b, 0xbe, 0xf2, 0x61, 0x63, 0xe2, 0xf6, + 0xed, 0x47, 0x1a, 0x71, 0x02, 0xec, 0x2a, 0xef, 0x89, 0x77, 0xe3, 0xfd, + 0x86, 0x69, 0xf1, 0x3f, 0x0d, 0xf9, 0x6e, 0xf9, 0x3b, 0xad, 0x26, 0x47, + 0xb7, 0xf2, 0x0d, 0xad, 0x23, 0xa3, 0x67, 0x3b, 0xcb, 0x6d, 0x9e, 0x03, + 0x0f, 0xbc, 0x69, 0x73, 0x9f, 0xd4, 0xa5, 0x0f, 0x6f, 0xf8, 0xab, 0x4d, + 0x36, 0xd1, 0xe0, 0xe0, 0x5d, 0x20, 0x43, 0x90, 0xc4, 0x65, 0x61, 0x93, + 0xe2, 0x0f, 0x51, 0x59, 0x0a, 0xf7, 0x88, 0x70, 0x57, 0xb9, 0x04, 0xa9, + 0x32, 0x57, 0x9c, 0xb3, 0x57, 0x38, 0x8b, 0x8e, 0x46, 0xc8, 0x32, 0x6c, + 0xb4, 0xf3, 0x96, 0x7f, 0x4b, 0xf0, 0x88, 0xf9, 0x7f, 0xe2, 0x71, 0xe1, + 0x8b, 0xe2, 0x14, 0xf1, 0x4b, 0x25, 0x00, 0x48, 0x1c, 0x7e, 0xe5, 0x8d, + 0x65, 0x2d, 0xeb, 0x72, 0x4f, 0x92, 0x44, 0xf3, 0xe6, 0xe0, 0xd0, 0xdf, + 0x85, 0xa8, 0x13, 0x4a, 0xfb, 0x99, 0xca, 0x14, 0x2c, 0x97, 0x80, 0x93, + 0x27, 0xd3, 0x20, 0xf8, 0x6d, 0x29, 0x28, 0x2c, 0xb9, 0x77, 0xea, 0xb1, + 0x63, 0xbd, 0x7d, 0x53, 0xfd, 0x4a, 0x62, 0x64, 0x0b, 0x98, 0xa8, 0xae, + 0x11, 0xfc, 0x6e, 0x8d, 0x63, 0xd4, 0x15, 0x55, 0xc6, 0x4c, 0x74, 0xf5, + 0x5f, 0xa0, 0xb9, 0x2c, 0x2d, 0x9a, 0x7a, 0x87, 0x6e, 0xf0, 0x5e, 0x25, + 0xed, 0xfc, 0xd8, 0xc4, 0x34, 0x33, 0x32, 0xad, 0x01, 0xd4, 0x4b, 0x49, + 0x51, 0xc2, 0x07, 0x7f, 0x90, 0x6d, 0xea, 0xf5, 0x4c, 0x41, 0x71, 0x64, + 0xeb, 0x1f, 0x29, 0xa3, 0x1f, 0x64, 0xa2, 0x1e, 0x0e, 0x6f, 0xa1, 0x67, + 0x99, 0x8d, 0x98, 0x1c, 0xb8, 0x53, 0x9d, 0x30, 0x1d, 0xae, 0x32, 0x56, + 0xd2 +}; +unsigned int certificate_printable_der_len = 829; + +unsigned char certificate_eku_der[] = { + 0x30, 0x82, 0x03, 0x90, 0x30, 0x82, 0x02, 0x78, 0xa0, 0x03, 0x02, 0x01, + 0x02, 0x02, 0x09, 0x00, 0xd3, 0x9c, 0x41, 0x33, 0xdd, 0x6b, 0x5f, 0x45, + 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, + 0x0b, 0x05, 0x00, 0x30, 0x47, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x0c, 0x18, 0x52, 0x65, 0x64, 0x20, 0x48, 0x61, 0x74, 0x20, + 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x20, 0x42, 0x6f, 0x6f, 0x74, 0x20, + 0x43, 0x41, 0x20, 0x36, 0x31, 0x22, 0x30, 0x20, 0x06, 0x09, 0x2a, 0x86, + 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x13, 0x73, 0x65, 0x63, + 0x61, 0x6c, 0x65, 0x72, 0x74, 0x40, 0x72, 0x65, 0x64, 0x68, 0x61, 0x74, + 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x32, 0x31, 0x30, 0x32, + 0x31, 0x35, 0x31, 0x34, 0x30, 0x30, 0x34, 0x34, 0x5a, 0x17, 0x0d, 0x33, + 0x38, 0x30, 0x31, 0x31, 0x37, 0x31, 0x34, 0x30, 0x30, 0x34, 0x34, 0x5a, + 0x30, 0x4e, 0x31, 0x28, 0x30, 0x26, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, + 0x1f, 0x52, 0x65, 0x64, 0x20, 0x48, 0x61, 0x74, 0x20, 0x53, 0x65, 0x63, + 0x75, 0x72, 0x65, 0x20, 0x42, 0x6f, 0x6f, 0x74, 0x20, 0x53, 0x69, 0x67, + 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x36, 0x30, 0x32, 0x31, 0x22, 0x30, 0x20, + 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, + 0x13, 0x73, 0x65, 0x63, 0x61, 0x6c, 0x65, 0x72, 0x74, 0x40, 0x72, 0x65, + 0x64, 0x68, 0x61, 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x82, 0x01, 0x22, + 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, + 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, + 0x02, 0x82, 0x01, 0x01, 0x00, 0xaa, 0x6f, 0xbb, 0x92, 0x77, 0xd7, 0x15, + 0xef, 0x88, 0x80, 0x88, 0xc0, 0xe7, 0x89, 0xeb, 0x35, 0x76, 0xf4, 0x85, + 0x05, 0x0f, 0x19, 0xe4, 0x5f, 0x25, 0xdd, 0xc1, 0xa2, 0xe5, 0x5c, 0x06, + 0xfb, 0xf1, 0x06, 0xb5, 0x65, 0x45, 0xcb, 0xbd, 0x19, 0x33, 0x54, 0xb5, + 0x1a, 0xcd, 0xe4, 0xa8, 0x35, 0x2a, 0xfe, 0x9c, 0x53, 0xf4, 0xc6, 0x76, + 0xdb, 0x1f, 0x8a, 0xd4, 0x7b, 0x18, 0x11, 0xaf, 0xa3, 0x90, 0xd4, 0xdd, + 0x4d, 0xd5, 0x42, 0xcc, 0x14, 0x9a, 0x64, 0x6b, 0xc0, 0x7f, 0xaa, 0x1c, + 0x94, 0x47, 0x4d, 0x79, 0xbd, 0x57, 0x9a, 0xbf, 0x99, 0x4e, 0x96, 0xa9, + 0x31, 0x2c, 0xa9, 0xe7, 0x14, 0x65, 0x86, 0xc8, 0xac, 0x79, 0x5e, 0x78, + 0xa4, 0x3c, 0x00, 0x24, 0xd3, 0xf7, 0xe1, 0xf5, 0x12, 0xad, 0xa0, 0x29, + 0xe5, 0xfe, 0x80, 0xae, 0xf8, 0xaa, 0x60, 0x36, 0xe7, 0xe8, 0x94, 0xcb, + 0xe9, 0xd1, 0xcc, 0x0b, 0x4d, 0xf7, 0xde, 0xeb, 0x52, 0xd2, 0x73, 0x09, + 0x28, 0xdf, 0x48, 0x99, 0x53, 0x9f, 0xc5, 0x9a, 0xd4, 0x36, 0xa3, 0xc6, + 0x5e, 0x8d, 0xbe, 0xd5, 0xdc, 0x76, 0xb4, 0x74, 0xb8, 0x26, 0x18, 0x27, + 0xfb, 0xf2, 0xfb, 0xd0, 0x9b, 0x3d, 0x7f, 0x10, 0xe2, 0xab, 0x44, 0xc7, + 0x88, 0x7f, 0xb4, 0x3d, 0x3e, 0xa3, 0xff, 0x6d, 0x06, 0x4b, 0x3e, 0x55, + 0xb2, 0x84, 0xf4, 0xad, 0x54, 0x88, 0x81, 0xc3, 0x9c, 0xf8, 0xb6, 0x68, + 0x96, 0x38, 0x8b, 0xcd, 0x90, 0x6d, 0x25, 0x4b, 0xbf, 0x0c, 0x44, 0x90, + 0xa5, 0x5b, 0x98, 0xd0, 0x40, 0x2f, 0xbb, 0x0d, 0xa8, 0x4b, 0x8a, 0x62, + 0x82, 0x46, 0x46, 0x18, 0x38, 0xae, 0x82, 0x07, 0xd0, 0xb4, 0x2f, 0x16, + 0x79, 0x55, 0x9f, 0x1b, 0xc5, 0x08, 0x6d, 0x85, 0xdf, 0x3f, 0xa9, 0x9b, + 0x4b, 0xc6, 0x28, 0xd3, 0x58, 0x72, 0x3d, 0x37, 0x11, 0x02, 0x03, 0x01, + 0x00, 0x01, 0xa3, 0x78, 0x30, 0x76, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, + 0x13, 0x01, 0x01, 0xff, 0x04, 0x02, 0x30, 0x00, 0x30, 0x0e, 0x06, 0x03, + 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x07, 0x80, + 0x30, 0x16, 0x06, 0x03, 0x55, 0x1d, 0x25, 0x01, 0x01, 0xff, 0x04, 0x0c, + 0x30, 0x0a, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x03, + 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x6c, + 0xe4, 0x6c, 0x27, 0xaa, 0xcd, 0x0d, 0x4b, 0x74, 0x21, 0xa4, 0xf6, 0x5f, + 0x87, 0xb5, 0x31, 0xfe, 0x10, 0xbb, 0xa7, 0x30, 0x1f, 0x06, 0x03, 0x55, + 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0xe8, 0x6a, 0x1c, 0xab, + 0x2c, 0x48, 0xf9, 0x60, 0x36, 0xa2, 0xf0, 0x7b, 0x8e, 0xd2, 0x9d, 0xb4, + 0x2a, 0x28, 0x98, 0xc8, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, + 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, + 0x55, 0x34, 0xe2, 0xfa, 0xf6, 0x89, 0x86, 0xad, 0x92, 0x21, 0xec, 0xb9, + 0x54, 0x0e, 0x18, 0x47, 0x0d, 0x1b, 0xa7, 0x58, 0xad, 0x69, 0xe4, 0xef, + 0x3b, 0xe6, 0x8d, 0xdd, 0xda, 0x0c, 0x45, 0xf6, 0xe8, 0x96, 0xa4, 0x29, + 0x0f, 0xbb, 0xcf, 0x16, 0xae, 0x93, 0xd0, 0xcb, 0x2a, 0x26, 0x1a, 0x7b, + 0xfc, 0x51, 0x22, 0x76, 0x98, 0x31, 0xa7, 0x0f, 0x29, 0x35, 0x79, 0xbf, + 0xe2, 0x4f, 0x0f, 0x14, 0xf5, 0x1f, 0xcb, 0xbf, 0x87, 0x65, 0x13, 0x32, + 0xa3, 0x19, 0x4a, 0xd1, 0x3f, 0x45, 0xd4, 0x4b, 0xe2, 0x00, 0x26, 0xa9, + 0x3e, 0xd7, 0xa5, 0x37, 0x9f, 0xf5, 0xad, 0x61, 0xe2, 0x40, 0xa9, 0x74, + 0x24, 0x53, 0xf2, 0x78, 0xeb, 0x10, 0x9b, 0x2c, 0x27, 0x88, 0x46, 0xcb, + 0xe4, 0x60, 0xca, 0xf5, 0x06, 0x24, 0x40, 0x2a, 0x97, 0x3a, 0xcc, 0xd0, + 0x81, 0xb1, 0x15, 0xa3, 0x4f, 0xd0, 0x2b, 0x4f, 0xca, 0x6e, 0xaa, 0x24, + 0x31, 0xb3, 0xac, 0xa6, 0x75, 0x05, 0xfe, 0x8a, 0xf4, 0x41, 0xc4, 0x06, + 0x8a, 0xc7, 0x0a, 0x83, 0x4e, 0x49, 0xd4, 0x3f, 0x83, 0x50, 0xec, 0x57, + 0x04, 0x97, 0x14, 0x49, 0xf5, 0xe1, 0xb1, 0x7a, 0x9c, 0x09, 0x4f, 0x61, + 0x87, 0xc3, 0x97, 0x22, 0x17, 0xc2, 0xeb, 0xcc, 0x32, 0x81, 0x31, 0x21, + 0x3f, 0x10, 0x57, 0x5b, 0x43, 0xbe, 0xcd, 0x68, 0x82, 0xbe, 0xe5, 0xc1, + 0x65, 0x94, 0x7e, 0xc2, 0x34, 0x76, 0x2b, 0xcf, 0x89, 0x3c, 0x2b, 0x81, + 0x23, 0x72, 0x95, 0xcf, 0xc9, 0x67, 0x19, 0x2a, 0xd5, 0x5c, 0xca, 0xa3, + 0x46, 0xbd, 0x48, 0x06, 0x0b, 0xa6, 0xa3, 0x96, 0x50, 0x28, 0xc7, 0x7e, + 0xcf, 0x62, 0xf2, 0xfa, 0xc4, 0xf2, 0x53, 0xe3, 0xc9, 0xe8, 0x2e, 0xdd, + 0x29, 0x37, 0x07, 0x47, 0xff, 0xff, 0x8a, 0x32, 0xbd, 0xa2, 0xb7, 0x21, + 0x89, 0xa0, 0x55, 0xf7 +}; +unsigned int certificate_eku_der_len = 916; diff --git a/grub-core/tests/lib/functional_test.c b/grub-core/tests/lib/functional_test.c index 38e981f2c..23048919d 100644 --- a/grub-core/tests/lib/functional_test.c +++ b/grub-core/tests/lib/functional_test.c @@ -73,6 +73,7 @@ grub_functional_all_tests (grub_extcmd_context_t ctxt __attribute__ ((unused)), grub_dl_load ("xnu_uuid_test"); grub_dl_load ("pbkdf2_test"); grub_dl_load ("signature_test"); + grub_dl_load ("appended_signature_test"); grub_dl_load ("sleep_test"); grub_dl_load ("bswap_test"); grub_dl_load ("ctz_test"); -- 2.50.1 (Apple Git-155) _______________________________________________ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel ^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH v13 18/20] docs/grub: Document signing GRUB under UEFI 2025-09-30 11:39 [PATCH v13 00/20] Appended Signature Secure Boot Support for PowerPC Sudhakar Kuppusamy ` (16 preceding siblings ...) 2025-09-30 11:40 ` [PATCH v13 17/20] appended signatures: Verification tests Sudhakar Kuppusamy @ 2025-09-30 11:40 ` Sudhakar Kuppusamy 2025-09-30 11:40 ` [PATCH v13 19/20] docs/grub: Document signing GRUB with an appended signature Sudhakar Kuppusamy ` (2 subsequent siblings) 20 siblings, 0 replies; 25+ messages in thread From: Sudhakar Kuppusamy @ 2025-09-30 11:40 UTC (permalink / raw) To: grub-devel Cc: dja, jan.setjeeilers, julian.klode, mate.kukri, pjones, msuchanek, mlewando, stefanb, avnish, nayna, ssrish, sridharm, Sudhakar Kuppusamy, Daniel Kiper From: Daniel Axtens <dja@axtens.net> 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> 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> --- docs/grub.texi | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/docs/grub.texi b/docs/grub.texi index 8a23c29a3..358975fc8 100644 --- a/docs/grub.texi +++ b/docs/grub.texi @@ -8907,6 +8907,7 @@ environment variables and commands are listed in the same order. * Measured Boot:: Measuring boot components * Lockdown:: Lockdown when booting on a secure setup * TPM2 key protector:: Managing disk key with TPM2 key protector +* Signing GRUB itself:: Ensuring the integrity of the GRUB core image @end menu @node Authentication and authorisation @@ -8987,7 +8988,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} @@ -9595,6 +9596,21 @@ which increases the risk of password leakage during the process. Moreover, the superuser list must be well maintained, and the password used cannot be synchronized with LUKS key rotation. +@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 enroll the public key used into a relevant firmware +key database. + @node Platform limitations @chapter Platform limitations -- 2.50.1 (Apple Git-155) _______________________________________________ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel ^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH v13 19/20] docs/grub: Document signing GRUB with an appended signature 2025-09-30 11:39 [PATCH v13 00/20] Appended Signature Secure Boot Support for PowerPC Sudhakar Kuppusamy ` (17 preceding siblings ...) 2025-09-30 11:40 ` [PATCH v13 18/20] docs/grub: Document signing GRUB under UEFI Sudhakar Kuppusamy @ 2025-09-30 11:40 ` Sudhakar Kuppusamy 2025-09-30 11:40 ` [PATCH v13 20/20] docs/grub: Document " Sudhakar Kuppusamy 2025-10-02 8:52 ` [PATCH v13 00/20] Appended Signature Secure Boot Support for PowerPC Avnish Chouhan 20 siblings, 0 replies; 25+ messages in thread From: Sudhakar Kuppusamy @ 2025-09-30 11:40 UTC (permalink / raw) To: grub-devel Cc: dja, jan.setjeeilers, julian.klode, mate.kukri, pjones, msuchanek, mlewando, stefanb, avnish, nayna, ssrish, Sudhakar Kuppusamy, sridharm, Daniel Kiper 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> 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> --- docs/grub.texi | 94 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) diff --git a/docs/grub.texi b/docs/grub.texi index 358975fc8..b87a32ea9 100644 --- a/docs/grub.texi +++ b/docs/grub.texi @@ -9611,6 +9611,100 @@ image works under UEFI secure boot and can maintain the secure-boot chain. It will also be necessary to enroll the public key used into a relevant firmware key database. +@section Signing GRUB with an appended signature +The @file{core.elf} itself can be signed with a Linux kernel module-style +appended signature (@pxref{Using appended signatures}). +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.elf} +can specify the size and location of the appended signature with an ELF +Note added by @command{grub-install} or @command{grub-mkimage}. +An image can be signed this way using the @command{sign-file} command from +the Linux kernel: + +@itemize +@item Signing a GRUB image using a single signer key. The grub.key is your +private key used for GRUB signing, grub.der is a corresponding public key +(certificate) used for GRUB signature verification, and the kernel.der is +your public key (certificate) used for kernel signature verification. +@example +@group +# Determine the size of the appended signature. It depends on the +# signing key and the hash algorithm. +# +# Signing the /dev/null with an appended signature. + +sign-file SHA256 grub.key grub.der /dev/null ./empty.sig + +# Build a GRUB image for the signature. + +grub-mkimage -O powerpc-ieee1275 -o core.elf.unsigned -x kernel.der \ + -p /grub --appended-signature-size $(stat -c '%s' ./empty.sig) \ + --modules="appendedsig ..." ... + +# Remove the empty file. + +rm ./empty.sig + +# Signing a GRUB image with an appended signature. + +sign-file SHA256 grub.key grub.der core.elf.unsigned core.elf.signed + +@end group +@end example +@item Signing a GRUB image using more than one signer key. The grub1.key and +grub2.key are private keys used for GRUB signing, grub1.der and grub2.der +are corresponding public keys (certificates) used for GRUB signature verification. +The kernel1.der and kernel2.der are your public keys (certificates) used for +kernel signature verification. +@example +@group +# Generate a raw signature for /dev/null signing using OpenSSL. + +openssl cms -sign -binary -nocerts -in /dev/null -signer \ + grub1.der -inkey grub1.key -signer grub2.der -inkey grub2.key \ + -out ./empty.p7s -outform DER -noattr -md sha256 + +# Signing the /dev/null with an appended signature. + +sign-file -s ./empty.p7s sha256 /dev/null /dev/null ./empty.sig + +# Build a GRUB image for the signature. + +grub-mkimage -O powerpc-ieee1275 -o core.elf.unsigned -x kernel1.der \ + kernel2.der -p /grub --appended-signature-size $(stat -c '%s' ./empty.sig) \ + --modules="appendedsig ..." ... + +# Remove the empty files. + +rm ./empty.sig ./empty.p7s + +# Generate a raw signature for GRUB image signing using OpenSSL. + +openssl cms -sign -binary -nocerts -in core.elf.unsigned -signer \ + grub1.der -inkey grub1.key -signer grub2.der -inkey grub2.key \ + -out core.p7s -outform DER -noattr -md sha256 + +# Signing a GRUB image with an appended signature. + +sign-file -s core.p7s sha256 /dev/null core.elf.unsigned core.elf.signed + +@end group +@end example +@item Don't forget to install the signed image as required +(e.g. on powerpc-ieee1275, to the PReP partition). +@example +@group +# Install signed GRUB image to the PReP partition on powerpc-ieee1275 + +dd if=core.elf.signed of=/dev/sda1 + +@end group +@end example +@end itemize + +As with UEFI secure boot, it is necessary to build-in the required modules, +or sign them if they are not part of the GRUB image. + @node Platform limitations @chapter Platform limitations -- 2.50.1 (Apple Git-155) _______________________________________________ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel ^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH v13 20/20] docs/grub: Document appended signature 2025-09-30 11:39 [PATCH v13 00/20] Appended Signature Secure Boot Support for PowerPC Sudhakar Kuppusamy ` (18 preceding siblings ...) 2025-09-30 11:40 ` [PATCH v13 19/20] docs/grub: Document signing GRUB with an appended signature Sudhakar Kuppusamy @ 2025-09-30 11:40 ` Sudhakar Kuppusamy 2025-10-02 8:52 ` [PATCH v13 00/20] Appended Signature Secure Boot Support for PowerPC Avnish Chouhan 20 siblings, 0 replies; 25+ messages in thread From: Sudhakar Kuppusamy @ 2025-09-30 11:40 UTC (permalink / raw) To: grub-devel Cc: dja, jan.setjeeilers, julian.klode, mate.kukri, pjones, msuchanek, mlewando, stefanb, avnish, nayna, ssrish, Sudhakar Kuppusamy, sridharm, Daniel Kiper This explains how appended signatures can be used to form part of a secure boot chain, and documents the commands and variables introduced. Signed-off-by: Daniel Axtens <dja@axtens.net> Signed-off-by: Sudhakar Kuppusamy <sudhakar@linux.ibm.com> Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com> --- docs/grub.texi | 327 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 327 insertions(+) diff --git a/docs/grub.texi b/docs/grub.texi index b87a32ea9..00a9cfbfa 100644 --- a/docs/grub.texi +++ b/docs/grub.texi @@ -3281,8 +3281,10 @@ GRUB. Others may be used freely in GRUB configuration files. These variables have special meaning to GRUB. @menu +* appendedsig_key_mgmt:: * biosnum:: * blsuki_save_default:: +* check_appended_signatures:: * check_signatures:: * chosen:: * cmdpath:: @@ -3333,6 +3335,19 @@ These variables have special meaning to GRUB. @end menu +@node appendedsig_key_mgmt +@subsection appendedsig_key_mgmt + +This variable controls whether GRUB enforces appended signature validation +using either @code{static} or @code{dynamic} key management. It is automatically +set by GRUB to either @code{static} or @code{dynamic} based on the +@strong{'ibm,secure-boot'} device tree property and Platform KeyStore (PKS). +Also, it can be explicitly set to either @code{static} or @code{dynamic} by +setting the @code{appendedsig_key_mgmt} variable from the GRUB console +when the GRUB is not locked down. + +@xref{Using appended signatures} for more information. + @node biosnum @subsection biosnum @@ -3353,6 +3368,17 @@ If this variable is set, menu entries generated from BLS config files (@pxref{blscfg}) or UKI files (@pxref{uki}) will be set as the default boot entry when selected. +@node check_appended_signatures +@subsection check_appended_signatures + +This variable controls whether GRUB enforces appended signature validation on +loaded kernel and GRUB module files. It is automatically set by GRUB +to either @code{no} or @code{yes} based on the @strong{'ibm,secure-boot'} device +tree property. Also, it can be explicitly set to either @code{no} or @code{yes} by +setting the @code{check_appended_signatures} variable from the GRUB console +when the GRUB is not locked down. + +@xref{Using appended signatures} for more information. @node check_signatures @subsection check_signatures @@ -6546,6 +6572,13 @@ you forget a command, you can run the command @command{help} @menu * [:: Check file types and compare values * acpi:: Load ACPI tables +* append_add_db_cert:: Add trusted certificate to the db list +* append_add_db_hash:: Add trusted certificate/binary hash to the db list +* append_add_dbx_cert:: Add distrusted certificate to the dbx list +* append_add_dbx_hash:: Add distrusted certificate/binary hash to the dbx list +* append_list_db:: List all trusted certificates from the db list +* append_list_dbx:: List all distrusted certificates and binary/certificate hashes from the dbx list +* append_verify:: Verify appended digital signature using db and dbx lists * authenticate:: Check whether user is in user list * background_color:: Set background color for active terminal * background_image:: Load background image for active terminal @@ -6669,6 +6702,140 @@ Note: The command is not allowed when lockdown is enforced (@pxref{Lockdown}). unsigned code. @end deffn +@node append_add_db_cert +@subsection append_add_db_cert + +@deffn Command append_add_db_cert <X509_certificate> +Read X.509 certificate from the file @var{X509_certificate} +and add it to GRUB's internal db list of trusted certificates. +These certificates are used to validate appended signatures when the +environment variable @code{check_appended_signatures} (@pxref{check_appended_signatures}) +is set to @code{yes} or the @command{append_verify} (@pxref{append_verify}) +command is executed from the GRUB console. + +@xref{Using appended signatures} for more information. +@end deffn + +@node append_add_db_hash +@subsection append_add_db_hash + +@deffn Command append_add_db_hash <hash_file> +Read binary hash from the file @var{hash_file} +and add it to GRUB's internal db list of trusted binary hashes. These +hashes are used to validate the Linux kernel/GRUB module binary hashes when the +environment variable @code{check_appended_signatures} +(@pxref{check_appended_signatures}) is set to @code{yes} or the +@command{append_verify} (@pxref{append_verify}) command is executed +from the GRUB console. + +Here is an example to generate a SHA-256 hash of a binary file using +OpenSSL in binary format: + +@example + +# The vmlinux (kernel image) file is your binary file, and +# it should be unsigned. +# +# Generate the binary_hash.bin file from the vmlinux file +# using OpenSSL command + +openssl dgst -binary -sha256 -out binary_hash.bin vmlinux + +@end example + +@xref{Using appended signatures} for more information. +@end deffn + +@node append_add_dbx_cert +@subsection append_add_dbx_cert + +@deffn Command append_add_dbx_cert <X509_certificate> +Read X.509 certificate from the file @var{X509_certificate} +and add it to GRUB's internal dbx list of distrusted certificates. +These certificates are used to ensure that the distrusted certificates +are rejected during appended signatures validation when the environment +variable @code{check_appended_signatures} is set to @code{yes} +(@pxref{check_appended_signatures}) or the @command{append_verify} +(@pxref{append_verify}) command is executed from the GRUB console. +Also, these certificates are used to block adding the distrusted +certificates to the db list in the future. + +@xref{Using appended signatures} for more information. +@end deffn + +@node append_add_dbx_hash +@subsection append_add_dbx_hash + +@deffn Command append_add_dbx_hash [@option{-b}|@option{-c}] <hash_file> +Read binary/certificate hash from the file @var{hash_file} +and add it to GRUB's internal dbx list of distrusted binary/certificate hashes. +These hashes are used to ensure that the distrusted binary hashes/certificates +are rejected during Linux kernel/GRUB module binary hashes and appended signatures validation +when the environment variable @code{check_appended_signatures} (@pxref{check_appended_signatures}) +is set to @code{yes} or the @command{append_verify} (@pxref{append_verify}) command +is executed from the GRUB console. Also, these hashes are used to block adding the distrusted +binary hashes and certificates to the db list in the future. + +The @option{-b} (@option{--binary-hash}) can be used to specify binary hash file and +@option{-c} (@option{--cert-hash}) can be used to specify certificate hash file. + +Here is an example to generate a hash of a binary and a certificate using +OpenSSL in binary format: + +@example + +# The vmlinux (kernel image) file is your binary file, and +# it should be unsigned. The kernel.der is your certificate file. +# +# Generate the cert_hash.bin file from the kernel.der file + +openssl dgst -binary -sha256 -out cert_hash.bin kernel.der + +# Generate the binary_hash.bin file from the vmlinux file + +openssl dgst -binary -sha256 -out binary_hash.bin vmlinux + +@end example + +@xref{Using appended signatures} for more information. +@end deffn + +@node append_list_db +@subsection append_list_db + +@deffn Command append_list_db +List all X.509 certificates and binary hashes trusted by GRUB for validating +appended signatures. The output is a numbered list of certificates and binary hashes, +showing the certificate's version, serial number, issuer, subject, +public key algorithm, RSA public key size, and certificate fingerprint. + +@xref{Using appended signatures} for more information. +@end deffn + +@node append_list_dbx +@subsection append_list_dbx + +@deffn Command append_list_dbx +List all the distrusted X.509 certificates and binary/certificate hashes. +The output is a numbered list of certificates and binary/certificate hashes, +showing the certificate's version, serial number, issuer, subject, +public key algorithm, RSA public key size, and certificate fingerprint. + +@xref{Using appended signatures} for more information. +@end deffn + +@node append_verify +@subsection append_verify + +@deffn Command append_verify <signed_file> +Verifies an appended signature on @var{signed_file} against the trusted X.509 certificates +and hashes known to GRUB (@pxref{append_list_db},@pxref{append_list_dbx}, @pxref{append_add_db_cert}, +@pxref{append_add_db_hash}, @pxref{append_add_dbx_hash} and @pxref{append_add_dbx_cert}). +Exit code @code{$?} is set to 0 if the signature validates successfully. +If validation fails, it is set to a non-zero value. + +@xref{Using appended signatures} for more information. +@end deffn @node authenticate @subsection authenticate @@ -7507,6 +7674,13 @@ configurations, but to allow the user to select from among multiple configurations, and to enable ``one-shot'' boot attempts and ``savedefault'' behavior. @xref{Using GPG-style digital signatures}, for more information. + +If the environment variable @code{check_appended_signatures} value is set to +@code{yes} and GRUB is in locked down mode, the user is not allowed to set +@code{check_appended_signatures} to @code{no} and @code{appendedsig_key_mgmt} +to @code{static} or @code{dynamic} either directly using @command{load_env} +command or via environment block file. @xref{Using appended signatures}, for +more information. @end deffn @@ -8902,11 +9076,13 @@ environment variables and commands are listed in the same order. @menu * Authentication and authorisation:: Users and access control * Using GPG-style digital signatures:: Booting digitally signed code +* Using appended signatures:: An alternative approach to booting digitally signed code * UEFI secure boot and shim:: Booting digitally signed PE files * Secure Boot Advanced Targeting:: Embedded information for generation number based revocation * Measured Boot:: Measuring boot components * Lockdown:: Lockdown when booting on a secure setup * TPM2 key protector:: Managing disk key with TPM2 key protector +* Signing certificate and hash file:: Certificate and hash file signing * Signing GRUB itself:: Ensuring the integrity of the GRUB core image @end menu @@ -9067,6 +9243,129 @@ or BIOS) configuration to cause the machine to boot from a different (attacker-controlled) device. GRUB is at best only one link in a secure boot chain. +@node Using appended signatures +@section Using appended signatures in GRUB + +GRUB supports verifying Linux-style 'appended signatures' for Linux on Power LPAR +secure boot. Appended signatures are PKCS#7 messages containing a signature over the +contents of a file, plus some metadata, appended to the end of a file. A file +with an appended signature ends with the magic string: + +@example +~Module signature appended~\n +@end example + +where @code{\n} represents the line feed character, @code{0x0a}. + +Linux on Power LPAR secure boot is controlled by @strong{'ibm,secure-boot'} +device tree property and if this property is set to @code{2} (@samp{enforce}), +GRUB enters lockdown. There are three secure boot modes. They are + +@itemize +@item @samp{0 - disabled}: Secure boot is disabled. This is the default. +@item @samp{1 - audit}: Enforce signature verification by setting + @code{check_appended_signatures} (@pxref{check_appended_signatures}) to + @code{yes} and do not to lockdown the GRUB. Signature verification + is performed and if signature verification fails, post the errors and + allow the boot to continue. +@item @samp{2 - enforce}: Lockdown the GRUB and enforce signature verification by setting + @code{check_appended_signatures} (@pxref{check_appended_signatures}) to @code{yes}. +@end itemize + +Note that Linux on Power LPAR only supports @samp{0 - disabled} and @samp{2 - enforce}, +and @samp{1 - audit} is considered as disabled. + +Enforcement of signature verification is controlled by the environment variable +@code{check_appended_signatures} (@pxref{check_appended_signatures}). + +@itemize +@item @samp{no}: No verification is performed. This is the default. +@item @samp{yes}: Signature verification is performed and if signature verification fails, + post the errors and stop the boot. Signature verification cannot be disabled by setting + the @code{check_appended_signatures} variable back to @samp{no}. +@end itemize + +To enable appended signature verification, load the appendedsig module and an +X.509 certificate for verification. Building the appendedsig module into the +core GRUB image is recommended. + +Key management is controlled by the environment variable @code{appendedsig_key_mgmt} +(@pxref{appendedsig_key_mgmt}). + +@itemize +@item @samp{static}: Enforce static key management signature verification. This is the default. + When the GRUB is locked down, user cannot change the value of the + @code{appendedsig_key_mgmt}. +@item @samp{dynamic}: Enforce dynamic key management signature verification. When the GRUB is + locked down, user cannot change the value of the @code{appendedsig_key_mgmt}. +@end itemize + +In static key management mode, certificates will be built into the core image using +the @code{--x509} parameter to @command{grub-mkimage}. Whether Secure Boot is enabled or not, +it is possible to list the trusted certificates available at boot time using +@command{append_list_db} (@pxref{append_list_db}). The distrusted certificates can be +explicitly removed from the db using @command{append_add_dbx_cert} (@pxref{append_add_dbx_cert}). +The trusted certificates can be explicitly added to the db using +@command{append_add_db_cert} (@pxref{append_add_db_cert}). + +In dynamic key management mode, db and dbx are read from the Platform KeyStore (PKS). If +db is not present or empty in PKS, static keys (built-in keys) are used as the default keys. +Whether Secure Boot is enabled or not, it is possible to list the trusted certificates +and binary hashes available at boot time using @command{append_list_db} (@pxref{append_list_db}) +and list the distrusted certificates and binary/certificate hashes available at boot time +using @command{append_list_dbx} (@pxref{append_list_dbx}). The trusted certificates and +binary hashes can be explicitly added to the db using the @command{append_add_db_cert} +(@pxref{append_add_db_cert}) and @command{append_add_db_hash} (@pxref{append_add_db_hash}). +The distrusted certificates can be explicitly added to the dbx using the +@command{append_add_dbx_cert} (@pxref{append_add_dbx_cert}) and the distrusted +certificate/binary hases can be explicitly added to the dbx using the @command{append_add_dbx_hash} +(@pxref{append_add_dbx_hash}). + +A file can be explicitly verified using @command{append_verify} (@pxref{append_verify}). + +Note that when the environment variable @code{check_appended_signatures} is set to @code{yes}, +the @command{append_add_db_cert} and @command{append_add_dbx_cert} commands only accept +the file @samp{@var{X509_certificate}} that is signed with an appended signature +(@pxref{Signing certificate and hash file}), and the @command{append_add_db_hash} and +@command{append_add_dbx_hash} commands only accept the file @samp{@var{hash_file}} that is +signed with an appended signature (@pxref{Signing certificate and hash file}). +The signature is verified by appendedsig module. +When the environment variable @code{check_appended_signatures} is set to @code{no}, +these commands accept files without an appended signature. + +Also, note that @samp{@var{X509_certificate}} should be in DER-format and @samp{@var{hash_file}} +should be in binary format. SHA-256, SHA-384, or SHA-512 hashes of binary/certificate are only allowed. +Certificates/hashes of certificates/binaries added through @command{append_add_db_cert}, +@command{append_add_dbx_cert}, @command{append_add_db_hash}, and @command{append_add_dbx_hash} +will not be persisted across boots. + +The signatures created using SHA-256 or SHA-512 hash algorithm along with RSA keys of size 2048, +3072, or 4096 bits are only supported. + +A file can be signed with the @command{sign-file} utility supplied with the +Linux kernel source. For example, if you have @code{signing.key} as the private +key and @code{certificate.der} as the X.509 certificate containing the public key: + +@example +sign-file SHA256 signing.key certificate.der vmlinux vmlinux.signed +@end example + +Once signature verification is turned on, the following file types must carry +appended signatures: + +@enumerate +@item Linux kernels +@item GRUB modules, except those built in to the core image +@item Any new certificate or binary hash files to be trusted +@item Any new certificate/binary hash files to be distrusted +@end enumerate + +When GRUB is locked down (when secure boot mode is set to @code{enforce}), +signature verification cannot be @strong{disabled} by setting the +@code{check_appended_signatures} (@pxref{check_appended_signatures}) variable +to @code{no} or using the @command{load_env} (@pxref{load_env}) command from +the GRUB console. + @node UEFI secure boot and shim @section UEFI secure boot and shim support @@ -9596,6 +9895,34 @@ which increases the risk of password leakage during the process. Moreover, the superuser list must be well maintained, and the password used cannot be synchronized with LUKS key rotation. +@node Signing certificate and hash file +@section Signing certificate and hash file +The X.509 certificate (public key) file and hash file (binary/certificate hash file) +can be signed with a Linux kernel module-style appended signature. + +The signer.key is your private key used for signing, signer.der is corresponding +public key (certificate) used for appended signature verification. Note that the +signer.der (certificate) should exist in the db (@pxref{Using appended signatures}). + +@itemize +@item Signing the X.509 certificate file using @file{sign-file}. +The kernel.der is your X.509 certificate file. +@example + +sign-file SHA256 signer.key signer.der kernel.der \ + kernel.der.signed + +@end example +@item Signing the hash file using @file{sign-file}. +The binary_hash.bin is your binary hash file. +@example + +sign-file SHA256 signer.key signer.der binary_hash.bin \ + binary_hash.signed + +@end example +@end itemize + @node Signing GRUB itself @section Signing GRUB itself To ensure a complete secure-boot chain, there must be a way for the code that -- 2.50.1 (Apple Git-155) _______________________________________________ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel ^ permalink raw reply related [flat|nested] 25+ messages in thread
* Re: [PATCH v13 00/20] Appended Signature Secure Boot Support for PowerPC 2025-09-30 11:39 [PATCH v13 00/20] Appended Signature Secure Boot Support for PowerPC Sudhakar Kuppusamy ` (19 preceding siblings ...) 2025-09-30 11:40 ` [PATCH v13 20/20] docs/grub: Document " Sudhakar Kuppusamy @ 2025-10-02 8:52 ` Avnish Chouhan 20 siblings, 0 replies; 25+ messages in thread From: Avnish Chouhan @ 2025-10-02 8:52 UTC (permalink / raw) To: Sudhakar Kuppusamy Cc: grub-devel, dja, jan.setjeeilers, julian.klode, mate.kukri, pjones, msuchanek, mlewando, stefanb, nayna, ssrish, sridharm, Daniel Kiper On 2025-09-30 17:09, Sudhakar Kuppusamy wrote: (applicable to the complete patch set...) Reviewed-by: Avnish Chouhan <avnish@linux.ibm.com> > This patch set contains v13 the consolidated version of the patch > sets for secure boot using appended signatures on powerpc, > rebased on top of git HEAD. > > The v12 series is at > https://lists.gnu.org/archive/html/grub-devel/2025-09/msg00197.html > > Changes since v12: > - Daniel Kiper review comments addressed: > - v13 patch 11: changed the function name from grub_pks_tmp_free to > grub_pks_free_data, corrected the typo error. > - v13 patch 12 - 20: Addressed all comments. > - v13: Removed the patch 16 and patch 17 from v12. > > Linux on Power LPAR secure boot ensures the integrity of the Linux boot > stack. The hypervisor and partition firmware are part of the core root > of > trust. The partition firmware verifies the signature on the GRUB image > before handing control to GRUB. Similarly, GRUB verifies the signature > on > the kernel image before booting the OS. This ensures that every image > running at the boot time is verified and trusted. UEFI platforms relies > on PECOFF based signature scheme. Since Power is not a UEFI platform, > an > alternative mechanism is needed. Power already uses appended signatures > on the Linux Kernel, and is now extended to sign the grub as well. > > Linux on Power also allows multiple signers, and if any one of the > signature passes, then the image passes the validation. Appended > signature > scheme uses CMS structure to contain signatures. On Power, the multiple > signature support relies on the multiple signers features already > supported > by CMS standards. It does require that all the signers should sign at > the > same time and are not allowed to add or remove the signatures randomly. > > By default, Linux LPAR secure boot uses static key management[1]. This > means > that each image embeds the keys it needs to verify the image it loads. > For example, the keys used to verify the GRUB image are built into the > firmware image. Similarly, the keys used for verifying the kernel image > are built into the GRUB image. These are pre-defined keys and they > cannot > be modified at runtime. The drawback of this approach is that key > rotations > results in both firmware and OS updates. This is where dynamic key > management is useful. > > An admin can switch from static keys to dynamic keys by coordinating > with > Hardware Management Console(HMC) admin and enabling the required flags > for the given LPAR. > > The dynamic key management relies on the Platform KeyStore(PKS)[2] > storage > allocation for each LPAR with individually managed access controls to > store sensitive information securely. Once switched to dynamic keys, > HMC > advertises this flag to the PowerVM, which then initializes the PKS > with the default secvars. It also creates a variable SB_VERSION that > represents the secure boot key management mode. The default secvars are > used by Partition firmware, grub and the linux kernel to reads keys for > verification. These secvars can be managed by user interface exposed > via > linux kernel. The linux kernel already supports this interface and > it is available in the upstream kernel. > > This patchset adds the appended signature support both for signing and > verification and the key management to the grub component. The whole > patchset can be split into following four main parts: > > The series has following four main parts: > > 1.) Sign grub.elf with an appended signature. (Patches 1, 18, 19) > > These patches provide some infrastructure and documentation for > signing grub's core.elf with a Linux-kernel-module style appended > signature. > > An appended signature is a 'dumb' signature over the contents of a > file. (It is distinct from schemes like Authenticode that are aware of > the structure of the file and only sign certain parts.) The signature > is wrapped in a PKCS#7 message, and is appended to the signed file > along with some metadata and a magic string. The signatures are > validated against a public key which is usually provided as an x509 > certificate. > > Because some platforms, such as powerpc-ieee1275, may 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. > > 2.) Enable lockdown if secure boot is enabled (Patch 9) > Read secure boot mode from 'ibm,secure-boot' property and > If the 'ibm,secure-boot' property of the root node is 2, > enter lockdown. Else it is considered as disabled. > There are three secure boot modes. They are > 0 - disabled > No signature verification is performed. This is the default. > 1 - audit > Signature verification is performed and if signature verification > fails, post the errors and allow the boot to continue. > 2 - enforce > Lockdown the GRUB. Signature verification is performed and > If signature verification fails, post the errors and stop the > boot. > > Now, only support disabled and enforce. > > 3.) Enable appended signature verification using builtin keys (Patches > 2 - 8 > and 10). > > Part of a secure boot chain is allowing grub to verify the boot > kernel. For UEFI platforms, this is usually delegated to the > shim. However, for platforms that do not implement UEFI, an > alternative scheme is required. > > This part teaches grub how to verify Linux kernel-style appended > signatures. Kernels on powerpc are already signed with this scheme and > can be verified by IMA for kexec. > > As PKCS#7 messages and x509 certificates are both based on ASN.1, we > import libtasn1 to parse them. Because ASN.1 isn't self-documenting, > we import from GNUTLS the information we need to navigate their > structure. > > This section is composed of the following patches: > > - patches 2 and 3 are small refactorings. > > - patch 4 allows x509 certificates to be built in to the grub core > in much the same way as PGP keys. > > - patch 5 brings in the code from GNUTLS that allows us to parse > PKCS#7 and x509 with libtasn1. > > - patch 6, 7 and 8 is our ASN1 node, PKCS#7 and x509 parser. They're > minimal > and fairly strict parsers that extract only the bits we need to > verify the > signatures. > > - patch 10 is the guts of the appended signature verifier. > > 4.) Enable accessing keys dynamically from Platform KeyStore (Patch 11 > - 16) > > This part teaches grub how to read db and dbx variables from platform > keystore > using client interface call then load keys from those two variable, and > use it > to verify Linux kernel. > > This section is composed of the following patches: > > - patch 11 is an exposes an interface in ieee1275 for reading secure > boot > variable db and dbx from Platform Keystore. Read secure boot > variables > such as db and dbx from PKS and extract certificates from ESL. > > - patch 12 is introducing key management environment variable. > > - patch 13 is create the db and dbx lists from PKS. > > - patch 14 is verify the kernel using db and dbx lists > > - patch 15 is GRUB commands to manage the certificates > > - patch 16 adds GRUB commands to access db and dbx. > > 5.) patch 17 adds unit test and 20 adds GRUB commands and an appended > signatures > documentation. > > Thanks to Daniel Kiper for providing review comments. > > I've pushed this all to > https://github.com/SudhakarKuppusamy1/grub/tree/appendedsig-2.13 > > [1]https://www.ibm.com/docs/en/linux-on-systems?topic=servers-guest-secure-boot-static-keys > [2]https://community.ibm.com/community/user/power/blogs/chris-engel1/2020/11/20/powervm-introduces-the-platform-keystore > > Daniel Axtens (2): > crypto: Move storage for grub_crypto_pk_* to crypto.c > docs/grub: Document signing GRUB under UEFI > > Sudhakar Kuppusamy (18): > powerpc-ieee1275: Add support for signing GRUB with an appended > signature > pgp: Rename OBJ_TYPE_PUBKEY to OBJ_TYPE_GPG_PUBKEY > grub-install: Support embedding x509 certificates > appended signatures: Import GNUTLS's ASN.1 description files > appended signatures: Parse ASN1 node > appended signatures: Parse PKCS#7 signed data > appended signatures: Parse X.509 certificates > powerpc_ieee1275: Enter lockdown based on /ibm,secure-boot > appended signatures: Support verifying appended signatures > powerpc_ieee1275: Read the db and dbx secure boot variables > appended signatures: Introducing key management environment variable > appended signatures: Create db and dbx lists > appended signatures: Using db and dbx lists for signature > verification > appended signatures: GRUB commands to manage the certificates > appended signatures: GRUB commands to manage the hashes > appended signatures: Verification tests > docs/grub: Document signing GRUB with an appended signature > docs/grub: Document appended signature > > docs/grub.texi | 475 ++++- > grub-core/Makefile.am | 2 + > grub-core/Makefile.core.def | 26 + > grub-core/commands/appendedsig/appendedsig.c | 1723 +++++++++++++++++ > grub-core/commands/appendedsig/appendedsig.h | 133 ++ > grub-core/commands/appendedsig/asn1util.c | 99 + > .../commands/appendedsig/gnutls_asn1_tab.c | 148 ++ > grub-core/commands/appendedsig/pkcs7.c | 452 +++++ > .../commands/appendedsig/pkix_asn1_tab.c | 485 +++++ > grub-core/commands/appendedsig/x509.c | 970 ++++++++++ > grub-core/commands/pgp.c | 6 +- > grub-core/kern/ieee1275/ieee1275.c | 1 - > grub-core/kern/ieee1275/init.c | 58 + > grub-core/kern/powerpc/ieee1275/ieee1275.c | 137 ++ > .../kern/powerpc/ieee1275/platform_keystore.c | 344 ++++ > grub-core/lib/crypto.c | 4 + > grub-core/tests/appended_signature_test.c | 348 ++++ > grub-core/tests/appended_signatures.h | 975 ++++++++++ > grub-core/tests/lib/functional_test.c | 1 + > include/grub/crypto.h | 1 + > include/grub/efi/pks.h | 112 ++ > include/grub/err.h | 3 +- > include/grub/file.h | 4 + > include/grub/ieee1275/ieee1275.h | 3 + > include/grub/kernel.h | 3 +- > include/grub/lockdown.h | 3 +- > include/grub/powerpc/ieee1275/ieee1275.h | 18 + > .../grub/powerpc/ieee1275/platform_keystore.h | 122 ++ > include/grub/types.h | 4 + > include/grub/util/install.h | 10 +- > include/grub/util/mkimage.h | 4 +- > util/grub-install-common.c | 36 +- > util/grub-mkimage.c | 26 +- > util/grub-mkimagexx.c | 40 +- > util/mkimage.c | 50 +- > 35 files changed, 6782 insertions(+), 44 deletions(-) > create mode 100644 grub-core/commands/appendedsig/appendedsig.c > create mode 100644 grub-core/commands/appendedsig/appendedsig.h > create mode 100644 grub-core/commands/appendedsig/asn1util.c > create mode 100644 grub-core/commands/appendedsig/gnutls_asn1_tab.c > create mode 100644 grub-core/commands/appendedsig/pkcs7.c > create mode 100644 grub-core/commands/appendedsig/pkix_asn1_tab.c > create mode 100644 grub-core/commands/appendedsig/x509.c > create mode 100644 grub-core/kern/powerpc/ieee1275/ieee1275.c > create mode 100644 grub-core/kern/powerpc/ieee1275/platform_keystore.c > create mode 100644 grub-core/tests/appended_signature_test.c > create mode 100644 grub-core/tests/appended_signatures.h > create mode 100644 include/grub/efi/pks.h > create mode 100644 include/grub/powerpc/ieee1275/platform_keystore.h _______________________________________________ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel ^ permalink raw reply [flat|nested] 25+ messages in thread
end of thread, other threads:[~2025-10-02 8:53 UTC | newest] Thread overview: 25+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2025-09-30 11:39 [PATCH v13 00/20] Appended Signature Secure Boot Support for PowerPC Sudhakar Kuppusamy 2025-09-30 11:39 ` [PATCH v13 01/20] powerpc-ieee1275: Add support for signing GRUB with an appended signature Sudhakar Kuppusamy 2025-09-30 11:39 ` [PATCH v13 02/20] crypto: Move storage for grub_crypto_pk_* to crypto.c Sudhakar Kuppusamy 2025-09-30 11:39 ` [PATCH v13 03/20] pgp: Rename OBJ_TYPE_PUBKEY to OBJ_TYPE_GPG_PUBKEY Sudhakar Kuppusamy 2025-09-30 11:39 ` [PATCH v13 04/20] grub-install: Support embedding x509 certificates Sudhakar Kuppusamy 2025-09-30 11:39 ` [PATCH v13 05/20] appended signatures: Import GNUTLS's ASN.1 description files Sudhakar Kuppusamy 2025-09-30 11:40 ` [PATCH v13 06/20] appended signatures: Parse ASN1 node Sudhakar Kuppusamy 2025-09-30 11:40 ` [PATCH v13 07/20] appended signatures: Parse PKCS#7 signed data Sudhakar Kuppusamy 2025-09-30 11:40 ` [PATCH v13 08/20] appended signatures: Parse X.509 certificates Sudhakar Kuppusamy 2025-09-30 11:40 ` [PATCH v13 09/20] powerpc_ieee1275: Enter lockdown based on /ibm, secure-boot Sudhakar Kuppusamy 2025-09-30 11:40 ` [PATCH v13 10/20] appended signatures: Support verifying appended signatures Sudhakar Kuppusamy 2025-09-30 11:40 ` [PATCH v13 11/20] powerpc_ieee1275: Read the db and dbx secure boot variables Sudhakar Kuppusamy 2025-10-01 15:52 ` Daniel Kiper 2025-09-30 11:40 ` [PATCH v13 12/20] appended signatures: Introducing key management environment variable Sudhakar Kuppusamy 2025-09-30 11:40 ` [PATCH v13 13/20] appended signatures: Create db and dbx lists Sudhakar Kuppusamy 2025-09-30 11:40 ` [PATCH v13 14/20] appended signatures: Using db and dbx lists for signature verification Sudhakar Kuppusamy 2025-09-30 11:40 ` [PATCH v13 15/20] appended signatures: GRUB commands to manage the certificates Sudhakar Kuppusamy 2025-10-01 9:10 ` Sridhar Markonda 2025-09-30 11:40 ` [PATCH v13 16/20] appended signatures: GRUB commands to manage the hashes Sudhakar Kuppusamy 2025-10-01 9:09 ` Sridhar Markonda 2025-09-30 11:40 ` [PATCH v13 17/20] appended signatures: Verification tests Sudhakar Kuppusamy 2025-09-30 11:40 ` [PATCH v13 18/20] docs/grub: Document signing GRUB under UEFI Sudhakar Kuppusamy 2025-09-30 11:40 ` [PATCH v13 19/20] docs/grub: Document signing GRUB with an appended signature Sudhakar Kuppusamy 2025-09-30 11:40 ` [PATCH v13 20/20] docs/grub: Document " Sudhakar Kuppusamy 2025-10-02 8:52 ` [PATCH v13 00/20] Appended Signature Secure Boot Support for PowerPC Avnish Chouhan
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).