File shim-opensuse-cert-prompt.patch of Package shim

From eeeb5117c7d30eef6ec8a09f884d6e6872e41638 Mon Sep 17 00:00:00 2001
From: Gary Ching-Pang Lin <glin@suse.com>
Date: Tue, 18 Feb 2014 17:29:19 +0800
Subject: [PATCH 1/3] Show the build-in certificate prompt

This is an openSUSE-only patch.

Pop up a window to ask if the user is willing to trust the built-in
openSUSE certificate.

If yes, set openSUSE_Verify, a BootService variable, to 1, and shim
won't bother the user afterward.

If no, continue the booting process without using the built-in
certificate to verify the EFI images, and the window will show up
again after reboot.

The state will store in use_openSUSE_cert, a volatile RT variable.
---
 shim.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 74 insertions(+), 2 deletions(-)

diff --git a/shim.c b/shim.c
index 6fbe427..112a141 100644
--- a/shim.c
+++ b/shim.c
@@ -91,6 +91,7 @@ UINT8 *vendor_dbx;
 verification_method_t verification_method;
 int loader_is_participating;
 int exit_only;
+BOOLEAN use_builtin_cert;
 
 #define EFI_IMAGE_SECURITY_DATABASE_GUID { 0xd719b2cb, 0x3d3a, 0x4596, { 0xa3, 0xbc, 0xda, 0xd0, 0x0e, 0x67, 0x65, 0x6f }}
 
@@ -955,7 +956,7 @@ static EFI_STATUS verify_buffer (char *data, int datasize,
 	if (status == EFI_SUCCESS)
 		return status;
 
-	if (cert) {
+	if (cert && use_builtin_cert) {
 		/*
 		 * Check against the shim build key
 		 */
@@ -1709,7 +1710,7 @@ EFI_STATUS mirror_mok_list()
 	if (efi_status != EFI_SUCCESS)
 		DataSize = 0;
 
-	if (vendor_cert_size) {
+	if (vendor_cert_size && use_builtin_cert) {
 		FullDataSize = DataSize
 			     + sizeof (*CertList)
 			     + sizeof (EFI_GUID)
@@ -2058,6 +2059,75 @@ uninstall_shim_protocols(void)
 			  &shim_lock_guid, &shim_lock_interface);
 }
 
+#define VENDOR_VERIFY L"openSUSE_Verify"
+
+/* Show the built-in certificate prompt if necessary */
+static int builtin_cert_prompt(void)
+{
+	EFI_GUID shim_lock_guid = SHIM_LOCK_GUID;
+	EFI_STATUS status;
+	UINT32 attributes;
+	UINTN len = sizeof(UINT8);
+	UINT8 data;
+
+	use_builtin_cert = FALSE;
+
+	if (vendor_cert_size == 0)
+		return 0;
+
+	status = uefi_call_wrapper(RT->GetVariable, 5, VENDOR_VERIFY,
+				   &shim_lock_guid, &attributes,
+				   &len, &data);
+	if (status != EFI_SUCCESS ||
+	    (attributes & EFI_VARIABLE_RUNTIME_ACCESS)) {
+		int choice;
+
+		if (status != EFI_NOT_FOUND)
+			LibDeleteVariable(VENDOR_VERIFY, &shim_lock_guid);
+
+		CHAR16 *str[] = {L"Trust openSUSE Certificate",
+				 L"",
+				 L"Do you agree to use the built-in openSUSE certificate",
+				 L"to verify boot loaders and kernels?",
+				 NULL};
+		choice = console_yes_no(str);
+		if (choice != 1) {
+			data = 0;
+			goto done;
+		}
+
+		data = 1;
+		status = uefi_call_wrapper(RT->SetVariable, 5,
+					   VENDOR_VERIFY,
+					   &shim_lock_guid,
+					   EFI_VARIABLE_NON_VOLATILE |
+					   EFI_VARIABLE_BOOTSERVICE_ACCESS,
+					   sizeof(UINT8), &data);
+		if (status != EFI_SUCCESS) {
+			console_error(L"Failed to set openSUSE_Verify", status);
+			return -1;
+		}
+	}
+
+	use_builtin_cert = TRUE;
+	data = 1;
+
+done:
+	/* Setup a runtime variable to show the current state */
+	status = uefi_call_wrapper(RT->SetVariable, 5,
+				   L"use_openSUSE_cert",
+				   &shim_lock_guid,
+				   EFI_VARIABLE_BOOTSERVICE_ACCESS |
+				   EFI_VARIABLE_RUNTIME_ACCESS,
+				   sizeof(UINT8), &data);
+	if (status != EFI_SUCCESS) {
+		console_error(L"Failed to set use_openSUSE_cert", status);
+		return -1;
+	}
+
+	return 0;
+}
+
 EFI_STATUS efi_main (EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *passed_systab)
 {
 	EFI_STATUS efi_status;
@@ -2114,6 +2184,8 @@ EFI_STATUS efi_main (EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *passed_systab)
 			 */
 			hook_exit_only = 0;
 			loader_is_participating = 0;
+			if (builtin_cert_prompt() != 0)
+				return EFI_ABORTED;
 		}
 	}
 
-- 
2.1.4


From 869b4633b647c00d13bdf9c2ad554e5d5b8b9670 Mon Sep 17 00:00:00 2001
From: Gary Ching-Pang Lin <glin@suse.com>
Date: Thu, 20 Feb 2014 16:57:08 +0800
Subject: [PATCH 2/3] Support revoking the openSUSE cert

This is an openSUSE-only patch.

To revoke the openSUSE cert, create ClearVerify, a NV RT variable,
and store the password hash in the variable, and then MokManager
will show up with an additional option to clear openSUSE_Verify
---
 MokManager.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
 shim.c       |  2 +-
 2 files changed, 60 insertions(+), 3 deletions(-)

diff --git a/MokManager.c b/MokManager.c
index 442ab8f..7277968 100644
--- a/MokManager.c
+++ b/MokManager.c
@@ -1731,6 +1731,33 @@ static INTN mok_pw_prompt (void *MokPW, UINTN MokPWSize) {
 	return -1;
 }
 
+static INTN mok_clear_verify_prompt(void *ClearVerify, UINTN ClearVerifySize) {
+	EFI_GUID shim_lock_guid = SHIM_LOCK_GUID;
+	EFI_STATUS status;
+
+        if (console_yes_no((CHAR16 *[]){L"Do you want to revoke openSUSE certificate?", NULL}) != 1)
+                return 0;
+
+	if (ClearVerifySize == PASSWORD_CRYPT_SIZE) {
+		status = match_password((PASSWORD_CRYPT *)ClearVerify, NULL, 0,
+					 NULL, NULL);
+	}
+	if (status != EFI_SUCCESS)
+		return -1;
+
+	status = LibDeleteVariable(L"openSUSE_Verify", &shim_lock_guid);
+	if (status != EFI_SUCCESS) {
+		console_error(L"Failed to delete openSUSE_Verify", status);
+		return -1;
+	}
+
+	console_notify(L"The system must now be rebooted");
+	uefi_call_wrapper(RT->ResetSystem, 4, EfiResetWarm,
+			  EFI_SUCCESS, 0, NULL);
+	console_notify(L"Failed to reboot");
+	return -1;
+}
+
 static BOOLEAN verify_certificate(UINT8 *cert, UINTN size)
 {
 	X509 *X509Cert;
@@ -2083,6 +2110,7 @@ typedef enum {
 	MOK_CHANGE_SB,
 	MOK_SET_PW,
 	MOK_CHANGE_DB,
+	MOK_CLEAR_VERIFY,
 	MOK_KEY_ENROLL,
 	MOK_HASH_ENROLL
 } mok_menu_item;
@@ -2094,7 +2122,8 @@ static EFI_STATUS enter_mok_menu(EFI_HANDLE image_handle,
 				 void *MokPW, UINTN MokPWSize,
 				 void *MokDB, UINTN MokDBSize,
 				 void *MokXNew, UINTN MokXNewSize,
-				 void *MokXDel, UINTN MokXDelSize)
+				 void *MokXDel, UINTN MokXDelSize,
+				 void *ClearVerify, UINTN ClearVerifySize)
 {
 	CHAR16 **menu_strings;
 	mok_menu_item *menu_item;
@@ -2168,6 +2197,9 @@ static EFI_STATUS enter_mok_menu(EFI_HANDLE image_handle,
 	if (MokDB)
 		menucount++;
 
+	if (ClearVerify)
+		menucount++;
+
 	menu_strings = AllocateZeroPool(sizeof(CHAR16 *) * (menucount + 1));
 
 	if (!menu_strings)
@@ -2237,6 +2269,12 @@ static EFI_STATUS enter_mok_menu(EFI_HANDLE image_handle,
 		i++;
 	}
 
+	if (ClearVerify) {
+		menu_strings[i] = L"Revoke openSUSE certificate";
+		menu_item[i] = MOK_CLEAR_VERIFY;
+		i++;
+	}
+
 	menu_strings[i] = L"Enroll key from disk";
 	menu_item[i] = MOK_KEY_ENROLL;
 	i++;
@@ -2287,6 +2325,9 @@ static EFI_STATUS enter_mok_menu(EFI_HANDLE image_handle,
 		case MOK_CHANGE_DB:
 			mok_db_prompt(MokDB, MokDBSize);
 			break;
+		case MOK_CLEAR_VERIFY:
+			mok_clear_verify_prompt(ClearVerify, ClearVerifySize);
+			break;
 		case MOK_KEY_ENROLL:
 			mok_key_enroll();
 			break;
@@ -2312,6 +2353,7 @@ static EFI_STATUS check_mok_request(EFI_HANDLE image_handle)
 	EFI_GUID shim_lock_guid = SHIM_LOCK_GUID;
 	UINTN MokNewSize = 0, MokDelSize = 0, MokSBSize = 0, MokPWSize = 0;
 	UINTN MokDBSize = 0, MokXNewSize = 0, MokXDelSize = 0;
+	UINTN ClearVerifySize = 0;
 	void *MokNew = NULL;
 	void *MokDel = NULL;
 	void *MokSB = NULL;
@@ -2319,6 +2361,7 @@ static EFI_STATUS check_mok_request(EFI_HANDLE image_handle)
 	void *MokDB = NULL;
 	void *MokXNew = NULL;
 	void *MokXDel = NULL;
+	void *ClearVerify = NULL;
 	EFI_STATUS status;
 
 	status = get_variable(L"MokNew", (UINT8 **)&MokNew, &MokNewSize,
@@ -2391,9 +2434,20 @@ static EFI_STATUS check_mok_request(EFI_HANDLE image_handle)
 		console_error(L"Could not retrieve MokXDel", status);
 	}
 
+	status = get_variable(L"ClearVerify", (UINT8 **)&ClearVerify, &ClearVerifySize,
+				shim_lock_guid);
+	if (status == EFI_SUCCESS) {
+		if (LibDeleteVariable(L"ClearVerify", &shim_lock_guid) != EFI_SUCCESS) {
+			console_notify(L"Failed to delete ClearVerify");
+		}
+	} else if (EFI_ERROR(status) && status != EFI_NOT_FOUND) {
+		console_error(L"Could not retrieve ClearVerify", status);
+	}
+
 	enter_mok_menu(image_handle, MokNew, MokNewSize, MokDel, MokDelSize,
 		       MokSB, MokSBSize, MokPW, MokPWSize, MokDB, MokDBSize,
-		       MokXNew, MokXNewSize, MokXDel, MokXDelSize);
+		       MokXNew, MokXNewSize, MokXDel, MokXDelSize,
+		       ClearVerify, ClearVerifySize);
 
 	if (MokNew)
 		FreePool (MokNew);
@@ -2416,6 +2470,9 @@ static EFI_STATUS check_mok_request(EFI_HANDLE image_handle)
 	if (MokXDel)
 		FreePool (MokXDel);
 
+	if (ClearVerify)
+		FreePool (ClearVerify);
+
 	LibDeleteVariable(L"MokAuth", &shim_lock_guid);
 	LibDeleteVariable(L"MokDelAuth", &shim_lock_guid);
 	LibDeleteVariable(L"MokXAuth", &shim_lock_guid);
diff --git a/shim.c b/shim.c
index 112a141..9ffac1f 100644
--- a/shim.c
+++ b/shim.c
@@ -1819,7 +1819,7 @@ EFI_STATUS check_mok_request(EFI_HANDLE image_handle)
 	    check_var(L"MokPW") || check_var(L"MokAuth") ||
 	    check_var(L"MokDel") || check_var(L"MokDB") ||
 	    check_var(L"MokXNew") || check_var(L"MokXDel") ||
-	    check_var(L"MokXAuth")) {
+	    check_var(L"MokXAuth") || check_var(L"ClearVerify")) {
 		efi_status = start_image(image_handle, MOK_MANAGER);
 
 		if (efi_status != EFI_SUCCESS) {
-- 
2.1.4


From 8d8ccfdebdd01601548d662ad8a43371d307e2f1 Mon Sep 17 00:00:00 2001
From: Gary Ching-Pang Lin <glin@suse.com>
Date: Fri, 7 Mar 2014 16:17:20 +0800
Subject: [PATCH 3/3] Delete openSUSE_Verify the right way

This is an openSUSE-only patch.

LibDeleteVariable only works on the runtime variables.
---
 MokManager.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/MokManager.c b/MokManager.c
index 7277968..b5d2454 100644
--- a/MokManager.c
+++ b/MokManager.c
@@ -1745,7 +1745,10 @@ static INTN mok_clear_verify_prompt(void *ClearVerify, UINTN ClearVerifySize) {
 	if (status != EFI_SUCCESS)
 		return -1;
 
-	status = LibDeleteVariable(L"openSUSE_Verify", &shim_lock_guid);
+	status = uefi_call_wrapper(RT->SetVariable, 5,
+				   L"openSUSE_Verify", &shim_lock_guid,
+				   EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,
+				   0, NULL);
 	if (status != EFI_SUCCESS) {
 		console_error(L"Failed to delete openSUSE_Verify", status);
 		return -1;
-- 
2.1.4

openSUSE Build Service is sponsored by