shim/shim-mokx-support.patch

1163 lines
33 KiB
Diff

From 8614cf8c164049e77d702eb234d608d5342e975b Mon Sep 17 00:00:00 2001
From: Gary Ching-Pang Lin <glin@suse.com>
Date: Thu, 24 Oct 2013 17:02:08 +0800
Subject: [PATCH 1/9] Support MOK blacklist
The new blacklist, MokListX, stores the keys and hashes that are
banned.
---
MokManager.c | 241 +++++++++++++++++++++++++++++++++++++++++++++++++----------
shim.c | 3 +-
2 files changed, 202 insertions(+), 42 deletions(-)
diff --git a/MokManager.c b/MokManager.c
index f5ed379..b9b42b6 100644
--- a/MokManager.c
+++ b/MokManager.c
@@ -701,23 +701,37 @@ static EFI_STATUS match_password (PASSWORD_CRYPT *pw_crypt,
return EFI_SUCCESS;
}
-static EFI_STATUS store_keys (void *MokNew, UINTN MokNewSize, int authenticate)
+static EFI_STATUS store_keys (void *MokNew, UINTN MokNewSize, int authenticate,
+ BOOLEAN MokX)
{
EFI_GUID shim_lock_guid = SHIM_LOCK_GUID;
EFI_STATUS efi_status;
+ CHAR16 *db_name;
+ CHAR16 *auth_name;
UINT8 auth[PASSWORD_CRYPT_SIZE];
UINTN auth_size = PASSWORD_CRYPT_SIZE;
UINT32 attributes;
+ if (MokX) {
+ db_name = L"MokListX";
+ auth_name = L"MokXAuth";
+ } else {
+ db_name = L"MokList";
+ auth_name = L"MokAuth";
+ }
+
if (authenticate) {
- efi_status = uefi_call_wrapper(RT->GetVariable, 5, L"MokAuth",
+ efi_status = uefi_call_wrapper(RT->GetVariable, 5, auth_name,
&shim_lock_guid,
&attributes, &auth_size, auth);
if (efi_status != EFI_SUCCESS ||
(auth_size != SHA256_DIGEST_SIZE &&
auth_size != PASSWORD_CRYPT_SIZE)) {
- console_error(L"Failed to get MokAuth", efi_status);
+ if (MokX)
+ console_error(L"Failed to get MokXAuth", efi_status);
+ else
+ console_error(L"Failed to get MokAuth", efi_status);
return efi_status;
}
@@ -734,14 +748,14 @@ static EFI_STATUS store_keys (void *MokNew, UINTN MokNewSize, int authenticate)
if (!MokNewSize) {
/* Delete MOK */
- efi_status = uefi_call_wrapper(RT->SetVariable, 5, L"MokList",
+ efi_status = uefi_call_wrapper(RT->SetVariable, 5, db_name,
&shim_lock_guid,
EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS,
0, NULL);
} else {
/* Write new MOK */
- efi_status = uefi_call_wrapper(RT->SetVariable, 5, L"MokList",
+ efi_status = uefi_call_wrapper(RT->SetVariable, 5, db_name,
&shim_lock_guid,
EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
@@ -757,17 +771,25 @@ static EFI_STATUS store_keys (void *MokNew, UINTN MokNewSize, int authenticate)
return EFI_SUCCESS;
}
-static UINTN mok_enrollment_prompt (void *MokNew, UINTN MokNewSize, int auth) {
+static UINTN mok_enrollment_prompt (void *MokNew, UINTN MokNewSize, int auth,
+ BOOLEAN MokX)
+{
EFI_GUID shim_lock_guid = SHIM_LOCK_GUID;
EFI_STATUS efi_status;
+ CHAR16 *title;
- if (list_keys(MokNew, MokNewSize, L"[Enroll MOK]") != EFI_SUCCESS)
+ if (MokX)
+ title = L"[Enroll MOKX]";
+ else
+ title = L"[Enroll MOK]";
+
+ if (list_keys(MokNew, MokNewSize, title) != EFI_SUCCESS)
return 0;
if (console_yes_no((CHAR16 *[]){L"Enroll the key(s)?", NULL}) == 0)
return 0;
- efi_status = store_keys(MokNew, MokNewSize, auth);
+ efi_status = store_keys(MokNew, MokNewSize, auth, MokX);
if (efi_status != EFI_SUCCESS) {
console_notify(L"Failed to enroll keys\n");
@@ -775,8 +797,13 @@ static UINTN mok_enrollment_prompt (void *MokNew, UINTN MokNewSize, int auth) {
}
if (auth) {
- LibDeleteVariable(L"MokNew", &shim_lock_guid);
- LibDeleteVariable(L"MokAuth", &shim_lock_guid);
+ if (MokX) {
+ LibDeleteVariable(L"MokXNew", &shim_lock_guid);
+ LibDeleteVariable(L"MokXAuth", &shim_lock_guid);
+ } else {
+ LibDeleteVariable(L"MokNew", &shim_lock_guid);
+ LibDeleteVariable(L"MokAuth", &shim_lock_guid);
+ }
console_notify(L"The system must now be rebooted");
uefi_call_wrapper(RT->ResetSystem, 4, EfiResetWarm,
@@ -788,25 +815,35 @@ static UINTN mok_enrollment_prompt (void *MokNew, UINTN MokNewSize, int auth) {
return 0;
}
-static INTN mok_reset_prompt ()
+static INTN mok_reset_prompt (BOOLEAN MokX)
{
EFI_GUID shim_lock_guid = SHIM_LOCK_GUID;
EFI_STATUS efi_status;
+ CHAR16 *prompt;
uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut);
- if (console_yes_no((CHAR16 *[]){L"Erase all stored keys?", NULL }) == 0)
+ if (MokX)
+ prompt = L"Erase all stored keys in MokListX?";
+ else
+ prompt = L"Erase all stored keys in MokList?";
+ if (console_yes_no((CHAR16 *[]){prompt, NULL }) == 0)
return 0;
- efi_status = store_keys(NULL, 0, TRUE);
+ efi_status = store_keys(NULL, 0, TRUE, MokX);
if (efi_status != EFI_SUCCESS) {
console_notify(L"Failed to erase keys\n");
return -1;
}
- LibDeleteVariable(L"MokNew", &shim_lock_guid);
- LibDeleteVariable(L"MokAuth", &shim_lock_guid);
+ if (MokX) {
+ LibDeleteVariable(L"MokXNew", &shim_lock_guid);
+ LibDeleteVariable(L"MokXAuth", &shim_lock_guid);
+ } else {
+ LibDeleteVariable(L"MokNew", &shim_lock_guid);
+ LibDeleteVariable(L"MokAuth", &shim_lock_guid);
+ }
console_notify(L"The system must now be rebooted");
uefi_call_wrapper(RT->ResetSystem, 4, EfiResetWarm,
@@ -815,7 +852,8 @@ static INTN mok_reset_prompt ()
return -1;
}
-static EFI_STATUS write_back_mok_list (MokListNode *list, INTN key_num)
+static EFI_STATUS write_back_mok_list (MokListNode *list, INTN key_num,
+ BOOLEAN MokX)
{
EFI_GUID shim_lock_guid = SHIM_LOCK_GUID;
EFI_STATUS efi_status;
@@ -824,6 +862,12 @@ static EFI_STATUS write_back_mok_list (MokListNode *list, INTN key_num)
void *Data = NULL, *ptr;
INTN DataSize = 0;
int i;
+ CHAR16 *db_name;
+
+ if (MokX)
+ db_name = L"MokListX";
+ else
+ db_name = L"MokList";
for (i = 0; i < key_num; i++) {
if (list[i].Mok == NULL)
@@ -861,7 +905,7 @@ static EFI_STATUS write_back_mok_list (MokListNode *list, INTN key_num)
sizeof(EFI_GUID) + list[i].MokSize;
}
- efi_status = uefi_call_wrapper(RT->SetVariable, 5, L"MokList",
+ efi_status = uefi_call_wrapper(RT->SetVariable, 5, db_name,
&shim_lock_guid,
EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS,
@@ -877,10 +921,14 @@ static EFI_STATUS write_back_mok_list (MokListNode *list, INTN key_num)
return EFI_SUCCESS;
}
-static EFI_STATUS delete_keys (void *MokDel, UINTN MokDelSize)
+static EFI_STATUS delete_keys (void *MokDel, UINTN MokDelSize, BOOLEAN MokX)
{
EFI_GUID shim_lock_guid = SHIM_LOCK_GUID;
EFI_STATUS efi_status;
+ CHAR16 *db_name;
+ CHAR16 *auth_name;
+ CHAR16 *err_str1;
+ CHAR16 *err_str2;
UINT8 auth[PASSWORD_CRYPT_SIZE];
UINTN auth_size = PASSWORD_CRYPT_SIZE;
UINT32 attributes;
@@ -890,13 +938,24 @@ static EFI_STATUS delete_keys (void *MokDel, UINTN MokDelSize)
INTN mok_num, del_num;
int i, j;
- efi_status = uefi_call_wrapper(RT->GetVariable, 5, L"MokDelAuth",
+ if (MokX) {
+ db_name = L"MokListX";
+ auth_name = L"MokXDelAuth";
+ } else {
+ db_name = L"MokList";
+ auth_name = L"MokDelAuth";
+ }
+
+ efi_status = uefi_call_wrapper(RT->GetVariable, 5, auth_name,
&shim_lock_guid,
&attributes, &auth_size, auth);
if (efi_status != EFI_SUCCESS ||
(auth_size != SHA256_DIGEST_SIZE && auth_size != PASSWORD_CRYPT_SIZE)) {
- console_error(L"Failed to get MokDelAuth", efi_status);
+ if (MokX)
+ console_error(L"Failed to get MokXDelAuth", efi_status);
+ else
+ console_error(L"Failed to get MokDelAuth", efi_status);
return efi_status;
}
@@ -909,15 +968,18 @@ static EFI_STATUS delete_keys (void *MokDel, UINTN MokDelSize)
if (efi_status != EFI_SUCCESS)
return EFI_ACCESS_DENIED;
- efi_status = get_variable_attr (L"MokList", &MokListData, &MokListDataSize,
+ efi_status = get_variable_attr (db_name, &MokListData, &MokListDataSize,
shim_lock_guid, &attributes);
if (attributes & EFI_VARIABLE_RUNTIME_ACCESS) {
- console_alertbox((CHAR16 *[]){L"MokList is compromised!",
- L"Erase all keys in MokList!",
- NULL});
- if (LibDeleteVariable(L"MokList", &shim_lock_guid) != EFI_SUCCESS) {
- console_notify(L"Failed to erase MokList");
+ if (MokX) {
+ err_str1 = L"MokListX is compromised!";
+ err_str2 = L"Erase all keys in MokListX!";
+ } else {
+ err_str1 = L"MokList is compromised!";
+ err_str2 = L"Erase all keys in MokList!";
}
+ console_alertbox((CHAR16 *[]){err_str1, err_str2, NULL});
+ LibDeleteVariable(db_name, &shim_lock_guid);
return EFI_ACCESS_DENIED;
}
@@ -945,7 +1007,7 @@ static EFI_STATUS delete_keys (void *MokDel, UINTN MokDelSize)
}
}
- efi_status = write_back_mok_list(mok, mok_num);
+ efi_status = write_back_mok_list(mok, mok_num, MokX);
if (MokListData)
FreePool(MokListData);
@@ -957,27 +1019,38 @@ static EFI_STATUS delete_keys (void *MokDel, UINTN MokDelSize)
return efi_status;
}
-static INTN mok_deletion_prompt (void *MokDel, UINTN MokDelSize)
+static INTN mok_deletion_prompt (void *MokDel, UINTN MokDelSize, BOOLEAN MokX)
{
EFI_GUID shim_lock_guid = SHIM_LOCK_GUID;
EFI_STATUS efi_status;
+ CHAR16 *title;
+
+ if (MokX)
+ title = L"[Delete MOKX]";
+ else
+ title = L"[Delete MOK]";
- if (list_keys(MokDel, MokDelSize, L"[Delete MOK]") != EFI_SUCCESS) {
+ if (list_keys(MokDel, MokDelSize, title) != EFI_SUCCESS) {
return 0;
}
if (console_yes_no((CHAR16 *[]){L"Delete the key(s)?", NULL}) == 0)
return 0;
- efi_status = delete_keys(MokDel, MokDelSize);
+ efi_status = delete_keys(MokDel, MokDelSize, MokX);
if (efi_status != EFI_SUCCESS) {
console_notify(L"Failed to delete keys");
return -1;
}
- LibDeleteVariable(L"MokDel", &shim_lock_guid);
- LibDeleteVariable(L"MokDelAuth", &shim_lock_guid);
+ if (MokX) {
+ LibDeleteVariable(L"MokXDel", &shim_lock_guid);
+ LibDeleteVariable(L"MokXDelAuth", &shim_lock_guid);
+ } else {
+ LibDeleteVariable(L"MokDel", &shim_lock_guid);
+ LibDeleteVariable(L"MokDelAuth", &shim_lock_guid);
+ }
console_notify(L"The system must now be rebooted");
uefi_call_wrapper(RT->ResetSystem, 4, EfiResetWarm,
@@ -1396,7 +1469,7 @@ static EFI_STATUS enroll_file (void *data, UINTN datasize, BOOLEAN hash)
goto out;
}
- mok_enrollment_prompt(mokbuffer, mokbuffersize, FALSE);
+ mok_enrollment_prompt(mokbuffer, mokbuffersize, FALSE, FALSE);
out:
if (mokbuffer)
FreePool(mokbuffer);
@@ -1631,8 +1704,11 @@ static int draw_countdown()
typedef enum {
MOK_CONTINUE_BOOT,
MOK_RESET_MOK,
+ MOK_RESET_MOKX,
MOK_ENROLL_MOK,
+ MOK_ENROLL_MOKX,
MOK_DELETE_MOK,
+ MOK_DELETE_MOKX,
MOK_CHANGE_SB,
MOK_SET_PW,
MOK_CHANGE_DB,
@@ -1645,13 +1721,17 @@ static EFI_STATUS enter_mok_menu(EFI_HANDLE image_handle,
void *MokDel, UINTN MokDelSize,
void *MokSB, UINTN MokSBSize,
void *MokPW, UINTN MokPWSize,
- void *MokDB, UINTN MokDBSize)
+ void *MokDB, UINTN MokDBSize,
+ void *MokXNew, UINTN MokXNewSize,
+ void *MokXDel, UINTN MokXDelSize)
{
CHAR16 **menu_strings;
mok_menu_item *menu_item;
int choice = 0;
UINT32 MokAuth = 0;
UINT32 MokDelAuth = 0;
+ UINT32 MokXAuth = 0;
+ UINT32 MokXDelAuth = 0;
UINTN menucount = 3, i = 0;
EFI_STATUS efi_status;
EFI_GUID shim_lock_guid = SHIM_LOCK_GUID;
@@ -1680,12 +1760,34 @@ static EFI_STATUS enter_mok_menu(EFI_HANDLE image_handle,
(auth_size == SHA256_DIGEST_SIZE || auth_size == PASSWORD_CRYPT_SIZE))
MokDelAuth = 1;
+ efi_status = uefi_call_wrapper(RT->GetVariable, 5, L"MokXAuth",
+ &shim_lock_guid,
+ &attributes, &auth_size, auth);
+
+ if ((efi_status == EFI_SUCCESS) &&
+ (auth_size == SHA256_DIGEST_SIZE || auth_size == PASSWORD_CRYPT_SIZE))
+ MokXAuth = 1;
+
+ efi_status = uefi_call_wrapper(RT->GetVariable, 5, L"MokXDelAuth",
+ &shim_lock_guid,
+ &attributes, &auth_size, auth);
+
+ if ((efi_status == EFI_SUCCESS) &&
+ (auth_size == SHA256_DIGEST_SIZE || auth_size == PASSWORD_CRYPT_SIZE))
+ MokXDelAuth = 1;
+
if (MokNew || MokAuth)
menucount++;
if (MokDel || MokDelAuth)
menucount++;
+ if (MokXNew || MokXAuth)
+ menucount++;
+
+ if (MokXDel || MokXDelAuth)
+ menucount++;
+
if (MokSB)
menucount++;
@@ -1723,12 +1825,29 @@ static EFI_STATUS enter_mok_menu(EFI_HANDLE image_handle,
i++;
}
- if (MokDel || MokDelAuth) {
+ if (MokDel || MokDelAuth) {
menu_strings[i] = L"Delete MOK";
menu_item[i] = MOK_DELETE_MOK;
i++;
}
+ if (MokXNew || MokXAuth) {
+ if (!MokXNew) {
+ menu_strings[i] = L"Reset MOKX";
+ menu_item[i] = MOK_RESET_MOKX;
+ } else {
+ menu_strings[i] = L"Enroll MOKX";
+ menu_item[i] = MOK_ENROLL_MOKX;
+ }
+ i++;
+ }
+
+ if (MokXDel || MokXDelAuth) {
+ menu_strings[i] = L"Delete MOKX";
+ menu_item[i] = MOK_DELETE_MOKX;
+ i++;
+ }
+
if (MokSB) {
menu_strings[i] = L"Change Secure Boot state";
menu_item[i] = MOK_CHANGE_SB;
@@ -1771,13 +1890,22 @@ static EFI_STATUS enter_mok_menu(EFI_HANDLE image_handle,
case MOK_CONTINUE_BOOT:
goto out;
case MOK_RESET_MOK:
- mok_reset_prompt();
+ mok_reset_prompt(FALSE);
break;
case MOK_ENROLL_MOK:
- mok_enrollment_prompt(MokNew, MokNewSize, TRUE);
+ mok_enrollment_prompt(MokNew, MokNewSize, TRUE, FALSE);
break;
case MOK_DELETE_MOK:
- mok_deletion_prompt(MokDel, MokDelSize);
+ mok_deletion_prompt(MokDel, MokDelSize, FALSE);
+ break;
+ case MOK_RESET_MOKX:
+ mok_reset_prompt(TRUE);
+ break;
+ case MOK_ENROLL_MOKX:
+ mok_enrollment_prompt(MokXNew, MokXNewSize, TRUE, TRUE);
+ break;
+ case MOK_DELETE_MOKX:
+ mok_deletion_prompt(MokXDel, MokXDelSize, TRUE);
break;
case MOK_CHANGE_SB:
mok_sb_prompt(MokSB, MokSBSize);
@@ -1811,13 +1939,15 @@ out:
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,
- MokDBSize = 0;
+ UINTN MokNewSize = 0, MokDelSize = 0, MokSBSize = 0, MokPWSize = 0;
+ UINTN MokDBSize = 0, MokXNewSize = 0, MokXDelSize = 0;
void *MokNew = NULL;
void *MokDel = NULL;
void *MokSB = NULL;
void *MokPW = NULL;
void *MokDB = NULL;
+ void *MokXNew = NULL;
+ void *MokXDel = NULL;
EFI_STATUS status;
status = get_variable(L"MokNew", (UINT8 **)&MokNew, &MokNewSize,
@@ -1870,8 +2000,29 @@ static EFI_STATUS check_mok_request(EFI_HANDLE image_handle)
console_error(L"Could not retrieve MokDB", status);
}
+ status = get_variable(L"MokXNew", (UINT8 **)&MokXNew, &MokXNewSize,
+ shim_lock_guid);
+ if (status == EFI_SUCCESS) {
+ if (LibDeleteVariable(L"MokXNew", &shim_lock_guid) != EFI_SUCCESS) {
+ console_notify(L"Failed to delete MokXNew");
+ }
+ } else if (EFI_ERROR(status) && status != EFI_NOT_FOUND) {
+ console_error(L"Could not retrieve MokXNew", status);
+ }
+
+ status = get_variable(L"MokXDel", (UINT8 **)&MokXDel, &MokXDelSize,
+ shim_lock_guid);
+ if (status == EFI_SUCCESS) {
+ if (LibDeleteVariable(L"MokXDel", &shim_lock_guid) != EFI_SUCCESS) {
+ console_notify(L"Failed to delete MokXDel");
+ }
+ } else if (EFI_ERROR(status) && status != EFI_NOT_FOUND) {
+ console_error(L"Could not retrieve MokXDel", status);
+ }
+
enter_mok_menu(image_handle, MokNew, MokNewSize, MokDel, MokDelSize,
- MokSB, MokSBSize, MokPW, MokPWSize, MokDB, MokDBSize);
+ MokSB, MokSBSize, MokPW, MokPWSize, MokDB, MokDBSize,
+ MokXNew, MokXNewSize, MokXDel, MokXDelSize);
if (MokNew)
FreePool (MokNew);
@@ -1888,8 +2039,16 @@ static EFI_STATUS check_mok_request(EFI_HANDLE image_handle)
if (MokDB)
FreePool (MokDB);
+ if (MokXNew)
+ FreePool (MokXNew);
+
+ if (MokXDel)
+ FreePool (MokXDel);
+
LibDeleteVariable(L"MokAuth", &shim_lock_guid);
LibDeleteVariable(L"MokDelAuth", &shim_lock_guid);
+ LibDeleteVariable(L"MokXAuth", &shim_lock_guid);
+ LibDeleteVariable(L"MokXDelAuth", &shim_lock_guid);
return EFI_SUCCESS;
}
diff --git a/shim.c b/shim.c
index 9ae1936..c133bb2 100644
--- a/shim.c
+++ b/shim.c
@@ -1510,7 +1510,8 @@ EFI_STATUS check_mok_request(EFI_HANDLE image_handle)
if (check_var(L"MokNew") || check_var(L"MokSB") ||
check_var(L"MokPW") || check_var(L"MokAuth") ||
- check_var(L"MokDel") || check_var(L"MokDB")) {
+ check_var(L"MokDel") || check_var(L"MokDB") ||
+ check_var(L"MokXNew") || check_var(L"MokXDel")) {
efi_status = start_image(image_handle, MOK_MANAGER);
if (efi_status != EFI_SUCCESS) {
--
1.8.1.4
From f36f4093bb72344242949b16b83905cefb93d3cd Mon Sep 17 00:00:00 2001
From: Gary Ching-Pang Lin <glin@suse.com>
Date: Thu, 24 Oct 2013 17:32:31 +0800
Subject: [PATCH 2/9] MokManager: show the hash list properly
---
MokManager.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++++--------
1 file changed, 71 insertions(+), 11 deletions(-)
diff --git a/MokManager.c b/MokManager.c
index b9b42b6..5575a94 100644
--- a/MokManager.c
+++ b/MokManager.c
@@ -165,9 +165,16 @@ static MokListNode *build_mok_list(UINT32 num, void *Data, UINTN DataSize) {
Cert = (EFI_SIGNATURE_DATA *) (((UINT8 *) CertList) +
sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);
- list[count].MokSize = CertList->SignatureSize - sizeof(EFI_GUID);
- list[count].Mok = (void *)Cert->SignatureData;
list[count].Type = CertList->SignatureType;
+ if (CompareGuid (&CertList->SignatureType, &CertType) == 0) {
+ list[count].MokSize = CertList->SignatureSize -
+ sizeof(EFI_GUID);
+ list[count].Mok = (void *)Cert->SignatureData;
+ } else {
+ list[count].MokSize = CertList->SignatureListSize -
+ sizeof(EFI_SIGNATURE_LIST);
+ list[count].Mok = (void *)Cert;
+ }
count++;
dbsize -= CertList->SignatureListSize;
@@ -373,7 +380,7 @@ static void show_x509_info (X509 *X509Cert, UINT8 *hash)
FreePool(text);
}
-static void show_efi_hash (UINT8 *hash)
+static void show_sha256_digest (UINT8 *hash)
{
CHAR16 *text[5];
POOL_PRINT hash_string1;
@@ -404,16 +411,68 @@ static void show_efi_hash (UINT8 *hash)
FreePool(hash_string2.str);
}
-static void show_mok_info (void *Mok, UINTN MokSize)
+static void show_efi_hash (void *Mok, UINTN MokSize)
+{
+ UINTN sig_size;
+ UINTN hash_num;
+ UINT8 *hash;
+ CHAR16 **menu_strings;
+ int key_num = 0;
+ int i;
+
+ sig_size = SHA256_DIGEST_SIZE + sizeof(EFI_GUID);
+ if ((MokSize % sig_size) != 0) {
+ console_errorbox(L"Corrupted Hash List");
+ return;
+ }
+ hash_num = MokSize / sig_size;
+
+ if (hash_num == 1) {
+ hash = (UINT8 *)Mok + sizeof(EFI_GUID);
+ show_sha256_digest(hash);
+ return;
+ }
+
+ menu_strings = AllocateZeroPool(sizeof(CHAR16 *) * (hash_num + 2));
+ if (!menu_strings) {
+ console_errorbox(L"Out of Resources");
+ return;
+ }
+ for (i=0; i<hash_num; i++) {
+ menu_strings[i] = PoolPrint(L"View hash %d", i);
+ }
+ menu_strings[i] = StrDuplicate(L"Continue");
+ menu_strings[i+1] = NULL;
+
+ while (key_num < hash_num) {
+ key_num = console_select((CHAR16 *[]){ L"[Hash List]", NULL },
+ menu_strings, 0);
+
+ if (key_num < 0 || key_num >= hash_num)
+ break;
+
+ hash = (UINT8 *)Mok + sig_size*key_num + sizeof(EFI_GUID);
+ show_sha256_digest(hash);
+ }
+
+ for (i=0; menu_strings[i] != NULL; i++)
+ FreePool(menu_strings[i]);
+
+ FreePool(menu_strings);
+}
+
+static void show_mok_info (EFI_GUID Type, void *Mok, UINTN MokSize)
{
EFI_STATUS efi_status;
UINT8 hash[SHA1_DIGEST_SIZE];
X509 *X509Cert;
+ EFI_GUID CertType = X509_GUID;
+ EFI_GUID HashType = EFI_CERT_SHA256_GUID;
if (!Mok || MokSize == 0)
return;
- if (MokSize != SHA256_DIGEST_SIZE) {
+ if (CompareGuid (&Type, &CertType) == 0) {
efi_status = get_sha1sum(Mok, MokSize, hash);
if (efi_status != EFI_SUCCESS) {
@@ -429,8 +488,8 @@ static void show_mok_info (void *Mok, UINTN MokSize)
console_notify(L"Not a valid X509 certificate");
return;
}
- } else {
- show_efi_hash(Mok);
+ } else if (CompareGuid (&Type, &HashType) == 0) {
+ show_efi_hash(Mok, MokSize);
}
}
@@ -438,7 +497,7 @@ static EFI_STATUS list_keys (void *KeyList, UINTN KeyListSize, CHAR16 *title)
{
UINT32 MokNum = 0;
MokListNode *keys = NULL;
- INTN key_num = 0;
+ int key_num = 0;
CHAR16 **menu_strings;
int i;
@@ -472,10 +531,11 @@ static EFI_STATUS list_keys (void *KeyList, UINTN KeyListSize, CHAR16 *title)
key_num = console_select((CHAR16 *[]){ title, NULL },
menu_strings, 0);
- if (key_num < 0)
+ if (key_num < 0 || key_num >= MokNum)
break;
- else if (key_num < MokNum)
- show_mok_info(keys[key_num].Mok, keys[key_num].MokSize);
+
+ show_mok_info(keys[key_num].Type, keys[key_num].Mok,
+ keys[key_num].MokSize);
}
for (i=0; menu_strings[i] != NULL; i++)
--
1.8.1.4
From f1073a9bc757008d44b5b86cb5002a3654faf2d2 Mon Sep 17 00:00:00 2001
From: Gary Ching-Pang Lin <glin@suse.com>
Date: Fri, 25 Oct 2013 16:54:25 +0800
Subject: [PATCH 3/9] MokManager: delete the hash properly
---
MokManager.c | 124 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
1 file changed, 114 insertions(+), 10 deletions(-)
diff --git a/MokManager.c b/MokManager.c
index 5575a94..23bdeef 100644
--- a/MokManager.c
+++ b/MokManager.c
@@ -981,9 +981,116 @@ static EFI_STATUS write_back_mok_list (MokListNode *list, INTN key_num,
return EFI_SUCCESS;
}
+static void delete_cert (void *key, UINT32 key_size,
+ MokListNode *mok, INTN mok_num)
+{
+ EFI_GUID CertType = X509_GUID;
+ int i;
+
+ for (i = 0; i < mok_num; i++) {
+ if (CompareGuid(&(mok[i].Type), &CertType) != 0)
+ continue;
+
+ if (mok[i].MokSize == key_size &&
+ CompareMem(key, mok[i].Mok, key_size) == 0) {
+ /* Remove the key */
+ mok[i].Mok = NULL;
+ mok[i].MokSize = 0;
+ }
+ }
+}
+
+static int match_hash (UINT8 *hash, UINT32 hash_size,
+ void *hash_list, UINT32 list_num)
+{
+ UINT8 *ptr;
+ int i;
+
+ ptr = hash_list + sizeof(EFI_GUID);
+ for (i = 0; i < list_num; i++) {
+ if (CompareMem(hash, ptr, hash_size) == 0)
+ return i;
+ ptr += hash_size + sizeof(EFI_GUID);
+ }
+
+ return -1;
+}
+
+static void mem_move (void *dest, void *src, UINTN size)
+{
+ UINT8 *d, *s;
+ int i;
+
+ d = (UINT8 *)dest;
+ s = (UINT8 *)src;
+ for (i = 0; i < size; i++)
+ d[i] = s[i];
+}
+
+static void delete_hash_in_list (UINT8 *hash, UINT32 hash_size,
+ MokListNode *mok, INTN mok_num)
+{
+ EFI_GUID HashType = EFI_CERT_SHA256_GUID;
+ UINT32 sig_size;
+ int i, del_ind;
+ void *start, *end;
+ UINT32 remain;
+
+ sig_size = hash_size + sizeof(EFI_GUID);
+
+ for (i = 0; i < mok_num; i++) {
+ if ((CompareGuid(&(mok[i].Type), &HashType) != 0) ||
+ (mok[i].MokSize < sig_size))
+ continue;
+
+ del_ind = match_hash(hash, hash_size, mok[i].Mok,
+ mok[i].MokSize);
+ if (del_ind < 0)
+ continue;
+ /* Remove the hash */
+ if (sig_size == mok[i].MokSize) {
+ mok[i].Mok = NULL;
+ mok[i].MokSize = 0;
+ } else {
+ start = mok[i].Mok + del_ind * sig_size;
+ end = start + sig_size;
+ remain = mok[i].MokSize - (del_ind + 1)*sig_size;
+
+ mem_move(start, end, remain);
+ mok[i].MokSize -= sig_size;
+ }
+ }
+}
+
+static void delete_hash_list (void *hash_list, UINT32 list_size,
+ MokListNode *mok, INTN mok_num)
+{
+ UINT32 hash_size;
+ UINT32 hash_num;
+ UINT32 sig_size;
+ UINT8 *hash;
+ int i;
+
+ hash_size = SHA256_DIGEST_SIZE;
+ sig_size = hash_size + sizeof(EFI_GUID);
+ if (list_size < sig_size)
+ return;
+
+ hash_num = list_size / sig_size;
+
+ hash = hash_list + sizeof(EFI_GUID);
+
+ for (i = 0; i < hash_num; i++) {
+ delete_hash_in_list (hash, hash_size, mok, mok_num);
+ hash += sig_size;
+ }
+}
+
static EFI_STATUS delete_keys (void *MokDel, UINTN MokDelSize, BOOLEAN MokX)
{
EFI_GUID shim_lock_guid = SHIM_LOCK_GUID;
+ EFI_GUID CertType = X509_GUID;
+ EFI_GUID HashType = EFI_CERT_SHA256_GUID;
EFI_STATUS efi_status;
CHAR16 *db_name;
CHAR16 *auth_name;
@@ -996,7 +1103,7 @@ static EFI_STATUS delete_keys (void *MokDel, UINTN MokDelSize, BOOLEAN MokX)
UINTN MokListDataSize = 0;
MokListNode *mok, *del_key;
INTN mok_num, del_num;
- int i, j;
+ int i;
if (MokX) {
db_name = L"MokListX";
@@ -1055,15 +1162,12 @@ static EFI_STATUS delete_keys (void *MokDel, UINTN MokDelSize, BOOLEAN MokX)
/* Search and destroy */
for (i = 0; i < del_num; i++) {
- UINT32 key_size = del_key[i].MokSize;
- void *key = del_key[i].Mok;
- for (j = 0; j < mok_num; j++) {
- if (mok[j].MokSize == key_size &&
- CompareMem(key, mok[j].Mok, key_size) == 0) {
- /* Remove the key */
- mok[j].Mok = NULL;
- mok[j].MokSize = 0;
- }
+ if (CompareGuid(&(del_key[i].Type), &CertType) == 0) {
+ delete_cert(del_key[i].Mok, del_key[i].MokSize,
+ mok, mok_num);
+ } else if (CompareGuid(&(del_key[i].Type), &HashType) == 0) {
+ delete_hash_list(del_key[i].Mok, del_key[i].MokSize,
+ mok, mok_num);
}
}
--
1.8.1.4
From b5cb83a92620b0b41857f3e3a292d1577eb3a3a5 Mon Sep 17 00:00:00 2001
From: Gary Ching-Pang Lin <glin@suse.com>
Date: Fri, 25 Oct 2013 17:05:10 +0800
Subject: [PATCH 4/9] MokManager: Match all hashes in the list
---
MokManager.c | 24 ++++++++++++++----------
1 file changed, 14 insertions(+), 10 deletions(-)
diff --git a/MokManager.c b/MokManager.c
index 23bdeef..5b40e19 100644
--- a/MokManager.c
+++ b/MokManager.c
@@ -1000,14 +1000,14 @@ static void delete_cert (void *key, UINT32 key_size,
}
}
-static int match_hash (UINT8 *hash, UINT32 hash_size,
+static int match_hash (UINT8 *hash, UINT32 hash_size, int start,
void *hash_list, UINT32 list_num)
{
UINT8 *ptr;
int i;
ptr = hash_list + sizeof(EFI_GUID);
- for (i = 0; i < list_num; i++) {
+ for (i = start; i < list_num; i++) {
if (CompareMem(hash, ptr, hash_size) == 0)
return i;
ptr += hash_size + sizeof(EFI_GUID);
@@ -1043,21 +1043,25 @@ static void delete_hash_in_list (UINT8 *hash, UINT32 hash_size,
(mok[i].MokSize < sig_size))
continue;
- del_ind = match_hash(hash, hash_size, mok[i].Mok,
+ del_ind = match_hash(hash, hash_size, 0, mok[i].Mok,
mok[i].MokSize);
- if (del_ind < 0)
- continue;
- /* Remove the hash */
- if (sig_size == mok[i].MokSize) {
- mok[i].Mok = NULL;
- mok[i].MokSize = 0;
- } else {
+ while (del_ind >= 0) {
+ /* Remove the hash */
+ if (sig_size == mok[i].MokSize) {
+ mok[i].Mok = NULL;
+ mok[i].MokSize = 0;
+ break;
+ }
+
start = mok[i].Mok + del_ind * sig_size;
end = start + sig_size;
remain = mok[i].MokSize - (del_ind + 1)*sig_size;
mem_move(start, end, remain);
mok[i].MokSize -= sig_size;
+
+ del_ind = match_hash(hash, hash_size, del_ind,
+ mok[i].Mok, mok[i].MokSize);
}
}
}
--
1.8.1.4
From 70a4e12d2e6ba37541d0b78ec3c8ed5e8da9a941 Mon Sep 17 00:00:00 2001
From: Gary Ching-Pang Lin <glin@suse.com>
Date: Fri, 25 Oct 2013 18:30:48 +0800
Subject: [PATCH 5/9] MokManager: Write the hash list properly
also return to the previous entry in the list
---
MokManager.c | 30 +++++++++++++++++++-----------
1 file changed, 19 insertions(+), 11 deletions(-)
diff --git a/MokManager.c b/MokManager.c
index 5b40e19..e79a8e0 100644
--- a/MokManager.c
+++ b/MokManager.c
@@ -441,12 +441,12 @@ static void show_efi_hash (void *Mok, UINTN MokSize)
for (i=0; i<hash_num; i++) {
menu_strings[i] = PoolPrint(L"View hash %d", i);
}
- menu_strings[i] = StrDuplicate(L"Continue");
+ menu_strings[i] = StrDuplicate(L"Back");
menu_strings[i+1] = NULL;
while (key_num < hash_num) {
key_num = console_select((CHAR16 *[]){ L"[Hash List]", NULL },
- menu_strings, 0);
+ menu_strings, key_num);
if (key_num < 0 || key_num >= hash_num)
break;
@@ -529,7 +529,7 @@ static EFI_STATUS list_keys (void *KeyList, UINTN KeyListSize, CHAR16 *title)
while (key_num < MokNum) {
key_num = console_select((CHAR16 *[]){ title, NULL },
- menu_strings, 0);
+ menu_strings, key_num);
if (key_num < 0 || key_num >= MokNum)
break;
@@ -916,6 +916,7 @@ static EFI_STATUS write_back_mok_list (MokListNode *list, INTN key_num,
BOOLEAN MokX)
{
EFI_GUID shim_lock_guid = SHIM_LOCK_GUID;
+ EFI_GUID CertType = X509_GUID;
EFI_STATUS efi_status;
EFI_SIGNATURE_LIST *CertList;
EFI_SIGNATURE_DATA *CertData;
@@ -952,17 +953,24 @@ static EFI_STATUS write_back_mok_list (MokListNode *list, INTN key_num,
sizeof(EFI_SIGNATURE_LIST));
CertList->SignatureType = list[i].Type;
- CertList->SignatureListSize = list[i].MokSize +
- sizeof(EFI_SIGNATURE_LIST) +
- sizeof(EFI_SIGNATURE_DATA) - 1;
CertList->SignatureHeaderSize = 0;
- CertList->SignatureSize = list[i].MokSize + sizeof(EFI_GUID);
- CertData->SignatureOwner = shim_lock_guid;
- CopyMem(CertData->SignatureData, list[i].Mok, list[i].MokSize);
+ if (CompareGuid(&(list[i].Type), &CertType) == 0) {
+ CertList->SignatureListSize = list[i].MokSize +
+ sizeof(EFI_SIGNATURE_LIST) +
+ sizeof(EFI_GUID);
+ CertList->SignatureSize = list[i].MokSize + sizeof(EFI_GUID);
- ptr = (uint8_t *)ptr + sizeof(EFI_SIGNATURE_LIST) +
- sizeof(EFI_GUID) + list[i].MokSize;
+ CertData->SignatureOwner = shim_lock_guid;
+ CopyMem(CertData->SignatureData, list[i].Mok, list[i].MokSize);
+ } else {
+ CertList->SignatureListSize = list[i].MokSize +
+ sizeof(EFI_SIGNATURE_LIST);
+ CertList->SignatureSize = SHA256_DIGEST_SIZE + sizeof(EFI_GUID);
+
+ CopyMem(CertData, list[i].Mok, list[i].MokSize);
+ }
+ ptr = (uint8_t *)ptr + CertList->SignatureListSize;
}
efi_status = uefi_call_wrapper(RT->SetVariable, 5, db_name,
--
1.8.1.4
From 225e5fca2f7cf63e365b77243d6e43b1eb9860c8 Mon Sep 17 00:00:00 2001
From: Gary Ching-Pang Lin <glin@suse.com>
Date: Mon, 28 Oct 2013 15:08:40 +0800
Subject: [PATCH 6/9] Copy the MOK blacklist to a RT variable
---
shim.c | 29 +++++++++++++++++++++++++++++
1 file changed, 29 insertions(+)
diff --git a/shim.c b/shim.c
index c133bb2..a0383a8 100644
--- a/shim.c
+++ b/shim.c
@@ -1480,6 +1480,33 @@ EFI_STATUS mirror_mok_list()
}
/*
+ * Copy the boot-services only MokListX variable to the runtime-accessible
+ * MokListXRT variable. It's not marked NV, so the OS can't modify it.
+ */
+EFI_STATUS mirror_mok_list_x()
+{
+ EFI_GUID shim_lock_guid = SHIM_LOCK_GUID;
+ EFI_STATUS efi_status;
+ UINT8 *Data = NULL;
+ UINTN DataSize = 0;
+
+ efi_status = get_variable(L"MokListX", &Data, &DataSize, shim_lock_guid);
+ if (efi_status != EFI_SUCCESS)
+ return efi_status;
+
+ efi_status = uefi_call_wrapper(RT->SetVariable, 5, L"MokListXRT",
+ &shim_lock_guid,
+ EFI_VARIABLE_BOOTSERVICE_ACCESS
+ | EFI_VARIABLE_RUNTIME_ACCESS,
+ DataSize, Data);
+ if (efi_status != EFI_SUCCESS) {
+ console_error(L"Failed to set MokListRT", efi_status);
+ }
+
+ return efi_status;
+}
+
+/*
* Check if a variable exists
*/
static BOOLEAN check_var(CHAR16 *varname)
@@ -1795,6 +1822,8 @@ EFI_STATUS efi_main (EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *passed_systab)
*/
efi_status = mirror_mok_list();
+ efi_status = mirror_mok_list_x();
+
/*
* Create the runtime MokIgnoreDB variable so the kernel can make
* use of it
--
1.8.1.4
From f9db55b719281ce491780ecd4ec269c5286a7251 Mon Sep 17 00:00:00 2001
From: Gary Ching-Pang Lin <glin@suse.com>
Date: Mon, 28 Oct 2013 16:36:34 +0800
Subject: [PATCH 7/9] No newline for console_notify
---
shim.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/shim.c b/shim.c
index a0383a8..a2e0862 100644
--- a/shim.c
+++ b/shim.c
@@ -470,7 +470,7 @@ static BOOLEAN secure_mode (void)
if (sb != 1) {
if (verbose)
- console_notify(L"Secure boot not enabled\n");
+ console_notify(L"Secure boot not enabled");
return FALSE;
}
@@ -483,7 +483,7 @@ static BOOLEAN secure_mode (void)
if (setupmode == 1) {
if (verbose)
- console_notify(L"Platform is in setup mode\n");
+ console_notify(L"Platform is in setup mode");
return FALSE;
}
--
1.8.1.4
From 0bf2da5c7d9442f3249fc977b3fbffab924a374c Mon Sep 17 00:00:00 2001
From: Gary Ching-Pang Lin <glin@suse.com>
Date: Mon, 4 Nov 2013 14:45:33 +0800
Subject: [PATCH 8/9] Verify the EFI images with MOK blacklist
Signed-off-by: Gary Ching-Pang Lin <glin@suse.com>
---
shim.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/shim.c b/shim.c
index a2e0862..5f5e9a6 100644
--- a/shim.c
+++ b/shim.c
@@ -365,6 +365,7 @@ static EFI_STATUS check_blacklist (WIN_CERTIFICATE_EFI_PKCS *cert,
UINT8 *sha256hash, UINT8 *sha1hash)
{
EFI_GUID secure_var = EFI_IMAGE_SECURITY_DATABASE_GUID;
+ EFI_GUID shim_var = SHIM_LOCK_GUID;
EFI_SIGNATURE_LIST *dbx = (EFI_SIGNATURE_LIST *)vendor_dbx;
if (check_db_hash_in_ram(dbx, vendor_dbx_size, sha256hash,
@@ -388,6 +389,14 @@ static EFI_STATUS check_blacklist (WIN_CERTIFICATE_EFI_PKCS *cert,
if (cert && check_db_cert(L"dbx", secure_var, cert, sha256hash) ==
DATA_FOUND)
return EFI_ACCESS_DENIED;
+ if (check_db_hash(L"MokListX", shim_var, sha256hash, SHA256_DIGEST_SIZE,
+ EFI_CERT_SHA256_GUID) == DATA_FOUND) {
+ return EFI_ACCESS_DENIED;
+ }
+ if (cert && check_db_cert(L"MokListX", shim_var, cert, sha256hash) ==
+ DATA_FOUND) {
+ return EFI_ACCESS_DENIED;
+ }
return EFI_SUCCESS;
}
--
1.8.1.4
From 20ced27d1785bceaf814c07ca0d5686506a119ad Mon Sep 17 00:00:00 2001
From: Gary Ching-Pang Lin <glin@suse.com>
Date: Mon, 4 Nov 2013 17:51:55 +0800
Subject: [PATCH 9/9] Exclude ca.crt while signing EFI images
If ca.crt was added into the certificate database, ca.crt would be the first
certificate in the signature. Because shim couldn't verify ca.crt with the
embedded shim.cer, it failed to load MokManager.efi.signed and
fallback.efi.signed.
Signed-off-by: Gary Ching-Pang Lin <glin@suse.com>
---
Makefile | 1 -
1 file changed, 1 deletion(-)
diff --git a/Makefile b/Makefile
index e65d28d..5e3fa9e 100644
--- a/Makefile
+++ b/Makefile
@@ -72,7 +72,6 @@ version.c : version.c.in
certdb/secmod.db: shim.crt
-mkdir certdb
- certutil -A -n 'my CA' -d certdb/ -t CT,CT,CT -i ca.crt
pk12util -d certdb/ -i shim.p12 -W "" -K ""
certutil -d certdb/ -A -i shim.crt -n shim -t u
--
1.8.1.4