Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
Base:System
grub2
0004-appendedsig-While-verifying-the-kernel-use...
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 0004-appendedsig-While-verifying-the-kernel-use-trusted-a.patch of Package grub2
From 5bff27911bb6575b80b5decf5364b7e6bde801d3 Mon Sep 17 00:00:00 2001 From: Sudhakar Kuppusamy <sudhakar@linux.ibm.com> Date: Wed, 18 Jan 2023 23:04:38 +0530 Subject: [PATCH 4/8] appendedsig: While verifying the kernel, use trusted and distrusted lists To verify the kernel's, the trusted key will be used from the trusted key list. If it fails, verify it against the list of hashes that are distrusted and trusted. Signed-off-by: Sudhakar Kuppusamy <sudhakar@linux.ibm.com> Reviewed-by: Stefan Berger <stefanb@linux.ibm.com> Tested-by: Nageswara Sastry <rnsastry@linux.ibm.com> --- grub-core/commands/appendedsig/appendedsig.c | 187 +++++++++++++------ 1 file changed, 131 insertions(+), 56 deletions(-) diff --git a/grub-core/commands/appendedsig/appendedsig.c b/grub-core/commands/appendedsig/appendedsig.c index 5bb09e349..f9638220e 100644 --- a/grub-core/commands/appendedsig/appendedsig.c +++ b/grub-core/commands/appendedsig/appendedsig.c @@ -36,6 +36,10 @@ #include <grub/platform_keystore.h> #include "appendedsig.h" +#define SHA256_LEN 32 +#define SHA384_LEN 48 +#define SHA512_LEN 64 + GRUB_MOD_LICENSE ("GPLv3+"); const char magic[] = "~Module signature appended~\n"; @@ -516,6 +520,80 @@ extract_appended_signature (const grub_uint8_t *buf, grub_size_t bufsize, return GRUB_ERR_NONE; } +static grub_err_t +grub_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_uuid_t guid = { 0 }; + + /* support SHA256, SHA384 and SHA512 for binary hash */ + if (binary_hash_size == SHA256_LEN) + grub_memcpy (&guid, &GRUB_PKS_CERT_SHA256_GUID, GRUB_UUID_SIZE); + else if (binary_hash_size == SHA384_LEN) + grub_memcpy (&guid, &GRUB_PKS_CERT_SHA384_GUID, GRUB_UUID_SIZE); + else if (binary_hash_size == SHA512_LEN) + grub_memcpy (&guid, &GRUB_PKS_CERT_SHA512_GUID, GRUB_UUID_SIZE); + else + { + grub_dprintf ("appendedsig", "unsupported hash type (%" PRIuGRUB_SIZE ") and skipping binary hash\n", + binary_hash_size); + return GRUB_ERR_UNKNOWN_COMMAND; + } + + return grub_get_hash (&guid, data, data_size, hash, hash_size); +} + +/* + * verify binary hash against the list of binary hashes that are distrusted + * and trusted. + */ +static grub_err_t +grub_verify_binary_hash (const grub_uint8_t *data, const grub_size_t data_size) +{ + grub_err_t rc = GRUB_ERR_NONE; + grub_size_t i = 0, hash_size = 0; + grub_uint8_t hash[GRUB_MAX_HASH_SIZE] = { 0 }; + + for (i = 0; i < grub_dbx.signature_entries; i++) + { + rc = grub_get_binary_hash (grub_dbx.signature_size[i], data, data_size, + hash, &hash_size); + if (rc != GRUB_ERR_NONE) + continue; + + if (hash_size == grub_dbx.signature_size[i] && + grub_memcmp (grub_dbx.signatures[i], hash, hash_size) == 0) + { + grub_dprintf ("appendedsig", "the binary hash (%02x%02x%02x%02x) was listed " + "as distrusted\n", hash[0], hash[1], hash[2], hash[3]); + return GRUB_ERR_BAD_SIGNATURE; + } + } + + for (i = 0; i < grub_db.signature_entries; i++) + { + rc = grub_get_binary_hash (grub_db.signature_size[i], data, data_size, + hash, &hash_size); + if (rc != GRUB_ERR_NONE) + continue; + + if (hash_size == grub_db.signature_size[i] && + grub_memcmp (grub_db.signatures[i], hash, hash_size) == 0) + { + grub_dprintf ("appendedsig", "verified with a trusted binary hash " + "(%02x%02x%02x%02x)\n", hash[0], hash[1], hash[2], hash[3]); + return GRUB_ERR_NONE; + } + } + + return GRUB_ERR_EOF; +} + +/* + * verify the kernel's integrity, the trusted key will be used from + * the trusted key list. If it fails, verify it against the list of binary hashes + * that are distrusted and trusted. + */ static grub_err_t grub_verify_appended_signature (const grub_uint8_t *buf, grub_size_t bufsize) { @@ -525,12 +603,12 @@ grub_verify_appended_signature (const grub_uint8_t *buf, grub_size_t bufsize) unsigned char *hash; gcry_mpi_t hashmpi; gcry_err_code_t rc; - struct x509_certificate *pk; + struct x509_certificate *cert; struct grub_appended_signature sig; struct pkcs7_signerInfo *si; int i; - if (!grub_db.key_entries) + if (!grub_db.key_entries && !grub_db.signature_entries) return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("No trusted keys to verify against")); err = extract_appended_signature (buf, bufsize, &sig); @@ -538,70 +616,67 @@ grub_verify_appended_signature (const grub_uint8_t *buf, grub_size_t bufsize) return err; datasize = bufsize - sig.signature_len; - - for (i = 0; i < sig.pkcs7.signerInfo_count; i++) + /* checking kernel binary hash is presents in trusted list (db)/distrusted list (dbx) */ + err = grub_verify_binary_hash (buf, datasize); + if (err == GRUB_ERR_EOF) { - /* This could be optimised in a couple of ways: - - we could only compute hashes once per hash type - - we could track signer information and only verify where IDs match - For now we do the naive O(trusted keys * pkcs7 signers) approach. - */ - si = &sig.pkcs7.signerInfos[i]; - context = grub_zalloc (si->hash->contextsize); - if (!context) - return grub_errno; - - si->hash->init (context); - si->hash->write (context, buf, datasize); - si->hash->final (context); - hash = si->hash->read (context); - - grub_dprintf ("appendedsig", - "data size %" PRIxGRUB_SIZE ", signer %d hash %02x%02x%02x%02x...\n", - datasize, i, hash[0], hash[1], hash[2], hash[3]); - - err = GRUB_ERR_BAD_SIGNATURE; - for (pk = grub_db.keys; pk; pk = pk->next) + /* verifying kernel binary signature using trusted keys from trusted list (db) */ + for (i = 0; i < sig.pkcs7.signerInfo_count; i++) { - rc = grub_crypto_rsa_pad (&hashmpi, hash, si->hash, pk->mpis[0]); - if (rc) + si = &sig.pkcs7.signerInfos[i]; + context = grub_zalloc (si->hash->contextsize); + if (!context) + return grub_errno; + + si->hash->init (context); + si->hash->write (context, buf, datasize); + si->hash->final (context); + hash = si->hash->read (context); + + grub_dprintf ("appendedsig", + "data size %" PRIxGRUB_SIZE ", signer %d hash %02x%02x%02x%02x...\n", + datasize, i, hash[0], hash[1], hash[2], hash[3]); + + err = GRUB_ERR_BAD_SIGNATURE; + for (cert = grub_db.keys; cert; cert = cert->next) { - err = grub_error (GRUB_ERR_BAD_SIGNATURE, - N_("Error padding hash for RSA verification: %d"), rc); - grub_free (context); - goto cleanup; + rc = grub_crypto_rsa_pad (&hashmpi, hash, si->hash, cert->mpis[0]); + if (rc) + { + err = grub_error (GRUB_ERR_BAD_SIGNATURE, + N_("Error padding hash for RSA verification: %d"), rc); + grub_free (context); + pkcs7_signedData_release (&sig.pkcs7); + return err; + } + + rc = _gcry_pubkey_spec_rsa.verify (0, hashmpi, &si->sig_mpi, cert->mpis, NULL, NULL); + gcry_mpi_release (hashmpi); + + if (rc == 0) + { + grub_dprintf ("appendedsig", "verify signer %d with key '%s' succeeded\n", + i, cert->subject); + err = GRUB_ERR_NONE; + break; + } + + grub_dprintf ("appendedsig", "verify signer %d with key '%s' failed with %d\n", + i, cert->subject, rc); } - rc = _gcry_pubkey_spec_rsa.verify (0, hashmpi, &si->sig_mpi, - pk->mpis, NULL, NULL); - gcry_mpi_release (hashmpi); - - if (rc == 0) - { - grub_dprintf ("appendedsig", - "verify signer %d with key '%s' succeeded\n", i, - pk->subject); - err = GRUB_ERR_NONE; - break; - } - - grub_dprintf ("appendedsig", - "verify signer %d with key '%s' failed with %d\n", i, - pk->subject, rc); - } - - grub_free (context); + grub_free (context); - if (err == GRUB_ERR_NONE) - break; + if (err == GRUB_ERR_NONE) + break; + } } - /* If we didn't verify, provide a neat message */ if (err != GRUB_ERR_NONE) - err = grub_error (GRUB_ERR_BAD_SIGNATURE, - N_("Failed to verify signature against a trusted key")); + grub_printf ("appendedsig: failed to verify signature with any trusted key\n"); + else + grub_printf ("appendedsig: successfully verified the signature with a trusted key\n"); -cleanup: pkcs7_signedData_release (&sig.pkcs7); return err; -- 2.47.0
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor