diff --git a/0003-mokutil-Add-option-to-print-the-UEFI-SBAT-variable-c.patch b/0003-mokutil-Add-option-to-print-the-UEFI-SBAT-variable-c.patch new file mode 100644 index 0000000..34f7fbc --- /dev/null +++ b/0003-mokutil-Add-option-to-print-the-UEFI-SBAT-variable-c.patch @@ -0,0 +1,124 @@ +From 698994102afcbbe16e65930a09e0df5248c4d200 Mon Sep 17 00:00:00 2001 +From: Javier Martinez Canillas +Date: Wed, 17 Mar 2021 14:38:57 +0100 +Subject: [PATCH] mokutil: Add option to print the UEFI SBAT variable content + +This variable contains the descriptive form of all the components used by +the operating systems that ship signed shim binaries. Along with a minimum +generation number for each component. More information in can be found in +the UEFI Secure Boot Advanced Targeting (SBAT) specification: + + https://github.com/rhboot/shim/blob/main/SBAT.md + +Since a SBAT variable contains a set of Comma Separated Values (CSV) UTF-8 +encoded strings, the data could just be printed without the need to do any +previous processing. + +Signed-off-by: Javier Martinez Canillas +--- + man/mokutil.1 | 5 +++++ + src/mokutil.c | 33 +++++++++++++++++++++++++++++++++ + 2 files changed, 38 insertions(+) + +diff --git a/man/mokutil.1 b/man/mokutil.1 +index 25fe8b433da..446298763ad 100644 +--- a/man/mokutil.1 ++++ b/man/mokutil.1 +@@ -73,6 +73,8 @@ mokutil \- utility to manipulate machine owner keys + .br + \fBmokutil\fR [--dbx] + .br ++\fBmokutil\fR [--sbat] ++.br + + .SH DESCRIPTION + \fBmokutil\fR is a tool to import or delete the machines owner keys +@@ -173,3 +175,6 @@ List the keys in the secure boot signature store (db) + \fB--dbx\fR + List the keys in the secure boot blacklist signature store (dbx) + .TP ++\fB--sbat\fR ++List the entries in the Secure Boot Advanced Targeting store (SBAT) ++.TP +diff --git a/src/mokutil.c b/src/mokutil.c +index b66c1b8b5a7..0c25ae5033d 100644 +--- a/src/mokutil.c ++++ b/src/mokutil.c +@@ -84,6 +84,7 @@ + #define DELETE_HASH (1 << 22) + #define VERBOSITY (1 << 23) + #define TIMEOUT (1 << 24) ++#define LIST_SBAT (1 << 25) + + #define DEFAULT_CRYPT_METHOD SHA512_BASED + #define DEFAULT_SALT_SIZE SHA512_SALT_MAX +@@ -176,6 +177,7 @@ print_help () + printf (" --db\t\t\t\t\tList the keys in db\n"); + printf (" --dbx\t\t\t\t\tList the keys in dbx\n"); + printf (" --timeout <-1,0..0x7fff>\t\tSet the timeout for MOK prompt\n"); ++ printf (" --sbat\t\t\t\tList the entries in SBAT\n"); + printf ("\n"); + printf ("Supplimentary Options:\n"); + printf (" --hash-file \t\tUse the specific password hash\n"); +@@ -1598,6 +1600,31 @@ error: + return ret; + } + ++static int ++print_var_content (const char *var_name, const efi_guid_t guid) ++{ ++ uint8_t *data = NULL; ++ size_t data_size; ++ uint32_t attributes; ++ int ret; ++ ++ ret = efi_get_variable (guid, var_name, &data, &data_size, &attributes); ++ if (ret < 0) { ++ if (errno == ENOENT) { ++ printf ("%s is empty\n", var_name); ++ return 0; ++ } ++ ++ fprintf (stderr, "Failed to read %s: %m\n", var_name); ++ return -1; ++ } ++ ++ printf ("%s", data); ++ free (data); ++ ++ return ret; ++} ++ + static int + revoke_request (MokRequest req) + { +@@ -2187,6 +2214,7 @@ main (int argc, char *argv[]) + {"kek", no_argument, 0, 0 }, + {"db", no_argument, 0, 0 }, + {"dbx", no_argument, 0, 0 }, ++ {"sbat", no_argument, 0, 0 }, + {"timeout", required_argument, 0, 0 }, + {0, 0, 0, 0} + }; +@@ -2271,6 +2299,8 @@ main (int argc, char *argv[]) + } else { + db_name = DBX; + } ++ } else if (strcmp (option, "sbat") == 0) { ++ command |= LIST_SBAT; + } else if (strcmp (option, "timeout") == 0) { + command |= TIMEOUT; + timeout = strdup (optarg); +@@ -2543,6 +2573,9 @@ main (int argc, char *argv[]) + case TIMEOUT: + ret = set_timeout (timeout); + break; ++ case LIST_SBAT: ++ ret = print_var_content ("SBAT", efi_guid_shim); ++ break; + default: + print_help (); + break; +-- +2.29.2 + diff --git a/0004-mokutil-add-mok-variables-parsing-support.patch b/0004-mokutil-add-mok-variables-parsing-support.patch new file mode 100644 index 0000000..88ea983 --- /dev/null +++ b/0004-mokutil-add-mok-variables-parsing-support.patch @@ -0,0 +1,241 @@ +From 256639accc910e60496fffef96128dc1afd0fa3a Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Wed, 17 Mar 2021 14:49:21 +0100 +Subject: [PATCH] mokutil: add mok-variables parsing support + +his patch adds support for getting mok variables from +/sys/firmware/efi/mok-variables/$NAME , if they are present, as well as +for checking MokListRT, MokListRT1, MokListRT2, etc., for any of the mok +variables. + +Signed-off-by: Peter Jones +--- + src/mokutil.c | 175 +++++++++++++++++++++++++++++++++++++++++++------- + 1 file changed, 151 insertions(+), 24 deletions(-) + +diff --git a/src/mokutil.c b/src/mokutil.c +index 0c25ae5033d..252dc7a327f 100644 +--- a/src/mokutil.c ++++ b/src/mokutil.c +@@ -251,6 +251,63 @@ signature_size (const efi_guid_t *hash_type) + return 0; + } + ++static int ++mok_get_variable(const char *name, uint8_t **datap, size_t *data_sizep) ++{ ++ char filename[] = "/sys/firmware/efi/mok-variables/implausibly-long-mok-variable-name"; ++ size_t filename_sz = sizeof(filename); ++ int fd, rc; ++ struct stat sb = { 0, }; ++ uint8_t *buf; ++ size_t bufsz, pos = 0; ++ ssize_t ssz; ++ ++ *datap = 0; ++ *data_sizep = 0; ++ ++ snprintf(filename, filename_sz, "/sys/firmware/efi/mok-variables/%s", name); ++ ++ fd = open(filename, O_RDONLY); ++ if (fd < 0) ++ return fd; ++ ++ rc = fstat(fd, &sb); ++ if (rc < 0) { ++err_close: ++ close(fd); ++ return rc; ++ } ++ ++ if (sb.st_size == 0) { ++ errno = ENOENT; ++ rc = -1; ++ goto err_close; ++ } ++ ++ bufsz = sb.st_size; ++ buf = calloc(1, bufsz); ++ if (!buf) ++ goto err_close; ++ ++ while (pos < bufsz) { ++ ssz = read(fd, &buf[pos], bufsz - pos); ++ if (ssz < 0) { ++ if (errno == EAGAIN || ++ errno == EWOULDBLOCK || ++ errno == EINTR) ++ continue; ++ free(buf); ++ goto err_close; ++ } ++ ++ pos += ssz; ++ } ++ *datap = buf; ++ *data_sizep = pos; ++ ++ return 0; ++} ++ + static MokListNode* + build_mok_list (void *data, unsigned long data_size, uint32_t *mok_num) + { +@@ -622,25 +679,44 @@ static int + list_keys_in_var (const char *var_name, const efi_guid_t guid) + { + uint8_t *data = NULL; +- size_t data_size; ++ char varname[] = "implausibly-long-mok-variable-name"; ++ size_t data_sz, i, varname_sz = sizeof(varname); + uint32_t attributes; + int ret; + +- ret = efi_get_variable (guid, var_name, &data, &data_size, &attributes); +- if (ret < 0) { +- if (errno == ENOENT) { +- printf ("%s is empty\n", var_name); +- return 0; ++ ret = mok_get_variable(var_name, &data, &data_sz); ++ if (ret >= 0) { ++ ret = list_keys (data, data_sz); ++ free(data); ++ return ret; ++ } ++ ++ for (i = 0; i < SIZE_MAX; i++) { ++ if (i == 0) { ++ snprintf(varname, varname_sz, "%s", var_name); ++ } else { ++ snprintf(varname, varname_sz, "%s%zu", var_name, i); + } + +- fprintf (stderr, "Failed to read %s: %m\n", var_name); +- return -1; +- } ++ ret = efi_get_variable (guid, varname, &data, &data_sz, ++ &attributes); ++ if (ret < 0) ++ return 0; + +- ret = list_keys (data, data_size); +- free (data); ++ ret = list_keys (data, data_sz); ++ free(data); ++ /* ++ * If ret is < 0, the next one will error as well. ++ * If ret is 0, we need to test the next variable. ++ * If it's 1, that's a real answer. ++ */ ++ if (ret < 0) ++ return 0; ++ if (ret > 0) ++ return ret; ++ } + +- return ret; ++ return 0; + } + + static int +@@ -1039,22 +1115,15 @@ is_valid_cert (void *cert, uint32_t cert_size) + } + + static int +-is_duplicate (const efi_guid_t *type, const void *data, const uint32_t data_size, +- const efi_guid_t *vendor, const char *db_name) ++is_one_duplicate (const efi_guid_t *type, ++ const void *data, const uint32_t data_size, ++ uint8_t *var_data, size_t var_data_size) + { +- uint8_t *var_data; +- size_t var_data_size; +- uint32_t attributes; + uint32_t node_num; + MokListNode *list; + int ret = 0; + +- if (!data || data_size == 0 || !db_name) +- return 0; +- +- ret = efi_get_variable (*vendor, db_name, &var_data, &var_data_size, +- &attributes); +- if (ret < 0) ++ if (!data || data_size == 0) + return 0; + + list = build_mok_list (var_data, var_data_size, &node_num); +@@ -1087,11 +1156,69 @@ is_duplicate (const efi_guid_t *type, const void *data, const uint32_t data_size + done: + if (list) + free (list); +- free (var_data); + + return ret; + } + ++static int ++is_duplicate (const efi_guid_t *type, ++ const void *data, const uint32_t data_size, ++ const efi_guid_t *vendor, const char *db_name) ++{ ++ uint32_t attributes; ++ char varname[] = "implausibly-long-mok-variable-name"; ++ size_t varname_sz = sizeof(varname); ++ int ret = 0; ++ size_t i; ++ ++ if (!strncmp(db_name, "Mok", 3)) { ++ uint8_t *var_data = NULL; ++ size_t var_data_size = 0; ++ ret = mok_get_variable(db_name, &var_data, &var_data_size); ++ if (ret >= 0) { ++ ret = is_one_duplicate(type, data, data_size, ++ var_data, var_data_size); ++ if (ret >= 0) { ++ free (var_data); ++ return ret; ++ } ++ var_data = NULL; ++ var_data_size = 0; ++ } ++ } ++ ++ for (i = 0; i < SIZE_MAX; i++) { ++ uint8_t *var_data = NULL; ++ size_t var_data_size = 0; ++ if (i == 0) { ++ snprintf(varname, varname_sz, "%s", db_name); ++ } else { ++ snprintf(varname, varname_sz, "%s%zu", db_name, i); ++ } ++ ++ ret = efi_get_variable (*vendor, varname, ++ &var_data, &var_data_size, ++ &attributes); ++ if (ret < 0) ++ return 0; ++ ++ ret = is_one_duplicate(type, data, data_size, ++ var_data, var_data_size); ++ free (var_data); ++ /* ++ * If ret is < 0, the next one will error as well. ++ * If ret is 0, we need to test the next variable. ++ * If it's 1, that's a real answer. ++ */ ++ if (ret < 0) ++ return 0; ++ if (ret > 0) ++ return ret; ++ } ++ ++ return 0; ++} ++ + static int + is_valid_request (const efi_guid_t *type, void *mok, uint32_t mok_size, + MokRequest req) +-- +2.29.2 + diff --git a/mokutil.spec b/mokutil.spec index 28291b2..e6de976 100644 --- a/mokutil.spec +++ b/mokutil.spec @@ -1,6 +1,6 @@ Name: mokutil Version: 0.4.0 -Release: 3%{?dist} +Release: 4%{?dist} Epoch: 2 Summary: Tool to manage UEFI Secure Boot MoK Keys License: GPLv3+ @@ -16,6 +16,8 @@ Obsoletes: mokutil < 0.2.0 Patch0001: 0001-Avoid-taking-pointer-to-packed-struct.patch Patch0002: 0002-Fix-a-integer-comparison-sign-issue.patch +Patch0003: 0003-mokutil-Add-option-to-print-the-UEFI-SBAT-variable-c.patch +Patch0004: 0004-mokutil-add-mok-variables-parsing-support.patch %description mokutil provides a tool to manage keys for Secure Boot through the MoK @@ -50,6 +52,9 @@ make PREFIX=%{_prefix} LIBDIR=%{_libdir} DESTDIR=%{buildroot} install %{_datadir}/bash-completion/completions/mokutil %changelog +* Wed Mar 17 2021 Javier Martinez Canillas - 0.4.0-4 +- Add SBAT and mok-variables support + * Tue Jan 26 2021 Fedora Release Engineering - 2:0.4.0-3 - Rebuilt for https://fedoraproject.org/wiki/Fedora_34_Mass_Rebuild