From 58b8e54ef60d488886a9f0d0877b7187eb200d07 Mon Sep 17 00:00:00 2001 From: Gary Ching-Pang Lin Date: Thu, 24 Oct 2013 17:02:08 +0800 Subject: [PATCH 01/10] Support MOK blacklist The new blacklist, MokListX, stores the keys and hashes that are banned. Signed-off-by: Gary Ching-Pang Lin --- MokManager.c | 241 +++++++++++++++++++++++++++++++++++++++++++++++++---------- shim.c | 3 +- 2 files changed, 202 insertions(+), 42 deletions(-) Index: shim-0.7/MokManager.c =================================================================== --- shim-0.7.orig/MokManager.c +++ shim-0.7/MokManager.c @@ -165,9 +165,16 @@ static MokListNode *build_mok_list(UINT3 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 *X509Ce 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) + 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, UI 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 *KeyLi { UINT32 MokNum = 0; MokListNode *keys = NULL; - INTN key_num = 0; + int key_num = 0; CHAR16 **menu_strings; unsigned int i; @@ -470,12 +529,13 @@ static EFI_STATUS list_keys (void *KeyLi while (key_num < MokNum) { key_num = console_select((CHAR16 *[]){ title, NULL }, - menu_strings, 0); + menu_strings, key_num); - 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++) @@ -707,23 +767,37 @@ static EFI_STATUS match_password (PASSWO 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; } @@ -740,14 +814,14 @@ static EFI_STATUS store_keys (void *MokN 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 @@ -763,17 +837,25 @@ static EFI_STATUS store_keys (void *MokN 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 (MokX) + title = L"[Enroll MOKX]"; + else + title = L"[Enroll MOK]"; - if (list_keys(MokNew, MokNewSize, L"[Enroll MOK]") != EFI_SUCCESS) + 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"); @@ -781,8 +863,13 @@ static UINTN mok_enrollment_prompt (void } 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, @@ -794,25 +881,35 @@ static UINTN mok_enrollment_prompt (void 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, @@ -821,15 +918,23 @@ 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_GUID CertType = X509_GUID; EFI_STATUS efi_status; EFI_SIGNATURE_LIST *CertList; EFI_SIGNATURE_DATA *CertData; 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) @@ -854,20 +959,27 @@ static EFI_STATUS write_back_mok_list (M 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, L"MokList", + efi_status = uefi_call_wrapper(RT->SetVariable, 5, db_name, &shim_lock_guid, EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS, @@ -883,10 +995,125 @@ static EFI_STATUS write_back_mok_list (M return EFI_SUCCESS; } -static EFI_STATUS delete_keys (void *MokDel, UINTN MokDelSize) +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, int start, + void *hash_list, UINT32 list_num) +{ + UINT8 *ptr; + int i; + + ptr = hash_list + sizeof(EFI_GUID); + for (i = start; 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, 0, mok[i].Mok, + mok[i].MokSize); + 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); + } + } +} + +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; + CHAR16 *err_str1; + CHAR16 *err_str2; UINT8 auth[PASSWORD_CRYPT_SIZE]; UINTN auth_size = PASSWORD_CRYPT_SIZE; UINT32 attributes; @@ -894,15 +1121,26 @@ static EFI_STATUS delete_keys (void *Mok UINTN MokListDataSize = 0; MokListNode *mok, *del_key; INTN mok_num, del_num; - int i, j; + int i; - 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; } @@ -915,15 +1153,18 @@ static EFI_STATUS delete_keys (void *Mok 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; } @@ -939,19 +1180,16 @@ static EFI_STATUS delete_keys (void *Mok /* 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); } } - efi_status = write_back_mok_list(mok, mok_num); + efi_status = write_back_mok_list(mok, mok_num, MokX); if (MokListData) FreePool(MokListData); @@ -963,27 +1201,38 @@ static EFI_STATUS delete_keys (void *Mok 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, @@ -1446,7 +1695,7 @@ static EFI_STATUS enroll_file (void *dat goto out; } - mok_enrollment_prompt(mokbuffer, mokbuffersize, FALSE); + mok_enrollment_prompt(mokbuffer, mokbuffersize, FALSE, FALSE); out: if (mokbuffer) FreePool(mokbuffer); @@ -1681,8 +1930,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, @@ -1695,13 +1947,17 @@ static EFI_STATUS enter_mok_menu(EFI_HAN 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; @@ -1730,12 +1986,34 @@ static EFI_STATUS enter_mok_menu(EFI_HAN (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++; @@ -1773,12 +2051,29 @@ static EFI_STATUS enter_mok_menu(EFI_HAN 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; @@ -1821,13 +2116,22 @@ static EFI_STATUS enter_mok_menu(EFI_HAN 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); @@ -1861,13 +2165,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, @@ -1920,8 +2226,29 @@ static EFI_STATUS check_mok_request(EFI_ 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); @@ -1938,8 +2265,16 @@ static EFI_STATUS check_mok_request(EFI_ 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; } Index: shim-0.7/shim.c =================================================================== --- shim-0.7.orig/shim.c +++ shim-0.7/shim.c @@ -390,6 +390,7 @@ static EFI_STATUS check_blacklist (WIN_C 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, @@ -413,6 +414,14 @@ static EFI_STATUS check_blacklist (WIN_C 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; } @@ -1589,7 +1598,9 @@ EFI_STATUS check_mok_request(EFI_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") || + check_var(L"MokXAuth")) { efi_status = start_image(image_handle, MOK_MANAGER); if (efi_status != EFI_SUCCESS) {