Thank you Daniel for the review. > On 23 Aug 2025, at 12:23 AM, Daniel Kiper <dki...@net-space.pl> wrote: > > On Thu, Aug 21, 2025 at 01:25:04PM +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 <sudha...@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 | 14 +- >> grub-core/kern/powerpc/ieee1275/ieee1275.c | 139 +++++++ >> .../kern/powerpc/ieee1275/platform_keystore.c | 341 ++++++++++++++++++ >> include/grub/ieee1275/ieee1275.h | 3 + >> include/grub/powerpc/ieee1275/ieee1275.h | 20 + >> .../grub/powerpc/ieee1275/platform_keystore.h | 142 ++++++++ >> 9 files changed, 662 insertions(+), 2 deletions(-) >> 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..cd6bb7c32 100644 >> --- a/grub-core/Makefile.am >> +++ b/grub-core/Makefile.am >> @@ -241,11 +241,13 @@ KERNEL_HEADER_FILES += >> $(top_builddir)/include/grub/machine/kernel.h >> endif >> >> if COND_powerpc_ieee1275 >> +KERNEL_HEADER_FILES += >> $(top_srcdir)/include/grub/powerpc/ieee1275/ieee1275.h >> KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/ieee1275/ieee1275.h >> 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/platform_keystore.h > > I am not entirely sure why you cannot put these two changes next to each > other… Sure, will put these two changes next to each other. > >> endif >> >> if COND_sparc64_ieee1275 >> diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def >> index d91694de0..05ccbf264 100644 >> --- a/grub-core/Makefile.core.def >> +++ b/grub-core/Makefile.core.def >> @@ -328,10 +328,12 @@ kernel = { >> extra_dist = video/sis315_init.c; >> mips_loongson = commands/keylayouts.c; >> >> + powerpc_ieee1275 = kern/powerpc/ieee1275/ieee1275.c; >> powerpc_ieee1275 = kern/powerpc/cache.S; >> powerpc_ieee1275 = kern/powerpc/dl.c; >> powerpc_ieee1275 = kern/powerpc/compiler-rt.S; >> powerpc_ieee1275 = kern/lockdown.c; >> + powerpc_ieee1275 = kern/powerpc/ieee1275/platform_keystore.c; > > Ditto… Will do. > >> 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) >> >> >> >> diff --git a/grub-core/kern/ieee1275/init.c b/grub-core/kern/ieee1275/init.c >> index 89303f33e..46bfaa9a8 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__ >> @@ -1007,6 +1009,7 @@ grub_parse_cmdline (void) >> static void >> grub_ieee1275_get_secure_boot (void) >> { >> + grub_err_t err; >> grub_ieee1275_phandle_t root; >> grub_uint32_t sb_mode = GRUB_SB_DISABLED; >> int rc; >> @@ -1038,7 +1041,16 @@ grub_ieee1275_get_secure_boot (void) >> * Now, only support disabled and enforced. >> */ >> if (sb_mode == GRUB_SB_ENFORCED) >> - grub_lockdown (); >> + { >> + grub_dprintf ("ieee1275", "Secure Boot Enabled\n"); >> + grub_lockdown (); >> + } >> + else >> + grub_dprintf ("ieee1275", "Secure Boot Disabled\n"); > > Sorry, this change does not belong to this patch. Sure, will do it. > >> + err = grub_pks_keystore_init (); >> + if (err != GRUB_ERR_NONE) >> + grub_error (err, "initialization of the Platform KeyStore failed\n"); > > Only this one... > >> } >> #endif /* __powerpc__ */ > > [...] > >> 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..aaf90500f >> --- /dev/null >> +++ b/grub-core/kern/powerpc/ieee1275/platform_keystore.c >> @@ -0,0 +1,341 @@ >> +/* >> + * 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> >> + >> +#if __GNUC__ >= 9 >> +#pragma GCC diagnostic ignored "-Waddress-of-packed-member" >> +#endif >> + >> +/* PKS consumer type for firmware. */ >> +#define PKS_CONSUMER_FW ((grub_uint8_t) 1) >> + >> +/* The maximum object size interface name for a PKS object. */ >> +#define PKS_MAX_OBJ_SIZE ((grub_uint8_t *) "pks-max-object-size") >> + >> +/* PKS read object lable for secure boot version. */ >> +#define SB_VERSION_KEY_NAME ((grub_uint8_t *) "SB_VERSION") >> +#define SB_VERSION_KEY_LEN ((grub_size_t) 10) >> + >> +/* PKS read secure boot variable request type for db and dbx. */ >> +#define DB ((grub_uint8_t) 1) >> +#define DBX ((grub_uint8_t) 2) >> + >> +static grub_size_t pks_max_object_size; >> +/* >> + * Flag to indicate the key management. >> + * True: Dynamic key management (use Platform KeySotre). >> + * False: Static key management (use built-in Keys). >> + */ >> +bool grub_pks_use_keystore = false; >> +/* >> + * Flag to indicate the availability of PSK support. >> + * True: PKS support available. >> + * False: No PKS support. >> + */ >> +bool grub_pks_is_support_pks = false; > > Why could not we use grub_pks_use_keystore only instead of both > grub_pks_use_keystore and grub_pks_is_support_pks? If you convince me > that both are needed then s/grub_pks_is_support_pks/grub_pks_supported/…
Ok. I will be strict with one variable, i.e., grub_pks_keystore, and will add the variables use_keystore and pks_supported to the member of grub_pks_keystore. > >> +/* Platform KeyStore db and dbx. */ >> +grub_pks_t grub_pks_keystore = { .db = NULL, .dbx = NULL, .db_entries = 0, >> .dbx_entries = 0 }; >> + >> +/* >> + * Import the Globally Unique Identifier (GUID), EFI Signature Database >> (ESD), >> + * and its size into the PKS Signature Database (SD) (i.e pks_sd buffer) >> and pks_sd entries >> + * from the EFI Signature List (ESL). >> + */ >> +static grub_err_t >> +esd_from_esl (const grub_uint8_t *esl_data, grub_size_t esl_size, > > s/esd_from_esl/__esl_to_esd/ Sure, will do it. > >> + 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_free_platform_keystore. >> + */ >> + *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; > > You do not need to wrap this line. I am OK with lines (a bit) longer > than 80 characters… Sure, will do it. > >> + /* 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 esd_from_esl (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_uint32_t *outlen, >> grub_uint32_t *policy) >> +{ >> + grub_int32_t rc; >> + >> + *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) >> + return grub_error (GRUB_ERR_READ_ERROR, "SB version read failed >> (%d)\n", rc); >> + >> + return GRUB_ERR_NONE; >> +} >> + >> +/* >> + * Reads the secure boot variable from PKS. >> + * Caller must free result. >> + */ >> +static grub_err_t >> +read_sbvar_from_pks (const grub_uint8_t sbvarflags, const grub_uint8_t >> sbvartype, >> + grub_uint8_t **out, grub_size_t *outlen) >> +{ >> + grub_int32_t rc; >> + >> + *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_sbvar (sbvarflags, sbvartype, >> pks_max_object_size, *out, outlen); >> + if (rc == IEEE1275_CELL_NOT_FOUND) >> + return grub_error (GRUB_ERR_UNKNOWN_COMMAND, "secure boot variable %s >> not found (%d)", >> + (sbvartype == DB ? "db" : "dbx"), rc); >> + else if (rc < 0) >> + return grub_error (GRUB_ERR_READ_ERROR, "secure boot variable %s >> reading (%d)", >> + (sbvartype == DB ? "db" : "dbx"), rc); >> + >> + return GRUB_ERR_NONE; >> +} >> + >> +/* Test the availability of PKS support. */ >> +static grub_err_t >> +is_support_pks (void) > > s/is_support_pks/is_pks_present/ Sure, will do it. > >> +{ >> + grub_int32_t rc; >> + grub_ieee1275_cell_t missing = 0; >> + >> + rc = grub_ieee1275_test (PKS_MAX_OBJ_SIZE, &missing); >> + if (rc < 0 || missing == IEEE1275_CELL_INVALID) >> + return grub_error (GRUB_ERR_BAD_FIRMWARE, "firmware doesn't have PKS >> support\n"); >> + else >> + { >> + rc = grub_ieee1275_pks_max_object_size (&pks_max_object_size); >> + if (rc < 0) >> + return grub_error (GRUB_ERR_BAD_NUMBER, "PKS support is there but >> it has zero objects\n"); >> + } >> + >> + return GRUB_ERR_NONE; >> +} >> + >> +/* >> + * Retrieve 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_secure_boot_variables (const grub_uint8_t sbvarflags, const >> grub_uint8_t sbvartype, >> + grub_pks_sd_t **pks_sd, grub_uint32_t >> *pks_sd_entries) >> +{ >> + grub_err_t rc; >> + grub_uint8_t *esl_data = NULL; >> + grub_size_t esl_data_size = 0; >> + >> + rc = read_sbvar_from_pks (sbvarflags, sbvartype, &esl_data, >> &esl_data_size); >> + if (rc == GRUB_ERR_NONE && esl_data_size != 0) >> + rc = pks_sd_from_esl ((const grub_uint8_t *) esl_data, esl_data_size, >> + pks_sd, pks_sd_entries); >> + grub_free (esl_data); >> + >> + return rc; >> +} >> + >> +/* >> + * Reads secure boot version (SB_VERSION) and it supports following. >> + * SB_VERSION: >> + * 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 void >> +get_secure_boot_version (void) > > s/get_secure_boot_version/is_pks_present/ > > And it seems to me the get_secure_boot_version() should be merged with > this function. Sure, will do it. Thanks, Sudhakar > >> +{ >> + grub_err_t rc; >> + grub_uint8_t *data = NULL; >> + grub_uint32_t len = 0, policy = 0; >> + >> + rc = read_sbversion_from_pks (&data, &len, &policy); >> + if (rc == GRUB_ERR_NONE && (len != 1 || (*data >= 2))) >> + grub_error (GRUB_ERR_BAD_NUMBER, "found unexpected SB version (%d)\n", >> *data); >> + >> + if (rc != GRUB_ERR_NONE) >> + grub_dprintf ("ieee1275", "switch to static key\n"); >> + else if (*data) >> + grub_pks_use_keystore = true; >> + >> + grub_free (data); >> +} > > Daniel _______________________________________________ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel