Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
home:michael-chang:bsc:1224465
grub2
0003-appendedsig-The-creation-of-trusted-and-di...
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 0003-appendedsig-The-creation-of-trusted-and-distrusted-l.patch of Package grub2
From 350e8d823db1febc2c81635115ef3c4c0f41f3e7 Mon Sep 17 00:00:00 2001 From: Sudhakar Kuppusamy <sudhakar@linux.ibm.com> Date: Tue, 17 Jan 2023 22:38:05 +0530 Subject: [PATCH 3/8] appendedsig: The creation of trusted and distrusted lists 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 would be stored in the buffer db and dbx. 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, the extracted data would be stored in the buffer db. Note:- if the trusted certificate nor binary hash exists in the distrusted list (DBX), rejected it while extracting it from the platform keystore buffer. 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 | 701 +++++++++++++++++-- 1 file changed, 635 insertions(+), 66 deletions(-) diff --git a/grub-core/commands/appendedsig/appendedsig.c b/grub-core/commands/appendedsig/appendedsig.c index e63ad1ac6..5bb09e349 100644 --- a/grub-core/commands/appendedsig/appendedsig.c +++ b/grub-core/commands/appendedsig/appendedsig.c @@ -33,7 +33,7 @@ #include <grub/libtasn1.h> #include <grub/env.h> #include <grub/lockdown.h> - +#include <grub/platform_keystore.h> #include "appendedsig.h" GRUB_MOD_LICENSE ("GPLv3+"); @@ -66,8 +66,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. @@ -90,12 +105,263 @@ struct x509_certificate *grub_trusted_key; */ 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 */ +static void grub_release_trusted_list (void); +/* releasing distrusted list memory */ +static void grub_release_distrusted_list (void); + static enum { check_sigs_no = 0, check_sigs_enforce = 1, 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, "signature data type 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; + + grub_memset (hash, 0x00, GRUB_MAX_HASH_SIZE); + grub_crypto_hash (hash_func, hash, data, data_size); + *hash_size = hash_func->mdlen; + + return GRUB_ERR_NONE; +} + +/* adding the certificate/binary hash into the trusted/distrusted list */ +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)); + } + + 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) +{ + 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) +{ + + 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 + * distrusted list, if it is present, return a bad signature. + * else, no errors. + */ +static grub_err_t +grub_is_distrusted_cert (const struct x509_certificate *db_cert) +{ + 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 && + 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_platform_keystore.dbx[i])); + 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 */ +static grub_err_t +grub_add_certificate (const grub_uint8_t *data, const grub_size_t data_size, + struct grub_database *database, const grub_uint8_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); + + 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) +{ + 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.")); + + 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))) @@ -153,10 +419,7 @@ file_read_all (grub_file_t file, grub_uint8_t **buf, grub_size_t *len) while (total_read_size < file_size) { - read_size = - grub_file_read (file, *buf + total_read_size, - file_size - total_read_size); - + read_size = grub_file_read (file, *buf + total_read_size, file_size - total_read_size); if (read_size < 0) { grub_free (*buf); @@ -267,9 +530,8 @@ grub_verify_appended_signature (const grub_uint8_t *buf, grub_size_t bufsize) struct pkcs7_signerInfo *si; int i; - if (!grub_trusted_key) - return grub_error (GRUB_ERR_BAD_SIGNATURE, - N_("No trusted keys to verify against")); + 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); if (err != GRUB_ERR_NONE) @@ -299,17 +561,16 @@ 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) - { - rc = grub_crypto_rsa_pad (&hashmpi, hash, si->hash, pk->mpis[0]); - if (rc) - { - err = grub_error (GRUB_ERR_BAD_SIGNATURE, - N_("Error padding hash for RSA verification: %d"), - rc); - grub_free (context); - goto cleanup; - } + for (pk = grub_db.keys; pk; pk = pk->next) + { + rc = grub_crypto_rsa_pad (&hashmpi, hash, si->hash, pk->mpis[0]); + if (rc) + { + err = grub_error (GRUB_ERR_BAD_SIGNATURE, + N_("Error padding hash for RSA verification: %d"), rc); + grub_free (context); + goto cleanup; + } rc = _gcry_pubkey_spec_rsa.verify (0, hashmpi, &si->sig_mpi, pk->mpis, NULL, NULL); @@ -402,16 +663,16 @@ grub_cmd_distrust (grub_command_t cmd __attribute__((unused)), 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) @@ -464,8 +725,8 @@ grub_cmd_trust (grub_command_t cmd __attribute__((unused)), 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; } @@ -479,7 +740,7 @@ grub_cmd_list (grub_command_t cmd __attribute__((unused)), 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); @@ -577,6 +838,305 @@ static struct grub_fs pseudo_fs = { .fs_read = pseudo_read }; +/* + * verify the trusted certificate against the certificate hashes from platform keystore buffer's + * distrusted list, if it is present, return a bad signature. + * 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_platform_keystore.dbx[i])); + return GRUB_ERR_BAD_SIGNATURE; + } + } + + return GRUB_ERR_NONE; +} + +/* + * verify the trusted binary hash against the platform keystore buffer's + * distrusted list, if it is present, return a bad signature. + * 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_platform_keystore.dbx[i])); + return GRUB_ERR_BAD_SIGNATURE; + } + } + + return GRUB_ERR_NONE; +} + +/* + * extracts the binary hashes from the platform keystore buffer, + * and adds it to the trusted list if not exists in 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) + 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) +{ + /* 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, + * parses it, and adds 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; + } + else if (grub_is_x509 (&grub_platform_keystore.db[i].guid) == GRUB_ERR_NONE) + { + + 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)) + { + 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, bool mode) +{ + 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)); + 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; + + if (mode) + { + err = grub_is_distrusted_cert_hash (cert_data, cert_data_size); + if (err != GRUB_ERR_NONE) + return err; + } + + err = grub_add_certificate (cert_data, cert_data_size, &grub_db, mode); + if (cert_data != NULL) + grub_free (cert_data); + + 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)); +} + +/* 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)); +} + +static grub_err_t +grub_load_static_keys (struct grub_module_header *header, bool mode) +{ + int rc = GRUB_ERR_NONE; + + FOR_MODULES (header) + { + /* Not an ELF module, skip. */ + if (header->type != OBJ_TYPE_X509_PUBKEY) + continue; + rc = grub_build_static_trusted_list (header, mode); + } + + return rc; +} + static grub_command_t cmd_verify, cmd_list, cmd_distrust, cmd_trust; GRUB_MOD_INIT (appendedsig) @@ -588,10 +1148,7 @@ 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_register_variable_hook ("check_appended_signatures", grub_env_read_sec, grub_env_write_sec); grub_env_export ("check_appended_signatures"); rc = asn1_init (); @@ -599,40 +1156,52 @@ GRUB_MOD_INIT (appendedsig) 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 ELF module, 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); - - grub_dprintf ("appendedsig", "loaded certificate CN='%s'\n", pk->subject); - - pk->next = grub_trusted_key; - grub_trusted_key = pk; - } + if (!grub_use_platform_keystore && check_sigs == check_sigs_forced) + { + rc = grub_load_static_keys (header, 0); + 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) + { + if (grub_platform_keystore.use_static_keys == 1) + { + grub_printf ("Warning: db variable not available and using a static key" + "as a default key in trusted list"); + rc = grub_load_static_keys (header, 1); + } + else + 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); + } + + grub_release_platform_keystore (); + } cmd_trust = grub_register_command ("trust_certificate", grub_cmd_trust, -- 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