shim/shim-opensuse-cert-prompt.patch
2018-12-20 08:53:52 +00:00

357 lines
10 KiB
Diff

From 49355a83722494099caeb23b46637b2c94a6ab9e 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.
---
mok.c | 3 ++-
shim.c | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
shim.h | 1 +
3 files changed, 71 insertions(+), 2 deletions(-)
diff --git a/mok.c b/mok.c
index 00dd1ad..1645d24 100644
--- a/mok.c
+++ b/mok.c
@@ -139,7 +139,8 @@ static EFI_STATUS mirror_one_mok_variable(struct mok_state_variable *v)
if ((v->flags & MOK_MIRROR_KEYDB) &&
v->addend_source && *v->addend_source &&
- v->addend_size && *v->addend_size) {
+ v->addend_size && *v->addend_size &&
+ use_builtin_cert) {
EFI_SIGNATURE_LIST *CertList = NULL;
EFI_SIGNATURE_DATA *CertData = NULL;
FullDataSize = v->data_size
diff --git a/shim.c b/shim.c
index 248c946..d52f46f 100644
--- a/shim.c
+++ b/shim.c
@@ -83,6 +83,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 }}
@@ -1066,7 +1067,7 @@ static EFI_STATUS verify_buffer (char *data, int datasize,
return efi_status;
}
- if (cert) {
+ if (cert && use_builtin_cert) {
#if defined(ENABLE_SHIM_CERT)
/*
* Check against the shim build key
@@ -2529,6 +2530,69 @@ shim_fini(void)
console_fini();
}
+#define VENDOR_VERIFY L"openSUSE_Verify"
+
+/* Show the built-in certificate prompt if necessary */
+static int builtin_cert_prompt(void)
+{
+ EFI_STATUS status;
+ UINT32 attributes;
+ UINTN len = sizeof(UINT8);
+ UINT8 data;
+
+ use_builtin_cert = FALSE;
+
+ if (vendor_cert_size == 0)
+ return 0;
+
+ status = gRT->GetVariable(VENDOR_VERIFY, &SHIM_LOCK_GUID,
+ &attributes, &len, (void *)&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 = gRT->SetVariable(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 = gRT->SetVariable(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);
@@ -2623,6 +2687,9 @@ efi_main (EFI_HANDLE passed_image_handle, EFI_SYSTEM_TABLE *passed_systab)
*/
debug_hook();
+ if (secure_mode() && (builtin_cert_prompt() != 0))
+ return EFI_ABORTED;
+
/*
* Before we do anything else, validate our non-volatile,
* boot-services-only state variables are what we think they are.
diff --git a/shim.h b/shim.h
index d9c60f5..ab384d4 100644
--- a/shim.h
+++ b/shim.h
@@ -174,6 +174,7 @@ extern UINT8 *vendor_dbx;
extern UINT8 user_insecure_mode;
extern UINT8 ignore_db;
extern UINT8 in_protocol;
+extern BOOLEAN use_builtin_cert;
#define perror_(file, line, func, fmt, ...) ({ \
UINTN __perror_ret = 0; \
--
2.19.2
From 18b6390f3193ebccad44cf1448ce54be512cd066 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 | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++--
mok.c | 2 +-
2 files changed, 59 insertions(+), 3 deletions(-)
diff --git a/MokManager.c b/MokManager.c
index 1ab8e5e..fbb7d22 100644
--- a/MokManager.c
+++ b/MokManager.c
@@ -1715,6 +1715,31 @@ mokpw_done:
return EFI_SUCCESS;
}
+static INTN mok_clear_verify_prompt(void *ClearVerify, UINTN ClearVerifySize) {
+ 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");
+ gRT->ResetSystem(EfiResetWarm, EFI_SUCCESS, 0, NULL);
+ console_notify(L"Failed to reboot");
+ return -1;
+}
+
static BOOLEAN verify_certificate(UINT8 * cert, UINTN size)
{
X509 *X509Cert;
@@ -2050,6 +2075,7 @@ typedef enum {
MOK_CHANGE_SB,
MOK_SET_PW,
MOK_CHANGE_DB,
+ MOK_CLEAR_VERIFY,
MOK_KEY_ENROLL,
MOK_HASH_ENROLL
} mok_menu_item;
@@ -2070,7 +2096,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;
@@ -2146,8 +2173,12 @@ 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)
return EFI_OUT_OF_RESOURCES;
@@ -2217,6 +2248,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++;
@@ -2321,6 +2358,9 @@ static EFI_STATUS enter_mok_menu(EFI_HANDLE image_handle,
if (!EFI_ERROR(efi_status))
MokDB = NULL;
break;
+ case MOK_CLEAR_VERIFY:
+ mok_clear_verify_prompt(ClearVerify, ClearVerifySize);
+ break;
case MOK_KEY_ENROLL:
efi_status = mok_key_enroll();
break;
@@ -2352,6 +2392,7 @@ static EFI_STATUS check_mok_request(EFI_HANDLE image_handle)
{
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;
@@ -2359,6 +2400,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 efi_status;
efi_status = get_variable(L"MokNew", (UINT8 **) & MokNew, &MokNewSize,
@@ -2431,9 +2473,20 @@ static EFI_STATUS check_mok_request(EFI_HANDLE image_handle)
console_error(L"Could not retrieve MokXDel", efi_status);
}
+ efi_status = get_variable(L"ClearVerify", (UINT8 **)&ClearVerify,
+ &ClearVerifySize, SHIM_LOCK_GUID);
+ if (!EFI_ERROR(efi_status)) {
+ efi_status = LibDeleteVariable(L"ClearVerify", &SHIM_LOCK_GUID);
+ if (EFI_ERROR(efi_status))
+ console_notify(L"Failed to delete ClearVerify");
+ } else if (EFI_ERROR(efi_status) && efi_status != EFI_NOT_FOUND) {
+ console_error(L"Could not retrieve ClearVerify", efi_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);
@@ -2456,6 +2509,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/mok.c b/mok.c
index 1645d24..45110cd 100644
--- a/mok.c
+++ b/mok.c
@@ -37,7 +37,7 @@ static 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_ERROR(efi_status)) {
--
2.19.2
From f16f00e47824722651e2e4f2b327dfbe4fb6367d 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 fbb7d22..22336d4 100644
--- a/MokManager.c
+++ b/MokManager.c
@@ -1728,7 +1728,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 = gRT->SetVariable(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.19.2