diff --git a/MokManager.c b/MokManager.c index 08b15d6d1..c195cadc5 100644 --- a/MokManager.c +++ b/MokManager.c @@ -40,6 +40,12 @@ typedef struct { CHAR16 Password[SB_PASSWORD_LEN]; } __attribute__ ((packed)) MokDBvar; +typedef struct { + UINT32 MokTMLState; + UINT32 PWLen; + CHAR16 Password[SB_PASSWORD_LEN]; +} __attribute__ ((packed)) MokTMLvar; + typedef struct { INT32 Timeout; } __attribute__ ((packed)) MokTimeoutvar; @@ -1678,6 +1684,121 @@ static EFI_STATUS mok_db_prompt(void *MokDB, UINTN MokDBSize) return EFI_SUCCESS; } +static EFI_STATUS mok_tml_prompt(void *MokTML, UINTN MokTMLSize) +{ + EFI_STATUS efi_status; + SIMPLE_TEXT_OUTPUT_MODE SavedMode; + MokTMLvar *var = MokTML; + CHAR16 *message[4]; + CHAR16 pass1, pass2, pass3; + CHAR16 *str; + UINT8 fail_count = 0; + UINT8 dbval = 1; + UINT8 pos1, pos2, pos3; + int ret; + CHAR16 *untrust_tml[] = { L"Do not trust the MOK list", NULL }; + CHAR16 *trust_tml[] = { L"Trust the MOK list", NULL }; + + if (MokTMLSize != sizeof(MokTMLvar)) { + console_notify(L"Invalid MokTML variable contents"); + return EFI_INVALID_PARAMETER; + } + + clear_screen(); + + message[0] = L"Change Trusted MOK List Keyring state"; + message[1] = NULL; + + console_save_and_set_mode(&SavedMode); + console_print_box_at(message, -1, 0, 0, -1, -1, 1, 1); + console_restore_mode(&SavedMode); + + while (fail_count < 3) { + RandomBytes(&pos1, sizeof(pos1)); + pos1 = (pos1 % var->PWLen); + + do { + RandomBytes(&pos2, sizeof(pos2)); + pos2 = (pos2 % var->PWLen); + } while (pos2 == pos1); + + do { + RandomBytes(&pos3, sizeof(pos3)); + pos3 = (pos3 % var->PWLen); + } while (pos3 == pos2 || pos3 == pos1); + + str = PoolPrint(L"Enter password character %d: ", pos1 + 1); + if (!str) { + console_errorbox(L"Failed to allocate buffer"); + return EFI_OUT_OF_RESOURCES; + } + pass1 = get_password_charater(str); + FreePool(str); + + str = PoolPrint(L"Enter password character %d: ", pos2 + 1); + if (!str) { + console_errorbox(L"Failed to allocate buffer"); + return EFI_OUT_OF_RESOURCES; + } + pass2 = get_password_charater(str); + FreePool(str); + + str = PoolPrint(L"Enter password character %d: ", pos3 + 1); + if (!str) { + console_errorbox(L"Failed to allocate buffer"); + return EFI_OUT_OF_RESOURCES; + } + pass3 = get_password_charater(str); + FreePool(str); + + if (pass1 != var->Password[pos1] || + pass2 != var->Password[pos2] || + pass3 != var->Password[pos3]) { + console_print(L"Invalid character\n"); + fail_count++; + } else { + break; + } + } + + if (fail_count >= 3) { + console_notify(L"Password limit reached"); + return EFI_ACCESS_DENIED; + } + + if (var->MokTMLState == 0) + ret = console_yes_no(trust_tml); + else + ret = console_yes_no(untrust_tml); + + if (ret == 0) { + LibDeleteVariable(L"MokListTrustedNew", &SHIM_LOCK_GUID); + return EFI_ABORTED; + } + + if (var->MokTMLState == 0) { + efi_status = RT->SetVariable(L"MokListTrusted", &SHIM_LOCK_GUID, + EFI_VARIABLE_NON_VOLATILE | + EFI_VARIABLE_BOOTSERVICE_ACCESS, + 1, &dbval); + if (EFI_ERROR(efi_status)) { + console_notify(L"Failed to set MokListTrusted state"); + return efi_status; + } + } else { + efi_status = RT->SetVariable(L"MokListTrusted", &SHIM_LOCK_GUID, + EFI_VARIABLE_NON_VOLATILE | + EFI_VARIABLE_BOOTSERVICE_ACCESS, + 0, NULL); + if (EFI_ERROR(efi_status)) { + console_notify(L"Failed to delete MokListTrusted state"); + return efi_status; + } + } + + return EFI_SUCCESS; +} + static EFI_STATUS mok_pw_prompt(void *MokPW, UINTN MokPWSize) { EFI_STATUS efi_status; @@ -2076,7 +2197,8 @@ typedef enum { MOK_SET_PW, MOK_CHANGE_DB, MOK_KEY_ENROLL, - MOK_HASH_ENROLL + MOK_HASH_ENROLL, + MOK_CHANGE_TML } mok_menu_item; static void free_menu(mok_menu_item * menu_item, CHAR16 ** menu_strings) @@ -2095,7 +2217,8 @@ static EFI_STATUS enter_mok_menu(EFI_HANDLE image_handle UNUSED, void *MokPW, UINTN MokPWSize, void *MokDB, UINTN MokDBSize, void *MokXNew, UINTN MokXNewSize, - void *MokXDel, UINTN MokXDelSize) + void *MokXDel, UINTN MokXDelSize, + void *MokTML, UINTN MokTMLSize) { CHAR16 **menu_strings = NULL; mok_menu_item *menu_item = NULL; @@ -2171,6 +2294,9 @@ static EFI_STATUS enter_mok_menu(EFI_HANDLE image_handle UNUSED, if (MokDB) menucount++; + if (MokTML) + menucount++; + menu_strings = AllocateZeroPool(sizeof(CHAR16 *) * (menucount + 1)); if (!menu_strings) @@ -2242,6 +2368,12 @@ static EFI_STATUS enter_mok_menu(EFI_HANDLE image_handle UNUSED, i++; } + if (MokTML) { + menu_strings[i] = L"Change MOK List Trusted State"; + menu_item[i] = MOK_CHANGE_TML; + i++; + } + menu_strings[i] = L"Enroll key from disk"; menu_item[i] = MOK_KEY_ENROLL; i++; @@ -2352,6 +2484,17 @@ static EFI_STATUS enter_mok_menu(EFI_HANDLE image_handle UNUSED, case MOK_HASH_ENROLL: efi_status = mok_hash_enroll(); break; + case MOK_CHANGE_TML: + if (!MokTML) { + console_print(L"MokManager: internal error: %s", + L"MokListTrusted was ! NULL bs is now NULL\n"); + ret = EFI_ABORTED; + goto out; + } + efi_status = mok_tml_prompt(MokTML, MokTMLSize); + if (!EFI_ERROR(efi_status)) + MokTML = NULL; + break; } if (!EFI_ERROR(efi_status)) @@ -2376,7 +2519,7 @@ static EFI_STATUS enter_mok_menu(EFI_HANDLE image_handle UNUSED, static EFI_STATUS check_mok_request(EFI_HANDLE image_handle) { UINTN MokNewSize = 0, MokDelSize = 0, MokSBSize = 0, MokPWSize = 0; - UINTN MokDBSize = 0, MokXNewSize = 0, MokXDelSize = 0; + UINTN MokDBSize = 0, MokXNewSize = 0, MokXDelSize = 0, MokTMLSize = 0; void *MokNew = NULL; void *MokDel = NULL; void *MokSB = NULL; @@ -2384,6 +2527,7 @@ static EFI_STATUS check_mok_request(EFI_HANDLE image_handle) void *MokDB = NULL; void *MokXNew = NULL; void *MokXDel = NULL; + void *MokTML = NULL; EFI_STATUS efi_status; efi_status = get_variable(L"MokNew", (UINT8 **) & MokNew, &MokNewSize, @@ -2436,6 +2580,18 @@ static EFI_STATUS check_mok_request(EFI_HANDLE image_handle) console_error(L"Could not retrieve MokDB", efi_status); } + efi_status = get_variable(L"MokListTrustedNew", (UINT8 **) & MokTML, + &MokTMLSize, SHIM_LOCK_GUID); + if (!EFI_ERROR(efi_status)) { + efi_status = LibDeleteVariable(L"MokListTrustedNew", + &SHIM_LOCK_GUID); + if (EFI_ERROR(efi_status)) + console_notify(L"Failed to delete MokListTrustedNew"); + } else if (EFI_ERROR(efi_status) && efi_status != EFI_NOT_FOUND) { + console_error(L"Could not retrieve MokListTrustedNew", + efi_status); + } + efi_status = get_variable(L"MokXNew", (UINT8 **) & MokXNew, &MokXNewSize, SHIM_LOCK_GUID); if (!EFI_ERROR(efi_status)) { @@ -2458,7 +2614,7 @@ static EFI_STATUS check_mok_request(EFI_HANDLE image_handle) enter_mok_menu(image_handle, MokNew, MokNewSize, MokDel, MokDelSize, MokSB, MokSBSize, MokPW, MokPWSize, MokDB, MokDBSize, - MokXNew, MokXNewSize, MokXDel, MokXDelSize); + MokXNew, MokXNewSize, MokXDel, MokXDelSize, MokTML, MokTMLSize); if (MokNew) FreePool(MokNew); @@ -2481,6 +2637,9 @@ static EFI_STATUS check_mok_request(EFI_HANDLE image_handle) if (MokXDel) FreePool(MokXDel); + if (MokTML) + FreePool(MokTML); + LibDeleteVariable(L"MokAuth", &SHIM_LOCK_GUID); LibDeleteVariable(L"MokDelAuth", &SHIM_LOCK_GUID); LibDeleteVariable(L"MokXAuth", &SHIM_LOCK_GUID); diff --git a/MokVars.txt b/MokVars.txt index 4b80a4134..cdfec2c8e 100644 --- a/MokVars.txt +++ b/MokVars.txt @@ -77,3 +77,9 @@ or not to import DB certs for its own verification purposes. MokPWStore: A SHA-256 representation of the password set by the user via MokPW. The user will be prompted to enter this password in order to interact with MokManager. + +MokListTrusted: An 8-bit unsigned integer. If 1, it signifies to Linux +to trust CA keys in the MokList. BS,NV + +MokListTrustedRT: A copy of MokListTrusted made available to the kernel +at runtime. RT diff --git a/globals.c b/globals.c index 476e2e9ca..4a1f432fd 100644 --- a/globals.c +++ b/globals.c @@ -25,6 +25,7 @@ int loader_is_participating; UINT8 user_insecure_mode; UINT8 ignore_db; +UINT8 trust_mok_list; UINT32 verbose = 0; diff --git a/mok.c b/mok.c index 7755eea9b..52dffc3ea 100644 --- a/mok.c +++ b/mok.c @@ -46,7 +46,7 @@ static EFI_STATUS check_mok_request(EFI_HANDLE image_handle) check_var(L"MokPW") || check_var(L"MokAuth") || check_var(L"MokDel") || check_var(L"MokDB") || check_var(L"MokXNew") || check_var(L"MokXDel") || - check_var(L"MokXAuth")) { + check_var(L"MokXAuth") || check_var(L"MokListTrustedNew")) { efi_status = start_image(image_handle, MOK_MANAGER); if (EFI_ERROR(efi_status)) { @@ -166,6 +166,20 @@ struct mok_state_variable mok_state_variable_data[] = { MOK_VARIABLE_MEASURE, .pcr = 7, }, + {.name = L"MokListTrusted", + .name8 = "MokListTrusted", + .rtname = L"MokListTrustedRT", + .rtname8 = "MokListTrustedRT", + .guid = &SHIM_LOCK_GUID, + .yes_attr = EFI_VARIABLE_BOOTSERVICE_ACCESS | + EFI_VARIABLE_NON_VOLATILE, + .no_attr = EFI_VARIABLE_RUNTIME_ACCESS, + .flags = MOK_MIRROR_DELETE_FIRST | + MOK_VARIABLE_MEASURE | + MOK_VARIABLE_LOG, + .pcr = 14, + .state = &trust_mok_list, + }, { NULL, } }; size_t n_mok_state_variables = sizeof(mok_state_variable_data) / sizeof(mok_state_variable_data[0]); @@ -897,6 +911,7 @@ EFI_STATUS import_mok_state(EFI_HANDLE image_handle) user_insecure_mode = 0; ignore_db = 0; + trust_mok_list = 0; UINT64 config_sz = 0; UINT8 *config_table = NULL; diff --git a/shim.h b/shim.h index 5e1ab36b5..69442da3f 100644 --- a/shim.h +++ b/shim.h @@ -255,6 +255,7 @@ extern UINT8 *build_cert; extern UINT8 user_insecure_mode; extern UINT8 ignore_db; +extern UINT8 trust_mok_list; extern UINT8 in_protocol; extern void *load_options; extern UINT32 load_options_size;