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.
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);
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++)
{