From 031e5cce385d3f96b1caa1d53495332a7eb03749 Mon Sep 17 00:00:00 2001 From: Steve McIntyre Date: Tue, 23 Mar 2021 23:49:46 +0000 Subject: New upstream version 15.3 --- lib/Makefile | 42 +++++++- lib/configtable.c | 22 ++-- lib/console.c | 218 ++++++++++++++++++++++++++++++-------- lib/execute.c | 42 +------- lib/guid.c | 8 +- lib/print_crypto.c | 32 ++++++ lib/security_policy.c | 18 +--- lib/shell.c | 6 +- lib/simple_file.c | 17 ++- lib/string.c | 284 ++++++++++++++++++++++++++++++++++++++++++++++++++ lib/variables.c | 199 +++++++++++++++++++++++++++-------- 11 files changed, 709 insertions(+), 179 deletions(-) create mode 100644 lib/print_crypto.c create mode 100644 lib/string.c (limited to 'lib') diff --git a/lib/Makefile b/lib/Makefile index db5ff711..6d83f789 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -1,9 +1,45 @@ TARGET = lib.a -LIBFILES = simple_file.o guid.o console.o execute.o configtable.o shell.o variables.o security_policy.o +LIBFILES_UNSORTED := $(foreach x,$(wildcard *.c),$(patsubst %.c,%.o,$(x))) +LIBFILES := $(sort $(LIBFILES_UNSORTED)) -EFI_INCLUDES = -I$(EFI_INCLUDE) -I$(EFI_INCLUDE)/$(ARCH) -I$(EFI_INCLUDE)/protocol -I$(TOPDIR)/../include \ - -I$(TOPDIR)/CryptLib/Include/openssl/ +CRYPTDIR = $(TOPDIR)/Cryptlib + +INCLUDES = $(EFI_INCLUDES) \ + -I$(TOPDIR)/include \ + -I$(CRYPTDIR)/Include/openssl/ \ + -I$(CRYPTDIR)/Include/ \ + -I$(CRYPTDIR) \ + -I$(TOPDIR) \ + -isystem $(TOPDIR)/include/system \ + -isystem $(shell $(CC) -print-file-name=include) + +CLANG_BUGS = $(if $(findstring gcc,$(CC)),-maccumulate-outgoing-args,) + +ifeq ($(ARCH),x86_64) +FEATUREFLAGS += -m64 -mno-mmx -mno-sse -mno-red-zone -nostdinc $(CLANG_BUGS) +DEFINES += -DMDE_CPU_X64 +endif +ifeq ($(ARCH),ia32) +FEATUREFLAGS += -m32 -mno-mmx -mno-sse -mno-red-zone -nostdinc $(CLANG_BUGS) +DEFINES += -DMDE_CPU_IA32 +endif +ifeq ($(ARCH),aarch64) +DEFINES += -DMDE_CPU_AARCH64 +endif +ifeq ($(ARCH),arm) +DEFINES += -DMDE_CPU_ARM +endif + +LDFLAGS = -nostdlib -znocombreloc + + +CFLAGS = $(FEATUREFLAGS) \ + $(OPTIMIZATIONS) \ + $(WARNFLAGS) \ + $(WERRFLAGS) \ + $(INCLUDES) \ + $(DEFINES) lib.a: $(LIBFILES) $(AR) rcs lib.a $(LIBFILES) diff --git a/lib/configtable.c b/lib/configtable.c index df047f0e..66e97f63 100644 --- a/lib/configtable.c +++ b/lib/configtable.c @@ -1,13 +1,9 @@ +// SPDX-License-Identifier: BSD-2-Clause-Patent /* * Copyright 2013 * - * see COPYING file - * * read some platform configuration tables */ -#include -#include - #include "shim.h" void * @@ -50,22 +46,22 @@ configtable_find_image(const EFI_DEVICE_PATH *DevicePath) /* print what we have for debugging */ UINT8 *d = (UINT8 *)e; // + sizeof(UINT32)*2; console_print(L"Data: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", - d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]); + d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]); d += 16; console_print(L"Data: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", - d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]); + d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]); d += 16; console_print(L"Data: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", - d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]); + d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]); d += 16; console_print(L"Data: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", - d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]); + d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]); d += 16; console_print(L"Data: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", - d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]); + d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]); d += 16; console_print(L"Data: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", - d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]); + d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]); #endif CHAR16 *name = (CHAR16 *)(e->Data); int skip = 0; @@ -94,12 +90,12 @@ configtable_find_image(const EFI_DEVICE_PATH *DevicePath) console_print(L"Device Path Size %d\n", Size); #endif if (Size > e->InfoSize) { - /* parse error; the platform obviously has a + /* parse error; the platform obviously has a * corrupted image table; bail */ console_print(L"Image Execution Information table corrupt\n"); break; } - + if (CompareMem(dp, (void *)DevicePath, Size) == 0) { #ifdef DEBUG_CONFIG console_print(L"***FOUND\n"); diff --git a/lib/console.c b/lib/console.c index 3aee41cd..c310d213 100644 --- a/lib/console.c +++ b/lib/console.c @@ -1,14 +1,8 @@ +// SPDX-License-Identifier: BSD-2-Clause-Patent /* * Copyright 2012 * Copyright 2013 Red Hat Inc. - * - * see COPYING file */ -#include -#include -#include -#include - #include "shim.h" static UINT8 console_text_mode = 0; @@ -89,27 +83,27 @@ VOID console_fini(VOID) setup_console(0); } -UINTN +UINTN EFIAPI console_print(const CHAR16 *fmt, ...) { - va_list args; + ms_va_list args; UINTN ret; if (!console_text_mode) setup_console(1); - va_start(args, fmt); + ms_va_start(args, fmt); ret = VPrint(fmt, args); - va_end(args); + ms_va_end(args); return ret; } -UINTN +UINTN EFIAPI console_print_at(UINTN col, UINTN row, const CHAR16 *fmt, ...) { SIMPLE_TEXT_OUTPUT_INTERFACE *co = ST->ConOut; - va_list args; + ms_va_list args; UINTN ret; if (!console_text_mode) @@ -117,9 +111,9 @@ console_print_at(UINTN col, UINTN row, const CHAR16 *fmt, ...) co->SetCursorPosition(co, col, row); - va_start(args, fmt); + ms_va_start(args, fmt); ret = VPrint(fmt, args); - va_end(args); + ms_va_end(args); return ret; } @@ -214,7 +208,7 @@ console_print_box_at(CHAR16 *str_arr[], int highlight, if (col < 0) col = 0; - CopyMem(Line + col + 1, s, min(len, size_cols - 2)*2); + CopyMem(Line + col + 1, s, MIN(len, size_cols - 2)*2); } if (line >= 0 && line == highlight) co->SetAttribute(co, EFI_LIGHTGRAY | @@ -409,12 +403,171 @@ console_notify(CHAR16 *string) console_alertbox(str_arr); } -#define ARRAY_SIZE(a) (sizeof (a) / sizeof ((a)[0])) +void +console_save_and_set_mode(SIMPLE_TEXT_OUTPUT_MODE * SavedMode) +{ + SIMPLE_TEXT_OUTPUT_INTERFACE *co = ST->ConOut; + + if (!SavedMode) { + console_print(L"Invalid parameter: SavedMode\n"); + return; + } + + CopyMem(SavedMode, co->Mode, sizeof(SIMPLE_TEXT_OUTPUT_MODE)); + co->EnableCursor(co, FALSE); + co->SetAttribute(co, EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE); +} + +void +console_restore_mode(SIMPLE_TEXT_OUTPUT_MODE * SavedMode) +{ + SIMPLE_TEXT_OUTPUT_INTERFACE *co = ST->ConOut; + + co->EnableCursor(co, SavedMode->CursorVisible); + co->SetCursorPosition(co, SavedMode->CursorColumn, + SavedMode->CursorRow); + co->SetAttribute(co, SavedMode->Attribute); +} + +int +console_countdown(CHAR16* title, const CHAR16* message, int timeout) +{ + SIMPLE_TEXT_OUTPUT_INTERFACE *co = ST->ConOut; + SIMPLE_INPUT_INTERFACE *ci = ST->ConIn; + SIMPLE_TEXT_OUTPUT_MODE SavedMode; + EFI_INPUT_KEY key; + EFI_STATUS efi_status; + UINTN cols, rows; + CHAR16 *titles[2]; + int wait = 10000000; + + console_save_and_set_mode(&SavedMode); + + titles[0] = title; + titles[1] = NULL; + + console_print_box_at(titles, -1, 0, 0, -1, -1, 1, 1); + + co->QueryMode(co, co->Mode->Mode, &cols, &rows); + + console_print_at((cols - StrLen(message)) / 2, rows / 2, message); + while (1) { + if (timeout > 1) + console_print_at(2, rows - 3, + L"Booting in %d seconds ", + timeout); + else if (timeout) + console_print_at(2, rows - 3, + L"Booting in %d second ", + timeout); + + efi_status = WaitForSingleEvent(ci->WaitForKey, wait); + if (efi_status != EFI_TIMEOUT) { + /* Clear the key in the queue */ + ci->ReadKeyStroke(ci, &key); + break; + } + + timeout--; + if (!timeout) + break; + } + + console_restore_mode(&SavedMode); + + return timeout; +} + +#define HORIZONTAL_MAX_OK 1920 +#define VERTICAL_MAX_OK 1080 +#define COLUMNS_MAX_OK 200 +#define ROWS_MAX_OK 100 + +void +console_mode_handle(VOID) +{ + SIMPLE_TEXT_OUTPUT_INTERFACE *co = ST->ConOut; + EFI_GRAPHICS_OUTPUT_PROTOCOL *gop; + EFI_GUID gop_guid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID; + EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info; + + UINTN mode_set; + UINTN rows = 0, columns = 0; + EFI_STATUS efi_status = EFI_SUCCESS; + + efi_status = gBS->LocateProtocol(&gop_guid, NULL, (void **)&gop); + if (EFI_ERROR(efi_status)) { + console_error(L"Locate graphic output protocol fail", efi_status); + return; + } + + Info = gop->Mode->Info; + + /* + * Start verifying if we are in a resolution larger than Full HD + * (1920x1080). If we're not, assume we're in a good mode and do not + * try to change it. + */ + if (Info->HorizontalResolution <= HORIZONTAL_MAX_OK && + Info->VerticalResolution <= VERTICAL_MAX_OK) { + /* keep original mode and return */ + return; + } + + efi_status = co->QueryMode(co, co->Mode->Mode, &columns, &rows); + if (EFI_ERROR(efi_status)) { + console_error(L"Console query mode fail", efi_status); + return; + } + + /* + * Verify current console output to check if the character columns and + * rows in a good mode. + */ + if (columns <= COLUMNS_MAX_OK && rows <= ROWS_MAX_OK) { + /* keep original mode and return */ + return; + } + + if (!console_text_mode) + setup_console(1); + + co->Reset(co, TRUE); + + /* + * If we reached here, then we have a high resolution screen and the + * text too small. Try to switch to a better mode. Mode number 2 is + * first non standard mode, which is provided by the device + * manufacturer, so it should be a good mode. + */ + if (co->Mode->MaxMode > 2) + mode_set = 2; + else + mode_set = 0; + + efi_status = co->SetMode(co, mode_set); + if (EFI_ERROR(efi_status) && mode_set != 0) { + /* + * Set to 0 mode which is required that all output devices + * support at least 80x25 text mode. + */ + mode_set = 0; + efi_status = co->SetMode(co, mode_set); + } + + co->ClearScreen(co); + + if (EFI_ERROR(efi_status)) { + console_error(L"Console set mode fail", efi_status); + } + + return; +} /* Copy of gnu-efi-3.0 with the added secure boot strings */ static struct { EFI_STATUS Code; - WCHAR *Desc; + CHAR16 *Desc; } error_table[] = { { EFI_SUCCESS, L"Success"}, { EFI_LOAD_ERROR, L"Load Error"}, @@ -445,7 +598,7 @@ static struct { { EFI_SECURITY_VIOLATION, L"Security Violation"}, // warnings - { EFI_WARN_UNKOWN_GLYPH, L"Warning Unknown Glyph"}, + { EFI_WARN_UNKNOWN_GLYPH, L"Warning Unknown Glyph"}, { EFI_WARN_DELETE_FAILURE, L"Warning Delete Failure"}, { EFI_WARN_WRITE_FAILURE, L"Warning Write Failure"}, { EFI_WARN_BUFFER_TOO_SMALL, L"Warning Buffer Too Small"}, @@ -523,33 +676,6 @@ setup_verbosity(VOID) setup_console(-1); } -/* Included here because they mess up the definition of va_list and friends */ -#include -#include -#include - -static int -print_errors_cb(const char *str, size_t len, void *u) -{ - console_print(L"%a", str); - - return len; -} - -EFI_STATUS -print_crypto_errors(EFI_STATUS efi_status, - char *file, const char *func, int line) -{ - if (!(verbose && EFI_ERROR(efi_status))) - return efi_status; - - console_print(L"SSL Error: %a:%d %a(): %r\n", file, line, func, - efi_status); - ERR_print_errors_cb(print_errors_cb, NULL); - - return efi_status; -} - VOID msleep(unsigned long msecs) { diff --git a/lib/execute.c b/lib/execute.c index 3aff28ad..642f94a3 100644 --- a/lib/execute.c +++ b/lib/execute.c @@ -1,46 +1,8 @@ +// SPDX-License-Identifier: BSD-2-Clause-Patent /* * Copyright 2012 - * - * see COPYING file - * - * -- - * - * generate_path is a cut and paste from - * - * git://github.com/mjg59/shim.git - * * Code 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. - * */ - -#include -#include - #include "shim.h" EFI_STATUS @@ -83,7 +45,7 @@ generate_path(CHAR16* name, EFI_LOADED_IMAGE *li, EFI_DEVICE_PATH **path, CHAR16 if (name[0] != '\\') StrCat(*PathName, L"\\"); StrCat(*PathName, name); - + *path = FileDevicePath(li->DeviceHandle, *PathName); error: diff --git a/lib/guid.c b/lib/guid.c index 57c02fbe..143e0bbd 100644 --- a/lib/guid.c +++ b/lib/guid.c @@ -1,8 +1,4 @@ -/* - * Copyright 2012 - * - * see COPYING file - */ +// SPDX-License-Identifier: BSD-2-Clause-Patent #include "shim.h" @@ -36,4 +32,6 @@ EFI_GUID EFI_SECURE_BOOT_DB_GUID = { 0xd719b2cb, 0x3d3a, 0x4596, { 0xa3, 0xbc, EFI_GUID EFI_SIMPLE_FILE_SYSTEM_GUID = SIMPLE_FILE_SYSTEM_PROTOCOL; EFI_GUID SECURITY_PROTOCOL_GUID = { 0xA46423E3, 0x4617, 0x49f1, {0xB9, 0xFF, 0xD1, 0xBF, 0xA9, 0x11, 0x58, 0x39 } }; EFI_GUID SECURITY2_PROTOCOL_GUID = { 0x94ab2f58, 0x1438, 0x4ef1, {0x91, 0x52, 0x18, 0x94, 0x1a, 0x3a, 0x0e, 0x68 } }; + EFI_GUID SHIM_LOCK_GUID = {0x605dab50, 0xe046, 0x4300, {0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23 } }; +EFI_GUID MOK_VARIABLE_STORE = {0xc451ed2b, 0x9694, 0x45d3, {0xba, 0xba, 0xed, 0x9f, 0x89, 0x88, 0xa3, 0x89} }; diff --git a/lib/print_crypto.c b/lib/print_crypto.c new file mode 100644 index 00000000..ccdb65b1 --- /dev/null +++ b/lib/print_crypto.c @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: BSD-2-Clause-Patent +/* + * Copyright 2019 SUSE LLC + */ +#include "shim.h" + +#include +#include +#include +#include + +static int +print_errors_cb(const char *str, size_t len, void *u UNUSED) +{ + console_print(L"%a", str); + + return len; +} + +EFI_STATUS +print_crypto_errors(EFI_STATUS efi_status, + char *file, const char *func, int line) +{ + if (!(verbose && EFI_ERROR(efi_status))) + return efi_status; + + console_print(L"SSL Error: %a:%d %a(): %r\n", file, line, func, + efi_status); + ERR_print_errors_cb(print_errors_cb, NULL); + + return efi_status; +} diff --git a/lib/security_policy.c b/lib/security_policy.c index 211f1cfd..6c42cc14 100644 --- a/lib/security_policy.c +++ b/lib/security_policy.c @@ -1,22 +1,12 @@ +// SPDX-License-Identifier: BSD-2-Clause-Patent /* * Copyright 2012 * - * see COPYING file - * * Install and remove a platform security2 override policy */ - -#include -#include - #include "shim.h" -#include -#include -#include - #if defined(OVERRIDE_SECURITY_POLICY) -#include /* * See the UEFI Platform Initialization manual (Vol2: DXE) for this @@ -60,7 +50,7 @@ extern EFI_STATUS thunk_security_policy_authentication( const EFI_SECURITY_PROTOCOL *This, UINT32 AuthenticationStatus, const EFI_DEVICE_PATH_PROTOCOL *DevicePath - ) + ) __attribute__((unused)); extern EFI_STATUS thunk_security2_policy_authentication( @@ -69,7 +59,7 @@ extern EFI_STATUS thunk_security2_policy_authentication( VOID *FileBuffer, UINTN FileSize, BOOLEAN BootPolicy - ) + ) __attribute__((unused)); static __attribute__((used)) EFI_STATUS @@ -112,7 +102,7 @@ security_policy_authentication ( ) { EFI_STATUS efi_status, fail_status; - EFI_DEVICE_PATH *DevPath + EFI_DEVICE_PATH *DevPath = DuplicateDevicePath((EFI_DEVICE_PATH *)DevicePathConst), *OrigDevPath = DevPath; EFI_HANDLE h; diff --git a/lib/shell.c b/lib/shell.c index e46e7fd2..146d9a21 100644 --- a/lib/shell.c +++ b/lib/shell.c @@ -1,13 +1,9 @@ +// SPDX-License-Identifier: BSD-2-Clause-Patent /* * Copyright 2012 * - * see COPYING file - * * misc shell helper functions */ -#include -#include - #include "shim.h" EFI_STATUS diff --git a/lib/simple_file.c b/lib/simple_file.c index 3bf92ed8..5fd3e1a6 100644 --- a/lib/simple_file.c +++ b/lib/simple_file.c @@ -1,12 +1,7 @@ +// SPDX-License-Identifier: BSD-2-Clause-Patent /* * Copyright 2012 - * - * see COPYING file */ - -#include -#include - #include "shim.h" EFI_STATUS @@ -67,8 +62,8 @@ simple_file_open(EFI_HANDLE image, CHAR16 *name, EFI_FILE **file, UINT64 mode) } EFI_STATUS -simple_dir_read_all_by_handle(EFI_HANDLE image, EFI_FILE *file, CHAR16* name, EFI_FILE_INFO **entries, - int *count) +simple_dir_read_all_by_handle(EFI_HANDLE image UNUSED, EFI_FILE *file, + CHAR16* name, EFI_FILE_INFO **entries, int *count) { EFI_STATUS efi_status; char buf[4096]; @@ -403,10 +398,10 @@ simple_file_selector(EFI_HANDLE * im, CHAR16 ** title, CHAR16 * name, filter = L""; if (!*im) { EFI_HANDLE h; - CHAR16 *volname; + CHAR16 *volname = NULL; - simple_volume_selector(title, &volname, &h); - if (!volname) + efi_status = simple_volume_selector(title, &volname, &h); + if (EFI_ERROR(efi_status) || !volname) return; FreePool(volname); *im = h; diff --git a/lib/string.c b/lib/string.c new file mode 100644 index 00000000..d941cd56 --- /dev/null +++ b/lib/string.c @@ -0,0 +1,284 @@ +// SPDX-License-Identifier: BSD-2-Clause-Patent +/* + * string.c - implementations we need for string finctions + */ +#define SHIM_STRING_C_ +#include "shim.h" + +#ifdef SHIM_UNIT_TEST +#define strlen shim_strlen +#ifdef strcmp +#undef strcmp +#endif +#define strcmp shim_strcmp +#ifdef strncmp +#undef strncmp +#endif +#define strncmp shim_strncmp +#define strncasecmp shim_strncasecmp +#define strcasecmp shim_strcasecmp +#define strrchr shim_strrchr +#define strlen shim_strlen +#define strnlen shim_strnlen +#define strcpy shim_strcpy +#ifdef strncpy +#undef strncpy +#endif +#define strncpy shim_strncpy +#ifdef strdup +#undef strdup +#endif +#define strdup shim_strdup +#ifdef strndup +#undef strndup +#endif +#define strndup shim_strndup +#ifdef stpcpy +#undef stpcpy +#endif +#define stpcpy shim_stpcpy +#define strchrnul shim_strchrnul +#ifdef strchr +#undef strchr +#endif +#define strchr shim_strchr +#endif + +size_t +strlen(const char *s1) +{ + size_t len; + + for (len = 0; *s1; s1 += 1, len += 1) + ; + return len; +} + +int +strcmp(const char *s1p, const char *s2p) +{ + const uint8_t *s1 = (const uint8_t *)s1p; + const uint8_t *s2 = (const uint8_t *)s2p; + + while (*s1) { + if (*s1 != *s2) { + break; + } + + s1 += 1; + s2 += 1; + } + + return *s1 - *s2; +} + +int +strncmp(const char *s1p, const char *s2p, size_t len) +{ + const uint8_t *s1 = (const uint8_t *)s1p; + const uint8_t *s2 = (const uint8_t *)s2p; + + while (*s1 && len) { + if (*s1 != *s2) { + break; + } + + s1 += 1; + s2 += 1; + len -= 1; + } + + return len ? *s1 - *s2 : 0; +} + +/* Based on AsciiStriCmp() in edk2 MdePkg/Library/BaseLib/String.c */ +int +strncasecmp(const char *s1p, const char *s2p, size_t n) +{ + const uint8_t *s1 = (const uint8_t *)s1p; + const uint8_t *s2 = (const uint8_t *)s2p; + + while (*s1 && n) { + if (toupper(*s1) != toupper(*s2)) { + break; + } + + s1 += 1; + s2 += 1; + n -= 1; + } + + return n ? *s1 - *s2 : 0; +} + +/* Based on AsciiStriCmp() in edk2 MdePkg/Library/BaseLib/String.c */ +int +strcasecmp(const char *str1, const char *str2) +{ + uint8_t c1, c2; + + c1 = toupper(*str1); + c2 = toupper(*str2); + while ((*str1 != '\0') && (c1 == c2)) { + str1++; + str2++; + c1 = toupper(*str1); + c2 = toupper(*str2); + } + + return c1 - c2; +} + +/* Scan a string for the last occurrence of a character */ +char * +strrchr(const char *str, int c) +{ + char *save; + + for (save = NULL;; ++str) { + if (*str == c) { + save = (char *)str; + } + if (*str == 0) { + return (save); + } + } +} + +NONNULL(1) +size_t +strnlen(const char *s, size_t n) +{ + size_t i; + for (i = 0; i < n; i++) + if (s[i] == '\0') + break; + return i; +} + +RETURNS_NONNULL NONNULL(1, 2) +char * +strcpy(char *dest, const char *src) +{ + size_t i; + + for (i = 0; src[i] != '\0'; i++) + dest[i] = src[i]; + + dest[i] = '\0'; + return dest; +} + +RETURNS_NONNULL NONNULL(1, 2) +char * +strncpy(char *dest, const char *src, size_t n) +{ + size_t i; + + for (i = 0; i < n && src[i] != '\0'; i++) + dest[i] = src[i]; + if (i < n) + dest[i] = '\0'; + + return dest; +} + +RETURNS_NONNULL NONNULL(1, 2) +char * +strcat(char *dest, const char *src) +{ + size_t dest_len = strlen(dest); + size_t i; + + for (i = 0; src[i] != '\0'; i++) + dest[dest_len + i] = src[i]; + dest[dest_len + i] = '\0'; + + return dest; +} + +NONNULL(1) +char * +strdup(const char *const src) +{ + size_t len; + char *news = NULL; + + len = strlen(src); + news = AllocateZeroPool(len + 1); + if (news) + strncpy(news, src, len); + return news; +} + +NONNULL(1) +char * +strndup(const char *const src, const size_t srcmax) +{ + size_t len; + char *news = NULL; + + len = strnlen(src, srcmax); + news = AllocateZeroPool(len + 1); + if (news) + strncpy(news, src, len); + return news; +} + +RETURNS_NONNULL NONNULL(1, 2) +char * +stpcpy(char *dest, const char *const src) +{ + size_t i = 0; + for (i = 0; src[i]; i++) + dest[i] = src[i]; + dest[i] = '\000'; + return &dest[i]; +} + +RETURNS_NONNULL NONNULL(1) +char * +strchrnul(const char *s, int c) +{ + unsigned int i; + + for (i = 0; s[i] != '\000' && s[i] != c; i++) + ; + + return (char *)&s[i]; +} + +NONNULL(1) +char * +strchr(const char *s, int c) +{ + const char *s1; + + s1 = strchrnul(s, c); + if (!s1 || s1[0] == '\000') + return NULL; + + return (char *)s1; +} + +char * +translate_slashes(char *out, const char *str) +{ + int i; + int j; + if (str == NULL || out == NULL) + return NULL; + + for (i = 0, j = 0; str[i] != '\0'; i++, j++) { + if (str[i] == '\\') { + out[j] = '/'; + if (str[i + 1] == '\\') + i++; + } else + out[j] = str[i]; + } + out[j] = '\0'; + return out; +} + +// vim:fenc=utf-8:tw=75:noet diff --git a/lib/variables.c b/lib/variables.c index 9c2e7d0a..f606e248 100644 --- a/lib/variables.c +++ b/lib/variables.c @@ -1,54 +1,119 @@ +// SPDX-License-Identifier: BSD-2-Clause-Patent /* * Copyright 2012 * - * see COPYING file - * * Portions of this file are a direct cut and paste from Tianocore * (http://tianocore.sf.net) * * SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.c * * Copyright (c) 2011 - 2012, Intel Corporation. All rights reserved.
- * This program and the accompanying materials - * are licensed and made available under the terms and conditions of the BSD License - * which accompanies this distribution. The full text of the license may be found - * at - * http://opensource.org/licenses/bsd-license.php - * - * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, - * WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. * */ -#include -#include - #include "shim.h" EFI_STATUS -variable_create_esl(void *cert, int cert_len, EFI_GUID *type, EFI_GUID *owner, - void **out, int *outlen) +fill_esl(const EFI_SIGNATURE_DATA *first_sig, const size_t howmany, + const EFI_GUID *type, const UINT32 sig_size, + uint8_t *out, size_t *outlen) { - *outlen = cert_len + sizeof(EFI_SIGNATURE_LIST) + sizeof(EFI_GUID); + EFI_SIGNATURE_LIST *sl; + EFI_SIGNATURE_DATA *sd; + size_t needed = 0; + size_t data_len = howmany * sig_size; - *out = AllocateZeroPool(*outlen); - if (!*out) - return EFI_OUT_OF_RESOURCES; + dprint(L"fill_esl: first_sig=0x%llx, data_len=%lu\n", first_sig, data_len); - EFI_SIGNATURE_LIST *sl = *out; + if ((out && !first_sig) || !howmany || !type || !sig_size || !outlen) + return EFI_INVALID_PARAMETER; + + if (howmany > (UINT32_MAX - sizeof(EFI_SIGNATURE_LIST)) / sig_size) + return EFI_INVALID_PARAMETER; + + needed = sizeof(EFI_SIGNATURE_LIST) + data_len; + if (!out || *outlen < needed) { + *outlen = needed; + return EFI_BUFFER_TOO_SMALL; + } + + *outlen = needed; + sl = (EFI_SIGNATURE_LIST *)out; sl->SignatureHeaderSize = 0; sl->SignatureType = *type; - sl->SignatureSize = cert_len + sizeof(EFI_GUID); - sl->SignatureListSize = *outlen; + sl->SignatureSize = sig_size; + sl->SignatureListSize = needed; - EFI_SIGNATURE_DATA *sd = *out + sizeof(EFI_SIGNATURE_LIST); + sd = (EFI_SIGNATURE_DATA *)(out + sizeof(EFI_SIGNATURE_LIST)); + CopyMem(sd, first_sig, data_len); - if (owner) - sd->SignatureOwner = *owner; + return EFI_SUCCESS; +} - CopyMem(sd->SignatureData, cert, cert_len); +EFI_STATUS +fill_esl_with_one_signature(const uint8_t *data, const uint32_t data_len, + const EFI_GUID *type, const EFI_GUID *owner, + uint8_t *out, size_t *outlen) +{ + EFI_STATUS efi_status; + EFI_SIGNATURE_DATA *sd = NULL; + UINT32 sig_size = sizeof(EFI_SIGNATURE_DATA) - 1 + data_len; - return EFI_SUCCESS; + if (data_len > UINT32_MAX - sizeof(EFI_SIGNATURE_DATA) + 1) + return EFI_INVALID_PARAMETER; + + if (out) { + sd = AllocateZeroPool(sig_size); + if (owner) + CopyMem(sd, owner, sizeof(EFI_GUID)); + CopyMem(sd->SignatureData, data, data_len); + } + + efi_status = fill_esl(sd, 1, type, sig_size, out, outlen); + + if (out) + FreePool(sd); + return efi_status; +} + +EFI_STATUS +variable_create_esl(const EFI_SIGNATURE_DATA *first_sig, const size_t howmany, + const EFI_GUID *type, const UINT32 sig_size, + uint8_t **out, size_t *outlen) +{ + EFI_STATUS efi_status; + + *outlen = 0; + efi_status = fill_esl(first_sig, howmany, type, sig_size, NULL, outlen); + if (efi_status != EFI_BUFFER_TOO_SMALL) + return efi_status; + + *out = AllocateZeroPool(*outlen); + if (!*out) + return EFI_OUT_OF_RESOURCES; + + return fill_esl(first_sig, howmany, type, sig_size, *out, outlen); +} + +EFI_STATUS +variable_create_esl_with_one_signature(const uint8_t* data, const size_t data_len, + const EFI_GUID *type, const EFI_GUID *owner, + uint8_t **out, size_t *outlen) +{ + EFI_STATUS efi_status; + + *outlen = 0; + efi_status = fill_esl_with_one_signature(data, data_len, type, owner, + NULL, outlen); + if (efi_status != EFI_BUFFER_TOO_SMALL) + return efi_status; + + *out = AllocateZeroPool(*outlen); + if (!*out) + return EFI_OUT_OF_RESOURCES; + + return fill_esl_with_one_signature(data, data_len, type, owner, *out, + outlen); } EFI_STATUS @@ -123,8 +188,8 @@ CreateTimeBasedPayload(IN OUT UINTN * DataSize, IN OUT UINT8 ** Data) } EFI_STATUS -SetSecureVariable(CHAR16 *var, UINT8 *Data, UINTN len, EFI_GUID owner, - UINT32 options, int createtimebased) +SetSecureVariable(const CHAR16 * const var, UINT8 *Data, UINTN len, + EFI_GUID owner, UINT32 options, int createtimebased) { EFI_SIGNATURE_LIST *Cert; UINTN DataSize; @@ -137,9 +202,10 @@ SetSecureVariable(CHAR16 *var, UINT8 *Data, UINTN len, EFI_GUID owner, return EFI_SECURITY_VIOLATION; if (createtimebased) { - int ds; - efi_status = variable_create_esl(Data, len, &X509_GUID, NULL, - (void **)&Cert, &ds); + size_t ds; + efi_status = variable_create_esl_with_one_signature( + Data, len, &X509_GUID, NULL, + (uint8_t **)&Cert, &ds); if (EFI_ERROR(efi_status)) { console_print(L"Failed to create %s certificate %d\n", var, efi_status); @@ -159,7 +225,7 @@ SetSecureVariable(CHAR16 *var, UINT8 *Data, UINTN len, EFI_GUID owner, return efi_status; } - efi_status = gRT->SetVariable(var, &owner, + efi_status = gRT->SetVariable((CHAR16 *)var, &owner, EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS | @@ -204,38 +270,86 @@ SETOSIndicationsAndReboot(UINT64 indications) } EFI_STATUS -get_variable_attr(CHAR16 *var, UINT8 **data, UINTN *len, EFI_GUID owner, - UINT32 *attributes) +get_variable_attr(const CHAR16 * const var, UINT8 **data, UINTN *len, + EFI_GUID owner, UINT32 *attributes) { EFI_STATUS efi_status; + if (!len) + return EFI_INVALID_PARAMETER; + *len = 0; - efi_status = gRT->GetVariable(var, &owner, NULL, len, NULL); + efi_status = gRT->GetVariable((CHAR16 *)var, &owner, NULL, len, NULL); if (efi_status != EFI_BUFFER_TOO_SMALL) { if (!EFI_ERROR(efi_status)) /* this should never happen */ return EFI_PROTOCOL_ERROR; return efi_status; } - *data = AllocateZeroPool(*len); + if (!data) + return EFI_INVALID_PARAMETER; + + /* + * Add three zero pad bytes; at least one correctly aligned UCS-2 + * character. + */ + *data = AllocateZeroPool(*len + 3); if (!*data) return EFI_OUT_OF_RESOURCES; - efi_status = gRT->GetVariable(var, &owner, attributes, len, *data); + efi_status = gRT->GetVariable((CHAR16 *)var, &owner, attributes, len, *data); if (EFI_ERROR(efi_status)) { FreePool(*data); *data = NULL; } + return efi_status; } EFI_STATUS -get_variable(CHAR16 *var, UINT8 **data, UINTN *len, EFI_GUID owner) +get_variable(const CHAR16 * const var, UINT8 **data, UINTN *len, EFI_GUID owner) { return get_variable_attr(var, data, len, owner, NULL); } +EFI_STATUS +get_variable_size(const CHAR16 * const var, EFI_GUID owner, UINTN *lenp) +{ + UINTN len = 0; + EFI_STATUS efi_status; + + efi_status = get_variable_attr(var, NULL, &len, owner, NULL); + if (EFI_ERROR(efi_status)) { + if (efi_status == EFI_BUFFER_TOO_SMALL) { + *lenp = len; + return EFI_SUCCESS; + } else if (efi_status == EFI_NOT_FOUND) { + *lenp = 0; + return EFI_SUCCESS; + } + return efi_status; + } + /* + * who knows what this means, but... + */ + *lenp = len; + return efi_status; +} + +EFI_STATUS +set_variable(CHAR16 *var, EFI_GUID owner, UINT32 attributes, + UINTN datasize, void *data) +{ + return gRT->SetVariable(var, &owner, attributes, datasize, data); +} + +EFI_STATUS +del_variable(CHAR16 *var, EFI_GUID owner) +{ + return set_variable(var, owner, 0, 0, ""); +} + EFI_STATUS find_in_esl(UINT8 *Data, UINTN DataSize, UINT8 *key, UINTN keylen) { @@ -254,7 +368,8 @@ find_in_esl(UINT8 *Data, UINTN DataSize, UINT8 *key, UINTN keylen) } EFI_STATUS -find_in_variable_esl(CHAR16* var, EFI_GUID owner, UINT8 *key, UINTN keylen) +find_in_variable_esl(const CHAR16 * const var, EFI_GUID owner, UINT8 *key, + UINTN keylen) { UINTN DataSize = 0; UINT8 *Data = NULL; @@ -305,7 +420,7 @@ variable_is_secureboot(void) } EFI_STATUS -variable_enroll_hash(CHAR16 *var, EFI_GUID owner, +variable_enroll_hash(const CHAR16 * const var, EFI_GUID owner, UINT8 hash[SHA256_DIGEST_SIZE]) { EFI_STATUS efi_status; @@ -330,7 +445,7 @@ variable_enroll_hash(CHAR16 *var, EFI_GUID owner, efi_status = SetSecureVariable(var, sig, sizeof(sig), owner, EFI_VARIABLE_APPEND_WRITE, 0); else - efi_status = gRT->SetVariable(var, &owner, + efi_status = gRT->SetVariable((CHAR16 *)var, &owner, EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_APPEND_WRITE, -- cgit v1.2.3