5d0e0f3e36
- Update mokutil-support-new-pw-hash.patch to extend the password hash format OBS-URL: https://build.opensuse.org/request/show/148927 OBS-URL: https://build.opensuse.org/package/show/Base:System/mokutil?expand=0&rev=4
1680 lines
44 KiB
Diff
1680 lines
44 KiB
Diff
From bd29992e580e9a48dc698e2e108c73b51a98f05f Mon Sep 17 00:00:00 2001
|
|
From: Gary Ching-Pang Lin <glin@suse.com>
|
|
Date: Wed, 9 Jan 2013 15:44:42 +0800
|
|
Subject: [PATCH 01/10] 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 <fcntl.h>
|
|
#include <unistd.h>
|
|
#include <termios.h>
|
|
+#include <getopt.h>
|
|
|
|
#include <openssl/sha.h>
|
|
#include <openssl/x509.h>
|
|
@@ -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 <der file>\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 <glin@suse.com>
|
|
Date: Wed, 9 Jan 2013 17:37:30 +0800
|
|
Subject: [PATCH 02/10] 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 <glin@suse.com>
|
|
Date: Wed, 9 Jan 2013 17:59:01 +0800
|
|
Subject: [PATCH 03/10] 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 <glin@suse.com>
|
|
Date: Thu, 10 Jan 2013 17:07:36 +0800
|
|
Subject: [PATCH 04/10] 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 <glin@suse.com>
|
|
Date: Thu, 10 Jan 2013 17:24:58 +0800
|
|
Subject: [PATCH 05/10] 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 <glin@suse.com>
|
|
Date: Thu, 10 Jan 2013 18:29:17 +0800
|
|
Subject: [PATCH 06/10] 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 <glin@suse.com>
|
|
Date: Tue, 15 Jan 2013 16:14:32 +0800
|
|
Subject: [PATCH 07/10] 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 <der file>...\n\n");
|
|
-
|
|
- printf("Request to delete specific keys\n");
|
|
- printf(" mokutil --delete <der file>...\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 <der file>\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 <der file...>\t\tImport keys\n");
|
|
+ printf (" --delete <der file...>\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 <der file>\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 <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 <glin@suse.com>
|
|
Date: Tue, 15 Jan 2013 17:48:04 +0800
|
|
Subject: [PATCH 08/10] 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 <der file...>\t\tImport keys\n");
|
|
printf (" --delete <der file...>\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 <glin@suse.com>
|
|
Date: Wed, 16 Jan 2013 15:12:28 +0800
|
|
Subject: [PATCH 09/10] 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
|
|
|
|
|
|
From 47645170396e2800980044c7054bcd1078bbba93 Mon Sep 17 00:00:00 2001
|
|
From: Gary Ching-Pang Lin <glin@suse.com>
|
|
Date: Fri, 18 Jan 2013 17:47:04 +0800
|
|
Subject: [PATCH 10/10] Extend the password hash format
|
|
|
|
Several new fields were added to support hash from /etc/shadow.
|
|
|
|
[Hash Method][Interation Count][Salt Size][Salt][hash]
|
|
|
|
Besides, the salt is hashed with the 8-bit char password instead of
|
|
an efi_char16_t password array.
|
|
---
|
|
src/PasswordHash.h | 33 ++++++++++++++++
|
|
src/mokutil.c | 106 +++++++++++++++++++++++++++++-----------------------
|
|
2 files changed, 93 insertions(+), 46 deletions(-)
|
|
create mode 100644 src/PasswordHash.h
|
|
|
|
diff --git a/src/PasswordHash.h b/src/PasswordHash.h
|
|
new file mode 100644
|
|
index 0000000..2aeded6
|
|
--- /dev/null
|
|
+++ b/src/PasswordHash.h
|
|
@@ -0,0 +1,33 @@
|
|
+#ifndef __PASSWORD_HASH_H__
|
|
+#define __PASSWORD_HASH_H__
|
|
+
|
|
+#include <sys/types.h>
|
|
+
|
|
+#define PASSWORD_HASH_SIZE 88
|
|
+
|
|
+/* The max salt size (in bits) */
|
|
+#define T_DES_SALT_MAX 12
|
|
+#define E_BSI_DES_SALT_MAX 24
|
|
+#define MD5_SALT_MAX 48
|
|
+#define SHA256_SALT_MAX 96
|
|
+#define SHA512_SALT_MAX 96
|
|
+#define BLOWFISH_SALT_MAX 128
|
|
+
|
|
+enum HashMethod {
|
|
+ Tranditional_DES = 0,
|
|
+ Extend_BSDI_DES,
|
|
+ MD5_BASED,
|
|
+ SHA256_BASED,
|
|
+ SHA512_BASED,
|
|
+ BLOWFISH_BASED
|
|
+};
|
|
+
|
|
+typedef struct {
|
|
+ uint16_t method;
|
|
+ uint32_t iter_count;
|
|
+ uint16_t salt_size;
|
|
+ uint8_t salt[16];
|
|
+ uint8_t hash[64];
|
|
+} __attribute__ ((packed)) pw_hash_t;
|
|
+
|
|
+#endif /* __PASSWORD_HASH_H__ */
|
|
diff --git a/src/mokutil.c b/src/mokutil.c
|
|
index c1a0ffc..38039b9 100644
|
|
--- a/src/mokutil.c
|
|
+++ b/src/mokutil.c
|
|
@@ -13,6 +13,7 @@
|
|
|
|
#include "efi.h"
|
|
#include "signature.h"
|
|
+#include "PasswordHash.h"
|
|
|
|
#define SHIM_LOCK_GUID \
|
|
EFI_GUID (0x605dab50, 0xe046, 0x4300, 0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23)
|
|
@@ -20,8 +21,6 @@ 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
|
|
@@ -359,37 +358,35 @@ error:
|
|
return ret;
|
|
}
|
|
|
|
-static void
|
|
-generate_salt (uint8_t salt[], unsigned int salt_len)
|
|
+static unsigned int
|
|
+generate_salt (uint8_t salt[], unsigned int max_size, unsigned int min_size)
|
|
{
|
|
+ unsigned int salt_len = max_size / 8;
|
|
int i;
|
|
|
|
srand (time (NULL));
|
|
|
|
for (i = 0; i < salt_len; i++)
|
|
salt[i] = rand() % 256;
|
|
+
|
|
+ return max_size;
|
|
}
|
|
|
|
static int
|
|
generate_hash (void *salt, unsigned int salt_len, char *password,
|
|
int pw_len, uint8_t *auth)
|
|
{
|
|
- efi_char16_t efichar_pass[PASSWORD_MAX+1];
|
|
- unsigned long efichar_len;
|
|
SHA256_CTX ctx;
|
|
|
|
if (!password || !auth)
|
|
return -1;
|
|
|
|
- efichar_len = efichar_from_char (efichar_pass, password,
|
|
- (PASSWORD_MAX+1)*sizeof(efi_char16_t));
|
|
-
|
|
SHA256_Init (&ctx);
|
|
|
|
if (salt)
|
|
SHA256_Update (&ctx, salt, salt_len);
|
|
|
|
- SHA256_Update (&ctx, efichar_pass, efichar_len);
|
|
+ SHA256_Update (&ctx, password, pw_len);
|
|
|
|
SHA256_Final (auth, &ctx);
|
|
|
|
@@ -412,7 +409,7 @@ char_to_int (const char c)
|
|
}
|
|
|
|
static int
|
|
-read_hex_array (const char *string, char *out, int len)
|
|
+read_hex_array (const char *string, uint8_t *out, unsigned int len)
|
|
{
|
|
int i, digit_1, digit_2;
|
|
|
|
@@ -422,17 +419,18 @@ read_hex_array (const char *string, char *out, int len)
|
|
if (digit_1 < 0 || digit_2 < 0)
|
|
return -1;
|
|
|
|
- out[i] = (char)digit_1 * 16 + (char)digit_2;
|
|
+ out[i] = (uint8_t)digit_1 * 16 + (uint8_t)digit_2;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
-get_hash_from_file (const char *file, void *salt, void *hash)
|
|
+get_hash_from_file (const char *file, pw_hash_t *pw_hash)
|
|
{
|
|
FILE *fptr;
|
|
- char salt_string[2*SALT_SIZE];
|
|
+ unsigned int method, iter_count, salt_size;
|
|
+ char salt_string[2*(SHA256_SALT_MAX/8)];
|
|
char hash_string[2*SHA256_DIGEST_LENGTH];
|
|
|
|
fptr = fopen (file, "r");
|
|
@@ -441,19 +439,24 @@ get_hash_from_file (const char *file, void *salt, void *hash)
|
|
return -1;
|
|
}
|
|
|
|
- memset (salt_string, 0, 2*SALT_SIZE);
|
|
+ memset (salt_string, 0, 2*(SHA256_SALT_MAX/8));
|
|
memset (hash_string, 0, 2*SHA256_DIGEST_LENGTH);
|
|
|
|
- fscanf (fptr, "%32c.%64c", salt_string, hash_string);
|
|
+ fscanf (fptr, "%x.%x.%x.%24c.%64c", &method, &iter_count, &salt_size,
|
|
+ salt_string, hash_string);
|
|
|
|
fclose (fptr);
|
|
|
|
- if (read_hex_array (salt_string, salt, SALT_SIZE) < 0) {
|
|
+ pw_hash->method = (uint16_t)method;
|
|
+ pw_hash->iter_count = (uint32_t)iter_count;
|
|
+ pw_hash->salt_size = (uint16_t)salt_size;
|
|
+
|
|
+ if (read_hex_array (salt_string, pw_hash->salt, salt_size/8) < 0) {
|
|
fprintf (stderr, "Corrupted salt\n");
|
|
return -1;
|
|
}
|
|
|
|
- if (read_hex_array (hash_string, hash, SHA256_DIGEST_LENGTH) < 0) {
|
|
+ if (read_hex_array (hash_string, pw_hash->hash, SHA256_DIGEST_LENGTH) < 0) {
|
|
fprintf (stderr, "Corrupted hash\n");
|
|
return -1;
|
|
}
|
|
@@ -467,13 +470,16 @@ update_request (void *new_list, int list_len, uint8_t import,
|
|
{
|
|
efi_variable_t var;
|
|
const char *req_name, *auth_name;
|
|
- uint8_t salt[SALT_SIZE];
|
|
- uint8_t hash[SHA256_DIGEST_LENGTH];
|
|
- uint8_t auth[SALT_SIZE + SHA256_DIGEST_LENGTH];
|
|
+ pw_hash_t pw_hash;
|
|
char *password = NULL;
|
|
int pw_len;
|
|
int ret = -1;
|
|
|
|
+ bzero (&pw_hash, sizeof(pw_hash_t));
|
|
+ pw_hash.method = SHA256_BASED;
|
|
+ pw_hash.iter_count = 1;
|
|
+ pw_hash.salt_size = SHA256_SALT_MAX;
|
|
+
|
|
if (import) {
|
|
req_name = "MokNew";
|
|
auth_name = "MokAuth";
|
|
@@ -483,7 +489,7 @@ update_request (void *new_list, int list_len, uint8_t import,
|
|
}
|
|
|
|
if (hash_file) {
|
|
- if (get_hash_from_file (hash_file, salt, hash) < 0) {
|
|
+ if (get_hash_from_file (hash_file, &pw_hash) < 0) {
|
|
fprintf (stderr, "Failed to read hash\n");
|
|
goto error;
|
|
}
|
|
@@ -493,14 +499,13 @@ update_request (void *new_list, int list_len, uint8_t import,
|
|
goto error;
|
|
}
|
|
|
|
- generate_salt (salt, SALT_SIZE);
|
|
- if (generate_hash (salt, SALT_SIZE, password, pw_len, hash) < 0) {
|
|
+ generate_salt (pw_hash.salt, SHA256_SALT_MAX, 0);
|
|
+ if (generate_hash (pw_hash.salt, SHA256_SALT_MAX/8, password,
|
|
+ pw_len, pw_hash.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*/
|
|
@@ -522,9 +527,9 @@ update_request (void *new_list, int list_len, uint8_t import,
|
|
test_and_delete_var (req_name);
|
|
}
|
|
|
|
- /* Write MokAuth */
|
|
- var.Data = auth;
|
|
- var.DataSize = SHA256_DIGEST_LENGTH + SALT_SIZE;
|
|
+ /* Write MokAuth or MokDelAuth */
|
|
+ var.Data = (void *)&pw_hash;
|
|
+ var.DataSize = PASSWORD_HASH_SIZE;
|
|
var.VariableName = auth_name;
|
|
|
|
var.VendorGuid = SHIM_LOCK_GUID;
|
|
@@ -848,15 +853,18 @@ static int
|
|
set_password (const char *hash_file)
|
|
{
|
|
efi_variable_t var;
|
|
- uint8_t salt[SALT_SIZE];
|
|
- uint8_t hash[SHA256_DIGEST_LENGTH];
|
|
- uint8_t auth[SHA256_DIGEST_LENGTH + SALT_SIZE];
|
|
+ pw_hash_t pw_hash;
|
|
char *password = NULL;
|
|
int pw_len;
|
|
int ret = -1;
|
|
|
|
+ bzero (&pw_hash, sizeof(pw_hash_t));
|
|
+ pw_hash.method = SHA256_BASED;
|
|
+ pw_hash.iter_count = 1;
|
|
+ pw_hash.salt_size = SHA256_SALT_MAX;
|
|
+
|
|
if (hash_file) {
|
|
- if (get_hash_from_file (hash_file, salt, hash) < 0) {
|
|
+ if (get_hash_from_file (hash_file, &pw_hash) < 0) {
|
|
fprintf (stderr, "Failed to read hash\n");
|
|
goto error;
|
|
}
|
|
@@ -866,17 +874,16 @@ set_password (const char *hash_file)
|
|
goto error;
|
|
}
|
|
|
|
- generate_salt (salt, SALT_SIZE);
|
|
- if (generate_hash (salt, SALT_SIZE, password, pw_len, hash) < 0) {
|
|
+ generate_salt (pw_hash.salt, SHA256_SALT_MAX, 0);
|
|
+ if (generate_hash (pw_hash.salt, SHA256_SALT_MAX/8, password,
|
|
+ pw_len, pw_hash.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 + SALT_SIZE;
|
|
+ var.Data = (void *)&pw_hash;
|
|
+ var.DataSize = PASSWORD_HASH_SIZE;
|
|
var.VariableName = "MokPW";
|
|
|
|
var.VendorGuid = SHIM_LOCK_GUID;
|
|
@@ -1044,11 +1051,15 @@ reset_moks (const char *hash_file)
|
|
static int
|
|
generate_pw_hash (const char *input_pw)
|
|
{
|
|
- uint8_t salt[SALT_SIZE];
|
|
- uint8_t hash[SHA256_DIGEST_LENGTH];
|
|
+ pw_hash_t pw_hash;
|
|
char *password = NULL;
|
|
int pw_len, i, ret = -1;
|
|
|
|
+ bzero (&pw_hash, sizeof(pw_hash_t));
|
|
+ pw_hash.method = SHA256_BASED;
|
|
+ pw_hash.iter_count = 1;
|
|
+ pw_hash.salt_size = SHA256_SALT_MAX;
|
|
+
|
|
if (input_pw) {
|
|
pw_len = strlen (input_pw);
|
|
if (pw_len > PASSWORD_MAX || pw_len < PASSWORD_MIN) {
|
|
@@ -1070,19 +1081,22 @@ generate_pw_hash (const char *input_pw)
|
|
}
|
|
}
|
|
|
|
- generate_salt (salt, SALT_SIZE);
|
|
- if (generate_hash (salt, SALT_SIZE, password, pw_len, hash) < 0) {
|
|
+ generate_salt (pw_hash.salt, SHA256_SALT_MAX, 0);
|
|
+ if (generate_hash (pw_hash.salt, SHA256_SALT_MAX/8, password,
|
|
+ pw_len, pw_hash.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);
|
|
+ printf ("%x.%x.%x.", pw_hash.method, pw_hash.iter_count,
|
|
+ pw_hash.salt_size);
|
|
+ for (i = 0; i < (SHA256_SALT_MAX/8); i++) {
|
|
+ printf ("%x%x", pw_hash.salt[i]/16, pw_hash.salt[i]%16);
|
|
}
|
|
putchar ('.');
|
|
for (i = 0; i < SHA256_DIGEST_LENGTH; i++)
|
|
- printf ("%x%x", hash[i]/16, hash[i]%16);
|
|
+ printf ("%x%x", pw_hash.hash[i]/16, pw_hash.hash[i]%16);
|
|
putchar ('\n');
|
|
|
|
ret = 0;
|
|
--
|
|
1.7.10.4
|
|
|