diff -Nru mokutil-0.3.0/configure.ac mokutil-0.3.0+1538710437.fb6250f/configure.ac --- mokutil-0.3.0/configure.ac 2014-10-31 09:19:10.000000000 +0000 +++ mokutil-0.3.0+1538710437.fb6250f/configure.ac 2018-10-05 03:33:57.000000000 +0000 @@ -37,7 +37,7 @@ default_strict=no fi -WARNINGFLAGS_C="$WARNINGFLAGS_C -std=gnu11" +WARNINGFLAGS_C="$WARNINGFLAGS_C -std=gnu11 -fshort-wchar" AC_ARG_ENABLE(strict, AS_HELP_STRING([--enable-strict],[Enable strict compilation options]), enable_strict=$enableval, enable_strict=$default_strict) @@ -86,6 +86,23 @@ PKG_CHECK_MODULES(OPENSSL, [openssl >= 0.9.8]) PKG_CHECK_MODULES(EFIVAR, [efivar >= 0.12]) +AC_ARG_WITH([bash-completion-dir], + AS_HELP_STRING([--with-bash-completion-dir[=PATH]], + [Install the bash auto-completion script in this directory. @<:@default=yes@:>@]), + [], + [with_bash_completion_dir=yes]) + +if test "x$with_bash_completion_dir" = "xyes"; then + PKG_CHECK_MODULES([BASH_COMPLETION], [bash-completion >= 2.0], + [BASH_COMPLETION_DIR="`pkg-config --variable=completionsdir bash-completion`"], + [BASH_COMPLETION_DIR="$datadir/bash-completion/completions"]) +else + BASH_COMPLETION_DIR="$with_bash_completion_dir" +fi + +AC_SUBST([BASH_COMPLETION_DIR]) +AM_CONDITIONAL([ENABLE_BASH_COMPLETION],[test "x$with_bash_completion_dir" != "xno"]) + AC_CONFIG_FILES([Makefile src/Makefile man/Makefile]) diff -Nru mokutil-0.3.0/data/mokutil mokutil-0.3.0+1538710437.fb6250f/data/mokutil --- mokutil-0.3.0/data/mokutil 1970-01-01 00:00:00.000000000 +0000 +++ mokutil-0.3.0+1538710437.fb6250f/data/mokutil 2018-10-05 03:33:57.000000000 +0000 @@ -0,0 +1,37 @@ +#!/bin/bash + +_mokutil() +{ + local cur=${COMP_WORDS[COMP_CWORD]} + + if [[ "$cur" == -* ]]; then + #COMPREPLY=( $( compgen -W "--help --list-enrolled --list-new --list-delete --import --delete --revoke-import --revoke-delete --export --password --clear-password --disable-validation --enable-validation --sb-state --test-key --reset --generate-hash --hash-file --root-pw --simple-hash" -- $cur ) ) + COMPREPLY=( $( compgen -W '$( _parse_help "$1" --long-help ) -h -l -N -D -i -d -x -p -c -t -f -g -P -s -X' -- "$cur" ) ) + [[ $COMPREPLY == *= ]] && compopt -o nospace + return 0 + fi + + case "${COMP_WORDS[COMP_CWORD-1]}" in + --import|-i|--delete|-d|--test-key|-t|--hash-file|-f) + _filedir + return 0 + ;; + --import-hash|--delete-hash) + COMPREPLY=( $( compgen -W "" ) ) + return 0 + ;; + --set-verbosity) + COMPREPLY=( $( compgen -W "true false") ) + return 0 + ;; + --generate-hash|-g) + COMPREPLY=( $( compgen -o nospace -P= -W "") ) + return 0 + ;; + *) + return 0 + ;; + esac +} + +complete -F _mokutil mokutil diff -Nru mokutil-0.3.0/debian/changelog mokutil-0.3.0+1538710437.fb6250f/debian/changelog --- mokutil-0.3.0/debian/changelog 2016-04-26 15:00:25.000000000 +0000 +++ mokutil-0.3.0+1538710437.fb6250f/debian/changelog 2018-10-11 18:55:12.000000000 +0000 @@ -1,8 +1,46 @@ -mokutil (0.3.0-0ubuntu3~14.04.1) trusty; urgency=medium +mokutil (0.3.0+1538710437.fb6250f-0ubuntu2~14.04.1) trusty; urgency=medium - * Backport mokutil to trusty. (LP: #1574727) + * Backport mokutil 0.3.0+1538710437.fb6250f-0ubuntu2 to 14.04. + (LP: #1797011) - -- Mathieu Trudel-Lapierre Tue, 26 Apr 2016 10:59:59 -0400 + -- Mathieu Trudel-Lapierre Thu, 11 Oct 2018 14:55:12 -0400 + +mokutil (0.3.0+1538710437.fb6250f-0ubuntu2) cosmic; urgency=medium + + * debian/patches/int-signedness.patch: Fix compile failure on + platforms where int != unsigned int. + + -- Steve Langasek Wed, 10 Oct 2018 22:41:15 -0700 + +mokutil (0.3.0+1538710437.fb6250f-0ubuntu1) cosmic; urgency=medium + + * New upstream snapshot. (LP: #1797011) + - Add support for --export to export arbitrary firmware keyrings. + - Improved output for --sb-state. + - Fix help for --timeout + - Various bugfixes. + + -- Mathieu Trudel-Lapierre Tue, 09 Oct 2018 20:43:25 -0400 + +mokutil (0.3.0+1531796165.cca7219-0ubuntu1) cosmic; urgency=medium + + * New upstream snapshot. + + -- Mathieu Trudel-Lapierre Wed, 29 Aug 2018 16:30:18 -0400 + +mokutil (0.3.0-0ubuntu5) bionic; urgency=high + + * No change rebuild against openssl1.1. + + -- Dimitri John Ledkov Mon, 05 Feb 2018 16:51:07 +0000 + +mokutil (0.3.0-0ubuntu4) zesty; urgency=medium + + * Rebuild against efivar 30-1ubuntu1. + * debian/patches/efivar-30-support.patch: port to efivar 30; where the API + for efi_set_variable() requires a mode to be specified. + + -- Mathieu Trudel-Lapierre Fri, 04 Nov 2016 16:09:31 -0600 mokutil (0.3.0-0ubuntu3) xenial; urgency=medium diff -Nru mokutil-0.3.0/debian/patches/0001-Build-with-fshort-wchar-so-toggle-passwords-work-rig.patch mokutil-0.3.0+1538710437.fb6250f/debian/patches/0001-Build-with-fshort-wchar-so-toggle-passwords-work-rig.patch --- mokutil-0.3.0/debian/patches/0001-Build-with-fshort-wchar-so-toggle-passwords-work-rig.patch 2016-03-25 18:16:27.000000000 +0000 +++ mokutil-0.3.0+1538710437.fb6250f/debian/patches/0001-Build-with-fshort-wchar-so-toggle-passwords-work-rig.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,42 +0,0 @@ -From 9eb111a7f7b897ba4ae19a68708e010a5c384260 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Fri, 19 Jun 2015 16:53:36 -0400 -Subject: [PATCH] Build with -fshort-wchar so toggle passwords work right. - -This source tree uses: - -typedef wchar_t efi_char16_t; - -to define UEFI's UCS-2 character type. On many platforms, wchar_t is -32-bits by default. As a result, efichar_from_char winds up writing -4-byte characters instead of 2-byte characters. In the case where we -hash the password in mokutil, this works fine, because the same datatype -is used, and the values are the same. But for our feature toggles, -where we store the raw data and shim is interpretting the character -array, every other character winds up being L'\0', and verification -fails. - -So always build with -fshort-wchar to ensure we get 2-byte character -storage. - -Signed-off-by: Peter Jones ---- - configure.ac | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/configure.ac b/configure.ac -index fe28fb9..69d412a 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -37,7 +37,7 @@ else - default_strict=no - fi - --WARNINGFLAGS_C="$WARNINGFLAGS_C -std=gnu11" -+WARNINGFLAGS_C="$WARNINGFLAGS_C -std=gnu11 -fshort-wchar" - - AC_ARG_ENABLE(strict, AS_HELP_STRING([--enable-strict],[Enable strict compilation options]), enable_strict=$enableval, - enable_strict=$default_strict) --- -2.7.4 - diff -Nru mokutil-0.3.0/debian/patches/0001-Fix-the-32bit-signedness-comparison.patch mokutil-0.3.0+1538710437.fb6250f/debian/patches/0001-Fix-the-32bit-signedness-comparison.patch --- mokutil-0.3.0/debian/patches/0001-Fix-the-32bit-signedness-comparison.patch 2016-03-23 02:24:08.000000000 +0000 +++ mokutil-0.3.0+1538710437.fb6250f/debian/patches/0001-Fix-the-32bit-signedness-comparison.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,34 +0,0 @@ -From cdb4b6f3bfd6ada6558ddfb889e27150f0841b28 Mon Sep 17 00:00:00 2001 -From: Gary Ching-Pang Lin -Date: Mon, 24 Nov 2014 11:38:54 +0800 -Subject: [PATCH] Fix the 32bit signedness comparison - ---- - src/mokutil.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/src/mokutil.c b/src/mokutil.c -index 93fb6fa..a7e83f7 100644 ---- a/src/mokutil.c -+++ b/src/mokutil.c -@@ -1284,7 +1284,7 @@ issue_mok_request (char **files, uint32_t total, MokRequest req, - - /* Mok */ - read_size = read (fd, ptr, sizes[i]); -- if (read_size < 0 || read_size != sizes[i]) { -+ if (read_size < 0 || read_size != (int64_t)sizes[i]) { - fprintf (stderr, "Failed to read %s\n", files[i]); - goto error; - } -@@ -1645,7 +1645,7 @@ export_moks () - goto error; - } - -- while (offset < list[i].mok_size) { -+ while (offset < (int64_t)list[i].mok_size) { - write_size = write (fd, list[i].mok + offset, - list[i].mok_size - offset); - if (write_size < 0) { --- -1.9.1 - diff -Nru mokutil-0.3.0/debian/patches/0001-Fix-the-potential-buffer-overflow.patch mokutil-0.3.0+1538710437.fb6250f/debian/patches/0001-Fix-the-potential-buffer-overflow.patch --- mokutil-0.3.0/debian/patches/0001-Fix-the-potential-buffer-overflow.patch 2016-03-25 17:45:04.000000000 +0000 +++ mokutil-0.3.0+1538710437.fb6250f/debian/patches/0001-Fix-the-potential-buffer-overflow.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,36 +0,0 @@ -From 1313fa02a5b2bfe61ee6702696600fc148ec2d6e Mon Sep 17 00:00:00 2001 -From: Gary Ching-Pang Lin -Date: Tue, 4 Nov 2014 15:50:03 +0800 -Subject: [PATCH] Fix the potential buffer overflow - -Signed-off-by: Gary Ching-Pang Lin ---- - src/mokutil.c | 5 ++--- - 1 file changed, 2 insertions(+), 3 deletions(-) - -diff --git a/src/mokutil.c b/src/mokutil.c -index 5b34f22..93fb6fa 100644 ---- a/src/mokutil.c -+++ b/src/mokutil.c -@@ -1743,7 +1743,7 @@ set_toggle (const char * VarName, uint32_t state) - MokToggleVar tvar; - char *password = NULL; - unsigned int pw_len; -- efi_char16_t efichar_pass[SB_PASSWORD_MAX]; -+ efi_char16_t efichar_pass[SB_PASSWORD_MAX+1]; - int ret = -1; - - printf ("password length: %d~%d\n", SB_PASSWORD_MIN, SB_PASSWORD_MAX); -@@ -1757,8 +1757,7 @@ set_toggle (const char * VarName, uint32_t state) - efichar_from_char (efichar_pass, password, - SB_PASSWORD_MAX * sizeof(efi_char16_t)); - -- memcpy(tvar.password, efichar_pass, -- SB_PASSWORD_MAX * sizeof(efi_char16_t)); -+ memcpy(tvar.password, efichar_pass, sizeof(tvar.password)); - - tvar.mok_toggle_state = state; - --- -2.7.4 - diff -Nru mokutil-0.3.0/debian/patches/0001-Make-all-efi_guid_t-const.patch mokutil-0.3.0+1538710437.fb6250f/debian/patches/0001-Make-all-efi_guid_t-const.patch --- mokutil-0.3.0/debian/patches/0001-Make-all-efi_guid_t-const.patch 2016-03-25 18:16:31.000000000 +0000 +++ mokutil-0.3.0+1538710437.fb6250f/debian/patches/0001-Make-all-efi_guid_t-const.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,87 +0,0 @@ -From eba569a8e6c33f07042758cbfa1706d7339464e1 Mon Sep 17 00:00:00 2001 -From: Gary Lin -Date: Wed, 13 Jan 2016 16:05:21 +0800 -Subject: [PATCH] Make all efi_guid_t const - -All UEFI GUIDs defined in efivar are const. Declare all of them const -to make gcc happy. - -Signed-off-by: Gary Lin ---- - src/mokutil.c | 18 +++++++++--------- - 1 file changed, 9 insertions(+), 9 deletions(-) - -diff --git a/src/mokutil.c b/src/mokutil.c -index 1fb34f9..d2c52b4 100644 ---- a/src/mokutil.c -+++ b/src/mokutil.c -@@ -200,7 +200,7 @@ efichar_from_char (efi_char16_t *dest, const char *src, size_t dest_len) - } - - static uint32_t --efi_hash_size (efi_guid_t *hash_type) -+efi_hash_size (const efi_guid_t *hash_type) - { - if (efi_guid_cmp (hash_type, &efi_guid_sha1) == 0) { - return SHA_DIGEST_LENGTH; -@@ -218,7 +218,7 @@ efi_hash_size (efi_guid_t *hash_type) - } - - static uint32_t --signature_size (efi_guid_t *hash_type) -+signature_size (const efi_guid_t *hash_type) - { - uint32_t hash_size; - -@@ -439,7 +439,7 @@ list_keys (uint8_t *data, size_t data_size) - - /* match the hash in the hash array and return the index if matched */ - static int --match_hash_array (efi_guid_t *hash_type, const void *hash, -+match_hash_array (const efi_guid_t *hash_type, const void *hash, - const void *hash_array, const uint32_t array_size) - { - uint32_t hash_size, hash_count; -@@ -469,8 +469,8 @@ match_hash_array (efi_guid_t *hash_type, const void *hash, - } - - static int --delete_data_from_list (efi_guid_t *var_guid, const char *var_name, -- efi_guid_t *type, void *data, uint32_t data_size) -+delete_data_from_list (const efi_guid_t *var_guid, const char *var_name, -+ const efi_guid_t *type, void *data, uint32_t data_size) - { - uint8_t *var_data = NULL; - size_t var_data_size = 0; -@@ -1006,8 +1006,8 @@ is_valid_cert (void *cert, uint32_t cert_size) - } - - static int --is_duplicate (efi_guid_t *type, const void *data, const uint32_t data_size, -- efi_guid_t *vendor, const char *db_name) -+is_duplicate (const efi_guid_t *type, const void *data, const uint32_t data_size, -+ const efi_guid_t *vendor, const char *db_name) - { - uint8_t *var_data; - size_t var_data_size; -@@ -1059,7 +1059,7 @@ done: - } - - static int --is_valid_request (efi_guid_t *type, void *mok, uint32_t mok_size, -+is_valid_request (const efi_guid_t *type, void *mok, uint32_t mok_size, - MokRequest req) - { - switch (req) { -@@ -1096,7 +1096,7 @@ is_valid_request (efi_guid_t *type, void *mok, uint32_t mok_size, - } - - static int --in_pending_request (efi_guid_t *type, void *data, uint32_t data_size, -+in_pending_request (const efi_guid_t *type, void *data, uint32_t data_size, - MokRequest req) - { - uint8_t *authvar_data; --- -2.7.4 - diff -Nru mokutil-0.3.0/debian/patches/int-signedness.patch mokutil-0.3.0+1538710437.fb6250f/debian/patches/int-signedness.patch --- mokutil-0.3.0/debian/patches/int-signedness.patch 1970-01-01 00:00:00.000000000 +0000 +++ mokutil-0.3.0+1538710437.fb6250f/debian/patches/int-signedness.patch 2018-10-11 05:38:28.000000000 +0000 @@ -0,0 +1,22 @@ +Description: Fix compile failure on platforms where int != unsigned int + The compiler may rightly warn about a comparison between an unsigned int + and an int on architectures where int is signed by default. Since the + existing code has been tested on architectures where int *is* unsigned, + we just make our other int explicitly unsigned, ignoring certain existing + corner cases for now wrt possible integer underflows. +Author: Steve Langasek +Last-Updated: 2018-10-10 + +Index: mokutil-0.3.0+1538710437.fb6250f/src/mokutil.c +=================================================================== +--- mokutil-0.3.0+1538710437.fb6250f.orig/src/mokutil.c ++++ mokutil-0.3.0+1538710437.fb6250f/src/mokutil.c +@@ -2005,7 +2005,7 @@ + char *password = NULL; + char *crypt_string; + const char *prefix; +- int settings_len = sizeof (settings) - 2; ++ unsigned int settings_len = sizeof (settings) - 2; + unsigned int pw_len, salt_size; + + if (input_pw) { diff -Nru mokutil-0.3.0/debian/patches/series mokutil-0.3.0+1538710437.fb6250f/debian/patches/series --- mokutil-0.3.0/debian/patches/series 2016-03-25 18:17:00.000000000 +0000 +++ mokutil-0.3.0+1538710437.fb6250f/debian/patches/series 2018-10-11 05:30:06.000000000 +0000 @@ -1,4 +1 @@ -0001-Fix-the-32bit-signedness-comparison.patch -0001-Fix-the-potential-buffer-overflow.patch -0001-Build-with-fshort-wchar-so-toggle-passwords-work-rig.patch -0001-Make-all-efi_guid_t-const.patch +int-signedness.patch diff -Nru mokutil-0.3.0/Makefile.am mokutil-0.3.0+1538710437.fb6250f/Makefile.am --- mokutil-0.3.0/Makefile.am 2014-10-31 09:19:10.000000000 +0000 +++ mokutil-0.3.0+1538710437.fb6250f/Makefile.am 2018-10-05 03:33:57.000000000 +0000 @@ -1 +1,6 @@ SUBDIRS = src man + +if ENABLE_BASH_COMPLETION + bashcompletiondir = $(BASH_COMPLETION_DIR) + dist_bashcompletion_DATA = data/mokutil +endif diff -Nru mokutil-0.3.0/src/mokutil.c mokutil-0.3.0+1538710437.fb6250f/src/mokutil.c --- mokutil-0.3.0/src/mokutil.c 2014-10-31 09:19:10.000000000 +0000 +++ mokutil-0.3.0+1538710437.fb6250f/src/mokutil.c 2018-10-05 03:33:57.000000000 +0000 @@ -83,6 +83,7 @@ #define IMPORT_HASH (1 << 21) #define DELETE_HASH (1 << 22) #define VERBOSITY (1 << 23) +#define TIMEOUT (1 << 24) #define DEFAULT_CRYPT_METHOD SHA512_BASED #define DEFAULT_SALT_SIZE SHA512_SALT_MAX @@ -111,6 +112,24 @@ DBX, } DBName; +const char *db_var_name[] = { + [MOK_LIST_RT] = "MokListRT", + [MOK_LIST_X_RT] = "MokListXRT", + [PK] = "PK", + [KEK] = "KEK", + [DB] = "db", + [DBX] = "dbx", +}; + +const char *db_friendly_name[] = { + [MOK_LIST_RT] = "MOK", + [MOK_LIST_X_RT] = "MOKX", + [PK] = "PK", + [KEK] = "KEK", + [DB] = "DB", + [DBX] = "DBX", +}; + typedef struct { EFI_SIGNATURE_LIST *header; uint32_t mok_size; @@ -138,7 +157,7 @@ printf (" --delete \t\tDelete specific keys\n"); printf (" --revoke-import\t\t\tRevoke the import request\n"); printf (" --revoke-delete\t\t\tRevoke the delete request\n"); - printf (" --export\t\t\t\tExport enrolled keys to files\n"); + printf (" --export\t\t\t\tExport keys to files\n"); printf (" --password\t\t\t\tSet MOK password\n"); printf (" --clear-password\t\t\tClear MOK password\n"); printf (" --disable-validation\t\t\tDisable signature validation\n"); @@ -156,6 +175,7 @@ printf (" --kek\t\t\t\t\tList the keys in KEK\n"); 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 ("\n"); printf ("Supplimentary Options:\n"); printf (" --hash-file \t\tUse the specific password hash\n"); @@ -200,7 +220,7 @@ } static uint32_t -efi_hash_size (efi_guid_t *hash_type) +efi_hash_size (const efi_guid_t *hash_type) { if (efi_guid_cmp (hash_type, &efi_guid_sha1) == 0) { return SHA_DIGEST_LENGTH; @@ -218,7 +238,7 @@ } static uint32_t -signature_size (efi_guid_t *hash_type) +signature_size (const efi_guid_t *hash_type) { uint32_t hash_size; @@ -439,7 +459,7 @@ /* match the hash in the hash array and return the index if matched */ static int -match_hash_array (efi_guid_t *hash_type, const void *hash, +match_hash_array (const efi_guid_t *hash_type, const void *hash, const void *hash_array, const uint32_t array_size) { uint32_t hash_size, hash_count; @@ -469,8 +489,8 @@ } static int -delete_data_from_list (efi_guid_t *var_guid, const char *var_name, - efi_guid_t *type, void *data, uint32_t data_size) +delete_data_from_list (const efi_guid_t *var_guid, const char *var_name, + const efi_guid_t *type, void *data, uint32_t data_size) { uint8_t *var_data = NULL; size_t var_data_size = 0; @@ -574,7 +594,8 @@ | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS; ret = efi_set_variable (*var_guid, var_name, - var_data, total, attributes); + var_data, total, attributes, + S_IRUSR | S_IWUSR); if (ret < 0) { fprintf (stderr, "Failed to write variable \"%s\": %m\n", var_name); @@ -601,7 +622,7 @@ ret = efi_get_variable (guid, var_name, &data, &data_size, &attributes); if (ret < 0) { - if (ret == ENOENT) { + if (errno == ENOENT) { printf ("%s is empty\n", var_name); return 0; } @@ -763,9 +784,10 @@ { pw_crypt_t new_crypt; char settings[SETTINGS_LEN]; + char *next; char *crypt_string; const char *prefix; - int hash_len, prefix_len; + int hash_len, settings_len = sizeof (settings) - 2; if (!password || !pw_crypt || password[pw_len] != '\0') return -1; @@ -773,15 +795,19 @@ prefix = get_crypt_prefix (pw_crypt->method); if (!prefix) return -1; - prefix_len = strlen(prefix); pw_crypt->salt_size = get_salt_size (pw_crypt->method); generate_salt ((char *)pw_crypt->salt, pw_crypt->salt_size); - strncpy (settings, prefix, prefix_len); - strncpy (settings + prefix_len, (const char *)pw_crypt->salt, - pw_crypt->salt_size); - settings[pw_crypt->salt_size + prefix_len] = '\0'; + memset (settings, 0, sizeof (settings)); + next = stpncpy (settings, prefix, settings_len); + if (pw_crypt->salt_size > settings_len - (next - settings)) { + errno = EOVERFLOW; + return -1; + } + next = stpncpy (next, (const char *)pw_crypt->salt, + pw_crypt->salt_size); + *next = '\0'; crypt_string = crypt (password, settings); if (!crypt_string) @@ -938,7 +964,8 @@ data_size = list_len; if (efi_set_variable (efi_guid_shim, req_name, - data, data_size, attributes) < 0) { + data, data_size, attributes, + S_IRUSR | S_IWUSR) < 0) { switch (req) { case ENROLL_MOK: fprintf (stderr, "Failed to enroll new keys\n"); @@ -1006,8 +1033,8 @@ } static int -is_duplicate (efi_guid_t *type, const void *data, const uint32_t data_size, - efi_guid_t *vendor, const char *db_name) +is_duplicate (const efi_guid_t *type, const void *data, const uint32_t data_size, + const efi_guid_t *vendor, const char *db_name) { uint8_t *var_data; size_t var_data_size; @@ -1059,7 +1086,7 @@ } static int -is_valid_request (efi_guid_t *type, void *mok, uint32_t mok_size, +is_valid_request (const efi_guid_t *type, void *mok, uint32_t mok_size, MokRequest req) { switch (req) { @@ -1096,7 +1123,7 @@ } static int -in_pending_request (efi_guid_t *type, void *data, uint32_t data_size, +in_pending_request (const efi_guid_t *type, void *data, uint32_t data_size, MokRequest req) { uint8_t *authvar_data; @@ -1284,7 +1311,7 @@ /* Mok */ read_size = read (fd, ptr, sizes[i]); - if (read_size < 0 || read_size != sizes[i]) { + if (read_size < 0 || read_size != (int64_t)sizes[i]) { fprintf (stderr, "Failed to read %s\n", files[i]); goto error; } @@ -1351,10 +1378,12 @@ } switch (len) { +#if 0 case SHA_DIGEST_LENGTH*2: *type = efi_guid_sha1; hash_size = SHA_DIGEST_LENGTH; break; +#endif case SHA224_DIGEST_LENGTH*2: *type = efi_guid_sha224; hash_size = SHA224_DIGEST_LENGTH; @@ -1598,27 +1627,43 @@ } static int -export_moks () +export_db_keys (const DBName db_name) { uint8_t *data = NULL; size_t data_size = 0; uint32_t attributes; char filename[PATH_MAX]; uint32_t mok_num; + efi_guid_t guid = efi_guid_shim; MokListNode *list; int fd; mode_t mode; int ret = -1; - ret = efi_get_variable (efi_guid_shim, "MokListRT", &data, &data_size, + switch (db_name) { + case MOK_LIST_RT: + case MOK_LIST_X_RT: + guid = efi_guid_shim; + break; + case PK: + case KEK: + guid = efi_guid_global; + break; + case DB: + case DBX: + guid = efi_guid_security; + break; + }; + + ret = efi_get_variable (guid, db_var_name[db_name], &data, &data_size, &attributes); if (ret < 0) { if (errno == ENOENT) { - printf ("MokListRT is empty\n"); + printf ("%s is empty\n", db_var_name[db_name]); return 0; } - fprintf (stderr, "Failed to read MokListRT: %m\n"); + fprintf (stderr, "Failed to read %s: %m\n", db_var_name[db_name]); return -1; } ret = -1; @@ -1638,14 +1683,14 @@ continue; /* Dump X509 certificate to files */ - snprintf (filename, PATH_MAX, "MOK-%04d.der", i+1); + snprintf (filename, PATH_MAX, "%s-%04d.der", db_friendly_name[db_name], i+1); fd = open (filename, O_CREAT | O_WRONLY, mode); if (fd < 0) { fprintf (stderr, "Failed to open %s: %m\n", filename); goto error; } - while (offset < list[i].mok_size) { + while (offset < (int64_t)list[i].mok_size) { write_size = write (fd, list[i].mok + offset, list[i].mok_size - offset); if (write_size < 0) { @@ -1743,7 +1788,7 @@ MokToggleVar tvar; char *password = NULL; unsigned int pw_len; - efi_char16_t efichar_pass[SB_PASSWORD_MAX]; + efi_char16_t efichar_pass[SB_PASSWORD_MAX+1]; int ret = -1; printf ("password length: %d~%d\n", SB_PASSWORD_MIN, SB_PASSWORD_MAX); @@ -1757,8 +1802,7 @@ efichar_from_char (efichar_pass, password, SB_PASSWORD_MAX * sizeof(efi_char16_t)); - memcpy(tvar.password, efichar_pass, - SB_PASSWORD_MAX * sizeof(efi_char16_t)); + memcpy(tvar.password, efichar_pass, sizeof(tvar.password)); tvar.mok_toggle_state = state; @@ -1797,7 +1841,9 @@ uint8_t *data; size_t data_size; uint32_t attributes; - int32_t state = -1; + int32_t secureboot = -1; + int32_t setupmode = -1; + int32_t moksbstate = -1; if (efi_get_variable (efi_guid_global, "SecureBoot", &data, &data_size, &attributes) < 0) { @@ -1811,16 +1857,45 @@ data_size); } if (data_size == 4) { - state = (int32_t)*(uint32_t *)data; + secureboot = (int32_t)*(uint32_t *)data; } else if (data_size == 2) { - state = (int32_t)*(uint16_t *)data; + secureboot = (int32_t)*(uint16_t *)data; } else if (data_size == 1) { - state = (int32_t)*(uint8_t *)data; + secureboot = (int32_t)*(uint8_t *)data; + } + + if (efi_get_variable (efi_guid_global, "SetupMode", &data, &data_size, + &attributes) < 0) { + fprintf (stderr, "Failed to read \"SecureBoot\" " + "variable: %m\n"); + return -1; } - if (state == 1) { + + if (data_size != 1) { + printf ("Strange data size %zd for \"SetupMode\" variable\n", + data_size); + } + if (data_size == 4) { + setupmode = (int32_t)*(uint32_t *)data; + } else if (data_size == 2) { + setupmode = (int32_t)*(uint16_t *)data; + } else if (data_size == 1) { + setupmode = (int32_t)*(uint8_t *)data; + } + + if (efi_get_variable (efi_guid_shim, "MokSBStateRT", &data, &data_size, + &attributes) >= 0) { + moksbstate = 1; + } + + if (secureboot == 1 && setupmode == 0) { printf ("SecureBoot enabled\n"); - } else if (state == 0) { + if (moksbstate == 1) + printf ("SecureBoot validation is disabled in shim\n"); + } else if (secureboot == 0 || setupmode == 1) { printf ("SecureBoot disabled\n"); + if (setupmode == 1) + printf ("Platform is in Setup Mode\n"); } else { printf ("Cannot determine secure boot state.\n"); } @@ -1926,10 +2001,11 @@ generate_pw_hash (const char *input_pw) { char settings[SETTINGS_LEN]; + char *next; char *password = NULL; char *crypt_string; const char *prefix; - int prefix_len; + int settings_len = sizeof (settings) - 2; unsigned int pw_len, salt_size; if (input_pw) { @@ -1955,12 +2031,18 @@ prefix = get_crypt_prefix (DEFAULT_CRYPT_METHOD); if (!prefix) return -1; - prefix_len = strlen(prefix); - strncpy (settings, prefix, prefix_len); + memset (settings, 0, sizeof (settings)); + next = stpncpy (settings, prefix, settings_len); salt_size = get_salt_size (DEFAULT_CRYPT_METHOD); - generate_salt ((settings + prefix_len), salt_size); - settings[DEFAULT_SALT_SIZE + prefix_len] = '\0'; + if (salt_size > settings_len - (next - settings)) { + free(password); + errno = EOVERFLOW; + return -1; + } + generate_salt (next, salt_size); + next += salt_size; + *next = '\0'; crypt_string = crypt (password, settings); free (password); @@ -1975,6 +2057,33 @@ } static int +set_timeout (char *t) +{ + int timeout = strtol(t, NULL, 10); + + if (errno == ERANGE || timeout > 0x7fff) + timeout = 0x7fff; + if (timeout < 0) + timeout = -1; + + if (timeout != 10) { + uint32_t attributes = EFI_VARIABLE_NON_VOLATILE + | EFI_VARIABLE_BOOTSERVICE_ACCESS + | EFI_VARIABLE_RUNTIME_ACCESS; + if (efi_set_variable (efi_guid_shim, "MokTimeout", + (uint8_t *)&timeout, sizeof (timeout), + attributes, S_IRUSR | S_IWUSR) < 0) { + fprintf (stderr, "Failed to set MokTimeout\n"); + return -1; + } + } else { + return test_and_delete_var ("MokTimeout"); + } + + return 0; +} + +static int set_verbosity (uint8_t verbosity) { if (verbosity) { @@ -2023,6 +2132,7 @@ char *hash_file = NULL; char *input_pw = NULL; char *hash_str = NULL; + char *timeout = NULL; const char *option; int c, i, f_ind, total = 0; unsigned int command = 0; @@ -2062,6 +2172,7 @@ {"simple-hash", no_argument, 0, 's'}, {"ignore-db", no_argument, 0, 0 }, {"use-db", no_argument, 0, 0 }, + {"mok", no_argument, 0, 'm'}, {"mokx", no_argument, 0, 'X'}, {"import-hash", required_argument, 0, 0 }, {"delete-hash", required_argument, 0, 0 }, @@ -2070,11 +2181,12 @@ {"kek", no_argument, 0, 0 }, {"db", no_argument, 0, 0 }, {"dbx", no_argument, 0, 0 }, + {"timeout", required_argument, 0, 0 }, {0, 0, 0, 0} }; int option_index = 0; - c = getopt_long (argc, argv, "cd:f:g::hi:lpst:xDNPX", + c = getopt_long (argc, argv, "cd:f:g::hi:lmpst:xDNPX", long_options, &option_index); if (c == -1) @@ -2133,30 +2245,29 @@ if (db_name != MOK_LIST_RT) { command |= HELP; } else { - command |= LIST_ENROLLED; db_name = PK; } } else if (strcmp (option, "kek") == 0) { if (db_name != MOK_LIST_RT) { command |= HELP; } else { - command |= LIST_ENROLLED; db_name = KEK; } } else if (strcmp (option, "db") == 0) { if (db_name != MOK_LIST_RT) { command |= HELP; } else { - command |= LIST_ENROLLED; db_name = DB; } } else if (strcmp (option, "dbx") == 0) { if (db_name != MOK_LIST_RT) { command |= HELP; } else { - command |= LIST_ENROLLED; db_name = DBX; } + } else if (strcmp (option, "timeout") == 0) { + command |= TIMEOUT; + timeout = strdup (optarg); } break; @@ -2261,6 +2372,9 @@ command |= SIMPLE_HASH; use_simple_hash = 1; break; + case 'm': + db_name = MOK_LIST_RT; + break; case 'X': if (db_name != MOK_LIST_RT) { command |= HELP; @@ -2284,6 +2398,9 @@ if (hash_file && use_root_pw) command |= HELP; + if (db_name != MOK_LIST_RT && !(command & ~MOKX)) + command |= LIST_ENROLLED; + if (!(command & HELP)) { /* Check whether the machine supports Secure Boot or not */ int rc; @@ -2294,7 +2411,7 @@ rc = efi_get_variable (efi_guid_global, "SecureBoot", &data, &data_size, &attributes); if (rc < 0) { - fprintf(stderr, "This system does't support Secure Boot\n"); + fprintf(stderr, "This system doesn't support Secure Boot\n"); ret = -1; goto out; } @@ -2339,7 +2456,8 @@ ret = revoke_request (DELETE_MOK); break; case EXPORT: - ret = export_moks (); + case EXPORT | MOKX: + ret = export_db_keys (db_name); break; case PASSWORD: case PASSWORD | SIMPLE_HASH: @@ -2416,6 +2534,9 @@ case VERBOSITY: ret = set_verbosity (verbosity); break; + case TIMEOUT: + ret = set_timeout (timeout); + break; default: print_help (); break; @@ -2428,6 +2549,9 @@ free (files); } + if (timeout) + free (timeout); + if (key_file) free (key_file); diff -Nru mokutil-0.3.0/TODO mokutil-0.3.0+1538710437.fb6250f/TODO --- mokutil-0.3.0/TODO 2014-10-31 09:19:10.000000000 +0000 +++ mokutil-0.3.0+1538710437.fb6250f/TODO 2018-10-05 03:33:57.000000000 +0000 @@ -1,2 +1,6 @@ -* Show the detail of the DER file when enrolling (?) -* Add an option to slience the output (?) +* Show the detail of the DER file when enrolling +* Add an option to slience the output +* Reorganize help +* Add an option to dump/list keys from a given file +* Support more db: dbr, dbt, dbDefault, dbrDefault, dbtDefault, dbxDefault, + PKDefault, KEKDefault