137 lines
4.9 KiB
Diff
137 lines
4.9 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:59 +0530
|
|
Subject: [PATCH] appended signatures: Using db and dbx lists for signature
|
|
verification
|
|
|
|
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: 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 0c4c788..9cfa1be 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++)
|
|
{
|