diff --git a/Makefile b/Makefile index a61e60b..7fb9484 100644 --- a/Makefile +++ b/Makefile @@ -33,9 +33,9 @@ CFLAGS += -DENABLE_SHIM_CERT else TARGETS += $(MMNAME) $(FBNAME) endif -OBJS = shim.o netboot.o cert.o replacements.o tpm.o version.o errlog.o +OBJS = shim.o mok.o netboot.o cert.o replacements.o tpm.o version.o errlog.o KEYS = shim_cert.h ocsp.* ca.* shim.crt shim.csr shim.p12 shim.pem shim.key shim.cer -ORIG_SOURCES = shim.c netboot.c replacements.c tpm.c errlog.c shim.h version.h $(wildcard include/*.h) +ORIG_SOURCES = shim.c mok.c netboot.c replacements.c tpm.c errlog.c shim.h version.h $(wildcard include/*.h) MOK_OBJS = MokManager.o PasswordCrypt.o crypt_blowfish.o ORIG_MOK_SOURCES = MokManager.c PasswordCrypt.c crypt_blowfish.c shim.h $(wildcard include/*.h) FALLBACK_OBJS = fallback.o tpm.o diff --git a/mok.c b/mok.c new file mode 100644 index 0000000..3867521 --- /dev/null +++ b/mok.c @@ -0,0 +1,334 @@ +/* + * mok.c + * Copyright 2017 Peter Jones + * + * Distributed under terms of the GPLv3 license. + */ + +#include "shim.h" + +/* + * Check if a variable exists + */ +static BOOLEAN check_var(CHAR16 *varname) +{ + EFI_STATUS efi_status; + UINTN size = sizeof(UINT32); + UINT32 MokVar; + UINT32 attributes; + + efi_status = gRT->GetVariable(varname, &SHIM_LOCK_GUID, &attributes, + &size, (void *)&MokVar); + if (!EFI_ERROR(efi_status) || efi_status == EFI_BUFFER_TOO_SMALL) + return TRUE; + + return FALSE; +} + +/* + * If the OS has set any of these variables we need to drop into MOK and + * handle them appropriately + */ +static EFI_STATUS check_mok_request(EFI_HANDLE image_handle) +{ + EFI_STATUS efi_status; + + 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"MokXAuth")) { + efi_status = start_image(image_handle, MOK_MANAGER); + + if (EFI_ERROR(efi_status)) { + perror(L"Failed to start MokManager: %r\n", efi_status); + return efi_status; + } + } + + return EFI_SUCCESS; +} + +/* + * MoK variables that need to have their storage validated. + * + * The order here is important, since this is where we measure for the + * tpm as well. + */ +struct mok_state_variable { + CHAR16 *name; + char *name8; + CHAR16 *rtname; + EFI_GUID *guid; + UINT8 *data; + UINTN data_size; + /* + * These two are indirect pointers just to make initialization + * saner... + */ + UINT8 **addend_source; + UINT32 *addend_size; + UINT32 yes_attr; + UINT32 no_attr; + UINT32 flags; + UINTN pcr; + UINT8 *state; +}; + +#define MOK_MIRROR_KEYDB 0x01 +#define MOK_MIRROR_DELETE_FIRST 0x02 +#define MOK_VARIABLE_MEASURE 0x04 +#define MOK_VARIABLE_LOG 0x08 + +struct mok_state_variable mok_state_variables[] = { + {.name = L"MokList", + .name8 = "MokList", + .rtname = L"MokListRT", + .guid = &SHIM_LOCK_GUID, + .yes_attr = EFI_VARIABLE_BOOTSERVICE_ACCESS | + EFI_VARIABLE_NON_VOLATILE, + .no_attr = EFI_VARIABLE_RUNTIME_ACCESS, + .addend_source = &vendor_cert, + .addend_size = &vendor_cert_size, + .flags = MOK_MIRROR_KEYDB | + MOK_VARIABLE_LOG, + .pcr = 14, + }, + {.name = L"MokListX", + .name8 = "MokListX", + .rtname = L"MokListXRT", + .guid = &SHIM_LOCK_GUID, + .yes_attr = EFI_VARIABLE_BOOTSERVICE_ACCESS | + EFI_VARIABLE_NON_VOLATILE, + .no_attr = EFI_VARIABLE_RUNTIME_ACCESS, + .flags = MOK_MIRROR_KEYDB | + MOK_VARIABLE_LOG, + .pcr = 14, + }, + {.name = L"MokSBState", + .name8 = "MokSBState", + .rtname = L"MokSBStateRT", + .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 = &user_insecure_mode, + }, + {.name = L"MokDBState", + .name8 = "MokDBState", + .rtname = L"MokIgnoreDB", + .guid = &SHIM_LOCK_GUID, + .yes_attr = EFI_VARIABLE_BOOTSERVICE_ACCESS | + EFI_VARIABLE_NON_VOLATILE, + .no_attr = EFI_VARIABLE_RUNTIME_ACCESS, + .state = &ignore_db, + }, + { NULL, } +}; + +static EFI_STATUS mirror_one_mok_variable(struct mok_state_variable *v) +{ + EFI_STATUS efi_status = EFI_SUCCESS; + void *FullData = NULL; + UINTN FullDataSize = 0; + uint8_t *p = NULL; + + if ((v->flags & MOK_MIRROR_KEYDB) && + v->addend_source && *v->addend_source && + v->addend_size && *v->addend_size) { + EFI_SIGNATURE_LIST *CertList = NULL; + EFI_SIGNATURE_DATA *CertData = NULL; + FullDataSize = v->data_size + + sizeof (*CertList) + + sizeof (EFI_GUID) + + *v->addend_size; + FullData = AllocatePool(FullDataSize); + if (!FullData) { + perror(L"Failed to allocate space for MokListRT\n"); + return EFI_OUT_OF_RESOURCES; + } + p = FullData; + + if (!EFI_ERROR(efi_status) && v->data_size > 0) { + CopyMem(p, v->data, v->data_size); + p += v->data_size; + } + CertList = (EFI_SIGNATURE_LIST *)p; + p += sizeof (*CertList); + CertData = (EFI_SIGNATURE_DATA *)p; + p += sizeof (EFI_GUID); + + CertList->SignatureType = EFI_CERT_TYPE_X509_GUID; + CertList->SignatureListSize = *v->addend_size + + sizeof (*CertList) + + sizeof (*CertData) + -1; + CertList->SignatureHeaderSize = 0; + CertList->SignatureSize = *v->addend_size + sizeof (EFI_GUID); + + CertData->SignatureOwner = SHIM_LOCK_GUID; + CopyMem(p, *v->addend_source, *v->addend_size); + + if (v->data && v->data_size) + FreePool(v->data); + v->data = FullData; + v->data_size = FullDataSize; + } else { + FullDataSize = v->data_size; + FullData = v->data; + } + + if (FullDataSize) { + efi_status = gRT->SetVariable(v->rtname, v->guid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | + EFI_VARIABLE_RUNTIME_ACCESS, + FullDataSize, FullData); + if (EFI_ERROR(efi_status)) { + perror(L"Failed to set %s: %r\n", + v->rtname, efi_status); + } + } + + return efi_status; +} + +/* + * Verify our non-volatile MoK state. This checks the variables above + * accessable and have valid attributes. If they don't, it removes + * them. If any of them can't be removed, our ability to do this is + * comprimized, so return EFI_SECURITY_VIOLATION. + * + * Any variable that isn't deleted and has ->measure == TRUE is then + * measured into the tpm. + * + * Any variable with a ->rtname element is then mirrored to a + * runtime-accessable version. The new ones won't be marked NV, so the OS + * can't modify them. + */ +EFI_STATUS import_mok_state(EFI_HANDLE image_handle) +{ + UINTN i; + EFI_STATUS ret = EFI_SUCCESS; + EFI_STATUS efi_status; + + user_insecure_mode = 0; + ignore_db = 0; + + for (i = 0; mok_state_variables[i].name != NULL; i++) { + struct mok_state_variable *v = &mok_state_variables[i]; + UINT32 attrs = 0; + BOOLEAN delete = FALSE, present, addend; + + efi_status = get_variable_attr(v->name, + &v->data, &v->data_size, + *v->guid, &attrs); + if (efi_status == EFI_NOT_FOUND) + continue; + if (EFI_ERROR(efi_status)) { + perror(L"Could not verify %s: %r\n", v->name, + efi_status); + /* + * don't clobber EFI_SECURITY_VIOLATION from some + * other variable in the list. + */ + if (ret != EFI_SECURITY_VIOLATION) + ret = efi_status; + continue; + } + + if (!(attrs & v->yes_attr)) { + perror(L"Variable %s is missing attributes:\n", + v->name); + perror(L" 0x%08x should have 0x%08x set.\n", + attrs, v->yes_attr); + delete = TRUE; + } + if (attrs & v->no_attr) { + perror(L"Variable %s has incorrect attribute:\n", + v->name); + perror(L" 0x%08x should not have 0x%08x set.\n", + attrs, v->no_attr); + delete = TRUE; + } + if (delete == TRUE) { + perror(L"Deleting bad variable %s\n", v->name); + efi_status = LibDeleteVariable(v->name, v->guid); + if (EFI_ERROR(efi_status)) { + perror(L"Failed to erase %s\n", v->name); + ret = EFI_SECURITY_VIOLATION; + } + FreePool(v->data); + v->data = NULL; + v->data_size = 0; + continue; + } + + if (v->data && v->data_size == sizeof(UINT8) && v->state) { + *v->state = v->data[0]; + } + + present = (v->data && v->data_size) ? TRUE : FALSE; + addend = (v->addend_source && v->addend_size && + *v->addend_source && *v->addend_size) + ? TRUE : FALSE; + + if (v->flags & MOK_VARIABLE_MEASURE && present) { + /* + * Measure this into PCR 7 in the Microsoft format + */ + efi_status = tpm_measure_variable(v->name, *v->guid, + v->data_size, + v->data); + if (EFI_ERROR(efi_status)) { + if (ret != EFI_SECURITY_VIOLATION) + ret = efi_status; + } + } + + if (v->flags & MOK_VARIABLE_LOG && present) { + /* + * Log this variable into whichever PCR the table + * says. + */ + EFI_PHYSICAL_ADDRESS datap = + (EFI_PHYSICAL_ADDRESS)(UINTN)v->data, + efi_status = tpm_log_event(datap, v->data_size, + v->pcr, (CHAR8 *)v->name8); + if (EFI_ERROR(efi_status)) { + if (ret != EFI_SECURITY_VIOLATION) + ret = efi_status; + } + } + + if (v->rtname && present && addend) { + if (v->flags & MOK_MIRROR_DELETE_FIRST) + LibDeleteVariable(v->rtname, v->guid); + + efi_status = mirror_one_mok_variable(v); + if (EFI_ERROR(efi_status) && + ret != EFI_SECURITY_VIOLATION) + ret = efi_status; + } + } + + /* + * Enter MokManager if necessary. Any actual *changes* here will + * cause MokManager to demand a machine reboot, so this is safe to + * have after the entire loop. + */ + efi_status = check_mok_request(image_handle); + if (EFI_ERROR(efi_status)) { + if (ret != EFI_SECURITY_VIOLATION) + ret = efi_status; + return ret; + } + + + return ret; +} + +// vim:fenc=utf-8:tw=75 diff --git a/replacements.c b/replacements.c index 27fbb52..1001056 100644 --- a/replacements.c +++ b/replacements.c @@ -101,7 +101,7 @@ load_image(BOOLEAN BootPolicy, EFI_HANDLE ParentImageHandle, } static EFI_STATUS EFIAPI -start_image(EFI_HANDLE image_handle, UINTN *exit_data_size, CHAR16 **exit_data) +replacement_start_image(EFI_HANDLE image_handle, UINTN *exit_data_size, CHAR16 **exit_data) { EFI_STATUS efi_status; unhook_system_services(); @@ -187,9 +187,9 @@ hook_system_services(EFI_SYSTEM_TABLE *local_systab) /* We need LoadImage() hooked so that fallback.c can load shim * without having to fake LoadImage as well. This allows it * to call the system LoadImage(), and have us track the output - * and mark loader_is_participating in start_image. This means - * anything added by fallback has to be verified by the system db, - * which we want to preserve anyway, since that's all launching + * and mark loader_is_participating in replacement_start_image. This + * means anything added by fallback has to be verified by the system + * db, which we want to preserve anyway, since that's all launching * through BDS gives us. */ system_load_image = systab->BootServices->LoadImage; systab->BootServices->LoadImage = load_image; @@ -197,7 +197,7 @@ hook_system_services(EFI_SYSTEM_TABLE *local_systab) /* we need StartImage() so that we can allow chain booting to an * image trusted by the firmware */ system_start_image = systab->BootServices->StartImage; - systab->BootServices->StartImage = start_image; + systab->BootServices->StartImage = replacement_start_image; /* we need to hook ExitBootServices() so a) we can enforce the policy * and b) we can unwrap when we're done. */ diff --git a/shim.c b/shim.c index 2b263c2..a13bd58 100644 --- a/shim.c +++ b/shim.c @@ -52,9 +52,6 @@ #include -#define FALLBACK L"\\fb" EFI_ARCH L".efi" -#define MOK_MANAGER L"\\mm" EFI_ARCH L".efi" - #define OID_EKU_MODSIGN "1.3.6.1.4.1.2312.16.1.2" static EFI_SYSTEM_TABLE *systab; @@ -971,34 +968,6 @@ done: return efi_status; } -/* - * Ensure that the MOK database hasn't been set or modified from an OS - */ -static EFI_STATUS verify_mok (void) { - EFI_STATUS efi_status; - UINT8 *MokListData = NULL; - UINTN MokListDataSize = 0; - UINT32 attributes; - - efi_status = get_variable_attr(L"MokList", &MokListData, - &MokListDataSize, SHIM_LOCK_GUID, - &attributes); - if (!EFI_ERROR(efi_status) && - attributes & EFI_VARIABLE_RUNTIME_ACCESS) { - perror(L"MokList is compromised!\nErase all keys in MokList!\n"); - efi_status = LibDeleteVariable(L"MokList", &SHIM_LOCK_GUID); - if (EFI_ERROR(efi_status)) { - perror(L"Failed to erase MokList\n"); - return EFI_SECURITY_VIOLATION; - } - } - - if (MokListData) - FreePool(MokListData); - - return EFI_SUCCESS; -} - /* * Check that the signature is valid and matches the binary */ @@ -1053,15 +1022,6 @@ static EFI_STATUS verify_buffer (char *data, int datasize, return efi_status; } - /* - * Check that the MOK database hasn't been modified - */ - efi_status = verify_mok(); - if (EFI_ERROR(efi_status)) { - LogError(L"verify_mok: %r\n", efi_status); - return efi_status; - } - /* * Ensure that the binary isn't blacklisted */ @@ -1997,337 +1957,6 @@ EFI_STATUS init_grub(EFI_HANDLE image_handle) return efi_status; } -/* - * Measure some of the MOK variables into the TPM. We measure the entirety - * of MokList into PCR 14, and also measure the raw MokSBState there. PCR 7 - * will be extended with MokSBState in the Microsoft format, and we'll - * measure any matching hashes or certificates later on in order to behave - * consistently with the PCR 7 spec. - */ -EFI_STATUS measure_mok() -{ - EFI_STATUS efi_status, ret = EFI_SUCCESS; - UINT8 *Data = NULL; - UINTN DataSize = 0; - - efi_status = get_variable(L"MokList", &Data, &DataSize, SHIM_LOCK_GUID); - if (!EFI_ERROR(efi_status)) { - efi_status = tpm_log_event((EFI_PHYSICAL_ADDRESS)(UINTN)Data, - DataSize, 14, (CHAR8 *)"MokList"); - FreePool(Data); - - if (EFI_ERROR(efi_status)) - ret = efi_status; - } else { - ret = efi_status; - } - - efi_status = get_variable(L"MokListX", &Data, &DataSize, SHIM_LOCK_GUID); - if (!EFI_ERROR(efi_status)) { - efi_status = tpm_log_event((EFI_PHYSICAL_ADDRESS)(UINTN)Data, - DataSize, 14, (CHAR8 *)"MokListX"); - FreePool(Data); - - if (EFI_ERROR(efi_status) && !EFI_ERROR(ret)) - ret = efi_status; - - } else if (!EFI_ERROR(ret)) { - ret = efi_status; - } - - efi_status = get_variable(L"MokSBState", &Data, &DataSize, - SHIM_LOCK_GUID); - if (!EFI_ERROR(efi_status)) { - efi_status = tpm_measure_variable(L"MokSBState", - SHIM_LOCK_GUID, - DataSize, Data); - if (!EFI_ERROR(efi_status)) { - efi_status = tpm_log_event((EFI_PHYSICAL_ADDRESS) - (UINTN)Data, DataSize, 14, - (CHAR8 *)"MokSBState"); - } - - FreePool(Data); - - if (EFI_ERROR(efi_status) && !EFI_ERROR(ret)) - ret = efi_status; - } else if (!EFI_ERROR(ret)) { - ret = efi_status; - } - - return efi_status; -} - -/* - * Copy the boot-services only MokList variable to the runtime-accessible - * MokListRT variable. It's not marked NV, so the OS can't modify it. - */ -EFI_STATUS mirror_mok_list() -{ - EFI_STATUS efi_status; - UINT8 *Data = NULL; - UINTN DataSize = 0; - void *FullData = NULL; - UINTN FullDataSize = 0; - EFI_SIGNATURE_LIST *CertList = NULL; - EFI_SIGNATURE_DATA *CertData = NULL; - uint8_t *p = NULL; - - efi_status = get_variable(L"MokList", &Data, &DataSize, SHIM_LOCK_GUID); - if (EFI_ERROR(efi_status)) - DataSize = 0; - - if (vendor_cert_size) { - FullDataSize = DataSize - + sizeof (*CertList) - + sizeof (EFI_GUID) - + vendor_cert_size - ; - FullData = AllocatePool(FullDataSize); - if (!FullData) { - perror(L"Failed to allocate space for MokListRT\n"); - return EFI_OUT_OF_RESOURCES; - } - p = FullData; - - if (!EFI_ERROR(efi_status) && DataSize > 0) { - CopyMem(p, Data, DataSize); - p += DataSize; - } - CertList = (EFI_SIGNATURE_LIST *)p; - p += sizeof (*CertList); - CertData = (EFI_SIGNATURE_DATA *)p; - p += sizeof (EFI_GUID); - - CertList->SignatureType = EFI_CERT_TYPE_X509_GUID; - CertList->SignatureListSize = vendor_cert_size - + sizeof (*CertList) - + sizeof (*CertData) - -1; - CertList->SignatureHeaderSize = 0; - CertList->SignatureSize = vendor_cert_size + sizeof (EFI_GUID); - - CertData->SignatureOwner = SHIM_LOCK_GUID; - CopyMem(p, vendor_cert, vendor_cert_size); - } else { - FullDataSize = DataSize; - FullData = Data; - } - - if (FullDataSize) { - efi_status = gRT->SetVariable(L"MokListRT", &SHIM_LOCK_GUID, - EFI_VARIABLE_BOOTSERVICE_ACCESS | - EFI_VARIABLE_RUNTIME_ACCESS, - FullDataSize, FullData); - if (EFI_ERROR(efi_status)) { - perror(L"Failed to set MokListRT: %r\n", efi_status); - } - } - - return efi_status; -} - -/* - * 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_STATUS efi_status; - UINT8 *Data = NULL; - UINTN DataSize = 0; - - efi_status = get_variable(L"MokListX", &Data, &DataSize, - SHIM_LOCK_GUID); - if (EFI_ERROR(efi_status)) - return efi_status; - - efi_status = gRT->SetVariable(L"MokListXRT", &SHIM_LOCK_GUID, - EFI_VARIABLE_BOOTSERVICE_ACCESS | - EFI_VARIABLE_RUNTIME_ACCESS, - DataSize, Data); - if (EFI_ERROR(efi_status)) { - console_error(L"Failed to set MokListRT", efi_status); - } - - return efi_status; -} - -/* - * Copy the boot-services only MokSBState variable to the runtime-accessible - * MokSBStateRT variable. It's not marked NV, so the OS can't modify it. - */ -EFI_STATUS mirror_mok_sb_state() -{ - EFI_STATUS efi_status; - UINT8 *Data = NULL; - UINTN DataSize = 0; - - efi_status = get_variable(L"MokSBState", &Data, &DataSize, - SHIM_LOCK_GUID); - if (!EFI_ERROR(efi_status)) { - UINT8 *Data_RT = NULL; - UINTN DataSize_RT = 0; - - efi_status = get_variable(L"MokSBStateRT", - &Data_RT, &DataSize_RT, - SHIM_LOCK_GUID); - if (!EFI_ERROR(efi_status) || efi_status != EFI_NOT_FOUND) - LibDeleteVariable(L"MokSBStateRT", &SHIM_LOCK_GUID); - - efi_status = gRT->SetVariable(L"MokSBStateRT", &SHIM_LOCK_GUID, - EFI_VARIABLE_BOOTSERVICE_ACCESS | - EFI_VARIABLE_RUNTIME_ACCESS, - DataSize, Data); - if (EFI_ERROR(efi_status)) { - console_error(L"Failed to set MokSBStateRT", efi_status); - } - } - return efi_status; -} - -/* - * Check if a variable exists - */ -static BOOLEAN check_var(CHAR16 *varname) -{ - EFI_STATUS efi_status; - UINTN size = sizeof(UINT32); - UINT32 MokVar; - UINT32 attributes; - - efi_status = gRT->GetVariable(varname, &SHIM_LOCK_GUID, &attributes, - &size, (void *)&MokVar); - if (!EFI_ERROR(efi_status) || efi_status == EFI_BUFFER_TOO_SMALL) - return TRUE; - - return FALSE; -} - -/* - * If the OS has set any of these variables we need to drop into MOK and - * handle them appropriately - */ -EFI_STATUS check_mok_request(EFI_HANDLE image_handle) -{ - EFI_STATUS efi_status; - - 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"MokXAuth")) { - efi_status = start_image(image_handle, MOK_MANAGER); - - if (EFI_ERROR(efi_status)) { - perror(L"Failed to start MokManager: %r\n", efi_status); - return efi_status; - } - } - - return EFI_SUCCESS; -} - -/* - * Verify that MokSBState is valid, and if appropriate set insecure mode - */ -static EFI_STATUS check_mok_sb (void) -{ - EFI_STATUS efi_status; - UINT8 MokSBState; - UINTN MokSBStateSize = sizeof(MokSBState); - UINT32 attributes; - - user_insecure_mode = 0; - ignore_db = 0; - - efi_status = gRT->GetVariable(L"MokSBState", &SHIM_LOCK_GUID, - &attributes, &MokSBStateSize, - &MokSBState); - if (EFI_ERROR(efi_status)) - return EFI_SECURITY_VIOLATION; - - /* - * Delete and ignore the variable if it's been set from or could be - * modified by the OS - */ - if (attributes & EFI_VARIABLE_RUNTIME_ACCESS) { - perror(L"MokSBState is compromised! Clearing it\n"); - efi_status = LibDeleteVariable(L"MokSBState", &SHIM_LOCK_GUID); - if (EFI_ERROR(efi_status)) { - perror(L"Failed to erase MokSBState\n"); - } - efi_status = EFI_SECURITY_VIOLATION; - } else { - if (MokSBState == 1) { - user_insecure_mode = 1; - } - } - - return efi_status; -} - -/* - * Verify that MokDBState is valid, and if appropriate set ignore db mode - */ - -static EFI_STATUS check_mok_db (void) -{ - EFI_STATUS efi_status; - UINT8 MokDBState; - UINTN MokDBStateSize = sizeof(MokDBState); - UINT32 attributes; - - efi_status = gRT->GetVariable(L"MokDBState", &SHIM_LOCK_GUID, - &attributes, &MokDBStateSize, - &MokDBState); - if (EFI_ERROR(efi_status)) - return EFI_SECURITY_VIOLATION; - - ignore_db = 0; - - /* - * Delete and ignore the variable if it's been set from or could be - * modified by the OS - */ - if (attributes & EFI_VARIABLE_RUNTIME_ACCESS) { - perror(L"MokDBState is compromised! Clearing it\n"); - efi_status = LibDeleteVariable(L"MokDBState", &SHIM_LOCK_GUID); - if (EFI_ERROR(efi_status)) { - perror(L"Failed to erase MokDBState\n"); - } - efi_status = EFI_SECURITY_VIOLATION; - } else { - if (MokDBState == 1) { - ignore_db = 1; - } - } - - return efi_status; -} - -static EFI_STATUS mok_ignore_db() -{ - EFI_STATUS efi_status = EFI_SUCCESS; - UINT8 Data = 1; - UINTN DataSize = sizeof(UINT8); - - check_mok_db(); - - if (ignore_db) { - efi_status = gRT->SetVariable(L"MokIgnoreDB", &SHIM_LOCK_GUID, - EFI_VARIABLE_BOOTSERVICE_ACCESS | - EFI_VARIABLE_RUNTIME_ACCESS, - DataSize, (void *)&Data); - if (EFI_ERROR(efi_status)) { - perror(L"Failed to set MokIgnoreDB: %r\n", efi_status); - } - } - - return efi_status; - -} - static inline EFI_STATUS get_load_option_optional_data(UINT8 *data, UINTN data_size, UINT8 **od, UINTN *ods) @@ -2922,31 +2551,22 @@ efi_main (EFI_HANDLE passed_image_handle, EFI_SYSTEM_TABLE *passed_systab) debug_hook(); /* - * Measure the MOK variables + * Before we do anything else, validate our non-volatile, + * boot-services-only state variables are what we think they are. */ - efi_status = measure_mok(); - if (EFI_ERROR(efi_status) && efi_status != EFI_NOT_FOUND) { - Print(L"Something has gone seriously wrong: %r\n", efi_status); - Print(L"Shim was unable to measure state into the TPM\n"); + efi_status = import_mok_state(image_handle); + if (EFI_ERROR(efi_status)) { +die: + Print(L"Something has gone seriously wrong: %r\n", + efi_status); msleep(5000000); gRT->ResetSystem(EfiResetShutdown, EFI_SECURITY_VIOLATION, 0, NULL); } - /* - * Check whether the user has configured the system to run in - * insecure mode - */ - check_mok_sb(); - efi_status = shim_init(); - if (EFI_ERROR(efi_status)) { - Print(L"Something has gone seriously wrong: %r\n", efi_status); - Print(L"shim cannot continue, sorry.\n"); - msleep(5000000); - gRT->ResetSystem(EfiResetShutdown, EFI_SECURITY_VIOLATION, - 0, NULL); - } + if (EFI_ERROR(efi_status)) + goto die; /* * Tell the user that we're in insecure mode if necessary @@ -2956,31 +2576,6 @@ efi_main (EFI_HANDLE passed_image_handle, EFI_SYSTEM_TABLE *passed_systab) msleep(2000000); } - /* - * Enter MokManager if necessary - */ - efi_status = check_mok_request(image_handle); - - /* - * Copy the MOK list to a runtime variable so the kernel can - * make use of it - */ - efi_status = mirror_mok_list(); - - efi_status = mirror_mok_list_x(); - - /* - * Copy the MOK SB State to a runtime variable so the kernel can - * make use of it - */ - efi_status = mirror_mok_sb_state(); - - /* - * Create the runtime MokIgnoreDB variable so the kernel can - * make use of it - */ - mok_ignore_db(); - /* * Hand over control to the second stage bootloader */ diff --git a/shim.h b/shim.h index ddc8d7f..4079ef8 100644 --- a/shim.h +++ b/shim.h @@ -92,6 +92,9 @@ #endif #endif +#define FALLBACK L"\\fb" EFI_ARCH L".efi" +#define MOK_MANAGER L"\\mm" EFI_ARCH L".efi" + #include "include/configtable.h" #include "include/console.h" #include "include/crypt_blowfish.h" @@ -160,13 +163,18 @@ extern EFI_STATUS LogError_(const char *file, int line, const char *func, CHAR16 extern EFI_STATUS VLogError(const char *file, int line, const char *func, CHAR16 *fmt, va_list args); extern VOID PrintErrors(VOID); extern VOID ClearErrors(VOID); +extern EFI_STATUS start_image(EFI_HANDLE image_handle, CHAR16 *ImagePath); +extern EFI_STATUS import_mok_state(EFI_HANDLE image_handle); extern UINT32 vendor_cert_size; extern UINT32 vendor_dbx_size; extern UINT8 *vendor_cert; extern UINT8 *vendor_dbx; +extern UINT8 user_insecure_mode; +extern UINT8 ignore_db; extern UINT8 in_protocol; + #define perror_(file, line, func, fmt, ...) ({ \ UINTN __perror_ret = 0; \ if (!in_protocol) \