avoid double-freeing after enrolling a key from the disk (bsc#1088585) OBS-URL: https://build.opensuse.org/request/show/595021 OBS-URL: https://build.opensuse.org/package/show/devel:openSUSE:Factory/shim?expand=0&rev=140
343 lines
10 KiB
Diff
343 lines
10 KiB
Diff
From aab03ce2522a3610ecfd5e2f9e896a1ccdd5a94a 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 | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
|
|
1 file changed, 75 insertions(+), 2 deletions(-)
|
|
|
|
diff --git a/shim.c b/shim.c
|
|
index 7b34868..be250b6 100644
|
|
--- a/shim.c
|
|
+++ b/shim.c
|
|
@@ -93,6 +93,7 @@ UINT8 *vendor_dbx;
|
|
*/
|
|
verification_method_t verification_method;
|
|
int loader_is_participating;
|
|
+BOOLEAN use_builtin_cert;
|
|
|
|
#define EFI_IMAGE_SECURITY_DATABASE_GUID { 0xd719b2cb, 0x3d3a, 0x4596, { 0xa3, 0xbc, 0xda, 0xd0, 0x0e, 0x67, 0x65, 0x6f }}
|
|
|
|
@@ -1096,7 +1097,7 @@ static EFI_STATUS verify_buffer (char *data, int datasize,
|
|
LogError(L"check_whitelist(): %r\n", status);
|
|
}
|
|
|
|
- if (cert) {
|
|
+ if (cert && use_builtin_cert) {
|
|
#if defined(ENABLE_SHIM_CERT)
|
|
/*
|
|
* Check against the shim build key
|
|
@@ -2080,7 +2081,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)
|
|
@@ -2829,6 +2830,75 @@ shim_fini(void)
|
|
setup_console(0);
|
|
}
|
|
|
|
+#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;
|
|
+}
|
|
+
|
|
extern EFI_STATUS
|
|
efi_main(EFI_HANDLE passed_image_handle, EFI_SYSTEM_TABLE *passed_systab);
|
|
|
|
@@ -2933,6 +3003,9 @@ efi_main (EFI_HANDLE passed_image_handle, EFI_SYSTEM_TABLE *passed_systab)
|
|
*/
|
|
check_mok_sb();
|
|
|
|
+ if (secure_mode() && (builtin_cert_prompt() != 0))
|
|
+ return EFI_ABORTED;
|
|
+
|
|
efi_status = shim_init();
|
|
if (EFI_ERROR(efi_status)) {
|
|
Print(L"Something has gone seriously wrong: %r\n", efi_status);
|
|
--
|
|
2.16.2
|
|
|
|
|
|
From d377f58aadd8c5579a922ef3c237d3ed25bb6d00 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 42bf72d..7a2b5fe 100644
|
|
--- a/MokManager.c
|
|
+++ b/MokManager.c
|
|
@@ -1794,6 +1794,33 @@ mokpw_done:
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
+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;
|
|
@@ -2150,6 +2177,7 @@ typedef enum {
|
|
MOK_CHANGE_SB,
|
|
MOK_SET_PW,
|
|
MOK_CHANGE_DB,
|
|
+ MOK_CLEAR_VERIFY,
|
|
MOK_KEY_ENROLL,
|
|
MOK_HASH_ENROLL
|
|
} mok_menu_item;
|
|
@@ -2170,7 +2198,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 = NULL;
|
|
mok_menu_item *menu_item = NULL;
|
|
@@ -2250,6 +2279,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)
|
|
@@ -2322,6 +2354,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++;
|
|
@@ -2424,6 +2462,9 @@ static EFI_STATUS enter_mok_menu(EFI_HANDLE image_handle,
|
|
if (efi_status == EFI_SUCCESS)
|
|
MokDB = NULL;
|
|
break;
|
|
+ case MOK_CLEAR_VERIFY:
|
|
+ mok_clear_verify_prompt(ClearVerify, ClearVerifySize);
|
|
+ break;
|
|
case MOK_KEY_ENROLL:
|
|
efi_status = mok_key_enroll();
|
|
break;
|
|
@@ -2456,6 +2497,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;
|
|
@@ -2463,6 +2505,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,
|
|
@@ -2535,9 +2578,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);
|
|
@@ -2560,6 +2614,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 be250b6..d461edd 100644
|
|
--- a/shim.c
|
|
+++ b/shim.c
|
|
@@ -2233,7 +2233,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.16.2
|
|
|
|
|
|
From 5a60e36a5c2bad616bc842d7ffaa6acc1493650f 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 7a2b5fe..feae113 100644
|
|
--- a/MokManager.c
|
|
+++ b/MokManager.c
|
|
@@ -1808,7 +1808,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.16.2
|
|
|