690 lines
23 KiB
Diff
690 lines
23 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
|
|
Date: Mon, 6 Oct 2025 12:54:58 +0530
|
|
Subject: [PATCH] appended signatures: Create db and dbx lists
|
|
|
|
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 db does not exist 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 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: Avnish Chouhan <avnish@linux.ibm.com>
|
|
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
|
---
|
|
grub-core/commands/appendedsig/appendedsig.c | 407 +++++++++++++++++++++++++--
|
|
include/grub/efi/pks.h | 112 ++++++++
|
|
include/grub/types.h | 4 +
|
|
3 files changed, 506 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 ca54c90..0c4c788 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,45 @@ 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 db does not exist 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_exists == false)
|
|
+ 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 +767,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 +990,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 +1020,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 0000000..ff306f5
|
|
--- /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 59e0302..5f37adb 100644
|
|
--- a/include/grub/types.h
|
|
+++ b/include/grub/types.h
|
|
@@ -380,6 +380,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;
|
|
@@ -389,4 +391,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 */
|