mirror of
https://git.proxmox.com/git/efi-boot-shim
synced 2025-07-27 12:45:27 +00:00
Add MOK password auth
Add support for setting an MOK password. The OS passes down a password hash. MokManager then presents an option for setting a password. Selecting it prompts the user for the same password again. If they match, the hash is enrolled into a boot services variable and MokManager will prompt for the password whenever it's started.
This commit is contained in:
parent
310ec753fa
commit
801c0faaf7
171
MokManager.c
171
MokManager.c
@ -777,6 +777,86 @@ static INTN mok_sb_prompt (void *MokSB, void *data2, void *data3) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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];
|
||||||
|
|
||||||
|
if (MokPWSize != SHA256_DIGEST_SIZE) {
|
||||||
|
Print(L"Invalid MokPW variable contents\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
LibDeleteVariable(L"MokPW", &shim_lock_guid);
|
||||||
|
|
||||||
|
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,
|
||||||
|
SB_PASSWORD_LEN, 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) {
|
||||||
|
Print(L"Password limit reached\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Print(L"Set MOK password? (y/n): ");
|
||||||
|
|
||||||
|
do {
|
||||||
|
get_line (&length, line, 1, 1);
|
||||||
|
|
||||||
|
if (line[0] == 'Y' || line[0] == 'y') {
|
||||||
|
efi_status = uefi_call_wrapper(RT->SetVariable, 5,
|
||||||
|
L"MokPWStore",
|
||||||
|
&shim_lock_guid,
|
||||||
|
EFI_VARIABLE_NON_VOLATILE |
|
||||||
|
EFI_VARIABLE_BOOTSERVICE_ACCESS,
|
||||||
|
MokPWSize, MokPW);
|
||||||
|
if (efi_status != EFI_SUCCESS) {
|
||||||
|
Print(L"Failed to set MOK password\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Print(L"Press 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 0;
|
||||||
|
}
|
||||||
|
|
||||||
static UINTN draw_menu (CHAR16 *header, UINTN lines, struct menu_item *items,
|
static UINTN draw_menu (CHAR16 *header, UINTN lines, struct menu_item *items,
|
||||||
UINTN count) {
|
UINTN count) {
|
||||||
UINTN i;
|
UINTN i;
|
||||||
@ -1335,9 +1415,67 @@ static INTN find_fs (void *data, void *data2, void *data3) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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",
|
||||||
|
&shim_lock_guid, &attributes, &size,
|
||||||
|
pwhash);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If anything can attack the password it could just set it to a
|
||||||
|
* known value, so there's no safety advantage in failing to validate
|
||||||
|
* purely because of a failure to read the variable
|
||||||
|
*/
|
||||||
|
if (efi_status != EFI_SUCCESS)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
if (attributes & EFI_VARIABLE_RUNTIME_ACCESS)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
Print(L"Password limit reached\n");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
static EFI_STATUS enter_mok_menu(EFI_HANDLE image_handle, void *MokNew,
|
static EFI_STATUS enter_mok_menu(EFI_HANDLE image_handle, void *MokNew,
|
||||||
UINTN MokNewSize, void *MokSB,
|
UINTN MokNewSize, void *MokSB,
|
||||||
UINTN MokSBSize)
|
UINTN MokSBSize, void *MokPW, UINTN MokPWSize)
|
||||||
{
|
{
|
||||||
struct menu_item *menu_item;
|
struct menu_item *menu_item;
|
||||||
UINT32 MokAuth = 0;
|
UINT32 MokAuth = 0;
|
||||||
@ -1348,6 +1486,9 @@ static EFI_STATUS enter_mok_menu(EFI_HANDLE image_handle, void *MokNew,
|
|||||||
UINTN auth_size = SHA256_DIGEST_SIZE;
|
UINTN auth_size = SHA256_DIGEST_SIZE;
|
||||||
UINT32 attributes;
|
UINT32 attributes;
|
||||||
|
|
||||||
|
if (verify_pw() == FALSE)
|
||||||
|
return EFI_ACCESS_DENIED;
|
||||||
|
|
||||||
efi_status = uefi_call_wrapper(RT->GetVariable, 5, L"MokAuth",
|
efi_status = uefi_call_wrapper(RT->GetVariable, 5, L"MokAuth",
|
||||||
&shim_lock_guid,
|
&shim_lock_guid,
|
||||||
&attributes, &auth_size, auth);
|
&attributes, &auth_size, auth);
|
||||||
@ -1361,6 +1502,9 @@ static EFI_STATUS enter_mok_menu(EFI_HANDLE image_handle, void *MokNew,
|
|||||||
if (MokSB)
|
if (MokSB)
|
||||||
menucount++;
|
menucount++;
|
||||||
|
|
||||||
|
if (MokPW)
|
||||||
|
menucount++;
|
||||||
|
|
||||||
menu_item = AllocateZeroPool(sizeof(struct menu_item) * menucount);
|
menu_item = AllocateZeroPool(sizeof(struct menu_item) * menucount);
|
||||||
|
|
||||||
if (!menu_item)
|
if (!menu_item)
|
||||||
@ -1396,6 +1540,15 @@ static EFI_STATUS enter_mok_menu(EFI_HANDLE image_handle, void *MokNew,
|
|||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (MokPW) {
|
||||||
|
menu_item[i].text = StrDuplicate(L"Set MOK password");
|
||||||
|
menu_item[i].colour = EFI_WHITE;
|
||||||
|
menu_item[i].callback = mok_pw_prompt;
|
||||||
|
menu_item[i].data = MokPW;
|
||||||
|
menu_item[i].data2 = (void *)MokPWSize;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
menu_item[i].text = StrDuplicate(L"Enroll key from disk");
|
menu_item[i].text = StrDuplicate(L"Enroll key from disk");
|
||||||
menu_item[i].colour = EFI_WHITE;
|
menu_item[i].colour = EFI_WHITE;
|
||||||
menu_item[i].callback = find_fs;
|
menu_item[i].callback = find_fs;
|
||||||
@ -1420,15 +1573,19 @@ static EFI_STATUS enter_mok_menu(EFI_HANDLE image_handle, void *MokNew,
|
|||||||
static EFI_STATUS check_mok_request(EFI_HANDLE image_handle)
|
static EFI_STATUS check_mok_request(EFI_HANDLE image_handle)
|
||||||
{
|
{
|
||||||
EFI_GUID shim_lock_guid = SHIM_LOCK_GUID;
|
EFI_GUID shim_lock_guid = SHIM_LOCK_GUID;
|
||||||
UINTN MokNewSize = 0, MokSBSize = 0;
|
UINTN MokNewSize = 0, MokSBSize = 0, MokPWSize = 0;
|
||||||
void *MokNew = NULL;
|
void *MokNew = NULL;
|
||||||
void *MokSB = NULL;
|
void *MokSB = NULL;
|
||||||
|
void *MokPW = NULL;
|
||||||
|
|
||||||
MokNew = LibGetVariableAndSize(L"MokNew", &shim_lock_guid, &MokNewSize);
|
MokNew = LibGetVariableAndSize(L"MokNew", &shim_lock_guid, &MokNewSize);
|
||||||
|
|
||||||
MokSB = LibGetVariableAndSize(L"MokSB", &shim_lock_guid, &MokSBSize);
|
MokSB = LibGetVariableAndSize(L"MokSB", &shim_lock_guid, &MokSBSize);
|
||||||
|
|
||||||
enter_mok_menu(image_handle, MokNew, MokNewSize, MokSB, MokSBSize);
|
MokPW = LibGetVariableAndSize(L"MokPW", &shim_lock_guid, &MokPWSize);
|
||||||
|
|
||||||
|
enter_mok_menu(image_handle, MokNew, MokNewSize, MokSB, MokSBSize,
|
||||||
|
MokPW, MokPWSize);
|
||||||
|
|
||||||
if (MokNew) {
|
if (MokNew) {
|
||||||
if (LibDeleteVariable(L"MokNew", &shim_lock_guid) != EFI_SUCCESS) {
|
if (LibDeleteVariable(L"MokNew", &shim_lock_guid) != EFI_SUCCESS) {
|
||||||
@ -1443,6 +1600,14 @@ static EFI_STATUS check_mok_request(EFI_HANDLE image_handle)
|
|||||||
}
|
}
|
||||||
FreePool (MokNew);
|
FreePool (MokNew);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (MokPW) {
|
||||||
|
if (LibDeleteVariable(L"MokPW", &shim_lock_guid) != EFI_SUCCESS) {
|
||||||
|
Print(L"Failed to delete MokPW\n");
|
||||||
|
}
|
||||||
|
FreePool (MokNew);
|
||||||
|
}
|
||||||
|
|
||||||
LibDeleteVariable(L"MokAuth", &shim_lock_guid);
|
LibDeleteVariable(L"MokAuth", &shim_lock_guid);
|
||||||
|
|
||||||
return EFI_SUCCESS;
|
return EFI_SUCCESS;
|
||||||
|
16
shim.c
16
shim.c
@ -1038,23 +1038,29 @@ done:
|
|||||||
EFI_STATUS check_mok_request(EFI_HANDLE image_handle)
|
EFI_STATUS check_mok_request(EFI_HANDLE image_handle)
|
||||||
{
|
{
|
||||||
EFI_GUID shim_lock_guid = SHIM_LOCK_GUID;
|
EFI_GUID shim_lock_guid = SHIM_LOCK_GUID;
|
||||||
EFI_STATUS moknew_status, moksb_status, efi_status;
|
EFI_STATUS moknew_status, moksb_status, mokpw_status, efi_status;
|
||||||
UINTN size = sizeof(UINT32);
|
UINTN size = sizeof(UINT32);
|
||||||
UINT32 MokNew;
|
UINT32 MokVar;
|
||||||
UINT32 attributes;
|
UINT32 attributes;
|
||||||
|
|
||||||
moknew_status = uefi_call_wrapper(RT->GetVariable, 5, L"MokNew",
|
moknew_status = uefi_call_wrapper(RT->GetVariable, 5, L"MokNew",
|
||||||
&shim_lock_guid, &attributes,
|
&shim_lock_guid, &attributes,
|
||||||
&size, (void *)&MokNew);
|
&size, (void *)&MokVar);
|
||||||
|
|
||||||
moksb_status = uefi_call_wrapper(RT->GetVariable, 5, L"MokSB",
|
moksb_status = uefi_call_wrapper(RT->GetVariable, 5, L"MokSB",
|
||||||
&shim_lock_guid, &attributes,
|
&shim_lock_guid, &attributes,
|
||||||
&size, (void *)&MokNew);
|
&size, (void *)&MokVar);
|
||||||
|
|
||||||
|
mokpw_status = uefi_call_wrapper(RT->GetVariable, 5, L"MokPW",
|
||||||
|
&shim_lock_guid, &attributes,
|
||||||
|
&size, (void *)&MokVar);
|
||||||
|
|
||||||
if (moknew_status == EFI_SUCCESS ||
|
if (moknew_status == EFI_SUCCESS ||
|
||||||
moknew_status == EFI_BUFFER_TOO_SMALL ||
|
moknew_status == EFI_BUFFER_TOO_SMALL ||
|
||||||
moksb_status == EFI_SUCCESS ||
|
moksb_status == EFI_SUCCESS ||
|
||||||
moksb_status == EFI_BUFFER_TOO_SMALL) {
|
moksb_status == EFI_BUFFER_TOO_SMALL ||
|
||||||
|
mokpw_status == EFI_SUCCESS ||
|
||||||
|
mokpw_status == EFI_BUFFER_TOO_SMALL) {
|
||||||
efi_status = start_image(image_handle, MOK_MANAGER);
|
efi_status = start_image(image_handle, MOK_MANAGER);
|
||||||
|
|
||||||
if (efi_status != EFI_SUCCESS) {
|
if (efi_status != EFI_SUCCESS) {
|
||||||
|
Loading…
Reference in New Issue
Block a user