the preboot loader for UEFI secureboot OBS-URL: https://build.opensuse.org/request/show/148684 OBS-URL: https://build.opensuse.org/package/show/openSUSE:Factory/shim?expand=0&rev=1
764 lines
21 KiB
Diff
764 lines
21 KiB
Diff
From 5abe73ab8177f0d831ff04ca67a8ed92ef09ca8b Mon Sep 17 00:00:00 2001
|
|
From: Gary Ching-Pang Lin <glin@suse.com>
|
|
Date: Thu, 20 Dec 2012 17:02:35 +0800
|
|
Subject: [PATCH 1/3] Add a general function for password matching
|
|
|
|
---
|
|
MokManager.c | 148 ++++++++++++++++++++++------------------------------------
|
|
1 file changed, 57 insertions(+), 91 deletions(-)
|
|
|
|
diff --git a/MokManager.c b/MokManager.c
|
|
index 7d6650e..ffe37ff 100644
|
|
--- a/MokManager.c
|
|
+++ b/MokManager.c
|
|
@@ -558,17 +558,61 @@ done:
|
|
return status;
|
|
}
|
|
|
|
+static EFI_STATUS match_password (void *Data, UINTN DataSize,
|
|
+ UINT8 auth[SHA256_DIGEST_SIZE],
|
|
+ CHAR16 *prompt)
|
|
+{
|
|
+ EFI_STATUS efi_status;
|
|
+ UINT8 hash[SHA256_DIGEST_SIZE];
|
|
+ CHAR16 password[PASSWORD_MAX];
|
|
+ UINT32 pw_length;
|
|
+ UINT8 fail_count = 0;
|
|
+
|
|
+ while (fail_count < 3) {
|
|
+ if (prompt) {
|
|
+ Print(L"%s", prompt);
|
|
+ } else {
|
|
+ Print(L"Password: ");
|
|
+ }
|
|
+ get_line(&pw_length, password, PASSWORD_MAX, 0);
|
|
+
|
|
+ if (pw_length < PASSWORD_MIN || pw_length > PASSWORD_MAX) {
|
|
+ Print(L"Invalid password length\n");
|
|
+ fail_count++;
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ efi_status = compute_pw_hash(Data, DataSize, password,
|
|
+ pw_length, hash);
|
|
+
|
|
+ if (efi_status != EFI_SUCCESS) {
|
|
+ Print(L"Unable to generate password hash\n");
|
|
+ fail_count++;
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ if (CompareMem(auth, hash, SHA256_DIGEST_SIZE) != 0) {
|
|
+ Print(L"Password doesn't match\n");
|
|
+ fail_count++;
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ if (fail_count >= 3)
|
|
+ return EFI_ACCESS_DENIED;
|
|
+
|
|
+ return EFI_SUCCESS;
|
|
+}
|
|
+
|
|
static EFI_STATUS store_keys (void *MokNew, UINTN MokNewSize, int authenticate)
|
|
{
|
|
EFI_GUID shim_lock_guid = SHIM_LOCK_GUID;
|
|
EFI_STATUS efi_status;
|
|
- UINT8 hash[SHA256_DIGEST_SIZE];
|
|
UINT8 auth[SHA256_DIGEST_SIZE];
|
|
UINTN auth_size;
|
|
UINT32 attributes;
|
|
- CHAR16 password[PASSWORD_MAX];
|
|
- UINT32 pw_length;
|
|
- UINT8 fail_count = 0;
|
|
|
|
if (authenticate) {
|
|
auth_size = SHA256_DIGEST_SIZE;
|
|
@@ -582,32 +626,8 @@ static EFI_STATUS store_keys (void *MokNew, UINTN MokNewSize, int authenticate)
|
|
return efi_status;
|
|
}
|
|
|
|
- while (fail_count < 3) {
|
|
- Print(L"Password(%d-%d characters): ",
|
|
- PASSWORD_MIN, PASSWORD_MAX);
|
|
- get_line(&pw_length, password, PASSWORD_MAX, 0);
|
|
-
|
|
- if (pw_length < 8) {
|
|
- Print(L"At least %d characters for the password\n",
|
|
- PASSWORD_MIN);
|
|
- }
|
|
-
|
|
- efi_status = compute_pw_hash(MokNew, MokNewSize, password,
|
|
- pw_length, hash);
|
|
-
|
|
- if (efi_status != EFI_SUCCESS) {
|
|
- return efi_status;
|
|
- }
|
|
-
|
|
- if (CompareMem(auth, hash, SHA256_DIGEST_SIZE) != 0) {
|
|
- Print(L"Password doesn't match\n");
|
|
- fail_count++;
|
|
- } else {
|
|
- break;
|
|
- }
|
|
- }
|
|
-
|
|
- if (fail_count >= 3)
|
|
+ efi_status = match_password(MokNew, MokNewSize, auth, NULL);
|
|
+ if (efi_status != EFI_SUCCESS)
|
|
return EFI_ACCESS_DENIED;
|
|
}
|
|
|
|
@@ -819,9 +839,7 @@ static INTN mok_pw_prompt (void *MokPW, void *data2, void *data3) {
|
|
EFI_GUID shim_lock_guid = SHIM_LOCK_GUID;
|
|
EFI_STATUS efi_status;
|
|
UINTN MokPWSize = (UINTN)data2;
|
|
- UINT8 fail_count = 0;
|
|
UINT8 hash[SHA256_DIGEST_SIZE];
|
|
- CHAR16 password[PASSWORD_MAX];
|
|
UINT32 length;
|
|
CHAR16 line[1];
|
|
|
|
@@ -849,34 +867,8 @@ static INTN mok_pw_prompt (void *MokPW, void *data2, void *data3) {
|
|
return 0;
|
|
}
|
|
|
|
- while (fail_count < 3) {
|
|
- Print(L"Confirm MOK passphrase: ");
|
|
- get_line(&length, password, PASSWORD_MAX, 0);
|
|
-
|
|
- if ((length < PASSWORD_MIN) || (length > PASSWORD_MAX)) {
|
|
- Print(L"Invalid password length\n");
|
|
- fail_count++;
|
|
- continue;
|
|
- }
|
|
-
|
|
- efi_status = compute_pw_hash(NULL, 0, password, length, hash);
|
|
-
|
|
- if (efi_status != EFI_SUCCESS) {
|
|
- Print(L"Unable to generate password hash\n");
|
|
- fail_count++;
|
|
- continue;
|
|
- }
|
|
-
|
|
- if (CompareMem(MokPW, hash, SHA256_DIGEST_SIZE) != 0) {
|
|
- Print(L"Password doesn't match\n");
|
|
- fail_count++;
|
|
- continue;
|
|
- }
|
|
-
|
|
- break;
|
|
- }
|
|
-
|
|
- if (fail_count >= 3) {
|
|
+ efi_status = match_password(NULL, 0, MokPW, L"Confirm MOK passphrase: ");
|
|
+ if (efi_status != EFI_SUCCESS) {
|
|
Print(L"Password limit reached\n");
|
|
return -1;
|
|
}
|
|
@@ -1483,12 +1475,8 @@ static BOOLEAN verify_pw(void)
|
|
{
|
|
EFI_GUID shim_lock_guid = SHIM_LOCK_GUID;
|
|
EFI_STATUS efi_status;
|
|
- CHAR16 password[PASSWORD_MAX];
|
|
- UINT8 fail_count = 0;
|
|
- UINT8 hash[SHA256_DIGEST_SIZE];
|
|
UINT8 pwhash[SHA256_DIGEST_SIZE];
|
|
UINTN size = SHA256_DIGEST_SIZE;
|
|
- UINT32 length;
|
|
UINT32 attributes;
|
|
|
|
efi_status = uefi_call_wrapper(RT->GetVariable, 5, L"MokPWStore",
|
|
@@ -1508,35 +1496,13 @@ static BOOLEAN verify_pw(void)
|
|
|
|
uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut);
|
|
|
|
- while (fail_count < 3) {
|
|
- Print(L"Enter MOK password: ");
|
|
- get_line(&length, password, PASSWORD_MAX, 0);
|
|
-
|
|
- if (length < PASSWORD_MIN || length > PASSWORD_MAX) {
|
|
- Print(L"Invalid password length\n");
|
|
- fail_count++;
|
|
- continue;
|
|
- }
|
|
-
|
|
- efi_status = compute_pw_hash(NULL, 0, password, length, hash);
|
|
-
|
|
- if (efi_status != EFI_SUCCESS) {
|
|
- Print(L"Unable to generate password hash\n");
|
|
- fail_count++;
|
|
- continue;
|
|
- }
|
|
-
|
|
- if (CompareMem(pwhash, hash, SHA256_DIGEST_SIZE) != 0) {
|
|
- Print(L"Password doesn't match\n");
|
|
- fail_count++;
|
|
- continue;
|
|
- }
|
|
-
|
|
- return TRUE;
|
|
+ efi_status = match_password(NULL, 0, pwhash, L"Enter MOK password: ");
|
|
+ if (efi_status != EFI_SUCCESS) {
|
|
+ Print(L"Password limit reached\n");
|
|
+ return FALSE;
|
|
}
|
|
|
|
- Print(L"Password limit reached\n");
|
|
- return FALSE;
|
|
+ return TRUE;
|
|
}
|
|
|
|
static EFI_STATUS enter_mok_menu(EFI_HANDLE image_handle, void *MokNew,
|
|
--
|
|
1.7.10.4
|
|
|
|
|
|
From 0c6a8a7501f2eb4e751c33090c6763044d131b96 Mon Sep 17 00:00:00 2001
|
|
From: Gary Ching-Pang Lin <glin@suse.com>
|
|
Date: Fri, 21 Dec 2012 15:02:09 +0800
|
|
Subject: [PATCH 2/3] MOK doesn't include the signature owner
|
|
|
|
---
|
|
MokManager.c | 4 ++--
|
|
1 file changed, 2 insertions(+), 2 deletions(-)
|
|
|
|
diff --git a/MokManager.c b/MokManager.c
|
|
index ffe37ff..ddf12de 100644
|
|
--- a/MokManager.c
|
|
+++ b/MokManager.c
|
|
@@ -124,7 +124,7 @@ 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;
|
|
+ list[count].MokSize = CertList->SignatureSize - sizeof(EFI_GUID);
|
|
list[count].Mok = (void *)Cert->SignatureData;
|
|
|
|
count++;
|
|
@@ -317,7 +317,7 @@ static void show_mok_info (void *Mok, UINTN MokSize)
|
|
if (!Mok || MokSize == 0)
|
|
return;
|
|
|
|
- if (MokSize != 48) {
|
|
+ if (MokSize != SHA256_DIGEST_SIZE) {
|
|
if (X509ConstructCertificate(Mok, MokSize,
|
|
(UINT8 **) &X509Cert) && X509Cert != NULL) {
|
|
show_x509_info(X509Cert);
|
|
--
|
|
1.7.10.4
|
|
|
|
|
|
From 990dcdb6a6cea2a22ef237b68630aa30784184c4 Mon Sep 17 00:00:00 2001
|
|
From: Gary Ching-Pang Lin <glin@suse.com>
|
|
Date: Fri, 21 Dec 2012 17:59:31 +0800
|
|
Subject: [PATCH 3/3] Add support for deleting specific keys
|
|
|
|
---
|
|
MokManager.c | 336 ++++++++++++++++++++++++++++++++++++++++++++++++++--------
|
|
shim.c | 3 +-
|
|
2 files changed, 293 insertions(+), 46 deletions(-)
|
|
|
|
diff --git a/MokManager.c b/MokManager.c
|
|
index ddf12de..bfcbfd6 100644
|
|
--- a/MokManager.c
|
|
+++ b/MokManager.c
|
|
@@ -31,6 +31,7 @@ struct menu_item {
|
|
typedef struct {
|
|
UINT32 MokSize;
|
|
UINT8 *Mok;
|
|
+ EFI_GUID Type;
|
|
} __attribute__ ((packed)) MokListNode;
|
|
|
|
typedef struct {
|
|
@@ -39,6 +40,32 @@ typedef struct {
|
|
CHAR16 Password[PASSWORD_MAX];
|
|
} __attribute__ ((packed)) MokSBvar;
|
|
|
|
+static EFI_STATUS get_variable (CHAR16 *name, EFI_GUID guid, UINT32 *attributes,
|
|
+ UINTN *size, void **buffer)
|
|
+{
|
|
+ EFI_STATUS efi_status;
|
|
+ char allocate = !(*size);
|
|
+
|
|
+ efi_status = uefi_call_wrapper(RT->GetVariable, 5, name, &guid,
|
|
+ attributes, size, buffer);
|
|
+
|
|
+ if (efi_status != EFI_BUFFER_TOO_SMALL || !allocate) {
|
|
+ return efi_status;
|
|
+ }
|
|
+
|
|
+ *buffer = AllocatePool(*size);
|
|
+
|
|
+ if (!*buffer) {
|
|
+ Print(L"Unable to allocate variable buffer\n");
|
|
+ return EFI_OUT_OF_RESOURCES;
|
|
+ }
|
|
+
|
|
+ efi_status = uefi_call_wrapper(RT->GetVariable, 5, name, &guid,
|
|
+ attributes, size, *buffer);
|
|
+
|
|
+ return efi_status;
|
|
+}
|
|
+
|
|
static EFI_INPUT_KEY get_keystroke (void)
|
|
{
|
|
EFI_INPUT_KEY key;
|
|
@@ -88,6 +115,42 @@ done:
|
|
return status;
|
|
}
|
|
|
|
+static UINT32 count_keys(void *Data, UINTN DataSize)
|
|
+{
|
|
+ EFI_SIGNATURE_LIST *CertList = Data;
|
|
+ EFI_GUID CertType = EfiCertX509Guid;
|
|
+ EFI_GUID HashType = EfiHashSha256Guid;
|
|
+ UINTN dbsize = DataSize;
|
|
+ UINT32 MokNum = 0;
|
|
+
|
|
+ while ((dbsize > 0) && (dbsize >= CertList->SignatureListSize)) {
|
|
+ if ((CompareGuid (&CertList->SignatureType, &CertType) != 0) &&
|
|
+ (CompareGuid (&CertList->SignatureType, &HashType) != 0)) {
|
|
+ Print(L"Doesn't look like a key or hash\n");
|
|
+ dbsize -= CertList->SignatureListSize;
|
|
+ CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList +
|
|
+ CertList->SignatureListSize);
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ if ((CompareGuid (&CertList->SignatureType, &CertType) != 0) &&
|
|
+ (CertList->SignatureSize != 48)) {
|
|
+ Print(L"Doesn't look like a valid hash\n");
|
|
+ dbsize -= CertList->SignatureListSize;
|
|
+ CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList +
|
|
+ CertList->SignatureListSize);
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ MokNum++;
|
|
+ dbsize -= CertList->SignatureListSize;
|
|
+ CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList +
|
|
+ CertList->SignatureListSize);
|
|
+ }
|
|
+
|
|
+ return MokNum;
|
|
+}
|
|
+
|
|
static MokListNode *build_mok_list(UINT32 num, void *Data, UINTN DataSize) {
|
|
MokListNode *list;
|
|
EFI_SIGNATURE_LIST *CertList = Data;
|
|
@@ -126,6 +189,7 @@ static MokListNode *build_mok_list(UINT32 num, void *Data, UINTN DataSize) {
|
|
|
|
list[count].MokSize = CertList->SignatureSize - sizeof(EFI_GUID);
|
|
list[count].Mok = (void *)Cert->SignatureData;
|
|
+ list[count].Type = CertList->SignatureType;
|
|
|
|
count++;
|
|
dbsize -= CertList->SignatureListSize;
|
|
@@ -391,61 +455,35 @@ static INTN get_number ()
|
|
return (INTN)Atoi(input);
|
|
}
|
|
|
|
-static UINT8 list_keys (void *MokNew, UINTN MokNewSize)
|
|
+static UINT8 list_keys (void *KeyList, UINTN KeyListSize, CHAR16 *title)
|
|
{
|
|
UINT32 MokNum = 0;
|
|
MokListNode *keys = NULL;
|
|
INTN key_num = 0;
|
|
UINT8 initial = 1;
|
|
- EFI_SIGNATURE_LIST *CertList = MokNew;
|
|
- EFI_GUID CertType = EfiCertX509Guid;
|
|
- EFI_GUID HashType = EfiHashSha256Guid;
|
|
- UINTN dbsize = MokNewSize;
|
|
|
|
- if (MokNewSize < (sizeof(EFI_SIGNATURE_LIST) +
|
|
- sizeof(EFI_SIGNATURE_DATA))) {
|
|
+ if (KeyListSize < (sizeof(EFI_SIGNATURE_LIST) +
|
|
+ sizeof(EFI_SIGNATURE_DATA))) {
|
|
Print(L"No keys\n");
|
|
Pause();
|
|
return 0;
|
|
}
|
|
|
|
- while ((dbsize > 0) && (dbsize >= CertList->SignatureListSize)) {
|
|
- if ((CompareGuid (&CertList->SignatureType, &CertType) != 0) &&
|
|
- (CompareGuid (&CertList->SignatureType, &HashType) != 0)) {
|
|
- Print(L"Doesn't look like a key or hash\n");
|
|
- dbsize -= CertList->SignatureListSize;
|
|
- CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList +
|
|
- CertList->SignatureListSize);
|
|
- continue;
|
|
- }
|
|
-
|
|
- if ((CompareGuid (&CertList->SignatureType, &CertType) != 0) &&
|
|
- (CertList->SignatureSize != 48)) {
|
|
- Print(L"Doesn't look like a valid hash\n");
|
|
- dbsize -= CertList->SignatureListSize;
|
|
- CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList +
|
|
- CertList->SignatureListSize);
|
|
- continue;
|
|
- }
|
|
-
|
|
- MokNum++;
|
|
- dbsize -= CertList->SignatureListSize;
|
|
- CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList +
|
|
- CertList->SignatureListSize);
|
|
- }
|
|
-
|
|
- keys = build_mok_list(MokNum, MokNew, MokNewSize);
|
|
+ MokNum = count_keys(KeyList, KeyListSize);
|
|
+ keys = build_mok_list(MokNum, KeyList, KeyListSize);
|
|
|
|
if (!keys) {
|
|
- Print(L"Failed to construct key list in MokNew\n");
|
|
+ Print(L"Failed to construct key list\n");
|
|
return 0;
|
|
}
|
|
|
|
do {
|
|
uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut);
|
|
+ if (title)
|
|
+ Print(L"%s\n", title);
|
|
Print(L"Input the key number to show the details of the key or\n"
|
|
L"type \'0\' to continue\n\n");
|
|
- Print(L"%d key(s) in the new key list\n\n", MokNum);
|
|
+ Print(L"%d key(s) in the key list\n\n", MokNum);
|
|
|
|
if (key_num > MokNum) {
|
|
Print(L"[Key %d]\n", key_num);
|
|
@@ -663,7 +701,7 @@ static UINTN mok_enrollment_prompt (void *MokNew, UINTN MokNewSize, int auth) {
|
|
EFI_STATUS efi_status;
|
|
|
|
do {
|
|
- if (!list_keys(MokNew, MokNewSize)) {
|
|
+ if (!list_keys(MokNew, MokNewSize, L"[Enroll MOK]")) {
|
|
return 0;
|
|
}
|
|
|
|
@@ -704,7 +742,8 @@ static INTN mok_enrollment_prompt_callback (void *MokNew, void *data2,
|
|
return mok_enrollment_prompt(MokNew, (UINTN)data2, TRUE);
|
|
}
|
|
|
|
-static INTN mok_deletion_prompt (void *MokNew, void *data2, void *data3) {
|
|
+static INTN mok_reset_prompt (void *MokNew, void *data2, void *data3)
|
|
+{
|
|
EFI_GUID shim_lock_guid = SHIM_LOCK_GUID;
|
|
CHAR16 line[1];
|
|
UINT32 length;
|
|
@@ -737,6 +776,180 @@ static INTN mok_deletion_prompt (void *MokNew, void *data2, void *data3) {
|
|
return 0;
|
|
}
|
|
|
|
+static EFI_STATUS write_back_mok_list (MokListNode *list, INTN key_num)
|
|
+{
|
|
+ EFI_GUID shim_lock_guid = SHIM_LOCK_GUID;
|
|
+ EFI_STATUS efi_status;
|
|
+ EFI_SIGNATURE_LIST *CertList;
|
|
+ EFI_SIGNATURE_DATA *CertData;
|
|
+ void *Data = NULL, *ptr;
|
|
+ INTN DataSize = 0;
|
|
+ int i;
|
|
+
|
|
+ for (i = 0; i < key_num; i++) {
|
|
+ if (list[i].Mok == NULL)
|
|
+ continue;
|
|
+
|
|
+ DataSize += sizeof(EFI_SIGNATURE_LIST) + sizeof(EFI_GUID);
|
|
+ DataSize += list[i].MokSize;
|
|
+ }
|
|
+
|
|
+ Data = AllocatePool(DataSize);
|
|
+ if (Data == NULL && DataSize != 0)
|
|
+ return EFI_OUT_OF_RESOURCES;
|
|
+
|
|
+ ptr = Data;
|
|
+
|
|
+ for (i = 0; i < key_num; i++) {
|
|
+ if (list[i].Mok == NULL)
|
|
+ continue;
|
|
+
|
|
+ CertList = (EFI_SIGNATURE_LIST *)ptr;
|
|
+ CertData = (EFI_SIGNATURE_DATA *)(((uint8_t *)ptr) +
|
|
+ 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);
|
|
+
|
|
+ ptr = (uint8_t *)ptr + sizeof(EFI_SIGNATURE_LIST) +
|
|
+ sizeof(EFI_GUID) + list[i].MokSize;
|
|
+ }
|
|
+
|
|
+ efi_status = uefi_call_wrapper(RT->SetVariable, 5, L"MokList",
|
|
+ &shim_lock_guid,
|
|
+ EFI_VARIABLE_NON_VOLATILE
|
|
+ | EFI_VARIABLE_BOOTSERVICE_ACCESS,
|
|
+ DataSize, Data);
|
|
+ if (Data)
|
|
+ FreePool(Data);
|
|
+
|
|
+ if (efi_status != EFI_SUCCESS) {
|
|
+ Print(L"Failed to set variable %d\n", efi_status);
|
|
+ return efi_status;
|
|
+ }
|
|
+
|
|
+ return EFI_SUCCESS;
|
|
+}
|
|
+
|
|
+static EFI_STATUS delete_keys (void *MokDel, UINTN MokDelSize)
|
|
+{
|
|
+ EFI_GUID shim_lock_guid = SHIM_LOCK_GUID;
|
|
+ EFI_STATUS efi_status;
|
|
+ UINT8 auth[SHA256_DIGEST_SIZE];
|
|
+ UINTN auth_size = SHA256_DIGEST_SIZE;
|
|
+ UINT32 attributes;
|
|
+ void *MokListData = NULL;
|
|
+ UINTN MokListDataSize = 0;
|
|
+ MokListNode *mok, *del_key;
|
|
+ INTN mok_num, del_num;
|
|
+ int i, j;
|
|
+
|
|
+ efi_status = uefi_call_wrapper(RT->GetVariable, 5, L"MokDelAuth",
|
|
+ &shim_lock_guid,
|
|
+ &attributes, &auth_size, auth);
|
|
+
|
|
+ if (efi_status != EFI_SUCCESS || auth_size != SHA256_DIGEST_SIZE) {
|
|
+ Print(L"Failed to get MokDelAuth %d\n", efi_status);
|
|
+ return efi_status;
|
|
+ }
|
|
+
|
|
+ efi_status = match_password(MokDel, MokDelSize, auth, NULL);
|
|
+ if (efi_status != EFI_SUCCESS)
|
|
+ return EFI_ACCESS_DENIED;
|
|
+
|
|
+ efi_status = get_variable(L"MokList", shim_lock_guid, &attributes,
|
|
+ &MokListDataSize, &MokListData);
|
|
+
|
|
+ if (attributes & EFI_VARIABLE_RUNTIME_ACCESS) {
|
|
+ Print(L"MokList is compromised!\nErase all keys in MokList!\n");
|
|
+ if (LibDeleteVariable(L"MokList", &shim_lock_guid) != EFI_SUCCESS) {
|
|
+ Print(L"Failed to erase MokList\n");
|
|
+ }
|
|
+ return EFI_ACCESS_DENIED;
|
|
+ }
|
|
+
|
|
+ /* Nothing to do */
|
|
+ if (!MokListData || MokListDataSize == 0)
|
|
+ return EFI_SUCCESS;
|
|
+
|
|
+ /* Construct lists */
|
|
+ mok_num = count_keys(MokListData, MokListDataSize);
|
|
+ mok = build_mok_list(mok_num, MokListData, MokListDataSize);
|
|
+ del_num = count_keys(MokDel, MokDelSize);
|
|
+ del_key = build_mok_list(del_num, MokDel, MokDelSize);
|
|
+
|
|
+ /* 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;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ efi_status = write_back_mok_list(mok, mok_num);
|
|
+
|
|
+ if (MokListData)
|
|
+ FreePool(MokListData);
|
|
+ if (mok)
|
|
+ FreePool(mok);
|
|
+ if (del_key)
|
|
+ FreePool(del_key);
|
|
+
|
|
+ return efi_status;
|
|
+}
|
|
+
|
|
+static INTN mok_deletion_prompt (void *MokDel, void *data2, void *data3)
|
|
+{
|
|
+ EFI_GUID shim_lock_guid = SHIM_LOCK_GUID;
|
|
+ UINTN MokDelSize = (UINTN)data2;
|
|
+ CHAR16 line[1];
|
|
+ UINT32 length;
|
|
+ EFI_STATUS efi_status;
|
|
+
|
|
+ do {
|
|
+ if (!list_keys(MokDel, MokDelSize, L"[Delete MOK]")) {
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ Print(L"Delete the key(s)? (y/n): ");
|
|
+
|
|
+ get_line (&length, line, 1, 1);
|
|
+
|
|
+ if (line[0] == 'Y' || line[0] == 'y') {
|
|
+ efi_status = delete_keys(MokDel, MokDelSize);
|
|
+
|
|
+ if (efi_status != EFI_SUCCESS) {
|
|
+ Print(L"Failed to delete keys\n");
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ LibDeleteVariable(L"MokDel", &shim_lock_guid);
|
|
+ LibDeleteVariable(L"MokDelAuth", &shim_lock_guid);
|
|
+
|
|
+ Print(L"\nPress a key to reboot system\n");
|
|
+ Pause();
|
|
+ uefi_call_wrapper(RT->ResetSystem, 4, EfiResetWarm,
|
|
+ EFI_SUCCESS, 0, NULL);
|
|
+ Print(L"Failed to reboot\n");
|
|
+ return -1;
|
|
+ }
|
|
+ } while (line[0] != 'N' && line[0] != 'n');
|
|
+ return -1;
|
|
+}
|
|
+
|
|
static INTN mok_sb_prompt (void *MokSB, void *data2, void *data3) {
|
|
EFI_GUID shim_lock_guid = SHIM_LOCK_GUID;
|
|
EFI_STATUS efi_status;
|
|
@@ -1505,12 +1718,15 @@ static BOOLEAN verify_pw(void)
|
|
return TRUE;
|
|
}
|
|
|
|
-static EFI_STATUS enter_mok_menu(EFI_HANDLE image_handle, void *MokNew,
|
|
- UINTN MokNewSize, void *MokSB,
|
|
- UINTN MokSBSize, void *MokPW, UINTN MokPWSize)
|
|
+static EFI_STATUS enter_mok_menu(EFI_HANDLE image_handle,
|
|
+ void *MokNew, UINTN MokNewSize,
|
|
+ void *MokDel, UINTN MokDelSize,
|
|
+ void *MokSB, UINTN MokSBSize,
|
|
+ void *MokPW, UINTN MokPWSize)
|
|
{
|
|
struct menu_item *menu_item;
|
|
UINT32 MokAuth = 0;
|
|
+ UINT32 MokDelAuth = 0;
|
|
UINTN menucount = 3, i = 0;
|
|
EFI_STATUS efi_status;
|
|
EFI_GUID shim_lock_guid = SHIM_LOCK_GUID;
|
|
@@ -1528,9 +1744,19 @@ static EFI_STATUS enter_mok_menu(EFI_HANDLE image_handle, void *MokNew,
|
|
if ((efi_status == EFI_SUCCESS) && (auth_size == SHA256_DIGEST_SIZE))
|
|
MokAuth = 1;
|
|
|
|
+ efi_status = uefi_call_wrapper(RT->GetVariable, 5, L"MokDelAuth",
|
|
+ &shim_lock_guid,
|
|
+ &attributes, &auth_size, auth);
|
|
+
|
|
+ if ((efi_status == EFI_SUCCESS) && (auth_size == SHA256_DIGEST_SIZE))
|
|
+ MokDelAuth = 1;
|
|
+
|
|
if (MokNew || MokAuth)
|
|
menucount++;
|
|
|
|
+ if (MokDel || MokDelAuth)
|
|
+ menucount++;
|
|
+
|
|
if (MokSB)
|
|
menucount++;
|
|
|
|
@@ -1550,9 +1776,9 @@ static EFI_STATUS enter_mok_menu(EFI_HANDLE image_handle, void *MokNew,
|
|
|
|
if (MokNew || MokAuth) {
|
|
if (!MokNew) {
|
|
- menu_item[i].text = StrDuplicate(L"Delete MOK");
|
|
+ menu_item[i].text = StrDuplicate(L"Reset MOK");
|
|
menu_item[i].colour = EFI_WHITE;
|
|
- menu_item[i].callback = mok_deletion_prompt;
|
|
+ menu_item[i].callback = mok_reset_prompt;
|
|
} else {
|
|
menu_item[i].text = StrDuplicate(L"Enroll MOK");
|
|
menu_item[i].colour = EFI_WHITE;
|
|
@@ -1563,6 +1789,15 @@ static EFI_STATUS enter_mok_menu(EFI_HANDLE image_handle, void *MokNew,
|
|
i++;
|
|
}
|
|
|
|
+ if (MokDel || MokDelAuth) {
|
|
+ menu_item[i].text = StrDuplicate(L"Delete MOK");
|
|
+ menu_item[i].colour = EFI_WHITE;
|
|
+ menu_item[i].data = MokDel;
|
|
+ menu_item[i].data2 = (void *)MokDelSize;
|
|
+ menu_item[i].callback = mok_deletion_prompt;
|
|
+ i++;
|
|
+ }
|
|
+
|
|
if (MokSB) {
|
|
menu_item[i].text = StrDuplicate(L"Change Secure Boot state");
|
|
menu_item[i].colour = EFI_WHITE;
|
|
@@ -1605,19 +1840,22 @@ static EFI_STATUS enter_mok_menu(EFI_HANDLE image_handle, void *MokNew,
|
|
static EFI_STATUS check_mok_request(EFI_HANDLE image_handle)
|
|
{
|
|
EFI_GUID shim_lock_guid = SHIM_LOCK_GUID;
|
|
- UINTN MokNewSize = 0, MokSBSize = 0, MokPWSize = 0;
|
|
+ UINTN MokNewSize = 0, MokDelSize = 0, MokSBSize = 0, MokPWSize = 0;
|
|
void *MokNew = NULL;
|
|
+ void *MokDel = NULL;
|
|
void *MokSB = NULL;
|
|
void *MokPW = NULL;
|
|
|
|
MokNew = LibGetVariableAndSize(L"MokNew", &shim_lock_guid, &MokNewSize);
|
|
|
|
+ MokDel = LibGetVariableAndSize(L"MokDel", &shim_lock_guid, &MokDelSize);
|
|
+
|
|
MokSB = LibGetVariableAndSize(L"MokSB", &shim_lock_guid, &MokSBSize);
|
|
|
|
MokPW = LibGetVariableAndSize(L"MokPW", &shim_lock_guid, &MokPWSize);
|
|
|
|
- enter_mok_menu(image_handle, MokNew, MokNewSize, MokSB, MokSBSize,
|
|
- MokPW, MokPWSize);
|
|
+ enter_mok_menu(image_handle, MokNew, MokNewSize, MokDel, MokDelSize,
|
|
+ MokSB, MokSBSize, MokPW, MokPWSize);
|
|
|
|
if (MokNew) {
|
|
if (LibDeleteVariable(L"MokNew", &shim_lock_guid) != EFI_SUCCESS) {
|
|
@@ -1626,6 +1864,13 @@ static EFI_STATUS check_mok_request(EFI_HANDLE image_handle)
|
|
FreePool (MokNew);
|
|
}
|
|
|
|
+ if (MokDel) {
|
|
+ if (LibDeleteVariable(L"MokDel", &shim_lock_guid) != EFI_SUCCESS) {
|
|
+ Print(L"Failed to delete MokDel\n");
|
|
+ }
|
|
+ FreePool (MokDel);
|
|
+ }
|
|
+
|
|
if (MokSB) {
|
|
if (LibDeleteVariable(L"MokSB", &shim_lock_guid) != EFI_SUCCESS) {
|
|
Print(L"Failed to delete MokSB\n");
|
|
@@ -1641,6 +1886,7 @@ static EFI_STATUS check_mok_request(EFI_HANDLE image_handle)
|
|
}
|
|
|
|
LibDeleteVariable(L"MokAuth", &shim_lock_guid);
|
|
+ LibDeleteVariable(L"MokDelAuth", &shim_lock_guid);
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
diff --git a/shim.c b/shim.c
|
|
index 44301dd..dcf1c51 100644
|
|
--- a/shim.c
|
|
+++ b/shim.c
|
|
@@ -1271,7 +1271,8 @@ EFI_STATUS check_mok_request(EFI_HANDLE image_handle)
|
|
EFI_STATUS efi_status;
|
|
|
|
if (check_var(L"MokNew") || check_var(L"MokSB") ||
|
|
- check_var(L"MokPW") || check_var(L"MokAuth")) {
|
|
+ check_var(L"MokPW") || check_var(L"MokAuth") ||
|
|
+ check_var(L"MokDel")) {
|
|
efi_status = start_image(image_handle, MOK_MANAGER);
|
|
|
|
if (efi_status != EFI_SUCCESS) {
|
|
--
|
|
1.7.10.4
|
|
|