X-Git-Url: https://code.delx.au/refind/blobdiff_plain/c5d1646e66976fff2184375187bb96db366afcbc..7e22a0b1a85d3403ed76ece8339a07ef59174ed3:/mok/mok.c diff --git a/mok/mok.c b/mok/mok.c new file mode 100644 index 0000000..bedd031 --- /dev/null +++ b/mok/mok.c @@ -0,0 +1,127 @@ +/* mok/mok.c + * + * Based mostly on shim.c by Matthew J. Garrett/Red Hat (see below + * copyright notice). + * + * Code to perform Secure Boot verification of boot loader programs + * using the Shim program and its Machine Owner Keys (MOKs), to + * supplement standard Secure Boot checks performed by the firmware. + * + */ + +/* + * shim - trivial UEFI first-stage bootloader + * + * Copyright 2012 Red Hat, Inc + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Significant portions of this code are derived from Tianocore + * (http://tianocore.sf.net) and are Copyright 2009-2012 Intel + * Corporation. + */ + +#include "global.h" +#include "mok.h" +#include "../include/refit_call_wrapper.h" + +static EFI_STATUS get_variable (CHAR16 *name, EFI_GUID guid, UINT32 *attributes, UINTN *size, VOID **buffer) +{ + EFI_STATUS efi_status; + char allocate = !(*size); + + efi_status = uefi_call_wrapper(RT->GetVariable, 5, name, &guid, attributes, size, buffer); + + if (efi_status != EFI_BUFFER_TOO_SMALL || !allocate) { + return efi_status; + } + + *buffer = AllocatePool(*size); + + if (!*buffer) { + Print(L"Unable to allocate variable buffer\n"); + return EFI_OUT_OF_RESOURCES; + } + + efi_status = uefi_call_wrapper(RT->GetVariable, 5, name, &guid, attributes, size, *buffer); + + return efi_status; +} // get_variable() + +/* + * Check whether we're in Secure Boot and user mode + */ +BOOLEAN secure_mode (VOID) +{ + EFI_STATUS status; + EFI_GUID global_var = EFI_GLOBAL_VARIABLE; + UINTN charsize = sizeof(char); + UINT8 sb, setupmode; + UINT32 attributes; + + status = get_variable(L"SecureBoot", global_var, &attributes, &charsize, (VOID *)&sb); + + /* FIXME - more paranoia here? */ + if (status != EFI_SUCCESS || sb != 1) { + return FALSE; + } + + status = get_variable(L"SetupMode", global_var, &attributes, &charsize, (VOID *)&setupmode); + + if (status == EFI_SUCCESS && setupmode == 1) { + return FALSE; + } + + return TRUE; +} // secure_mode() + +// Returns TRUE if the shim program is available to verify binaries, +// FALSE if not +BOOLEAN ShimLoaded(void) { + SHIM_LOCK *shim_lock; + EFI_GUID ShimLockGuid = SHIM_LOCK_GUID; + + return (refit_call3_wrapper(BS->LocateProtocol, &ShimLockGuid, NULL, (VOID**) &shim_lock) == EFI_SUCCESS); +} // ShimLoaded() + +// The following is based on the grub_linuxefi_secure_validate() function in Fedora's +// version of GRUB 2. +// Returns TRUE if the specified data is validated by Shim's MOK, FALSE otherwise +BOOLEAN ShimValidate (VOID *data, UINT32 size) +{ + SHIM_LOCK *shim_lock; + EFI_GUID ShimLockGuid = SHIM_LOCK_GUID; + + if (refit_call3_wrapper(BS->LocateProtocol, &ShimLockGuid, NULL, (VOID**) &shim_lock) == EFI_SUCCESS) { + if (!shim_lock) + return FALSE; + + if (shim_lock->shim_verify(data, size) == EFI_SUCCESS) + return TRUE; + } + + return FALSE; +} // BOOLEAN ShimValidate()