On Mon, Jul 14, 2025 at 11:05:08PM +0530, Sudhakar Kuppusamy wrote: > If secure boot is enabled with a static key, the trusted certificates will be > extracted > from the GRUB ELF NOTE and adding in the db list. The db list is used by GRUB
s/and adding in the/and added to db/ > for kernel verification. AIUI this is introduced by subsequent patch. So, it should be mentioned here... > If secure boot is enabled with a dynamic key, the trusted certificates and > certificate/binary hash will be extracted from the PKS and adding in the db > list. s/and adding in the/and added to db/ > The distrusted certificates, certificate/binary hash from the PKS and adding > in > the dbx list. Both dbx and db list are used by GRUB for kernel verification. s/and adding in the/and added to dbx/ > > Note:- > > If the certificate or the certificate hash exists in the dbx list, then > reject the certificate/certificate hash before adding it in the db list. ... then do not add certificate to the db list. > Signed-off-by: Sudhakar Kuppusamy <sudha...@linux.ibm.com> > Reviewed-by: Stefan Berger <stef...@linux.ibm.com> > Reviewed-by: Avnish Chouhan <avn...@linux.ibm.com> > --- > grub-core/commands/appendedsig/appendedsig.c | 558 +++++++++++++++++-- > include/grub/crypto.h | 1 + > include/grub/efi/pks.h | 112 ++++ > 3 files changed, 629 insertions(+), 42 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 d1149695b..a4b786d0c 100644 > --- a/grub-core/commands/appendedsig/appendedsig.c > +++ b/grub-core/commands/appendedsig/appendedsig.c > @@ -33,13 +33,16 @@ > #include <libtasn1.h> > #include <grub/env.h> > #include <grub/lockdown.h> > - > +#include <grub/efi/pks.h> > +#include <grub/powerpc/ieee1275/platform_keystore.h> > #include "appendedsig.h" > > GRUB_MOD_LICENSE ("GPLv3+"); > > /* Public key type. */ > -#define GRUB_PKEY_ID_PKCS7 2 > +#define GRUB_PKEY_ID_PKCS7 2 > +/* GUID size. */ > +#define GRUB_GUID_SIZE (sizeof (grub_packed_guid_t)) If you really need that then add it to include/grub/types.h after grub_packed_guid_t definition. And it should be renamed to GRUB_PACKED_GUID_SIZE. And for completeness GRUB_GUID_SIZE should be defined after grub_guid_t definition. > /* Appended signature magic string. */ > static const char magic[] = "~Module signature appended~\n"; > @@ -67,8 +70,30 @@ struct grub_appended_signature > struct pkcs7_signedData pkcs7; /* Parsed PKCS#7 data. */ > }; > > -/* Trusted certificates for verifying appended signatures. */ > -struct x509_certificate *db; > +/* This represents a db/dbx list. */ > +struct grub_database > +{ > + struct x509_certificate *certs; /* Certificates. */ > + grub_size_t cert_entries; /* Number of certificates. */ > + grub_uint8_t **signatures; /* Certificate/binary hashes. */ > + grub_size_t *signature_size; /* Size of certificate/binary hashes. */ > + grub_size_t signature_entries; /* Number of certificate/binary hashes. */ > +}; > + > +/* The db list */ > +struct grub_database db = {.certs = NULL, .cert_entries = 0, .signatures = > NULL, > + .signature_size = NULL, .signature_entries = 0}; > + > +/* The dbx list */ > +struct grub_database dbx = {.certs = NULL, .cert_entries = 0, .signatures = > NULL, > + .signature_size = NULL, .signature_entries = 0}; > + > +/* Free db list memory */ > +static void > +free_db_list (void); > +/* Free dbx list memory */ > +static void > +free_dbx_list (void); > > static enum > { > @@ -77,6 +102,201 @@ static enum > CHECK_SIGS_FORCED = 2 > } check_sigs = CHECK_SIGS_NO; > > +/* > + * 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 empty."); s/GUID is empty./GUID is not available/ > + if (grub_memcmp (guid, &GRUB_PKS_CERT_SHA256_GUID, GRUB_GUID_SIZE) == 0 || > + grub_memcmp (guid, &GRUB_PKS_CERT_X509_SHA256_GUID, GRUB_GUID_SIZE) == > 0) > + hash_func = &_gcry_digest_spec_sha256; > + else if (grub_memcmp (guid, &GRUB_PKS_CERT_SHA384_GUID, GRUB_GUID_SIZE) == > 0 || > + grub_memcmp (guid, &GRUB_PKS_CERT_X509_SHA384_GUID, > GRUB_GUID_SIZE) == 0) > + hash_func = &_gcry_digest_spec_sha384; > + else if (grub_memcmp (guid, &GRUB_PKS_CERT_SHA512_GUID, GRUB_GUID_SIZE) == > 0 || > + grub_memcmp (guid, &GRUB_PKS_CERT_X509_SHA512_GUID, > GRUB_GUID_SIZE) == 0) > + hash_func = &_gcry_digest_spec_sha512; > + else > + return grub_error (GRUB_ERR_OUT_OF_RANGE, "unsupported GUID for hash."); s/ for// > + grub_memset (hash, 0, GRUB_MAX_HASH_SIZE); > + grub_crypto_hash (hash_func, hash, data, data_size); > + *hash_size = hash_func->mdlen; > + > + return GRUB_ERR_NONE; > +} > + > +/* Add the certificate/binary hash into the db/dbx list. */ > +static grub_err_t > +add_hash (const grub_uint8_t **data, const grub_size_t data_size, > + grub_uint8_t ***signature_list, grub_size_t **signature_size_list, > + grub_size_t *signature_list_entries) > +{ > + grub_uint8_t **signatures = *signature_list; > + grub_size_t *signature_size = *signature_size_list; > + grub_size_t signature_entries = *signature_list_entries; > + > + if (*data == NULL || data_size == 0) > + return grub_error (GRUB_ERR_OUT_OF_RANGE, "certificate/binary-hash data > or size is empty."); > + > + signatures = grub_realloc (signatures, sizeof (grub_uint8_t *) * > (signature_entries + 1)); > + signature_size = grub_realloc (signature_size, > + sizeof (grub_size_t) * (signature_entries + > 1)); > + > + if (signatures == NULL || signature_size == NULL) > + { > + /* > + * Allocated memory will be freed by > + * free_db_list/free_dbx_list. > + */ > + if (signatures != NULL) > + { > + *signature_list = signatures; > + *signature_list_entries = signature_entries + 1; > + } > + > + if (signature_size != NULL) > + *signature_size_list = signature_size; > + > + return grub_error (GRUB_ERR_OUT_OF_MEMORY, "out of memory."); > + } > + > + signatures[signature_entries] = (grub_uint8_t *) *data; > + signature_size[signature_entries] = data_size; > + signature_entries++; > + *data = NULL; > + > + *signature_list = signatures; > + *signature_size_list = signature_size; > + *signature_list_entries = signature_entries; > + > + return GRUB_ERR_NONE; > +} > + > +static bool > +is_x509 (const grub_packed_guid_t *guid) > +{ > + if (grub_memcmp (guid, &GRUB_PKS_CERT_X509_GUID, GRUB_GUID_SIZE) == 0) > + return true; > + > + return false; > +} > + > +static bool > +is_cert_match (const struct x509_certificate *distrusted_cert, > + const struct x509_certificate *db_cert) > +{ > + if (grub_memcmp (distrusted_cert->subject, db_cert->subject, > db_cert->subject_len) == 0 > + && grub_memcmp (distrusted_cert->serial, db_cert->serial, > db_cert->serial_len) == 0 > + && grub_memcmp (distrusted_cert->mpis[0], db_cert->mpis[0], sizeof > (db_cert->mpis[0])) == 0 > + && grub_memcmp (distrusted_cert->mpis[1], db_cert->mpis[1], sizeof > (db_cert->mpis[1])) == 0) > + return true; > + > + return false; > +} > + > + > +/* Check the certificate presence in the platform keystore dbx list. */ > +static grub_err_t > +is_dbx_cert (const struct x509_certificate *db_cert) > +{ > + grub_err_t rc; > + grub_size_t i; > + struct x509_certificate *distrusted_cert; > + > + for (i = 0; i < grub_pks_keystore.dbx_entries; i++) > + { > + if (grub_pks_keystore.dbx[i].data == NULL) > + continue; > + > + if (is_x509 (&grub_pks_keystore.dbx[i].guid) == true) > + { > + distrusted_cert = grub_zalloc (sizeof (struct x509_certificate)); > + if (distrusted_cert == NULL) > + return grub_error (GRUB_ERR_OUT_OF_MEMORY, "out of memory."); > + > + rc = parse_x509_certificate (grub_pks_keystore.dbx[i].data, > + grub_pks_keystore.dbx[i].data_size, > distrusted_cert); > + if (rc != GRUB_ERR_NONE) > + { > + grub_free (distrusted_cert); > + continue; > + } > + > + if (is_cert_match (distrusted_cert, db_cert) == true) > + { > + grub_printf ("Warning: a trusted certificate CN='%s' is > ignored " > + "because it is on the dbx list.\n", > db_cert->subject); > + grub_free (grub_pks_keystore.dbx[i].data); > + grub_memset (&grub_pks_keystore.dbx[i], 0, sizeof > (grub_pks_sd_t)); > + certificate_release (distrusted_cert); > + grub_free (distrusted_cert); > + return GRUB_ERR_ACCESS_DENIED; > + } > + > + certificate_release (distrusted_cert); > + grub_free (distrusted_cert); > + } > + } > + > + return GRUB_ERR_NONE; > +} > + > +/* Add the certificate into the db/dbx list */ > +static grub_err_t > +add_certificate (const grub_uint8_t *data, const grub_size_t data_size, > + struct grub_database *database, const bool is_db) > +{ > + struct x509_certificate *cert; > + grub_err_t rc; > + grub_size_t cert_entries = database->cert_entries; > + > + if (data == NULL || data_size == 0) > + return grub_error (GRUB_ERR_OUT_OF_RANGE, "certificate data or size is > empty."); > + > + cert = grub_zalloc (sizeof (struct x509_certificate)); > + if (cert == NULL) > + return grub_error (GRUB_ERR_OUT_OF_MEMORY, "out of memory."); > + > + rc = parse_x509_certificate (data, data_size, cert); > + if (rc != GRUB_ERR_NONE) > + { > + grub_dprintf ("appendedsig", "skipped %s certificate (%d)\n", > + (is_db == true ? "trusted":"distrusted"), (int) rc); > + grub_free (cert); > + return rc; > + } > + > + if (is_db == true) > + { > + rc = is_dbx_cert (cert); > + if (rc != GRUB_ERR_NONE) > + { > + certificate_release (cert); > + grub_free (cert); > + return rc; > + } > + } > + > + grub_dprintf ("appendedsig", "add a %s certificate CN='%s'\n", > + (is_db == true ? "trusted":"distrusted"), cert->subject); Missing spaces around ":"... Or better (is_db == true) ? "trusted" : "distrusted" > + > + cert_entries++; > + cert->next = database->certs; > + database->certs = cert; > + database->cert_entries = cert_entries; > + > + return rc; > +} [...] > +/* Add the X.509 certificates/binary hash to the db list. */ From where? PKS? Please be precise? > +static grub_err_t > +create_db_list (void) > +{ > + grub_err_t rc; > + grub_size_t i; > + > + for (i = 0; i < grub_pks_keystore.db_entries; i++) > + { > + if (is_hash (&grub_pks_keystore.db[i].guid) == true) > + { > + rc = add_db_binary_hash ((const grub_uint8_t **) > &grub_pks_keystore.db[i].data, > + grub_pks_keystore.db[i].data_size); > + if (rc == GRUB_ERR_OUT_OF_MEMORY) > + return rc; > + } > + else if (is_x509 (&grub_pks_keystore.db[i].guid) == true) > + { > + if (is_dbx_cert_hash (grub_pks_keystore.db[i].data, > + grub_pks_keystore.db[i].data_size) == true) > + continue; > + > + rc = add_certificate (grub_pks_keystore.db[i].data, > + grub_pks_keystore.db[i].data_size, &db, > true); > + if (rc == GRUB_ERR_OUT_OF_MEMORY) > + return rc; > + } > + else > + grub_dprintf ("appendedsig", "unsupported signature data type and " > + "skipped (%" PRIuGRUB_SIZE ")\n", i + 1); > + } > + > + return GRUB_ERR_NONE; > +} > + > +/* Add the certificates and certificate/binary hash to the dbx list. */ Ditto... > +static grub_err_t > +create_dbx_list (void) > +{ > + grub_err_t rc; > + grub_size_t i; > + > + for (i = 0; i < grub_pks_keystore.dbx_entries; i++) > + { > + if (grub_pks_keystore.dbx[i].data != NULL || > + grub_pks_keystore.dbx[i].data_size > 0) > + { > + if (is_x509 (&grub_pks_keystore.dbx[i].guid) == true) > + { > + rc = add_certificate (grub_pks_keystore.dbx[i].data, > + grub_pks_keystore.dbx[i].data_size, > &dbx, false); > + if (rc == GRUB_ERR_OUT_OF_MEMORY) > + return rc; > + } > + else if (is_hash (&grub_pks_keystore.dbx[i].guid) == true) > + { > + rc = add_hash ((const grub_uint8_t **) > &grub_pks_keystore.dbx[i].data, > + grub_pks_keystore.dbx[i].data_size, > + &dbx.signatures, &dbx.signature_size, > + &dbx.signature_entries); > + if (rc != GRUB_ERR_NONE) > + return rc; > + } > + else > + grub_dprintf ("appendedsig", "unsupported signature data type > and " > + "skipped (%" PRIuGRUB_SIZE ")\n", i + 1); > + } > + } > + > + return GRUB_ERR_NONE; > +} Daniel _______________________________________________ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel