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

Reply via email to