diff --git a/shim-opensuse-cert-prompt.patch b/shim-opensuse-cert-prompt.patch new file mode 100644 index 0000000..cda94bb --- /dev/null +++ b/shim-opensuse-cert-prompt.patch @@ -0,0 +1,358 @@ +From 67255511496bdf4a950e9e04782ac18491b248be Mon Sep 17 00:00:00 2001 +From: Gary Ching-Pang Lin +Date: Tue, 18 Feb 2014 17:29:19 +0800 +Subject: [PATCH 1/2] 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 | 116 ++++++++++++++++++++++++++++++++++++++++++++++++++++++----------- + 1 file changed, 97 insertions(+), 19 deletions(-) + +diff --git a/shim.c b/shim.c +index 8404892..3373a85 100644 +--- a/shim.c ++++ b/shim.c +@@ -82,6 +82,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 }} + +@@ -752,7 +753,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 + */ +@@ -1418,11 +1419,14 @@ EFI_STATUS mirror_mok_list() + if (efi_status != EFI_SUCCESS) + DataSize = 0; + +- FullDataSize = DataSize +- + sizeof (*CertList) +- + sizeof (EFI_GUID) +- + vendor_cert_size +- ; ++ FullDataSize = DataSize; ++ if (use_builtin_cert) { ++ FullDataSize += sizeof (*CertList) + ++ sizeof (EFI_GUID) + ++ vendor_cert_size; ++ } else if (DataSize == 0) { ++ return EFI_SUCCESS; ++ } + FullData = AllocatePool(FullDataSize); + if (!FullData) { + Print(L"Failed to allocate space for MokListRT\n"); +@@ -1434,21 +1438,24 @@ EFI_STATUS mirror_mok_list() + CopyMem(p, Data, DataSize); + p += DataSize; + } +- CertList = (EFI_SIGNATURE_LIST *)p; +- p += sizeof (*CertList); +- CertData = (EFI_SIGNATURE_DATA *)p; +- p += sizeof (EFI_GUID); + +- CertList->SignatureType = EFI_CERT_X509_GUID; +- CertList->SignatureListSize = vendor_cert_size +- + sizeof (*CertList) +- + sizeof (*CertData) +- -1; +- CertList->SignatureHeaderSize = 0; +- CertList->SignatureSize = vendor_cert_size + sizeof (EFI_GUID); ++ if (use_builtin_cert) { ++ CertList = (EFI_SIGNATURE_LIST *)p; ++ p += sizeof (*CertList); ++ CertData = (EFI_SIGNATURE_DATA *)p; ++ p += sizeof (EFI_GUID); + +- CertData->SignatureOwner = SHIM_LOCK_GUID; +- CopyMem(p, vendor_cert, vendor_cert_size); ++ CertList->SignatureType = EFI_CERT_X509_GUID; ++ CertList->SignatureListSize = vendor_cert_size ++ + sizeof (*CertList) ++ + sizeof (*CertData) ++ -1; ++ CertList->SignatureHeaderSize = 0; ++ CertList->SignatureSize = vendor_cert_size + sizeof (EFI_GUID); ++ ++ CertData->SignatureOwner = SHIM_LOCK_GUID; ++ CopyMem(p, vendor_cert, vendor_cert_size); ++ } + + efi_status = uefi_call_wrapper(RT->SetVariable, 5, L"MokListRT", + &shim_lock_guid, +@@ -1719,6 +1726,75 @@ EFI_STATUS set_second_stage (EFI_HANDLE image_handle) + return EFI_SUCCESS; + } + ++#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_GUID shim_lock_guid = SHIM_LOCK_GUID; +@@ -1774,6 +1850,8 @@ EFI_STATUS efi_main (EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *passed_systab) + */ + hook_system_services(systab); + loader_is_participating = 0; ++ if (builtin_cert_prompt() != 0) ++ return EFI_ABORTED; + } + + /* +-- +1.8.4.5 + + +From ef360e53f1c247837f2009cf1adb05af74439837 Mon Sep 17 00:00:00 2001 +From: Gary Ching-Pang Lin +Date: Thu, 20 Feb 2014 16:57:08 +0800 +Subject: [PATCH 2/2] 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 71a3137..a03eea4 100644 +--- a/MokManager.c ++++ b/MokManager.c +@@ -1570,6 +1570,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(void *cert, UINTN size) + { + X509 *X509Cert; +@@ -1903,6 +1930,7 @@ typedef enum { + MOK_CHANGE_SB, + MOK_SET_PW, + MOK_CHANGE_DB, ++ MOK_CLEAR_VERIFY, + MOK_KEY_ENROLL, + MOK_HASH_ENROLL + } mok_menu_item; +@@ -1914,7 +1942,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; +@@ -1988,6 +2017,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) +@@ -2057,6 +2089,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++; +@@ -2107,6 +2145,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; +@@ -2132,6 +2173,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; +@@ -2139,6 +2181,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, +@@ -2211,9 +2254,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); +@@ -2236,6 +2290,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 3373a85..8a193cb 100644 +--- a/shim.c ++++ b/shim.c +@@ -1529,7 +1529,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) { +-- +1.8.4.5 + diff --git a/shim.changes b/shim.changes index 5441d64..c9c6887 100644 --- a/shim.changes +++ b/shim.changes @@ -1,3 +1,9 @@ +------------------------------------------------------------------- +Fri Feb 21 08:45:46 UTC 2014 - glin@suse.com + +- Add shim-opensuse-cert-prompt.patch to show the prompt to ask + whether the user trusts the openSUSE certificate or not + ------------------------------------------------------------------- Thu Feb 20 11:57:01 UTC 2014 - lnussel@suse.de diff --git a/shim.spec b/shim.spec index facbd8d..e81adda 100644 --- a/shim.spec +++ b/shim.spec @@ -60,6 +60,8 @@ Patch8: shim-get-variable-check.patch Patch9: shim-fallback-improve-entries-creation.patch # PATCH-FIX-UPSTREAM shim-bnc863205-mokmanager-fix-hash-delete.patch bnc#863205 glin@suse.com -- Fix the hash deletion operation to avoid ruining the whole list Patch10: shim-bnc863205-mokmanager-fix-hash-delete.patch +# PATCH-FIX-OPENSUSE shim-opensuse-cert-prompt.patch glin@suse.com -- Show the prompt to ask whether the user trusts openSUSE certificate or not +Patch100: shim-opensuse-cert-prompt.patch BuildRequires: gnu-efi >= 3.0t BuildRequires: mozilla-nss-tools BuildRequires: openssl >= 0.9.8 @@ -92,6 +94,7 @@ Authors: %patch8 -p1 %patch9 -p1 %patch10 -p1 +%patch100 -p1 %build # first, build MokManager and fallback as they don't depend on a