From cb345da9fef2e844f86d8f7cbad93a68bce84a8b8845aa732989dcca9e59dce8 Mon Sep 17 00:00:00 2001 From: Andreas Jaeger Date: Tue, 15 Jan 2013 08:03:56 +0000 Subject: [PATCH] Accepting request 148524 from home:gary_lin:UEFI mokutil is a program to manipulate the machine owner keys. It sets up MOK requests, such as enroll and delete, and shim/MokManager shows the information of the keys during the next boot time. OBS-URL: https://build.opensuse.org/request/show/148524 OBS-URL: https://build.opensuse.org/package/show/Base:System/mokutil?expand=0&rev=1 --- .gitattributes | 23 ++ mokutil-0.1.0.tar.bz2 | 3 + mokutil-no-duplicate-keys-imported.patch | 283 +++++++++++++++++++++++ mokutil-probe-secure-boot-state.patch | 111 +++++++++ mokutil.changes | 13 ++ mokutil.spec | 67 ++++++ 6 files changed, 500 insertions(+) create mode 100644 .gitattributes create mode 100644 mokutil-0.1.0.tar.bz2 create mode 100644 mokutil-no-duplicate-keys-imported.patch create mode 100644 mokutil-probe-secure-boot-state.patch create mode 100644 mokutil.changes create mode 100644 mokutil.spec diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..9b03811 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,23 @@ +## Default LFS +*.7z filter=lfs diff=lfs merge=lfs -text +*.bsp filter=lfs diff=lfs merge=lfs -text +*.bz2 filter=lfs diff=lfs merge=lfs -text +*.gem filter=lfs diff=lfs merge=lfs -text +*.gz filter=lfs diff=lfs merge=lfs -text +*.jar filter=lfs diff=lfs merge=lfs -text +*.lz filter=lfs diff=lfs merge=lfs -text +*.lzma filter=lfs diff=lfs merge=lfs -text +*.obscpio filter=lfs diff=lfs merge=lfs -text +*.oxt filter=lfs diff=lfs merge=lfs -text +*.pdf filter=lfs diff=lfs merge=lfs -text +*.png filter=lfs diff=lfs merge=lfs -text +*.rpm filter=lfs diff=lfs merge=lfs -text +*.tbz filter=lfs diff=lfs merge=lfs -text +*.tbz2 filter=lfs diff=lfs merge=lfs -text +*.tgz filter=lfs diff=lfs merge=lfs -text +*.ttf filter=lfs diff=lfs merge=lfs -text +*.txz filter=lfs diff=lfs merge=lfs -text +*.whl filter=lfs diff=lfs merge=lfs -text +*.xz filter=lfs diff=lfs merge=lfs -text +*.zip filter=lfs diff=lfs merge=lfs -text +*.zst filter=lfs diff=lfs merge=lfs -text diff --git a/mokutil-0.1.0.tar.bz2 b/mokutil-0.1.0.tar.bz2 new file mode 100644 index 0000000..a4559da --- /dev/null +++ b/mokutil-0.1.0.tar.bz2 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:739a241e18cc5b89c46eecc473568fb295952598ff518e7af90f81900afb62d4 +size 94722 diff --git a/mokutil-no-duplicate-keys-imported.patch b/mokutil-no-duplicate-keys-imported.patch new file mode 100644 index 0000000..358954e --- /dev/null +++ b/mokutil-no-duplicate-keys-imported.patch @@ -0,0 +1,283 @@ +From 0e1ac853fb889b3d8d00e3a4751f388b0b8d8f26 Mon Sep 17 00:00:00 2001 +From: Gary Ching-Pang Lin +Date: Wed, 5 Dec 2012 11:12:43 +0800 +Subject: [PATCH 1/4] Correct MOK size and SignatureSize + +The MOK size didn't include the SignatureOwner GUID. +The SignatureData header size was added twice accidentally. +--- + src/mokutil.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +diff --git a/src/mokutil.c b/src/mokutil.c +index 1c32828..1b8465f 100644 +--- a/src/mokutil.c ++++ b/src/mokutil.c +@@ -143,7 +143,7 @@ build_mok_list (void *data, unsigned long data_size, uint32_t *mok_num) + return NULL; + } + +- list[count].mok_size = CertList->SignatureSize; ++ list[count].mok_size = CertList->SignatureSize - sizeof(efi_guid_t); + list[count].mok = (void *)Cert->SignatureData; + + count++; +@@ -497,8 +497,7 @@ import_moks (char **files, uint32_t total) + CertList->SignatureListSize = sizes[i] + + sizeof(EFI_SIGNATURE_LIST) + sizeof(EFI_SIGNATURE_DATA) - 1; + CertList->SignatureHeaderSize = 0; +- CertList->SignatureSize = sizes[i] + +- sizeof(EFI_SIGNATURE_DATA) + 16; ++ CertList->SignatureSize = sizes[i] + sizeof(efi_guid_t); + CertData->SignatureOwner = SHIM_LOCK_GUID; + + fd = open (files[i], O_RDONLY); +-- +1.7.10.4 + + +From 69955da3819da3abaf198e5dae038c44814df5c0 Mon Sep 17 00:00:00 2001 +From: Gary Ching-Pang Lin +Date: Wed, 5 Dec 2012 11:24:58 +0800 +Subject: [PATCH 2/4] Don't import duplicate keys + +This commit compares keys in PK, KEK, db, MokListRT, and MokNew +before issuing a new request to avoid enrolling keys twice. +--- + src/mokutil.c | 128 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-- + 1 file changed, 124 insertions(+), 4 deletions(-) + +diff --git a/src/mokutil.c b/src/mokutil.c +index 1b8465f..cf38422 100644 +--- a/src/mokutil.c ++++ b/src/mokutil.c +@@ -333,8 +333,8 @@ get_password (char **password, int *len, int min, int max) + } + + static int +-generate_auth (void *new_list, int list_len, char *password, int pw_len, +- uint8_t *auth) ++generate_auth (void *new_list, unsigned long list_len, char *password, ++ int pw_len, uint8_t *auth) + { + efi_char16_t efichar_pass[PASSWORD_MAX+1]; + unsigned long efichar_len; +@@ -444,12 +444,97 @@ 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) ++{ ++ efi_variable_t var; ++ uint32_t mok_num; ++ MokListNode *list; ++ int i, ret = 0; ++ ++ if (!cert || cert_size == 0 || !db_name) ++ return 0; ++ ++ memset (&var, 0, sizeof(var)); ++ var.VariableName = db_name; ++ var.VendorGuid = guid; ++ ++ if (read_variable (&var) != EFI_SUCCESS) ++ return 0; ++ ++ list = build_mok_list (var.Data, var.DataSize, &mok_num); ++ if (list == NULL) { ++ goto done; ++ } ++ ++ for (i = 0; i < mok_num; i++) { ++ if (list[i].mok_size != cert_size) ++ continue; ++ ++ if (memcmp (list[i].mok, cert, cert_size) == 0) { ++ ret = 1; ++ break; ++ } ++ } ++ ++done: ++ free (var.Data); ++ ++ return ret; ++} ++ ++static int ++verify_mok_new (void *mok_new, unsigned long mok_new_size) ++{ ++ efi_variable_t mok_auth; ++ uint8_t auth[SHA256_DIGEST_LENGTH]; ++ char *password; ++ int pw_len, fail = 0; ++ size_t n; ++ int ret = 0; ++ ++ memset (&mok_auth, 0, sizeof(mok_auth)); ++ mok_auth.VariableName = "MokAuth"; ++ mok_auth.VendorGuid = SHIM_LOCK_GUID; ++ if (read_variable (&mok_auth) == EFI_SUCCESS) ++ return 0; ++ ++ while (fail < 3) { ++ printf ("input old password: "); ++ pw_len = read_hidden_line (&password, &n); ++ printf ("\n"); ++ ++ if (pw_len > PASSWORD_MAX || pw_len < PASSWORD_MIN) { ++ free (password); ++ fprintf (stderr, "invalid password\n"); ++ fail++; ++ continue; ++ } ++ ++ generate_auth (mok_new, mok_new_size, password, pw_len, auth); ++ if (memcmp (auth, mok_auth.Data, SHA256_DIGEST_LENGTH) == 0) { ++ ret = 1; ++ break; ++ } ++ ++ fail++; ++ } ++ ++ if (mok_auth.Data) ++ free (mok_auth.Data); ++ ++ return ret; ++} ++ ++static int + import_moks (char **files, uint32_t total) + { ++ efi_variable_t mok_new; + void *new_list = NULL; + void *ptr; + struct stat buf; + unsigned long list_size = 0; ++ unsigned long real_size = 0; + uint32_t *sizes = NULL; + int fd = -1; + ssize_t read_size; +@@ -481,6 +566,12 @@ import_moks (char **files, uint32_t total) + list_size += sizeof(EFI_SIGNATURE_LIST) * total; + list_size += sizeof(efi_guid_t) * total; + ++ memset (&mok_new, 0, sizeof(mok_new)); ++ mok_new.VariableName = "MokNew"; ++ mok_new.VendorGuid = SHIM_LOCK_GUID; ++ if (read_variable (&mok_new) == EFI_SUCCESS) ++ list_size += mok_new.DataSize; ++ + new_list = malloc (list_size); + if (!new_list) { + fprintf (stderr, "Failed to allocate space for MokNew\n"); +@@ -518,17 +609,46 @@ import_moks (char **files, uint32_t total) + fprintf (stderr, "Warning!!! %s is not a valid x509 certificate in DER format\n", + files[i]); + } +- ptr += sizes[i]; ++ ++ /* whether this key is already enrolled... */ ++ if (!is_duplicate (ptr, sizes[i], "PK", EFI_GLOBAL_VARIABLE) && ++ !is_duplicate (ptr, sizes[i], "KEK", EFI_GLOBAL_VARIABLE) && ++ !is_duplicate (ptr, sizes[i], "db", EFI_GLOBAL_VARIABLE) && ++ !is_duplicate (ptr, sizes[i], "MokListRT", SHIM_LOCK_GUID) && ++ !is_duplicate (ptr, sizes[i], "MokNew", SHIM_LOCK_GUID)) { ++ ptr += sizes[i]; ++ real_size += sizes[i] + sizeof(EFI_SIGNATURE_LIST) + sizeof(efi_guid_t); ++ } else { ++ ptr -= sizeof(EFI_SIGNATURE_LIST) + sizeof(efi_guid_t); ++ } + + close (fd); + } + +- if (update_request (new_list, list_size) < 0) { ++ /* All keys are enrolled, nothing to do here... */ ++ if (real_size == 0) { ++ ret = 0; ++ goto error; ++ } ++ ++ /* append the keys in MokNew */ ++ if (mok_new.Data) { ++ /* request the previous password to verify the keys */ ++ if (!verify_mok_new (mok_new.Data, mok_new.DataSize)) { ++ goto error; ++ } ++ ++ memcpy (ptr, mok_new.Data, mok_new.DataSize); ++ } ++ ++ if (update_request (new_list, real_size) < 0) { + goto error; + } + + ret = 0; + error: ++ if (mok_new.Data) ++ free (mok_new.Data); + if (sizes) + free (sizes); + if (new_list) +-- +1.7.10.4 + + +From 10046350e223b6912bd9c3a7031f06779cb326bb Mon Sep 17 00:00:00 2001 +From: Gary Ching-Pang Lin +Date: Fri, 7 Dec 2012 15:57:50 +0800 +Subject: [PATCH 3/4] Check MokAuth correctly + +--- + src/mokutil.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/src/mokutil.c b/src/mokutil.c +index cf38422..9d56a90 100644 +--- a/src/mokutil.c ++++ b/src/mokutil.c +@@ -496,8 +496,10 @@ verify_mok_new (void *mok_new, unsigned long mok_new_size) + memset (&mok_auth, 0, sizeof(mok_auth)); + mok_auth.VariableName = "MokAuth"; + mok_auth.VendorGuid = SHIM_LOCK_GUID; +- if (read_variable (&mok_auth) == EFI_SUCCESS) ++ if (read_variable (&mok_auth) != EFI_SUCCESS) { ++ fprintf (stderr, "Failed to read MokAuth\n"); + return 0; ++ } + + while (fail < 3) { + printf ("input old password: "); +-- +1.7.10.4 + + +From 9674b3249fef0d2ba00364f9f120f1ef17b710fc Mon Sep 17 00:00:00 2001 +From: Gary Ching-Pang Lin +Date: Fri, 7 Dec 2012 15:58:30 +0800 +Subject: [PATCH 4/4] Really append the old request to the new one... + +--- + src/mokutil.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/src/mokutil.c b/src/mokutil.c +index 9d56a90..aba1cfb 100644 +--- a/src/mokutil.c ++++ b/src/mokutil.c +@@ -640,7 +640,8 @@ import_moks (char **files, uint32_t total) + goto error; + } + +- memcpy (ptr, mok_new.Data, mok_new.DataSize); ++ memcpy (new_list + real_size, mok_new.Data, mok_new.DataSize); ++ real_size += mok_new.DataSize; + } + + if (update_request (new_list, real_size) < 0) { +-- +1.7.10.4 + diff --git a/mokutil-probe-secure-boot-state.patch b/mokutil-probe-secure-boot-state.patch new file mode 100644 index 0000000..36e1ca9 --- /dev/null +++ b/mokutil-probe-secure-boot-state.patch @@ -0,0 +1,111 @@ +commit b2602eee326c15df8d23baa44f9e9e3e8b6bad93 +Author: Gary Ching-Pang Lin +Date: Mon Dec 3 17:45:41 2012 +0800 + + Probe the state of SecureBoot + +diff --git a/src/mokutil.c b/src/mokutil.c +index 3707220..1c32828 100644 +--- a/src/mokutil.c ++++ b/src/mokutil.c +@@ -40,6 +40,7 @@ enum Command { + COMMAND_PASSWORD, + COMMAND_DISABLE_VALIDATION, + COMMAND_ENABLE_VALIDATION, ++ COMMAND_SB_STATE, + }; + + static void +@@ -48,22 +49,33 @@ print_help () + printf("Usage:\n"); + printf("List the enrolled keys:\n"); + printf(" mokutil --list-enrolled\n\n"); ++ + printf("List the keys to be enrolled:\n"); + printf(" mokutil --list-new\n\n"); ++ + printf("Import keys:\n"); + printf(" mokutil --import ...\n\n"); ++ + printf("Request to delete all keys\n"); + printf(" mokutil --delete-all\n\n"); ++ + printf("Revoke the request:\n"); + printf(" mokutil --revoke\n\n"); ++ + printf("Export enrolled keys to files:\n"); + printf(" mokutil --export\n\n"); ++ + printf("Set MOK password:\n"); + printf(" mokutil --password\n\n"); ++ + printf("Disable signature validation:\n"); + printf(" mokutil --disable-validation\n\n"); ++ + printf("Enable signature validation:\n"); + printf(" mokutil --enable-validation\n\n"); ++ ++ printf("SecureBoot State:\n"); ++ printf(" mokutil --sb-state\n\n"); + } + + static int +@@ -709,7 +721,36 @@ enable_validation() + { + return set_validation(1); + } +- ++ ++static int ++sb_state () ++{ ++ efi_variable_t var; ++ char *state; ++ ++ memset (&var, 0, sizeof(var)); ++ var.VariableName = "SecureBoot"; ++ var.VendorGuid = EFI_GLOBAL_VARIABLE; ++ ++ if (read_variable (&var) != EFI_SUCCESS) { ++ fprintf (stderr, "Failed to read SecureBoot\n"); ++ return -1; ++ } ++ ++ state = (char *)var.Data; ++ if (*state == 1) { ++ printf ("SecureBoot enabled\n"); ++ } else if (*state == 0) { ++ printf ("SecureBoot disabled\n"); ++ } else { ++ printf ("SecureBoot unknown"); ++ } ++ ++ free (var.Data); ++ ++ return 0; ++} ++ + int + main (int argc, char *argv[]) + { +@@ -786,6 +827,10 @@ main (int argc, char *argv[]) + + command = COMMAND_ENABLE_VALIDATION; + ++ } else if (strcmp (argv[1], "--sb-state") == 0) { ++ ++ command = COMMAND_SB_STATE; ++ + } else { + fprintf (stderr, "Unknown argument: %s\n\n", argv[1]); + print_help (); +@@ -820,6 +865,9 @@ main (int argc, char *argv[]) + case COMMAND_ENABLE_VALIDATION: + enable_validation (); + break; ++ case COMMAND_SB_STATE: ++ sb_state (); ++ break; + default: + fprintf (stderr, "Unknown command\n"); + break; diff --git a/mokutil.changes b/mokutil.changes new file mode 100644 index 0000000..58c695a --- /dev/null +++ b/mokutil.changes @@ -0,0 +1,13 @@ +------------------------------------------------------------------- +Tue Dec 11 08:07:32 UTC 2012 - glin@suse.com + +- Add mokutil-probe-secure-boot-state.patch to probe the state of + secure boot +- Add mokutil-no-duplicate-keys-imported.patch to avoid importing + duplicate keys + +------------------------------------------------------------------- +Wed Nov 7 08:10:45 UTC 2012 - glin@suse.com + +- Add new package mokutil-0.1.0 (FATE#314510) + diff --git a/mokutil.spec b/mokutil.spec new file mode 100644 index 0000000..f093163 --- /dev/null +++ b/mokutil.spec @@ -0,0 +1,67 @@ +# +# spec file for package mokutil +# +# Copyright (c) 2012 SUSE LINUX Products GmbH, Nuernberg, Germany. +# +# All modifications and additions to the file contributed by third parties +# remain the property of their copyright owners, unless otherwise agreed +# upon. The license for this file, and modifications and additions to the +# file, is the same license as for the pristine package itself (unless the +# license for the pristine package is not an Open Source License, in which +# case the license is the MIT License). An "Open Source License" is a +# license that conforms to the Open Source Definition (Version 1.9) +# published by the Open Source Initiative. + +# Please submit bugfixes or comments via http://bugs.opensuse.org/ +# + + + +Name: mokutil +Version: 0.1.0 +Release: 1 +License: GPL-3.0 +Summary: Tools for manipulating machine owner keys +Url: https://github.com/lcp/mokutil +Group: Productivity/Security +Source: %{name}-%{version}.tar.bz2 +# PATCH-FIX-UPSTREAM mokutil-probe-secure-boot-state.patch glin@suse.com -- Probe the state of secure boot +Patch1: mokutil-probe-secure-boot-state.patch +# PATCH-FIX-UPSTREAM mokutil-no-duplicate-keys-imported.patch glin@suse.com -- Do not import duplicate keys +Patch2: mokutil-no-duplicate-keys-imported.patch +BuildRequires: pkg-config +BuildRequires: libopenssl-devel >= 0.9.8 +BuildRoot: %{_tmppath}/%{name}-%{version}-build +ExclusiveArch: x86_64 + +%description +This program provides the means to enroll and erase the machine owner +keys (MOK) stored in the database of shim. + + + +Authors: +-------- + Gary Lin + +%prep +%setup -q +%patch1 -p1 +%patch2 -p1 + +%build +%configure +make + +%install +%makeinstall + +%clean +%{?buildroot:%__rm -rf "%{buildroot}"} + +%files +%defattr(-,root,root) +%{_bindir}/mokutil +%{_mandir}/man?/* + +%changelog