diff --git a/mokutil-mokx-support.patch b/mokutil-mokx-support.patch new file mode 100644 index 0000000..f2a5ab3 --- /dev/null +++ b/mokutil-mokx-support.patch @@ -0,0 +1,2917 @@ +From 65c8d2eb32beda5e90af891de3e5bda41a8aa6f1 Mon Sep 17 00:00:00 2001 +From: Gary Ching-Pang Lin +Date: Mon, 21 Oct 2013 17:49:33 +0800 +Subject: [PATCH 01/18] Update TODO + +--- + TODO | 16 ++-------------- + 1 file changed, 2 insertions(+), 14 deletions(-) + +diff --git a/TODO b/TODO +index 373e48d..465835a 100644 +--- a/TODO ++++ b/TODO +@@ -1,17 +1,5 @@ +-* Validate the DER file [DONE] + * Show the detail of the DER file when enrolling (?) + * Add an option to slience the output (?) +-* Show the current value of MokNew and MokListRT [DONE] +-* Request the user to input a password before enrolling [DONE] +-* Read the list from a volatile RT variable [DONE] +-* Export keys in MokListRT [DONE] + * List hashes in MokListRT +-* Add a new command to probe the state of SecureBoot +- - SecureBoot, EFI_GLOBAL_VARIABLE +-* Do not to enroll duplicate key +- - compare the keys in MokListRT before enrolling the new keys +- - compare the keys in MokNew +- - add a new command to check duplicate +-* Add a new command to append the new key request to the old one +- - use the old password to verify the old request +-* Delete a specific key ++* Support MokX ++* Import hash into MokNew, NokDel, MokXNew +-- +1.8.1.4 + + +From 012d82be0468e876a10691fbabab2ed11b7a4954 Mon Sep 17 00:00:00 2001 +From: Gary Ching-Pang Lin +Date: Tue, 22 Oct 2013 14:24:13 +0800 +Subject: [PATCH 02/18] Show the hashes in the database + +--- + src/efi.h | 2 +- + src/mokutil.c | 110 +++++++++++++++++++++++++++++++++++++++++++++++++++----- + src/signature.h | 14 ++++++-- + 3 files changed, 113 insertions(+), 13 deletions(-) + +diff --git a/src/efi.h b/src/efi.h +index a622a2b..33579c5 100644 +--- a/src/efi.h ++++ b/src/efi.h +@@ -102,7 +102,7 @@ EFI_GUID( 0x47c7b226, 0xc42a, 0x11d2, 0x8e, 0x57, 0x00, 0xa0, 0xc9, 0x69, 0x72, + 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) ++efi_guidcmp(const efi_guid_t left, const efi_guid_t right) + { + return memcmp(&left, &right, sizeof (efi_guid_t)); + } +diff --git a/src/mokutil.c b/src/mokutil.c +index e4e247c..62690ef 100644 +--- a/src/mokutil.c ++++ b/src/mokutil.c +@@ -157,14 +157,29 @@ test_and_delete_var (const char *var_name) + return 0; + } + ++static uint32_t ++signature_size (efi_guid_t hash_type) ++{ ++ if (efi_guidcmp (hash_type, EfiHashSha1Guid) == 0) ++ return (SHA_DIGEST_LENGTH + sizeof(efi_guid_t)); ++ else if (efi_guidcmp (hash_type, EfiHashSha224Guid) == 0) ++ return (SHA224_DIGEST_LENGTH + sizeof(efi_guid_t)); ++ else if (efi_guidcmp (hash_type, EfiHashSha256Guid) == 0) ++ return (SHA256_DIGEST_LENGTH + sizeof(efi_guid_t)); ++ else if (efi_guidcmp (hash_type, EfiHashSha384Guid) == 0) ++ return (SHA384_DIGEST_LENGTH + sizeof(efi_guid_t)); ++ else if (efi_guidcmp (hash_type, EfiHashSha512Guid) == 0) ++ return (SHA512_DIGEST_LENGTH + sizeof(efi_guid_t)); ++ ++ return 0; ++} ++ + static MokListNode* + build_mok_list (void *data, unsigned long data_size, uint32_t *mok_num) + { + MokListNode *list; + EFI_SIGNATURE_LIST *CertList = data; + EFI_SIGNATURE_DATA *Cert; +- efi_guid_t CertType = EfiCertX509Guid; +- efi_guid_t HashType = EfiHashSha256Guid; + unsigned long dbsize = data_size; + unsigned long count = 0; + +@@ -176,16 +191,20 @@ build_mok_list (void *data, unsigned long data_size, uint32_t *mok_num) + } + + while ((dbsize > 0) && (dbsize >= CertList->SignatureListSize)) { +- if ((efi_guidcmp (CertList->SignatureType, CertType) != 0) && +- (efi_guidcmp (CertList->SignatureType, HashType) != 0)) { ++ if ((efi_guidcmp (CertList->SignatureType, EfiCertX509Guid) != 0) && ++ (efi_guidcmp (CertList->SignatureType, EfiHashSha1Guid) != 0) && ++ (efi_guidcmp (CertList->SignatureType, EfiHashSha224Guid) != 0) && ++ (efi_guidcmp (CertList->SignatureType, EfiHashSha256Guid) != 0) && ++ (efi_guidcmp (CertList->SignatureType, EfiHashSha384Guid) != 0) && ++ (efi_guidcmp (CertList->SignatureType, EfiHashSha512Guid) != 0)) { + dbsize -= CertList->SignatureListSize; + CertList = (EFI_SIGNATURE_LIST *)((uint8_t *) CertList + + CertList->SignatureListSize); + continue; + } + +- if ((efi_guidcmp (CertList->SignatureType, HashType) == 0) && +- (CertList->SignatureSize != 48)) { ++ if ((efi_guidcmp (CertList->SignatureType, EfiCertX509Guid) != 0) && ++ (CertList->SignatureSize != signature_size (CertList->SignatureType))) { + dbsize -= CertList->SignatureListSize; + CertList = (EFI_SIGNATURE_LIST *)((uint8_t *) CertList + + CertList->SignatureListSize); +@@ -203,8 +222,18 @@ build_mok_list (void *data, unsigned long data_size, uint32_t *mok_num) + } + + list[count].header = CertList; +- list[count].mok_size = CertList->SignatureSize - sizeof(efi_guid_t); +- list[count].mok = (void *)Cert->SignatureData; ++ if (efi_guidcmp (CertList->SignatureType, EfiCertX509Guid) == 0) { ++ /* X509 certificate */ ++ list[count].mok_size = CertList->SignatureSize - ++ sizeof(efi_guid_t); ++ list[count].mok = (void *)Cert->SignatureData; ++ } else { ++ /* hash array */ ++ list[count].mok_size = CertList->SignatureListSize - ++ sizeof(EFI_SIGNATURE_LIST) - ++ CertList->SignatureHeaderSize; ++ list[count].mok = (void *)Cert; ++ } + + count++; + dbsize -= CertList->SignatureListSize; +@@ -258,6 +287,64 @@ print_x509 (char *cert, int cert_size) + } + + static int ++print_hash_array (efi_guid_t hash_type, void *hash_array, uint32_t array_size) ++{ ++ uint32_t hash_size, remain; ++ uint32_t sig_size; ++ uint8_t *hash; ++ const char *name; ++ int i; ++ ++ if (!hash_array || array_size == 0) { ++ fprintf (stderr, "invalid hash array\n"); ++ return -1; ++ } ++ ++ if (efi_guidcmp (hash_type, EfiHashSha1Guid) == 0) { ++ name = "SHA1"; ++ hash_size = SHA_DIGEST_LENGTH; ++ } else if (efi_guidcmp (hash_type, EfiHashSha224Guid) == 0) { ++ name = "SHA224"; ++ hash_size = SHA224_DIGEST_LENGTH; ++ } else if (efi_guidcmp (hash_type, EfiHashSha256Guid) == 0) { ++ name = "SHA256"; ++ hash_size = SHA256_DIGEST_LENGTH; ++ } else if (efi_guidcmp (hash_type, EfiHashSha384Guid) == 0) { ++ name = "SHA384"; ++ hash_size = SHA384_DIGEST_LENGTH; ++ } else if (efi_guidcmp (hash_type, EfiHashSha512Guid) == 0) { ++ name = "SHA512"; ++ hash_size = SHA512_DIGEST_LENGTH; ++ } else { ++ fprintf (stderr, "unknown hash type\n"); ++ return -1; ++ } ++ sig_size = hash_size + sizeof(efi_guid_t); ++ ++ printf (" [%s]\n", name); ++ ++ remain = array_size; ++ hash = (uint8_t *)hash_array; ++ ++ while (remain > 0) { ++ if (remain < sig_size) { ++ fprintf (stderr, "invalid array size\n"); ++ return -1; ++ } ++ ++ printf (" "); ++ hash += sizeof(efi_guid_t); ++ for (i = 0; iSignatureType, EfiCertX509Guid) == 0) { ++ print_x509 ((char *)list[i].mok, list[i].mok_size); ++ } else { ++ print_hash_array (list[i].header->SignatureType, ++ list[i].mok, list[i].mok_size); ++ } + if (i < mok_num - 1) + printf ("\n"); + } +diff --git a/src/signature.h b/src/signature.h +index df88e98..02f0211 100644 +--- a/src/signature.h ++++ b/src/signature.h +@@ -28,11 +28,17 @@ + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ +-#define SHA256_DIGEST_SIZE 32 ++#ifndef SIGNATURE_H ++#define SIGNATURE_H + +-#define EfiHashSha1Guid EFI_GUID (0x826ca512, 0xcf10, 0x4ac9, 0xb1, 0x87, 0xbe, 0x1, 0x49, 0x66, 0x31, 0xbd) ++#include "efi.h" ++ ++#define EfiHashSha1Guid EFI_GUID (0x826ca512, 0xcf10, 0x4ac9, 0xb1, 0x87, 0xbe, 0x1, 0x49, 0x66, 0x31, 0xbd) ++#define EfiHashSha224Guid EFI_GUID (0xb6e5233, 0xa65c, 0x44c9, 0x94, 0x7, 0xd9, 0xab, 0x83, 0xbf, 0xc8, 0xbd) + #define EfiHashSha256Guid EFI_GUID (0xc1c41626, 0x504c, 0x4092, 0xac, 0xa9, 0x41, 0xf9, 0x36, 0x93, 0x43, 0x28) +-#define EfiCertX509Guid EFI_GUID (0xa5c059a1, 0x94e4, 0x4aa7, 0x87, 0xb5, 0xab, 0x15, 0x5c, 0x2b, 0xf0, 0x72) ++#define EfiHashSha384Guid EFI_GUID (0xff3e5307, 0x9fd0, 0x48c9, 0x85, 0xf1, 0x8a, 0xd5, 0x6c, 0x70, 0x1e, 0x1) ++#define EfiHashSha512Guid EFI_GUID (0x93e0fae, 0xa6c4, 0x4f50, 0x9f, 0x1b, 0xd4, 0x1e, 0x2b, 0x89, 0xc1, 0x9a) ++#define EfiCertX509Guid EFI_GUID (0xa5c059a1, 0x94e4, 0x4aa7, 0x87, 0xb5, 0xab, 0x15, 0x5c, 0x2b, 0xf0, 0x72) + + typedef struct { + /// +@@ -71,3 +77,5 @@ typedef struct { + /// EFI_SIGNATURE_DATA Signatures[][SignatureSize]; + /// + } __attribute__ ((packed)) EFI_SIGNATURE_LIST; ++ ++#endif /* SIGNATURE_H */ +-- +1.8.1.4 + + +From 77a215f86139b21fd55dca4d032b7269f62b51c1 Mon Sep 17 00:00:00 2001 +From: Gary Ching-Pang Lin +Date: Tue, 22 Oct 2013 14:34:21 +0800 +Subject: [PATCH 03/18] Don't allocate the MOK list until there is a node + +--- + src/mokutil.c | 9 +-------- + 1 file changed, 1 insertion(+), 8 deletions(-) + +diff --git a/src/mokutil.c b/src/mokutil.c +index 62690ef..ec476dd 100644 +--- a/src/mokutil.c ++++ b/src/mokutil.c +@@ -177,19 +177,12 @@ signature_size (efi_guid_t hash_type) + static MokListNode* + build_mok_list (void *data, unsigned long data_size, uint32_t *mok_num) + { +- MokListNode *list; ++ MokListNode *list = NULL; + EFI_SIGNATURE_LIST *CertList = data; + EFI_SIGNATURE_DATA *Cert; + unsigned long dbsize = data_size; + unsigned long count = 0; + +- list = malloc(sizeof(MokListNode)); +- +- if (!list) { +- fprintf(stderr, "Unable to allocate MOK list\n"); +- return NULL; +- } +- + while ((dbsize > 0) && (dbsize >= CertList->SignatureListSize)) { + if ((efi_guidcmp (CertList->SignatureType, EfiCertX509Guid) != 0) && + (efi_guidcmp (CertList->SignatureType, EfiHashSha1Guid) != 0) && +-- +1.8.1.4 + + +From befae0e92ea24e35208b07786857d195ce8aa086 Mon Sep 17 00:00:00 2001 +From: Gary Ching-Pang Lin +Date: Tue, 22 Oct 2013 14:40:58 +0800 +Subject: [PATCH 04/18] Skip hashes while exporting MokListRT + +--- + src/mokutil.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/src/mokutil.c b/src/mokutil.c +index ec476dd..04f7655 100644 +--- a/src/mokutil.c ++++ b/src/mokutil.c +@@ -1119,6 +1119,10 @@ export_moks () + /* mode 644 */ + mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; + for (i = 0; i < mok_num; i++) { ++ if (efi_guidcmp (list[i].header->SignatureType, EfiCertX509Guid) != 0) ++ continue; ++ ++ /* Dump X509 certificate to files */ + snprintf (filename, PATH_MAX, "MOK-%04d.der", i+1); + fd = open (filename, O_CREAT | O_WRONLY, mode); + if (fd == -1) { +-- +1.8.1.4 + + +From 9cfc5f93e15e05dabf46a86e4f8e899e32443176 Mon Sep 17 00:00:00 2001 +From: Gary Ching-Pang Lin +Date: Tue, 22 Oct 2013 16:05:33 +0800 +Subject: [PATCH 05/18] Match the hashes in the database + +--- + src/mokutil.c | 162 +++++++++++++++++++++++++++++++++++++++------------------- + 1 file changed, 109 insertions(+), 53 deletions(-) + +diff --git a/src/mokutil.c b/src/mokutil.c +index 04f7655..fa5d668 100644 +--- a/src/mokutil.c ++++ b/src/mokutil.c +@@ -157,19 +157,50 @@ test_and_delete_var (const char *var_name) + return 0; + } + ++static const char* ++efi_hash_to_string (efi_guid_t hash_type) ++{ ++ if (efi_guidcmp (hash_type, EfiHashSha1Guid) == 0) { ++ return "SHA1"; ++ } else if (efi_guidcmp (hash_type, EfiHashSha224Guid) == 0) { ++ return "SHA224"; ++ } else if (efi_guidcmp (hash_type, EfiHashSha256Guid) == 0) { ++ return "SHA256"; ++ } else if (efi_guidcmp (hash_type, EfiHashSha384Guid) == 0) { ++ return "SHA384"; ++ } else if (efi_guidcmp (hash_type, EfiHashSha512Guid) == 0) { ++ return "SHA512"; ++ } ++ ++ return NULL; ++} ++ ++static uint32_t ++efi_hash_size (efi_guid_t hash_type) ++{ ++ if (efi_guidcmp (hash_type, EfiHashSha1Guid) == 0) { ++ return SHA_DIGEST_LENGTH; ++ } else if (efi_guidcmp (hash_type, EfiHashSha224Guid) == 0) { ++ return SHA224_DIGEST_LENGTH; ++ } else if (efi_guidcmp (hash_type, EfiHashSha256Guid) == 0) { ++ return SHA256_DIGEST_LENGTH; ++ } else if (efi_guidcmp (hash_type, EfiHashSha384Guid) == 0) { ++ return SHA384_DIGEST_LENGTH; ++ } else if (efi_guidcmp (hash_type, EfiHashSha512Guid) == 0) { ++ return SHA512_DIGEST_LENGTH; ++ } ++ ++ return 0; ++} ++ + static uint32_t + signature_size (efi_guid_t hash_type) + { +- if (efi_guidcmp (hash_type, EfiHashSha1Guid) == 0) +- return (SHA_DIGEST_LENGTH + sizeof(efi_guid_t)); +- else if (efi_guidcmp (hash_type, EfiHashSha224Guid) == 0) +- return (SHA224_DIGEST_LENGTH + sizeof(efi_guid_t)); +- else if (efi_guidcmp (hash_type, EfiHashSha256Guid) == 0) +- return (SHA256_DIGEST_LENGTH + sizeof(efi_guid_t)); +- else if (efi_guidcmp (hash_type, EfiHashSha384Guid) == 0) +- return (SHA384_DIGEST_LENGTH + sizeof(efi_guid_t)); +- else if (efi_guidcmp (hash_type, EfiHashSha512Guid) == 0) +- return (SHA512_DIGEST_LENGTH + sizeof(efi_guid_t)); ++ uint32_t hash_size; ++ ++ hash_size = efi_hash_size (hash_type); ++ if (hash_size) ++ return (hash_size + sizeof(efi_guid_t)); + + return 0; + } +@@ -293,29 +324,16 @@ print_hash_array (efi_guid_t hash_type, void *hash_array, uint32_t array_size) + return -1; + } + +- if (efi_guidcmp (hash_type, EfiHashSha1Guid) == 0) { +- name = "SHA1"; +- hash_size = SHA_DIGEST_LENGTH; +- } else if (efi_guidcmp (hash_type, EfiHashSha224Guid) == 0) { +- name = "SHA224"; +- hash_size = SHA224_DIGEST_LENGTH; +- } else if (efi_guidcmp (hash_type, EfiHashSha256Guid) == 0) { +- name = "SHA256"; +- hash_size = SHA256_DIGEST_LENGTH; +- } else if (efi_guidcmp (hash_type, EfiHashSha384Guid) == 0) { +- name = "SHA384"; +- hash_size = SHA384_DIGEST_LENGTH; +- } else if (efi_guidcmp (hash_type, EfiHashSha512Guid) == 0) { +- name = "SHA512"; +- hash_size = SHA512_DIGEST_LENGTH; +- } else { ++ name = efi_hash_to_string (hash_type); ++ hash_size = efi_hash_size (hash_type); ++ sig_size = hash_size + sizeof(efi_guid_t); ++ ++ if (!name) { + fprintf (stderr, "unknown hash type\n"); + return -1; + } +- sig_size = hash_size + sizeof(efi_guid_t); + + printf (" [%s]\n", name); +- + remain = array_size; + hash = (uint8_t *)hash_array; + +@@ -829,36 +847,78 @@ is_valid_cert (void *cert, uint32_t cert_size) + } + + static int +-is_duplicate (const void *cert, const uint32_t cert_size, const char *db_name, +- efi_guid_t guid) ++match_hash_array (efi_guid_t hash_type, const void *hash, ++ const void *hash_array, const uint32_t array_size) ++{ ++ uint32_t hash_size, hash_count; ++ uint32_t sig_size; ++ int i; ++ void *ptr; ++ ++ hash_size = efi_hash_size (hash_type); ++ if (!hash_size) ++ return 0; ++ ++ sig_size = hash_size + sizeof(efi_guid_t); ++ if ((array_size % sig_size) != 0) { ++ fprintf (stderr, "invalid hash array size\n"); ++ return 0; ++ } ++ ++ ptr = (void *)hash_array; ++ hash_count = array_size / sig_size; ++ for (i = 0; i < hash_count; i++) { ++ ptr += sizeof(efi_guid_t); ++ if (memcmp (ptr, hash, hash_size) == 0) ++ return 1; ++ ptr += hash_size; ++ } ++ ++ return 0; ++} ++ ++static int ++is_duplicate (efi_guid_t type, const void *data, const uint32_t data_size, ++ efi_guid_t vendor, const char *db_name) + { + efi_variable_t var; +- uint32_t mok_num; ++ uint32_t node_num; + MokListNode *list; + int i, ret = 0; + +- if (!cert || cert_size == 0 || !db_name) ++ if (!data || data_size == 0 || !db_name) + return 0; + + memset (&var, 0, sizeof(var)); + var.VariableName = db_name; +- var.VendorGuid = guid; ++ var.VendorGuid = vendor; + + if (read_variable (&var) != EFI_SUCCESS) + return 0; + +- list = build_mok_list (var.Data, var.DataSize, &mok_num); ++ list = build_mok_list (var.Data, var.DataSize, &node_num); + if (list == NULL) { + goto done; + } + +- for (i = 0; i < mok_num; i++) { +- if (list[i].mok_size != cert_size) ++ for (i = 0; i < node_num; i++) { ++ if (efi_guidcmp (list[i].header->SignatureType, type) != 0) + continue; + +- if (memcmp (list[i].mok, cert, cert_size) == 0) { +- ret = 1; +- break; ++ if (efi_guidcmp (type, EfiCertX509Guid) == 0) { ++ if (list[i].mok_size != data_size) ++ continue; ++ ++ if (memcmp (list[i].mok, data, data_size) == 0) { ++ ret = 1; ++ break; ++ } ++ } else { ++ if (match_hash_array (type, data, list[i].mok, ++ list[i].mok_size)) { ++ ret = 1; ++ break; ++ } + } + } + +@@ -870,19 +930,19 @@ done: + } + + static int +-is_valid_request (void *mok, uint32_t mok_size, uint8_t import) ++is_valid_request (efi_guid_t type, void *mok, uint32_t mok_size, uint8_t import) + { + 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)) { ++ if (is_duplicate (type, mok, mok_size, EFI_GLOBAL_VARIABLE, "PK") || ++ is_duplicate (type, mok, mok_size, EFI_GLOBAL_VARIABLE, "KEK") || ++ is_duplicate (type, mok, mok_size, EFI_IMAGE_SECURITY_DATABASE_GUID, "db") || ++ is_duplicate (type, mok, mok_size, SHIM_LOCK_GUID, "MokListRT") || ++ is_duplicate (type, mok, mok_size, SHIM_LOCK_GUID, "MokNew")) { + return 0; + } + } else { +- if (!is_duplicate (mok, mok_size, "MokListRT", SHIM_LOCK_GUID) || +- is_duplicate (mok, mok_size, "MokDel", SHIM_LOCK_GUID)) { ++ if (!is_duplicate (type, mok, mok_size, SHIM_LOCK_GUID, "MokListRT") || ++ is_duplicate (type, mok, mok_size, SHIM_LOCK_GUID, "MokDel")) { + return 0; + } + } +@@ -1008,7 +1068,7 @@ issue_mok_request (char **files, uint32_t total, uint8_t import, + files[i]); + } + +- if (is_valid_request (ptr, sizes[i], import)) { ++ if (is_valid_request (EfiCertX509Guid, ptr, sizes[i], import)) { + ptr += sizes[i]; + real_size += sizes[i] + sizeof(EFI_SIGNATURE_LIST) + sizeof(efi_guid_t); + } else if (in_pending_request (ptr, sizes[i], import)) { +@@ -1359,11 +1419,7 @@ test_key (const char *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)) { ++ if (!is_valid_request (EfiCertX509Guid, key, read_size, 1)) { + printf ("%s is not enrolled\n", key_file); + ret = 0; + } else { +-- +1.8.1.4 + + +From 9ec6f6836a386d527cf62d6583c3ea5e394f62a5 Mon Sep 17 00:00:00 2001 +From: Gary Ching-Pang Lin +Date: Tue, 22 Oct 2013 18:01:11 +0800 +Subject: [PATCH 06/18] Support MOK blacklist + +--- + src/mokutil.c | 223 ++++++++++++++++++++++++++++++++++++++++++++++++++-------- + 1 file changed, 195 insertions(+), 28 deletions(-) + +diff --git a/src/mokutil.c b/src/mokutil.c +index fa5d668..f10e6e8 100644 +--- a/src/mokutil.c ++++ b/src/mokutil.c +@@ -79,6 +79,7 @@ EFI_GUID (0x605dab50, 0xe046, 0x4300, 0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, + #define SIMPLE_HASH (1 << 17) + #define IGNORE_DB (1 << 18) + #define USE_DB (1 << 19) ++#define MOKX (1 << 20) + + #define DEFAULT_CRYPT_METHOD SHA512_BASED + #define DEFAULT_SALT_SIZE SHA512_SALT_MAX +@@ -86,6 +87,13 @@ EFI_GUID (0x605dab50, 0xe046, 0x4300, 0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, + + static int use_simple_hash; + ++typedef enum { ++ DELETE_MOK = 0, ++ ENROLL_MOK, ++ DELETE_BLACKLIST, ++ ENROLL_BLACKLIST ++} MokRequest; ++ + typedef struct { + EFI_SIGNATURE_LIST *header; + uint32_t mok_size; +@@ -135,6 +143,10 @@ print_help () + printf (" --simple-hash\t\t\t\tUse the old password hash method\n"); + printf (" \t\t\t\t(For --import, --delete, --password,\n"); + printf (" \t\t\t\t --clear-password and --reset)\n"); ++ printf (" --mokx\t\t\t\tManipulate the MOK blacklist\n"); ++ printf (" \t\t\t\t(For --list-enrolled, --list-new,\n"); ++ printf (" \t\t\t\t --list-delete, --import, --delete,\n"); ++ printf (" \t\t\t\t --revoke-import, and --revoke-delete)\n"); + } + + static int +@@ -724,7 +736,7 @@ get_password_from_shadow (pw_crypt_t *pw_crypt) + } + + static int +-update_request (void *new_list, int list_len, uint8_t import, ++update_request (void *new_list, int list_len, MokRequest req, + const char *hash_file, const int root_pw) + { + efi_variable_t var; +@@ -739,12 +751,25 @@ update_request (void *new_list, int list_len, uint8_t import, + bzero (&pw_crypt, sizeof(pw_crypt_t)); + pw_crypt.method = DEFAULT_CRYPT_METHOD; + +- if (import) { ++ switch (req) { ++ case ENROLL_MOK: + req_name = "MokNew"; + auth_name = "MokAuth"; +- } else { ++ break; ++ case DELETE_MOK: + req_name = "MokDel"; + auth_name = "MokDelAuth"; ++ break; ++ case ENROLL_BLACKLIST: ++ req_name = "MokXNew"; ++ auth_name = "MokXAuth"; ++ break; ++ case DELETE_BLACKLIST: ++ req_name = "MokXDel"; ++ auth_name = "MokXDelAuth"; ++ break; ++ default: ++ return -1; + } + + if (hash_file) { +@@ -776,7 +801,7 @@ update_request (void *new_list, int list_len, uint8_t import, + } + + if (new_list) { +- /* Write MokNew*/ ++ /* Write MokNew, MokDel, MokXNew, or MokXDel*/ + var.Data = new_list; + var.DataSize = list_len; + var.VariableName = req_name; +@@ -787,15 +812,27 @@ update_request (void *new_list, int list_len, uint8_t import, + | EFI_VARIABLE_RUNTIME_ACCESS; + + if (edit_variable (&var) != EFI_SUCCESS) { +- fprintf (stderr, "Failed to %s keys\n", +- import ? "enroll new" : "delete"); ++ switch (req) { ++ case ENROLL_MOK: ++ fprintf (stderr, "Failed to enroll new keys\n"); ++ break; ++ case ENROLL_BLACKLIST: ++ fprintf (stderr, "Failed to enroll blacklist\n"); ++ break; ++ case DELETE_MOK: ++ fprintf (stderr, "Failed to delete keys\n"); ++ break; ++ case DELETE_BLACKLIST: ++ fprintf (stderr, "Failed to delete blacklist\n"); ++ break; ++ } + goto error; + } + } else { + test_and_delete_var (req_name); + } + +- /* Write MokAuth or MokDelAuth */ ++ /* Write MokAuth, MokDelAuth, MokXAuth, or MokXDelAuth */ + if (!use_simple_hash) { + var.Data = (void *)&pw_crypt; + var.DataSize = PASSWORD_CRYPT_SIZE; +@@ -930,9 +967,10 @@ done: + } + + static int +-is_valid_request (efi_guid_t type, void *mok, uint32_t mok_size, uint8_t import) ++is_valid_request (efi_guid_t type, void *mok, uint32_t mok_size, MokRequest req) + { +- if (import) { ++ switch (req) { ++ case ENROLL_MOK: + if (is_duplicate (type, mok, mok_size, EFI_GLOBAL_VARIABLE, "PK") || + is_duplicate (type, mok, mok_size, EFI_GLOBAL_VARIABLE, "KEK") || + is_duplicate (type, mok, mok_size, EFI_IMAGE_SECURITY_DATABASE_GUID, "db") || +@@ -940,29 +978,63 @@ is_valid_request (efi_guid_t type, void *mok, uint32_t mok_size, uint8_t import) + is_duplicate (type, mok, mok_size, SHIM_LOCK_GUID, "MokNew")) { + return 0; + } +- } else { ++ break; ++ case DELETE_MOK: + if (!is_duplicate (type, mok, mok_size, SHIM_LOCK_GUID, "MokListRT") || + is_duplicate (type, mok, mok_size, SHIM_LOCK_GUID, "MokDel")) { + return 0; + } ++ break; ++ case ENROLL_BLACKLIST: ++ if (is_duplicate (type, mok, mok_size, SHIM_LOCK_GUID, "MokListXRT") || ++ is_duplicate (type, mok, mok_size, SHIM_LOCK_GUID, "MokXNew")) { ++ return 0; ++ } ++ break; ++ case DELETE_BLACKLIST: ++ if (!is_duplicate (type, mok, mok_size, SHIM_LOCK_GUID, "MokListXRT") || ++ is_duplicate (type, mok, mok_size, SHIM_LOCK_GUID, "MokXDel")) { ++ return 0; ++ } ++ break; + } + + return 1; + } + + static int +-in_pending_request (void *mok, uint32_t mok_size, uint8_t import) ++in_pending_request (void *mok, uint32_t mok_size, MokRequest req) + { + efi_variable_t authvar; +- const char *var_name = import ? "MokDel" : "MokNew"; ++ const char *var_name; + + if (!mok || mok_size == 0) + return 0; + + memset (&authvar, 0, sizeof(authvar)); +- authvar.VariableName = import ? "MokDelAuth" : "MokAuth"; + authvar.VendorGuid = SHIM_LOCK_GUID; + ++ switch (req) { ++ case ENROLL_MOK: ++ var_name = "MokDel"; ++ authvar.VariableName = "MokDelAuth"; ++ break; ++ case DELETE_MOK: ++ var_name = "MokNew"; ++ authvar.VariableName = "MokAuth"; ++ break; ++ case ENROLL_BLACKLIST: ++ var_name = "MokXDel"; ++ authvar.VariableName = "MokXDelAuth"; ++ break; ++ case DELETE_BLACKLIST: ++ var_name = "MokXNew"; ++ authvar.VariableName = "MokXAuth"; ++ break; ++ default: ++ return 0; ++ } ++ + if (read_variable (&authvar) != EFI_SUCCESS) { + return 0; + } +@@ -979,7 +1051,7 @@ in_pending_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, MokRequest req, + const char *hash_file, const int root_pw) + { + efi_variable_t old_req; +@@ -999,7 +1071,22 @@ issue_mok_request (char **files, uint32_t total, uint8_t import, + if (!files) + return -1; + +- req_name = import ? "MokNew" : "MokDel"; ++ switch (req) { ++ case ENROLL_MOK: ++ req_name = "MokNew"; ++ break; ++ case DELETE_MOK: ++ req_name = "MokDel"; ++ break; ++ case ENROLL_BLACKLIST: ++ req_name = "MokXNew"; ++ break; ++ case DELETE_BLACKLIST: ++ req_name = "MokXDel"; ++ break; ++ default: ++ return -1; ++ } + + sizes = malloc (total * sizeof(uint32_t)); + +@@ -1068,11 +1155,29 @@ issue_mok_request (char **files, uint32_t total, uint8_t import, + files[i]); + } + +- if (is_valid_request (EfiCertX509Guid, ptr, sizes[i], import)) { ++ if (is_valid_request (EfiCertX509Guid, ptr, sizes[i], req)) { + ptr += sizes[i]; + real_size += sizes[i] + sizeof(EFI_SIGNATURE_LIST) + sizeof(efi_guid_t); +- } else if (in_pending_request (ptr, sizes[i], import)) { +- printf ("Removed %s from %s\n", files[i], import ? "MokDel" : "MokNew"); ++ } else if (in_pending_request (ptr, sizes[i], req)) { ++ const char *pending; ++ switch (req) { ++ case ENROLL_MOK: ++ pending = "MokDel"; ++ break; ++ case DELETE_MOK: ++ pending = "MokNew"; ++ break; ++ case ENROLL_BLACKLIST: ++ pending = "MokXDel"; ++ break; ++ case DELETE_BLACKLIST: ++ pending = "MokXNew"; ++ break; ++ default: ++ pending = ""; ++ break; ++ } ++ printf ("Removed %s from %s\n", files[i], pending); + + ptr -= sizeof(EFI_SIGNATURE_LIST) + sizeof(efi_guid_t); + } else { +@@ -1095,7 +1200,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, hash_file, root_pw) < 0) { ++ if (update_request (new_list, real_size, req, hash_file, root_pw) < 0) { + goto error; + } + +@@ -1115,29 +1220,58 @@ static int + import_moks (char **files, uint32_t total, const char *hash_file, + const int root_pw) + { +- return issue_mok_request (files, total, 1, hash_file, root_pw); ++ return issue_mok_request (files, total, ENROLL_MOK, hash_file, root_pw); + } + + static int + delete_moks (char **files, uint32_t total, const char *hash_file, + const int root_pw) + { +- return issue_mok_request (files, total, 0, hash_file, root_pw); ++ return issue_mok_request (files, total, DELETE_MOK, hash_file, root_pw); + } + + static int +-revoke_request (uint8_t import) ++import_blacklist (char **files, uint32_t total, const char *hash_file, ++ const int root_pw) + { +- if (import == 1) { ++ return issue_mok_request (files, total, ENROLL_BLACKLIST, hash_file, root_pw); ++} ++ ++static int ++delete_blacklist (char **files, uint32_t total, const char *hash_file, ++ const int root_pw) ++{ ++ return issue_mok_request (files, total, DELETE_BLACKLIST, hash_file, root_pw); ++} ++ ++static int ++revoke_request (MokRequest req) ++{ ++ switch (req) { ++ case ENROLL_MOK: + if (test_and_delete_var ("MokNew") < 0) + return -1; + if (test_and_delete_var ("MokAuth") < 0) + return -1; +- } else { ++ break; ++ case DELETE_MOK: + if (test_and_delete_var ("MokDel") < 0) + return -1; + if (test_and_delete_var ("MokDelAuth") < 0) + return -1; ++ break; ++ case ENROLL_BLACKLIST: ++ if (test_and_delete_var ("MokXNew") < 0) ++ return -1; ++ if (test_and_delete_var ("MokXAuth") < 0) ++ return -1; ++ break; ++ case DELETE_BLACKLIST: ++ if (test_and_delete_var ("MokXDel") < 0) ++ return -1; ++ if (test_and_delete_var ("MokXDelAuth") < 0) ++ return -1; ++ break; + } + + return 0; +@@ -1419,7 +1553,7 @@ test_key (const char *key_file) + goto error; + } + +- if (!is_valid_request (EfiCertX509Guid, key, read_size, 1)) { ++ if (!is_valid_request (EfiCertX509Guid, key, read_size, ENROLL_MOK)) { + printf ("%s is not enrolled\n", key_file); + ret = 0; + } else { +@@ -1440,7 +1574,7 @@ error: + static int + reset_moks (const char *hash_file, const int root_pw) + { +- if (update_request (NULL, 0, 1, hash_file, root_pw)) { ++ if (update_request (NULL, 0, ENROLL_MOK, hash_file, root_pw)) { + fprintf (stderr, "Failed to issue a reset request\n"); + return -1; + } +@@ -1539,6 +1673,7 @@ main (int argc, char *argv[]) + {"simple-hash", no_argument, 0, 's'}, + {"ignore-db", no_argument, 0, 0 }, + {"use-db", no_argument, 0, 0 }, ++ {"mokx", no_argument, 0, 0 }, + {0, 0, 0, 0} + }; + +@@ -1574,6 +1709,8 @@ main (int argc, char *argv[]) + command |= IGNORE_DB; + } else if (strcmp (option, "use-db") == 0) { + command |= USE_DB; ++ } else if (strcmp (option, "mokx") == 0) { ++ command |= MOKX; + } + break; + case 'd': +@@ -1683,10 +1820,10 @@ main (int argc, char *argv[]) + ret = delete_moks (files, total, hash_file, 0); + break; + case REVOKE_IMPORT: +- ret = revoke_request (1); ++ ret = revoke_request (ENROLL_MOK); + break; + case REVOKE_DELETE: +- ret = revoke_request (0); ++ ret = revoke_request (DELETE_MOK); + break; + case EXPORT: + ret = export_moks (); +@@ -1730,6 +1867,36 @@ main (int argc, char *argv[]) + case USE_DB: + ret = enable_db (); + break; ++ case LIST_ENROLLED | MOKX: ++ ret = list_keys_in_var ("MokListXRT"); ++ break; ++ case LIST_NEW | MOKX: ++ ret = list_keys_in_var ("MokXNew"); ++ break; ++ case LIST_DELETE | MOKX: ++ ret = list_keys_in_var ("MokXDel"); ++ break; ++ case IMPORT | MOKX: ++ case IMPORT | SIMPLE_HASH | MOKX: ++ if (use_root_pw) ++ ret = import_blacklist (files, total, NULL, 1); ++ else ++ ret = import_blacklist (files, total, hash_file, 0); ++ break; ++ case DELETE | MOKX: ++ case DELETE | SIMPLE_HASH | MOKX: ++ if (use_root_pw) ++ ret = delete_blacklist (files, total, NULL, 1); ++ else ++ ret = delete_blacklist (files, total, hash_file, 0); ++ break; ++ case REVOKE_IMPORT | MOKX: ++ ret = revoke_request (ENROLL_BLACKLIST); ++ break; ++ case REVOKE_DELETE | MOKX: ++ ret = revoke_request (DELETE_BLACKLIST); ++ break; ++ + default: + print_help (); + break; +-- +1.8.1.4 + + +From 73c2a558b6fa9fb42526d4d2ac5c7db40d402c8f Mon Sep 17 00:00:00 2001 +From: Gary Ching-Pang Lin +Date: Wed, 23 Oct 2013 10:41:58 +0800 +Subject: [PATCH 07/18] Fix the memory leakage + +--- + src/mokutil.c | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/src/mokutil.c b/src/mokutil.c +index f10e6e8..bcc12ca 100644 +--- a/src/mokutil.c ++++ b/src/mokutil.c +@@ -1746,10 +1746,18 @@ main (int argc, char *argv[]) + + break; + case 'f': ++ if (hash_file) { ++ command |= HELP; ++ break; ++ } + hash_file = strdup (optarg); + + break; + case 'g': ++ if (input_pw) { ++ command |= HELP; ++ break; ++ } + if (optarg) + input_pw = strdup (optarg); + +@@ -1765,6 +1773,10 @@ main (int argc, char *argv[]) + use_root_pw = 1; + break; + case 't': ++ if (key_file) { ++ command |= HELP; ++ break; ++ } + key_file = strdup (optarg); + if (key_file == NULL) { + fprintf (stderr, "Could not allocate space: %m\n"); +-- +1.8.1.4 + + +From 62162fc5a5c33c987e4b8106a9e98c3abf8288ae Mon Sep 17 00:00:00 2001 +From: Gary Ching-Pang Lin +Date: Wed, 23 Oct 2013 17:29:53 +0800 +Subject: [PATCH 08/18] Support import and delete a hash + +--- + src/mokutil.c | 424 ++++++++++++++++++++++++++++++++++++++++++++-------------- + 1 file changed, 322 insertions(+), 102 deletions(-) + +diff --git a/src/mokutil.c b/src/mokutil.c +index bcc12ca..b8edf74 100644 +--- a/src/mokutil.c ++++ b/src/mokutil.c +@@ -80,6 +80,8 @@ EFI_GUID (0x605dab50, 0xe046, 0x4300, 0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, + #define IGNORE_DB (1 << 18) + #define USE_DB (1 << 19) + #define MOKX (1 << 20) ++#define IMPORT_HASH (1 << 21) ++#define DELETE_HASH (1 << 22) + + #define DEFAULT_CRYPT_METHOD SHA512_BASED + #define DEFAULT_SALT_SIZE SHA512_SALT_MAX +@@ -132,21 +134,27 @@ print_help () + printf (" --generate-hash[=password]\t\tGenerate the password hash\n"); + printf (" --ignore-db\t\t\t\tIgnore DB for validation\n"); + printf (" --use-db\t\t\t\tUse DB for validation\n"); ++ printf (" --import-hash \t\t\tImport a hash\n"); ++ printf (" --delete-hash \t\t\tDelete a specific hash\n"); + printf ("\n"); + printf ("Supplimentary Options:\n"); + printf (" --hash-file \t\tUse the specific password hash\n"); + printf (" \t\t(For --import, --delete, --password,\n"); +- printf (" \t\t and --reset)\n"); ++ printf (" \t\t --reset, --import-hash,\n"); ++ printf (" \t\t and --delete-hash)\n"); + printf (" --root-pw\t\t\t\tUse the root password\n"); + printf (" \t\t\t\t(For --import, --delete, --password,\n"); +- printf (" \t\t\t\t and --reset)\n"); ++ printf (" \t\t\t\t --reset, --import-hash,\n"); ++ printf (" \t\t\t\t and --delete-hash)\n"); + printf (" --simple-hash\t\t\t\tUse the old password hash method\n"); + printf (" \t\t\t\t(For --import, --delete, --password,\n"); +- printf (" \t\t\t\t --clear-password and --reset)\n"); ++ printf (" \t\t\t\t --clear-password, --reset,\n"); ++ printf (" \t\t\t\t --import-hash, and --delete-hash)\n"); + printf (" --mokx\t\t\t\tManipulate the MOK blacklist\n"); + printf (" \t\t\t\t(For --list-enrolled, --list-new,\n"); + printf (" \t\t\t\t --list-delete, --import, --delete,\n"); +- printf (" \t\t\t\t --revoke-import, and --revoke-delete)\n"); ++ printf (" \t\t\t\t --revoke-import, --revoke-delete,\n"); ++ printf (" \t\t\t\t --import-hash, and --delete-hash)\n"); + } + + static int +@@ -396,17 +404,50 @@ list_keys (efi_variable_t *var) + return 0; + } + ++/* match the hash in the hash array and return the index if matched */ + static int +-delete_key_from_list (void *mok, uint32_t mok_size, +- const char *var_name, efi_guid_t guid) ++match_hash_array (efi_guid_t hash_type, const void *hash, ++ const void *hash_array, const uint32_t array_size) ++{ ++ uint32_t hash_size, hash_count; ++ uint32_t sig_size; ++ int i; ++ void *ptr; ++ ++ hash_size = efi_hash_size (hash_type); ++ if (!hash_size) ++ return -1; ++ ++ sig_size = hash_size + sizeof(efi_guid_t); ++ if ((array_size % sig_size) != 0) { ++ fprintf (stderr, "invalid hash array size\n"); ++ return -1; ++ } ++ ++ ptr = (void *)hash_array; ++ hash_count = array_size / sig_size; ++ for (i = 0; i < hash_count; i++) { ++ ptr += sizeof(efi_guid_t); ++ if (memcmp (ptr, hash, hash_size) == 0) ++ return i; ++ ptr += hash_size; ++ } ++ ++ return -1; ++} ++ ++static int ++delete_data_from_list (efi_guid_t type, void *data, uint32_t data_size, ++ const char *var_name, efi_guid_t guid) + { + efi_variable_t var; + MokListNode *list; + uint32_t mok_num, total, remain; +- void *ptr, *data = NULL; ++ void *end, *start = NULL; + int i, del_ind, ret = 0; ++ uint32_t sig_list_size, sig_size; + +- if (!var_name || !mok || mok_size == 0) ++ if (!var_name || !data || data_size == 0) + return 0; + + memset (&var, 0, sizeof(var)); +@@ -422,30 +463,56 @@ delete_key_from_list (void *mok, uint32_t mok_size, + if (list == NULL) + goto done; + ++ remain = total; + for (i = 0; i < mok_num; i++) { +- if (list[i].mok_size != mok_size) ++ remain -= list[i].header->SignatureListSize; ++ if (efi_guidcmp (list[i].header->SignatureType, type) != 0) + continue; + +- if (memcmp (list[i].mok, mok, mok_size) == 0) { +- /* Remove this key */ +- del_ind = i; +- data = (void *)list[i].header; +- ptr = data + list[i].header->SignatureListSize; +- total -= list[i].header->SignatureListSize; ++ sig_list_size = list[i].header->SignatureListSize; ++ ++ if (efi_guidcmp (type, EfiCertX509Guid) == 0) { ++ if (list[i].mok_size != data_size) ++ continue; ++ ++ if (memcmp (list[i].mok, data, data_size) == 0) { ++ /* Remove this key */ ++ start = (void *)list[i].header; ++ end = start + sig_list_size; ++ total -= sig_list_size; ++ break; ++ } ++ } else { ++ del_ind = match_hash_array (type, data, list[i].mok, ++ list[i].mok_size); ++ if (del_ind < 0) ++ continue; ++ ++ start = (void *)list[i].header; ++ sig_size = signature_size (type); ++ if (sig_list_size == (sizeof(EFI_SIGNATURE_LIST) + sig_size)) { ++ /* Only one hash in the list */ ++ end = start + sig_list_size; ++ total -= sig_list_size; ++ } else { ++ /* More than one hash in the list */ ++ start += sizeof(EFI_SIGNATURE_LIST) + sig_size * del_ind; ++ end = start + sig_size; ++ total -= sig_size; ++ remain += sig_list_size - sizeof(EFI_SIGNATURE_LIST) - ++ (del_ind + 1) * sig_size; ++ } + break; + } + } + +- /* the key is not in this list */ +- if (data == NULL) ++ /* the key or hash is not in this list */ ++ if (start == NULL) + return 0; + +- /* Move the rest of the keys */ +- remain = 0; +- for (i = del_ind + 1; i < mok_num; i++) +- remain += list[i].header->SignatureListSize; ++ /* remove the key or hash */ + if (remain > 0) +- memmove (data, ptr, remain); ++ memmove (start, end, remain); + + var.DataSize = total; + var.Attributes = EFI_VARIABLE_NON_VOLATILE +@@ -459,7 +526,8 @@ delete_key_from_list (void *mok, uint32_t mok_size, + + ret = 1; + done: +- free (list); ++ if (list) ++ free (list); + free (var.Data); + + return ret; +@@ -884,37 +952,6 @@ is_valid_cert (void *cert, uint32_t cert_size) + } + + static int +-match_hash_array (efi_guid_t hash_type, const void *hash, +- const void *hash_array, const uint32_t array_size) +-{ +- uint32_t hash_size, hash_count; +- uint32_t sig_size; +- int i; +- void *ptr; +- +- hash_size = efi_hash_size (hash_type); +- if (!hash_size) +- return 0; +- +- sig_size = hash_size + sizeof(efi_guid_t); +- if ((array_size % sig_size) != 0) { +- fprintf (stderr, "invalid hash array size\n"); +- return 0; +- } +- +- ptr = (void *)hash_array; +- hash_count = array_size / sig_size; +- for (i = 0; i < hash_count; i++) { +- ptr += sizeof(efi_guid_t); +- if (memcmp (ptr, hash, hash_size) == 0) +- return 1; +- ptr += hash_size; +- } +- +- return 0; +-} +- +-static int + is_duplicate (efi_guid_t type, const void *data, const uint32_t data_size, + efi_guid_t vendor, const char *db_name) + { +@@ -952,7 +989,7 @@ is_duplicate (efi_guid_t type, const void *data, const uint32_t data_size, + } + } else { + if (match_hash_array (type, data, list[i].mok, +- list[i].mok_size)) { ++ list[i].mok_size) >= 0) { + ret = 1; + break; + } +@@ -960,7 +997,8 @@ is_duplicate (efi_guid_t type, const void *data, const uint32_t data_size, + } + + done: +- free (list); ++ if (list) ++ free (list); + free (var.Data); + + return ret; +@@ -1003,12 +1041,13 @@ is_valid_request (efi_guid_t type, void *mok, uint32_t mok_size, MokRequest req) + } + + static int +-in_pending_request (void *mok, uint32_t mok_size, MokRequest req) ++in_pending_request (efi_guid_t type, void *data, uint32_t data_size, ++ MokRequest req) + { + efi_variable_t authvar; + const char *var_name; + +- if (!mok || mok_size == 0) ++ if (!data || data_size == 0) + return 0; + + memset (&authvar, 0, sizeof(authvar)); +@@ -1044,8 +1083,9 @@ in_pending_request (void *mok, uint32_t mok_size, MokRequest req) + if (authvar.DataSize == SHA256_DIGEST_LENGTH) + return 0; + +- if (delete_key_from_list (mok, mok_size, var_name, SHIM_LOCK_GUID)) +- return 1; ++ if (delete_data_from_list (type, data, data_size, var_name, ++ SHIM_LOCK_GUID)) ++ return 1; + + return 0; + } +@@ -1158,7 +1198,7 @@ issue_mok_request (char **files, uint32_t total, MokRequest req, + if (is_valid_request (EfiCertX509Guid, ptr, sizes[i], req)) { + ptr += sizes[i]; + real_size += sizes[i] + sizeof(EFI_SIGNATURE_LIST) + sizeof(efi_guid_t); +- } else if (in_pending_request (ptr, sizes[i], req)) { ++ } else if (in_pending_request (EfiCertX509Guid, ptr, sizes[i], req)) { + const char *pending; + switch (req) { + case ENROLL_MOK: +@@ -1217,31 +1257,186 @@ error: + } + + static int +-import_moks (char **files, uint32_t total, const char *hash_file, +- const int root_pw) ++identify_hash_type (const char *hash_str, efi_guid_t *type) + { +- return issue_mok_request (files, total, ENROLL_MOK, hash_file, root_pw); +-} ++ int len = strlen (hash_str); ++ int hash_size; ++ int i; + +-static int +-delete_moks (char **files, uint32_t total, const char *hash_file, +- const int root_pw) +-{ +- return issue_mok_request (files, total, DELETE_MOK, hash_file, root_pw); ++ for (i = 0; i < len; i++) { ++ if ((hash_str[i] > '9' || hash_str[i] < '0') && ++ (hash_str[i] > 'f' || hash_str[i] < 'a') && ++ (hash_str[i] > 'F' || hash_str[i] < 'A')) ++ return -1; ++ } ++ ++ switch (len) { ++ case SHA_DIGEST_LENGTH*2: ++ *type = EfiHashSha1Guid; ++ hash_size = SHA_DIGEST_LENGTH; ++ break; ++ case SHA224_DIGEST_LENGTH*2: ++ *type = EfiHashSha224Guid; ++ hash_size = SHA224_DIGEST_LENGTH; ++ break; ++ case SHA256_DIGEST_LENGTH*2: ++ *type = EfiHashSha256Guid; ++ hash_size = SHA256_DIGEST_LENGTH; ++ break; ++ case SHA384_DIGEST_LENGTH*2: ++ *type = EfiHashSha384Guid; ++ hash_size = SHA384_DIGEST_LENGTH; ++ break; ++ case SHA512_DIGEST_LENGTH*2: ++ *type = EfiHashSha512Guid; ++ hash_size = SHA512_DIGEST_LENGTH; ++ break; ++ default: ++ return -1; ++ } ++ ++ return hash_size; + } + + static int +-import_blacklist (char **files, uint32_t total, const char *hash_file, +- const int root_pw) ++hex_str_to_binary (const char *hex_str, uint8_t *array, int len) + { +- return issue_mok_request (files, total, ENROLL_BLACKLIST, hash_file, root_pw); ++ char *pos; ++ int i; ++ ++ if (!hex_str || !array) ++ return -1; ++ ++ pos = (char *)hex_str; ++ for (i = 0; i < len; i++) { ++ sscanf (pos, "%2hhx", &array[i]); ++ pos += 2; ++ } ++ ++ return 0; + } + + static int +-delete_blacklist (char **files, uint32_t total, const char *hash_file, +- const int root_pw) ++issue_hash_request (const char *hash_str, MokRequest req, ++ const char *hash_file, const int root_pw) + { +- return issue_mok_request (files, total, DELETE_BLACKLIST, hash_file, root_pw); ++ efi_variable_t old_req; ++ const char *req_name; ++ void *new_list = NULL; ++ void *ptr; ++ unsigned long list_size = 0; ++ uint32_t sig_list_size; ++ int ret = -1; ++ EFI_SIGNATURE_LIST *CertList; ++ EFI_SIGNATURE_DATA *CertData; ++ efi_guid_t hash_type; ++ uint8_t db_hash[SHA512_DIGEST_LENGTH]; ++ int hash_size; ++ uint8_t valid = 0; ++ ++ if (!hash_str) ++ return -1; ++ ++ hash_size = identify_hash_type (hash_str, &hash_type); ++ if (hash_size < 0) ++ return -1; ++ ++ if (hex_str_to_binary (hash_str, db_hash, hash_size) < 0) ++ return -1; ++ ++ switch (req) { ++ case ENROLL_MOK: ++ req_name = "MokNew"; ++ break; ++ case DELETE_MOK: ++ req_name = "MokDel"; ++ break; ++ case ENROLL_BLACKLIST: ++ req_name = "MokXNew"; ++ break; ++ case DELETE_BLACKLIST: ++ req_name = "MokXDel"; ++ break; ++ default: ++ return -1; ++ } ++ ++ sig_list_size = sizeof(EFI_SIGNATURE_LIST) + sizeof(efi_guid_t) + hash_size; ++ list_size += sig_list_size; ++ ++ 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 %s\n", req_name); ++ goto error; ++ } ++ ptr = new_list; ++ ++ CertList = ptr; ++ CertList->SignatureType = hash_type; ++ CertList->SignatureListSize = sig_list_size; ++ CertList->SignatureHeaderSize = 0; ++ CertList->SignatureSize = hash_size + sizeof(efi_guid_t); ++ ++ CertData = (EFI_SIGNATURE_DATA *)(((uint8_t *)ptr) + ++ sizeof(EFI_SIGNATURE_LIST)); ++ CertData->SignatureOwner = SHIM_LOCK_GUID; ++ memcpy (CertData->SignatureData, db_hash, hash_size); ++ ++ if (is_valid_request (hash_type, db_hash, hash_size, req)) { ++ valid = 1; ++ } else if (in_pending_request (hash_type, db_hash, hash_size, req)) { ++ const char *pending; ++ switch (req) { ++ case ENROLL_MOK: ++ pending = "MokDel"; ++ break; ++ case DELETE_MOK: ++ pending = "MokNew"; ++ break; ++ case ENROLL_BLACKLIST: ++ pending = "MokXDel"; ++ break; ++ case DELETE_BLACKLIST: ++ pending = "MokXNew"; ++ break; ++ default: ++ pending = ""; ++ break; ++ } ++ printf ("Removed hash from %s\n", pending); ++ } else { ++ printf ("Skip hash\n"); ++ } ++ ++ if (!valid) { ++ ret = 0; ++ goto error; ++ } ++ ++ /* append the keys to the previous request */ ++ if (old_req.Data) { ++ memcpy (new_list + sig_list_size, old_req.Data, old_req.DataSize); ++ } ++ ++ if (update_request (new_list, list_size, req, hash_file, root_pw) < 0) { ++ goto error; ++ } ++ ++ ret = 0; ++error: ++ if (old_req.Data) ++ free (old_req.Data); ++ if (new_list) ++ free (new_list); ++ ++ return ret; + } + + static int +@@ -1641,6 +1836,7 @@ main (int argc, char *argv[]) + char *key_file = NULL; + char *hash_file = NULL; + char *input_pw = NULL; ++ char *hash_str = NULL; + const char *option; + int c, i, f_ind, total = 0; + unsigned int command = 0; +@@ -1674,6 +1870,8 @@ main (int argc, char *argv[]) + {"ignore-db", no_argument, 0, 0 }, + {"use-db", no_argument, 0, 0 }, + {"mokx", no_argument, 0, 0 }, ++ {"import-hash", required_argument, 0, 0 }, ++ {"delete-hash", required_argument, 0, 0 }, + {0, 0, 0, 0} + }; + +@@ -1711,6 +1909,20 @@ main (int argc, char *argv[]) + command |= USE_DB; + } else if (strcmp (option, "mokx") == 0) { + command |= MOKX; ++ } else if (strcmp (option, "import-hash") == 0) { ++ command |= IMPORT_HASH; ++ if (hash_str) { ++ command |= HELP; ++ break; ++ } ++ hash_str = strdup (optarg); ++ } else if (strcmp (option, "delete-hash") == 0) { ++ command |= DELETE_HASH; ++ if (hash_str) { ++ command |= HELP; ++ break; ++ } ++ hash_str = strdup (optarg); + } + break; + case 'd': +@@ -1802,7 +2014,7 @@ main (int argc, char *argv[]) + } + + if (use_root_pw == 1 && use_simple_hash == 1) +- use_simple_hash = 0;; ++ use_simple_hash = 0; + + if (hash_file && use_root_pw) + command |= HELP; +@@ -1819,17 +2031,23 @@ main (int argc, char *argv[]) + break; + case IMPORT: + case IMPORT | SIMPLE_HASH: +- if (use_root_pw) +- ret = import_moks (files, total, NULL, 1); +- else +- ret = import_moks (files, total, hash_file, 0); ++ ret = issue_mok_request (files, total, ENROLL_MOK, ++ hash_file, use_root_pw); + break; + case DELETE: + case DELETE | SIMPLE_HASH: +- if (use_root_pw) +- ret = delete_moks (files, total, NULL, 1); +- else +- ret = delete_moks (files, total, hash_file, 0); ++ ret = issue_mok_request (files, total, DELETE_MOK, ++ hash_file, use_root_pw); ++ break; ++ case IMPORT_HASH: ++ case IMPORT_HASH | SIMPLE_HASH: ++ ret = issue_hash_request (hash_str, ENROLL_MOK, ++ hash_file, use_root_pw); ++ break; ++ case DELETE_HASH: ++ case DELETE_HASH | SIMPLE_HASH: ++ ret = issue_hash_request (hash_str, DELETE_MOK, ++ hash_file, use_root_pw); + break; + case REVOKE_IMPORT: + ret = revoke_request (ENROLL_MOK); +@@ -1842,10 +2060,7 @@ main (int argc, char *argv[]) + break; + case PASSWORD: + case PASSWORD | SIMPLE_HASH: +- if (use_root_pw) +- ret = set_password (NULL, 1, 0); +- else +- ret = set_password (hash_file, 0, 0); ++ ret = set_password (hash_file, use_root_pw, 0); + break; + case CLEAR_PASSWORD: + case CLEAR_PASSWORD | SIMPLE_HASH: +@@ -1865,10 +2080,7 @@ main (int argc, char *argv[]) + break; + case RESET: + case RESET | SIMPLE_HASH: +- if (use_root_pw) +- ret = reset_moks (NULL, 1); +- else +- ret = reset_moks (hash_file, 0); ++ ret = reset_moks (hash_file, use_root_pw); + break; + case GENERATE_PW_HASH: + ret = generate_pw_hash (input_pw); +@@ -1890,17 +2102,23 @@ main (int argc, char *argv[]) + break; + case IMPORT | MOKX: + case IMPORT | SIMPLE_HASH | MOKX: +- if (use_root_pw) +- ret = import_blacklist (files, total, NULL, 1); +- else +- ret = import_blacklist (files, total, hash_file, 0); ++ ret = issue_mok_request (files, total, ENROLL_BLACKLIST, ++ hash_file, use_root_pw); + break; + case DELETE | MOKX: + case DELETE | SIMPLE_HASH | MOKX: +- if (use_root_pw) +- ret = delete_blacklist (files, total, NULL, 1); +- else +- ret = delete_blacklist (files, total, hash_file, 0); ++ ret = issue_mok_request (files, total, DELETE_BLACKLIST, ++ hash_file, use_root_pw); ++ break; ++ case IMPORT_HASH | MOKX: ++ case IMPORT_HASH | SIMPLE_HASH | MOKX: ++ ret = issue_hash_request (hash_str, ENROLL_BLACKLIST, ++ hash_file, use_root_pw); ++ break; ++ case DELETE_HASH | MOKX: ++ case DELETE_HASH | SIMPLE_HASH | MOKX: ++ ret = issue_hash_request (hash_str, DELETE_BLACKLIST, ++ hash_file, use_root_pw); + break; + case REVOKE_IMPORT | MOKX: + ret = revoke_request (ENROLL_BLACKLIST); +@@ -1908,7 +2126,6 @@ main (int argc, char *argv[]) + case REVOKE_DELETE | MOKX: + ret = revoke_request (DELETE_BLACKLIST); + break; +- + default: + print_help (); + break; +@@ -1929,5 +2146,8 @@ main (int argc, char *argv[]) + if (input_pw) + free (input_pw); + ++ if (hash_str) ++ free (hash_str); ++ + return ret; + } +-- +1.8.1.4 + + +From e852519aad00c669716c76db8908b89c6b5583e1 Mon Sep 17 00:00:00 2001 +From: Gary Ching-Pang Lin +Date: Wed, 23 Oct 2013 17:42:05 +0800 +Subject: [PATCH 09/18] Reorganize issue_*_request + +--- + src/mokutil.c | 75 +++++++++++++++++++---------------------------------------- + 1 file changed, 24 insertions(+), 51 deletions(-) + +diff --git a/src/mokutil.c b/src/mokutil.c +index b8edf74..862cfbf 100644 +--- a/src/mokutil.c ++++ b/src/mokutil.c +@@ -1096,6 +1096,7 @@ issue_mok_request (char **files, uint32_t total, MokRequest req, + { + efi_variable_t old_req; + const char *req_name; ++ const char *reverse_req; + void *new_list = NULL; + void *ptr; + struct stat buf; +@@ -1114,15 +1115,19 @@ issue_mok_request (char **files, uint32_t total, MokRequest req, + switch (req) { + case ENROLL_MOK: + req_name = "MokNew"; ++ reverse_req = "MokDel"; + break; + case DELETE_MOK: + req_name = "MokDel"; ++ reverse_req = "MokNew"; + break; + case ENROLL_BLACKLIST: + req_name = "MokXNew"; ++ reverse_req = "MokXDel"; + break; + case DELETE_BLACKLIST: + req_name = "MokXDel"; ++ reverse_req = "MokXNew"; + break; + default: + return -1; +@@ -1199,26 +1204,7 @@ issue_mok_request (char **files, uint32_t total, MokRequest req, + ptr += sizes[i]; + real_size += sizes[i] + sizeof(EFI_SIGNATURE_LIST) + sizeof(efi_guid_t); + } else if (in_pending_request (EfiCertX509Guid, ptr, sizes[i], req)) { +- const char *pending; +- switch (req) { +- case ENROLL_MOK: +- pending = "MokDel"; +- break; +- case DELETE_MOK: +- pending = "MokNew"; +- break; +- case ENROLL_BLACKLIST: +- pending = "MokXDel"; +- break; +- case DELETE_BLACKLIST: +- pending = "MokXNew"; +- break; +- default: +- pending = ""; +- break; +- } +- printf ("Removed %s from %s\n", files[i], pending); +- ++ printf ("Removed %s from %s\n", files[i], reverse_req); + ptr -= sizeof(EFI_SIGNATURE_LIST) + sizeof(efi_guid_t); + } else { + printf ("Skip %s\n", files[i]); +@@ -1322,6 +1308,7 @@ issue_hash_request (const char *hash_str, MokRequest req, + { + efi_variable_t old_req; + const char *req_name; ++ const char *reverse_req; + void *new_list = NULL; + void *ptr; + unsigned long list_size = 0; +@@ -1347,20 +1334,37 @@ issue_hash_request (const char *hash_str, MokRequest req, + switch (req) { + case ENROLL_MOK: + req_name = "MokNew"; ++ reverse_req = "MokDel"; + break; + case DELETE_MOK: + req_name = "MokDel"; ++ reverse_req = "MokNew"; + break; + case ENROLL_BLACKLIST: + req_name = "MokXNew"; ++ reverse_req = "MokXDel"; + break; + case DELETE_BLACKLIST: + req_name = "MokXDel"; ++ reverse_req = "MokXNew"; + break; + default: + return -1; + } + ++ if (is_valid_request (hash_type, db_hash, hash_size, req)) { ++ valid = 1; ++ } else if (in_pending_request (hash_type, db_hash, hash_size, req)) { ++ printf ("Removed hash from %s\n", reverse_req); ++ } else { ++ printf ("Skip hash\n"); ++ } ++ ++ if (!valid) { ++ ret = 0; ++ goto error; ++ } ++ + sig_list_size = sizeof(EFI_SIGNATURE_LIST) + sizeof(efi_guid_t) + hash_size; + list_size += sig_list_size; + +@@ -1389,37 +1393,6 @@ issue_hash_request (const char *hash_str, MokRequest req, + CertData->SignatureOwner = SHIM_LOCK_GUID; + memcpy (CertData->SignatureData, db_hash, hash_size); + +- if (is_valid_request (hash_type, db_hash, hash_size, req)) { +- valid = 1; +- } else if (in_pending_request (hash_type, db_hash, hash_size, req)) { +- const char *pending; +- switch (req) { +- case ENROLL_MOK: +- pending = "MokDel"; +- break; +- case DELETE_MOK: +- pending = "MokNew"; +- break; +- case ENROLL_BLACKLIST: +- pending = "MokXDel"; +- break; +- case DELETE_BLACKLIST: +- pending = "MokXNew"; +- break; +- default: +- pending = ""; +- break; +- } +- printf ("Removed hash from %s\n", pending); +- } else { +- printf ("Skip hash\n"); +- } +- +- if (!valid) { +- ret = 0; +- goto error; +- } +- + /* append the keys to the previous request */ + if (old_req.Data) { + memcpy (new_list + sig_list_size, old_req.Data, old_req.DataSize); +-- +1.8.1.4 + + +From 8603b648095d847fbed56b956b0b5aeaa62f091a Mon Sep 17 00:00:00 2001 +From: Gary Ching-Pang Lin +Date: Wed, 23 Oct 2013 18:29:09 +0800 +Subject: [PATCH 10/18] Merge the hash into an existed signature list + +--- + src/mokutil.c | 87 +++++++++++++++++++++++++++++++++++++++++++++++------------ + 1 file changed, 70 insertions(+), 17 deletions(-) + +diff --git a/src/mokutil.c b/src/mokutil.c +index 862cfbf..f87ae7a 100644 +--- a/src/mokutil.c ++++ b/src/mokutil.c +@@ -1312,14 +1312,17 @@ issue_hash_request (const char *hash_str, MokRequest req, + void *new_list = NULL; + void *ptr; + unsigned long list_size = 0; +- uint32_t sig_list_size; ++ uint32_t sig_size, sig_list_size; + int ret = -1; + EFI_SIGNATURE_LIST *CertList; + EFI_SIGNATURE_DATA *CertData; + efi_guid_t hash_type; + uint8_t db_hash[SHA512_DIGEST_LENGTH]; + int hash_size; ++ int merge_ind = -1; + uint8_t valid = 0; ++ MokListNode *mok_list = NULL; ++ uint32_t mok_num; + + if (!hash_str) + return -1; +@@ -1365,16 +1368,31 @@ issue_hash_request (const char *hash_str, MokRequest req, + goto error; + } + +- sig_list_size = sizeof(EFI_SIGNATURE_LIST) + sizeof(efi_guid_t) + hash_size; +- list_size += sig_list_size; +- + 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) ++ if (read_variable (&old_req) == EFI_SUCCESS) { ++ int i; + list_size += old_req.DataSize; + ++ mok_list = build_mok_list (old_req.Data, old_req.DataSize, ++ &mok_num); ++ if (mok_list == NULL) ++ goto error; ++ ++ /* Check if there is a signature list with the same type */ ++ for (i = 0; i < mok_num; i++) { ++ if (efi_guidcmp (mok_list[i].header->SignatureType, ++ hash_type) == 0) { ++ merge_ind = i; ++ break; ++ } ++ } ++ } ++ ++ list_size += sizeof(EFI_SIGNATURE_LIST) + sizeof(efi_guid_t) + hash_size; ++ + new_list = malloc (list_size); + if (!new_list) { + fprintf (stderr, "Failed to allocate space for %s\n", req_name); +@@ -1382,20 +1400,53 @@ issue_hash_request (const char *hash_str, MokRequest req, + } + ptr = new_list; + +- CertList = ptr; +- CertList->SignatureType = hash_type; +- CertList->SignatureListSize = sig_list_size; +- CertList->SignatureHeaderSize = 0; +- CertList->SignatureSize = hash_size + sizeof(efi_guid_t); ++ if (merge_ind < 0) { ++ /* Create a new signature list for the hash */ ++ sig_list_size = sizeof(EFI_SIGNATURE_LIST) + ++ sizeof(efi_guid_t) + hash_size; ++ CertList = ptr; ++ CertList->SignatureType = hash_type; ++ CertList->SignatureListSize = sig_list_size; ++ CertList->SignatureHeaderSize = 0; ++ CertList->SignatureSize = hash_size + sizeof(efi_guid_t); + +- CertData = (EFI_SIGNATURE_DATA *)(((uint8_t *)ptr) + +- sizeof(EFI_SIGNATURE_LIST)); +- CertData->SignatureOwner = SHIM_LOCK_GUID; +- memcpy (CertData->SignatureData, db_hash, hash_size); ++ CertData = (EFI_SIGNATURE_DATA *)(((uint8_t *)ptr) + ++ sizeof(EFI_SIGNATURE_LIST)); ++ CertData->SignatureOwner = SHIM_LOCK_GUID; ++ memcpy (CertData->SignatureData, db_hash, hash_size); + +- /* append the keys to the previous request */ +- if (old_req.Data) { +- memcpy (new_list + sig_list_size, old_req.Data, old_req.DataSize); ++ /* prepend the hash to the previous request */ ++ ptr += sig_list_size; ++ if (old_req.Data) { ++ memcpy (ptr, old_req.Data, old_req.DataSize); ++ } ++ } else { ++ /* Merge the hash into an existed signature list */ ++ int i; ++ ++ for (i = 0; i < merge_ind; i++) { ++ sig_list_size = mok_list[i].header->SignatureListSize; ++ memcpy (ptr, (void *)mok_list[i].header, sig_list_size); ++ ptr += sig_list_size; ++ } ++ ++ /* Append the hash to the list */ ++ i = merge_ind; ++ sig_list_size = mok_list[i].header->SignatureListSize; ++ sig_size = hash_size + sizeof(efi_guid_t); ++ mok_list[i].header->SignatureListSize += sig_size; ++ memcpy (ptr, (void *)mok_list[i].header, sig_list_size); ++ ptr += sig_list_size; ++ memcpy (ptr, (void *)&hash_type, sizeof(efi_guid_t)); ++ ptr += sizeof(efi_guid_t); ++ memcpy (ptr, db_hash, hash_size); ++ ptr += hash_size; ++ ++ for (i = merge_ind + 1; i < mok_num; i++) { ++ sig_list_size = mok_list[i].header->SignatureListSize; ++ memcpy (ptr, (void *)mok_list[i].header, sig_list_size); ++ ptr += sig_list_size; ++ } + } + + if (update_request (new_list, list_size, req, hash_file, root_pw) < 0) { +@@ -1406,6 +1457,8 @@ issue_hash_request (const char *hash_str, MokRequest req, + error: + if (old_req.Data) + free (old_req.Data); ++ if (mok_list) ++ free (mok_list); + if (new_list) + free (new_list); + +-- +1.8.1.4 + + +From d933eba21ebad708d85ff23a715a14a7d67f51a9 Mon Sep 17 00:00:00 2001 +From: Gary Ching-Pang Lin +Date: Thu, 24 Oct 2013 17:54:18 +0800 +Subject: [PATCH 11/18] Initialize the request variable to avoid the potential + crash + +--- + src/mokutil.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/mokutil.c b/src/mokutil.c +index f87ae7a..880c38f 100644 +--- a/src/mokutil.c ++++ b/src/mokutil.c +@@ -1334,6 +1334,8 @@ issue_hash_request (const char *hash_str, MokRequest req, + if (hex_str_to_binary (hash_str, db_hash, hash_size) < 0) + return -1; + ++ memset (&old_req, 0, sizeof(old_req)); ++ + switch (req) { + case ENROLL_MOK: + req_name = "MokNew"; +@@ -1368,8 +1370,6 @@ issue_hash_request (const char *hash_str, MokRequest req, + goto error; + } + +- 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.8.1.4 + + +From 6c9d5519172ca5f87a08d1a46105c2a68b9f4db7 Mon Sep 17 00:00:00 2001 +From: Gary Ching-Pang Lin +Date: Fri, 25 Oct 2013 18:29:07 +0800 +Subject: [PATCH 12/18] Make test-key and reset support MOK blacklist + +--- + src/mokutil.c | 22 +++++++++++++++------- + 1 file changed, 15 insertions(+), 7 deletions(-) + +diff --git a/src/mokutil.c b/src/mokutil.c +index 880c38f..8ff4b41 100644 +--- a/src/mokutil.c ++++ b/src/mokutil.c +@@ -154,7 +154,8 @@ print_help () + printf (" \t\t\t\t(For --list-enrolled, --list-new,\n"); + printf (" \t\t\t\t --list-delete, --import, --delete,\n"); + printf (" \t\t\t\t --revoke-import, --revoke-delete,\n"); +- printf (" \t\t\t\t --import-hash, and --delete-hash)\n"); ++ printf (" \t\t\t\t --import-hash, --delete-hash,\n"); ++ printf (" \t\t\t\t --reset, and --test-key)\n"); + } + + static int +@@ -1756,7 +1757,7 @@ read_file(int fd, void **bufp, size_t *lenptr) { + } + + static int +-test_key (const char *key_file) ++test_key (MokRequest req, const char *key_file) + { + void *key = NULL; + size_t read_size; +@@ -1774,7 +1775,7 @@ test_key (const char *key_file) + goto error; + } + +- if (!is_valid_request (EfiCertX509Guid, key, read_size, ENROLL_MOK)) { ++ if (!is_valid_request (EfiCertX509Guid, key, read_size, req)) { + printf ("%s is not enrolled\n", key_file); + ret = 0; + } else { +@@ -1793,9 +1794,9 @@ error: + } + + static int +-reset_moks (const char *hash_file, const int root_pw) ++reset_moks (MokRequest req, const char *hash_file, const int root_pw) + { +- if (update_request (NULL, 0, ENROLL_MOK, hash_file, root_pw)) { ++ if (update_request (NULL, 0, req, hash_file, root_pw)) { + fprintf (stderr, "Failed to issue a reset request\n"); + return -1; + } +@@ -2102,11 +2103,11 @@ main (int argc, char *argv[]) + ret = sb_state (); + break; + case TEST_KEY: +- ret = test_key (key_file); ++ ret = test_key (ENROLL_MOK, key_file); + break; + case RESET: + case RESET | SIMPLE_HASH: +- ret = reset_moks (hash_file, use_root_pw); ++ ret = reset_moks (ENROLL_MOK, hash_file, use_root_pw); + break; + case GENERATE_PW_HASH: + ret = generate_pw_hash (input_pw); +@@ -2152,6 +2153,13 @@ main (int argc, char *argv[]) + case REVOKE_DELETE | MOKX: + ret = revoke_request (DELETE_BLACKLIST); + break; ++ case RESET | MOKX: ++ case RESET | SIMPLE_HASH | MOKX: ++ ret = reset_moks (ENROLL_BLACKLIST, hash_file, use_root_pw); ++ break; ++ case TEST_KEY | MOKX: ++ ret = test_key (ENROLL_BLACKLIST, key_file); ++ break; + default: + print_help (); + break; +-- +1.8.1.4 + + +From 0fdc023cf98addb23ae511b91c963619ec1e8e2d Mon Sep 17 00:00:00 2001 +From: Gary Ching-Pang Lin +Date: Wed, 30 Oct 2013 10:29:25 +0800 +Subject: [PATCH 13/18] Set the verbosity for shim and MokManager + +--- + src/mokutil.c | 40 ++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 40 insertions(+) + +diff --git a/src/mokutil.c b/src/mokutil.c +index 8ff4b41..cd3b622 100644 +--- a/src/mokutil.c ++++ b/src/mokutil.c +@@ -82,6 +82,7 @@ EFI_GUID (0x605dab50, 0xe046, 0x4300, 0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, + #define MOKX (1 << 20) + #define IMPORT_HASH (1 << 21) + #define DELETE_HASH (1 << 22) ++#define VERBOSITY (1 << 23) + + #define DEFAULT_CRYPT_METHOD SHA512_BASED + #define DEFAULT_SALT_SIZE SHA512_SALT_MAX +@@ -136,6 +137,7 @@ print_help () + printf (" --use-db\t\t\t\tUse DB for validation\n"); + printf (" --import-hash \t\t\tImport a hash\n"); + printf (" --delete-hash \t\t\tDelete a specific hash\n"); ++ printf (" --set-verbosity \t\tSet the verbosity bit for shim\n"); + printf ("\n"); + printf ("Supplimentary Options:\n"); + printf (" --hash-file \t\tUse the specific password hash\n"); +@@ -1856,6 +1858,31 @@ generate_pw_hash (const char *input_pw) + return 0; + } + ++static int ++set_verbosity (uint8_t verbosity) ++{ ++ efi_variable_t var; ++ ++ if (verbosity) { ++ var.VariableName = "SHIM_VERBOSE"; ++ var.VendorGuid = SHIM_LOCK_GUID; ++ var.Data = (void *)&verbosity; ++ var.DataSize = sizeof(uint8_t); ++ var.Attributes = EFI_VARIABLE_NON_VOLATILE ++ | EFI_VARIABLE_BOOTSERVICE_ACCESS ++ | EFI_VARIABLE_RUNTIME_ACCESS; ++ ++ if (edit_protected_variable (&var) != EFI_SUCCESS) { ++ fprintf (stderr, "Failed to set SHIM_VERBOSE\n"); ++ return -1; ++ } ++ } else { ++ return test_and_delete_var ("SHIM_VERBOSE"); ++ } ++ ++ return 0; ++} ++ + int + main (int argc, char *argv[]) + { +@@ -1868,6 +1895,7 @@ main (int argc, char *argv[]) + int c, i, f_ind, total = 0; + unsigned int command = 0; + int use_root_pw = 0; ++ uint8_t verbosity = 0; + int ret = -1; + + use_simple_hash = 0; +@@ -1899,6 +1927,7 @@ main (int argc, char *argv[]) + {"mokx", no_argument, 0, 0 }, + {"import-hash", required_argument, 0, 0 }, + {"delete-hash", required_argument, 0, 0 }, ++ {"set-verbosity", required_argument, 0, 0 }, + {0, 0, 0, 0} + }; + +@@ -1950,6 +1979,14 @@ main (int argc, char *argv[]) + break; + } + hash_str = strdup (optarg); ++ } else if (strcmp (option, "set-verbosity") == 0) { ++ command |= VERBOSITY; ++ if (strcmp (optarg, "true") == 0) ++ verbosity = 1; ++ else if (strcmp (optarg, "false") == 0) ++ verbosity = 0; ++ else ++ command |= HELP; + } + break; + case 'd': +@@ -2160,6 +2197,9 @@ main (int argc, char *argv[]) + case TEST_KEY | MOKX: + ret = test_key (ENROLL_BLACKLIST, key_file); + break; ++ case VERBOSITY: ++ ret = set_verbosity (verbosity); ++ break; + default: + print_help (); + break; +-- +1.8.1.4 + + +From 96dfa331c2067c3a44d6086ec86e6abb87f3c30f Mon Sep 17 00:00:00 2001 +From: Gary Ching-Pang Lin +Date: Tue, 26 Nov 2013 12:36:12 +0800 +Subject: [PATCH 14/18] Update the help and manpage + +--- + man/mokutil.1 | 30 +++++++++++++++++++++++++++--- + src/mokutil.c | 4 ++-- + 2 files changed, 29 insertions(+), 5 deletions(-) + +diff --git a/man/mokutil.1 b/man/mokutil.1 +index abfdebb..fa990e5 100644 +--- a/man/mokutil.1 ++++ b/man/mokutil.1 +@@ -5,22 +5,27 @@ mokutil \- utility to manipulate machine owner keys + + .SH SYNOPSIS + \fBmokutil\fR [--list-enrolled] ++ ([--mokx]) + .br + \fBmokutil\fR [--list-new] ++ ([--mokx]) + .br + \fBmokutil\fR [--list-delete] ++ ([--mokx]) + .br + \fBmokutil\fR [--import \fIkeylist\fR| -i \fIkeylist\fR] + ([--hash-file \fIhashfile\fR | -f \fIhashfile\fR] | [--root-pw | -P] | +- [--simple-hash | -s]) ++ [--simple-hash | -s] | [--mokx]) + .br + \fBmokutil\fR [--delete \fIkeylist\fR | -d \fIkeylist\fR] + ([--hash-file \fIhashfile\fR | -f \fIhashfile\fR] | [--root-pw | -P] | +- [--simple-hash | -s]) ++ [--simple-hash | -s] | [--mokx]) + .br + \fBmokutil\fR [--revoke-import] ++ ([--mokx]) + .br + \fBmokutil\fR [--revoke-delete] ++ ([--mokx]) + .br + \fBmokutil\fR [--export | -x] + .br +@@ -41,10 +46,16 @@ mokutil \- utility to manipulate machine owner keys + .br + \fBmokutil\fR [--reset] + ([--hash-file \fIhashfile\fR | -f \fIhashfile\fR] | [--root-pw | -P] | +- [--simple-hash | -s]) ++ [--simple-hash | -s] | [--mok]) + .br + \fBmokutil\fR [--generate-hash=\fIpassword\fR | -g\fIpassword\fR] + .br ++\fBmokutil\fR [--ignore-db] ++.br ++\fBmokutil\fR [--use-db] ++.br ++\fBmokutil\fR [--set-verbosity (\fItrue\fR | \fIfalse\fR)] ++.br + + .SH DESCRIPTION + \fBmokutil\fR is a tool to import or delete the machines owner keys +@@ -108,3 +119,16 @@ Use the root password hash from /etc/shadow + Use the old SHA256 password hash method to hash the password + .br + Note: --root-pw invalidates --simple-hash ++.TP ++\fB--ignore-db\fR ++Tell shim to not use the keys in db to verify EFI images ++.TP ++\fB--use-db\fR ++Tell shim to use the keys in db to verify EFI images (default) ++.TP ++\fB--mokx\fR ++Manipulate the MOK blacklist (MOKX) instead of the MOK list ++.TP ++\fB--set-verbosity\fR ++Set the SHIM_VERBOSE to make shim more or less verbose ++.TP +diff --git a/src/mokutil.c b/src/mokutil.c +index cd3b622..a1f1213 100644 +--- a/src/mokutil.c ++++ b/src/mokutil.c +@@ -135,8 +135,8 @@ print_help () + printf (" --generate-hash[=password]\t\tGenerate the password hash\n"); + printf (" --ignore-db\t\t\t\tIgnore DB for validation\n"); + printf (" --use-db\t\t\t\tUse DB for validation\n"); +- printf (" --import-hash \t\t\tImport a hash\n"); +- printf (" --delete-hash \t\t\tDelete a specific hash\n"); ++ printf (" --import-hash \t\t\tImport a hash into MOK or MOKX\n"); ++ printf (" --delete-hash \t\t\tDelete a hash in MOK or MOKX\n"); + printf (" --set-verbosity \t\tSet the verbosity bit for shim\n"); + printf ("\n"); + printf ("Supplimentary Options:\n"); +-- +1.8.1.4 + + +From e2ea0acb875247d70626545d5f3837f2a422af2f Mon Sep 17 00:00:00 2001 +From: Gary Ching-Pang Lin +Date: Tue, 26 Nov 2013 12:40:57 +0800 +Subject: [PATCH 15/18] Make the help less verbose + +It's all in the manpage anyway. +--- + src/mokutil.c | 14 -------------- + 1 file changed, 14 deletions(-) + +diff --git a/src/mokutil.c b/src/mokutil.c +index a1f1213..628df7d 100644 +--- a/src/mokutil.c ++++ b/src/mokutil.c +@@ -141,23 +141,9 @@ print_help () + printf ("\n"); + printf ("Supplimentary Options:\n"); + printf (" --hash-file \t\tUse the specific password hash\n"); +- printf (" \t\t(For --import, --delete, --password,\n"); +- printf (" \t\t --reset, --import-hash,\n"); +- printf (" \t\t and --delete-hash)\n"); + printf (" --root-pw\t\t\t\tUse the root password\n"); +- printf (" \t\t\t\t(For --import, --delete, --password,\n"); +- printf (" \t\t\t\t --reset, --import-hash,\n"); +- printf (" \t\t\t\t and --delete-hash)\n"); + printf (" --simple-hash\t\t\t\tUse the old password hash method\n"); +- printf (" \t\t\t\t(For --import, --delete, --password,\n"); +- printf (" \t\t\t\t --clear-password, --reset,\n"); +- printf (" \t\t\t\t --import-hash, and --delete-hash)\n"); + printf (" --mokx\t\t\t\tManipulate the MOK blacklist\n"); +- printf (" \t\t\t\t(For --list-enrolled, --list-new,\n"); +- printf (" \t\t\t\t --list-delete, --import, --delete,\n"); +- printf (" \t\t\t\t --revoke-import, --revoke-delete,\n"); +- printf (" \t\t\t\t --import-hash, --delete-hash,\n"); +- printf (" \t\t\t\t --reset, and --test-key)\n"); + } + + static int +-- +1.8.1.4 + + +From 72dd17981660747bc84b7ce643451110529ece38 Mon Sep 17 00:00:00 2001 +From: Gary Ching-Pang Lin +Date: Tue, 26 Nov 2013 16:26:16 +0800 +Subject: [PATCH 16/18] New options to list the firmware keys + +--- + man/mokutil.1 | 20 +++++++++++++ + src/mokutil.c | 93 ++++++++++++++++++++++++++++++++++++++++++++++++++++------- + 2 files changed, 102 insertions(+), 11 deletions(-) + +diff --git a/man/mokutil.1 b/man/mokutil.1 +index fa990e5..86846b4 100644 +--- a/man/mokutil.1 ++++ b/man/mokutil.1 +@@ -56,6 +56,14 @@ mokutil \- utility to manipulate machine owner keys + .br + \fBmokutil\fR [--set-verbosity (\fItrue\fR | \fIfalse\fR)] + .br ++\fBmokutil\fR [--pk] ++.br ++\fBmokutil\fR [--kek] ++.br ++\fBmokutil\fR [--db] ++.br ++\fBmokutil\fR [--dbx] ++.br + + .SH DESCRIPTION + \fBmokutil\fR is a tool to import or delete the machines owner keys +@@ -132,3 +140,15 @@ Manipulate the MOK blacklist (MOKX) instead of the MOK list + \fB--set-verbosity\fR + Set the SHIM_VERBOSE to make shim more or less verbose + .TP ++\fB--pk\fR ++List the keys in the public Platform Key (PK) ++.TP ++\fB--kek\fR ++List the keys in the Key Exchange Key Signature database (KEK) ++.TP ++\fB--db\fR ++List the keys in the secure boot signature store (db) ++.TP ++\fB--dbx\fR ++List the keys in the secure boot blacklist signature store (dbx) ++.TP +diff --git a/src/mokutil.c b/src/mokutil.c +index 628df7d..6f5aec4 100644 +--- a/src/mokutil.c ++++ b/src/mokutil.c +@@ -97,6 +97,15 @@ typedef enum { + ENROLL_BLACKLIST + } MokRequest; + ++typedef enum { ++ MOK_LIST_RT = 0, ++ MOK_LIST_X_RT, ++ PK, ++ KEK, ++ DB, ++ DBX, ++} DBName; ++ + typedef struct { + EFI_SIGNATURE_LIST *header; + uint32_t mok_size; +@@ -138,6 +147,10 @@ print_help () + printf (" --import-hash \t\t\tImport a hash into MOK or MOKX\n"); + printf (" --delete-hash \t\t\tDelete a hash in MOK or MOKX\n"); + printf (" --set-verbosity \t\tSet the verbosity bit for shim\n"); ++ printf (" --pk\t\t\t\t\tList the keys in PK\n"); ++ printf (" --kek\t\t\t\t\tList the keys in KEK\n"); ++ printf (" --db\t\t\t\t\tList the keys in db\n"); ++ printf (" --dbx\t\t\t\t\tList the keys in dbx\n"); + printf ("\n"); + printf ("Supplimentary Options:\n"); + printf (" --hash-file \t\tUse the specific password hash\n"); +@@ -523,7 +536,7 @@ done: + } + + static int +-list_keys_in_var (const char *var_name) ++list_keys_in_var (const char *var_name, const efi_guid_t guid) + { + efi_variable_t var; + efi_status_t status; +@@ -531,7 +544,7 @@ list_keys_in_var (const char *var_name) + + memset (&var, 0, sizeof(var)); + var.VariableName = var_name; +- var.VendorGuid = SHIM_LOCK_GUID; ++ var.VendorGuid = guid; + + status = read_variable (&var); + if (status != EFI_SUCCESS) { +@@ -1869,6 +1882,27 @@ set_verbosity (uint8_t verbosity) + return 0; + } + ++static inline int ++list_db (DBName db_name) ++{ ++ switch (db_name) { ++ case MOK_LIST_RT: ++ return list_keys_in_var ("MokListRT", SHIM_LOCK_GUID); ++ case MOK_LIST_X_RT: ++ return list_keys_in_var ("MokListXRT", SHIM_LOCK_GUID); ++ case PK: ++ return list_keys_in_var ("PK", EFI_GLOBAL_VARIABLE); ++ case KEK: ++ return list_keys_in_var ("KEK", EFI_GLOBAL_VARIABLE); ++ case DB: ++ return list_keys_in_var ("db", EFI_IMAGE_SECURITY_DATABASE_GUID); ++ case DBX: ++ return list_keys_in_var ("dbx", EFI_IMAGE_SECURITY_DATABASE_GUID); ++ } ++ ++ return -1; ++} ++ + int + main (int argc, char *argv[]) + { +@@ -1882,6 +1916,7 @@ main (int argc, char *argv[]) + unsigned int command = 0; + int use_root_pw = 0; + uint8_t verbosity = 0; ++ DBName db_name = MOK_LIST_RT; + int ret = -1; + + use_simple_hash = 0; +@@ -1914,6 +1949,10 @@ main (int argc, char *argv[]) + {"import-hash", required_argument, 0, 0 }, + {"delete-hash", required_argument, 0, 0 }, + {"set-verbosity", required_argument, 0, 0 }, ++ {"pk", no_argument, 0, 0 }, ++ {"kek", no_argument, 0, 0 }, ++ {"db", no_argument, 0, 0 }, ++ {"dbx", no_argument, 0, 0 }, + {0, 0, 0, 0} + }; + +@@ -1950,7 +1989,12 @@ main (int argc, char *argv[]) + } else if (strcmp (option, "use-db") == 0) { + command |= USE_DB; + } else if (strcmp (option, "mokx") == 0) { +- command |= MOKX; ++ if (db_name != MOK_LIST_RT) { ++ command |= HELP; ++ } else { ++ command |= MOKX; ++ db_name = MOK_LIST_X_RT; ++ } + } else if (strcmp (option, "import-hash") == 0) { + command |= IMPORT_HASH; + if (hash_str) { +@@ -1973,7 +2017,36 @@ main (int argc, char *argv[]) + verbosity = 0; + else + command |= HELP; ++ } else if (strcmp (option, "pk") == 0) { ++ if (db_name != MOK_LIST_RT) { ++ command |= HELP; ++ } else { ++ command |= LIST_ENROLLED; ++ db_name = PK; ++ } ++ } else if (strcmp (option, "kek") == 0) { ++ if (db_name != MOK_LIST_RT) { ++ command |= HELP; ++ } else { ++ command |= LIST_ENROLLED; ++ db_name = KEK; ++ } ++ } else if (strcmp (option, "db") == 0) { ++ if (db_name != MOK_LIST_RT) { ++ command |= HELP; ++ } else { ++ command |= LIST_ENROLLED; ++ db_name = DB; ++ } ++ } else if (strcmp (option, "dbx") == 0) { ++ if (db_name != MOK_LIST_RT) { ++ command |= HELP; ++ } else { ++ command |= LIST_ENROLLED; ++ db_name = DBX; ++ } + } ++ + break; + case 'd': + case 'i': +@@ -2071,13 +2144,14 @@ main (int argc, char *argv[]) + + switch (command) { + case LIST_ENROLLED: +- ret = list_keys_in_var ("MokListRT"); ++ case LIST_ENROLLED | MOKX: ++ ret = list_db (db_name); + break; + case LIST_NEW: +- ret = list_keys_in_var ("MokNew"); ++ ret = list_keys_in_var ("MokNew", SHIM_LOCK_GUID); + break; + case LIST_DELETE: +- ret = list_keys_in_var ("MokDel"); ++ ret = list_keys_in_var ("MokDel", SHIM_LOCK_GUID); + break; + case IMPORT: + case IMPORT | SIMPLE_HASH: +@@ -2141,14 +2215,11 @@ main (int argc, char *argv[]) + case USE_DB: + ret = enable_db (); + break; +- case LIST_ENROLLED | MOKX: +- ret = list_keys_in_var ("MokListXRT"); +- break; + case LIST_NEW | MOKX: +- ret = list_keys_in_var ("MokXNew"); ++ ret = list_keys_in_var ("MokXNew", SHIM_LOCK_GUID); + break; + case LIST_DELETE | MOKX: +- ret = list_keys_in_var ("MokXDel"); ++ ret = list_keys_in_var ("MokXDel", SHIM_LOCK_GUID); + break; + case IMPORT | MOKX: + case IMPORT | SIMPLE_HASH | MOKX: +-- +1.8.1.4 + + +From 9820c083e2a9b605a59aae7bdf56992f63abf7b8 Mon Sep 17 00:00:00 2001 +From: Gary Ching-Pang Lin +Date: Tue, 26 Nov 2013 16:49:14 +0800 +Subject: [PATCH 17/18] Add more short options + +--- + man/mokutil.1 | 54 +++++++++++++++++++++++++++++------------------------- + src/mokutil.c | 42 +++++++++++++++++++++++------------------- + 2 files changed, 52 insertions(+), 44 deletions(-) + +diff --git a/man/mokutil.1 b/man/mokutil.1 +index 86846b4..02b346f 100644 +--- a/man/mokutil.1 ++++ b/man/mokutil.1 +@@ -4,28 +4,28 @@ + mokutil \- utility to manipulate machine owner keys + + .SH SYNOPSIS +-\fBmokutil\fR [--list-enrolled] +- ([--mokx]) ++\fBmokutil\fR [--list-enrolled | -l] ++ ([--mokx | -X]) + .br +-\fBmokutil\fR [--list-new] +- ([--mokx]) ++\fBmokutil\fR [--list-new | -N] ++ ([--mokx | -X]) + .br +-\fBmokutil\fR [--list-delete] +- ([--mokx]) ++\fBmokutil\fR [--list-delete | -D] ++ ([--mokx | -X]) + .br + \fBmokutil\fR [--import \fIkeylist\fR| -i \fIkeylist\fR] + ([--hash-file \fIhashfile\fR | -f \fIhashfile\fR] | [--root-pw | -P] | +- [--simple-hash | -s] | [--mokx]) ++ [--simple-hash | -s] | [--mokx | -X]) + .br + \fBmokutil\fR [--delete \fIkeylist\fR | -d \fIkeylist\fR] + ([--hash-file \fIhashfile\fR | -f \fIhashfile\fR] | [--root-pw | -P] | +- [--simple-hash | -s] | [--mokx]) ++ [--simple-hash | -s] | [--mokx |- X]) + .br + \fBmokutil\fR [--revoke-import] +- ([--mokx]) ++ ([--mokx | -X]) + .br + \fBmokutil\fR [--revoke-delete] +- ([--mokx]) ++ ([--mokx | -X]) + .br + \fBmokutil\fR [--export | -x] + .br +@@ -42,11 +42,11 @@ mokutil \- utility to manipulate machine owner keys + .br + \fBmokutil\fR [--sb-state] + .br +-\fBmokutil\fR [--test-key | -t] ... ++\fBmokutil\fR [--test-key \fIkeyfile\fR | -t \fIkeyfile\fR] + .br + \fBmokutil\fR [--reset] + ([--hash-file \fIhashfile\fR | -f \fIhashfile\fR] | [--root-pw | -P] | +- [--simple-hash | -s] | [--mok]) ++ [--simple-hash | -s] | [--mok | -X]) + .br + \fBmokutil\fR [--generate-hash=\fIpassword\fR | -g\fIpassword\fR] + .br +@@ -71,18 +71,22 @@ mokutil \- utility to manipulate machine owner keys + + .SH OPTIONS + .TP +-\fB--list-enrolled\fR ++\fB-l, --list-enrolled\fR + List the keys the already stored in the database + .TP +-\fB--list-new\fR ++\fB-N, --list-new\fR + List the keys to be enrolled + .TP +-\fB--list-delete\fR ++\fB-D, --list-delete\fR + List the keys to be deleted + .TP +-\fB--import\fR +-Collect the followed files and form a request to shim. The files must be in DER +-format. ++\fB-i, --import\fR ++Collect the followed files and form a enrolling request to shim. The files must ++be in DER format. ++.TP ++\fB-d, --delete\fR ++Collect the followed files and form a deleting request to shim. The files must be ++in DER format. + .TP + \fB--revoke-import\fR + Revoke the current import request (MokNew) +@@ -90,13 +94,13 @@ Revoke the current import request (MokNew) + \fB--revoke-delete\fR + Revoke the current delete request (MokDel) + .TP +-\fB--export\fR ++\fB-x, --export\fR + Export the keys stored in MokListRT + .TP +-\fB--password\fR ++\fB-p, --password\fR + Setup the password for MokManager (MokPW) + .TP +-\fB--clear-password\fR ++\fB-c, --clear-password\fR + Clear the password for MokManager (MokPW) + .TP + \fB--disable-validation\fR +@@ -108,7 +112,7 @@ Enable the validation process in shim + \fB--sb-state\fR + Show SecureBoot State + .TP +-\fB--test-key\fR ++\fB-t, --test-key\fR + Test if the key is enrolled or not + .TP + \fB--reset\fR +@@ -120,10 +124,10 @@ Generate the password hash + \fB--hash-file\fR + Use the password hash from a specific file + .TP +-\fB--root-pw\fR ++\fB-P, --root-pw\fR + Use the root password hash from /etc/shadow + .TP +-\fB--simple-hash\fR ++\fB-s, --simple-hash\fR + Use the old SHA256 password hash method to hash the password + .br + Note: --root-pw invalidates --simple-hash +@@ -134,7 +138,7 @@ Tell shim to not use the keys in db to verify EFI images + \fB--use-db\fR + Tell shim to use the keys in db to verify EFI images (default) + .TP +-\fB--mokx\fR ++\fB-X, --mokx\fR + Manipulate the MOK blacklist (MOKX) instead of the MOK list + .TP + \fB--set-verbosity\fR +diff --git a/src/mokutil.c b/src/mokutil.c +index 6f5aec4..6fe8ae2 100644 +--- a/src/mokutil.c ++++ b/src/mokutil.c +@@ -1924,9 +1924,9 @@ main (int argc, char *argv[]) + while (1) { + static struct option long_options[] = { + {"help", no_argument, 0, 'h'}, +- {"list-enrolled", no_argument, 0, 0 }, +- {"list-new", no_argument, 0, 0 }, +- {"list-delete", no_argument, 0, 0 }, ++ {"list-enrolled", no_argument, 0, 'l'}, ++ {"list-new", no_argument, 0, 'N'}, ++ {"list-delete", no_argument, 0, 'D'}, + {"import", required_argument, 0, 'i'}, + {"delete", required_argument, 0, 'd'}, + {"revoke-import", no_argument, 0, 0 }, +@@ -1945,7 +1945,7 @@ main (int argc, char *argv[]) + {"simple-hash", no_argument, 0, 's'}, + {"ignore-db", no_argument, 0, 0 }, + {"use-db", no_argument, 0, 0 }, +- {"mokx", no_argument, 0, 0 }, ++ {"mokx", no_argument, 0, 'X'}, + {"import-hash", required_argument, 0, 0 }, + {"delete-hash", required_argument, 0, 0 }, + {"set-verbosity", required_argument, 0, 0 }, +@@ -1957,7 +1957,7 @@ main (int argc, char *argv[]) + }; + + int option_index = 0; +- c = getopt_long (argc, argv, "cd:f:g::hi:pst:xP", ++ c = getopt_long (argc, argv, "cd:f:g::hi:lpst:xDNPX", + long_options, &option_index); + + if (c == -1) +@@ -1966,13 +1966,7 @@ main (int argc, char *argv[]) + 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, "list-delete") == 0) { +- command |= LIST_DELETE; +- } else if (strcmp (option, "revoke-import") == 0) { ++ if (strcmp (option, "revoke-import") == 0) { + command |= REVOKE_IMPORT; + } else if (strcmp (option, "revoke-delete") == 0) { + command |= REVOKE_DELETE; +@@ -1988,13 +1982,6 @@ main (int argc, char *argv[]) + command |= IGNORE_DB; + } else if (strcmp (option, "use-db") == 0) { + command |= USE_DB; +- } else if (strcmp (option, "mokx") == 0) { +- if (db_name != MOK_LIST_RT) { +- command |= HELP; +- } else { +- command |= MOKX; +- db_name = MOK_LIST_X_RT; +- } + } else if (strcmp (option, "import-hash") == 0) { + command |= IMPORT_HASH; + if (hash_str) { +@@ -2048,6 +2035,15 @@ main (int argc, char *argv[]) + } + + break; ++ case 'l': ++ command |= LIST_ENROLLED; ++ break; ++ case 'N': ++ command |= LIST_NEW; ++ break; ++ case 'D': ++ command |= LIST_DELETE; ++ break; + case 'd': + case 'i': + if (c == 'd') +@@ -2127,6 +2123,14 @@ main (int argc, char *argv[]) + command |= SIMPLE_HASH; + use_simple_hash = 1; + break; ++ case 'X': ++ if (db_name != MOK_LIST_RT) { ++ command |= HELP; ++ } else { ++ command |= MOKX; ++ db_name = MOK_LIST_X_RT; ++ } ++ break; + case 'h': + case '?': + command |= HELP; +-- +1.8.1.4 + + +From 0ff8112146c355c1bc4eec57cdeb0aed4cc4065c Mon Sep 17 00:00:00 2001 +From: Gary Ching-Pang Lin +Date: Tue, 26 Nov 2013 18:13:20 +0800 +Subject: [PATCH 18/18] Catch the error from strdup() + +--- + src/mokutil.c | 23 ++++++++++++++++++++++- + 1 file changed, 22 insertions(+), 1 deletion(-) + +diff --git a/src/mokutil.c b/src/mokutil.c +index 6fe8ae2..27b9585 100644 +--- a/src/mokutil.c ++++ b/src/mokutil.c +@@ -1989,6 +1989,10 @@ main (int argc, char *argv[]) + break; + } + hash_str = strdup (optarg); ++ if (hash_str == NULL) { ++ fprintf (stderr, "Could not allocate space: %m\n"); ++ exit(1); ++ } + } else if (strcmp (option, "delete-hash") == 0) { + command |= DELETE_HASH; + if (hash_str) { +@@ -1996,6 +2000,10 @@ main (int argc, char *argv[]) + break; + } + hash_str = strdup (optarg); ++ if (hash_str == NULL) { ++ fprintf (stderr, "Could not allocate space: %m\n"); ++ exit(1); ++ } + } else if (strcmp (option, "set-verbosity") == 0) { + command |= VERBOSITY; + if (strcmp (optarg, "true") == 0) +@@ -2069,6 +2077,10 @@ main (int argc, char *argv[]) + } + + files = malloc (total * sizeof (char *)); ++ if (files == NULL) { ++ fprintf (stderr, "Could not allocate space: %m\n"); ++ exit(1); ++ } + for (i = 0; i < total; i++) { + f_ind = i + optind - 1; + files[i] = malloc (strlen(argv[f_ind]) + 1); +@@ -2082,6 +2094,10 @@ main (int argc, char *argv[]) + break; + } + hash_file = strdup (optarg); ++ if (hash_file == NULL) { ++ fprintf (stderr, "Could not allocate space: %m\n"); ++ exit(1); ++ } + + break; + case 'g': +@@ -2089,8 +2105,13 @@ main (int argc, char *argv[]) + command |= HELP; + break; + } +- if (optarg) ++ if (optarg) { + input_pw = strdup (optarg); ++ if (input_pw == NULL) { ++ fprintf (stderr, "Could not allocate space: %m\n"); ++ exit(1); ++ } ++ } + + command |= GENERATE_PW_HASH; + break; +-- +1.8.1.4 + diff --git a/mokutil-upstream-fixes.patch b/mokutil-upstream-fixes.patch new file mode 100644 index 0000000..b0e5c38 --- /dev/null +++ b/mokutil-upstream-fixes.patch @@ -0,0 +1,853 @@ +From 9bbf4150add7de95bfeed8515aa9d9d63977ebd4 Mon Sep 17 00:00:00 2001 +From: Gary Ching-Pang Lin +Date: Wed, 25 Sep 2013 18:04:29 +0800 +Subject: [PATCH 01/10] Update the copyright declaration + +Allow the binary to be linked with openssl +--- + src/efi.h | 47 +++++++++++++++++++++++++++++------------------ + src/efilib.c | 17 +++++++++++++++++ + src/mokutil.c | 14 ++++++++++++++ + src/password-crypt.c | 14 ++++++++++++++ + src/password-crypt.h | 14 ++++++++++++++ + src/signature.h | 30 ++++++++++++++++++++++++++++++ + 6 files changed, 118 insertions(+), 18 deletions(-) + +diff --git a/src/efi.h b/src/efi.h +index 7930a94..a622a2b 100644 +--- a/src/efi.h ++++ b/src/efi.h +@@ -1,22 +1,33 @@ + /* +- efi.h - Extensible Firmware Interface definitions +- +- Copyright (C) 2001, 2003 Dell Computer Corporation +- Copyright (C) 2012 Gary Lin +- +- This program is free software; you can redistribute it and/or modify +- it under the terms of the GNU General Public License as published by +- the Free Software Foundation; either version 2 of the License, or +- (at your option) any later version. +- +- This program is distributed in the hope that it will be useful, +- but WITHOUT ANY WARRANTY; without even the implied warranty of +- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- GNU General Public License for more details. +- +- You should have received a copy of the GNU General Public License +- along with this program; if not, write to the Free Software +- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ * Copyright (C) 2001, 2003 Dell Computer Corporation ++ * Copyright (C) 2012-2013 Gary Lin ++ * ++ * This program is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . ++ * ++ * In addition, as a special exception, the copyright holders give ++ * permission to link the code of portions of this program with the ++ * OpenSSL library under certain conditions as described in each ++ * individual source file, and distribute linked combinations ++ * including the two. ++ * ++ * You must obey the GNU General Public License in all respects ++ * for all of the code used other than OpenSSL. If you modify ++ * file(s) with this exception, you may extend this exception to your ++ * version of the file(s), but you are not obligated to do so. If you ++ * do not wish to do so, delete this exception statement from your ++ * version. If you delete this exception statement from all source ++ * files in the program, then also delete it here. + */ + + #ifndef EFI_H +diff --git a/src/efilib.c b/src/efilib.c +index c2336f9..6db914f 100644 +--- a/src/efilib.c ++++ b/src/efilib.c +@@ -14,6 +14,23 @@ + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . ++ * ++ * In addition, as a special exception, the copyright holders give ++ * permission to link the code of portions of this program with the ++ * OpenSSL library under certain conditions as described in each ++ * individual source file, and distribute linked combinations ++ * including the two. ++ * ++ * You must obey the GNU General Public License in all respects ++ * for all of the code used other than OpenSSL. If you modify ++ * file(s) with this exception, you may extend this exception to your ++ * version of the file(s), but you are not obligated to do so. If you ++ * do not wish to do so, delete this exception statement from your ++ * version. If you delete this exception statement from all source ++ * files in the program, then also delete it here. ++ * + * A part of the source code is copied from efibootmgr + */ + #include +diff --git a/src/mokutil.c b/src/mokutil.c +index e7ea08f..109a3eb 100644 +--- a/src/mokutil.c ++++ b/src/mokutil.c +@@ -14,6 +14,20 @@ + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . ++ * ++ * In addition, as a special exception, the copyright holders give ++ * permission to link the code of portions of this program with the ++ * OpenSSL library under certain conditions as described in each ++ * individual source file, and distribute linked combinations ++ * including the two. ++ * ++ * You must obey the GNU General Public License in all respects ++ * for all of the code used other than OpenSSL. If you modify ++ * file(s) with this exception, you may extend this exception to your ++ * version of the file(s), but you are not obligated to do so. If you ++ * do not wish to do so, delete this exception statement from your ++ * version. If you delete this exception statement from all source ++ * files in the program, then also delete it here. + */ + #include + #include +diff --git a/src/password-crypt.c b/src/password-crypt.c +index a1d213b..7fbc3b6 100644 +--- a/src/password-crypt.c ++++ b/src/password-crypt.c +@@ -13,6 +13,20 @@ + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . ++ * ++ * In addition, as a special exception, the copyright holders give ++ * permission to link the code of portions of this program with the ++ * OpenSSL library under certain conditions as described in each ++ * individual source file, and distribute linked combinations ++ * including the two. ++ * ++ * You must obey the GNU General Public License in all respects ++ * for all of the code used other than OpenSSL. If you modify ++ * file(s) with this exception, you may extend this exception to your ++ * version of the file(s), but you are not obligated to do so. If you ++ * do not wish to do so, delete this exception statement from your ++ * version. If you delete this exception statement from all source ++ * files in the program, then also delete it here. + */ + #include + #include +diff --git a/src/password-crypt.h b/src/password-crypt.h +index b694ac1..04451b4 100644 +--- a/src/password-crypt.h ++++ b/src/password-crypt.h +@@ -13,6 +13,20 @@ + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . ++ * ++ * In addition, as a special exception, the copyright holders give ++ * permission to link the code of portions of this program with the ++ * OpenSSL library under certain conditions as described in each ++ * individual source file, and distribute linked combinations ++ * including the two. ++ * ++ * You must obey the GNU General Public License in all respects ++ * for all of the code used other than OpenSSL. If you modify ++ * file(s) with this exception, you may extend this exception to your ++ * version of the file(s), but you are not obligated to do so. If you ++ * do not wish to do so, delete this exception statement from your ++ * version. If you delete this exception statement from all source ++ * files in the program, then also delete it here. + */ + #ifndef __PASSWORD_CRYPT_H__ + #define __PASSWORD_CRYPT_H__ +diff --git a/src/signature.h b/src/signature.h +index f795f14..df88e98 100644 +--- a/src/signature.h ++++ b/src/signature.h +@@ -1,3 +1,33 @@ ++/** ++ * Copyright (C) 2012-2013 Gary Lin ++ * ++ * This program is free software: you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation, either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . ++ * ++ * In addition, as a special exception, the copyright holders give ++ * permission to link the code of portions of this program with the ++ * OpenSSL library under certain conditions as described in each ++ * individual source file, and distribute linked combinations ++ * including the two. ++ * ++ * You must obey the GNU General Public License in all respects ++ * for all of the code used other than OpenSSL. If you modify ++ * file(s) with this exception, you may extend this exception to your ++ * version of the file(s), but you are not obligated to do so. If you ++ * do not wish to do so, delete this exception statement from your ++ * version. If you delete this exception statement from all source ++ * files in the program, then also delete it here. ++ */ + #define SHA256_DIGEST_SIZE 32 + + #define EfiHashSha1Guid EFI_GUID (0x826ca512, 0xcf10, 0x4ac9, 0xb1, 0x87, 0xbe, 0x1, 0x49, 0x66, 0x31, 0xbd) +-- +1.8.1.4 + + +From dcb76ee1e91c02a026bc0b0b8d02dac71d3c85e1 Mon Sep 17 00:00:00 2001 +From: Josh Boyer +Date: Wed, 2 Oct 2013 13:09:20 -0400 +Subject: [PATCH 02/10] Add support for disabling/enabling the use of DB for + verification + +This lets a user disable the use of DB for verification purposes. The new +options "--ignore-db" and "--use-db" toggle the state of this. This sets +a UEFI variable called MokDB that makes MokManager prompt the user to approve +the setting after a reboot. + +We refactor MokSBVar to MokToggleVar and set_validation to set_toggle, as +both MokDB and MokSB are really just toggle variables. +--- + src/mokutil.c | 54 +++++++++++++++++++++++++++++++++++++++++------------- + 1 file changed, 41 insertions(+), 13 deletions(-) + +diff --git a/src/mokutil.c b/src/mokutil.c +index 109a3eb..41bd8eb 100644 +--- a/src/mokutil.c ++++ b/src/mokutil.c +@@ -76,6 +76,8 @@ EFI_GUID (0x605dab50, 0xe046, 0x4300, 0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, + #define RESET (1 << 15) + #define GENERATE_PW_HASH (1 << 16) + #define SIMPLE_HASH (1 << 17) ++#define IGNORE_DB (1 << 18) ++#define USE_DB (1 << 19) + + #define DEFAULT_CRYPT_METHOD SHA512_BASED + #define DEFAULT_SALT_SIZE SHA512_SALT_MAX +@@ -90,10 +92,10 @@ typedef struct { + } MokListNode; + + typedef struct { +- uint32_t mok_sb_state; ++ uint32_t mok_toggle_state; + uint32_t password_length; + uint16_t password[SB_PASSWORD_MAX]; +-} MokSBVar; ++} MokToggleVar; + + static void + print_help () +@@ -119,6 +121,8 @@ print_help () + 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 (" --ignore-db\t\t\t\tIgnore DB for validation\n"); ++ printf (" --use-db\t\t\t\tUse DB for validation\n"); + printf ("\n"); + printf ("Supplimentary Options:\n"); + printf (" --hash-file \t\tUse the specific password hash\n"); +@@ -1108,10 +1112,10 @@ error: + } + + static int +-set_validation (uint32_t state) ++set_toggle (const char * VarName, uint32_t state) + { + efi_variable_t var; +- MokSBVar sbvar; ++ MokToggleVar tvar; + char *password = NULL; + int pw_len; + efi_char16_t efichar_pass[SB_PASSWORD_MAX]; +@@ -1123,26 +1127,26 @@ set_validation (uint32_t state) + goto error; + } + +- sbvar.password_length = pw_len; ++ tvar.password_length = pw_len; + + efichar_from_char (efichar_pass, password, + SB_PASSWORD_MAX * sizeof(efi_char16_t)); + +- memcpy(sbvar.password, efichar_pass, ++ memcpy(tvar.password, efichar_pass, + SB_PASSWORD_MAX * sizeof(efi_char16_t)); + +- sbvar.mok_sb_state = state; ++ tvar.mok_toggle_state = state; + +- var.VariableName = "MokSB"; ++ var.VariableName = VarName; + var.VendorGuid = SHIM_LOCK_GUID; +- var.Data = (void *)&sbvar; +- var.DataSize = sizeof(sbvar); ++ var.Data = (void *)&tvar; ++ var.DataSize = sizeof(tvar); + var.Attributes = EFI_VARIABLE_NON_VOLATILE + | EFI_VARIABLE_BOOTSERVICE_ACCESS + | EFI_VARIABLE_RUNTIME_ACCESS; + + if (edit_protected_variable (&var) != EFI_SUCCESS) { +- fprintf (stderr, "Failed to request new SB state\n"); ++ fprintf (stderr, "Failed to request new %s state\n", VarName); + goto error; + } + +@@ -1156,13 +1160,13 @@ error: + static int + disable_validation() + { +- return set_validation(0); ++ return set_toggle("MokSB", 0); + } + + static int + enable_validation() + { +- return set_validation(1); ++ return set_toggle("MokSB", 1); + } + + static int +@@ -1195,6 +1199,18 @@ sb_state () + } + + static int ++disable_db() ++{ ++ return set_toggle("MokDB", 0); ++} ++ ++static int ++enable_db() ++{ ++ return set_toggle("MokDB", 1); ++} ++ ++static int + test_key (const char *key_file) + { + struct stat buf; +@@ -1346,6 +1362,8 @@ main (int argc, char *argv[]) + {"generate-hash", optional_argument, 0, 'g'}, + {"root-pw", no_argument, 0, 'P'}, + {"simple-hash", no_argument, 0, 's'}, ++ {"ignore-db", no_argument, 0, 0 }, ++ {"use-db", no_argument, 0, 0 }, + {0, 0, 0, 0} + }; + +@@ -1377,6 +1395,10 @@ main (int argc, char *argv[]) + command |= SB_STATE; + } else if (strcmp (option, "reset") == 0) { + command |= RESET; ++ } else if (strcmp (option, "ignore-db") == 0) { ++ command |= IGNORE_DB; ++ } else if (strcmp (option, "use-db") == 0) { ++ command |= USE_DB; + } + break; + case 'd': +@@ -1523,6 +1545,12 @@ main (int argc, char *argv[]) + case GENERATE_PW_HASH: + ret = generate_pw_hash (input_pw); + break; ++ case IGNORE_DB: ++ ret = disable_db (); ++ break; ++ case USE_DB: ++ ret = enable_db (); ++ break; + default: + print_help (); + break; +-- +1.8.1.4 + + +From 2cc44c8e18c48a6985265fd3173e156280d1ec59 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Fri, 15 Nov 2013 09:41:41 -0500 +Subject: [PATCH 03/10] Free mok lists we've allocated in our error paths. + +Coverity says they're leaking, and it's right, though I suspect we just +exit anyway. + +Signed-off-by: Peter Jones +--- + src/mokutil.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/src/mokutil.c b/src/mokutil.c +index 41bd8eb..566c14e 100644 +--- a/src/mokutil.c ++++ b/src/mokutil.c +@@ -343,6 +343,7 @@ delete_key_from_list (void *mok, uint32_t mok_size, + + ret = 1; + done: ++ free (list); + free (var.Data); + + return ret; +@@ -763,6 +764,7 @@ is_duplicate (const void *cert, const uint32_t cert_size, const char *db_name, + } + + done: ++ free (list); + free (var.Data); + + return ret; +@@ -1037,6 +1039,7 @@ export_moks () + + ret = 0; + error: ++ free (list); + free (var.Data); + + return ret; +-- +1.8.1.4 + + +From 86007043adb5bbd2dd0e206998a16783779f9bd3 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Fri, 15 Nov 2013 09:43:57 -0500 +Subject: [PATCH 04/10] Don't close file descriptors < 0. + +Coverity complains, though you'll just get EBADFD. + +Signed-off-by: Peter Jones +--- + src/mokutil.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/src/mokutil.c b/src/mokutil.c +index 566c14e..4f9b288 100644 +--- a/src/mokutil.c ++++ b/src/mokutil.c +@@ -1256,7 +1256,8 @@ error: + if (key) + free (key); + +- close (fd); ++ if (fd >= 0) ++ close (fd); + + return ret; + } +-- +1.8.1.4 + + +From 11d68c32f35306dd475d429ba8fbc127a1c77f44 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Fri, 15 Nov 2013 09:48:32 -0500 +Subject: [PATCH 05/10] Error check reading hash from file. + +Coverity noticed that if read() returns error, we're doing string[-1]. +We're also only reading some of the file in some cases. Replaced this +with a proper read loop. + +Also we were overruning the string by one byte. + +Signed-off-by: Peter Jones +--- + src/mokutil.c | 20 +++++++++++++++++--- + 1 file changed, 17 insertions(+), 3 deletions(-) + +diff --git a/src/mokutil.c b/src/mokutil.c +index 4f9b288..2a5e72f 100644 +--- a/src/mokutil.c ++++ b/src/mokutil.c +@@ -29,6 +29,7 @@ + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ ++#include + #include + #include + #include +@@ -567,7 +568,7 @@ static int + get_hash_from_file (const char *file, pw_crypt_t *pw_crypt) + { + char string[300]; +- ssize_t read_len; ++ ssize_t read_len = 0; + int fd; + + fd = open (file, O_RDONLY); +@@ -575,10 +576,23 @@ get_hash_from_file (const char *file, pw_crypt_t *pw_crypt) + fprintf (stderr, "Failed to open %s\n", file); + return -1; + } +- read_len = read (fd, string, 300); ++ ++ while (read_len < 300) { ++ int rc = read (fd, string + read_len, 300 - read_len); ++ if (rc == EAGAIN) ++ continue; ++ if (rc < 0) { ++ fprintf (stderr, "Failed to read %s: %m\n", file); ++ close (fd); ++ return -1; ++ } ++ if (rc == 0) ++ break; ++ read_len += rc; ++ } + close (fd); + +- if (string[read_len] != '\0') { ++ if (string[read_len-1] != '\0') { + fprintf (stderr, "corrupted string\n"); + return -1; + } +-- +1.8.1.4 + + +From 97b09b346640ea74e7d51c9b59247cd75836c453 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Fri, 15 Nov 2013 10:01:35 -0500 +Subject: [PATCH 06/10] Use a read/realloc loop to avoid a race condition on + stat() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Coverity says: + 4. shim-0.7/mokutil-0.2.0/src/mokutil.c:1228:toctou – Calling function + "open(char const *, int, ...)" that uses "key_file" after a check + function. This can cause a time-of-check, time-of-use race condition. + +So with the new code we'll probably get garbage if somebody tries racing +that for some reason, but at least it'll be consistent garbage :) + +Signed-off-by: Peter Jones +--- + src/mokutil.c | 35 ++++++++++++++++++++++++++--------- + 1 file changed, 26 insertions(+), 9 deletions(-) + +diff --git a/src/mokutil.c b/src/mokutil.c +index 2a5e72f..f29b57d 100644 +--- a/src/mokutil.c ++++ b/src/mokutil.c +@@ -1227,6 +1227,30 @@ enable_db() + return set_toggle("MokDB", 1); + } + ++static inline int ++read_file(int fd, char **bufp, size_t *lenptr) { ++ int alloced = 0, size = 0, i = 0; ++ char * buf = NULL; ++ ++ do { ++ size += i; ++ if ((size + 1024) > alloced) { ++ alloced += 4096; ++ buf = realloc (buf, alloced + 1); ++ } ++ } while ((i = read (fd, buf + size, 1024)) > 0); ++ ++ if (i < 0) { ++ free (buf); ++ return -1; ++ } ++ ++ *bufp = buf; ++ *lenptr = size; ++ ++ return 0; ++} ++ + static int + test_key (const char *key_file) + { +@@ -1235,21 +1259,14 @@ test_key (const char *key_file) + 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) { ++ int rc = read_file (fd, &key, &read_size); ++ if (rc < 0) { + fprintf (stderr, "Failed to read %s\n", key_file); + goto error; + } +-- +1.8.1.4 + + +From 5facb36c5320fe54d38ab081505259c962f8fadb Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Fri, 15 Nov 2013 10:04:06 -0500 +Subject: [PATCH 07/10] Fix check for string termination that was actually a + NULL ptr check... +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Coverity says: + + 2. shim-0.7/mokutil-0.2.0/src/password-crypt.c:267:check_after_deref – + Null-checking "tmp" suggests that it may be null, but it has already + been dereferenced on all paths leading to the check. + +And: + + 2. shim-0.7/mokutil-0.2.0/src/password-crypt.c:215:check_after_deref – + Null-checking "tmp" suggests that it may be null, but it has already + been dereferenced on all paths leading to the check. + +But to me it looks like these were supposed to be checking for end-of-string +instead. + +Signed-off-by: Peter Jones +--- + src/password-crypt.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/password-crypt.c b/src/password-crypt.c +index 7fbc3b6..17362f1 100644 +--- a/src/password-crypt.c ++++ b/src/password-crypt.c +@@ -212,7 +212,7 @@ decode_sha256_pass (const char *string, pw_crypt_t *pw_crypt) + tmp = ptr; + if (strlen (ptr) > SHA256_B64_LENGTH) { + while (*tmp != '$') { +- if (tmp == '\0') ++ if (*tmp == '\0') + return -1; + count++; + tmp++; +@@ -264,7 +264,7 @@ decode_sha512_pass (const char *string, pw_crypt_t *pw_crypt) + tmp = ptr; + if (strlen (ptr) > SHA512_B64_LENGTH) { + while (*tmp != '$') { +- if (tmp == '\0') ++ if (*tmp == '\0') + return -1; + count++; + tmp++; +-- +1.8.1.4 + + +From fcae982278ee1399d44c10a162a825589f735b54 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Fri, 15 Nov 2013 10:23:03 -0500 +Subject: [PATCH 08/10] Make generate_pw_hash() somewhat cleaner. +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Coverity needlessly complains: + + 2. shim-0.7/mokutil-0.2.0/src/mokutil.c:1322:check_after_deref – + Null-checking "password" suggests that it may be null, but it has + already been dereferenced on all paths leading to the check. + +While this doesn't really make any difference, the whole ret and +error-path was overkill here, so I got rid of it. + +Signed-off-by: Peter Jones +--- + src/mokutil.c | 16 ++++++++-------- + 1 file changed, 8 insertions(+), 8 deletions(-) + +diff --git a/src/mokutil.c b/src/mokutil.c +index f29b57d..c6cfb29 100644 +--- a/src/mokutil.c ++++ b/src/mokutil.c +@@ -1312,7 +1312,7 @@ generate_pw_hash (const char *input_pw) + char *crypt_string; + const char *prefix; + int prefix_len; +- int pw_len, salt_size, ret = -1; ++ int pw_len, salt_size; + + if (input_pw) { + pw_len = strlen (input_pw); +@@ -1345,19 +1345,15 @@ generate_pw_hash (const char *input_pw) + settings[DEFAULT_SALT_SIZE + prefix_len] = '\0'; + + crypt_string = crypt (password, settings); ++ free (password); + if (!crypt_string) { + fprintf (stderr, "Failed to generate hash\n"); +- goto error; ++ return -1; + } + + printf ("%s\n", crypt_string); + +- ret = 0; +-error: +- if (password) +- free (password); +- +- return ret; ++ return 0; + } + + int +@@ -1489,6 +1485,10 @@ main (int argc, char *argv[]) + break; + case 't': + key_file = strdup (optarg); ++ if (key_file == NULL) { ++ fprintf (stderr, "Could not allocate space: %m\n"); ++ exit(1); ++ } + + command |= TEST_KEY; + break; +-- +1.8.1.4 + + +From ab16ba45293896bc9e649d23e20ae4e39946f219 Mon Sep 17 00:00:00 2001 +From: Gary Ching-Pang Lin +Date: Mon, 25 Nov 2013 16:55:23 +0800 +Subject: [PATCH 09/10] Fix warnings from gcc + +--- + src/mokutil.c | 11 +++++------ + 1 file changed, 5 insertions(+), 6 deletions(-) + +diff --git a/src/mokutil.c b/src/mokutil.c +index c6cfb29..9aa4376 100644 +--- a/src/mokutil.c ++++ b/src/mokutil.c +@@ -1228,9 +1228,9 @@ enable_db() + } + + static inline int +-read_file(int fd, char **bufp, size_t *lenptr) { ++read_file(int fd, void **bufp, size_t *lenptr) { + int alloced = 0, size = 0, i = 0; +- char * buf = NULL; ++ void * buf = NULL; + + do { + size += i; +@@ -1254,10 +1254,9 @@ read_file(int fd, char **bufp, size_t *lenptr) { + static int + test_key (const char *key_file) + { +- struct stat buf; + void *key = NULL; +- ssize_t read_size; +- int fd, ret = -1; ++ size_t read_size; ++ int fd, rc, ret = -1; + + fd = open (key_file, O_RDONLY); + if (fd < 0) { +@@ -1265,7 +1264,7 @@ test_key (const char *key_file) + goto error; + } + +- int rc = read_file (fd, &key, &read_size); ++ rc = read_file (fd, &key, &read_size); + if (rc < 0) { + fprintf (stderr, "Failed to read %s\n", key_file); + goto error; +-- +1.8.1.4 + + +From a1a7385419b45834a728464f36100fa1098b9741 Mon Sep 17 00:00:00 2001 +From: Gary Ching-Pang Lin +Date: Mon, 25 Nov 2013 16:57:33 +0800 +Subject: [PATCH 10/10] Fix the indentation + +--- + src/mokutil.c | 34 +++++++++++++++++----------------- + 1 file changed, 17 insertions(+), 17 deletions(-) + +diff --git a/src/mokutil.c b/src/mokutil.c +index 9aa4376..e4e247c 100644 +--- a/src/mokutil.c ++++ b/src/mokutil.c +@@ -1229,26 +1229,26 @@ enable_db() + + static inline int + read_file(int fd, void **bufp, size_t *lenptr) { +- int alloced = 0, size = 0, i = 0; +- void * buf = NULL; +- +- do { +- size += i; +- if ((size + 1024) > alloced) { +- alloced += 4096; +- buf = realloc (buf, alloced + 1); +- } +- } while ((i = read (fd, buf + size, 1024)) > 0); ++ int alloced = 0, size = 0, i = 0; ++ void * buf = NULL; + +- if (i < 0) { +- free (buf); +- return -1; +- } ++ do { ++ size += i; ++ if ((size + 1024) > alloced) { ++ alloced += 4096; ++ buf = realloc (buf, alloced + 1); ++ } ++ } while ((i = read (fd, buf + size, 1024)) > 0); + +- *bufp = buf; +- *lenptr = size; ++ if (i < 0) { ++ free (buf); ++ return -1; ++ } ++ ++ *bufp = buf; ++ *lenptr = size; + +- return 0; ++ return 0; + } + + static int +-- +1.8.1.4 + diff --git a/mokutil.changes b/mokutil.changes index fc649fd..fdc2436 100644 --- a/mokutil.changes +++ b/mokutil.changes @@ -1,3 +1,11 @@ +------------------------------------------------------------------- +Thu Dec 5 02:11:40 UTC 2013 - glin@suse.com + +- Add mokutil-upstream-fixes.patch to include upstream fixes for + db signature check, gcc warnings, and error handling +- Add mokutil-mokx-support.patch to support the MOK blacklist + (FATE#316531) + ------------------------------------------------------------------- Thu Jul 25 09:13:44 UTC 2013 - glin@suse.com diff --git a/mokutil.spec b/mokutil.spec index 3c6c8c4..6eec95d 100644 --- a/mokutil.spec +++ b/mokutil.spec @@ -24,6 +24,10 @@ License: GPL-3.0 Group: Productivity/Security Url: https://github.com/lcp/mokutil Source: %{name}-%{version}.tar.bz2 +# PATCH-FIX-UPSTREAM mokutil-upstream-fixes.patch glin@suse.com -- Include upstream fixes for db signature check, gcc warnings, error handling +Patch1: mokutil-upstream-fixes.patch +# PATCH-FIX-UPSTREAM mokutil-mokx-support.patch glin@suse.com -- Support the MOK blacklist +Patch2: mokutil-mokx-support.patch BuildRequires: autoconf BuildRequires: automake BuildRequires: libopenssl-devel >= 0.9.8 @@ -43,6 +47,8 @@ Authors: %prep %setup -q +%patch1 -p1 +%patch2 -p1 %build %configure