summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile4
-rw-r--r--mok.c334
-rw-r--r--replacements.c10
-rw-r--r--shim.c423
-rw-r--r--shim.h8
5 files changed, 358 insertions, 421 deletions
diff --git a/Makefile b/Makefile
index a61e60ba..7fb9484e 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 00000000..38675211
--- /dev/null
+++ b/mok.c
@@ -0,0 +1,334 @@
+/*
+ * mok.c
+ * Copyright 2017 Peter Jones <pjones@redhat.com>
+ *
+ * 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 27fbb52d..10010567 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 2b263c27..a13bd58b 100644
--- a/shim.c
+++ b/shim.c
@@ -52,9 +52,6 @@
#include <stdint.h>
-#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;
@@ -972,34 +969,6 @@ done:
}
/*
- * 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
*/
static EFI_STATUS verify_buffer (char *data, int datasize,
@@ -1054,15 +1023,6 @@ static EFI_STATUS verify_buffer (char *data, int datasize,
}
/*
- * 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
*/
efi_status = check_blacklist(cert, sha256hash, sha1hash);
@@ -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
@@ -2957,31 +2577,6 @@ efi_main (EFI_HANDLE passed_image_handle, EFI_SYSTEM_TABLE *passed_systab)
}
/*
- * 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
*/
efi_status = init_grub(image_handle);
diff --git a/shim.h b/shim.h
index ddc8d7f6..4079ef8f 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) \