mirror of
https://git.proxmox.com/git/efi-boot-shim
synced 2025-08-08 08:05:10 +00:00
Merge branch 'mok' into netboot
Conflicts: Makefile shim.c
This commit is contained in:
commit
5c9470f288
7
Makefile
7
Makefile
@ -29,7 +29,7 @@ LDFLAGS = -nostdlib -znocombreloc -T $(EFI_LDS) -shared -Bsymbolic -L$(EFI_PATH
|
|||||||
VERSION = 0.1
|
VERSION = 0.1
|
||||||
|
|
||||||
TARGET = shim.efi MokManager.efi
|
TARGET = shim.efi MokManager.efi
|
||||||
OBJS = shim.o netboot.o cert.o
|
OBJS = shim.o netboot.o cert.o dbx.o
|
||||||
SOURCES = shim.c shim.h netboot.c signature.h PeImage.h
|
SOURCES = shim.c shim.h netboot.c signature.h PeImage.h
|
||||||
MOK_OBJS = MokManager.o
|
MOK_OBJS = MokManager.o
|
||||||
MOK_SOURCES = MokManager.c shim.h
|
MOK_SOURCES = MokManager.c shim.h
|
||||||
@ -41,7 +41,10 @@ shim.o: $(SOURCES)
|
|||||||
cert.o : cert.S
|
cert.o : cert.S
|
||||||
$(CC) $(CFLAGS) -c -o $@ $<
|
$(CC) $(CFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
shim.so: $(OBJS) Cryptlib/libcryptlib.a Cryptlib/OpenSSL/libopenssl.a cert.o
|
dbx.o : dbx.S
|
||||||
|
$(CC) $(CFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
|
shim.so: $(OBJS) Cryptlib/libcryptlib.a Cryptlib/OpenSSL/libopenssl.a
|
||||||
$(LD) -o $@ $(LDFLAGS) $^ $(EFI_LIBS)
|
$(LD) -o $@ $(LDFLAGS) $^ $(EFI_LIBS)
|
||||||
|
|
||||||
MokManager.o: $(SOURCES)
|
MokManager.o: $(SOURCES)
|
||||||
|
541
MokManager.c
541
MokManager.c
@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
#define PASSWORD_MAX 16
|
#define PASSWORD_MAX 16
|
||||||
#define PASSWORD_MIN 8
|
#define PASSWORD_MIN 8
|
||||||
|
#define SB_PASSWORD_LEN 8
|
||||||
|
|
||||||
#ifndef SHIM_VENDOR
|
#ifndef SHIM_VENDOR
|
||||||
#define SHIM_VENDOR L"Shim"
|
#define SHIM_VENDOR L"Shim"
|
||||||
@ -15,6 +16,9 @@
|
|||||||
|
|
||||||
#define EFI_VARIABLE_APPEND_WRITE 0x00000040
|
#define EFI_VARIABLE_APPEND_WRITE 0x00000040
|
||||||
|
|
||||||
|
#define CERT_STRING L"Select an X509 certificate to enroll:\n\n"
|
||||||
|
#define HASH_STRING L"Select a file to trust:\n\n"
|
||||||
|
|
||||||
struct menu_item {
|
struct menu_item {
|
||||||
CHAR16 *text;
|
CHAR16 *text;
|
||||||
INTN (* callback)(void *data, void *data2, void *data3);
|
INTN (* callback)(void *data, void *data2, void *data3);
|
||||||
@ -29,6 +33,12 @@ typedef struct {
|
|||||||
UINT8 *Mok;
|
UINT8 *Mok;
|
||||||
} __attribute__ ((packed)) MokListNode;
|
} __attribute__ ((packed)) MokListNode;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
UINT32 MokSBState;
|
||||||
|
UINT32 PWLen;
|
||||||
|
CHAR16 Password[PASSWORD_MAX];
|
||||||
|
} __attribute__ ((packed)) MokSBvar;
|
||||||
|
|
||||||
static EFI_INPUT_KEY get_keystroke (void)
|
static EFI_INPUT_KEY get_keystroke (void)
|
||||||
{
|
{
|
||||||
EFI_INPUT_KEY key;
|
EFI_INPUT_KEY key;
|
||||||
@ -99,7 +109,7 @@ static MokListNode *build_mok_list(UINT32 num, void *Data, UINTN DataSize) {
|
|||||||
(CompareGuid (&CertList->SignatureType, &HashType) != 0)) {
|
(CompareGuid (&CertList->SignatureType, &HashType) != 0)) {
|
||||||
dbsize -= CertList->SignatureListSize;
|
dbsize -= CertList->SignatureListSize;
|
||||||
CertList = (EFI_SIGNATURE_LIST *)((UINT8 *) CertList +
|
CertList = (EFI_SIGNATURE_LIST *)((UINT8 *) CertList +
|
||||||
CertList->SignatureSize);
|
CertList->SignatureListSize);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -107,7 +117,7 @@ static MokListNode *build_mok_list(UINT32 num, void *Data, UINTN DataSize) {
|
|||||||
(CertList->SignatureSize != 48)) {
|
(CertList->SignatureSize != 48)) {
|
||||||
dbsize -= CertList->SignatureListSize;
|
dbsize -= CertList->SignatureListSize;
|
||||||
CertList = (EFI_SIGNATURE_LIST *)((UINT8 *) CertList +
|
CertList = (EFI_SIGNATURE_LIST *)((UINT8 *) CertList +
|
||||||
CertList->SignatureSize);
|
CertList->SignatureListSize);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -120,7 +130,7 @@ static MokListNode *build_mok_list(UINT32 num, void *Data, UINTN DataSize) {
|
|||||||
count++;
|
count++;
|
||||||
dbsize -= CertList->SignatureListSize;
|
dbsize -= CertList->SignatureListSize;
|
||||||
CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList +
|
CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList +
|
||||||
CertList->SignatureSize);
|
CertList->SignatureListSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
return list;
|
return list;
|
||||||
@ -308,8 +318,8 @@ static void show_mok_info (void *Mok, UINTN MokSize)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
if (MokSize != 48) {
|
if (MokSize != 48) {
|
||||||
if (X509ConstructCertificate(Mok, MokSize, (UINT8 **) &X509Cert) &&
|
if (X509ConstructCertificate(Mok, MokSize,
|
||||||
X509Cert != NULL) {
|
(UINT8 **) &X509Cert) && X509Cert != NULL) {
|
||||||
show_x509_info(X509Cert);
|
show_x509_info(X509Cert);
|
||||||
X509_free(X509Cert);
|
X509_free(X509Cert);
|
||||||
} else {
|
} else {
|
||||||
@ -317,6 +327,20 @@ static void show_mok_info (void *Mok, UINTN MokSize)
|
|||||||
((UINT32 *)Mok)[0]);
|
((UINT32 *)Mok)[0]);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
efi_status = get_sha1sum(Mok, MokSize, hash);
|
||||||
|
|
||||||
|
if (efi_status != EFI_SUCCESS) {
|
||||||
|
Print(L"Failed to compute MOK fingerprint\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Print(L" Fingerprint (SHA1):\n ");
|
||||||
|
for (i = 0; i < SHA1_DIGEST_SIZE; i++) {
|
||||||
|
Print(L" %02x", hash[i]);
|
||||||
|
if (i % 10 == 9)
|
||||||
|
Print(L"\n ");
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
Print(L"SHA256 hash:\n ");
|
Print(L"SHA256 hash:\n ");
|
||||||
for (i = 0; i < SHA256_DIGEST_SIZE; i++) {
|
for (i = 0; i < SHA256_DIGEST_SIZE; i++) {
|
||||||
@ -326,19 +350,7 @@ static void show_mok_info (void *Mok, UINTN MokSize)
|
|||||||
}
|
}
|
||||||
Print(L"\n");
|
Print(L"\n");
|
||||||
}
|
}
|
||||||
efi_status = get_sha1sum(Mok, MokSize, hash);
|
|
||||||
|
|
||||||
if (efi_status != EFI_SUCCESS) {
|
|
||||||
Print(L"Failed to compute MOK fingerprint\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Print(L" Fingerprint (SHA1):\n ");
|
|
||||||
for (i = 0; i < SHA1_DIGEST_SIZE; i++) {
|
|
||||||
Print(L" %02x", hash[i]);
|
|
||||||
if (i % 10 == 9)
|
|
||||||
Print(L"\n ");
|
|
||||||
}
|
|
||||||
Print(L"\n");
|
Print(L"\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -403,7 +415,7 @@ static UINT8 list_keys (void *MokNew, UINTN MokNewSize)
|
|||||||
Print(L"Doesn't look like a key or hash\n");
|
Print(L"Doesn't look like a key or hash\n");
|
||||||
dbsize -= CertList->SignatureListSize;
|
dbsize -= CertList->SignatureListSize;
|
||||||
CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList +
|
CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList +
|
||||||
CertList->SignatureSize);
|
CertList->SignatureListSize);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -412,14 +424,14 @@ static UINT8 list_keys (void *MokNew, UINTN MokNewSize)
|
|||||||
Print(L"Doesn't look like a valid hash\n");
|
Print(L"Doesn't look like a valid hash\n");
|
||||||
dbsize -= CertList->SignatureListSize;
|
dbsize -= CertList->SignatureListSize;
|
||||||
CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList +
|
CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList +
|
||||||
CertList->SignatureSize);
|
CertList->SignatureListSize);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
MokNum++;
|
MokNum++;
|
||||||
dbsize -= CertList->SignatureListSize;
|
dbsize -= CertList->SignatureListSize;
|
||||||
CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList +
|
CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList +
|
||||||
CertList->SignatureSize);
|
CertList->SignatureListSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
keys = build_mok_list(MokNum, MokNew, MokNewSize);
|
keys = build_mok_list(MokNum, MokNew, MokNewSize);
|
||||||
@ -604,8 +616,7 @@ static EFI_STATUS store_keys (void *MokNew, UINTN MokNewSize, int authenticate)
|
|||||||
efi_status = uefi_call_wrapper(RT->SetVariable, 5, L"MokList",
|
efi_status = uefi_call_wrapper(RT->SetVariable, 5, L"MokList",
|
||||||
&shim_lock_guid,
|
&shim_lock_guid,
|
||||||
EFI_VARIABLE_NON_VOLATILE
|
EFI_VARIABLE_NON_VOLATILE
|
||||||
| EFI_VARIABLE_BOOTSERVICE_ACCESS
|
| EFI_VARIABLE_BOOTSERVICE_ACCESS,
|
||||||
| EFI_VARIABLE_APPEND_WRITE,
|
|
||||||
0, NULL);
|
0, NULL);
|
||||||
} else {
|
} else {
|
||||||
/* Write new MOK */
|
/* Write new MOK */
|
||||||
@ -653,7 +664,9 @@ static UINTN mok_enrollment_prompt (void *MokNew, UINTN MokNewSize, int auth) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static INTN mok_enrollment_prompt_callback (void *MokNew, void *data2,
|
static INTN mok_enrollment_prompt_callback (void *MokNew, void *data2,
|
||||||
void *data3) {
|
void *data3)
|
||||||
|
{
|
||||||
|
uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut);
|
||||||
return mok_enrollment_prompt(MokNew, (UINTN)data2, TRUE);
|
return mok_enrollment_prompt(MokNew, (UINTN)data2, TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -678,7 +691,203 @@ static INTN mok_deletion_prompt (void *MokNew, void *data2, void *data3) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static UINTN draw_menu (struct menu_item *items, UINTN count) {
|
static INTN mok_sb_prompt (void *MokSB, void *data2, void *data3) {
|
||||||
|
EFI_GUID shim_lock_guid = SHIM_LOCK_GUID;
|
||||||
|
EFI_STATUS efi_status;
|
||||||
|
UINTN MokSBSize = (UINTN)data2;
|
||||||
|
MokSBvar *var = MokSB;
|
||||||
|
CHAR16 pass1, pass2, pass3;
|
||||||
|
UINT8 fail_count = 0;
|
||||||
|
UINT32 length;
|
||||||
|
CHAR16 line[1];
|
||||||
|
UINT8 sbval = 1;
|
||||||
|
UINT8 pos1, pos2, pos3;
|
||||||
|
|
||||||
|
if (MokSBSize != sizeof(MokSBvar)) {
|
||||||
|
Print(L"Invalid MokSB variable contents\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut);
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
Print(L"Enter password character %d: ", pos1 + 1);
|
||||||
|
get_line(&length, &pass1, 1, 0);
|
||||||
|
|
||||||
|
Print(L"Enter password character %d: ", pos2 + 1);
|
||||||
|
get_line(&length, &pass2, 1, 0);
|
||||||
|
|
||||||
|
Print(L"Enter password character %d: ", pos3 + 1);
|
||||||
|
get_line(&length, &pass3, 1, 0);
|
||||||
|
|
||||||
|
if (pass1 != var->Password[pos1] ||
|
||||||
|
pass2 != var->Password[pos2] ||
|
||||||
|
pass3 != var->Password[pos3]) {
|
||||||
|
Print(L"Invalid character\n");
|
||||||
|
fail_count++;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fail_count >= 3) {
|
||||||
|
Print(L"Password limit reached\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (var->MokSBState == 0) {
|
||||||
|
Print(L"Disable Secure Boot? (y/n): ");
|
||||||
|
} else {
|
||||||
|
Print(L"Enable Secure Boot? (y/n): ");
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
get_line (&length, line, 1, 1);
|
||||||
|
|
||||||
|
if (line[0] == 'Y' || line[0] == 'y') {
|
||||||
|
if (var->MokSBState == 0) {
|
||||||
|
efi_status = uefi_call_wrapper(RT->SetVariable,
|
||||||
|
5, L"MokSBState",
|
||||||
|
&shim_lock_guid,
|
||||||
|
EFI_VARIABLE_NON_VOLATILE |
|
||||||
|
EFI_VARIABLE_BOOTSERVICE_ACCESS,
|
||||||
|
1, &sbval);
|
||||||
|
if (efi_status != EFI_SUCCESS) {
|
||||||
|
Print(L"Failed to set Secure Boot state\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
LibDeleteVariable(L"MokSBState",
|
||||||
|
&shim_lock_guid);
|
||||||
|
}
|
||||||
|
|
||||||
|
LibDeleteVariable(L"MokSB", &shim_lock_guid);
|
||||||
|
|
||||||
|
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 -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut);
|
||||||
|
|
||||||
|
SetMem(hash, SHA256_DIGEST_SIZE, 0);
|
||||||
|
|
||||||
|
if (CompareMem(MokPW, hash, SHA256_DIGEST_SIZE) == 0) {
|
||||||
|
Print(L"Clear MOK password? (y/n): ");
|
||||||
|
|
||||||
|
do {
|
||||||
|
get_line (&length, line, 1, 1);
|
||||||
|
|
||||||
|
if (line[0] == 'Y' || line[0] == 'y') {
|
||||||
|
LibDeleteVariable(L"MokPWStore", &shim_lock_guid);
|
||||||
|
LibDeleteVariable(L"MokPW", &shim_lock_guid);
|
||||||
|
}
|
||||||
|
} while (line[0] != 'N' && line[0] != 'n');
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (fail_count < 3) {
|
||||||
|
Print(L"Confirm MOK passphrase: ");
|
||||||
|
get_line(&length, password, PASSWORD_MAX, 0);
|
||||||
|
|
||||||
|
if ((length < PASSWORD_MIN) || (length > PASSWORD_MAX)) {
|
||||||
|
Print(L"Invalid password length\n");
|
||||||
|
fail_count++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
efi_status = compute_pw_hash(NULL, 0, password, length, hash);
|
||||||
|
|
||||||
|
if (efi_status != EFI_SUCCESS) {
|
||||||
|
Print(L"Unable to generate password hash\n");
|
||||||
|
fail_count++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CompareMem(MokPW, hash, SHA256_DIGEST_SIZE) != 0) {
|
||||||
|
Print(L"Password doesn't match\n");
|
||||||
|
fail_count++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fail_count >= 3) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
LibDeleteVariable(L"MokPW", &shim_lock_guid);
|
||||||
|
|
||||||
|
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,
|
||||||
|
UINTN count) {
|
||||||
UINTN i;
|
UINTN i;
|
||||||
|
|
||||||
uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut);
|
uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut);
|
||||||
@ -688,6 +897,9 @@ static UINTN draw_menu (struct menu_item *items, UINTN count) {
|
|||||||
|
|
||||||
Print(L"%s UEFI key management\n\n", SHIM_VENDOR);
|
Print(L"%s UEFI key management\n\n", SHIM_VENDOR);
|
||||||
|
|
||||||
|
if (header)
|
||||||
|
Print(L"%s", header);
|
||||||
|
|
||||||
for (i = 0; i < count; i++) {
|
for (i = 0; i < count; i++) {
|
||||||
uefi_call_wrapper(ST->ConOut->SetAttribute, 2, ST->ConOut,
|
uefi_call_wrapper(ST->ConOut->SetAttribute, 2, ST->ConOut,
|
||||||
items[i].colour | EFI_BACKGROUND_BLACK);
|
items[i].colour | EFI_BACKGROUND_BLACK);
|
||||||
@ -697,7 +909,7 @@ static UINTN draw_menu (struct menu_item *items, UINTN count) {
|
|||||||
uefi_call_wrapper(ST->ConOut->SetCursorPosition, 3, ST->ConOut, 0, 0);
|
uefi_call_wrapper(ST->ConOut->SetCursorPosition, 3, ST->ConOut, 0, 0);
|
||||||
uefi_call_wrapper(ST->ConOut->EnableCursor, 2, ST->ConOut, TRUE);
|
uefi_call_wrapper(ST->ConOut->EnableCursor, 2, ST->ConOut, TRUE);
|
||||||
|
|
||||||
return 2;
|
return 2 + lines;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void free_menu (struct menu_item *items, UINTN count) {
|
static void free_menu (struct menu_item *items, UINTN count) {
|
||||||
@ -711,31 +923,42 @@ static void free_menu (struct menu_item *items, UINTN count) {
|
|||||||
FreePool(items);
|
FreePool(items);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void run_menu (struct menu_item *items, UINTN count, UINTN timeout) {
|
static void update_time (UINTN position, UINTN timeout)
|
||||||
|
{
|
||||||
|
uefi_call_wrapper(ST->ConOut->SetCursorPosition, 3, ST->ConOut, 0,
|
||||||
|
position);
|
||||||
|
|
||||||
|
uefi_call_wrapper(ST->ConOut->SetAttribute, 2, ST->ConOut,
|
||||||
|
EFI_BLACK | EFI_BACKGROUND_BLACK);
|
||||||
|
|
||||||
|
Print(L" ", timeout);
|
||||||
|
|
||||||
|
uefi_call_wrapper(ST->ConOut->SetCursorPosition, 3, ST->ConOut, 0,
|
||||||
|
position);
|
||||||
|
|
||||||
|
uefi_call_wrapper(ST->ConOut->SetAttribute, 2, ST->ConOut,
|
||||||
|
EFI_WHITE | EFI_BACKGROUND_BLACK);
|
||||||
|
|
||||||
|
if (timeout > 1)
|
||||||
|
Print(L"Booting in %d seconds\n", timeout);
|
||||||
|
else if (timeout)
|
||||||
|
Print(L"Booting in %d second\n", timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void run_menu (CHAR16 *header, UINTN lines, struct menu_item *items,
|
||||||
|
UINTN count, UINTN timeout) {
|
||||||
UINTN index, pos = 0, wait = 0, offset;
|
UINTN index, pos = 0, wait = 0, offset;
|
||||||
EFI_INPUT_KEY key;
|
EFI_INPUT_KEY key;
|
||||||
EFI_STATUS status;
|
EFI_STATUS status;
|
||||||
|
INTN ret;
|
||||||
|
|
||||||
if (timeout)
|
if (timeout)
|
||||||
wait = 10000000;
|
wait = 10000000;
|
||||||
|
|
||||||
|
offset = draw_menu (header, lines, items, count);
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut);
|
update_time(count + offset + 1, timeout);
|
||||||
|
|
||||||
offset = draw_menu (items, count);
|
|
||||||
|
|
||||||
uefi_call_wrapper(ST->ConOut->SetAttribute, 2,
|
|
||||||
ST->ConOut,
|
|
||||||
EFI_WHITE | EFI_BACKGROUND_BLACK);
|
|
||||||
|
|
||||||
if (timeout) {
|
|
||||||
uefi_call_wrapper(ST->ConOut->SetCursorPosition, 3,
|
|
||||||
ST->ConOut, 0, count + 1 + offset);
|
|
||||||
if (timeout > 1)
|
|
||||||
Print(L"Booting in %d seconds\n", timeout);
|
|
||||||
else
|
|
||||||
Print(L"Booting in %d second\n", timeout);
|
|
||||||
}
|
|
||||||
|
|
||||||
uefi_call_wrapper(ST->ConOut->SetCursorPosition, 3, ST->ConOut,
|
uefi_call_wrapper(ST->ConOut->SetCursorPosition, 3, ST->ConOut,
|
||||||
0, pos + offset);
|
0, pos + offset);
|
||||||
@ -781,9 +1004,14 @@ static void run_menu (struct menu_item *items, UINTN count, UINTN timeout) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
items[pos].callback(items[pos].data, items[pos].data2,
|
ret = items[pos].callback(items[pos].data,
|
||||||
items[pos].data3);
|
items[pos].data2,
|
||||||
draw_menu (items, count);
|
items[pos].data3);
|
||||||
|
if (ret < 0) {
|
||||||
|
Print(L"Press a key to continue\n");
|
||||||
|
Pause();
|
||||||
|
}
|
||||||
|
draw_menu (header, lines, items, count);
|
||||||
pos = 0;
|
pos = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -937,6 +1165,7 @@ static INTN directory_callback (void *data, void *data2, void *data3) {
|
|||||||
EFI_FILE *dir;
|
EFI_FILE *dir;
|
||||||
CHAR16 *filename = data;
|
CHAR16 *filename = data;
|
||||||
EFI_FILE *root = data2;
|
EFI_FILE *root = data2;
|
||||||
|
BOOLEAN hash = !!data3;
|
||||||
|
|
||||||
status = uefi_call_wrapper(root->Open, 5, root, &dir, filename,
|
status = uefi_call_wrapper(root->Open, 5, root, &dir, filename,
|
||||||
EFI_FILE_MODE_READ, 0);
|
EFI_FILE_MODE_READ, 0);
|
||||||
@ -1023,7 +1252,10 @@ static INTN directory_callback (void *data, void *data2, void *data3) {
|
|||||||
buffer = NULL;
|
buffer = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
run_menu(dircontent, dircount, 0);
|
if (hash)
|
||||||
|
run_menu(HASH_STRING, 2, dircontent, dircount, 0);
|
||||||
|
else
|
||||||
|
run_menu(CERT_STRING, 2, dircontent, dircount, 0);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -1035,6 +1267,7 @@ static INTN filesystem_callback (void *data, void *data2, void *data3) {
|
|||||||
UINTN dircount = 0, i = 0;
|
UINTN dircount = 0, i = 0;
|
||||||
struct menu_item *dircontent;
|
struct menu_item *dircontent;
|
||||||
EFI_FILE *root = data;
|
EFI_FILE *root = data;
|
||||||
|
BOOLEAN hash = !!data3;
|
||||||
|
|
||||||
uefi_call_wrapper(root->SetPosition, 2, root, 0);
|
uefi_call_wrapper(root->SetPosition, 2, root, 0);
|
||||||
|
|
||||||
@ -1117,7 +1350,10 @@ static INTN filesystem_callback (void *data, void *data2, void *data3) {
|
|||||||
buffersize = 0;
|
buffersize = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
run_menu(dircontent, dircount, 0);
|
if (hash)
|
||||||
|
run_menu(HASH_STRING, 2, dircontent, dircount, 0);
|
||||||
|
else
|
||||||
|
run_menu(CERT_STRING, 2, dircontent, dircount, 0);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -1126,8 +1362,9 @@ static INTN find_fs (void *data, void *data2, void *data3) {
|
|||||||
EFI_GUID fs_guid = SIMPLE_FILE_SYSTEM_PROTOCOL;
|
EFI_GUID fs_guid = SIMPLE_FILE_SYSTEM_PROTOCOL;
|
||||||
UINTN count, i;
|
UINTN count, i;
|
||||||
UINTN OldSize, NewSize;
|
UINTN OldSize, NewSize;
|
||||||
EFI_HANDLE **filesystem_handles;
|
EFI_HANDLE *filesystem_handles = NULL;
|
||||||
struct menu_item *filesystems;
|
struct menu_item *filesystems;
|
||||||
|
BOOLEAN hash = !!data3;
|
||||||
|
|
||||||
uefi_call_wrapper(BS->LocateHandleBuffer, 5, ByProtocol, &fs_guid,
|
uefi_call_wrapper(BS->LocateHandleBuffer, 5, ByProtocol, &fs_guid,
|
||||||
NULL, &count, &filesystem_handles);
|
NULL, &count, &filesystem_handles);
|
||||||
@ -1146,7 +1383,7 @@ static INTN find_fs (void *data, void *data2, void *data3) {
|
|||||||
filesystems[0].colour = EFI_YELLOW;
|
filesystems[0].colour = EFI_YELLOW;
|
||||||
|
|
||||||
for (i=1; i<count; i++) {
|
for (i=1; i<count; i++) {
|
||||||
EFI_HANDLE *fs = filesystem_handles[i-1];
|
EFI_HANDLE fs = filesystem_handles[i-1];
|
||||||
EFI_FILE_IO_INTERFACE *fs_interface;
|
EFI_FILE_IO_INTERFACE *fs_interface;
|
||||||
EFI_DEVICE_PATH *path;
|
EFI_DEVICE_PATH *path;
|
||||||
EFI_FILE *root;
|
EFI_FILE *root;
|
||||||
@ -1157,7 +1394,7 @@ static INTN find_fs (void *data, void *data2, void *data3) {
|
|||||||
EFI_GUID file_info_guid = EFI_FILE_INFO_ID;
|
EFI_GUID file_info_guid = EFI_FILE_INFO_ID;
|
||||||
|
|
||||||
status = uefi_call_wrapper(BS->HandleProtocol, 3, fs, &fs_guid,
|
status = uefi_call_wrapper(BS->HandleProtocol, 3, fs, &fs_guid,
|
||||||
&fs_interface);
|
(void **)&fs_interface);
|
||||||
|
|
||||||
if (status != EFI_SUCCESS || !fs_interface)
|
if (status != EFI_SUCCESS || !fs_interface)
|
||||||
continue;
|
continue;
|
||||||
@ -1208,23 +1445,90 @@ static INTN find_fs (void *data, void *data2, void *data3) {
|
|||||||
|
|
||||||
uefi_call_wrapper(BS->FreePool, 1, filesystem_handles);
|
uefi_call_wrapper(BS->FreePool, 1, filesystem_handles);
|
||||||
|
|
||||||
run_menu(filesystems, count, 0);
|
if (hash)
|
||||||
|
run_menu(HASH_STRING, 2, filesystems, count, 0);
|
||||||
|
else
|
||||||
|
run_menu(CERT_STRING, 2, filesystems, count, 0);
|
||||||
|
|
||||||
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;
|
||||||
|
|
||||||
|
uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut);
|
||||||
|
|
||||||
|
while (fail_count < 3) {
|
||||||
|
Print(L"Enter MOK password: ");
|
||||||
|
get_line(&length, password, PASSWORD_MAX, 0);
|
||||||
|
|
||||||
|
if (length < PASSWORD_MIN || length > PASSWORD_MAX) {
|
||||||
|
Print(L"Invalid password length\n");
|
||||||
|
fail_count++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
efi_status = compute_pw_hash(NULL, 0, password, length, hash);
|
||||||
|
|
||||||
|
if (efi_status != EFI_SUCCESS) {
|
||||||
|
Print(L"Unable to generate password hash\n");
|
||||||
|
fail_count++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CompareMem(pwhash, hash, SHA256_DIGEST_SIZE) != 0) {
|
||||||
|
Print(L"Password doesn't match\n");
|
||||||
|
fail_count++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
UINTN MokNewSize, void *MokSB,
|
||||||
|
UINTN MokSBSize, void *MokPW, UINTN MokPWSize)
|
||||||
{
|
{
|
||||||
struct menu_item *menu_item;
|
struct menu_item *menu_item;
|
||||||
UINT32 MokAuth = 0;
|
UINT32 MokAuth = 0;
|
||||||
UINTN menucount = 0;
|
UINTN menucount = 3, i = 0;
|
||||||
EFI_STATUS efi_status;
|
EFI_STATUS efi_status;
|
||||||
EFI_GUID shim_lock_guid = SHIM_LOCK_GUID;
|
EFI_GUID shim_lock_guid = SHIM_LOCK_GUID;
|
||||||
UINT8 auth[SHA256_DIGEST_SIZE];
|
UINT8 auth[SHA256_DIGEST_SIZE];
|
||||||
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);
|
||||||
@ -1233,49 +1537,73 @@ static EFI_STATUS enter_mok_menu(EFI_HANDLE image_handle, void *MokNew,
|
|||||||
MokAuth = 1;
|
MokAuth = 1;
|
||||||
|
|
||||||
if (MokNew || MokAuth)
|
if (MokNew || MokAuth)
|
||||||
menu_item = AllocateZeroPool(sizeof(struct menu_item) * 4);
|
menucount++;
|
||||||
else
|
|
||||||
menu_item = AllocateZeroPool(sizeof(struct menu_item) * 3);
|
if (MokSB)
|
||||||
|
menucount++;
|
||||||
|
|
||||||
|
if (MokPW)
|
||||||
|
menucount++;
|
||||||
|
|
||||||
|
menu_item = AllocateZeroPool(sizeof(struct menu_item) * menucount);
|
||||||
|
|
||||||
if (!menu_item)
|
if (!menu_item)
|
||||||
return EFI_OUT_OF_RESOURCES;
|
return EFI_OUT_OF_RESOURCES;
|
||||||
|
|
||||||
menu_item[0].text = StrDuplicate(L"Continue boot");
|
menu_item[i].text = StrDuplicate(L"Continue boot");
|
||||||
menu_item[0].colour = EFI_WHITE;
|
menu_item[i].colour = EFI_WHITE;
|
||||||
menu_item[0].callback = NULL;
|
menu_item[i].callback = NULL;
|
||||||
|
|
||||||
menucount++;
|
i++;
|
||||||
|
|
||||||
if (MokNew || MokAuth) {
|
if (MokNew || MokAuth) {
|
||||||
if (!MokNew) {
|
if (!MokNew) {
|
||||||
menu_item[1].text = StrDuplicate(L"Delete MOK");
|
menu_item[i].text = StrDuplicate(L"Delete MOK");
|
||||||
menu_item[1].colour = EFI_WHITE;
|
menu_item[i].colour = EFI_WHITE;
|
||||||
menu_item[1].callback = mok_deletion_prompt;
|
menu_item[i].callback = mok_deletion_prompt;
|
||||||
} else {
|
} else {
|
||||||
menu_item[1].text = StrDuplicate(L"Enroll MOK");
|
menu_item[i].text = StrDuplicate(L"Enroll MOK");
|
||||||
menu_item[1].colour = EFI_WHITE;
|
menu_item[i].colour = EFI_WHITE;
|
||||||
menu_item[1].data = MokNew;
|
menu_item[i].data = MokNew;
|
||||||
menu_item[1].data2 = (void *)MokNewSize;
|
menu_item[i].data2 = (void *)MokNewSize;
|
||||||
menu_item[1].callback = mok_enrollment_prompt_callback;
|
menu_item[i].callback = mok_enrollment_prompt_callback;
|
||||||
}
|
}
|
||||||
menucount++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
menu_item[menucount].text = StrDuplicate(L"Enroll key from disk");
|
if (MokSB) {
|
||||||
menu_item[menucount].colour = EFI_WHITE;
|
menu_item[i].text = StrDuplicate(L"Change Secure Boot state");
|
||||||
menu_item[menucount].callback = find_fs;
|
menu_item[i].colour = EFI_WHITE;
|
||||||
menu_item[menucount].data3 = (void *)FALSE;
|
menu_item[i].callback = mok_sb_prompt;
|
||||||
|
menu_item[i].data = MokSB;
|
||||||
|
menu_item[i].data2 = (void *)MokSBSize;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
menucount++;
|
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[menucount].text = StrDuplicate(L"Enroll hash from disk");
|
menu_item[i].text = StrDuplicate(L"Enroll key from disk");
|
||||||
menu_item[menucount].colour = EFI_WHITE;
|
menu_item[i].colour = EFI_WHITE;
|
||||||
menu_item[menucount].callback = find_fs;
|
menu_item[i].callback = find_fs;
|
||||||
menu_item[menucount].data3 = (void *)TRUE;
|
menu_item[i].data3 = (void *)FALSE;
|
||||||
|
|
||||||
menucount++;
|
i++;
|
||||||
|
|
||||||
run_menu(menu_item, menucount, 10);
|
menu_item[i].text = StrDuplicate(L"Enroll hash from disk");
|
||||||
|
menu_item[i].colour = EFI_WHITE;
|
||||||
|
menu_item[i].callback = find_fs;
|
||||||
|
menu_item[i].data3 = (void *)TRUE;
|
||||||
|
|
||||||
|
i++;
|
||||||
|
|
||||||
|
run_menu(NULL, 0, menu_item, menucount, 10);
|
||||||
|
|
||||||
uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut);
|
uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut);
|
||||||
|
|
||||||
@ -1285,12 +1613,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;
|
UINTN MokNewSize = 0, MokSBSize = 0, MokPWSize = 0;
|
||||||
void *MokNew = NULL;
|
void *MokNew = NULL;
|
||||||
|
void *MokSB = NULL;
|
||||||
|
void *MokPW = NULL;
|
||||||
|
|
||||||
MokNew = LibGetVariableAndSize(L"MokNew", &shim_lock_guid, &MokNewSize);
|
MokNew = LibGetVariableAndSize(L"MokNew", &shim_lock_guid, &MokNewSize);
|
||||||
|
|
||||||
enter_mok_menu(image_handle, MokNew, MokNewSize);
|
MokSB = LibGetVariableAndSize(L"MokSB", &shim_lock_guid, &MokSBSize);
|
||||||
|
|
||||||
|
MokPW = LibGetVariableAndSize(L"MokPW", &shim_lock_guid, &MokPWSize);
|
||||||
|
|
||||||
|
enter_mok_menu(image_handle, MokNew, MokNewSize, MokSB, MokSBSize,
|
||||||
|
MokPW, MokPWSize);
|
||||||
|
|
||||||
if (MokNew) {
|
if (MokNew) {
|
||||||
if (LibDeleteVariable(L"MokNew", &shim_lock_guid) != EFI_SUCCESS) {
|
if (LibDeleteVariable(L"MokNew", &shim_lock_guid) != EFI_SUCCESS) {
|
||||||
@ -1298,17 +1633,59 @@ static EFI_STATUS check_mok_request(EFI_HANDLE image_handle)
|
|||||||
}
|
}
|
||||||
FreePool (MokNew);
|
FreePool (MokNew);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (MokSB) {
|
||||||
|
if (LibDeleteVariable(L"MokSB", &shim_lock_guid) != EFI_SUCCESS) {
|
||||||
|
Print(L"Failed to delete MokSB\n");
|
||||||
|
}
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static EFI_STATUS setup_rand (void)
|
||||||
|
{
|
||||||
|
EFI_TIME time;
|
||||||
|
EFI_STATUS efi_status;
|
||||||
|
UINT64 seed;
|
||||||
|
BOOLEAN status;
|
||||||
|
|
||||||
|
efi_status = uefi_call_wrapper(RT->GetTime, 2, &time, NULL);
|
||||||
|
|
||||||
|
if (efi_status != EFI_SUCCESS)
|
||||||
|
return efi_status;
|
||||||
|
|
||||||
|
seed = ((UINT64)time.Year << 48) | ((UINT64)time.Month << 40) |
|
||||||
|
((UINT64)time.Day << 32) | ((UINT64)time.Hour << 24) |
|
||||||
|
((UINT64)time.Minute << 16) | ((UINT64)time.Second << 8) |
|
||||||
|
((UINT64)time.Daylight);
|
||||||
|
|
||||||
|
status = RandomSeed((UINT8 *)&seed, sizeof(seed));
|
||||||
|
|
||||||
|
if (!status)
|
||||||
|
return EFI_ABORTED;
|
||||||
|
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
EFI_STATUS efi_main (EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *systab)
|
EFI_STATUS efi_main (EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *systab)
|
||||||
{
|
{
|
||||||
EFI_STATUS efi_status;
|
EFI_STATUS efi_status;
|
||||||
|
|
||||||
InitializeLib(image_handle, systab);
|
InitializeLib(image_handle, systab);
|
||||||
|
|
||||||
|
setup_rand();
|
||||||
|
|
||||||
efi_status = check_mok_request(image_handle);
|
efi_status = check_mok_request(image_handle);
|
||||||
|
|
||||||
return efi_status;
|
return efi_status;
|
||||||
|
51
MokVars.txt
Normal file
51
MokVars.txt
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
Variables used by Shim and Mokmanager
|
||||||
|
|
||||||
|
Request variables:
|
||||||
|
|
||||||
|
MokPW: Set by MokUtil when setting a password. A SHA-256 hash of the
|
||||||
|
UCS-2 representation of the password. The user will be asked to
|
||||||
|
re-enter the password to confirm. If the hash of the entered password
|
||||||
|
matches the contents of MokPW, the user will be prompted to copy MokPW
|
||||||
|
into MokPWState. BS,RT,NV
|
||||||
|
|
||||||
|
MokSB: Set by MokUtil when requesting a change in state of signature
|
||||||
|
validation. A packed structure as follows:
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
UINT32 MokSBState;
|
||||||
|
UINT32 PWLen;
|
||||||
|
CHAR16 Password[PASSWORD_MAX];
|
||||||
|
} __attribute__ ((packed)) MokSBvar;
|
||||||
|
|
||||||
|
If MokSBState is 0, the user will be prompted to disable signature
|
||||||
|
validation. Otherwise, the user will be prompted to enable it. PWLen
|
||||||
|
is the length of the password, in characters. Password is a UCS-2
|
||||||
|
representation of the password. The user will be prompted to enter
|
||||||
|
three randomly chosen characters from the password. If successful,
|
||||||
|
they will then be prompted to change the signature validation
|
||||||
|
according to MokSBState. BS,RT,NV
|
||||||
|
|
||||||
|
MokNew: Set by MokUtil when requesting the addition or removal of keys
|
||||||
|
from MokList. Is an EFI_SIGNATURE_LIST as described in the UEFI
|
||||||
|
specification. BS,RT,NV
|
||||||
|
|
||||||
|
MokAuth: A hash dependent upon the contents of MokNew and the sealing
|
||||||
|
password. The user's password in UCS-2 form should be appended to the
|
||||||
|
contents of MokNew and a SHA-256 hash generated and stored in MokAuth.
|
||||||
|
The hash will be regenerated by MokManager after the user is requested
|
||||||
|
to enter their password to confirm enrolment of the keys. If the hash
|
||||||
|
matches MokAuth, the user will be prompted to enrol the keys. BS,RT,NV
|
||||||
|
|
||||||
|
State variables:
|
||||||
|
|
||||||
|
MokList: A list of whitelisted keys and hashes. An EFI_SIGNATURE_LIST
|
||||||
|
as described in the UEFI specification. BS,NV
|
||||||
|
|
||||||
|
MokListRT: A copy of MokList made available to the kernel at runtime. RT
|
||||||
|
|
||||||
|
MokSBState: An 8-bit unsigned integer. If 1, shim will switch to
|
||||||
|
insecure mode. BS,NV
|
||||||
|
|
||||||
|
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.
|
32
dbx.S
Normal file
32
dbx.S
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
#if defined(VENDOR_DBX_FILE)
|
||||||
|
.globl vendor_dbx_size
|
||||||
|
.data
|
||||||
|
.align 1
|
||||||
|
.type vendor_dbx_size, @object
|
||||||
|
.size vendor_dbx_size, 4
|
||||||
|
vendor_dbx_size:
|
||||||
|
.long .L0 - vendor_dbx
|
||||||
|
.globl vendor_dbx
|
||||||
|
.data
|
||||||
|
.align 1
|
||||||
|
.type vendor_dbx, @object
|
||||||
|
.size vendor_dbx_size, vendor_dbx_size-vendor_dbx
|
||||||
|
vendor_dbx:
|
||||||
|
.incbin VENDOR_DBX_FILE
|
||||||
|
.L0:
|
||||||
|
#else
|
||||||
|
.globl vendor_dbx
|
||||||
|
.bss
|
||||||
|
.type vendor_dbx, @object
|
||||||
|
.size vendor_dbx, 1
|
||||||
|
vendor_dbx:
|
||||||
|
.zero 1
|
||||||
|
|
||||||
|
.globl vendor_dbx_size
|
||||||
|
.data
|
||||||
|
.align 4
|
||||||
|
.type vendor_dbx_size, @object
|
||||||
|
.size vendor_dbx_size, 4
|
||||||
|
vendor_dbx_size:
|
||||||
|
.long 0
|
||||||
|
#endif
|
229
shim.c
229
shim.c
@ -52,9 +52,13 @@ static EFI_STATUS (EFIAPI *entry_point) (EFI_HANDLE image_handle, EFI_SYSTEM_TAB
|
|||||||
*/
|
*/
|
||||||
extern UINT8 vendor_cert[];
|
extern UINT8 vendor_cert[];
|
||||||
extern UINT32 vendor_cert_size;
|
extern UINT32 vendor_cert_size;
|
||||||
|
extern EFI_SIGNATURE_LIST *vendor_dbx;
|
||||||
|
extern UINT32 vendor_dbx_size;
|
||||||
|
|
||||||
#define EFI_IMAGE_SECURITY_DATABASE_GUID { 0xd719b2cb, 0x3d3a, 0x4596, { 0xa3, 0xbc, 0xda, 0xd0, 0x0e, 0x67, 0x65, 0x6f }}
|
#define EFI_IMAGE_SECURITY_DATABASE_GUID { 0xd719b2cb, 0x3d3a, 0x4596, { 0xa3, 0xbc, 0xda, 0xd0, 0x0e, 0x67, 0x65, 0x6f }}
|
||||||
|
|
||||||
|
static UINT8 insecure_mode;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
DATA_FOUND,
|
DATA_FOUND,
|
||||||
DATA_NOT_FOUND,
|
DATA_NOT_FOUND,
|
||||||
@ -79,8 +83,7 @@ static EFI_STATUS get_variable (CHAR16 *name, EFI_GUID guid, UINT32 *attributes,
|
|||||||
return efi_status;
|
return efi_status;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (allocate)
|
*buffer = AllocatePool(*size);
|
||||||
*buffer = AllocatePool(*size);
|
|
||||||
|
|
||||||
if (!*buffer) {
|
if (!*buffer) {
|
||||||
Print(L"Unable to allocate variable buffer\n");
|
Print(L"Unable to allocate variable buffer\n");
|
||||||
@ -208,26 +211,16 @@ static EFI_STATUS relocate_coff (PE_COFF_LOADER_IMAGE_CONTEXT *context,
|
|||||||
return EFI_SUCCESS;
|
return EFI_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static CHECK_STATUS check_db_cert(CHAR16 *dbname, EFI_GUID guid,
|
static CHECK_STATUS check_db_cert_in_ram(EFI_SIGNATURE_LIST *CertList,
|
||||||
WIN_CERTIFICATE_EFI_PKCS *data, UINT8 *hash)
|
UINTN dbsize,
|
||||||
|
WIN_CERTIFICATE_EFI_PKCS *data,
|
||||||
|
UINT8 *hash)
|
||||||
{
|
{
|
||||||
EFI_STATUS efi_status;
|
|
||||||
EFI_SIGNATURE_LIST *CertList;
|
|
||||||
EFI_SIGNATURE_DATA *Cert;
|
EFI_SIGNATURE_DATA *Cert;
|
||||||
UINTN dbsize = 0;
|
|
||||||
UINTN CertCount, Index;
|
UINTN CertCount, Index;
|
||||||
UINT32 attributes;
|
|
||||||
BOOLEAN IsFound = FALSE;
|
BOOLEAN IsFound = FALSE;
|
||||||
void *db;
|
|
||||||
EFI_GUID CertType = EfiCertX509Guid;
|
EFI_GUID CertType = EfiCertX509Guid;
|
||||||
|
|
||||||
efi_status = get_variable(dbname, guid, &attributes, &dbsize, &db);
|
|
||||||
|
|
||||||
if (efi_status != EFI_SUCCESS)
|
|
||||||
return VAR_NOT_FOUND;
|
|
||||||
|
|
||||||
CertList = db;
|
|
||||||
|
|
||||||
while ((dbsize > 0) && (dbsize >= CertList->SignatureListSize)) {
|
while ((dbsize > 0) && (dbsize >= CertList->SignatureListSize)) {
|
||||||
if (CompareGuid (&CertList->SignatureType, &CertType) == 0) {
|
if (CompareGuid (&CertList->SignatureType, &CertType) == 0) {
|
||||||
CertCount = (CertList->SignatureListSize - CertList->SignatureHeaderSize) / CertList->SignatureSize;
|
CertCount = (CertList->SignatureListSize - CertList->SignatureHeaderSize) / CertList->SignatureSize;
|
||||||
@ -240,43 +233,57 @@ static CHECK_STATUS check_db_cert(CHAR16 *dbname, EFI_GUID guid,
|
|||||||
hash, SHA256_DIGEST_SIZE);
|
hash, SHA256_DIGEST_SIZE);
|
||||||
if (IsFound)
|
if (IsFound)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) Cert + CertList->SignatureSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) Cert + CertList->SignatureSize);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (IsFound)
|
||||||
|
break;
|
||||||
|
|
||||||
dbsize -= CertList->SignatureListSize;
|
dbsize -= CertList->SignatureListSize;
|
||||||
CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);
|
CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
FreePool(db);
|
|
||||||
|
|
||||||
if (IsFound)
|
if (IsFound)
|
||||||
return DATA_FOUND;
|
return DATA_FOUND;
|
||||||
|
|
||||||
return DATA_NOT_FOUND;
|
return DATA_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
static CHECK_STATUS check_db_hash(CHAR16 *dbname, EFI_GUID guid, UINT8 *data,
|
static CHECK_STATUS check_db_cert(CHAR16 *dbname, EFI_GUID guid,
|
||||||
int SignatureSize, EFI_GUID CertType)
|
WIN_CERTIFICATE_EFI_PKCS *data, UINT8 *hash)
|
||||||
{
|
{
|
||||||
|
CHECK_STATUS rc;
|
||||||
EFI_STATUS efi_status;
|
EFI_STATUS efi_status;
|
||||||
EFI_SIGNATURE_LIST *CertList;
|
EFI_SIGNATURE_LIST *CertList;
|
||||||
EFI_SIGNATURE_DATA *Cert;
|
|
||||||
UINTN dbsize = 0;
|
UINTN dbsize = 0;
|
||||||
UINTN CertCount, Index;
|
|
||||||
UINT32 attributes;
|
UINT32 attributes;
|
||||||
BOOLEAN IsFound = FALSE;
|
|
||||||
void *db;
|
void *db;
|
||||||
|
|
||||||
efi_status = get_variable(dbname, guid, &attributes, &dbsize, &db);
|
efi_status = get_variable(dbname, guid, &attributes, &dbsize, &db);
|
||||||
|
|
||||||
if (efi_status != EFI_SUCCESS) {
|
if (efi_status != EFI_SUCCESS)
|
||||||
return VAR_NOT_FOUND;
|
return VAR_NOT_FOUND;
|
||||||
}
|
|
||||||
|
|
||||||
CertList = db;
|
CertList = db;
|
||||||
|
|
||||||
|
rc = check_db_cert_in_ram(CertList, dbsize, data, hash);
|
||||||
|
|
||||||
|
FreePool(db);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static CHECK_STATUS check_db_hash_in_ram(EFI_SIGNATURE_LIST *CertList,
|
||||||
|
UINTN dbsize, UINT8 *data,
|
||||||
|
int SignatureSize, EFI_GUID CertType)
|
||||||
|
{
|
||||||
|
EFI_SIGNATURE_DATA *Cert;
|
||||||
|
UINTN CertCount, Index;
|
||||||
|
BOOLEAN IsFound = FALSE;
|
||||||
|
|
||||||
while ((dbsize > 0) && (dbsize >= CertList->SignatureListSize)) {
|
while ((dbsize > 0) && (dbsize >= CertList->SignatureListSize)) {
|
||||||
CertCount = (CertList->SignatureListSize - CertList->SignatureHeaderSize) / CertList->SignatureSize;
|
CertCount = (CertList->SignatureListSize - CertList->SignatureHeaderSize) / CertList->SignatureSize;
|
||||||
Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);
|
Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);
|
||||||
@ -301,19 +308,53 @@ static CHECK_STATUS check_db_hash(CHAR16 *dbname, EFI_GUID guid, UINT8 *data,
|
|||||||
CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);
|
CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
FreePool(db);
|
|
||||||
|
|
||||||
if (IsFound)
|
if (IsFound)
|
||||||
return DATA_FOUND;
|
return DATA_FOUND;
|
||||||
|
|
||||||
return DATA_NOT_FOUND;
|
return DATA_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static CHECK_STATUS check_db_hash(CHAR16 *dbname, EFI_GUID guid, UINT8 *data,
|
||||||
|
int SignatureSize, EFI_GUID CertType)
|
||||||
|
{
|
||||||
|
EFI_STATUS efi_status;
|
||||||
|
EFI_SIGNATURE_LIST *CertList;
|
||||||
|
UINT32 attributes;
|
||||||
|
UINTN dbsize = 0;
|
||||||
|
void *db;
|
||||||
|
|
||||||
|
efi_status = get_variable(dbname, guid, &attributes, &dbsize, &db);
|
||||||
|
|
||||||
|
if (efi_status != EFI_SUCCESS) {
|
||||||
|
return VAR_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
CertList = db;
|
||||||
|
|
||||||
|
CHECK_STATUS rc = check_db_hash_in_ram(CertList, dbsize, data,
|
||||||
|
SignatureSize, CertType);
|
||||||
|
FreePool(db);
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
static EFI_STATUS check_blacklist (WIN_CERTIFICATE_EFI_PKCS *cert,
|
static EFI_STATUS check_blacklist (WIN_CERTIFICATE_EFI_PKCS *cert,
|
||||||
UINT8 *sha256hash, UINT8 *sha1hash)
|
UINT8 *sha256hash, UINT8 *sha1hash)
|
||||||
{
|
{
|
||||||
EFI_GUID secure_var = EFI_IMAGE_SECURITY_DATABASE_GUID;
|
EFI_GUID secure_var = EFI_IMAGE_SECURITY_DATABASE_GUID;
|
||||||
|
|
||||||
|
if (check_db_hash_in_ram(vendor_dbx, vendor_dbx_size, sha256hash,
|
||||||
|
SHA256_DIGEST_SIZE, EfiHashSha256Guid) ==
|
||||||
|
DATA_FOUND)
|
||||||
|
return EFI_ACCESS_DENIED;
|
||||||
|
if (check_db_hash_in_ram(vendor_dbx, vendor_dbx_size, sha1hash,
|
||||||
|
SHA1_DIGEST_SIZE, EfiHashSha1Guid) ==
|
||||||
|
DATA_FOUND)
|
||||||
|
return EFI_ACCESS_DENIED;
|
||||||
|
if (check_db_cert_in_ram(vendor_dbx, vendor_dbx_size, cert,
|
||||||
|
sha256hash) == DATA_FOUND)
|
||||||
|
return EFI_ACCESS_DENIED;
|
||||||
|
|
||||||
if (check_db_hash(L"dbx", secure_var, sha256hash, SHA256_DIGEST_SIZE,
|
if (check_db_hash(L"dbx", secure_var, sha256hash, SHA256_DIGEST_SIZE,
|
||||||
EfiHashSha256Guid) == DATA_FOUND)
|
EfiHashSha256Guid) == DATA_FOUND)
|
||||||
return EFI_ACCESS_DENIED;
|
return EFI_ACCESS_DENIED;
|
||||||
@ -361,6 +402,9 @@ static BOOLEAN secure_mode (void)
|
|||||||
UINT8 sb, setupmode;
|
UINT8 sb, setupmode;
|
||||||
UINT32 attributes;
|
UINT32 attributes;
|
||||||
|
|
||||||
|
if (insecure_mode)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
status = get_variable(L"SecureBoot", global_var, &attributes, &charsize,
|
status = get_variable(L"SecureBoot", global_var, &attributes, &charsize,
|
||||||
(void *)&sb);
|
(void *)&sb);
|
||||||
|
|
||||||
@ -505,7 +549,8 @@ static EFI_STATUS generate_hash (char *data, int datasize,
|
|||||||
|
|
||||||
if (!hashbase) {
|
if (!hashbase) {
|
||||||
Print(L"Malformed section header\n");
|
Print(L"Malformed section header\n");
|
||||||
return EFI_INVALID_PARAMETER;
|
status = EFI_INVALID_PARAMETER;
|
||||||
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(Sha256Update(sha256ctx, hashbase, hashsize)) ||
|
if (!(Sha256Update(sha256ctx, hashbase, hashsize)) ||
|
||||||
@ -585,6 +630,11 @@ static EFI_STATUS verify_buffer (char *data, int datasize,
|
|||||||
WIN_CERTIFICATE_EFI_PKCS *cert;
|
WIN_CERTIFICATE_EFI_PKCS *cert;
|
||||||
unsigned int size = datasize;
|
unsigned int size = datasize;
|
||||||
|
|
||||||
|
if (context->SecDir->Size == 0) {
|
||||||
|
Print(L"Empty security header\n");
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
cert = ImageAddress (data, size, context->SecDir->VirtualAddress);
|
cert = ImageAddress (data, size, context->SecDir->VirtualAddress);
|
||||||
|
|
||||||
if (!cert) {
|
if (!cert) {
|
||||||
@ -643,9 +693,19 @@ static EFI_STATUS read_header(void *data, unsigned int datasize,
|
|||||||
EFI_IMAGE_DOS_HEADER *DosHdr = data;
|
EFI_IMAGE_DOS_HEADER *DosHdr = data;
|
||||||
EFI_IMAGE_OPTIONAL_HEADER_UNION *PEHdr = data;
|
EFI_IMAGE_OPTIONAL_HEADER_UNION *PEHdr = data;
|
||||||
|
|
||||||
|
if (datasize < sizeof(EFI_IMAGE_DOS_HEADER)) {
|
||||||
|
Print(L"Invalid image\n");
|
||||||
|
return EFI_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE)
|
if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE)
|
||||||
PEHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)((char *)data + DosHdr->e_lfanew);
|
PEHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)((char *)data + DosHdr->e_lfanew);
|
||||||
|
|
||||||
|
if ((((UINT8 *)PEHdr - (UINT8 *)data) + sizeof(EFI_IMAGE_OPTIONAL_HEADER_UNION)) > datasize) {
|
||||||
|
Print(L"Invalid image\n");
|
||||||
|
return EFI_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
if (PEHdr->Te.Signature != EFI_IMAGE_NT_SIGNATURE) {
|
if (PEHdr->Te.Signature != EFI_IMAGE_NT_SIGNATURE) {
|
||||||
Print(L"Unsupported image type\n");
|
Print(L"Unsupported image type\n");
|
||||||
return EFI_UNSUPPORTED;
|
return EFI_UNSUPPORTED;
|
||||||
@ -672,13 +732,18 @@ static EFI_STATUS read_header(void *data, unsigned int datasize,
|
|||||||
context->FirstSection = (EFI_IMAGE_SECTION_HEADER *)((char *)PEHdr + PEHdr->Pe32.FileHeader.SizeOfOptionalHeader + sizeof(UINT32) + sizeof(EFI_IMAGE_FILE_HEADER));
|
context->FirstSection = (EFI_IMAGE_SECTION_HEADER *)((char *)PEHdr + PEHdr->Pe32.FileHeader.SizeOfOptionalHeader + sizeof(UINT32) + sizeof(EFI_IMAGE_FILE_HEADER));
|
||||||
context->SecDir = (EFI_IMAGE_DATA_DIRECTORY *) &PEHdr->Pe32Plus.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY];
|
context->SecDir = (EFI_IMAGE_DATA_DIRECTORY *) &PEHdr->Pe32Plus.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY];
|
||||||
|
|
||||||
if (context->SecDir->VirtualAddress >= datasize) {
|
if (context->ImageSize < context->SizeOfHeaders) {
|
||||||
Print(L"Malformed security header\n");
|
Print(L"Invalid image\n");
|
||||||
return EFI_INVALID_PARAMETER;
|
return EFI_UNSUPPORTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (context->SecDir->Size == 0) {
|
if (((UINT8 *)context->SecDir - (UINT8 *)data) > (datasize - sizeof(EFI_IMAGE_DATA_DIRECTORY))) {
|
||||||
Print(L"Empty security header\n");
|
Print(L"Invalid image\n");
|
||||||
|
return EFI_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (context->SecDir->VirtualAddress >= datasize) {
|
||||||
|
Print(L"Malformed security header\n");
|
||||||
return EFI_INVALID_PARAMETER;
|
return EFI_INVALID_PARAMETER;
|
||||||
}
|
}
|
||||||
return EFI_SUCCESS;
|
return EFI_SUCCESS;
|
||||||
@ -790,7 +855,7 @@ static EFI_STATUS generate_path(EFI_LOADED_IMAGE *li, CHAR16 *ImagePath,
|
|||||||
|
|
||||||
bootpath[i+1] = '\0';
|
bootpath[i+1] = '\0';
|
||||||
|
|
||||||
if (bootpath[i-i] == '\\')
|
if (i == 0 || bootpath[i-i] == '\\')
|
||||||
bootpath[i] = '\0';
|
bootpath[i] = '\0';
|
||||||
|
|
||||||
*PathName = AllocatePool(StrSize(bootpath) + StrSize(ImagePath));
|
*PathName = AllocatePool(StrSize(bootpath) + StrSize(ImagePath));
|
||||||
@ -829,7 +894,8 @@ static EFI_STATUS load_image (EFI_LOADED_IMAGE *li, void **data,
|
|||||||
device = li->DeviceHandle;
|
device = li->DeviceHandle;
|
||||||
|
|
||||||
efi_status = uefi_call_wrapper(BS->HandleProtocol, 3, device,
|
efi_status = uefi_call_wrapper(BS->HandleProtocol, 3, device,
|
||||||
&simple_file_system_protocol, &drive);
|
&simple_file_system_protocol,
|
||||||
|
(void **)&drive);
|
||||||
|
|
||||||
if (efi_status != EFI_SUCCESS) {
|
if (efi_status != EFI_SUCCESS) {
|
||||||
Print(L"Failed to find fs\n");
|
Print(L"Failed to find fs\n");
|
||||||
@ -863,6 +929,7 @@ static EFI_STATUS load_image (EFI_LOADED_IMAGE *li, void **data,
|
|||||||
&buffersize, fileinfo);
|
&buffersize, fileinfo);
|
||||||
|
|
||||||
if (efi_status == EFI_BUFFER_TOO_SMALL) {
|
if (efi_status == EFI_BUFFER_TOO_SMALL) {
|
||||||
|
FreePool(fileinfo);
|
||||||
fileinfo = AllocatePool(buffersize);
|
fileinfo = AllocatePool(buffersize);
|
||||||
if (!fileinfo) {
|
if (!fileinfo) {
|
||||||
Print(L"Unable to allocate file info buffer\n");
|
Print(L"Unable to allocate file info buffer\n");
|
||||||
@ -905,14 +972,15 @@ static EFI_STATUS load_image (EFI_LOADED_IMAGE *li, void **data,
|
|||||||
|
|
||||||
*datasize = buffersize;
|
*datasize = buffersize;
|
||||||
|
|
||||||
|
FreePool(fileinfo);
|
||||||
|
|
||||||
return EFI_SUCCESS;
|
return EFI_SUCCESS;
|
||||||
error:
|
error:
|
||||||
if (*data) {
|
if (*data) {
|
||||||
FreePool(*data);
|
FreePool(*data);
|
||||||
*data = NULL;
|
*data = NULL;
|
||||||
}
|
}
|
||||||
if (PathName)
|
|
||||||
FreePool(PathName);
|
|
||||||
if (fileinfo)
|
if (fileinfo)
|
||||||
FreePool(fileinfo);
|
FreePool(fileinfo);
|
||||||
return efi_status;
|
return efi_status;
|
||||||
@ -949,7 +1017,7 @@ EFI_STATUS start_image(EFI_HANDLE image_handle, CHAR16 *ImagePath)
|
|||||||
int datasize;
|
int datasize;
|
||||||
|
|
||||||
efi_status = uefi_call_wrapper(BS->HandleProtocol, 3, image_handle,
|
efi_status = uefi_call_wrapper(BS->HandleProtocol, 3, image_handle,
|
||||||
&loaded_image_protocol, &li);
|
&loaded_image_protocol, (void **)&li);
|
||||||
|
|
||||||
if (efi_status != EFI_SUCCESS) {
|
if (efi_status != EFI_SUCCESS) {
|
||||||
Print(L"Unable to init protocol\n");
|
Print(L"Unable to init protocol\n");
|
||||||
@ -996,10 +1064,16 @@ EFI_STATUS start_image(EFI_HANDLE image_handle, CHAR16 *ImagePath)
|
|||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
efi_status = uefi_call_wrapper(entry_point, 3, image_handle, systab);
|
efi_status = uefi_call_wrapper(entry_point, 2, image_handle, systab);
|
||||||
|
|
||||||
CopyMem(li, &li_bak, sizeof(li_bak));
|
CopyMem(li, &li_bak, sizeof(li_bak));
|
||||||
done:
|
done:
|
||||||
|
if (PathName)
|
||||||
|
FreePool(PathName);
|
||||||
|
|
||||||
|
if (data)
|
||||||
|
FreePool(data);
|
||||||
|
|
||||||
return efi_status;
|
return efi_status;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1048,35 +1122,71 @@ done:
|
|||||||
return efi_status;
|
return efi_status;
|
||||||
}
|
}
|
||||||
|
|
||||||
EFI_STATUS check_mok_request(EFI_HANDLE image_handle)
|
static BOOLEAN check_var(CHAR16 *varname)
|
||||||
{
|
{
|
||||||
EFI_GUID shim_lock_guid = SHIM_LOCK_GUID;
|
|
||||||
EFI_STATUS efi_status;
|
EFI_STATUS efi_status;
|
||||||
|
EFI_GUID shim_lock_guid = SHIM_LOCK_GUID;
|
||||||
UINTN size = sizeof(UINT32);
|
UINTN size = sizeof(UINT32);
|
||||||
UINT32 MokNew;
|
UINT32 MokVar;
|
||||||
UINT32 attributes;
|
UINT32 attributes;
|
||||||
|
|
||||||
if (!secure_mode())
|
efi_status = uefi_call_wrapper(RT->GetVariable, 5, varname,
|
||||||
return EFI_SUCCESS;
|
|
||||||
|
|
||||||
efi_status = uefi_call_wrapper(RT->GetVariable, 5, L"MokNew",
|
|
||||||
&shim_lock_guid, &attributes,
|
&shim_lock_guid, &attributes,
|
||||||
&size, (void *)&MokNew);
|
&size, (void *)&MokVar);
|
||||||
|
|
||||||
if (efi_status != EFI_SUCCESS && efi_status != EFI_BUFFER_TOO_SMALL)
|
if (efi_status == EFI_SUCCESS || efi_status == EFI_BUFFER_TOO_SMALL)
|
||||||
goto done;
|
return TRUE;
|
||||||
|
|
||||||
efi_status = start_image(image_handle, MOK_MANAGER);
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
if (efi_status != EFI_SUCCESS) {
|
EFI_STATUS check_mok_request(EFI_HANDLE image_handle)
|
||||||
Print(L"Failed to start MokManager\n");
|
{
|
||||||
goto done;
|
EFI_STATUS efi_status;
|
||||||
|
|
||||||
|
if (check_var(L"MokNew") || check_var(L"MokSB") ||
|
||||||
|
check_var(L"MokPW") || check_var(L"MokAuth")) {
|
||||||
|
efi_status = start_image(image_handle, MOK_MANAGER);
|
||||||
|
|
||||||
|
if (efi_status != EFI_SUCCESS) {
|
||||||
|
Print(L"Failed to start MokManager\n");
|
||||||
|
return efi_status;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
done:
|
return EFI_SUCCESS;
|
||||||
return efi_status;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static EFI_STATUS check_mok_sb (void)
|
||||||
|
{
|
||||||
|
EFI_GUID shim_lock_guid = SHIM_LOCK_GUID;
|
||||||
|
EFI_STATUS status = EFI_SUCCESS;
|
||||||
|
void *MokSBState = NULL;
|
||||||
|
UINTN MokSBStateSize = 0;
|
||||||
|
UINT32 attributes;
|
||||||
|
|
||||||
|
status = get_variable(L"MokSBState", shim_lock_guid, &attributes,
|
||||||
|
&MokSBStateSize, &MokSBState);
|
||||||
|
|
||||||
|
if (status != EFI_SUCCESS)
|
||||||
|
return EFI_ACCESS_DENIED;
|
||||||
|
|
||||||
|
if (attributes & EFI_VARIABLE_RUNTIME_ACCESS) {
|
||||||
|
Print(L"MokSBState is compromised! Clearing it\n");
|
||||||
|
if (LibDeleteVariable(L"MokSBState", &shim_lock_guid) != EFI_SUCCESS) {
|
||||||
|
Print(L"Failed to erase MokSBState\n");
|
||||||
|
}
|
||||||
|
status = EFI_ACCESS_DENIED;
|
||||||
|
} else {
|
||||||
|
if (*(UINT8 *)MokSBState == 1) {
|
||||||
|
insecure_mode = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
EFI_STATUS efi_main (EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *passed_systab)
|
EFI_STATUS efi_main (EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *passed_systab)
|
||||||
{
|
{
|
||||||
EFI_GUID shim_lock_guid = SHIM_LOCK_GUID;
|
EFI_GUID shim_lock_guid = SHIM_LOCK_GUID;
|
||||||
@ -1092,6 +1202,13 @@ EFI_STATUS efi_main (EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *passed_systab)
|
|||||||
|
|
||||||
InitializeLib(image_handle, systab);
|
InitializeLib(image_handle, systab);
|
||||||
|
|
||||||
|
check_mok_sb();
|
||||||
|
|
||||||
|
if (insecure_mode) {
|
||||||
|
Print(L"Booting in insecure mode\n");
|
||||||
|
uefi_call_wrapper(BS->Stall, 1, 2000000);
|
||||||
|
}
|
||||||
|
|
||||||
efi_status = check_mok_request(image_handle);
|
efi_status = check_mok_request(image_handle);
|
||||||
|
|
||||||
efi_status = mirror_mok_list();
|
efi_status = mirror_mok_list();
|
||||||
|
Loading…
Reference in New Issue
Block a user