[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [PATCH v1 16/21] appendedsig: The creation of trusted and distrusted
From: |
Stefan Berger |
Subject: |
Re: [PATCH v1 16/21] appendedsig: The creation of trusted and distrusted lists |
Date: |
Tue, 31 Dec 2024 12:21:34 -0500 |
User-agent: |
Mozilla Thunderbird |
On 12/18/24 9:56 AM, Sudhakar Kuppusamy wrote:
The trusted certificates and binary hashes, distrusted certificates and
binary/certificate hashes will be extracted from the platform keystore buffer
if Secure Boot is enabled with PKS.
In order to verify the integerity of the kernel, the extracted data
integrity
would be stored in the buffer db and dbx.
needs to be stored?
The trusted certificates will be extracted from the grub ELFNOTE if Secure Boot
is
enabled with static key. In order to verify the integerity of the kernel,
integrity
the extracted data would be stored in the buffer db.
needs to be stored?
Note:-
if the trusted certificate nor binary hash exists in the distrusted list (DBX),
If neither the ... nor ...
rejected it while extracting it from the platform keystore buffer.
what is 'it' in this context
Signed-off-by: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
---
grub-core/commands/appendedsig/appendedsig.c | 636 +++++++++++++++++--
1 file changed, 592 insertions(+), 44 deletions(-)
diff --git a/grub-core/commands/appendedsig/appendedsig.c
b/grub-core/commands/appendedsig/appendedsig.c
index 5c82b96a4..31649e800 100644
--- a/grub-core/commands/appendedsig/appendedsig.c
+++ b/grub-core/commands/appendedsig/appendedsig.c
@@ -34,7 +34,7 @@
#include <libtasn1.h>
#include <grub/env.h>
#include <grub/lockdown.h>
-
+#include <grub/platform_keystore.h>
#include "appendedsig.h"
GRUB_MOD_LICENSE ("GPLv3+");
@@ -64,9 +64,23 @@ struct grub_appended_signature
struct pkcs7_signedData pkcs7; /* Parsed PKCS#7 data */
};
-/* Trusted certificates for verifying appended signatures */
-struct x509_certificate *grub_trusted_key;
+/* This represents a trusted/distrusted list*/
+struct grub_database
+{
+ struct x509_certificate *keys; /* Certificates */
+ grub_size_t key_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 */
+};
+
+/* Trusted list */
+struct grub_database grub_db = {.keys = NULL, .key_entries = 0, .signatures =
NULL,
+ .signature_size = NULL, .signature_entries =
0};
+/* Distrusted list */
+struct grub_database grub_dbx = {.signatures = NULL, .signature_size = NULL,
+ .signature_entries = 0};
/*
* Force gcry_rsa to be a module dependency.
*
@@ -87,6 +101,13 @@ struct x509_certificate *grub_trusted_key;
* also resolves our concerns about loading from the filesystem.
*/
extern gcry_pk_spec_t _gcry_pubkey_spec_rsa;
+extern gcry_md_spec_t _gcry_digest_spec_sha224;
+extern gcry_md_spec_t _gcry_digest_spec_sha384;
+
+/* releasing trusted list memory */
Typically these functions start with 'free'. Free trusted list memory.
+static void grub_release_trusted_list (void);
+/* releasing distrusted list memory */
+static void grub_release_distrusted_list (void);
I am not sure whether local functions and variables should be prefixed
with grub_ since typically those prefixed wit grub_ are global
functions. This comment applies to all functions in this patch and series.
static enum
{
@@ -95,6 +116,248 @@ 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
+grub_get_hash (const grub_uuid_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 null");
+
+ if (grub_memcmp (guid, &GRUB_PKS_CERT_SHA256_GUID, GRUB_UUID_SIZE) == 0 ||
+ grub_memcmp (guid, &GRUB_PKS_CERT_X509_SHA256_GUID, GRUB_UUID_SIZE)
== 0)
+ hash_func = &_gcry_digest_spec_sha256;
+ else if (grub_memcmp (guid, &GRUB_PKS_CERT_SHA384_GUID, GRUB_UUID_SIZE) == 0
||
+ grub_memcmp (guid, &GRUB_PKS_CERT_X509_SHA384_GUID, GRUB_UUID_SIZE)
== 0)
+ hash_func = &_gcry_digest_spec_sha384;
+ else if (grub_memcmp (guid, &GRUB_PKS_CERT_SHA512_GUID, GRUB_UUID_SIZE) == 0
||
+ grub_memcmp (guid, &GRUB_PKS_CERT_X509_SHA512_GUID, GRUB_UUID_SIZE)
== 0)
+ hash_func = &_gcry_digest_spec_sha512;
+ else
+ return GRUB_ERR_UNKNOWN_COMMAND;
return grub_error (GRUB_ERR_OUT_OF_RANGE, "Unsupported GUID for hash")
+
+ grub_memset (hash, 0x00, GRUB_MAX_HASH_SIZE);
+ grub_crypto_hash (hash_func, hash, data, data_size);
+ *hash_size = hash_func->mdlen;
grub_memset(hash, 0, *hash_size);
+
+ return GRUB_ERR_NONE;
+}
+
+/* adding the certificate/binary hash into the trusted/distrusted list */
Add the ...
+static grub_err_t
+grub_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/size is
null");
+
+ if (signatures == NULL && signature_size == NULL)
+ {
+ signatures = grub_zalloc (sizeof (grub_uint8_t *));
+ signature_size = grub_zalloc (sizeof (grub_size_t));
+ }
+ else
+ {
+ signatures = grub_realloc (signatures, sizeof (grub_uint8_t *) *
(signature_entries + 1));
+ signature_size = grub_realloc (signature_size,
+ sizeof (grub_size_t) * (signature_entries
+ 1));
+ }
Also in this case grub_realloc can be used for first parameter being
NULL but may need a 2nd variable to handle allocation failures.
+
+ if (signatures == NULL || signature_size == NULL)
+ {
+ /*
+ * allocated memory will be freed by
+ * grub_release_trusted_list/grub_release_distrusted_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 grub_err_t
+grub_is_x509 (const grub_uuid_t *guid)
Return int like many other *_is_xyz functions do ?
+{
+ if (grub_memcmp (guid, &GRUB_PKS_CERT_X509_GUID, GRUB_UUID_SIZE) == 0)
+ return GRUB_ERR_NONE;
+
+ return GRUB_ERR_UNKNOWN_COMMAND;
+}
+
+static grub_err_t
+grub_is_cert_match (const struct x509_certificate *distrusted_cert,
+ const struct x509_certificate *db_cert)
Return int ?
+{
+
+ 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 GRUB_ERR_NONE;
+
+ return GRUB_ERR_UNKNOWN_COMMAND;
+}
+
+/*
+ * verify the certificate against the certificate from platform keystore
buffer's
Verify -- capitalize everywhere.
+ * distrusted list, if it is present, return a bad signature.
You won't construct a bad signture but you return GRUB_ERR_BAD_SIGNATURE.
+ * else, no errors.
Otherwise no error is returned. -- or omit entirely. Also in other cases.
It looks like it can return GRUB_ERR_OUT_OF_MEMORY as well.
+ */
+static grub_err_t
+grub_is_distrusted_cert (const struct x509_certificate *db_cert)
So this one here can have allocation failures and should return
grub_err_t but calls the other two without propagating their errors.
+{
+ grub_err_t rc = GRUB_ERR_NONE;
+ grub_size_t i = 0;
+ struct x509_certificate *distrusted_cert = NULL;
+
+ for (i = 0; i < grub_platform_keystore.dbx_entries; i++)
+ {
+ if (grub_platform_keystore.dbx[i].data == NULL &&
should be a '||' or simply remove data_size == 0 check?
+ grub_platform_keystore.dbx[i].data_size == 0)
+ continue;
+
+ if (grub_is_x509 (&grub_platform_keystore.dbx[i].guid) == GRUB_ERR_NONE)
+ {
+ 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_platform_keystore.dbx[i].data,
+
grub_platform_keystore.dbx[i].data_size, distrusted_cert);
+ if (rc != GRUB_ERR_NONE)
+ {
+ grub_free (distrusted_cert);
+ continue;
+ }
+
+ if (grub_is_cert_match (distrusted_cert, db_cert) == GRUB_ERR_NONE)
+ {
+ grub_printf ("Warning: a trusted certificate CN='%s' is ignored "
+ "because it is on the distrusted list (dbx).\n",
db_cert->subject);
+ grub_free (grub_platform_keystore.dbx[i].data);
+ grub_memset (&grub_platform_keystore.dbx[i], 0x00, sizeof
(grub_pks_sd_t));
s/0x00/0
+ certificate_release (distrusted_cert);
+ grub_free (distrusted_cert);
+ return GRUB_ERR_BAD_SIGNATURE;
+ }
+
+ certificate_release (distrusted_cert);
+ grub_free (distrusted_cert);
+ }
+ }
+
+ return GRUB_ERR_NONE;
+}
+
+/* adding the certificate into the trusted/distrusted list */
Add the ..
+static grub_err_t
+grub_add_certificate (const grub_uint8_t *data, const grub_size_t data_size,
+ struct grub_database *database, const grub_size_t is_db)
+{
+ grub_err_t rc = GRUB_ERR_NONE;
+ grub_size_t key_entries = database->key_entries;
+ struct x509_certificate *cert = NULL;
+
+ if (data == NULL || data_size == 0)
+ return grub_error (GRUB_ERR_OUT_OF_RANGE, "certificate data/size is null");
+
+ 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_printf ("Warning: skipping %s certificate (%d)\n",
+ (is_db ? "trusted":"distrused"), rc);
+ grub_free (cert);
+ return rc;
+ }
+
+ if (is_db)
+ {
+ rc = grub_is_distrusted_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 ? "trusted":"distrused"), cert->subject);
distrusted
+
+ key_entries++;
+ cert->next = database->keys;
+ database->keys = cert;
+ database->key_entries = key_entries;
+
+ return rc;
+}
+
+static grub_err_t
+grub_read_file (const grub_file_t file, grub_uint8_t **data, grub_ssize_t
*data_size)
This function sounds so generic that it could be used in other places as
well. It would we goood to move it to the same file as grub_file_read.
+{
+ grub_uint8_t *buffer = NULL;
+ grub_ssize_t read_size = 0;
+ grub_off_t total_read_size = 0;
+ grub_off_t file_size = grub_file_size (file);
+
+ if (file_size == GRUB_FILE_SIZE_UNKNOWN)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT,
+ N_("could not parse the unknown size of the file."));
could not determine the size of the file
+
+ buffer = grub_zalloc (file_size);
+ if (buffer == NULL)
+ return grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
+
+ while (total_read_size < file_size)
+ {
+ read_size = grub_file_read (file, &buffer[total_read_size], file_size -
total_read_size);
+ if (read_size < 0)
+ {
+ grub_free (buffer);
+ return grub_error (GRUB_ERR_READ_ERROR, N_("unable to read the
file"));
+ }
+
+ total_read_size += read_size;
+ }
+
+ *data = buffer;
+ *data_size = total_read_size;
+
+ return GRUB_ERR_NONE;
+}
+
static const char *
grub_env_read_sec (struct grub_env_var *var __attribute__ ((unused)),
const char *val __attribute__ ((unused)))
@@ -248,7 +511,7 @@ grub_verify_appended_signature (const grub_uint8_t *buf,
grub_size_t bufsize)
struct pkcs7_signerInfo *si;
int i;
- if (!grub_trusted_key)
+ if (!grub_db.key_entries)
return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("No trusted keys to verify
against"));
err = extract_appended_signature (buf, bufsize, &sig);
@@ -279,7 +542,7 @@ grub_verify_appended_signature (const grub_uint8_t *buf,
grub_size_t bufsize)
datasize, i, hash[0], hash[1], hash[2], hash[3]);
err = GRUB_ERR_BAD_SIGNATURE;
- for (pk = grub_trusted_key; pk; pk = pk->next)
+ for (pk = grub_db.keys; pk; pk = pk->next)
{
rc = grub_crypto_rsa_pad (&hashmpi, hash, si->hash, pk->mpis[0]);
if (rc)
@@ -376,16 +639,16 @@ grub_cmd_distrust (grub_command_t cmd __attribute__
((unused)), int argc, char *
if (cert_num == 1)
{
- cert = grub_trusted_key;
- grub_trusted_key = cert->next;
+ cert = grub_db.keys;
+ grub_db.keys = cert->next;
certificate_release (cert);
grub_free (cert);
return GRUB_ERR_NONE;
}
i = 2;
- prev = grub_trusted_key;
- cert = grub_trusted_key->next;
+ prev = grub_db.keys;
+ cert = grub_db.keys->next;
while (cert)
{
if (i == cert_num)
@@ -432,8 +695,8 @@ grub_cmd_trust (grub_command_t cmd __attribute__
((unused)), int argc, char **ar
}
grub_dprintf ("appendedsig", "Loaded certificate with CN: %s\n",
cert->subject);
- cert->next = grub_trusted_key;
- grub_trusted_key = cert;
+ cert->next = grub_db.keys;
+ grub_db.keys = cert;
return GRUB_ERR_NONE;
}
@@ -446,7 +709,7 @@ grub_cmd_list (grub_command_t cmd __attribute__ ((unused)),
int argc __attribute
int cert_num = 1;
grub_size_t i;
- for (cert = grub_trusted_key; cert; cert = cert->next)
+ for (cert = grub_db.keys; cert; cert = cert->next)
{
grub_printf (N_("Certificate %d:\n"), cert_num);
@@ -539,6 +802,280 @@ static struct grub_fs pseudo_fs = { .name = "pseudo", .fs_read = pseudo_read };
static grub_command_t cmd_verify, cmd_list, cmd_distrust, cmd_trust;
+/*
+ * verify the trusted certificate against the certificate hashes from platform
keystore buffer's
Verify
+ * distrusted list, if it is present, return a bad signature.
Same comments as above.
+ * else, no errors.
+ */
+static grub_err_t
+grub_is_distrusted_cert_hash (const grub_uint8_t *data, const grub_size_t
data_size)
+{
+ grub_err_t rc = GRUB_ERR_NONE;
+ grub_size_t i = 0, cert_hash_size = 0;
+ grub_uint8_t cert_hash[GRUB_MAX_HASH_SIZE] = { 0 };
+
+ if (data == NULL || data_size == 0)
+ return grub_error (GRUB_ERR_OUT_OF_RANGE, "trusted certificate data/size is
null");
+
+ for (i = 0; i < grub_platform_keystore.dbx_entries; i++)
+ {
+ if (grub_platform_keystore.dbx[i].data == NULL &&
'||' ?
+ grub_platform_keystore.dbx[i].data_size == 0)
+ continue;
+
+ rc = grub_get_hash (&grub_platform_keystore.dbx[i].guid, data, data_size,
+ cert_hash, &cert_hash_size);
+ if (rc != GRUB_ERR_NONE)
+ continue;
+
+ if (cert_hash_size == grub_platform_keystore.dbx[i].data_size &&
+ grub_memcmp (grub_platform_keystore.dbx[i].data, cert_hash,
cert_hash_size) == 0)
+ {
+ grub_printf ("Warning: a trusted certificate (%02x%02x%02x%02x) is
ignored "
+ "because this certificate hash is on the distrusted list
(dbx).\n",
+ cert_hash[0], cert_hash[1], cert_hash[2], cert_hash[3]);
+ grub_free (grub_platform_keystore.dbx[i].data);
+ grub_memset (&grub_platform_keystore.dbx[i], 0x00, sizeof
(grub_pks_sd_t));
s/0x00/0
sizeof(grub_platform_keystore.dbx[i]) -- so we don't need to know the
type of this array
+ return GRUB_ERR_BAD_SIGNATURE;
+ }
+ }
+
+ return GRUB_ERR_NONE;
+}
+
+/*
+ * verify the trusted binary hash against the platform keystore buffer's
Verify.
+ * distrusted list, if it is present, return a bad signature.
Same comments as above.
+ * else, no errors.
+ */
+static grub_err_t
+grub_is_distrusted_binary_hash (const grub_uint8_t *binary_hash,
+ const grub_size_t binary_hash_size)
+{
+ grub_size_t i = 0;
+
+ for (i = 0; i < grub_platform_keystore.dbx_entries; i++)
+ {
+ if (grub_platform_keystore.dbx[i].data == NULL &&
'||' ?
+ grub_platform_keystore.dbx[i].data_size == 0)
+ continue;
+
+ if (binary_hash_size == grub_platform_keystore.dbx[i].data_size &&
+ grub_memcmp (grub_platform_keystore.dbx[i].data, binary_hash,
binary_hash_size) == 0)
+ {
+ grub_printf ("Warning: a trusted binary hash (%02x%02x%02x%02x) is
ignored"
+ " because it is on the distrusted list (dbx).\n",
+ binary_hash[0], binary_hash[1], binary_hash[2],
binary_hash[3]);
+ grub_free (grub_platform_keystore.dbx[i].data);
+ grub_memset (&grub_platform_keystore.dbx[i], 0x00, sizeof
(grub_pks_sd_t));
same comments as above
+ return GRUB_ERR_BAD_SIGNATURE;
+ }
+ }
+
+ return GRUB_ERR_NONE;
+}
+
+/*
+ * extracts the binary hashes from the platform keystore buffer,
Extract the ...
+ * and adds it to the trusted list if not exists in distrusted list.
and add it .. if it does not exist in the distrusted list.
+ */
+static grub_err_t
+grub_add_trusted_binary_hash (const grub_uint8_t **data, const grub_size_t
data_size)
+{
+ grub_err_t rc = GRUB_ERR_NONE;
+
+ if (*data == NULL || data_size == 0)
Here you have the '||'...
+ return grub_error (GRUB_ERR_OUT_OF_RANGE, "trusted binary hash data/size is
null");
+
+ rc = grub_is_distrusted_binary_hash (*data, data_size);
+ if (rc != GRUB_ERR_NONE)
+ return rc;
+
+ rc = grub_add_hash (data, data_size, &grub_db.signatures,
&grub_db.signature_size,
+ &grub_db.signature_entries);
+ return rc;
+}
+
+static grub_err_t
+grub_is_hash (const grub_uuid_t *guid)
Same comments as with other functions as above.
+{
+ /* GUID type of the binary hash */
+ if (grub_memcmp (guid, &GRUB_PKS_CERT_SHA256_GUID, GRUB_UUID_SIZE) == 0 ||
+ grub_memcmp (guid, &GRUB_PKS_CERT_SHA384_GUID, GRUB_UUID_SIZE) == 0 ||
+ grub_memcmp (guid, &GRUB_PKS_CERT_SHA512_GUID, GRUB_UUID_SIZE) == 0)
+ return GRUB_ERR_NONE;
+
+ /* GUID type of the certificate hash */
+ if (grub_memcmp (guid, &GRUB_PKS_CERT_X509_SHA256_GUID, GRUB_UUID_SIZE) == 0
||
+ grub_memcmp (guid, &GRUB_PKS_CERT_X509_SHA384_GUID, GRUB_UUID_SIZE) == 0
||
+ grub_memcmp (guid, &GRUB_PKS_CERT_X509_SHA512_GUID, GRUB_UUID_SIZE) == 0)
+ return GRUB_ERR_NONE;
+
+ return GRUB_ERR_UNKNOWN_COMMAND;
+}
+
> +/*> + * extracts the x509 certificates/binary hashes from the
platform keystore buffer,
Extract the x509...
+ * parses it, and adds it to the trusted list.
parse it, and add it to the trusted list.
+ */
+static grub_err_t
+grub_create_trusted_list (void)
+{
+ grub_err_t rc = GRUB_ERR_NONE;
+ grub_size_t i = 0;
+
+ for (i = 0; i < grub_platform_keystore.db_entries; i++)
+ {
+ if (grub_is_hash (&grub_platform_keystore.db[i].guid) == GRUB_ERR_NONE)
+ {
+ rc = grub_add_trusted_binary_hash ((const grub_uint8_t **)
+
&grub_platform_keystore.db[i].data,
+
grub_platform_keystore.db[i].data_size);
+ if (rc == GRUB_ERR_OUT_OF_MEMORY)
+ return rc;
+
+ continue;
'continue' not needed
+ }
+ else if (grub_is_x509 (&grub_platform_keystore.db[i].guid) ==
GRUB_ERR_NONE)
+ {
+
stray empty line
+ rc = grub_is_distrusted_cert_hash (grub_platform_keystore.db[i].data,
+
grub_platform_keystore.db[i].data_size);
> + if (rc != GRUB_ERR_NONE)> + continue;
+
+ rc = grub_add_certificate (grub_platform_keystore.db[i].data,
+ grub_platform_keystore.db[i].data_size,
&grub_db, 1);
+ if (rc == GRUB_ERR_OUT_OF_MEMORY)
+ return rc;
+ else if (rc != GRUB_ERR_NONE)
+ continue;
+ }
+ else
+ grub_printf ("Warning: unsupported signature data type and "
+ "skipping trusted data (%" PRIuGRUB_SIZE ")\n", i + 1);
+ }
+
+ return GRUB_ERR_NONE;
+}
+
+/*
+ * extracts the certificates, certificate/binary hashes out of the platform
keystore buffer,
+ * and adds it to the distrusted list.
+ */
+static grub_err_t
+grub_create_distrusted_list (void)
+{
+ grub_err_t rc = GRUB_ERR_NONE;
+ grub_size_t i = 0;
+
+ for (i = 0; i < grub_platform_keystore.dbx_entries; i++)
+ {
+ if (grub_platform_keystore.dbx[i].data != NULL &&
'||'?
+ grub_platform_keystore.dbx[i].data_size > 0)
+ {
+ if (grub_is_x509 (&grub_platform_keystore.dbx[i].guid) ==
GRUB_ERR_NONE)
+ {
+ rc = grub_add_certificate (grub_platform_keystore.dbx[i].data,
+ grub_platform_keystore.dbx[i].data_size,
&grub_dbx, 0);
+ if (rc == GRUB_ERR_OUT_OF_MEMORY)
+ return rc;
+ }
+ else if (grub_is_hash (&grub_platform_keystore.dbx[i].guid) ==
GRUB_ERR_NONE)
+ {
+ rc = grub_add_hash ((const grub_uint8_t **)
&grub_platform_keystore.dbx[i].data,
+ grub_platform_keystore.dbx[i].data_size,
+ &grub_dbx.signatures,
&grub_dbx.signature_size,
+ &grub_dbx.signature_entries);
+ if (rc != GRUB_ERR_NONE)
+ return rc;
+ }
+ else
+ grub_printf ("Warning: unsupported signature data type and "
+ "skipping distrusted data (%" PRIuGRUB_SIZE ")\n", i
+ 1);
+ }
+ }
+
+ return rc;
+}
+
+/*
+ * extracts the x509 certificates from the ELF note header,
+ * parses it, and adds it to the trusted list.
+ */
+static grub_err_t
+grub_build_static_trusted_list (const struct grub_module_header *header)
+{
+ grub_err_t err = GRUB_ERR_NONE;
+ struct grub_file pseudo_file;
+ grub_uint8_t *cert_data = NULL;
+ grub_ssize_t cert_data_size = 0;
+
+ grub_memset (&pseudo_file, 0, sizeof (pseudo_file));
ah, '0'
+ pseudo_file.fs = &pseudo_fs;
+ pseudo_file.size = header->size - sizeof (struct grub_module_header);
+ pseudo_file.data = (char *) header + sizeof (struct grub_module_header);
+
+ grub_dprintf ("appendedsig", "found an x509 key, size=%" PRIuGRUB_UINT64_T
"\n",
+ pseudo_file.size);
+
+ err = grub_read_file (&pseudo_file, &cert_data, &cert_data_size);
+ if (err != GRUB_ERR_NONE)
+ return err;
+
+ err = grub_add_certificate (cert_data, cert_data_size, &grub_db, 1);
+ if (cert_data != NULL)
+ grub_free (cert_data);
no need to check for cert_data != NULL
+
+ return err;
+}
+
+/* releasing memory */
+static void
+grub_release_trusted_list (void)
+{
+ struct x509_certificate *cert;
+ grub_size_t i = 0;
+
+ while (grub_db.keys != NULL)
+ {
+ cert = grub_db.keys;
+ grub_db.keys = grub_db.keys->next;
+ certificate_release (cert);
+ grub_free (cert);
+ }
+
+ for (i = 0; i < grub_db.signature_entries; i++)
+ grub_free (grub_db.signatures[i]);
+
+ grub_free (grub_db.signatures);
+ grub_free (grub_db.signature_size);
+ grub_memset (&grub_db, 0x00, sizeof (grub_db));
s/0x00/0
+}
+
+/* releasing memory */
+static void
+grub_release_distrusted_list (void)
+{
+ struct x509_certificate *cert;
+ grub_size_t i = 0;
+
+ while (grub_dbx.keys != NULL)
+ {
+ cert = grub_dbx.keys;
+ grub_dbx.keys = grub_dbx.keys->next;
+ certificate_release (cert);
+ grub_free (cert);
+ }
+
+ for (i = 0; i < grub_dbx.signature_entries; i++)
+ grub_free (grub_dbx.signatures[i]);
+
+ grub_free (grub_dbx.signatures);
+ grub_free (grub_dbx.signature_size);
+ grub_memset (&grub_dbx, 0x00, sizeof (grub_dbx));
s/0x00.0
+}
+
GRUB_MOD_INIT (appendedsig)
{
int rc;
@@ -548,7 +1085,6 @@ GRUB_MOD_INIT (appendedsig)
if (grub_is_lockdown () == GRUB_LOCKDOWN_ENABLED)
check_sigs = check_sigs_forced;
- grub_trusted_key = NULL;
grub_register_variable_hook ("check_appended_signatures",
grub_env_read_sec, grub_env_write_sec);
grub_env_export ("check_appended_signatures");
@@ -556,39 +1092,51 @@ GRUB_MOD_INIT (appendedsig)
if (rc)
grub_fatal ("Error initing ASN.1 data structures: %d: %s\n", rc,
asn1_strerror (rc));
- FOR_MODULES (header)
- {
- struct grub_file pseudo_file;
- struct x509_certificate *pk = NULL;
- grub_err_t err;
-
- /* Not an X.509 certificate, skip. */
- if (header->type != OBJ_TYPE_X509_PUBKEY)
- continue;
-
- grub_memset (&pseudo_file, 0, sizeof (pseudo_file));
- pseudo_file.fs = &pseudo_fs;
- pseudo_file.size = header->size - sizeof (struct grub_module_header);
- pseudo_file.data = (char *) header + sizeof (struct grub_module_header);
-
- grub_dprintf ("appendedsig", "Found an x509 key, size=%" PRIuGRUB_UINT64_T
"\n",
- pseudo_file.size);
-
- pk = grub_zalloc (sizeof (struct x509_certificate));
- if (!pk)
- {
- grub_fatal ("Out of memory loading initial certificates");
- }
-
- err = read_cert_from_file (&pseudo_file, pk);
- if (err != GRUB_ERR_NONE)
- grub_fatal ("Error loading initial key: %s", grub_errmsg);
+ if (!grub_use_platform_keystore && check_sigs == check_sigs_forced)
+ {
+ FOR_MODULES (header)
+ {
+ /* Not an ELF module, skip. */
+ if (header->type != OBJ_TYPE_X509_PUBKEY)
+ continue;
- grub_dprintf ("appendedsig", "loaded certificate CN='%s'\n", pk->subject);
+ rc = grub_build_static_trusted_list (header);
+ if (rc != GRUB_ERR_NONE)
+ {
+ grub_release_trusted_list ();
+ grub_error (rc, "static trusted list creation failed");
+ }
+ else
+ grub_printf ("appendedsig: the trusted list now has %" PRIuGRUB_SIZE "
static keys\n",
+ grub_db.key_entries);
+ }
+ }
+ else if (grub_use_platform_keystore && check_sigs == check_sigs_forced)
+ {
+ rc = grub_create_trusted_list ();
+ if (rc != GRUB_ERR_NONE)
+ {
+ grub_release_trusted_list ();
+ grub_error (rc, "trusted list creation failed");
+ }
+ else
+ {
+ rc = grub_create_distrusted_list ();
+ if (rc != GRUB_ERR_NONE)
+ {
+ grub_release_trusted_list ();
+ grub_release_distrusted_list ();
+ grub_error (rc, "distrusted list creation failed");
+ }
+ else
+ grub_printf ("appendedsig: the trusted list now has %" PRIuGRUB_SIZE "
keys.\n"
+ "appendedsig: the distrusted list now has %" PRIuGRUB_SIZE
" keys.\n",
+ grub_db.signature_entries + grub_db.key_entries,
+ grub_dbx.signature_entries);
+ }
- pk->next = grub_trusted_key;
- grub_trusted_key = pk;
- }
+ grub_release_platform_keystore ();
+ }
cmd_trust = grub_register_command ("trust_certificate", grub_cmd_trust, N_("X509_CERTIFICATE"),
N_("Add X509_CERTIFICATE to trusted
certificates."));
- Re: [PATCH v1 15/21] ieee1275: Read the DB and DBX secure boot variables, (continued)
- [PATCH v1 10/21] appended signatures: support verifying appended signatures, Sudhakar Kuppusamy, 2024/12/18
- [PATCH v1 12/21] appended signatures: documentation, Sudhakar Kuppusamy, 2024/12/18
- [PATCH v1 11/21] appended signatures: verification tests, Sudhakar Kuppusamy, 2024/12/18
- [PATCH v1 13/21] ieee1275: enter lockdown based on /ibm,secure-boot, Sudhakar Kuppusamy, 2024/12/18
- [PATCH v1 16/21] appendedsig: The creation of trusted and distrusted lists, Sudhakar Kuppusamy, 2024/12/18
- Re: [PATCH v1 16/21] appendedsig: The creation of trusted and distrusted lists,
Stefan Berger <=
- [PATCH v1 17/21] appendedsig: While verifying the kernel, use trusted and distrusted lists, Sudhakar Kuppusamy, 2024/12/18
- [PATCH v1 18/21] ieee1275: set use_static_keys flag, Sudhakar Kuppusamy, 2024/12/18
- [PATCH v1 19/21] appendedsig: Reads the default DB keys from ELF Note, Sudhakar Kuppusamy, 2024/12/18
- [PATCH v1 20/21] appendedsig: The grub command's trusted and distrusted support, Sudhakar Kuppusamy, 2024/12/18
- [PATCH v1 21/21] appendedsig: documentation, Sudhakar Kuppusamy, 2024/12/18