diff --git a/SOURCES/0012-initial-mok-variables-code.patch b/SOURCES/0012-initial-mok-variables-code.patch new file mode 100644 index 0000000..39dc09d --- /dev/null +++ b/SOURCES/0012-initial-mok-variables-code.patch @@ -0,0 +1,243 @@ +From 678895d781125544df91432861fadcae8d1c7a80 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Mon, 17 Aug 2020 14:18:31 -0400 +Subject: [PATCH] initial mok-variables code + +This patch adds support for getting mok variables from +/sys/firmware/fi/mok-variables/$NAME , if they are present, as well as +for checking MokListRT, MokListRT1, MokListRT2, etc., for any of the mok +variables. + +Resolves: rhbz#1868820 + +Signed-off-by: Peter Jones +--- + src/mokutil.c | 177 +++++++++++++++++++++++++++++++++++++++++++------- + 1 file changed, 153 insertions(+), 24 deletions(-) + +diff --git a/src/mokutil.c b/src/mokutil.c +index b5080107600..d2fcdc9da0e 100644 +--- a/src/mokutil.c ++++ b/src/mokutil.c +@@ -229,6 +229,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) + { +@@ -596,25 +653,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_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; + } + +- ret = list_keys (data, data_size); +- free (data); +- +- return ret; ++ return 0; + } + + static int +@@ -1013,22 +1089,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); +@@ -1060,11 +1129,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.26.2 + diff --git a/SPECS/mokutil.spec b/SPECS/mokutil.spec index e7db2ed..ecf2265 100644 --- a/SPECS/mokutil.spec +++ b/SPECS/mokutil.spec @@ -1,6 +1,6 @@ Name: mokutil Version: 0.3.0 -Release: 9%{?dist} +Release: 11%{?dist} Epoch: 1 Summary: Tool to manage UEFI Secure Boot MoK Keys License: GPLv3+ @@ -23,6 +23,7 @@ Patch0008: 0008-Fix-typo-in-error-message-when-the-system-lacks-Secu.patch Patch0009: 0009-list_keys_in_var-check-errno-correctly-not-ret-twice.patch Patch0010: 0010-generate_hash-generate_pw_hash-don-t-use-strlen-for-.patch Patch0011: 0011-Fix-a-integer-comparison-sign-issue.patch +Patch0012: 0012-initial-mok-variables-code.patch %description mokutil provides a tool to manage keys for Secure Boot through the MoK @@ -57,6 +58,16 @@ make PREFIX=%{_prefix} LIBDIR=%{_libdir} DESTDIR=%{buildroot} install %{_datadir}/bash-completion/completions/mokutil %changelog +* Tue Jan 05 2021 Javier Martinez Canillas - 0.3.0-11 +- Bump NVR for brew to build the package + Related: rhbz##1907418 + +* Wed Dec 30 2020 Javier Martinez Canillas - 0.3.0-10 +- Add mokutil code to consume data from /sys/firmware/efi/mok-variables/ + as well as attempting to consume numbered mok variables from efivarfs + when mok-variables aren't present (pjones) + Resolves: rhbz#1907418 + * Tue Jul 24 2018 Peter Jones - 0.3.0-9 - Minor obsoletes fix - Import some fixes from upstream