From 7363fb09df4d68d13facf2805f44d0176f6288644d42e135e7daa784d21d8497 Mon Sep 17 00:00:00 2001 From: Gary Ching-Pang Lin Date: Wed, 16 Jan 2013 09:28:17 +0000 Subject: [PATCH] Accepting request 148683 from home:gary_lin:branches:Base:System - Merge patches for FATE#314506 + Add mokutil-support-delete-keys.patch to delete specific keys + Add mokutil-support-new-pw-hash.patch to support the new password format + Add mokutil-allow-password-from-pipe.patch to allow the password to be generated in a script and be sent through pipeline - Install COPYING OBS-URL: https://build.opensuse.org/request/show/148683 OBS-URL: https://build.opensuse.org/package/show/Base:System/mokutil?expand=0&rev=2 --- mokutil-allow-password-from-pipe.patch | 50 + mokutil-support-delete-keys.patch | 835 +++++++++++++++ mokutil-support-new-pw-hash.patch | 1342 ++++++++++++++++++++++++ mokutil.changes | 12 + mokutil.spec | 21 +- 5 files changed, 2254 insertions(+), 6 deletions(-) create mode 100644 mokutil-allow-password-from-pipe.patch create mode 100644 mokutil-support-delete-keys.patch create mode 100644 mokutil-support-new-pw-hash.patch diff --git a/mokutil-allow-password-from-pipe.patch b/mokutil-allow-password-from-pipe.patch new file mode 100644 index 0000000..9c8d986 --- /dev/null +++ b/mokutil-allow-password-from-pipe.patch @@ -0,0 +1,50 @@ +commit adce7208ddcb65daac83ea3429aa8586d9cc4ea5 +Author: Gary Ching-Pang Lin +Date: Wed Jan 2 17:30:07 2013 +0800 + + Only change terminal settings + + tcgetattr() will fail if we send password through a pipeline instead + of a TTY. + +diff --git a/src/mokutil.c b/src/mokutil.c +index a99e355..ea8481a 100644 +--- a/src/mokutil.c ++++ b/src/mokutil.c +@@ -278,22 +278,27 @@ read_hidden_line (char **line, size_t *n) + { + struct termios old, new; + int nread; ++ int isTTY = isatty(fileno (stdin)); + +- /* Turn echoing off and fail if we can't. */ +- if (tcgetattr (fileno (stdin), &old) != 0) +- return -1; ++ if (isTTY) { ++ /* Turn echoing off and fail if we can't. */ ++ if (tcgetattr (fileno (stdin), &old) != 0) ++ return -1; + +- new = old; +- new.c_lflag &= ~ECHO; ++ new = old; ++ new.c_lflag &= ~ECHO; + +- if (tcsetattr (fileno (stdin), TCSAFLUSH, &new) != 0) +- return -1; ++ if (tcsetattr (fileno (stdin), TCSAFLUSH, &new) != 0) ++ return -1; ++ } + + /* Read the password. */ + nread = getline (line, n, stdin); + +- /* Restore terminal. */ +- (void) tcsetattr (fileno (stdin), TCSAFLUSH, &old); ++ if (isTTY) { ++ /* Restore terminal. */ ++ (void) tcsetattr (fileno (stdin), TCSAFLUSH, &old); ++ } + + /* Remove the newline */ + (*line)[nread-1] = '\0'; diff --git a/mokutil-support-delete-keys.patch b/mokutil-support-delete-keys.patch new file mode 100644 index 0000000..20d03c4 --- /dev/null +++ b/mokutil-support-delete-keys.patch @@ -0,0 +1,835 @@ +From 36241509b1c96c3103becae75dc6df72d794cce7 Mon Sep 17 00:00:00 2001 +From: Gary Ching-Pang Lin +Date: Thu, 13 Dec 2012 17:09:34 +0800 +Subject: [PATCH 1/7] Move fail check to get_password() + +--- + src/mokutil.c | 83 ++++++++++++++++++++++++++++++++------------------------- + 1 file changed, 46 insertions(+), 37 deletions(-) + +diff --git a/src/mokutil.c b/src/mokutil.c +index aba1cfb..eea2b6c 100644 +--- a/src/mokutil.c ++++ b/src/mokutil.c +@@ -297,39 +297,60 @@ static int + get_password (char **password, int *len, int min, int max) + { + char *password_1, *password_2; +- int len_1, len_2; ++ int len_1, len_2, fail, ret = -1; + size_t n; + + password_1 = password_2 = NULL; + +- printf ("input password (%d~%d characters): ", min, max); +- len_1 = read_hidden_line (&password_1, &n); +- printf ("\n"); ++ fail = 0; + +- if (len_1 > max || len_1 < min) { +- free (password_1); +- fprintf (stderr, "password should be %d~%d characters\n", +- min, max); +- return -1; ++ while (fail < 3) { ++ printf ("input password (%d~%d characters): ", min, max); ++ len_1 = read_hidden_line (&password_1, &n); ++ printf ("\n"); ++ ++ if (len_1 > max || len_1 < min) { ++ fail++; ++ fprintf (stderr, "password should be %d~%d characters\n", ++ min, max); ++ } else { ++ break; ++ } + } + +- printf ("input password again: "); +- len_2 = read_hidden_line (&password_2, &n); +- printf ("\n"); ++ if (fail >= 3) { ++ if (password_1) ++ free (password_1); ++ goto error; ++ } + +- if (len_1 != len_2 || strcmp (password_1, password_2) != 0) { +- free (password_1); +- free (password_2); +- fprintf (stderr, "password doesn't match\n"); +- return -1; ++ fail = 0; ++ ++ while (fail < 3) { ++ printf ("input password again: "); ++ len_2 = read_hidden_line (&password_2, &n); ++ printf ("\n"); ++ ++ if (len_1 != len_2 || strcmp (password_1, password_2) != 0) { ++ fail++; ++ fprintf (stderr, "password doesn't match\n"); ++ } else { ++ break; ++ } + } + ++ if (fail >= 3) ++ goto error; ++ + *password = password_1; + *len = len_1; + +- free (password_2); ++ ret = 0; ++error: ++ if (password_2) ++ free (password_2); + +- return 0; ++ return ret; + } + + static int +@@ -364,14 +385,10 @@ update_request (void *new_list, int list_len) + efi_variable_t var; + uint8_t auth[SHA256_DIGEST_LENGTH]; + char *password = NULL; +- int pw_len, fail = 0; ++ int pw_len; + int ret = -1; + +- while (fail < 3 && +- get_password (&password, &pw_len, PASSWORD_MIN, PASSWORD_MAX) < 0) +- fail++; +- +- if (fail >= 3) { ++ if (get_password (&password, &pw_len, PASSWORD_MIN, PASSWORD_MAX) < 0) { + fprintf (stderr, "Abort\n"); + goto error; + } +@@ -745,14 +762,10 @@ set_password () + efi_variable_t var; + uint8_t auth[SHA256_DIGEST_LENGTH]; + char *password = NULL; +- int pw_len, fail = 0; ++ int pw_len; + int ret = -1; + +- while (fail < 3 && +- get_password (&password, &pw_len, PASSWORD_MIN, PASSWORD_MAX) < 0) +- fail++; +- +- if (fail >= 3) { ++ while (get_password (&password, &pw_len, PASSWORD_MIN, PASSWORD_MAX) < 0) { + fprintf (stderr, "Abort\n"); + goto error; + } +@@ -789,15 +802,11 @@ set_validation (uint32_t state) + efi_variable_t var; + MokSBVar sbvar; + char *password = NULL; +- int pw_len, fail = 0; ++ int pw_len; + efi_char16_t efichar_pass[PASSWORD_MAX]; + int ret = -1; + +- while (fail < 3 && +- get_password (&password, &pw_len, PASSWORD_MIN, PASSWORD_MAX) < 0) +- fail++; +- +- if (fail >= 3) { ++ while (get_password (&password, &pw_len, PASSWORD_MIN, PASSWORD_MAX) < 0) { + fprintf (stderr, "Abort\n"); + goto error; + } +-- +1.7.10.4 + + +From 2649dde769b563f55a85ea68eb1fc9ce5bc7c984 Mon Sep 17 00:00:00 2001 +From: Gary Ching-Pang Lin +Date: Mon, 17 Dec 2012 16:22:41 +0800 +Subject: [PATCH 2/7] Add "--test-key" to test if the key is enrolled or not + +--- + src/mokutil.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 65 insertions(+) + +diff --git a/src/mokutil.c b/src/mokutil.c +index eea2b6c..68a25bc 100644 +--- a/src/mokutil.c ++++ b/src/mokutil.c +@@ -41,6 +41,7 @@ enum Command { + COMMAND_DISABLE_VALIDATION, + COMMAND_ENABLE_VALIDATION, + COMMAND_SB_STATE, ++ COMMAND_TEST_KEY, + }; + + static void +@@ -76,6 +77,9 @@ print_help () + + printf("SecureBoot State:\n"); + printf(" mokutil --sb-state\n\n"); ++ ++ printf("Test if the key is enrolled or not:\n"); ++ printf(" mokutil --test-key\n\n"); + } + + static int +@@ -882,10 +886,57 @@ sb_state () + return 0; + } + ++static int ++test_key (const char *key_file) ++{ ++ struct stat buf; ++ void *key = NULL; ++ ssize_t read_size; ++ int fd, ret = -1; ++ ++ if (stat (key_file, &buf) != 0) { ++ fprintf (stderr, "Failed to get file status, %s\n", key_file); ++ return -1; ++ } ++ ++ key = malloc (buf.st_size); ++ ++ fd = open (key_file, O_RDONLY); ++ if (fd < 0) { ++ fprintf (stderr, "Failed to open %s\n", key_file); ++ goto error; ++ } ++ ++ read_size = read (fd, key, buf.st_size); ++ if (read_size < 0 || read_size != buf.st_size) { ++ fprintf (stderr, "Failed to read %s\n", key_file); ++ goto error; ++ } ++ ++ if (!is_duplicate (key, read_size, "PK", EFI_GLOBAL_VARIABLE) && ++ !is_duplicate (key, read_size, "KEK", EFI_GLOBAL_VARIABLE) && ++ !is_duplicate (key, read_size, "db", EFI_GLOBAL_VARIABLE) && ++ !is_duplicate (key, read_size, "MokListRT", SHIM_LOCK_GUID) && ++ !is_duplicate (key, read_size, "MokNew", SHIM_LOCK_GUID)) { ++ printf ("%s is not enrolled\n", key_file); ++ ret = 0; ++ } else { ++ printf ("%s is already enrolled\n", key_file); ++ ret = 1; ++ } ++ ++error: ++ if (key) ++ free (key); ++ ++ return ret; ++} ++ + int + main (int argc, char *argv[]) + { + char **files = NULL; ++ char *key_file = NULL; + int i, total; + int command; + +@@ -962,6 +1013,17 @@ main (int argc, char *argv[]) + + command = COMMAND_SB_STATE; + ++ } else if (strcmp (argv[1], "--test-key") == 0) { ++ ++ if (argc < 3) { ++ print_help (); ++ return -1; ++ } ++ ++ key_file = argv[2]; ++ ++ command = COMMAND_TEST_KEY; ++ + } else { + fprintf (stderr, "Unknown argument: %s\n\n", argv[1]); + print_help (); +@@ -999,6 +1061,9 @@ main (int argc, char *argv[]) + case COMMAND_SB_STATE: + sb_state (); + break; ++ case COMMAND_TEST_KEY: ++ test_key (key_file); ++ break; + default: + fprintf (stderr, "Unknown command\n"); + break; +-- +1.7.10.4 + + +From bba82fceec875ccf0d92eae1e9c7db54e92bcec9 Mon Sep 17 00:00:00 2001 +From: Gary Ching-Pang Lin +Date: Mon, 17 Dec 2012 16:33:59 +0800 +Subject: [PATCH 3/7] Handle the return values + +--- + src/mokutil.c | 25 +++++++++++++------------ + 1 file changed, 13 insertions(+), 12 deletions(-) + +diff --git a/src/mokutil.c b/src/mokutil.c +index 68a25bc..13ef69d 100644 +--- a/src/mokutil.c ++++ b/src/mokutil.c +@@ -939,6 +939,7 @@ main (int argc, char *argv[]) + char *key_file = NULL; + int i, total; + int command; ++ int ret = -1; + + if (argc < 2) { + print_help (); +@@ -1032,37 +1033,37 @@ main (int argc, char *argv[]) + + switch (command) { + case COMMAND_LIST_ENROLLED: +- list_enrolled_keys (); ++ ret = list_enrolled_keys (); + break; + case COMMAND_LIST_NEW: +- list_new_keys (); ++ ret = list_new_keys (); + break; + case COMMAND_IMPORT: +- import_moks (files, total); ++ ret = import_moks (files, total); + break; + case COMMAND_DELETE: +- delete_all (); ++ ret = delete_all (); + break; + case COMMAND_REVOKE: +- revoke_request (); ++ ret = revoke_request (); + break; + case COMMAND_EXPORT: +- export_moks (); ++ ret = export_moks (); + break; + case COMMAND_PASSWORD: +- set_password (); ++ ret = set_password (); + break; + case COMMAND_DISABLE_VALIDATION: +- disable_validation (); ++ ret = disable_validation (); + break; + case COMMAND_ENABLE_VALIDATION: +- enable_validation (); ++ ret = enable_validation (); + break; + case COMMAND_SB_STATE: +- sb_state (); ++ ret = sb_state (); + break; + case COMMAND_TEST_KEY: +- test_key (key_file); ++ ret = test_key (key_file); + break; + default: + fprintf (stderr, "Unknown command\n"); +@@ -1072,5 +1073,5 @@ main (int argc, char *argv[]) + if (files) + free (files); + +- return 0; ++ return ret; + } +-- +1.7.10.4 + + +From fee5db0bd74fd7239832d435cdc653ade426c61c Mon Sep 17 00:00:00 2001 +From: Gary Ching-Pang Lin +Date: Mon, 24 Dec 2012 16:35:37 +0800 +Subject: [PATCH 4/7] Correct the GUID of "db" + +--- + src/efi.h | 2 ++ + src/mokutil.c | 2 +- + 2 files changed, 3 insertions(+), 1 deletion(-) + +diff --git a/src/efi.h b/src/efi.h +index 7185179..d2640b4 100644 +--- a/src/efi.h ++++ b/src/efi.h +@@ -86,6 +86,8 @@ EFI_GUID( 0x47c7b225, 0xc42a, 0x11d2, 0x8e, 0x57, 0x00, 0xa0, 0xc9, 0x69, 0x72, + EFI_GUID( 0x47c7b227, 0xc42a, 0x11d2, 0x8e, 0x57, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b) + #define ESP_UNKNOWN_GUID \ + EFI_GUID( 0x47c7b226, 0xc42a, 0x11d2, 0x8e, 0x57, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b) ++#define EFI_IMAGE_SECURITY_DATABASE_GUID \ ++EFI_GUID( 0xd719b2cb, 0x3d3a, 0x4596, 0xa3, 0xbc, 0xda, 0xd0, 0x0e, 0x67, 0x65, 0x6f) + + static inline int + efi_guidcmp(efi_guid_t left, efi_guid_t right) +diff --git a/src/mokutil.c b/src/mokutil.c +index 13ef69d..6af5a9c 100644 +--- a/src/mokutil.c ++++ b/src/mokutil.c +@@ -636,7 +636,7 @@ import_moks (char **files, uint32_t total) + /* whether this key is already enrolled... */ + if (!is_duplicate (ptr, sizes[i], "PK", EFI_GLOBAL_VARIABLE) && + !is_duplicate (ptr, sizes[i], "KEK", EFI_GLOBAL_VARIABLE) && +- !is_duplicate (ptr, sizes[i], "db", EFI_GLOBAL_VARIABLE) && ++ !is_duplicate (ptr, sizes[i], "db", EFI_IMAGE_SECURITY_DATABASE_GUID) && + !is_duplicate (ptr, sizes[i], "MokListRT", SHIM_LOCK_GUID) && + !is_duplicate (ptr, sizes[i], "MokNew", SHIM_LOCK_GUID)) { + ptr += sizes[i]; +-- +1.7.10.4 + + +From b1a6476307909b4c391b5cc632c0535ea43b08b1 Mon Sep 17 00:00:00 2001 +From: Gary Ching-Pang Lin +Date: Mon, 24 Dec 2012 18:12:48 +0800 +Subject: [PATCH 5/7] Initialize password array + +--- + src/mokutil.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/mokutil.c b/src/mokutil.c +index 6af5a9c..3d00df0 100644 +--- a/src/mokutil.c ++++ b/src/mokutil.c +@@ -509,7 +509,7 @@ verify_mok_new (void *mok_new, unsigned long mok_new_size) + { + efi_variable_t mok_auth; + uint8_t auth[SHA256_DIGEST_LENGTH]; +- char *password; ++ char *password = NULL; + int pw_len, fail = 0; + size_t n; + int ret = 0; +-- +1.7.10.4 + + +From e772f72f23b4cf13c033292b55570a861281b71b Mon Sep 17 00:00:00 2001 +From: Gary Ching-Pang Lin +Date: Tue, 25 Dec 2012 15:53:56 +0800 +Subject: [PATCH 6/7] Add support for deleting specific keys + +--- + src/mokutil.c | 179 +++++++++++++++++++++++++++++++++++++++++---------------- + 1 file changed, 128 insertions(+), 51 deletions(-) + +diff --git a/src/mokutil.c b/src/mokutil.c +index 3d00df0..e6807da 100644 +--- a/src/mokutil.c ++++ b/src/mokutil.c +@@ -42,6 +42,7 @@ enum Command { + COMMAND_ENABLE_VALIDATION, + COMMAND_SB_STATE, + COMMAND_TEST_KEY, ++ COMMAND_RESET, + }; + + static void +@@ -57,8 +58,8 @@ print_help () + printf("Import keys:\n"); + printf(" mokutil --import ...\n\n"); + +- printf("Request to delete all keys\n"); +- printf(" mokutil --delete-all\n\n"); ++ printf("Request to delete specific keys\n"); ++ printf(" mokutil --delete ...\n\n"); + + printf("Revoke the request:\n"); + printf(" mokutil --revoke\n\n"); +@@ -80,6 +81,9 @@ print_help () + + printf("Test if the key is enrolled or not:\n"); + printf(" mokutil --test-key\n\n"); ++ ++ printf("Reset MOK list:\n"); ++ printf(" mokutil --reset\n\n"); + } + + static int +@@ -384,14 +388,23 @@ generate_auth (void *new_list, unsigned long list_len, char *password, + } + + static int +-update_request (void *new_list, int list_len) ++update_request (void *new_list, int list_len, uint8_t import) + { + efi_variable_t var; ++ const char *req_name, *auth_name; + uint8_t auth[SHA256_DIGEST_LENGTH]; + char *password = NULL; + int pw_len; + int ret = -1; + ++ if (import) { ++ req_name = "MokNew"; ++ auth_name = "MokAuth"; ++ } else { ++ req_name = "MokDel"; ++ auth_name = "MokDelAuth"; ++ } ++ + if (get_password (&password, &pw_len, PASSWORD_MIN, PASSWORD_MAX) < 0) { + fprintf (stderr, "Abort\n"); + goto error; +@@ -403,7 +416,7 @@ update_request (void *new_list, int list_len) + /* Write MokNew*/ + var.Data = new_list; + var.DataSize = list_len; +- var.VariableName = "MokNew"; ++ var.VariableName = req_name; + + var.VendorGuid = SHIM_LOCK_GUID; + var.Attributes = EFI_VARIABLE_NON_VOLATILE +@@ -411,17 +424,18 @@ update_request (void *new_list, int list_len) + | EFI_VARIABLE_RUNTIME_ACCESS; + + if (edit_variable (&var) != EFI_SUCCESS) { +- fprintf (stderr, "Failed to enroll new keys\n"); ++ fprintf (stderr, "Failed to %s keys\n", ++ import ? "enroll new" : "delete"); + goto error; + } + } else { +- test_and_delete_var ("MokNew"); ++ test_and_delete_var (req_name); + } + + /* Write MokAuth */ + var.Data = auth; + var.DataSize = SHA256_DIGEST_LENGTH; +- var.VariableName = "MokAuth"; ++ var.VariableName = auth_name; + + var.VendorGuid = SHIM_LOCK_GUID; + var.Attributes = EFI_VARIABLE_NON_VOLATILE +@@ -429,8 +443,8 @@ update_request (void *new_list, int list_len) + | EFI_VARIABLE_RUNTIME_ACCESS; + + if (edit_variable (&var) != EFI_SUCCESS) { +- fprintf (stderr, "Failed to write MokAuth\n"); +- test_and_delete_var ("MokNew"); ++ fprintf (stderr, "Failed to write %s\n", auth_name); ++ test_and_delete_var (req_name); + goto error; + } + +@@ -505,20 +519,47 @@ done: + } + + static int +-verify_mok_new (void *mok_new, unsigned long mok_new_size) ++is_valid_request (void *mok, uint32_t mok_size, uint8_t import) + { +- efi_variable_t mok_auth; ++ if (import) { ++ if (is_duplicate (mok, mok_size, "PK", EFI_GLOBAL_VARIABLE) || ++ is_duplicate (mok, mok_size, "KEK", EFI_GLOBAL_VARIABLE) || ++ is_duplicate (mok, mok_size, "db", EFI_IMAGE_SECURITY_DATABASE_GUID) || ++ is_duplicate (mok, mok_size, "MokListRT", SHIM_LOCK_GUID) || ++ is_duplicate (mok, mok_size, "MokNew", SHIM_LOCK_GUID)) { ++ return 0; ++ } ++ } else { ++ if (!is_duplicate (mok, mok_size, "MokListRT", SHIM_LOCK_GUID) || ++ is_duplicate (mok, mok_size, "MokDel", SHIM_LOCK_GUID)) { ++ return 0; ++ } ++ } ++ ++ return 1; ++} ++ ++static int ++verify_old_req (void *old_req, unsigned long old_req_size, uint8_t import) ++{ ++ efi_variable_t req_auth; ++ const char *auth_name; + uint8_t auth[SHA256_DIGEST_LENGTH]; + char *password = NULL; + int pw_len, fail = 0; + size_t n; + int ret = 0; + +- memset (&mok_auth, 0, sizeof(mok_auth)); +- mok_auth.VariableName = "MokAuth"; +- mok_auth.VendorGuid = SHIM_LOCK_GUID; +- if (read_variable (&mok_auth) != EFI_SUCCESS) { +- fprintf (stderr, "Failed to read MokAuth\n"); ++ if (import) ++ auth_name = "MokAuth"; ++ else ++ auth_name = "MokDelAuth"; ++ ++ memset (&req_auth, 0, sizeof(req_auth)); ++ req_auth.VariableName = auth_name; ++ req_auth.VendorGuid = SHIM_LOCK_GUID; ++ if (read_variable (&req_auth) != EFI_SUCCESS) { ++ fprintf (stderr, "Failed to read %s\n", auth_name); + return 0; + } + +@@ -534,8 +575,8 @@ verify_mok_new (void *mok_new, unsigned long mok_new_size) + continue; + } + +- generate_auth (mok_new, mok_new_size, password, pw_len, auth); +- if (memcmp (auth, mok_auth.Data, SHA256_DIGEST_LENGTH) == 0) { ++ generate_auth (old_req, old_req_size, password, pw_len, auth); ++ if (memcmp (auth, req_auth.Data, SHA256_DIGEST_LENGTH) == 0) { + ret = 1; + break; + } +@@ -543,16 +584,17 @@ verify_mok_new (void *mok_new, unsigned long mok_new_size) + fail++; + } + +- if (mok_auth.Data) +- free (mok_auth.Data); ++ if (req_auth.Data) ++ free (req_auth.Data); + + return ret; + } + + static int +-import_moks (char **files, uint32_t total) ++issue_mok_request (char **files, uint32_t total, uint8_t import) + { +- efi_variable_t mok_new; ++ efi_variable_t old_req; ++ const char *req_name; + void *new_list = NULL; + void *ptr; + struct stat buf; +@@ -568,6 +610,11 @@ import_moks (char **files, uint32_t total) + if (!files) + return -1; + ++ if (import) ++ req_name = "MokNew"; ++ else ++ req_name = "MokDel"; ++ + sizes = malloc (total * sizeof(uint32_t)); + + if (!sizes) { +@@ -589,15 +636,15 @@ import_moks (char **files, uint32_t total) + list_size += sizeof(EFI_SIGNATURE_LIST) * total; + list_size += sizeof(efi_guid_t) * total; + +- memset (&mok_new, 0, sizeof(mok_new)); +- mok_new.VariableName = "MokNew"; +- mok_new.VendorGuid = SHIM_LOCK_GUID; +- if (read_variable (&mok_new) == EFI_SUCCESS) +- list_size += mok_new.DataSize; ++ memset (&old_req, 0, sizeof(old_req)); ++ old_req.VariableName = req_name; ++ old_req.VendorGuid = SHIM_LOCK_GUID; ++ if (read_variable (&old_req) == EFI_SUCCESS) ++ list_size += old_req.DataSize; + + new_list = malloc (list_size); + if (!new_list) { +- fprintf (stderr, "Failed to allocate space for MokNew\n"); ++ fprintf (stderr, "Failed to allocate space for %s\n", req_name); + goto error; + } + ptr = new_list; +@@ -633,15 +680,11 @@ import_moks (char **files, uint32_t total) + files[i]); + } + +- /* whether this key is already enrolled... */ +- if (!is_duplicate (ptr, sizes[i], "PK", EFI_GLOBAL_VARIABLE) && +- !is_duplicate (ptr, sizes[i], "KEK", EFI_GLOBAL_VARIABLE) && +- !is_duplicate (ptr, sizes[i], "db", EFI_IMAGE_SECURITY_DATABASE_GUID) && +- !is_duplicate (ptr, sizes[i], "MokListRT", SHIM_LOCK_GUID) && +- !is_duplicate (ptr, sizes[i], "MokNew", SHIM_LOCK_GUID)) { ++ if (is_valid_request (ptr, sizes[i], import)) { + ptr += sizes[i]; + real_size += sizes[i] + sizeof(EFI_SIGNATURE_LIST) + sizeof(efi_guid_t); + } else { ++ printf ("Skip %s\n", files[i]); + ptr -= sizeof(EFI_SIGNATURE_LIST) + sizeof(efi_guid_t); + } + +@@ -654,25 +697,25 @@ import_moks (char **files, uint32_t total) + goto error; + } + +- /* append the keys in MokNew */ +- if (mok_new.Data) { ++ /* append the keys to the previous request */ ++ if (old_req.Data) { + /* request the previous password to verify the keys */ +- if (!verify_mok_new (mok_new.Data, mok_new.DataSize)) { ++ if (!verify_old_req (old_req.Data, old_req.DataSize, import)) { + goto error; + } + +- memcpy (new_list + real_size, mok_new.Data, mok_new.DataSize); +- real_size += mok_new.DataSize; ++ memcpy (new_list + real_size, old_req.Data, old_req.DataSize); ++ real_size += old_req.DataSize; + } + +- if (update_request (new_list, real_size) < 0) { ++ if (update_request (new_list, real_size, import) < 0) { + goto error; + } + + ret = 0; + error: +- if (mok_new.Data) +- free (mok_new.Data); ++ if (old_req.Data) ++ free (old_req.Data); + if (sizes) + free (sizes); + if (new_list) +@@ -682,14 +725,15 @@ error: + } + + static int +-delete_all () ++import_moks (char **files, uint32_t total) + { +- if (update_request (NULL, 0)) { +- fprintf (stderr, "Failed to issue an delete request\n"); +- return -1; +- } ++ return issue_mok_request (files, total, 1); ++} + +- return 0; ++static int ++delete_moks (char **files, uint32_t total) ++{ ++ return issue_mok_request (files, total, 0); + } + + static int +@@ -932,6 +976,17 @@ error: + return ret; + } + ++static int ++reset_moks () ++{ ++ if (update_request (NULL, 0, 1)) { ++ fprintf (stderr, "Failed to issue a reset request\n"); ++ return -1; ++ } ++ ++ return 0; ++} ++ + int + main (int argc, char *argv[]) + { +@@ -982,8 +1037,23 @@ main (int argc, char *argv[]) + + command = COMMAND_IMPORT; + +- } else if (strcmp (argv[1], "-D") == 0 || +- strcmp (argv[1], "--delete-all") == 0) { ++ } else if (strcmp (argv[1], "-d") == 0 || ++ strcmp (argv[1], "--delete") == 0) { ++ ++ if (argc < 3) { ++ print_help (); ++ return -1; ++ } ++ total = argc - 2; ++ ++ files = malloc (total * sizeof(char *)); ++ if (!files) { ++ fprintf (stderr, "Failed to allocate file list\n"); ++ return -1; ++ } ++ ++ for (i = 0; i < total; i++) ++ files[i] = argv[i+2]; + + command = COMMAND_DELETE; + +@@ -1025,6 +1095,10 @@ main (int argc, char *argv[]) + + command = COMMAND_TEST_KEY; + ++ } else if (strcmp (argv[1], "--reset") == 0) { ++ ++ command = COMMAND_RESET; ++ + } else { + fprintf (stderr, "Unknown argument: %s\n\n", argv[1]); + print_help (); +@@ -1042,7 +1116,7 @@ main (int argc, char *argv[]) + ret = import_moks (files, total); + break; + case COMMAND_DELETE: +- ret = delete_all (); ++ ret = delete_moks (files, total); + break; + case COMMAND_REVOKE: + ret = revoke_request (); +@@ -1065,6 +1139,9 @@ main (int argc, char *argv[]) + case COMMAND_TEST_KEY: + ret = test_key (key_file); + break; ++ case COMMAND_RESET: ++ ret = reset_moks (); ++ break; + default: + fprintf (stderr, "Unknown command\n"); + break; +-- +1.7.10.4 + + +From 799d37815f470739ed079e2fea49077decaee3d3 Mon Sep 17 00:00:00 2001 +From: Gary Ching-Pang Lin +Date: Wed, 2 Jan 2013 17:09:35 +0800 +Subject: [PATCH 7/7] Initialize the variable to prevent a potential crash + +In issue_mok_request(), old_req.Data must be intialized before +"goto error", or the process would segfault when freeing old_req.Data. +--- + src/mokutil.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/src/mokutil.c b/src/mokutil.c +index e6807da..a99e355 100644 +--- a/src/mokutil.c ++++ b/src/mokutil.c +@@ -617,6 +617,8 @@ issue_mok_request (char **files, uint32_t total, uint8_t import) + + sizes = malloc (total * sizeof(uint32_t)); + ++ memset (&old_req, 0, sizeof(old_req)); ++ + if (!sizes) { + fprintf (stderr, "Failed to allocate space for sizes\n"); + goto error; +@@ -636,7 +638,6 @@ issue_mok_request (char **files, uint32_t total, uint8_t import) + list_size += sizeof(EFI_SIGNATURE_LIST) * total; + list_size += sizeof(efi_guid_t) * total; + +- memset (&old_req, 0, sizeof(old_req)); + old_req.VariableName = req_name; + old_req.VendorGuid = SHIM_LOCK_GUID; + if (read_variable (&old_req) == EFI_SUCCESS) +-- +1.7.10.4 + diff --git a/mokutil-support-new-pw-hash.patch b/mokutil-support-new-pw-hash.patch new file mode 100644 index 0000000..82702e2 --- /dev/null +++ b/mokutil-support-new-pw-hash.patch @@ -0,0 +1,1342 @@ +From bd29992e580e9a48dc698e2e108c73b51a98f05f Mon Sep 17 00:00:00 2001 +From: Gary Ching-Pang Lin +Date: Wed, 9 Jan 2013 15:44:42 +0800 +Subject: [PATCH 1/9] Use getopt() to parse options + +--- + src/mokutil.c | 259 +++++++++++++++++++++++++++------------------------------ + 1 file changed, 124 insertions(+), 135 deletions(-) + +diff --git a/src/mokutil.c b/src/mokutil.c +index ea8481a..2ab005c 100644 +--- a/src/mokutil.c ++++ b/src/mokutil.c +@@ -6,6 +6,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -19,6 +20,20 @@ EFI_GUID (0x605dab50, 0xe046, 0x4300, 0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, + #define PASSWORD_MAX 16 + #define PASSWORD_MIN 8 + ++#define HELP 0x1 ++#define LIST_ENROLLED 0x2 ++#define LIST_NEW 0x4 ++#define IMPORT 0x8 ++#define DELETE 0x10 ++#define REVOKE 0x20 ++#define EXPORT 0x40 ++#define PASSWORD 0x80 ++#define DISABLE_VALIDATION 0x100 ++#define ENABLE_VALIDATION 0x200 ++#define SB_STATE 0x400 ++#define TEST_KEY 0x800 ++#define RESET 0x1000 ++ + typedef struct { + uint32_t mok_size; + void *mok; +@@ -30,21 +45,6 @@ typedef struct { + uint16_t password[PASSWORD_MAX]; + } MokSBVar; + +-enum Command { +- COMMAND_LIST_ENROLLED, +- COMMAND_LIST_NEW, +- COMMAND_IMPORT, +- COMMAND_DELETE, +- COMMAND_REVOKE, +- COMMAND_EXPORT, +- COMMAND_PASSWORD, +- COMMAND_DISABLE_VALIDATION, +- COMMAND_ENABLE_VALIDATION, +- COMMAND_SB_STATE, +- COMMAND_TEST_KEY, +- COMMAND_RESET, +-}; +- + static void + print_help () + { +@@ -80,7 +80,7 @@ print_help () + printf(" mokutil --sb-state\n\n"); + + printf("Test if the key is enrolled or not:\n"); +- printf(" mokutil --test-key\n\n"); ++ printf(" mokutil --test-key \n\n"); + + printf("Reset MOK list:\n"); + printf(" mokutil --reset\n\n"); +@@ -998,163 +998,152 @@ main (int argc, char *argv[]) + { + char **files = NULL; + char *key_file = NULL; +- int i, total; +- int command; ++ const char *option; ++ int c, i, f_ind, total = 0; ++ unsigned int command = 0; + int ret = -1; + +- if (argc < 2) { +- print_help (); +- return 0; +- } +- +- if (strcmp (argv[1], "-h") == 0 || +- strcmp (argv[1], "--help") == 0) { +- +- print_help (); +- return 0; +- +- } else if (strcmp (argv[1], "-le") == 0 || +- strcmp (argv[1], "--list-enrolled") == 0) { +- +- command = COMMAND_LIST_ENROLLED; +- +- } else if (strcmp (argv[1], "-ln") == 0 || +- strcmp (argv[1], "--list-new") == 0) { +- +- command = COMMAND_LIST_NEW; +- +- } else if (strcmp (argv[1], "-i") == 0 || +- strcmp (argv[1], "--import") == 0) { +- +- if (argc < 3) { +- print_help (); +- return -1; +- } +- total = argc - 2; +- +- files = malloc (total * sizeof(char *)); +- if (!files) { +- fprintf (stderr, "Failed to allocate file list\n"); +- return -1; +- } +- +- for (i = 0; i < total; i++) +- files[i] = argv[i+2]; +- +- command = COMMAND_IMPORT; +- +- } else if (strcmp (argv[1], "-d") == 0 || +- strcmp (argv[1], "--delete") == 0) { +- +- if (argc < 3) { +- print_help (); +- return -1; +- } +- total = argc - 2; +- +- files = malloc (total * sizeof(char *)); +- if (!files) { +- fprintf (stderr, "Failed to allocate file list\n"); +- return -1; +- } +- +- for (i = 0; i < total; i++) +- files[i] = argv[i+2]; +- +- command = COMMAND_DELETE; +- +- } else if (strcmp (argv[1], "-r") == 0 || +- strcmp (argv[1], "--revoke") == 0) { +- +- command = COMMAND_REVOKE; +- +- } else if (strcmp (argv[1], "-x") == 0 || +- strcmp (argv[1], "--export") == 0) { +- +- command = COMMAND_EXPORT; +- +- } else if (strcmp (argv[1], "-p") == 0 || +- strcmp (argv[1], "--password") == 0) { +- +- command = COMMAND_PASSWORD; +- +- } else if (strcmp (argv[1], "--disable-validation") == 0) { +- +- command = COMMAND_DISABLE_VALIDATION; +- +- } else if (strcmp (argv[1], "--enable-validation") == 0) { +- +- command = COMMAND_ENABLE_VALIDATION; +- +- } else if (strcmp (argv[1], "--sb-state") == 0) { ++ while (1) { ++ static struct option long_options[] = { ++ {"help", no_argument, 0, 'h'}, ++ {"list-enrolled", no_argument, 0, 0 }, ++ {"list-new", no_argument, 0, 0 }, ++ {"import", required_argument, 0, 'i'}, ++ {"delete", required_argument, 0, 'd'}, ++ {"revoke", no_argument, 0, 0 }, ++ {"export", no_argument, 0, 'x'}, ++ {"password", no_argument, 0, 'p'}, ++ {"disable-validation", no_argument, 0, 0 }, ++ {"enable-validation", no_argument, 0, 0 }, ++ {"sb-state", no_argument, 0, 0 }, ++ {"test-key", required_argument, 0, 't'}, ++ {"reset", no_argument, 0, 0 }, ++ {0, 0, 0, 0} ++ }; ++ ++ int option_index = 0; ++ c = getopt_long (argc, argv, "d:hi:pt:x", ++ long_options, &option_index); ++ ++ if (c == -1) ++ break; + +- command = COMMAND_SB_STATE; ++ switch (c) { ++ case 0: ++ option = long_options[option_index].name; ++ if (strcmp (option, "list-enrolled") == 0) { ++ command |= LIST_ENROLLED; ++ } else if (strcmp (option, "list-new") == 0) { ++ command |= LIST_NEW; ++ } else if (strcmp (option, "revoke") == 0) { ++ command |= REVOKE; ++ } else if (strcmp (option, "disable-validation") == 0) { ++ command |= DISABLE_VALIDATION; ++ } else if (strcmp (option, "enable-validation") == 0) { ++ command |= ENABLE_VALIDATION; ++ } else if (strcmp (option, "sb-state") == 0) { ++ command |= SB_STATE; ++ } else if (strcmp (option, "reset") == 0) { ++ command |= RESET; ++ } ++ break; ++ case 'd': ++ case 'i': ++ if (c == 'd') ++ command |= DELETE; ++ else ++ command |= IMPORT; ++ ++ if (files) { ++ command |= HELP; ++ break; ++ } ++ ++ total = 0; ++ for (f_ind = optind - 1; ++ f_ind < argc && *argv[f_ind] != '-'; ++ f_ind++) { ++ total++; ++ } ++ ++ files = malloc (total * sizeof (char *)); ++ for (i = 0; i < total; i++) { ++ f_ind = i + optind - 1; ++ files[i] = malloc (strlen(argv[f_ind]) + 1); ++ strcpy (files[i], argv[f_ind]); ++ } + +- } else if (strcmp (argv[1], "--test-key") == 0) { ++ break; ++ case 'p': ++ command |= PASSWORD; ++ break; ++ case 't': ++ key_file = strdup (optarg); + +- if (argc < 3) { +- print_help (); +- return -1; ++ command |= TEST_KEY; ++ break; ++ case 'x': ++ command |= EXPORT; ++ break; ++ case 'h': ++ case '?': ++ command |= HELP; ++ break; ++ default: ++ abort (); + } +- +- key_file = argv[2]; +- +- command = COMMAND_TEST_KEY; +- +- } else if (strcmp (argv[1], "--reset") == 0) { +- +- command = COMMAND_RESET; +- +- } else { +- fprintf (stderr, "Unknown argument: %s\n\n", argv[1]); +- print_help (); +- return -1; + } + + switch (command) { +- case COMMAND_LIST_ENROLLED: ++ case LIST_ENROLLED: + ret = list_enrolled_keys (); + break; +- case COMMAND_LIST_NEW: ++ case LIST_NEW: + ret = list_new_keys (); + break; +- case COMMAND_IMPORT: ++ case IMPORT: + ret = import_moks (files, total); + break; +- case COMMAND_DELETE: ++ case DELETE: + ret = delete_moks (files, total); + break; +- case COMMAND_REVOKE: ++ case REVOKE: + ret = revoke_request (); + break; +- case COMMAND_EXPORT: ++ case EXPORT: + ret = export_moks (); + break; +- case COMMAND_PASSWORD: ++ case PASSWORD: + ret = set_password (); + break; +- case COMMAND_DISABLE_VALIDATION: ++ case DISABLE_VALIDATION: + ret = disable_validation (); + break; +- case COMMAND_ENABLE_VALIDATION: ++ case ENABLE_VALIDATION: + ret = enable_validation (); + break; +- case COMMAND_SB_STATE: ++ case SB_STATE: + ret = sb_state (); + break; +- case COMMAND_TEST_KEY: ++ case TEST_KEY: + ret = test_key (key_file); + break; +- case COMMAND_RESET: ++ case RESET: + ret = reset_moks (); + break; + default: +- fprintf (stderr, "Unknown command\n"); ++ print_help (); + break; + } + +- if (files) ++ if (files) { ++ for (i = 0; i < total; i++) ++ free (files[i]); + free (files); ++ } ++ ++ if (key_file) ++ free (key_file); + + return ret; + } +-- +1.7.10.4 + + +From 32a919cd2ca89ea0dfcc7644c05a3cf88cbb13c4 Mon Sep 17 00:00:00 2001 +From: Gary Ching-Pang Lin +Date: Wed, 9 Jan 2013 17:37:30 +0800 +Subject: [PATCH 2/9] Adopt new password hash format + +old format: MokNew + sha256sum(MokNew + password) +new format: salt + sha256sum(salt + password) +The new format makes a preset hash possible. +--- + src/mokutil.c | 102 ++++++++++++++++++++------------------------------------- + 1 file changed, 35 insertions(+), 67 deletions(-) + +diff --git a/src/mokutil.c b/src/mokutil.c +index 2ab005c..61c432d 100644 +--- a/src/mokutil.c ++++ b/src/mokutil.c +@@ -20,6 +20,8 @@ EFI_GUID (0x605dab50, 0xe046, 0x4300, 0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, + #define PASSWORD_MAX 16 + #define PASSWORD_MIN 8 + ++#define SALT_SIZE 16 ++ + #define HELP 0x1 + #define LIST_ENROLLED 0x2 + #define LIST_NEW 0x4 +@@ -366,8 +368,19 @@ error: + return ret; + } + ++static void ++generate_salt (uint8_t salt[], unsigned int salt_len) ++{ ++ int i; ++ ++ srand (time (NULL)); ++ ++ for (i = 0; i < salt_len; i++) ++ salt[i] = rand() % 256; ++} ++ + static int +-generate_auth (void *new_list, unsigned long list_len, char *password, ++generate_hash (void *salt, unsigned int salt_len, char *password, + int pw_len, uint8_t *auth) + { + efi_char16_t efichar_pass[PASSWORD_MAX+1]; +@@ -382,8 +395,8 @@ generate_auth (void *new_list, unsigned long list_len, char *password, + + SHA256_Init (&ctx); + +- if (new_list) +- SHA256_Update (&ctx, new_list, list_len); ++ if (salt) ++ SHA256_Update (&ctx, salt, salt_len); + + SHA256_Update (&ctx, efichar_pass, efichar_len); + +@@ -397,7 +410,9 @@ update_request (void *new_list, int list_len, uint8_t import) + { + efi_variable_t var; + const char *req_name, *auth_name; +- uint8_t auth[SHA256_DIGEST_LENGTH]; ++ uint8_t salt[SALT_SIZE]; ++ uint8_t hash[SHA256_DIGEST_LENGTH]; ++ uint8_t auth[SALT_SIZE + SHA256_DIGEST_LENGTH]; + char *password = NULL; + int pw_len; + int ret = -1; +@@ -415,7 +430,13 @@ update_request (void *new_list, int list_len, uint8_t import) + goto error; + } + +- generate_auth (new_list, list_len, password, pw_len, auth); ++ generate_salt (salt, SALT_SIZE); ++ if (generate_hash (salt, SALT_SIZE, password, pw_len, hash) < 0) { ++ fprintf (stderr, "Couldn't generate hash\n"); ++ goto error; ++ } ++ memcpy (auth, salt, SALT_SIZE); ++ memcpy (auth + SALT_SIZE, hash, SHA256_DIGEST_LENGTH); + + if (new_list) { + /* Write MokNew*/ +@@ -439,7 +460,7 @@ update_request (void *new_list, int list_len, uint8_t import) + + /* Write MokAuth */ + var.Data = auth; +- var.DataSize = SHA256_DIGEST_LENGTH; ++ var.DataSize = SHA256_DIGEST_LENGTH + SALT_SIZE; + var.VariableName = auth_name; + + var.VendorGuid = SHIM_LOCK_GUID; +@@ -545,57 +566,6 @@ is_valid_request (void *mok, uint32_t mok_size, uint8_t import) + } + + static int +-verify_old_req (void *old_req, unsigned long old_req_size, uint8_t import) +-{ +- efi_variable_t req_auth; +- const char *auth_name; +- uint8_t auth[SHA256_DIGEST_LENGTH]; +- char *password = NULL; +- int pw_len, fail = 0; +- size_t n; +- int ret = 0; +- +- if (import) +- auth_name = "MokAuth"; +- else +- auth_name = "MokDelAuth"; +- +- memset (&req_auth, 0, sizeof(req_auth)); +- req_auth.VariableName = auth_name; +- req_auth.VendorGuid = SHIM_LOCK_GUID; +- if (read_variable (&req_auth) != EFI_SUCCESS) { +- fprintf (stderr, "Failed to read %s\n", auth_name); +- return 0; +- } +- +- while (fail < 3) { +- printf ("input old password: "); +- pw_len = read_hidden_line (&password, &n); +- printf ("\n"); +- +- if (pw_len > PASSWORD_MAX || pw_len < PASSWORD_MIN) { +- free (password); +- fprintf (stderr, "invalid password\n"); +- fail++; +- continue; +- } +- +- generate_auth (old_req, old_req_size, password, pw_len, auth); +- if (memcmp (auth, req_auth.Data, SHA256_DIGEST_LENGTH) == 0) { +- ret = 1; +- break; +- } +- +- fail++; +- } +- +- if (req_auth.Data) +- free (req_auth.Data); +- +- return ret; +-} +- +-static int + issue_mok_request (char **files, uint32_t total, uint8_t import) + { + efi_variable_t old_req; +@@ -705,11 +675,6 @@ issue_mok_request (char **files, uint32_t total, uint8_t import) + + /* append the keys to the previous request */ + if (old_req.Data) { +- /* request the previous password to verify the keys */ +- if (!verify_old_req (old_req.Data, old_req.DataSize, import)) { +- goto error; +- } +- + memcpy (new_list + real_size, old_req.Data, old_req.DataSize); + real_size += old_req.DataSize; + } +@@ -745,8 +710,6 @@ delete_moks (char **files, uint32_t total) + static int + revoke_request () + { +- /* TODO request the old password? */ +- + if (test_and_delete_var ("MokNew") < 0) + return -1; + +@@ -814,7 +777,9 @@ static int + set_password () + { + efi_variable_t var; +- uint8_t auth[SHA256_DIGEST_LENGTH]; ++ uint8_t salt[SALT_SIZE]; ++ uint8_t hash[SHA256_DIGEST_LENGTH]; ++ uint8_t auth[SHA256_DIGEST_LENGTH + SALT_SIZE]; + char *password = NULL; + int pw_len; + int ret = -1; +@@ -824,13 +789,16 @@ set_password () + goto error; + } + +- if (generate_auth (NULL, 0, password, pw_len, auth) < 0) { ++ generate_salt (salt, SALT_SIZE); ++ if (generate_hash (salt, SALT_SIZE, password, pw_len, hash) < 0) { + fprintf (stderr, "Couldn't generate hash\n"); + goto error; + } ++ memcpy (auth, salt, SALT_SIZE); ++ memcpy (auth + SALT_SIZE, hash, SHA256_DIGEST_LENGTH); + + var.Data = auth; +- var.DataSize = SHA256_DIGEST_LENGTH; ++ var.DataSize = SHA256_DIGEST_LENGTH + SALT_SIZE; + var.VariableName = "MokPW"; + + var.VendorGuid = SHIM_LOCK_GUID; +-- +1.7.10.4 + + +From 326082d300337b347ae2cc42808ce905dd92eb3b Mon Sep 17 00:00:00 2001 +From: Gary Ching-Pang Lin +Date: Wed, 9 Jan 2013 17:59:01 +0800 +Subject: [PATCH 3/9] Close the key file + +--- + src/mokutil.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/src/mokutil.c b/src/mokutil.c +index 61c432d..86d5328 100644 +--- a/src/mokutil.c ++++ b/src/mokutil.c +@@ -947,6 +947,8 @@ error: + if (key) + free (key); + ++ close (fd); ++ + return ret; + } + +-- +1.7.10.4 + + +From 97d977246991f750827764fb48662c8be4b40f78 Mon Sep 17 00:00:00 2001 +From: Gary Ching-Pang Lin +Date: Thu, 10 Jan 2013 17:07:36 +0800 +Subject: [PATCH 4/9] Get rid of misused while statement + +--- + src/mokutil.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/mokutil.c b/src/mokutil.c +index 86d5328..36783cb 100644 +--- a/src/mokutil.c ++++ b/src/mokutil.c +@@ -784,7 +784,7 @@ set_password () + int pw_len; + int ret = -1; + +- while (get_password (&password, &pw_len, PASSWORD_MIN, PASSWORD_MAX) < 0) { ++ if (get_password (&password, &pw_len, PASSWORD_MIN, PASSWORD_MAX) < 0) { + fprintf (stderr, "Abort\n"); + goto error; + } +@@ -828,7 +828,7 @@ set_validation (uint32_t state) + efi_char16_t efichar_pass[PASSWORD_MAX]; + int ret = -1; + +- while (get_password (&password, &pw_len, PASSWORD_MIN, PASSWORD_MAX) < 0) { ++ if (get_password (&password, &pw_len, PASSWORD_MIN, PASSWORD_MAX) < 0) { + fprintf (stderr, "Abort\n"); + goto error; + } +-- +1.7.10.4 + + +From ca1978555253562c4ad39ff8b050cbbbe485474b Mon Sep 17 00:00:00 2001 +From: Gary Ching-Pang Lin +Date: Thu, 10 Jan 2013 17:24:58 +0800 +Subject: [PATCH 5/9] Read the password hash from the file + +--- + src/mokutil.c | 158 ++++++++++++++++++++++++++++++++++++++++++++++----------- + 1 file changed, 127 insertions(+), 31 deletions(-) + +diff --git a/src/mokutil.c b/src/mokutil.c +index 36783cb..4b9002e 100644 +--- a/src/mokutil.c ++++ b/src/mokutil.c +@@ -35,6 +35,7 @@ EFI_GUID (0x605dab50, 0xe046, 0x4300, 0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, + #define SB_STATE 0x400 + #define TEST_KEY 0x800 + #define RESET 0x1000 ++#define HASH_FILE 0x2000 + + typedef struct { + uint32_t mok_size; +@@ -406,7 +407,73 @@ generate_hash (void *salt, unsigned int salt_len, char *password, + } + + static int +-update_request (void *new_list, int list_len, uint8_t import) ++char_to_int (const char c) ++{ ++ if (c >= '0' && c <= '9') ++ return (c - '0'); ++ ++ if (c >= 'A' && c <= 'F') ++ return (c - 'A' + 10); ++ ++ if (c >= 'a' && c <= 'f') ++ return (c - 'a' + 10); ++ ++ return -1; ++} ++ ++static int ++read_hex_array (const char *string, char *out, int len) ++{ ++ int i, digit_1, digit_2; ++ ++ for (i = 0; i < len; i++) { ++ digit_1 = char_to_int (string[2*i]); ++ digit_2 = char_to_int (string[2*i + 1]); ++ if (digit_1 < 0 || digit_2 < 0) ++ return -1; ++ ++ out[i] = (char)digit_1 * 16 + (char)digit_2; ++ } ++ ++ return 0; ++} ++ ++static int ++get_hash_from_file (const char *file, void *salt, void *hash) ++{ ++ FILE *fptr; ++ char salt_string[2*SALT_SIZE]; ++ char hash_string[2*SHA256_DIGEST_LENGTH]; ++ ++ fptr = fopen (file, "r"); ++ if (fptr == NULL) { ++ fprintf (stderr, "Failed to open %s\n", file); ++ return -1; ++ } ++ ++ memset (salt_string, 0, 2*SALT_SIZE); ++ memset (hash_string, 0, 2*SHA256_DIGEST_LENGTH); ++ ++ fscanf (fptr, "%32c.%64c", salt_string, hash_string); ++ ++ fclose (fptr); ++ ++ if (read_hex_array (salt_string, salt, SALT_SIZE) < 0) { ++ fprintf (stderr, "Corrupted salt\n"); ++ return -1; ++ } ++ ++ if (read_hex_array (hash_string, hash, SHA256_DIGEST_LENGTH) < 0) { ++ fprintf (stderr, "Corrupted hash\n"); ++ return -1; ++ } ++ ++ return 0; ++} ++ ++static int ++update_request (void *new_list, int list_len, uint8_t import, ++ const char *hash_file) + { + efi_variable_t var; + const char *req_name, *auth_name; +@@ -425,15 +492,22 @@ update_request (void *new_list, int list_len, uint8_t import) + auth_name = "MokDelAuth"; + } + +- if (get_password (&password, &pw_len, PASSWORD_MIN, PASSWORD_MAX) < 0) { +- fprintf (stderr, "Abort\n"); +- goto error; +- } ++ if (hash_file) { ++ if (get_hash_from_file (hash_file, salt, hash) < 0) { ++ fprintf (stderr, "Failed to read hash\n"); ++ goto error; ++ } ++ } else { ++ if (get_password (&password, &pw_len, PASSWORD_MIN, PASSWORD_MAX) < 0) { ++ fprintf (stderr, "Abort\n"); ++ goto error; ++ } + +- generate_salt (salt, SALT_SIZE); +- if (generate_hash (salt, SALT_SIZE, password, pw_len, hash) < 0) { +- fprintf (stderr, "Couldn't generate hash\n"); +- goto error; ++ generate_salt (salt, SALT_SIZE); ++ if (generate_hash (salt, SALT_SIZE, password, pw_len, hash) < 0) { ++ fprintf (stderr, "Couldn't generate hash\n"); ++ goto error; ++ } + } + memcpy (auth, salt, SALT_SIZE); + memcpy (auth + SALT_SIZE, hash, SHA256_DIGEST_LENGTH); +@@ -566,7 +640,8 @@ is_valid_request (void *mok, uint32_t mok_size, uint8_t import) + } + + static int +-issue_mok_request (char **files, uint32_t total, uint8_t import) ++issue_mok_request (char **files, uint32_t total, uint8_t import, ++ const char *hash_file) + { + efi_variable_t old_req; + const char *req_name; +@@ -679,7 +754,7 @@ issue_mok_request (char **files, uint32_t total, uint8_t import) + real_size += old_req.DataSize; + } + +- if (update_request (new_list, real_size, import) < 0) { ++ if (update_request (new_list, real_size, import, hash_file) < 0) { + goto error; + } + +@@ -696,15 +771,15 @@ error: + } + + static int +-import_moks (char **files, uint32_t total) ++import_moks (char **files, uint32_t total, const char *hash_file) + { +- return issue_mok_request (files, total, 1); ++ return issue_mok_request (files, total, 1, hash_file); + } + + static int +-delete_moks (char **files, uint32_t total) ++delete_moks (char **files, uint32_t total, const char *hash_file) + { +- return issue_mok_request (files, total, 0); ++ return issue_mok_request (files, total, 0, hash_file); + } + + static int +@@ -774,7 +849,7 @@ error: + } + + static int +-set_password () ++set_password (const char *hash_file) + { + efi_variable_t var; + uint8_t salt[SALT_SIZE]; +@@ -784,15 +859,22 @@ set_password () + int pw_len; + int ret = -1; + +- if (get_password (&password, &pw_len, PASSWORD_MIN, PASSWORD_MAX) < 0) { +- fprintf (stderr, "Abort\n"); +- goto error; +- } ++ if (hash_file) { ++ if (get_hash_from_file (hash_file, salt, hash) < 0) { ++ fprintf (stderr, "Failed to read hash\n"); ++ goto error; ++ } ++ } else { ++ if (get_password (&password, &pw_len, PASSWORD_MIN, PASSWORD_MAX) < 0) { ++ fprintf (stderr, "Abort\n"); ++ goto error; ++ } + +- generate_salt (salt, SALT_SIZE); +- if (generate_hash (salt, SALT_SIZE, password, pw_len, hash) < 0) { +- fprintf (stderr, "Couldn't generate hash\n"); +- goto error; ++ generate_salt (salt, SALT_SIZE); ++ if (generate_hash (salt, SALT_SIZE, password, pw_len, hash) < 0) { ++ fprintf (stderr, "Couldn't generate hash\n"); ++ goto error; ++ } + } + memcpy (auth, salt, SALT_SIZE); + memcpy (auth + SALT_SIZE, hash, SHA256_DIGEST_LENGTH); +@@ -953,9 +1035,9 @@ error: + } + + static int +-reset_moks () ++reset_moks (const char *hash_file) + { +- if (update_request (NULL, 0, 1)) { ++ if (update_request (NULL, 0, 1, hash_file)) { + fprintf (stderr, "Failed to issue a reset request\n"); + return -1; + } +@@ -968,6 +1050,7 @@ main (int argc, char *argv[]) + { + char **files = NULL; + char *key_file = NULL; ++ char *hash_file = NULL; + const char *option; + int c, i, f_ind, total = 0; + unsigned int command = 0; +@@ -988,11 +1071,12 @@ main (int argc, char *argv[]) + {"sb-state", no_argument, 0, 0 }, + {"test-key", required_argument, 0, 't'}, + {"reset", no_argument, 0, 0 }, ++ {"hash-file", required_argument, 0, 'f'}, + {0, 0, 0, 0} + }; + + int option_index = 0; +- c = getopt_long (argc, argv, "d:hi:pt:x", ++ c = getopt_long (argc, argv, "d:f:hi:pt:x", + long_options, &option_index); + + if (c == -1) +@@ -1044,6 +1128,11 @@ main (int argc, char *argv[]) + } + + break; ++ case 'f': ++ hash_file = strdup (optarg); ++ ++ command |= HASH_FILE; ++ break; + case 'p': + command |= PASSWORD; + break; +@@ -1072,10 +1161,12 @@ main (int argc, char *argv[]) + ret = list_new_keys (); + break; + case IMPORT: +- ret = import_moks (files, total); ++ case IMPORT | HASH_FILE: ++ ret = import_moks (files, total, hash_file); + break; + case DELETE: +- ret = delete_moks (files, total); ++ case DELETE | HASH_FILE: ++ ret = delete_moks (files, total, hash_file); + break; + case REVOKE: + ret = revoke_request (); +@@ -1084,7 +1175,8 @@ main (int argc, char *argv[]) + ret = export_moks (); + break; + case PASSWORD: +- ret = set_password (); ++ case PASSWORD | HASH_FILE: ++ ret = set_password (hash_file); + break; + case DISABLE_VALIDATION: + ret = disable_validation (); +@@ -1099,7 +1191,8 @@ main (int argc, char *argv[]) + ret = test_key (key_file); + break; + case RESET: +- ret = reset_moks (); ++ case RESET | HASH_FILE: ++ ret = reset_moks (hash_file); + break; + default: + print_help (); +@@ -1115,5 +1208,8 @@ main (int argc, char *argv[]) + if (key_file) + free (key_file); + ++ if (hash_file) ++ free (hash_file); ++ + return ret; + } +-- +1.7.10.4 + + +From c45ffc0d42c0564cf817a1682c0cbd5be164197d Mon Sep 17 00:00:00 2001 +From: Gary Ching-Pang Lin +Date: Thu, 10 Jan 2013 18:29:17 +0800 +Subject: [PATCH 6/9] Add a new command to generate the password hash + +--- + src/mokutil.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++- + 1 file changed, 68 insertions(+), 1 deletion(-) + +diff --git a/src/mokutil.c b/src/mokutil.c +index 4b9002e..fdb1a2b 100644 +--- a/src/mokutil.c ++++ b/src/mokutil.c +@@ -36,6 +36,7 @@ EFI_GUID (0x605dab50, 0xe046, 0x4300, 0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, + #define TEST_KEY 0x800 + #define RESET 0x1000 + #define HASH_FILE 0x2000 ++#define GENERATE_PW_HASH 0x4000 + + typedef struct { + uint32_t mok_size; +@@ -1045,12 +1046,65 @@ reset_moks (const char *hash_file) + return 0; + } + ++static int ++generate_pw_hash (const char *input_pw) ++{ ++ uint8_t salt[SALT_SIZE]; ++ uint8_t hash[SHA256_DIGEST_LENGTH]; ++ char *password = NULL; ++ int pw_len, i, ret = -1; ++ ++ if (input_pw) { ++ pw_len = strlen (input_pw); ++ if (pw_len > PASSWORD_MAX || pw_len < PASSWORD_MIN) { ++ fprintf (stderr, "password should be %d~%d characters\n", ++ PASSWORD_MIN, PASSWORD_MAX); ++ return -1; ++ } ++ ++ password = strdup (input_pw); ++ ++ if (!password) { ++ fprintf (stderr, "Failed to duplicate string\n"); ++ return -1; ++ } ++ } else { ++ if (get_password (&password, &pw_len, PASSWORD_MIN, PASSWORD_MAX) < 0) { ++ fprintf (stderr, "Abort\n"); ++ return -1; ++ } ++ } ++ ++ generate_salt (salt, SALT_SIZE); ++ if (generate_hash (salt, SALT_SIZE, password, pw_len, hash) < 0) { ++ fprintf (stderr, "Couldn't generate hash\n"); ++ goto error; ++ } ++ ++ /* Print the salt and hash */ ++ for (i = 0; i < SALT_SIZE; i++) { ++ printf ("%x%x", salt[i]/16, salt[i]%16); ++ } ++ putchar ('.'); ++ for (i = 0; i < SHA256_DIGEST_LENGTH; i++) ++ printf ("%x%x", hash[i]/16, hash[i]%16); ++ putchar ('\n'); ++ ++ ret = 0; ++error: ++ if (password) ++ free (password); ++ ++ return ret; ++} ++ + int + main (int argc, char *argv[]) + { + char **files = NULL; + char *key_file = NULL; + char *hash_file = NULL; ++ char *input_pw = NULL; + const char *option; + int c, i, f_ind, total = 0; + unsigned int command = 0; +@@ -1072,11 +1126,12 @@ main (int argc, char *argv[]) + {"test-key", required_argument, 0, 't'}, + {"reset", no_argument, 0, 0 }, + {"hash-file", required_argument, 0, 'f'}, ++ {"generate-hash", optional_argument, 0, 'g'}, + {0, 0, 0, 0} + }; + + int option_index = 0; +- c = getopt_long (argc, argv, "d:f:hi:pt:x", ++ c = getopt_long (argc, argv, "d:f:g::hi:pt:x", + long_options, &option_index); + + if (c == -1) +@@ -1133,6 +1188,12 @@ main (int argc, char *argv[]) + + command |= HASH_FILE; + break; ++ case 'g': ++ if (optarg) ++ input_pw = strdup (optarg); ++ ++ command |= GENERATE_PW_HASH; ++ break; + case 'p': + command |= PASSWORD; + break; +@@ -1194,6 +1255,9 @@ main (int argc, char *argv[]) + case RESET | HASH_FILE: + ret = reset_moks (hash_file); + break; ++ case GENERATE_PW_HASH: ++ ret = generate_pw_hash (input_pw); ++ break; + default: + print_help (); + break; +@@ -1211,5 +1275,8 @@ main (int argc, char *argv[]) + if (hash_file) + free (hash_file); + ++ if (input_pw) ++ free (input_pw); ++ + return ret; + } +-- +1.7.10.4 + + +From ba347d456e80101b7c4306e7b30465c47c0fbea6 Mon Sep 17 00:00:00 2001 +From: Gary Ching-Pang Lin +Date: Tue, 15 Jan 2013 16:14:32 +0800 +Subject: [PATCH 7/9] Amend help + +--- + src/mokutil.c | 59 ++++++++++++++++++++++----------------------------------- + 1 file changed, 23 insertions(+), 36 deletions(-) + +diff --git a/src/mokutil.c b/src/mokutil.c +index fdb1a2b..72a651a 100644 +--- a/src/mokutil.c ++++ b/src/mokutil.c +@@ -52,42 +52,29 @@ typedef struct { + static void + print_help () + { +- printf("Usage:\n"); +- printf("List the enrolled keys:\n"); +- printf(" mokutil --list-enrolled\n\n"); +- +- printf("List the keys to be enrolled:\n"); +- printf(" mokutil --list-new\n\n"); +- +- printf("Import keys:\n"); +- printf(" mokutil --import ...\n\n"); +- +- printf("Request to delete specific keys\n"); +- printf(" mokutil --delete ...\n\n"); +- +- printf("Revoke the request:\n"); +- printf(" mokutil --revoke\n\n"); +- +- printf("Export enrolled keys to files:\n"); +- printf(" mokutil --export\n\n"); +- +- printf("Set MOK password:\n"); +- printf(" mokutil --password\n\n"); +- +- printf("Disable signature validation:\n"); +- printf(" mokutil --disable-validation\n\n"); +- +- printf("Enable signature validation:\n"); +- printf(" mokutil --enable-validation\n\n"); +- +- printf("SecureBoot State:\n"); +- printf(" mokutil --sb-state\n\n"); +- +- printf("Test if the key is enrolled or not:\n"); +- printf(" mokutil --test-key \n\n"); +- +- printf("Reset MOK list:\n"); +- printf(" mokutil --reset\n\n"); ++ printf ("Usage:\n"); ++ printf (" mokutil OPTIONS [ARGS...]\n"); ++ printf ("\n"); ++ printf ("Options:\n"); ++ printf (" --help\t\t\t\tShow help\n"); ++ printf (" --list-enrolled\t\t\tList the enrolled keys\n"); ++ printf (" --list-new\t\t\t\tList the keys to be enrolled\n"); ++ printf (" --import \t\tImport keys\n"); ++ printf (" --delete \t\tDelete specific keys\n"); ++ printf (" --revoke\t\t\t\tRevoke the import request\n"); ++ printf (" --export\t\t\t\tExport enrolled keys to files\n"); ++ printf (" --password\t\t\t\tSet MOK password\n"); ++ printf (" --disable-validation\t\t\tDisable signature validation\n"); ++ printf (" --enable-validation\t\t\tEnable signature validation\n"); ++ printf (" --sb-state\t\t\t\tShow SecureBoot State\n"); ++ printf (" --test-key \t\t\tTest if the key is enrolled or not\n"); ++ printf (" --reset\t\t\t\tReset MOK list\n"); ++ printf (" --generate-hash[=password]\t\tGenerate the password hash\n"); ++ printf ("\n"); ++ printf ("Suboptions:\n"); ++ printf (" --hash-file \t\tUse the specific password hash\n"); ++ printf (" \t\t(Only valid with --import, --delete,\n"); ++ printf (" \t\t --password, and --reset)\n"); + } + + static int +-- +1.7.10.4 + + +From f1a1c7abd8fde13afcb5196c599c662109936d49 Mon Sep 17 00:00:00 2001 +From: Gary Ching-Pang Lin +Date: Tue, 15 Jan 2013 17:48:04 +0800 +Subject: [PATCH 8/9] New commands to revoke the import or delete request + +--- + src/mokutil.c | 58 +++++++++++++++++++++++++++++++++++---------------------- + 1 file changed, 36 insertions(+), 22 deletions(-) + +diff --git a/src/mokutil.c b/src/mokutil.c +index 72a651a..7392845 100644 +--- a/src/mokutil.c ++++ b/src/mokutil.c +@@ -27,16 +27,17 @@ EFI_GUID (0x605dab50, 0xe046, 0x4300, 0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, + #define LIST_NEW 0x4 + #define IMPORT 0x8 + #define DELETE 0x10 +-#define REVOKE 0x20 +-#define EXPORT 0x40 +-#define PASSWORD 0x80 +-#define DISABLE_VALIDATION 0x100 +-#define ENABLE_VALIDATION 0x200 +-#define SB_STATE 0x400 +-#define TEST_KEY 0x800 +-#define RESET 0x1000 +-#define HASH_FILE 0x2000 +-#define GENERATE_PW_HASH 0x4000 ++#define REVOKE_IMPORT 0x20 ++#define REVOKE_DELETE 0x40 ++#define EXPORT 0x80 ++#define PASSWORD 0x100 ++#define DISABLE_VALIDATION 0x200 ++#define ENABLE_VALIDATION 0x400 ++#define SB_STATE 0x800 ++#define TEST_KEY 0x1000 ++#define RESET 0x2000 ++#define HASH_FILE 0x4000 ++#define GENERATE_PW_HASH 0x8000 + + typedef struct { + uint32_t mok_size; +@@ -61,7 +62,8 @@ print_help () + printf (" --list-new\t\t\t\tList the keys to be enrolled\n"); + printf (" --import \t\tImport keys\n"); + printf (" --delete \t\tDelete specific keys\n"); +- printf (" --revoke\t\t\t\tRevoke the import request\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 (" --password\t\t\t\tSet MOK password\n"); + printf (" --disable-validation\t\t\tDisable signature validation\n"); +@@ -771,13 +773,19 @@ delete_moks (char **files, uint32_t total, const char *hash_file) + } + + static int +-revoke_request () ++revoke_request (uint8_t import) + { +- if (test_and_delete_var ("MokNew") < 0) +- return -1; +- +- if (test_and_delete_var ("MokAuth") < 0) +- return -1; ++ if (import == 1) { ++ if (test_and_delete_var ("MokNew") < 0) ++ return -1; ++ if (test_and_delete_var ("MokAuth") < 0) ++ return -1; ++ } else { ++ if (test_and_delete_var ("MokDel") < 0) ++ return -1; ++ if (test_and_delete_var ("MokDelAuth") < 0) ++ return -1; ++ } + + return 0; + } +@@ -1104,7 +1112,8 @@ main (int argc, char *argv[]) + {"list-new", no_argument, 0, 0 }, + {"import", required_argument, 0, 'i'}, + {"delete", required_argument, 0, 'd'}, +- {"revoke", no_argument, 0, 0 }, ++ {"revoke-import", no_argument, 0, 0 }, ++ {"revoke-delete", no_argument, 0, 0 }, + {"export", no_argument, 0, 'x'}, + {"password", no_argument, 0, 'p'}, + {"disable-validation", no_argument, 0, 0 }, +@@ -1131,8 +1140,10 @@ main (int argc, char *argv[]) + command |= LIST_ENROLLED; + } else if (strcmp (option, "list-new") == 0) { + command |= LIST_NEW; +- } else if (strcmp (option, "revoke") == 0) { +- command |= REVOKE; ++ } else if (strcmp (option, "revoke-import") == 0) { ++ command |= REVOKE_IMPORT; ++ } else if (strcmp (option, "revoke-delete") == 0) { ++ command |= REVOKE_DELETE; + } else if (strcmp (option, "disable-validation") == 0) { + command |= DISABLE_VALIDATION; + } else if (strcmp (option, "enable-validation") == 0) { +@@ -1216,8 +1227,11 @@ main (int argc, char *argv[]) + case DELETE | HASH_FILE: + ret = delete_moks (files, total, hash_file); + break; +- case REVOKE: +- ret = revoke_request (); ++ case REVOKE_IMPORT: ++ ret = revoke_request (1); ++ break; ++ case REVOKE_DELETE: ++ ret = revoke_request (0); + break; + case EXPORT: + ret = export_moks (); +-- +1.7.10.4 + + +From 5cd7872982361be10755e3c8e7ecf228da92e164 Mon Sep 17 00:00:00 2001 +From: Gary Ching-Pang Lin +Date: Wed, 16 Jan 2013 15:12:28 +0800 +Subject: [PATCH 9/9] Apply stricter permissions to some variables + +The UEFI variables which contain the password or the password hash +should not be accessed by normal users. +--- + src/efi.h | 1 + + src/efilib.c | 22 ++++++++++++++++++++++ + src/mokutil.c | 6 +++--- + 3 files changed, 26 insertions(+), 3 deletions(-) + +diff --git a/src/efi.h b/src/efi.h +index d2640b4..ceed6c2 100644 +--- a/src/efi.h ++++ b/src/efi.h +@@ -360,6 +360,7 @@ extern efi_status_t test_variable (efi_variable_t *var); + extern efi_status_t read_variable (efi_variable_t *var); + extern efi_status_t edit_variable (efi_variable_t *var); + extern efi_status_t delete_variable (efi_variable_t *var); ++extern efi_status_t edit_protected_variable (efi_variable_t *var); + + extern int efichar_strlen (const efi_char16_t *p, int max); + extern unsigned long efichar_from_char (efi_char16_t *dest, const char *src, size_t dest_len); +diff --git a/src/efilib.c b/src/efilib.c +index f192c1a..cb1aca6 100644 +--- a/src/efilib.c ++++ b/src/efilib.c +@@ -215,3 +215,25 @@ delete_variable(efi_variable_t *var) + + return EFI_OUT_OF_RESOURCES; + } ++ ++efi_status_t ++edit_protected_variable (efi_variable_t *var) ++{ ++ char name[PATH_MAX]; ++ char filename[PATH_MAX]; ++ int ret; ++ if (!var) ++ return EFI_INVALID_PARAMETER; ++ ++ variable_to_name(var, name); ++ ++ snprintf(filename, PATH_MAX-1, "%s/%s", SYSFS_DIR_EFI_VARS, name); ++ ret = write_variable (filename, var); ++ if (ret != EFI_SUCCESS) ++ return ret; ++ ++ if (chmod (filename, S_IRUSR | S_IWUSR) < 0) ++ return EFI_UNSUPPORTED; ++ ++ return EFI_SUCCESS; ++} +diff --git a/src/mokutil.c b/src/mokutil.c +index 7392845..c1a0ffc 100644 +--- a/src/mokutil.c ++++ b/src/mokutil.c +@@ -532,7 +532,7 @@ update_request (void *new_list, int list_len, uint8_t import, + | EFI_VARIABLE_BOOTSERVICE_ACCESS + | EFI_VARIABLE_RUNTIME_ACCESS; + +- if (edit_variable (&var) != EFI_SUCCESS) { ++ if (edit_protected_variable (&var) != EFI_SUCCESS) { + fprintf (stderr, "Failed to write %s\n", auth_name); + test_and_delete_var (req_name); + goto error; +@@ -884,7 +884,7 @@ set_password (const char *hash_file) + | EFI_VARIABLE_BOOTSERVICE_ACCESS + | EFI_VARIABLE_RUNTIME_ACCESS; + +- if (edit_variable (&var) != EFI_SUCCESS) { ++ if (edit_protected_variable (&var) != EFI_SUCCESS) { + fprintf (stderr, "Failed to write MokPW\n"); + goto error; + } +@@ -929,7 +929,7 @@ set_validation (uint32_t state) + | EFI_VARIABLE_BOOTSERVICE_ACCESS + | EFI_VARIABLE_RUNTIME_ACCESS; + +- if (edit_variable (&var) != EFI_SUCCESS) { ++ if (edit_protected_variable (&var) != EFI_SUCCESS) { + fprintf (stderr, "Failed to request new SB state\n"); + goto error; + } +-- +1.7.10.4 + diff --git a/mokutil.changes b/mokutil.changes index 58c695a..e22a2ab 100644 --- a/mokutil.changes +++ b/mokutil.changes @@ -1,3 +1,15 @@ +------------------------------------------------------------------- +Wed Jan 16 08:41:15 UTC 2013 - glin@suse.com + +- Merge patches for FATE#314506 + + Add mokutil-support-delete-keys.patch to delete specific keys + + Add mokutil-support-new-pw-hash.patch to support the new + password format + + Add mokutil-allow-password-from-pipe.patch to allow the + password to be generated in a script and be sent through + pipeline +- Install COPYING + ------------------------------------------------------------------- Tue Dec 11 08:07:32 UTC 2012 - glin@suse.com diff --git a/mokutil.spec b/mokutil.spec index f093163..1ff4115 100644 --- a/mokutil.spec +++ b/mokutil.spec @@ -1,7 +1,7 @@ # # spec file for package mokutil # -# Copyright (c) 2012 SUSE LINUX Products GmbH, Nuernberg, Germany. +# Copyright (c) 2013 SUSE LINUX Products GmbH, Nuernberg, Germany. # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -16,21 +16,26 @@ # - Name: mokutil Version: 0.1.0 -Release: 1 -License: GPL-3.0 +Release: 0 Summary: Tools for manipulating machine owner keys -Url: https://github.com/lcp/mokutil +License: GPL-3.0 Group: Productivity/Security +Url: https://github.com/lcp/mokutil Source: %{name}-%{version}.tar.bz2 # PATCH-FIX-UPSTREAM mokutil-probe-secure-boot-state.patch glin@suse.com -- Probe the state of secure boot Patch1: mokutil-probe-secure-boot-state.patch # PATCH-FIX-UPSTREAM mokutil-no-duplicate-keys-imported.patch glin@suse.com -- Do not import duplicate keys Patch2: mokutil-no-duplicate-keys-imported.patch -BuildRequires: pkg-config +# PATCH-FIX-UPSTREAM mokutil-accept-password-from-pipe.patch glin@suse.com -- Allow the password to be sent through pipeline +Patch3: mokutil-allow-password-from-pipe.patch +# PATCH-FIX-UPSTREAM mokutil-support-delete-keys.patch glin@suse.com -- Add support for deleting specific keys +Patch4: mokutil-support-delete-keys.patch +# PATCH-FIX-UPSTREAM mokutil-support-new-pw-hash.patch glin@suse.com -- Support the new password hash format +Patch5: mokutil-support-new-pw-hash.patch BuildRequires: libopenssl-devel >= 0.9.8 +BuildRequires: pkg-config BuildRoot: %{_tmppath}/%{name}-%{version}-build ExclusiveArch: x86_64 @@ -48,6 +53,9 @@ Authors: %setup -q %patch1 -p1 %patch2 -p1 +%patch3 -p1 +%patch4 -p1 +%patch5 -p1 %build %configure @@ -61,6 +69,7 @@ make %files %defattr(-,root,root) +%doc COPYING %{_bindir}/mokutil %{_mandir}/man?/*