From 72a6913fa790c6d504f87eefddd1b2b392185b79 Mon Sep 17 00:00:00 2001 From: Gary Ching-Pang Lin Date: Thu, 24 Oct 2013 17:02:08 +0800 Subject: [PATCH 01/16] 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(-) diff --git a/MokManager.c b/MokManager.c index ee29051..29ea4db 100644 --- a/MokManager.c +++ b/MokManager.c @@ -738,23 +738,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; } @@ -771,14 +785,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 @@ -794,17 +808,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"); @@ -812,8 +834,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, @@ -825,25 +852,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, @@ -852,7 +889,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; @@ -861,6 +899,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) @@ -898,7 +942,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, @@ -914,10 +958,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; @@ -927,13 +975,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; } @@ -946,15 +1005,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; } @@ -982,7 +1044,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); @@ -994,27 +1056,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, @@ -1477,7 +1550,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); @@ -1712,8 +1785,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, @@ -1726,13 +1802,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; @@ -1761,12 +1841,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++; @@ -1804,12 +1906,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; @@ -1852,13 +1971,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); @@ -1892,13 +2020,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, @@ -1951,8 +2081,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); @@ -1969,8 +2120,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 8076caa..bab5e92 100644 --- a/shim.c +++ b/shim.c @@ -1779,7 +1779,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.4.5 From 697a7b7d80692ea6ed9b9a73ffde1d742eee8850 Mon Sep 17 00:00:00 2001 From: Gary Ching-Pang Lin Date: Thu, 24 Oct 2013 17:32:31 +0800 Subject: [PATCH 02/16] MokManager: show the hash list properly Signed-off-by: Gary Ching-Pang Lin --- MokManager.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 71 insertions(+), 11 deletions(-) diff --git a/MokManager.c b/MokManager.c index 29ea4db..2441026 100644 --- a/MokManager.c +++ b/MokManager.c @@ -187,9 +187,16 @@ static MokListNode *build_mok_list(UINT32 num, void *Data, UINTN DataSize) { return NULL; } - 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; + } /* MOK out of bounds? */ if (list[count].MokSize > (unsigned long)end - @@ -402,7 +409,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; @@ -433,16 +440,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) { @@ -458,8 +517,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); } } @@ -467,7 +526,7 @@ static EFI_STATUS list_keys (void *KeyList, UINTN KeyListSize, CHAR16 *title) { INTN MokNum = 0; MokListNode *keys = NULL; - INTN key_num = 0; + int key_num = 0; CHAR16 **menu_strings; int i; @@ -503,10 +562,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.4.5 From 22b51db7daa834f8746ce3bc4e6670f21ea2311b Mon Sep 17 00:00:00 2001 From: Gary Ching-Pang Lin Date: Fri, 25 Oct 2013 16:54:25 +0800 Subject: [PATCH 03/16] MokManager: delete the hash properly Signed-off-by: Gary Ching-Pang Lin --- MokManager.c | 124 ++++++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 114 insertions(+), 10 deletions(-) diff --git a/MokManager.c b/MokManager.c index 2441026..59df4a6 100644 --- a/MokManager.c +++ b/MokManager.c @@ -1018,9 +1018,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; @@ -1033,7 +1140,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"; @@ -1092,15 +1199,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.4.5 From 3c4c4f8e2b41a127aad6c7e967138639ed162ed1 Mon Sep 17 00:00:00 2001 From: Gary Ching-Pang Lin Date: Fri, 25 Oct 2013 17:05:10 +0800 Subject: [PATCH 04/16] MokManager: Match all hashes in the list Signed-off-by: Gary Ching-Pang Lin --- MokManager.c | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/MokManager.c b/MokManager.c index 59df4a6..31cc06a 100644 --- a/MokManager.c +++ b/MokManager.c @@ -1037,14 +1037,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); @@ -1080,21 +1080,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.4.5 From 2b5292ad76908cbfeba28f9b212a421b1efc50d9 Mon Sep 17 00:00:00 2001 From: Gary Ching-Pang Lin Date: Fri, 25 Oct 2013 18:30:48 +0800 Subject: [PATCH 05/16] MokManager: Write the hash list properly also return to the previous entry in the list Signed-off-by: Gary Ching-Pang Lin --- MokManager.c | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/MokManager.c b/MokManager.c index 31cc06a..56839cc 100644 --- a/MokManager.c +++ b/MokManager.c @@ -470,12 +470,12 @@ static void show_efi_hash (void *Mok, UINTN MokSize) for (i=0; i= hash_num) break; @@ -560,7 +560,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; @@ -953,6 +953,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; @@ -989,17 +990,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.4.5 From 41d29504d597daffde481349e6bc4a6521819941 Mon Sep 17 00:00:00 2001 From: Gary Ching-Pang Lin Date: Mon, 28 Oct 2013 15:08:40 +0800 Subject: [PATCH 06/16] Copy the MOK blacklist to a RT variable Signed-off-by: Gary Ching-Pang Lin --- shim.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/shim.c b/shim.c index bab5e92..8eef64d 100644 --- a/shim.c +++ b/shim.c @@ -1749,6 +1749,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) @@ -2093,6 +2120,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.4.5 From d424bdcdead0add27c1c1fbd80ba2b8acb7e558f Mon Sep 17 00:00:00 2001 From: Gary Ching-Pang Lin Date: Mon, 4 Nov 2013 14:45:33 +0800 Subject: [PATCH 07/16] Verify the EFI images with MOK blacklist Signed-off-by: Gary Ching-Pang Lin --- shim.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/shim.c b/shim.c index 8eef64d..2c05886 100644 --- a/shim.c +++ b/shim.c @@ -518,6 +518,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, @@ -541,6 +542,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.4.5 From 7767893c145fa3d00b1019547716b1fdfa8d1c53 Mon Sep 17 00:00:00 2001 From: Gary Ching-Pang Lin Date: Tue, 11 Feb 2014 14:11:15 +0800 Subject: [PATCH 08/16] Make shim to check MokXAuth for MOKX reset Signed-off-by: Gary Ching-Pang Lin --- shim.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/shim.c b/shim.c index 2c05886..d46494a 100644 --- a/shim.c +++ b/shim.c @@ -1816,7 +1816,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"MokXNew") || check_var(L"MokXDel")) { + 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) { -- 1.8.4.5 From 195edc629f9d316071f108a6e9390d86329b0e5f Mon Sep 17 00:00:00 2001 From: Gary Ching-Pang Lin Date: Thu, 13 Feb 2014 15:05:45 +0800 Subject: [PATCH 09/16] MokManager: calculate the variable size correctly MokSize of the hash signature list includes the owner GUID, so we should not add the 16bytes compensation. Signed-off-by: Gary Ching-Pang Lin --- MokManager.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/MokManager.c b/MokManager.c index 56839cc..af38405 100644 --- a/MokManager.c +++ b/MokManager.c @@ -971,7 +971,9 @@ static EFI_STATUS write_back_mok_list (MokListNode *list, INTN key_num, if (list[i].Mok == NULL) continue; - DataSize += sizeof(EFI_SIGNATURE_LIST) + sizeof(EFI_GUID); + DataSize += sizeof(EFI_SIGNATURE_LIST); + if (CompareGuid(&(list[i].Type), &CertType) == 0) + DataSize += sizeof(EFI_GUID); DataSize += list[i].MokSize; } -- 1.8.4.5 From b5bdd25de7cfda1b6b23780b947d979abfae0782 Mon Sep 17 00:00:00 2001 From: Gary Ching-Pang Lin Date: Mon, 17 Feb 2014 17:49:55 +0800 Subject: [PATCH 10/16] MokManager: fix the hash list counting in delete match_hash() requests the number of keys in a list and it was mistakenly replaced with the size of the Mok node. This would made MokManager to remove the whole Mok node instead of one hash. Signed-off-by: Gary Ching-Pang Lin --- MokManager.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/MokManager.c b/MokManager.c index af38405..5901f65 100644 --- a/MokManager.c +++ b/MokManager.c @@ -1079,6 +1079,7 @@ static void delete_hash_in_list (UINT8 *hash, UINT32 hash_size, { EFI_GUID HashType = EFI_CERT_SHA256_GUID; UINT32 sig_size; + UINT32 list_num; int i, del_ind; void *start, *end; UINT32 remain; @@ -1090,8 +1091,10 @@ static void delete_hash_in_list (UINT8 *hash, UINT32 hash_size, (mok[i].MokSize < sig_size)) continue; + list_num = mok[i].MokSize / sig_size; + del_ind = match_hash(hash, hash_size, 0, mok[i].Mok, - mok[i].MokSize); + list_num); while (del_ind >= 0) { /* Remove the hash */ if (sig_size == mok[i].MokSize) { @@ -1106,9 +1109,10 @@ static void delete_hash_in_list (UINT8 *hash, UINT32 hash_size, mem_move(start, end, remain); mok[i].MokSize -= sig_size; + list_num--; del_ind = match_hash(hash, hash_size, del_ind, - mok[i].Mok, mok[i].MokSize); + mok[i].Mok, list_num); } } } -- 1.8.4.5 From a660b38e1bfafab7cfe6699a01e672aba40e7a36 Mon Sep 17 00:00:00 2001 From: Gary Ching-Pang Lin Date: Thu, 3 Apr 2014 18:26:37 +0800 Subject: [PATCH 11/16] MokManager: Support SHA1 hash in MOK Add SHA1 hash support and amend the code to make it easier to support other SHA digests. --- MokManager.c | 121 ++++++++++++++++++++++++++++++++++++----------------------- 1 file changed, 75 insertions(+), 46 deletions(-) diff --git a/MokManager.c b/MokManager.c index 5901f65..4ab54ed 100644 --- a/MokManager.c +++ b/MokManager.c @@ -93,11 +93,53 @@ done: return status; } +static BOOLEAN is_sha_hash (EFI_GUID Type) +{ + EFI_GUID Sha1 = EFI_CERT_SHA1_GUID; + EFI_GUID Sha256 = EFI_CERT_SHA256_GUID; + + if (CompareGuid(&Type, &Sha1) == 0) + return TRUE; + else if (CompareGuid(&Type, &Sha256) == 0) + return TRUE; + + return FALSE; +} + +static UINT32 sha_size (EFI_GUID Type) +{ + EFI_GUID Sha1 = EFI_CERT_SHA1_GUID; + EFI_GUID Sha256 = EFI_CERT_SHA256_GUID; + + if (CompareGuid(&Type, &Sha1) == 0) + return SHA1_DIGEST_SIZE; + else if (CompareGuid(&Type, &Sha256) == 0) + return SHA256_DIGEST_SIZE; + + return 0; +} + +static BOOLEAN is_valid_siglist (EFI_GUID Type, UINT32 SigSize) +{ + EFI_GUID CertType = X509_GUID; + UINT32 hash_sig_size; + + if (CompareGuid (&Type, &CertType) == 0 && SigSize != 0) + return TRUE; + + if (!is_sha_hash (Type)) + return FALSE; + + hash_sig_size = sha_size (Type) + sizeof(EFI_GUID); + if (SigSize != hash_sig_size) + return FALSE; + + return TRUE; +} + static UINT32 count_keys(void *Data, UINTN DataSize) { EFI_SIGNATURE_LIST *CertList = Data; - EFI_GUID CertType = X509_GUID; - EFI_GUID HashType = EFI_CERT_SHA256_GUID; UINTN dbsize = DataSize; UINT32 MokNum = 0; void *end = Data + DataSize; @@ -112,18 +154,7 @@ static UINT32 count_keys(void *Data, UINTN DataSize) return 0; } - if ((CompareGuid (&CertList->SignatureType, &CertType) != 0) && - (CompareGuid (&CertList->SignatureType, &HashType) != 0)) { - console_notify(L"Doesn't look like a key or hash"); - dbsize -= CertList->SignatureListSize; - CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + - CertList->SignatureListSize); - continue; - } - - if ((CompareGuid (&CertList->SignatureType, &CertType) != 0) && - (CertList->SignatureSize != 48)) { - console_notify(L"Doesn't look like a valid hash"); + if (!is_valid_siglist(CertList->SignatureType, CertList->SignatureSize)) { dbsize -= CertList->SignatureListSize; CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize); @@ -144,7 +175,6 @@ static MokListNode *build_mok_list(UINT32 num, void *Data, UINTN DataSize) { EFI_SIGNATURE_LIST *CertList = Data; EFI_SIGNATURE_DATA *Cert; EFI_GUID CertType = X509_GUID; - EFI_GUID HashType = EFI_CERT_SHA256_GUID; UINTN dbsize = DataSize; UINTN count = 0; void *end = Data + DataSize; @@ -162,16 +192,7 @@ static MokListNode *build_mok_list(UINT32 num, void *Data, UINTN DataSize) { FreePool(list); return NULL; } - if ((CompareGuid (&CertList->SignatureType, &CertType) != 0) && - (CompareGuid (&CertList->SignatureType, &HashType) != 0)) { - dbsize -= CertList->SignatureListSize; - CertList = (EFI_SIGNATURE_LIST *)((UINT8 *) CertList + - CertList->SignatureListSize); - continue; - } - - if ((CompareGuid (&CertList->SignatureType, &HashType) == 0) && - (CertList->SignatureSize != 48)) { + if (!is_valid_siglist(CertList->SignatureType, CertList->SignatureSize)) { dbsize -= CertList->SignatureListSize; CertList = (EFI_SIGNATURE_LIST *)((UINT8 *) CertList + CertList->SignatureListSize); @@ -409,22 +430,34 @@ static void show_x509_info (X509 *X509Cert, UINT8 *hash) FreePool(text); } -static void show_sha256_digest (UINT8 *hash) +static void show_sha_digest (EFI_GUID Type, UINT8 *hash) { + EFI_GUID Sha1 = EFI_CERT_SHA1_GUID; + EFI_GUID Sha256 = EFI_CERT_SHA256_GUID; CHAR16 *text[5]; POOL_PRINT hash_string1; POOL_PRINT hash_string2; int i; + int length; + + if (CompareGuid(&Type, &Sha1) == 0) { + length = SHA1_DIGEST_SIZE; + text[0] = L"SHA1 hash"; + } else if (CompareGuid(&Type, &Sha256) == 0) { + length = SHA256_DIGEST_SIZE; + text[0] = L"SHA256 hash"; + } else { + return; + } ZeroMem(&hash_string1, sizeof(hash_string1)); ZeroMem(&hash_string2, sizeof(hash_string2)); - text[0] = L"SHA256 hash"; text[1] = L""; - for (i=0; i<16; i++) + for (i=0; iSignatureListSize = list[i].MokSize + sizeof(EFI_SIGNATURE_LIST); - CertList->SignatureSize = SHA256_DIGEST_SIZE + sizeof(EFI_GUID); + CertList->SignatureSize = sha_size(list[i].Type) + sizeof(EFI_GUID); CopyMem(CertData, list[i].Mok, list[i].MokSize); } @@ -1077,7 +1109,6 @@ static void mem_move (void *dest, void *src, UINTN size) 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; UINT32 list_num; int i, del_ind; @@ -1087,8 +1118,7 @@ static void delete_hash_in_list (UINT8 *hash, UINT32 hash_size, 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)) + if (!is_sha_hash(mok[i].Type) || (mok[i].MokSize < sig_size)) continue; list_num = mok[i].MokSize / sig_size; @@ -1117,7 +1147,7 @@ static void delete_hash_in_list (UINT8 *hash, UINT32 hash_size, } } -static void delete_hash_list (void *hash_list, UINT32 list_size, +static void delete_hash_list (EFI_GUID Type, void *hash_list, UINT32 list_size, MokListNode *mok, INTN mok_num) { UINT32 hash_size; @@ -1126,7 +1156,7 @@ static void delete_hash_list (void *hash_list, UINT32 list_size, UINT8 *hash; int i; - hash_size = SHA256_DIGEST_SIZE; + hash_size = sha_size (Type); sig_size = hash_size + sizeof(EFI_GUID); if (list_size < sig_size) return; @@ -1145,7 +1175,6 @@ 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; @@ -1220,9 +1249,9 @@ static EFI_STATUS delete_keys (void *MokDel, UINTN MokDelSize, BOOLEAN MokX) 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); + } else if (is_sha_hash(del_key[i].Type)) { + delete_hash_list(del_key[i].Type, del_key[i].Mok, + del_key[i].MokSize, mok, mok_num); } } -- 1.8.4.5 From 66098cc304ae505d20dc6b6cbdcf8861cd11a9fc Mon Sep 17 00:00:00 2001 From: Gary Ching-Pang Lin Date: Wed, 9 Apr 2014 16:49:25 +0800 Subject: [PATCH 12/16] MokManager: fix the return value and type There are some functions that the return value and the type didn't match. Signed-off-by: Gary Ching-Pang Lin --- MokManager.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/MokManager.c b/MokManager.c index 4ab54ed..78d831e 100644 --- a/MokManager.c +++ b/MokManager.c @@ -565,7 +565,7 @@ static EFI_STATUS list_keys (void *KeyList, UINTN KeyListSize, CHAR16 *title) if (KeyListSize < (sizeof(EFI_SIGNATURE_LIST) + sizeof(EFI_SIGNATURE_DATA))) { console_notify(L"No MOK keys found"); - return 0; + return EFI_NOT_FOUND; } MokNum = count_keys(KeyList, KeyListSize); @@ -575,7 +575,7 @@ static EFI_STATUS list_keys (void *KeyList, UINTN KeyListSize, CHAR16 *title) if (!keys) { console_notify(L"Failed to construct key list"); - return 0; + return EFI_ABORTED; } menu_strings = AllocateZeroPool(sizeof(CHAR16 *) * (MokNum + 2)); @@ -900,7 +900,7 @@ 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 INTN mok_enrollment_prompt (void *MokNew, UINTN MokNewSize, int auth, BOOLEAN MokX) { EFI_GUID shim_lock_guid = SHIM_LOCK_GUID; -- 1.8.4.5 From 3d4fb965556a4a0508d8bc5570203ae210ed9836 Mon Sep 17 00:00:00 2001 From: Gary Ching-Pang Lin Date: Thu, 10 Apr 2014 14:39:43 +0800 Subject: [PATCH 13/16] MokManager: Add more key list safe checks Signed-off-by: Gary Ching-Pang Lin --- MokManager.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 56 insertions(+), 6 deletions(-) diff --git a/MokManager.c b/MokManager.c index 78d831e..1a67a39 100644 --- a/MokManager.c +++ b/MokManager.c @@ -154,6 +154,12 @@ static UINT32 count_keys(void *Data, UINTN DataSize) return 0; } + if (CertList->SignatureListSize == 0 || + CertList->SignatureListSize <= CertList->SignatureSize) { + console_errorbox(L"Corrupted signature list"); + return 0; + } + if (!is_valid_siglist(CertList->SignatureType, CertList->SignatureSize)) { dbsize -= CertList->SignatureListSize; CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + @@ -569,12 +575,13 @@ static EFI_STATUS list_keys (void *KeyList, UINTN KeyListSize, CHAR16 *title) } MokNum = count_keys(KeyList, KeyListSize); - if (MokNum == 0) - return 0; + if (MokNum == 0) { + console_errorbox(L"Invalid key list"); + return EFI_ABORTED; + } keys = build_mok_list(MokNum, KeyList, KeyListSize); - if (!keys) { - console_notify(L"Failed to construct key list"); + console_errorbox(L"Failed to construct key list"); return EFI_ABORTED; } @@ -1221,7 +1228,13 @@ static EFI_STATUS delete_keys (void *MokDel, UINTN MokDelSize, BOOLEAN MokX) efi_status = get_variable_attr (db_name, &MokListData, &MokListDataSize, shim_lock_guid, &attributes); - if (attributes & EFI_VARIABLE_RUNTIME_ACCESS) { + if (efi_status != EFI_SUCCESS) { + if (MokX) + console_errorbox(L"Failed to retrieve MokListX"); + else + console_errorbox(L"Failed to retrieve MokList"); + return EFI_ABORTED; + } else if (attributes & EFI_VARIABLE_RUNTIME_ACCESS) { if (MokX) { err_str1 = L"MokListX is compromised!"; err_str2 = L"Erase all keys in MokListX!"; @@ -1230,7 +1243,11 @@ static EFI_STATUS delete_keys (void *MokDel, UINTN MokDelSize, BOOLEAN MokX) err_str2 = L"Erase all keys in MokList!"; } console_alertbox((CHAR16 *[]){err_str1, err_str2, NULL}); - LibDeleteVariable(db_name, &shim_lock_guid); + uefi_call_wrapper(RT->SetVariable, 5, db_name, + &shim_lock_guid, + EFI_VARIABLE_NON_VOLATILE | + EFI_VARIABLE_BOOTSERVICE_ACCESS, + 0, NULL); return EFI_ACCESS_DENIED; } @@ -1240,9 +1257,41 @@ static EFI_STATUS delete_keys (void *MokDel, UINTN MokDelSize, BOOLEAN MokX) /* Construct lists */ mok_num = count_keys(MokListData, MokListDataSize); + if (mok_num == 0) { + if (MokX) { + err_str1 = L"Failed to construct the key list of MokListX"; + err_str2 = L"Reset MokListX!"; + } else { + err_str1 = L"Failed to construct the key list of MokList"; + err_str2 = L"Reset MokList!"; + } + console_alertbox((CHAR16 *[]){err_str1, err_str2, NULL}); + uefi_call_wrapper(RT->SetVariable, 5, db_name, + &shim_lock_guid, + EFI_VARIABLE_NON_VOLATILE | + EFI_VARIABLE_BOOTSERVICE_ACCESS, + 0, NULL); + efi_status = EFI_ABORTED; + goto error; + } mok = build_mok_list(mok_num, MokListData, MokListDataSize); + if (!mok) { + console_errorbox(L"Failed to construct key list"); + efi_status = EFI_ABORTED; + goto error; + } del_num = count_keys(MokDel, MokDelSize); + if (del_num == 0) { + console_errorbox(L"Invalid key delete list"); + efi_status = EFI_ABORTED; + goto error; + } del_key = build_mok_list(del_num, MokDel, MokDelSize); + if (!del_key) { + console_errorbox(L"Failed to construct key list"); + efi_status = EFI_ABORTED; + goto error; + } /* Search and destroy */ for (i = 0; i < del_num; i++) { @@ -1257,6 +1306,7 @@ static EFI_STATUS delete_keys (void *MokDel, UINTN MokDelSize, BOOLEAN MokX) efi_status = write_back_mok_list(mok, mok_num, MokX); +error: if (MokListData) FreePool(MokListData); if (mok) -- 1.8.4.5 From 8d5456736bae63490a528f6ac12f677bc770cf41 Mon Sep 17 00:00:00 2001 From: Gary Ching-Pang Lin Date: Thu, 10 Apr 2014 15:29:14 +0800 Subject: [PATCH 14/16] MokManager: Support SHA224, SHA384, and SHA512 Signed-off-by: Gary Ching-Pang Lin --- MokManager.c | 40 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 37 insertions(+), 3 deletions(-) diff --git a/MokManager.c b/MokManager.c index 1a67a39..9607d2f 100644 --- a/MokManager.c +++ b/MokManager.c @@ -25,6 +25,9 @@ #define EFI_VARIABLE_APPEND_WRITE 0x00000040 EFI_GUID SHIM_LOCK_GUID = { 0x605dab50, 0xe046, 0x4300, {0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23} }; +EFI_GUID EFI_CERT_SHA224_GUID = { 0xb6e5233, 0xa65c, 0x44c9, {0x94, 0x7, 0xd9, 0xab, 0x83, 0xbf, 0xc8, 0xbd} }; +EFI_GUID EFI_CERT_SHA384_GUID = { 0xff3e5307, 0x9fd0, 0x48c9, {0x85, 0xf1, 0x8a, 0xd5, 0x6c, 0x70, 0x1e, 0x1} }; +EFI_GUID EFI_CERT_SHA512_GUID = { 0x93e0fae, 0xa6c4, 0x4f50, {0x9f, 0x1b, 0xd4, 0x1e, 0x2b, 0x89, 0xc1, 0x9a} }; #define CERT_STRING L"Select an X509 certificate to enroll:\n\n" #define HASH_STRING L"Select a file to trust:\n\n" @@ -96,12 +99,21 @@ done: static BOOLEAN is_sha_hash (EFI_GUID Type) { EFI_GUID Sha1 = EFI_CERT_SHA1_GUID; + EFI_GUID Sha224 = EFI_CERT_SHA224_GUID; EFI_GUID Sha256 = EFI_CERT_SHA256_GUID; + EFI_GUID Sha384 = EFI_CERT_SHA384_GUID; + EFI_GUID Sha512 = EFI_CERT_SHA512_GUID; if (CompareGuid(&Type, &Sha1) == 0) return TRUE; + else if (CompareGuid(&Type, &Sha224) == 0) + return TRUE; else if (CompareGuid(&Type, &Sha256) == 0) return TRUE; + else if (CompareGuid(&Type, &Sha384) == 0) + return TRUE; + else if (CompareGuid(&Type, &Sha512) == 0) + return TRUE; return FALSE; } @@ -109,12 +121,21 @@ static BOOLEAN is_sha_hash (EFI_GUID Type) static UINT32 sha_size (EFI_GUID Type) { EFI_GUID Sha1 = EFI_CERT_SHA1_GUID; + EFI_GUID Sha224 = EFI_CERT_SHA224_GUID; EFI_GUID Sha256 = EFI_CERT_SHA256_GUID; + EFI_GUID Sha384 = EFI_CERT_SHA384_GUID; + EFI_GUID Sha512 = EFI_CERT_SHA512_GUID; if (CompareGuid(&Type, &Sha1) == 0) return SHA1_DIGEST_SIZE; + else if (CompareGuid(&Type, &Sha224) == 0) + return SHA224_DIGEST_LENGTH; else if (CompareGuid(&Type, &Sha256) == 0) return SHA256_DIGEST_SIZE; + else if (CompareGuid(&Type, &Sha384) == 0) + return SHA384_DIGEST_LENGTH; + else if (CompareGuid(&Type, &Sha512) == 0) + return SHA512_DIGEST_LENGTH; return 0; } @@ -439,7 +460,10 @@ static void show_x509_info (X509 *X509Cert, UINT8 *hash) static void show_sha_digest (EFI_GUID Type, UINT8 *hash) { EFI_GUID Sha1 = EFI_CERT_SHA1_GUID; + EFI_GUID Sha224 = EFI_CERT_SHA224_GUID; EFI_GUID Sha256 = EFI_CERT_SHA256_GUID; + EFI_GUID Sha384 = EFI_CERT_SHA384_GUID; + EFI_GUID Sha512 = EFI_CERT_SHA512_GUID; CHAR16 *text[5]; POOL_PRINT hash_string1; POOL_PRINT hash_string2; @@ -449,9 +473,18 @@ static void show_sha_digest (EFI_GUID Type, UINT8 *hash) if (CompareGuid(&Type, &Sha1) == 0) { length = SHA1_DIGEST_SIZE; text[0] = L"SHA1 hash"; + } else if (CompareGuid(&Type, &Sha224) == 0) { + length = SHA224_DIGEST_LENGTH; + text[0] = L"SHA224 hash"; } else if (CompareGuid(&Type, &Sha256) == 0) { length = SHA256_DIGEST_SIZE; text[0] = L"SHA256 hash"; + } else if (CompareGuid(&Type, &Sha384) == 0) { + length = SHA384_DIGEST_LENGTH; + text[0] = L"SHA384 hash"; + } else if (CompareGuid(&Type, &Sha512) == 0) { + length = SHA512_DIGEST_LENGTH; + text[0] = L"SHA512 hash"; } else { return; } @@ -1113,7 +1146,7 @@ static void mem_move (void *dest, void *src, UINTN size) d[i] = s[i]; } -static void delete_hash_in_list (UINT8 *hash, UINT32 hash_size, +static void delete_hash_in_list (EFI_GUID Type, UINT8 *hash, UINT32 hash_size, MokListNode *mok, INTN mok_num) { UINT32 sig_size; @@ -1125,7 +1158,8 @@ static void delete_hash_in_list (UINT8 *hash, UINT32 hash_size, sig_size = hash_size + sizeof(EFI_GUID); for (i = 0; i < mok_num; i++) { - if (!is_sha_hash(mok[i].Type) || (mok[i].MokSize < sig_size)) + if ((CompareGuid(&(mok[i].Type), &Type) != 0) || + (mok[i].MokSize < sig_size)) continue; list_num = mok[i].MokSize / sig_size; @@ -1173,7 +1207,7 @@ static void delete_hash_list (EFI_GUID Type, void *hash_list, UINT32 list_size, hash = hash_list + sizeof(EFI_GUID); for (i = 0; i < hash_num; i++) { - delete_hash_in_list (hash, hash_size, mok, mok_num); + delete_hash_in_list (Type, hash, hash_size, mok, mok_num); hash += sig_size; } } -- 1.8.4.5 From 2d0e330fb06a7d26810f86dcfdb59b045d444b51 Mon Sep 17 00:00:00 2001 From: Gary Ching-Pang Lin Date: Thu, 10 Apr 2014 15:55:35 +0800 Subject: [PATCH 15/16] MokManager: Discard the list contains an invalid signature Signed-off-by: Gary Ching-Pang Lin --- MokManager.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/MokManager.c b/MokManager.c index 9607d2f..046f779 100644 --- a/MokManager.c +++ b/MokManager.c @@ -182,10 +182,8 @@ static UINT32 count_keys(void *Data, UINTN DataSize) } if (!is_valid_siglist(CertList->SignatureType, CertList->SignatureSize)) { - dbsize -= CertList->SignatureListSize; - CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + - CertList->SignatureListSize); - continue; + console_errorbox(L"Invalid signature list found"); + return 0; } MokNum++; @@ -219,12 +217,9 @@ static MokListNode *build_mok_list(UINT32 num, void *Data, UINTN DataSize) { FreePool(list); return NULL; } - if (!is_valid_siglist(CertList->SignatureType, CertList->SignatureSize)) { - dbsize -= CertList->SignatureListSize; - CertList = (EFI_SIGNATURE_LIST *)((UINT8 *) CertList + - CertList->SignatureListSize); - continue; - } + + /* Omit the signature check here since we already did it + in count_keys() */ Cert = (EFI_SIGNATURE_DATA *) (((UINT8 *) CertList) + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize); -- 1.8.4.5 From 658c3ac8ea38ac057f21278c9d10ba8aae28b0a5 Mon Sep 17 00:00:00 2001 From: Gary Ching-Pang Lin Date: Tue, 28 Oct 2014 11:21:51 +0800 Subject: [PATCH 16/16] MokManager: fix comparison between signed and unsigned integer Patch from Johannes Segitz --- MokManager.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/MokManager.c b/MokManager.c index 046f779..442ab8f 100644 --- a/MokManager.c +++ b/MokManager.c @@ -513,8 +513,8 @@ static void show_efi_hash (EFI_GUID Type, void *Mok, UINTN MokSize) UINTN hash_num; UINT8 *hash; CHAR16 **menu_strings; - int key_num = 0; - int i; + UINTN key_num = 0; + UINTN i; sig_size = sha_size(Type) + sizeof(EFI_GUID); if ((MokSize % sig_size) != 0) { @@ -592,7 +592,7 @@ static EFI_STATUS list_keys (void *KeyList, UINTN KeyListSize, CHAR16 *title) { INTN MokNum = 0; MokListNode *keys = NULL; - int key_num = 0; + UINT32 key_num = 0; CHAR16 **menu_strings; int i; @@ -1118,7 +1118,7 @@ static int match_hash (UINT8 *hash, UINT32 hash_size, int start, void *hash_list, UINT32 list_num) { UINT8 *ptr; - int i; + UINTN i; ptr = hash_list + sizeof(EFI_GUID); for (i = start; i < list_num; i++) { @@ -1133,7 +1133,7 @@ static int match_hash (UINT8 *hash, UINT32 hash_size, int start, static void mem_move (void *dest, void *src, UINTN size) { UINT8 *d, *s; - int i; + UINTN i; d = (UINT8 *)dest; s = (UINT8 *)src; @@ -1190,7 +1190,7 @@ static void delete_hash_list (EFI_GUID Type, void *hash_list, UINT32 list_size, UINT32 hash_num; UINT32 sig_size; UINT8 *hash; - int i; + UINT32 i; hash_size = sha_size (Type); sig_size = hash_size + sizeof(EFI_GUID); -- 1.8.4.5