From 17857eb8b55fa9864bfd71083d9291c74b0bab8e Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Thu, 26 Sep 2013 11:57:59 -0400 Subject: Port MokManager to Linux Foundation loader UI code This is the first stage of porting the MokManager UI to the UI code used by the Linux Foundation UEFI loader. --- lib/Makefile | 28 +++ lib/configtable.c | 144 +++++++++++++++ lib/console.c | 402 ++++++++++++++++++++++++++++++++++++++++ lib/execute.c | 127 +++++++++++++ lib/guid.c | 47 +++++ lib/security_policy.c | 391 +++++++++++++++++++++++++++++++++++++++ lib/shell.c | 57 ++++++ lib/simple_file.c | 501 ++++++++++++++++++++++++++++++++++++++++++++++++++ lib/variables.c | 340 ++++++++++++++++++++++++++++++++++ 9 files changed, 2037 insertions(+) create mode 100644 lib/Makefile create mode 100644 lib/configtable.c create mode 100644 lib/console.c create mode 100644 lib/execute.c create mode 100644 lib/guid.c create mode 100644 lib/security_policy.c create mode 100644 lib/shell.c create mode 100644 lib/simple_file.c create mode 100644 lib/variables.c (limited to 'lib') diff --git a/lib/Makefile b/lib/Makefile new file mode 100644 index 00000000..be5f3542 --- /dev/null +++ b/lib/Makefile @@ -0,0 +1,28 @@ +TARGET = lib.a + +LIBFILES = simple_file.o guid.o console.o execute.o configtable.o shell.o + +ARCH = $(shell uname -m | sed s,i[3456789]86,ia32,) + +EFI_INCLUDE = /usr/include/efi +EFI_INCLUDES = -I$(EFI_INCLUDE) -I$(EFI_INCLUDE)/$(ARCH) -I$(EFI_INCLUDE)/protocol -I../include +EFI_PATH = /usr/lib64/gnuefi + +EFI_CRT_OBJS = $(EFI_PATH)/crt0-efi-$(ARCH).o +EFI_LDS = $(EFI_PATH)/elf_$(ARCH)_efi.lds + +CFLAGS = -ggdb -O0 -fno-stack-protector -fno-strict-aliasing -fpic \ + -fshort-wchar -Wall -mno-red-zone -DBUILD_EFI $(EFI_INCLUDES) +ifeq ($(ARCH),x86_64) + CFLAGS += -DEFI_FUNCTION_WRAPPER -DGNU_EFI_USE_MS_ABI +endif + +lib.a: $(LIBFILES) + ar rcs lib.a $(LIBFILES) + +all: $(TARGET) + +clean: + rm -f lib.a + rm -f $(LIBFILES) + diff --git a/lib/configtable.c b/lib/configtable.c new file mode 100644 index 00000000..735ce8f8 --- /dev/null +++ b/lib/configtable.c @@ -0,0 +1,144 @@ +/* + * Copyright 2013 + * + * see COPYING file + * + * read some platform configuration tables + */ +#include +#include + +#include +#include + +void * +configtable_get_table(EFI_GUID *guid) +{ + int i; + + for (i = 0; i < ST->NumberOfTableEntries; i++) { + EFI_CONFIGURATION_TABLE *CT = &ST->ConfigurationTable[i]; + + if (CompareGuid(guid, &CT->VendorGuid) == 0) { + return CT->VendorTable; + } + } + return NULL; +} + +EFI_IMAGE_EXECUTION_INFO_TABLE * +configtable_get_image_table(void) +{ + return configtable_get_table(&SIG_DB); +} + +EFI_IMAGE_EXECUTION_INFO * +configtable_find_image(const EFI_DEVICE_PATH *DevicePath) +{ + EFI_IMAGE_EXECUTION_INFO_TABLE *t = configtable_get_image_table(); + + if (!t) + return NULL; + + int entries = t->NumberOfImages; + EFI_IMAGE_EXECUTION_INFO *e = t->InformationInfo; + + int i; + for (i = 0; i < entries; i++) { +#ifdef DEBUG_CONFIG + Print(L"InfoSize = %d Action = %d\n", e->InfoSize, e->Action); + + /* print what we have for debugging */ + UINT8 *d = (UINT8 *)e; // + sizeof(UINT32)*2; + 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 += 16; + 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 += 16; + 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 += 16; + 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 += 16; + 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 += 16; + 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]); +#endif + CHAR16 *name = (CHAR16 *)(e->Data); + int skip = 0; + + /* There's a bug in a lot of EFI platforms and they forget to + * put the name here. The only real way of detecting it is to + * look for either a UC16 NULL or ASCII as UC16 */ + if (name[0] == '\0' || (e->Data[1] == 0 && e->Data[3] == 0)) { + skip = StrSize(name); +#ifdef DEBUG_CONFIG + Print(L"FOUND NAME %s (%d)\n", name, skip); +#endif + } + EFI_DEVICE_PATH *dp = (EFI_DEVICE_PATH *)(e->Data + skip), *dpn = dp; + if (dp->Type == 0 || dp->Type > 6 || dp->SubType == 0 + || (((dp->Length[1] << 8) + dp->Length[0]) > e->InfoSize)) { + /* Parse error, table corrupt, bail */ + Print(L"Image Execution Information table corrupt\n"); + break; + } + + UINTN Size; + DevicePathInstance(&dpn, &Size); +#ifdef DEBUG_CONFIG + Print(L"Path: %s\n", DevicePathToStr(dp)); + Print(L"Device Path Size %d\n", Size); +#endif + if (Size > e->InfoSize) { + /* parse error; the platform obviously has a + * corrupted image table; bail */ + Print(L"Image Execution Information table corrupt\n"); + break; + } + + if (CompareMem(dp, DevicePath, Size) == 0) { +#ifdef DEBUG_CONFIG + Print(L"***FOUND\n"); + console_get_keystroke(); +#endif + return e; + } + e = (EFI_IMAGE_EXECUTION_INFO *)((UINT8 *)e + e->InfoSize); + } + +#ifdef DEBUG_CONFIG + Print(L"***NOT FOUND\n"); + console_get_keystroke(); +#endif + + return NULL; +} + +int +configtable_image_is_forbidden(const EFI_DEVICE_PATH *DevicePath) +{ + EFI_IMAGE_EXECUTION_INFO *e = configtable_find_image(DevicePath); + + /* Image may not be in DB if it gets executed successfully If it is, + * and EFI_IMAGE_EXECUTION_INITIALIZED is not set, then the image + * isn't authenticated. If there's no signature, usually + * EFI_IMAGE_EXECUTION_AUTH_UNTESTED is set, if the hash is in dbx, + * EFI_IMAGE_EXECUTION_AUTH_SIG_FOUND is returned, and if the key is + * in dbx, EFI_IMAGE_EXECUTION_AUTH_SIG_FAILED is returned*/ + + if (e && (e->Action == EFI_IMAGE_EXECUTION_AUTH_SIG_FOUND + || e->Action == EFI_IMAGE_EXECUTION_AUTH_SIG_FAILED)) { + /* this means the images signing key is in dbx */ +#ifdef DEBUG_CONFIG + Print(L"SIGNATURE IS IN DBX, FORBIDDING EXECUTION\n"); +#endif + return 1; + } + + return 0; +} diff --git a/lib/console.c b/lib/console.c new file mode 100644 index 00000000..af01f035 --- /dev/null +++ b/lib/console.c @@ -0,0 +1,402 @@ +/* + * Copyright 2012 + * + * see COPYING file + */ +#include +#include + +#include +#include + +static int min(int a, int b) +{ + if (a < b) + return a; + return b; +} + +static int +count_lines(CHAR16 *str_arr[]) +{ + int i = 0; + + while (str_arr[i]) + i++; + return i; +} + +static void +SetMem16(CHAR16 *dst, UINT32 n, CHAR16 c) +{ + int i; + + for (i = 0; i < n/2; i++) { + dst[i] = c; + } +} + +EFI_INPUT_KEY +console_get_keystroke(void) +{ + EFI_INPUT_KEY key; + UINTN EventIndex; + + uefi_call_wrapper(BS->WaitForEvent, 3, 1, &ST->ConIn->WaitForKey, &EventIndex); + uefi_call_wrapper(ST->ConIn->ReadKeyStroke, 2, ST->ConIn, &key); + + return key; +} + +void +console_print_box_at(CHAR16 *str_arr[], int highlight, int start_col, int start_row, int size_cols, int size_rows, int offset, int lines) +{ + int i; + SIMPLE_TEXT_OUTPUT_INTERFACE *co = ST->ConOut; + UINTN rows, cols; + CHAR16 *Line; + + if (lines == 0) + return; + + uefi_call_wrapper(co->QueryMode, 4, co, co->Mode->Mode, &cols, &rows); + + /* last row on screen is unusable without scrolling, so ignore it */ + rows--; + + if (size_rows < 0) + size_rows = rows + size_rows + 1; + if (size_cols < 0) + size_cols = cols + size_cols + 1; + + if (start_col < 0) + start_col = (cols + start_col + 2)/2; + if (start_row < 0) + start_row = (rows + start_row + 2)/2; + if (start_col < 0) + start_col = 0; + if (start_row < 0) + start_row = 0; + + if (start_col > cols || start_row > rows) { + Print(L"Starting Position (%d,%d) is off screen\n", + start_col, start_row); + return; + } + if (size_cols + start_col > cols) + size_cols = cols - start_col; + if (size_rows + start_row > rows) + size_rows = rows - start_row; + + if (lines > size_rows - 2) + lines = size_rows - 2; + + Line = AllocatePool((size_cols+1)*sizeof(CHAR16)); + if (!Line) { + Print(L"Failed Allocation\n"); + return; + } + + SetMem16 (Line, size_cols * 2, BOXDRAW_HORIZONTAL); + + Line[0] = BOXDRAW_DOWN_RIGHT; + Line[size_cols - 1] = BOXDRAW_DOWN_LEFT; + Line[size_cols] = L'\0'; + uefi_call_wrapper(co->SetCursorPosition, 3, co, start_col, start_row); + uefi_call_wrapper(co->OutputString, 2, co, Line); + + int start; + if (offset == 0) + /* middle */ + start = (size_rows - lines)/2 + start_row + offset; + else if (offset < 0) + /* from bottom */ + start = start_row + size_rows - lines + offset - 1; + else + /* from top */ + start = start_row + offset; + + + for (i = start_row + 1; i < size_rows + start_row - 1; i++) { + int line = i - start; + + SetMem16 (Line, size_cols*2, L' '); + Line[0] = BOXDRAW_VERTICAL; + Line[size_cols - 1] = BOXDRAW_VERTICAL; + Line[size_cols] = L'\0'; + if (line >= 0 && line < lines) { + CHAR16 *s = str_arr[line]; + int len = StrLen(s); + int col = (size_cols - 2 - len)/2; + + if (col < 0) + col = 0; + + CopyMem(Line + col + 1, s, min(len, size_cols - 2)*2); + } + if (line >= 0 && line == highlight) + uefi_call_wrapper(co->SetAttribute, 2, co, EFI_LIGHTGRAY | EFI_BACKGROUND_BLACK); + uefi_call_wrapper(co->SetCursorPosition, 3, co, start_col, i); + uefi_call_wrapper(co->OutputString, 2, co, Line); + if (line >= 0 && line == highlight) + uefi_call_wrapper(co->SetAttribute, 2, co, EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE); + + } + SetMem16 (Line, size_cols * 2, BOXDRAW_HORIZONTAL); + Line[0] = BOXDRAW_UP_RIGHT; + Line[size_cols - 1] = BOXDRAW_UP_LEFT; + Line[size_cols] = L'\0'; + uefi_call_wrapper(co->SetCursorPosition, 3, co, start_col, i); + uefi_call_wrapper(co->OutputString, 2, co, Line); + + FreePool (Line); + +} + +void +console_print_box(CHAR16 *str_arr[], int highlight) +{ + SIMPLE_TEXT_OUTPUT_MODE SavedConsoleMode; + SIMPLE_TEXT_OUTPUT_INTERFACE *co = ST->ConOut; + CopyMem(&SavedConsoleMode, co->Mode, sizeof(SavedConsoleMode)); + uefi_call_wrapper(co->EnableCursor, 2, co, FALSE); + uefi_call_wrapper(co->SetAttribute, 2, co, EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE); + + console_print_box_at(str_arr, highlight, 0, 0, -1, -1, 0, + count_lines(str_arr)); + + console_get_keystroke(); + + uefi_call_wrapper(co->EnableCursor, 2, co, SavedConsoleMode.CursorVisible); + + uefi_call_wrapper(co->EnableCursor, 2, co, SavedConsoleMode.CursorVisible); + uefi_call_wrapper(co->SetCursorPosition, 3, co, SavedConsoleMode.CursorColumn, SavedConsoleMode.CursorRow); + uefi_call_wrapper(co->SetAttribute, 2, co, SavedConsoleMode.Attribute); +} + +int +console_select(CHAR16 *title[], CHAR16* selectors[], int start) +{ + SIMPLE_TEXT_OUTPUT_MODE SavedConsoleMode; + SIMPLE_TEXT_OUTPUT_INTERFACE *co = ST->ConOut; + EFI_INPUT_KEY k; + int selector; + int selector_lines = count_lines(selectors); + int selector_max_cols = 0; + int i, offs_col, offs_row, size_cols, size_rows, lines; + int selector_offset; + UINTN cols, rows; + + uefi_call_wrapper(co->QueryMode, 4, co, co->Mode->Mode, &cols, &rows); + + for (i = 0; i < selector_lines; i++) { + int len = StrLen(selectors[i]); + + if (len > selector_max_cols) + selector_max_cols = len; + } + + if (start < 0) + start = 0; + if (start >= selector_lines) + start = selector_lines - 1; + + offs_col = - selector_max_cols - 4; + size_cols = selector_max_cols + 4; + + if (selector_lines > rows - 10) { + int title_lines = count_lines(title); + offs_row = title_lines + 1; + size_rows = rows - 3 - title_lines; + lines = size_rows - 2; + } else { + offs_row = - selector_lines - 4; + size_rows = selector_lines + 2; + lines = selector_lines; + } + + if (start > lines) { + selector = lines; + selector_offset = start - lines; + } else { + selector = start; + selector_offset = 0; + } + + CopyMem(&SavedConsoleMode, co->Mode, sizeof(SavedConsoleMode)); + uefi_call_wrapper(co->EnableCursor, 2, co, FALSE); + uefi_call_wrapper(co->SetAttribute, 2, co, EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE); + + console_print_box_at(title, -1, 0, 0, -1, -1, 1, count_lines(title)); + + console_print_box_at(selectors, selector, offs_col, offs_row, + size_cols, size_rows, 0, lines); + + do { + k = console_get_keystroke(); + + if (k.ScanCode == SCAN_ESC) { + selector = -1; + break; + } + + if (k.ScanCode == SCAN_UP) { + if (selector > 0) + selector--; + else if (selector_offset > 0) + selector_offset--; + } else if (k.ScanCode == SCAN_DOWN) { + if (selector < lines - 1) + selector++; + else if (selector_offset < (selector_lines - lines)) + selector_offset++; + } + + console_print_box_at(&selectors[selector_offset], selector, + offs_col, offs_row, + size_cols, size_rows, 0, lines); + } while (!(k.ScanCode == SCAN_NULL + && k.UnicodeChar == CHAR_CARRIAGE_RETURN)); + + uefi_call_wrapper(co->EnableCursor, 2, co, SavedConsoleMode.CursorVisible); + + uefi_call_wrapper(co->EnableCursor, 2, co, SavedConsoleMode.CursorVisible); + uefi_call_wrapper(co->SetCursorPosition, 3, co, SavedConsoleMode.CursorColumn, SavedConsoleMode.CursorRow); + uefi_call_wrapper(co->SetAttribute, 2, co, SavedConsoleMode.Attribute); + + if (selector < 0) + /* ESC pressed */ + return selector; + return selector + selector_offset; +} + + +int +console_yes_no(CHAR16 *str_arr[]) +{ + return console_select(str_arr, (CHAR16 *[]){ L"No", L"Yes", NULL }, 0); +} + +void +console_alertbox(CHAR16 **title) +{ + console_select(title, (CHAR16 *[]){ L"OK", 0 }, 0); +} + +void +console_errorbox(CHAR16 *err) +{ + CHAR16 **err_arr = (CHAR16 *[]){ + L"ERROR", + L"", + 0, + 0, + }; + + err_arr[2] = err; + + console_alertbox(err_arr); +} + +void +console_notify(CHAR16 *string) +{ + CHAR16 **str_arr = (CHAR16 *[]){ + 0, + 0, + }; + + str_arr[0] = string; + + console_alertbox(str_arr); +} + +#define ARRAY_SIZE(a) (sizeof (a) / sizeof ((a)[0])) + +/* Copy of gnu-efi-3.0 with the added secure boot strings */ +static struct { + EFI_STATUS Code; + WCHAR *Desc; +} error_table[] = { + { EFI_SUCCESS, L"Success"}, + { EFI_LOAD_ERROR, L"Load Error"}, + { EFI_INVALID_PARAMETER, L"Invalid Parameter"}, + { EFI_UNSUPPORTED, L"Unsupported"}, + { EFI_BAD_BUFFER_SIZE, L"Bad Buffer Size"}, + { EFI_BUFFER_TOO_SMALL, L"Buffer Too Small"}, + { EFI_NOT_READY, L"Not Ready"}, + { EFI_DEVICE_ERROR, L"Device Error"}, + { EFI_WRITE_PROTECTED, L"Write Protected"}, + { EFI_OUT_OF_RESOURCES, L"Out of Resources"}, + { EFI_VOLUME_CORRUPTED, L"Volume Corrupt"}, + { EFI_VOLUME_FULL, L"Volume Full"}, + { EFI_NO_MEDIA, L"No Media"}, + { EFI_MEDIA_CHANGED, L"Media changed"}, + { EFI_NOT_FOUND, L"Not Found"}, + { EFI_ACCESS_DENIED, L"Access Denied"}, + { EFI_NO_RESPONSE, L"No Response"}, + { EFI_NO_MAPPING, L"No mapping"}, + { EFI_TIMEOUT, L"Time out"}, + { EFI_NOT_STARTED, L"Not started"}, + { EFI_ALREADY_STARTED, L"Already started"}, + { EFI_ABORTED, L"Aborted"}, + { EFI_ICMP_ERROR, L"ICMP Error"}, + { EFI_TFTP_ERROR, L"TFTP Error"}, + { EFI_PROTOCOL_ERROR, L"Protocol Error"}, + { EFI_INCOMPATIBLE_VERSION, L"Incompatible Version"}, + { EFI_SECURITY_VIOLATION, L"Security Violation"}, + + // warnings + { EFI_WARN_UNKOWN_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"}, + { 0, NULL} +} ; + + +static CHAR16 * +err_string ( + IN EFI_STATUS Status + ) +{ + UINTN Index; + + for (Index = 0; error_table[Index].Desc; Index +=1) { + if (error_table[Index].Code == Status) { + return error_table[Index].Desc; + } + } + + return L""; +} + + +void +console_error(CHAR16 *err, EFI_STATUS status) +{ + CHAR16 **err_arr = (CHAR16 *[]){ + L"ERROR", + L"", + 0, + 0, + }; + CHAR16 str[512]; + + SPrint(str, sizeof(str), L"%s: (%d) %s", err, status, err_string(status)); + + err_arr[2] = str; + + console_alertbox(err_arr); +} + +void +console_reset(void) +{ + SIMPLE_TEXT_OUTPUT_INTERFACE *co = ST->ConOut; + + uefi_call_wrapper(co->Reset, 2, co, TRUE); + /* set mode 0 - required to be 80x25 */ + uefi_call_wrapper(co->SetMode, 2, co, 0); + uefi_call_wrapper(co->ClearScreen, 1, co); +} diff --git a/lib/execute.c b/lib/execute.c new file mode 100644 index 00000000..8d726eb8 --- /dev/null +++ b/lib/execute.c @@ -0,0 +1,127 @@ +/* + * 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 +#include + +EFI_STATUS +generate_path(CHAR16* name, EFI_LOADED_IMAGE *li, EFI_DEVICE_PATH **path, CHAR16 **PathName) +{ + unsigned int pathlen; + EFI_STATUS efi_status = EFI_SUCCESS; + CHAR16 *devpathstr = DevicePathToStr(li->FilePath), + *found = NULL; + int i; + + for (i = 0; i < StrLen(devpathstr); i++) { + if (devpathstr[i] == '/') + devpathstr[i] = '\\'; + if (devpathstr[i] == '\\') + found = &devpathstr[i]; + } + if (!found) { + pathlen = 0; + } else { + while (*(found - 1) == '\\') + --found; + *found = '\0'; + pathlen = StrLen(devpathstr); + } + + if (name[0] != '\\') + pathlen++; + + *PathName = AllocatePool((pathlen + 1 + StrLen(name))*sizeof(CHAR16)); + + if (!*PathName) { + Print(L"Failed to allocate path buffer\n"); + efi_status = EFI_OUT_OF_RESOURCES; + goto error; + } + + StrCpy(*PathName, devpathstr); + + if (name[0] != '\\') + StrCat(*PathName, L"\\"); + StrCat(*PathName, name); + + *path = FileDevicePath(li->DeviceHandle, *PathName); + +error: + FreePool(devpathstr); + + return efi_status; +} + +EFI_STATUS +execute(EFI_HANDLE image, CHAR16 *name) +{ + EFI_STATUS status; + EFI_HANDLE h; + EFI_LOADED_IMAGE *li; + EFI_DEVICE_PATH *devpath; + CHAR16 *PathName; + + status = uefi_call_wrapper(BS->HandleProtocol, 3, image, + &IMAGE_PROTOCOL, &li); + if (status != EFI_SUCCESS) + return status; + + + status = generate_path(name, li, &devpath, &PathName); + if (status != EFI_SUCCESS) + return status; + + status = uefi_call_wrapper(BS->LoadImage, 6, FALSE, image, + devpath, NULL, 0, &h); + if (status != EFI_SUCCESS) + goto out; + + status = uefi_call_wrapper(BS->StartImage, 3, h, NULL, NULL); + uefi_call_wrapper(BS->UnloadImage, 1, h); + + out: + FreePool(PathName); + FreePool(devpath); + return status; +} diff --git a/lib/guid.c b/lib/guid.c new file mode 100644 index 00000000..25db91a7 --- /dev/null +++ b/lib/guid.c @@ -0,0 +1,47 @@ +/* + * Copyright 2012 + * + * see COPYING file + */ + +#include +#include + +#ifndef BUILD_EFI +/* EFI has %g for this, so it's only needed in platform c */ +const char *guid_to_str(EFI_GUID *guid) +{ + static char str[256]; + + sprintf(str, "%08x-%04hx-%04hx-%02hhx%02hhx-%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx", + guid->Data1, guid->Data2, guid->Data3, + guid->Data4[0], guid->Data4[1], guid->Data4[2], + guid->Data4[3], guid->Data4[4], guid->Data4[5], + guid->Data4[6], guid->Data4[7]); + + return str; +} + +void str_to_guid(const char *str, EFI_GUID *guid) +{ + sscanf(str, "%8x-%4hx-%4hx-%2hhx%2hhx-%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx", + &guid->Data1, &guid->Data2, &guid->Data3, + guid->Data4, guid->Data4 + 1, guid->Data4 + 2, + guid->Data4 + 3, guid->Data4 + 4, guid->Data4 + 5, + guid->Data4 + 6, guid->Data4 + 7); +} +#endif + +/* all the necessary guids */ +EFI_GUID GV_GUID = EFI_GLOBAL_VARIABLE; +EFI_GUID SIG_DB = { 0xd719b2cb, 0x3d3a, 0x4596, {0xa3, 0xbc, 0xda, 0xd0, 0xe, 0x67, 0x65, 0x6f }}; + +EFI_GUID X509_GUID = { 0xa5c059a1, 0x94e4, 0x4aa7, {0x87, 0xb5, 0xab, 0x15, 0x5c, 0x2b, 0xf0, 0x72} }; +EFI_GUID RSA2048_GUID = { 0x3c5766e8, 0x269c, 0x4e34, {0xaa, 0x14, 0xed, 0x77, 0x6e, 0x85, 0xb3, 0xb6} }; +EFI_GUID PKCS7_GUID = { 0x4aafd29d, 0x68df, 0x49ee, {0x8a, 0xa9, 0x34, 0x7d, 0x37, 0x56, 0x65, 0xa7} }; +EFI_GUID IMAGE_PROTOCOL = LOADED_IMAGE_PROTOCOL; +EFI_GUID SIMPLE_FS_PROTOCOL = SIMPLE_FILE_SYSTEM_PROTOCOL; +EFI_GUID EFI_CERT_SHA256_GUID = { 0xc1c41626, 0x504c, 0x4092, { 0xac, 0xa9, 0x41, 0xf9, 0x36, 0x93, 0x43, 0x28 } }; +EFI_GUID MOK_OWNER = { 0x605dab50, 0xe046, 0x4300, {0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23} }; +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 } }; diff --git a/lib/security_policy.c b/lib/security_policy.c new file mode 100644 index 00000000..e7becbf4 --- /dev/null +++ b/lib/security_policy.c @@ -0,0 +1,391 @@ +/* + * Copyright 2012 + * + * see COPYING file + * + * Install and remove a platform security2 override policy + */ + +#include +#include + +#include +#include +#include +#include +#include + +#include + +/* + * See the UEFI Platform Initialization manual (Vol2: DXE) for this + */ +struct _EFI_SECURITY2_PROTOCOL; +struct _EFI_SECURITY_PROTOCOL; +typedef struct _EFI_SECURITY2_PROTOCOL EFI_SECURITY2_PROTOCOL; +typedef struct _EFI_SECURITY_PROTOCOL EFI_SECURITY_PROTOCOL; +typedef EFI_DEVICE_PATH EFI_DEVICE_PATH_PROTOCOL; + +typedef EFI_STATUS (EFIAPI *EFI_SECURITY_FILE_AUTHENTICATION_STATE) ( + const EFI_SECURITY_PROTOCOL *This, + UINT32 AuthenticationStatus, + const EFI_DEVICE_PATH_PROTOCOL *File + ); +typedef EFI_STATUS (EFIAPI *EFI_SECURITY2_FILE_AUTHENTICATION) ( + const EFI_SECURITY2_PROTOCOL *This, + const EFI_DEVICE_PATH_PROTOCOL *DevicePath, + VOID *FileBuffer, + UINTN FileSize, + BOOLEAN BootPolicy + ); + +struct _EFI_SECURITY2_PROTOCOL { + EFI_SECURITY2_FILE_AUTHENTICATION FileAuthentication; +}; + +struct _EFI_SECURITY_PROTOCOL { + EFI_SECURITY_FILE_AUTHENTICATION_STATE FileAuthenticationState; +}; + + +static UINT8 *security_policy_esl = NULL; +static UINTN security_policy_esl_len; + +static EFI_STATUS +security_policy_check_mok(void *data, UINTN len) +{ + EFI_STATUS status; + UINT8 hash[SHA256_DIGEST_SIZE]; + UINT32 attr; + UINT8 *VarData; + UINTN VarLen; + + /* first check is MokSBState. If we're in insecure mode, boot + * anyway regardless of dbx contents */ + status = get_variable_attr(L"MokSBState", &VarData, &VarLen, + MOK_OWNER, &attr); + if (status == EFI_SUCCESS) { + UINT8 MokSBState = VarData[0]; + + FreePool(VarData); + if ((attr & EFI_VARIABLE_RUNTIME_ACCESS) == 0 + && MokSBState) + return EFI_SUCCESS; + } + + status = sha256_get_pecoff_digest_mem(data, len, hash); + if (status != EFI_SUCCESS) + return status; + + if (find_in_variable_esl(L"dbx", SIG_DB, hash, SHA256_DIGEST_SIZE) + == EFI_SUCCESS) + /* MOK list cannot override dbx */ + return EFI_SECURITY_VIOLATION; + + status = get_variable_attr(L"MokList", &VarData, &VarLen, MOK_OWNER, + &attr); + if (status != EFI_SUCCESS) + goto check_tmplist; + + FreePool(VarData); + + if (attr & EFI_VARIABLE_RUNTIME_ACCESS) + goto check_tmplist; + + if (find_in_variable_esl(L"MokList", MOK_OWNER, hash, SHA256_DIGEST_SIZE) == EFI_SUCCESS) + return EFI_SUCCESS; + + check_tmplist: + if (security_policy_esl + && find_in_esl(security_policy_esl, security_policy_esl_len, hash, + SHA256_DIGEST_SIZE) == EFI_SUCCESS) + return EFI_SUCCESS; + + return EFI_SECURITY_VIOLATION; +} + +static EFI_SECURITY_FILE_AUTHENTICATION_STATE esfas = NULL; +static EFI_SECURITY2_FILE_AUTHENTICATION es2fa = NULL; + +static EFI_STATUS thunk_security_policy_authentication( + const EFI_SECURITY_PROTOCOL *This, + UINT32 AuthenticationStatus, + const EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +__attribute__((unused)); + +static EFI_STATUS thunk_security2_policy_authentication( + const EFI_SECURITY2_PROTOCOL *This, + const EFI_DEVICE_PATH_PROTOCOL *DevicePath, + VOID *FileBuffer, + UINTN FileSize, + BOOLEAN BootPolicy + ) +__attribute__((unused)); + +static __attribute__((used)) EFI_STATUS +security2_policy_authentication ( + const EFI_SECURITY2_PROTOCOL *This, + const EFI_DEVICE_PATH_PROTOCOL *DevicePath, + VOID *FileBuffer, + UINTN FileSize, + BOOLEAN BootPolicy + ) +{ + EFI_STATUS status, auth; + + /* Chain original security policy */ + + status = uefi_call_wrapper(es2fa, 5, This, DevicePath, FileBuffer, + FileSize, BootPolicy); + + /* if OK, don't bother with MOK check */ + if (status == EFI_SUCCESS) + return status; + + auth = security_policy_check_mok(FileBuffer, FileSize); + + if (auth == EFI_SECURITY_VIOLATION || auth == EFI_ACCESS_DENIED) + /* return previous status, which is the correct one + * for the platform: may be either EFI_ACCESS_DENIED + * or EFI_SECURITY_VIOLATION */ + return status; + + return auth; +} + +static __attribute__((used)) EFI_STATUS +security_policy_authentication ( + const EFI_SECURITY_PROTOCOL *This, + UINT32 AuthenticationStatus, + const EFI_DEVICE_PATH_PROTOCOL *DevicePathConst + ) +{ + EFI_STATUS status, fail_status; + EFI_DEVICE_PATH *DevPath + = DuplicateDevicePath((EFI_DEVICE_PATH *)DevicePathConst), + *OrigDevPath = DevPath; + EFI_HANDLE h; + EFI_FILE *f; + VOID *FileBuffer; + UINTN FileSize; + CHAR16* DevPathStr; + + /* Chain original security policy */ + status = uefi_call_wrapper(esfas, 3, This, AuthenticationStatus, + DevicePathConst); + + /* if OK avoid checking MOK: It's a bit expensive to + * read the whole file in again (esfas already did this) */ + if (status == EFI_SUCCESS) + goto out; + + /* capture failure status: may be either EFI_ACCESS_DENIED or + * EFI_SECURITY_VIOLATION */ + fail_status = status; + + status = uefi_call_wrapper(BS->LocateDevicePath, 3, + &SIMPLE_FS_PROTOCOL, &DevPath, &h); + if (status != EFI_SUCCESS) + goto out; + + DevPathStr = DevicePathToStr(DevPath); + + status = simple_file_open_by_handle(h, DevPathStr, &f, + EFI_FILE_MODE_READ); + FreePool(DevPathStr); + if (status != EFI_SUCCESS) + goto out; + + status = simple_file_read_all(f, &FileSize, &FileBuffer); + simple_file_close(f); + if (status != EFI_SUCCESS) + goto out; + + status = security_policy_check_mok(FileBuffer, FileSize); + FreePool(FileBuffer); + + if (status == EFI_ACCESS_DENIED || status == EFI_SECURITY_VIOLATION) + /* return what the platform originally said */ + status = fail_status; + out: + FreePool(OrigDevPath); + return status; +} + + +/* Nasty: ELF and EFI have different calling conventions. Here is the map for + * calling ELF -> EFI + * + * 1) rdi -> rcx (32 saved) + * 2) rsi -> rdx (32 saved) + * 3) rdx -> r8 ( 32 saved) + * 4) rcx -> r9 (32 saved) + * 5) r8 -> 32(%rsp) (48 saved) + * 6) r9 -> 40(%rsp) (48 saved) + * 7) pad+0(%rsp) -> 48(%rsp) (64 saved) + * 8) pad+8(%rsp) -> 56(%rsp) (64 saved) + * 9) pad+16(%rsp) -> 64(%rsp) (80 saved) + * 10) pad+24(%rsp) -> 72(%rsp) (80 saved) + * 11) pad+32(%rsp) -> 80(%rsp) (96 saved) + + * + * So for a five argument callback, the map is ignore the first two arguments + * and then map (EFI -> ELF) assuming pad = 0. + * + * ARG4 -> ARG1 + * ARG3 -> ARG2 + * ARG5 -> ARG3 + * ARG6 -> ARG4 + * ARG11 -> ARG5 + * + * Calling conventions also differ over volatile and preserved registers in + * MS: RBX, RBP, RDI, RSI, R12, R13, R14, and R15 are considered nonvolatile . + * In ELF: Registers %rbp, %rbx and %r12 through %r15 “belong” to the calling + * function and the called function is required to preserve their values. + * + * This means when accepting a function callback from MS -> ELF, we have to do + * separate preservation on %rdi, %rsi before swizzling the arguments and + * handing off to the ELF function. + */ + +asm ( +".type security2_policy_authentication,@function\n" +"thunk_security2_policy_authentication:\n\t" + "mov 0x28(%rsp), %r10 # ARG5\n\t" + "push %rdi\n\t" + "push %rsi\n\t" + "mov %r10, %rdi\n\t" + "subq $8, %rsp # space for storing stack pad\n\t" + "mov $0x08, %rax\n\t" + "mov $0x10, %r10\n\t" + "and %rsp, %rax\n\t" + "cmovnz %rax, %r11\n\t" + "cmovz %r10, %r11\n\t" + "subq %r11, %rsp\n\t" + "addq $8, %r11\n\t" + "mov %r11, (%rsp)\n\t" +"# five argument swizzle\n\t" + "mov %rdi, %r10\n\t" + "mov %rcx, %rdi\n\t" + "mov %rdx, %rsi\n\t" + "mov %r8, %rdx\n\t" + "mov %r9, %rcx\n\t" + "mov %r10, %r8\n\t" + "callq security2_policy_authentication@PLT\n\t" + "mov (%rsp), %r11\n\t" + "addq %r11, %rsp\n\t" + "pop %rsi\n\t" + "pop %rdi\n\t" + "ret\n" +); + +asm ( +".type security_policy_authentication,@function\n" +"thunk_security_policy_authentication:\n\t" + "push %rdi\n\t" + "push %rsi\n\t" + "subq $8, %rsp # space for storing stack pad\n\t" + "mov $0x08, %rax\n\t" + "mov $0x10, %r10\n\t" + "and %rsp, %rax\n\t" + "cmovnz %rax, %r11\n\t" + "cmovz %r10, %r11\n\t" + "subq %r11, %rsp\n\t" + "addq $8, %r11\n\t" + "mov %r11, (%rsp)\n\t" +"# three argument swizzle\n\t" + "mov %rcx, %rdi\n\t" + "mov %rdx, %rsi\n\t" + "mov %r8, %rdx\n\t" + "callq security_policy_authentication@PLT\n\t" + "mov (%rsp), %r11\n\t" + "addq %r11, %rsp\n\t" + "pop %rsi\n\t" + "pop %rdi\n\t" + "ret\n" +); + +EFI_STATUS +security_policy_install(void) +{ + EFI_SECURITY_PROTOCOL *security_protocol; + EFI_SECURITY2_PROTOCOL *security2_protocol = NULL; + EFI_STATUS status; + + if (esfas) + /* Already Installed */ + return EFI_ALREADY_STARTED; + + /* Don't bother with status here. The call is allowed + * to fail, since SECURITY2 was introduced in PI 1.2.1 + * If it fails, use security2_protocol == NULL as indicator */ + uefi_call_wrapper(BS->LocateProtocol, 3, + &SECURITY2_PROTOCOL_GUID, NULL, + &security2_protocol); + + status = uefi_call_wrapper(BS->LocateProtocol, 3, + &SECURITY_PROTOCOL_GUID, NULL, + &security_protocol); + if (status != EFI_SUCCESS) + /* This one is mandatory, so there's a serious problem */ + return status; + + if (security2_protocol) { + es2fa = security2_protocol->FileAuthentication; + security2_protocol->FileAuthentication = + thunk_security2_policy_authentication; + } + + esfas = security_protocol->FileAuthenticationState; + security_protocol->FileAuthenticationState = + thunk_security_policy_authentication; + + return EFI_SUCCESS; +} + +EFI_STATUS +security_policy_uninstall(void) +{ + EFI_STATUS status; + + if (esfas) { + EFI_SECURITY_PROTOCOL *security_protocol; + + status = uefi_call_wrapper(BS->LocateProtocol, 3, + &SECURITY_PROTOCOL_GUID, NULL, + &security_protocol); + + if (status != EFI_SUCCESS) + return status; + + security_protocol->FileAuthenticationState = esfas; + esfas = NULL; + } else { + /* nothing installed */ + return EFI_NOT_STARTED; + } + + if (es2fa) { + EFI_SECURITY2_PROTOCOL *security2_protocol; + + status = uefi_call_wrapper(BS->LocateProtocol, 3, + &SECURITY2_PROTOCOL_GUID, NULL, + &security2_protocol); + + if (status != EFI_SUCCESS) + return status; + + security2_protocol->FileAuthentication = es2fa; + es2fa = NULL; + } + + return EFI_SUCCESS; +} + +void +security_protocol_set_hashes(unsigned char *esl, int len) +{ + security_policy_esl = esl; + security_policy_esl_len = len; +} diff --git a/lib/shell.c b/lib/shell.c new file mode 100644 index 00000000..51de4e0d --- /dev/null +++ b/lib/shell.c @@ -0,0 +1,57 @@ +/* + * Copyright 2012 + * + * see COPYING file + * + * misc shell helper functions + */ +#include +#include + +#include + +EFI_STATUS +argsplit(EFI_HANDLE image, int *argc, CHAR16*** ARGV) +{ + int i, count = 1; + EFI_STATUS status; + EFI_LOADED_IMAGE *info; + CHAR16 *start; + + *argc = 0; + + status = uefi_call_wrapper(BS->HandleProtocol, 3, image, &LoadedImageProtocol, (VOID **) &info); + if (EFI_ERROR(status)) { + Print(L"Failed to get arguments\n"); + return status; + } + + for (i = 0; i < info->LoadOptionsSize; i += 2) { + CHAR16 *c = (CHAR16 *)(info->LoadOptions + i); + if (*c == L' ' && *(c+1) != '\0') { + (*argc)++; + } + } + + (*argc)++; /* we counted spaces, so add one for initial */ + + *ARGV = AllocatePool(*argc * sizeof(*ARGV)); + if (!*ARGV) { + return EFI_OUT_OF_RESOURCES; + } + (*ARGV)[0] = (CHAR16 *)info->LoadOptions; + for (i = 0; i < info->LoadOptionsSize; i += 2) { + CHAR16 *c = (CHAR16 *)(info->LoadOptions + i); + if (*c == L' ') { + *c = L'\0'; + if (*(c + 1) == '\0') + /* strip trailing space */ + break; + start = c + 1; + (*ARGV)[count++] = start; + } + } + + return EFI_SUCCESS; +} + diff --git a/lib/simple_file.c b/lib/simple_file.c new file mode 100644 index 00000000..0e5ecd25 --- /dev/null +++ b/lib/simple_file.c @@ -0,0 +1,501 @@ +/* + * Copyright 2012 + * + * see COPYING file + */ + +#include +#include + +#include +#include +#include +#include /* for generate_path() */ + +static EFI_GUID IMAGE_PROTOCOL = LOADED_IMAGE_PROTOCOL; +static EFI_GUID SIMPLE_FS_PROTOCOL = SIMPLE_FILE_SYSTEM_PROTOCOL; +static EFI_GUID FILE_INFO = EFI_FILE_INFO_ID; +static EFI_GUID FS_INFO = EFI_FILE_SYSTEM_INFO_ID; + +EFI_STATUS +simple_file_open_by_handle(EFI_HANDLE device, CHAR16 *name, EFI_FILE **file, UINT64 mode) +{ + EFI_STATUS efi_status; + EFI_FILE_IO_INTERFACE *drive; + EFI_FILE *root; + + efi_status = uefi_call_wrapper(BS->HandleProtocol, 3, device, + &SIMPLE_FS_PROTOCOL, &drive); + + if (efi_status != EFI_SUCCESS) { + Print(L"Unable to find simple file protocol (%d)\n", efi_status); + goto error; + } + + efi_status = uefi_call_wrapper(drive->OpenVolume, 2, drive, &root); + + if (efi_status != EFI_SUCCESS) { + Print(L"Failed to open drive volume (%d)\n", efi_status); + goto error; + } + + efi_status = uefi_call_wrapper(root->Open, 5, root, file, name, + mode, 0); + + error: + return efi_status; +} + +EFI_STATUS +simple_file_open(EFI_HANDLE image, CHAR16 *name, EFI_FILE **file, UINT64 mode) +{ + EFI_STATUS efi_status; + EFI_HANDLE device; + EFI_LOADED_IMAGE *li; + EFI_DEVICE_PATH *loadpath = NULL; + CHAR16 *PathName = NULL; + + efi_status = uefi_call_wrapper(BS->HandleProtocol, 3, image, + &IMAGE_PROTOCOL, &li); + + if (efi_status != EFI_SUCCESS) + return simple_file_open_by_handle(image, name, file, mode); + + efi_status = generate_path(name, li, &loadpath, &PathName); + + if (efi_status != EFI_SUCCESS) { + Print(L"Unable to generate load path for %s\n", name); + return efi_status; + } + + device = li->DeviceHandle; + + efi_status = simple_file_open_by_handle(device, PathName, file, mode); + + FreePool(PathName); + FreePool(loadpath); + + return efi_status; +} + +EFI_STATUS +simple_dir_read_all_by_handle(EFI_HANDLE image, EFI_FILE *file, CHAR16* name, EFI_FILE_INFO **entries, + int *count) +{ + EFI_STATUS status; + char buf[4096]; + UINTN size = sizeof(buf); + EFI_FILE_INFO *fi = (void *)buf; + + status = uefi_call_wrapper(file->GetInfo, 4, file, &FILE_INFO, + &size, fi); + if (status != EFI_SUCCESS) { + Print(L"Failed to get file info\n"); + goto out; + } + if ((fi->Attribute & EFI_FILE_DIRECTORY) == 0) { + Print(L"Not a directory %s\n", name); + status = EFI_INVALID_PARAMETER; + goto out; + } + size = 0; + *count = 0; + for (;;) { + UINTN len = sizeof(buf); + status = uefi_call_wrapper(file->Read, 3, file, &len, buf); + if (status != EFI_SUCCESS || len == 0) + break; + (*count)++; + size += len; + } + uefi_call_wrapper(file->SetPosition, 2, file, 0); + + char *ptr = AllocatePool(size); + *entries = (EFI_FILE_INFO *)ptr; + if (!*entries) + return EFI_OUT_OF_RESOURCES; + int i; + for (i = 0; i < *count; i++) { + int len = size; + uefi_call_wrapper(file->Read, 3, file, &len, ptr); + ptr += len; + size -= len; + } + status = EFI_SUCCESS; + out: + simple_file_close(file); + if (status != EFI_SUCCESS && *entries) { + FreePool(*entries); + *entries = NULL; + } + return status; +} + +EFI_STATUS +simple_dir_read_all(EFI_HANDLE image, CHAR16 *name, EFI_FILE_INFO **entries, + int *count) +{ + EFI_FILE *file; + EFI_STATUS status; + + status = simple_file_open(image, name, &file, EFI_FILE_MODE_READ); + if (status != EFI_SUCCESS) { + Print(L"failed to open file %s: %d\n", name, status); + return status; + } + + return simple_dir_read_all_by_handle(image, file, name, entries, count); +} + +EFI_STATUS +simple_file_read_all(EFI_FILE *file, UINTN *size, void **buffer) +{ + EFI_STATUS efi_status; + EFI_FILE_INFO *fi; + char buf[1024]; + + *size = sizeof(buf); + fi = (void *)buf; + + + efi_status = uefi_call_wrapper(file->GetInfo, 4, file, &FILE_INFO, + size, fi); + if (efi_status != EFI_SUCCESS) { + Print(L"Failed to get file info\n"); + return efi_status; + } + + *size = fi->FileSize; + + *buffer = AllocatePool(*size); + if (!*buffer) { + Print(L"Failed to allocate buffer of size %d\n", *size); + return EFI_OUT_OF_RESOURCES; + } + efi_status = uefi_call_wrapper(file->Read, 3, file, size, *buffer); + + return efi_status; +} + + +EFI_STATUS +simple_file_write_all(EFI_FILE *file, UINTN size, void *buffer) +{ + EFI_STATUS efi_status; + + efi_status = uefi_call_wrapper(file->Write, 3, file, &size, buffer); + + return efi_status; +} + +void +simple_file_close(EFI_FILE *file) +{ + uefi_call_wrapper(file->Close, 1, file); +} + +EFI_STATUS +simple_volume_selector(CHAR16 **title, CHAR16 **selected, EFI_HANDLE *h) +{ + UINTN count, i; + EFI_HANDLE *vol_handles = NULL; + EFI_STATUS status; + CHAR16 **entries; + int val; + + uefi_call_wrapper(BS->LocateHandleBuffer, 5, ByProtocol, + &SIMPLE_FS_PROTOCOL, NULL, &count, &vol_handles); + + if (!count || !vol_handles) + return EFI_NOT_FOUND; + + entries = AllocatePool(sizeof(CHAR16 *) * (count+1)); + if (!entries) + return EFI_OUT_OF_RESOURCES; + + for (i = 0; i < count; i++) { + char buf[4096]; + UINTN size = sizeof(buf); + EFI_FILE_SYSTEM_INFO *fi = (void *)buf; + EFI_FILE *root; + CHAR16 *name; + EFI_FILE_IO_INTERFACE *drive; + + status = uefi_call_wrapper(BS->HandleProtocol, 3, + vol_handles[i], + &SIMPLE_FS_PROTOCOL, &drive); + if (status != EFI_SUCCESS || !drive) + continue; + + status = uefi_call_wrapper(drive->OpenVolume, 2, drive, &root); + if (status != EFI_SUCCESS) + continue; + + status = uefi_call_wrapper(root->GetInfo, 4, root, &FS_INFO, + &size, fi); + if (status != EFI_SUCCESS) + continue; + + name = fi->VolumeLabel; + + if (!name || StrLen(name) == 0 || StrCmp(name, L" ") == 0) + name = DevicePathToStr(DevicePathFromHandle(vol_handles[i])); + + entries[i] = AllocatePool((StrLen(name) + 2) * sizeof(CHAR16)); + if (!entries[i]) + break; + StrCpy(entries[i], name); + } + entries[i] = NULL; + + val = console_select(title, entries, 0); + + if (val >= 0) { + *selected = AllocatePool((StrLen(entries[val]) + 1) * sizeof(CHAR16)); + if (*selected) { + StrCpy(*selected , entries[val]); + } + *h = vol_handles[val]; + } else { + *selected = NULL; + *h = 0; + } + + for (i = 0; i < count; i++) { + if (entries[i]) + FreePool(entries[i]); + } + FreePool(entries); + FreePool(vol_handles); + + + return EFI_SUCCESS; +} + +EFI_STATUS +simple_dir_filter(EFI_HANDLE image, CHAR16 *name, CHAR16 *filter, + CHAR16 ***result, int *count, EFI_FILE_INFO **entries) +{ + EFI_STATUS status; + int tot, offs = StrLen(filter), i, c, filtercount = 1; + EFI_FILE_INFO *next; + void *ptr; + CHAR16 *newfilter = AllocatePool((StrLen(filter) + 1) * sizeof(CHAR16)), + **filterarr; + + if (!newfilter) + return EFI_OUT_OF_RESOURCES; + + /* just in case efi ever stops writeable strings */ + StrCpy(newfilter, filter); + + for (i = 0; i < offs; i++) { + if (filter[i] == '|') + filtercount++; + } + filterarr = AllocatePool(filtercount * sizeof(void *)); + if (!filterarr) + return EFI_OUT_OF_RESOURCES; + c = 0; + filterarr[c++] = newfilter; + for (i = 0; i < offs; i++) { + if (filter[i] == '|') { + newfilter[i] = '\0'; + filterarr[c++] = &newfilter[i+1]; + } + } + + *count = 0; + + status = simple_dir_read_all(image, name, entries, &tot); + + if (status != EFI_SUCCESS) + goto out; + ptr = next = *entries; + + for (i = 0; i < tot; i++) { + int len = StrLen(next->FileName); + + for (c = 0; c < filtercount; c++) { + offs = StrLen(filterarr[c]); + + if (StrCmp(&next->FileName[len - offs], filterarr[c]) == 0 + || (next->Attribute & EFI_FILE_DIRECTORY)) { + (*count)++; + break; + } + } + ptr += OFFSET_OF(EFI_FILE_INFO, FileName) + (len + 1)*sizeof(CHAR16); + next = ptr; + } + if (*count) + *result = AllocatePool(((*count) + 1) * sizeof(void *)); + else + *result = AllocatePool(2 * sizeof(void *)); + + *count = 0; + ptr = next = *entries; + + for (i = 0; i < tot; i++) { + int len = StrLen(next->FileName); + + if (StrCmp(next->FileName, L".") == 0) + /* ignore . directory */ + goto next; + + if (next->Attribute & EFI_FILE_DIRECTORY) { + (*result)[(*count)] = next->FileName; + (*result)[(*count)][len] = '/'; + (*result)[(*count)++][len + 1] = '\0'; + goto next; + } + + for (c = 0; c < filtercount; c++) { + offs = StrLen(filterarr[c]); + + if (StrCmp(&next->FileName[len - offs], filterarr[c]) == 0) { + (*result)[(*count)++] = next->FileName; + } else { + continue; + } + break; + } + + next: + if (StrCmp(next->FileName, L"../") == 0) { + /* place .. directory first */ + CHAR16 *tmp = (*result)[(*count) - 1]; + + (*result)[(*count) - 1] = (*result)[0]; + (*result)[0] = tmp; + } + + ptr += OFFSET_OF(EFI_FILE_INFO, FileName) + (len + 1)*sizeof(CHAR16); + next = ptr; + } + if (*count == 0) { + /* no entries at all ... can happen because top level dir has no . or .. */ + (*result)[(*count)++] = L"./"; + } + (*result)[*count] = NULL; + status = EFI_SUCCESS; + + out: + if (status != EFI_SUCCESS) { + if (*entries) + FreePool(*entries); + *entries = NULL; + if (*result) + FreePool(*result); + *result = NULL; + } + return status; +} + +void +simple_file_selector(EFI_HANDLE *im, CHAR16 **title, CHAR16 *name, + CHAR16 *filter, CHAR16 **result) +{ + EFI_STATUS status; + CHAR16 **entries; + EFI_FILE_INFO *dmp; + int count, select, len; + CHAR16 *newname, *selected; + + *result = NULL; + if (!name) + name = L"\\"; + if (!filter) + filter = L""; + if (!*im) { + EFI_HANDLE h; + CHAR16 *volname; + + simple_volume_selector(title, &volname, &h); + if (!volname) + return; + FreePool(volname); + *im = h; + } + + newname = AllocatePool((StrLen(name) + 1)*sizeof(CHAR16)); + if (!newname) + return; + + StrCpy(newname, name); + name = newname; + + redo: + status = simple_dir_filter(*im, name, filter, &entries, &count, &dmp); + + if (status != EFI_SUCCESS) + goto out_free_name; + + select = console_select(title, entries, 0); + if (select < 0) + /* ESC key */ + goto out_free; + selected = entries[select]; + FreePool(entries); + entries = NULL; + /* note that memory used by selected is valid until dmp is freed */ + len = StrLen(selected); + if (selected[len - 1] == '/') { + CHAR16 *newname; + + /* stay where we are */ + if (StrCmp(selected, L"./") == 0) { + FreePool(dmp); + goto redo; + } else if (StrCmp(selected, L"../") == 0) { + int i; + + i = StrLen(name) - 1; + + + for (i = StrLen(name); i > 0; --i) { + if (name[i] == '\\') + break; + } + if (i == 0) + i = 1; + + if (StrCmp(name, L"\\") != 0 + && StrCmp(&name[i], L"..") != 0) { + name[i] = '\0'; + FreePool(dmp); + goto redo; + } + } + newname = AllocatePool((StrLen(name) + len + 2)*sizeof(CHAR16)); + if (!newname) + goto out_free; + StrCpy(newname, name); + + if (name[StrLen(name) - 1] != '\\') + StrCat(newname, L"\\"); + StrCat(newname, selected); + /* remove trailing / */ + newname[StrLen(newname) - 1] = '\0'; + + FreePool(dmp); + FreePool(name); + name = newname; + + goto redo; + } + *result = AllocatePool((StrLen(name) + len + 2)*sizeof(CHAR16)); + if (*result) { + StrCpy(*result, name); + if (name[StrLen(name) - 1] != '\\') + StrCat(*result, L"\\"); + StrCat(*result, selected); + } + + out_free: + FreePool(dmp); + if (entries) + FreePool(entries); + out_free_name: + FreePool(name); +} diff --git a/lib/variables.c b/lib/variables.c new file mode 100644 index 00000000..9db64809 --- /dev/null +++ b/lib/variables.c @@ -0,0 +1,340 @@ +/* + * 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 + +#include +#include +#include +#include +#include + +EFI_STATUS +variable_create_esl(void *cert, int cert_len, EFI_GUID *type, EFI_GUID *owner, + void **out, int *outlen) +{ + *outlen = cert_len + sizeof(EFI_SIGNATURE_LIST) + sizeof(EFI_GUID); + + *out = AllocateZeroPool(*outlen); + if (!*out) + return EFI_OUT_OF_RESOURCES; + + EFI_SIGNATURE_LIST *sl = *out; + + sl->SignatureHeaderSize = 0; + sl->SignatureType = *type; + sl->SignatureSize = cert_len + sizeof(EFI_GUID); + sl->SignatureListSize = *outlen; + + EFI_SIGNATURE_DATA *sd = *out + sizeof(EFI_SIGNATURE_LIST); + + if (owner) + sd->SignatureOwner = *owner; + + CopyMem(sd->SignatureData, cert, cert_len); + + return EFI_SUCCESS; +} + + +EFI_STATUS +CreateTimeBasedPayload ( + IN OUT UINTN *DataSize, + IN OUT UINT8 **Data + ) +{ + EFI_STATUS Status; + UINT8 *NewData; + UINT8 *Payload; + UINTN PayloadSize; + EFI_VARIABLE_AUTHENTICATION_2 *DescriptorData; + UINTN DescriptorSize; + EFI_TIME Time; + EFI_GUID efi_cert_type = EFI_CERT_TYPE_PKCS7_GUID; + + if (Data == NULL || DataSize == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // In Setup mode or Custom mode, the variable does not need to be signed but the + // parameters to the SetVariable() call still need to be prepared as authenticated + // variable. So we create EFI_VARIABLE_AUTHENTICATED_2 descriptor without certificate + // data in it. + // + Payload = *Data; + PayloadSize = *DataSize; + + DescriptorSize = OFFSET_OF(EFI_VARIABLE_AUTHENTICATION_2, AuthInfo) + OFFSET_OF(WIN_CERTIFICATE_UEFI_GUID, CertData); + NewData = (UINT8*) AllocateZeroPool (DescriptorSize + PayloadSize); + if (NewData == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + if ((Payload != NULL) && (PayloadSize != 0)) { + CopyMem (NewData + DescriptorSize, Payload, PayloadSize); + } + + DescriptorData = (EFI_VARIABLE_AUTHENTICATION_2 *) (NewData); + + ZeroMem (&Time, sizeof (EFI_TIME)); + Status = uefi_call_wrapper(RT->GetTime,2, &Time, NULL); + if (EFI_ERROR (Status)) { + FreePool(NewData); + return Status; + } + Time.Pad1 = 0; + Time.Nanosecond = 0; + Time.TimeZone = 0; + Time.Daylight = 0; + Time.Pad2 = 0; + CopyMem (&DescriptorData->TimeStamp, &Time, sizeof (EFI_TIME)); + + DescriptorData->AuthInfo.Hdr.dwLength = OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID, CertData); + DescriptorData->AuthInfo.Hdr.wRevision = 0x0200; + DescriptorData->AuthInfo.Hdr.wCertificateType = WIN_CERT_TYPE_EFI_GUID; + DescriptorData->AuthInfo.CertType = efi_cert_type; + + /* we're expecting an EFI signature list, so don't free the input since + * it might not be in a pool */ +#if 0 + if (Payload != NULL) { + FreePool(Payload); + } +#endif + + *DataSize = DescriptorSize + PayloadSize; + *Data = NewData; + return EFI_SUCCESS; +} + +EFI_STATUS +SetSecureVariable(CHAR16 *var, UINT8 *Data, UINTN len, EFI_GUID owner, + UINT32 options, int createtimebased) +{ + EFI_SIGNATURE_LIST *Cert; + UINTN DataSize; + EFI_STATUS efi_status; + + /* Microsoft request: Bugs in some UEFI platforms mean that PK or any + * other secure variable can be updated or deleted programmatically, + * so prevent */ + if (!variable_is_setupmode()) + return EFI_SECURITY_VIOLATION; + + if (createtimebased) { + int ds; + efi_status = variable_create_esl(Data, len, &X509_GUID, NULL, + (void **)&Cert, &ds); + if (efi_status != EFI_SUCCESS) { + Print(L"Failed to create %s certificate %d\n", var, efi_status); + return efi_status; + } + + DataSize = ds; + } else { + /* we expect an efi signature list rather than creating it */ + Cert = (EFI_SIGNATURE_LIST *)Data; + DataSize = len; + } + efi_status = CreateTimeBasedPayload(&DataSize, (UINT8 **)&Cert); + if (efi_status != EFI_SUCCESS) { + Print(L"Failed to create time based payload %d\n", efi_status); + return efi_status; + } + + efi_status = uefi_call_wrapper(RT->SetVariable, 5, var, &owner, + EFI_VARIABLE_NON_VOLATILE + | EFI_VARIABLE_RUNTIME_ACCESS + | EFI_VARIABLE_BOOTSERVICE_ACCESS + | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS + | options, + DataSize, Cert); + + return efi_status; +} + +UINT64 +GetOSIndications(void) +{ + UINT64 indications; + UINTN DataSize = sizeof(indications); + EFI_STATUS efi_status; + + efi_status = uefi_call_wrapper(RT->GetVariable, 5, L"OsIndicationsSupported", &GV_GUID, NULL, &DataSize, &indications); + if (efi_status != EFI_SUCCESS) + return 0; + + return indications; +} + +EFI_STATUS +SETOSIndicationsAndReboot(UINT64 indications) +{ + UINTN DataSize = sizeof(indications); + EFI_STATUS efi_status; + + efi_status = uefi_call_wrapper(RT->SetVariable, 5, L"OsIndications", + &GV_GUID, + EFI_VARIABLE_NON_VOLATILE + | EFI_VARIABLE_RUNTIME_ACCESS + | EFI_VARIABLE_BOOTSERVICE_ACCESS, + DataSize, &indications); + + if (efi_status != EFI_SUCCESS) + return efi_status; + + uefi_call_wrapper(RT->ResetSystem, 4, EfiResetWarm, EFI_SUCCESS, 0, NULL); + /* does not return */ + + return EFI_SUCCESS; +} + +EFI_STATUS +get_variable_attr(CHAR16 *var, UINT8 **data, UINTN *len, EFI_GUID owner, + UINT32 *attributes) +{ + EFI_STATUS efi_status; + + *len = 0; + + efi_status = uefi_call_wrapper(RT->GetVariable, 5, var, &owner, + NULL, len, NULL); + if (efi_status != EFI_BUFFER_TOO_SMALL) + return efi_status; + + *data = AllocateZeroPool(*len); + if (!data) + return EFI_OUT_OF_RESOURCES; + + efi_status = uefi_call_wrapper(RT->GetVariable, 5, var, &owner, + attributes, len, *data); + + if (efi_status != EFI_SUCCESS) { + FreePool(*data); + *data = NULL; + } + return efi_status; +} + +EFI_STATUS +get_variable(CHAR16 *var, UINT8 **data, UINTN *len, EFI_GUID owner) +{ + return get_variable_attr(var, data, len, owner, NULL); +} + +EFI_STATUS +find_in_esl(UINT8 *Data, UINTN DataSize, UINT8 *key, UINTN keylen) +{ + EFI_SIGNATURE_LIST *CertList; + + certlist_for_each_certentry(CertList, Data, DataSize, DataSize) { + if (CertList->SignatureSize != keylen + sizeof(EFI_GUID)) + continue; + EFI_SIGNATURE_DATA *Cert; + + certentry_for_each_cert(Cert, CertList) + if (CompareMem (Cert->SignatureData, key, keylen) == 0) + return EFI_SUCCESS; + } + return EFI_NOT_FOUND; +} + +EFI_STATUS +find_in_variable_esl(CHAR16* var, EFI_GUID owner, UINT8 *key, UINTN keylen) +{ + UINTN DataSize; + UINT8 *Data; + EFI_STATUS status; + + status = get_variable(var, &Data, &DataSize, owner); + if (status != EFI_SUCCESS) + return status; + + status = find_in_esl(Data, DataSize, key, keylen); + + FreePool(Data); + + return status; +} + +int +variable_is_setupmode(void) +{ + /* set to 1 because we return true if SetupMode doesn't exist */ + UINT8 SetupMode = 1; + UINTN DataSize = sizeof(SetupMode); + + uefi_call_wrapper(RT->GetVariable, 5, L"SetupMode", &GV_GUID, NULL, + &DataSize, &SetupMode); + + return SetupMode; +} + +int +variable_is_secureboot(void) +{ + /* return false if variable doesn't exist */ + UINT8 SecureBoot = 0; + UINTN DataSize; + + DataSize = sizeof(SecureBoot); + uefi_call_wrapper(RT->GetVariable, 5, L"SecureBoot", &GV_GUID, NULL, + &DataSize, &SecureBoot); + + return SecureBoot; +} + +EFI_STATUS +variable_enroll_hash(CHAR16 *var, EFI_GUID owner, + UINT8 hash[SHA256_DIGEST_SIZE]) +{ + EFI_STATUS status; + + if (find_in_variable_esl(var, owner, hash, SHA256_DIGEST_SIZE) + == EFI_SUCCESS) + /* hash already present */ + return EFI_ALREADY_STARTED; + + UINT8 sig[sizeof(EFI_SIGNATURE_LIST) + sizeof(EFI_SIGNATURE_DATA) - 1 + SHA256_DIGEST_SIZE]; + EFI_SIGNATURE_LIST *l = (void *)sig; + EFI_SIGNATURE_DATA *d = (void *)sig + sizeof(EFI_SIGNATURE_LIST); + SetMem(sig, 0, sizeof(sig)); + l->SignatureType = EFI_CERT_SHA256_GUID; + l->SignatureListSize = sizeof(sig); + l->SignatureSize = 16 +32; /* UEFI defined */ + CopyMem(&d->SignatureData, hash, SHA256_DIGEST_SIZE); + d->SignatureOwner = MOK_OWNER; + + if (CompareGuid(&owner, &SIG_DB) == 0) + status = SetSecureVariable(var, sig, sizeof(sig), owner, + EFI_VARIABLE_APPEND_WRITE, 0); + else + status = uefi_call_wrapper(RT->SetVariable, 5, var, &owner, + EFI_VARIABLE_NON_VOLATILE + | EFI_VARIABLE_BOOTSERVICE_ACCESS + | EFI_VARIABLE_APPEND_WRITE, + sizeof(sig), sig); + return status; +} -- cgit v1.2.3 From b1a00240ab3d7cb4e20fbc020e09c7b17972f479 Mon Sep 17 00:00:00 2001 From: Gary Ching-Pang Lin Date: Thu, 26 Sep 2013 11:58:01 -0400 Subject: simple_file: Allocate buffers for file entries The dir filter appends L'/' to the directory entries without allocating a new buffer, and this could crash the whole program. --- lib/simple_file.c | 42 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 34 insertions(+), 8 deletions(-) (limited to 'lib') diff --git a/lib/simple_file.c b/lib/simple_file.c index 0e5ecd25..e2882728 100644 --- a/lib/simple_file.c +++ b/lib/simple_file.c @@ -344,9 +344,12 @@ simple_dir_filter(EFI_HANDLE image, CHAR16 *name, CHAR16 *filter, goto next; if (next->Attribute & EFI_FILE_DIRECTORY) { - (*result)[(*count)] = next->FileName; - (*result)[(*count)][len] = '/'; - (*result)[(*count)++][len + 1] = '\0'; + (*result)[(*count)] = PoolPrint(L"%s/", next->FileName); + if (!(*result)[(*count)]) { + Print(L"Failed to allocate buffer"); + return EFI_OUT_OF_RESOURCES; + } + (*count)++; goto next; } @@ -354,7 +357,12 @@ simple_dir_filter(EFI_HANDLE image, CHAR16 *name, CHAR16 *filter, offs = StrLen(filterarr[c]); if (StrCmp(&next->FileName[len - offs], filterarr[c]) == 0) { - (*result)[(*count)++] = next->FileName; + (*result)[(*count)] = StrDuplicate(next->FileName); + if (!(*result)[(*count)]) { + Print(L"Failed to allocate buffer"); + return EFI_OUT_OF_RESOURCES; + } + (*count)++; } else { continue; } @@ -362,7 +370,7 @@ simple_dir_filter(EFI_HANDLE image, CHAR16 *name, CHAR16 *filter, } next: - if (StrCmp(next->FileName, L"../") == 0) { + if (StrCmp(next->FileName, L"..") == 0) { /* place .. directory first */ CHAR16 *tmp = (*result)[(*count) - 1]; @@ -392,6 +400,15 @@ simple_dir_filter(EFI_HANDLE image, CHAR16 *name, CHAR16 *filter, return status; } +static void +free_entries(CHAR16 **entries, int count) +{ + int i; + + for (i = 0; i Date: Thu, 26 Sep 2013 11:58:01 -0400 Subject: Make EFI_PATH easily resettable from the build command line. Signed-off-by: Peter Jones --- Makefile | 4 ++-- lib/Makefile | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/Makefile b/Makefile index 134d7299..868fb958 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,7 @@ LIB_PATH = /usr/lib64 EFI_INCLUDE = /usr/include/efi EFI_INCLUDES = -nostdinc -ICryptlib -ICryptlib/Include -I$(EFI_INCLUDE) -I$(EFI_INCLUDE)/$(ARCH) -I$(EFI_INCLUDE)/protocol -EFI_PATH = /usr/lib64/gnuefi +EFI_PATH := /usr/lib64/gnuefi LIB_GCC = $(shell $(CC) -print-libgcc-file-name) EFI_LIBS = -lefi -lgnuefi --start-group Cryptlib/libcryptlib.a Cryptlib/OpenSSL/libopenssl.a --end-group $(LIB_GCC) @@ -88,7 +88,7 @@ Cryptlib/OpenSSL/libopenssl.a: $(MAKE) -C Cryptlib/OpenSSL lib/lib.a: - $(MAKE) -C lib + $(MAKE) -C lib EFI_PATH=$(EFI_PATH) %.efi: %.so objcopy -j .text -j .sdata -j .data \ diff --git a/lib/Makefile b/lib/Makefile index be5f3542..43907005 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -6,7 +6,6 @@ ARCH = $(shell uname -m | sed s,i[3456789]86,ia32,) EFI_INCLUDE = /usr/include/efi EFI_INCLUDES = -I$(EFI_INCLUDE) -I$(EFI_INCLUDE)/$(ARCH) -I$(EFI_INCLUDE)/protocol -I../include -EFI_PATH = /usr/lib64/gnuefi EFI_CRT_OBJS = $(EFI_PATH)/crt0-efi-$(ARCH).o EFI_LDS = $(EFI_PATH)/elf_$(ARCH)_efi.lds -- cgit v1.2.3 From 53862ddace32172c364b620afbd93603ac734b54 Mon Sep 17 00:00:00 2001 From: Gary Ching-Pang Lin Date: Thu, 26 Sep 2013 11:58:02 -0400 Subject: Merge signature.h into efiauthenticated.h and guid.h Conflicts: shim.c --- Makefile | 4 ++-- MokManager.c | 19 ++++++++++--------- include/guid.h | 1 + lib/guid.c | 1 + shim.c | 20 +++++++++++--------- signature.h | 43 ------------------------------------------- 6 files changed, 25 insertions(+), 63 deletions(-) delete mode 100644 signature.h (limited to 'lib') diff --git a/Makefile b/Makefile index 83b3df95..031e27ff 100644 --- a/Makefile +++ b/Makefile @@ -38,7 +38,7 @@ VERSION = 0.4 TARGET = shim.efi MokManager.efi.signed fallback.efi.signed OBJS = shim.o netboot.o cert.o dbx.o KEYS = shim_cert.h ocsp.* ca.* shim.crt shim.csr shim.p12 shim.pem shim.key -SOURCES = shim.c shim.h netboot.c signature.h include/PeImage.h include/wincert.h +SOURCES = shim.c shim.h netboot.c include/PeImage.h include/wincert.h MOK_OBJS = MokManager.o PasswordCrypt.o crypt_blowfish.o MOK_SOURCES = MokManager.c shim.h console_control.h PasswordCrypt.c PasswordCrypt.h crypt_blowfish.c crypt_blowfish.h FALLBACK_OBJS = fallback.o @@ -71,7 +71,7 @@ cert.o : cert.S dbx.o : dbx.S $(CC) $(CFLAGS) -c -o $@ $< -shim.so: $(OBJS) Cryptlib/libcryptlib.a Cryptlib/OpenSSL/libopenssl.a +shim.so: $(OBJS) Cryptlib/libcryptlib.a Cryptlib/OpenSSL/libopenssl.a lib/lib.a $(LD) -o $@ $(LDFLAGS) $^ $(EFI_LIBS) fallback.o: $(FALLBACK_SRCS) diff --git a/MokManager.c b/MokManager.c index f6bc6c28..b01c65ec 100644 --- a/MokManager.c +++ b/MokManager.c @@ -4,12 +4,13 @@ #include #include "console_control.h" #include "shim.h" -#include "signature.h" #include "PeImage.h" #include "PasswordCrypt.h" -#include "include/console.h" -#include "include/simple_file.h" +#include "guid.h" +#include "console.h" +#include "simple_file.h" +#include "efiauthenticated.h" #define PASSWORD_MAX 256 #define PASSWORD_MIN 1 @@ -115,8 +116,8 @@ done: static UINT32 count_keys(void *Data, UINTN DataSize) { EFI_SIGNATURE_LIST *CertList = Data; - EFI_GUID CertType = EfiCertX509Guid; - EFI_GUID HashType = EfiHashSha256Guid; + EFI_GUID CertType = X509_GUID; + EFI_GUID HashType = EFI_CERT_SHA256_GUID; UINTN dbsize = DataSize; UINT32 MokNum = 0; @@ -152,8 +153,8 @@ static MokListNode *build_mok_list(UINT32 num, void *Data, UINTN DataSize) { MokListNode *list; EFI_SIGNATURE_LIST *CertList = Data; EFI_SIGNATURE_DATA *Cert; - EFI_GUID CertType = EfiCertX509Guid; - EFI_GUID HashType = EfiHashSha256Guid; + EFI_GUID CertType = X509_GUID; + EFI_GUID HashType = EFI_CERT_SHA256_GUID; UINTN dbsize = DataSize; UINTN count = 0; @@ -1271,7 +1272,7 @@ static EFI_STATUS enroll_file (void *data, UINTN datasize, BOOLEAN hash) goto out; CertList = mokbuffer; - CertList->SignatureType = EfiHashSha256Guid; + CertList->SignatureType = EFI_CERT_SHA256_GUID; CertList->SignatureSize = 16 + SHA256_DIGEST_SIZE; CertData = (EFI_SIGNATURE_DATA *)(((UINT8 *)mokbuffer) + sizeof(EFI_SIGNATURE_LIST)); @@ -1285,7 +1286,7 @@ static EFI_STATUS enroll_file (void *data, UINTN datasize, BOOLEAN hash) goto out; CertList = mokbuffer; - CertList->SignatureType = EfiCertX509Guid; + CertList->SignatureType = X509_GUID; CertList->SignatureSize = 16 + datasize; memcpy(mokbuffer + sizeof(EFI_SIGNATURE_LIST) + 16, data, diff --git a/include/guid.h b/include/guid.h index 10f865ad..3c58be0b 100644 --- a/include/guid.h +++ b/include/guid.h @@ -12,6 +12,7 @@ extern EFI_GUID RSA2048_GUID; extern EFI_GUID PKCS7_GUID; extern EFI_GUID IMAGE_PROTOCOL; extern EFI_GUID SIMPLE_FS_PROTOCOL; +extern EFI_GUID EFI_CERT_SHA1_GUID; extern EFI_GUID EFI_CERT_SHA256_GUID; extern EFI_GUID MOK_OWNER; extern EFI_GUID SECURITY_PROTOCOL_GUID; diff --git a/lib/guid.c b/lib/guid.c index 25db91a7..56ec952b 100644 --- a/lib/guid.c +++ b/lib/guid.c @@ -41,6 +41,7 @@ EFI_GUID RSA2048_GUID = { 0x3c5766e8, 0x269c, 0x4e34, {0xaa, 0x14, 0xed, 0x77, 0 EFI_GUID PKCS7_GUID = { 0x4aafd29d, 0x68df, 0x49ee, {0x8a, 0xa9, 0x34, 0x7d, 0x37, 0x56, 0x65, 0xa7} }; EFI_GUID IMAGE_PROTOCOL = LOADED_IMAGE_PROTOCOL; EFI_GUID SIMPLE_FS_PROTOCOL = SIMPLE_FILE_SYSTEM_PROTOCOL; +EFI_GUID EFI_CERT_SHA1_GUID = { 0x826ca512, 0xcf10, 0x4ac9, {0xb1, 0x87, 0xbe, 0x1, 0x49, 0x66, 0x31, 0xbd }}; EFI_GUID EFI_CERT_SHA256_GUID = { 0xc1c41626, 0x504c, 0x4092, { 0xac, 0xa9, 0x41, 0xf9, 0x36, 0x93, 0x43, 0x28 } }; EFI_GUID MOK_OWNER = { 0x605dab50, 0xe046, 0x4300, {0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23} }; EFI_GUID SECURITY_PROTOCOL_GUID = { 0xA46423E3, 0x4617, 0x49f1, {0xB9, 0xFF, 0xD1, 0xBF, 0xA9, 0x11, 0x58, 0x39 } }; diff --git a/shim.c b/shim.c index e9e67710..9ffc94a6 100644 --- a/shim.c +++ b/shim.c @@ -38,11 +38,13 @@ #include #include "PeImage.h" #include "shim.h" -#include "signature.h" #include "netboot.h" #include "shim_cert.h" #include "ucs2.h" +#include "guid.h" +#include "efiauthenticated.h" + #define FALLBACK L"\\fallback.efi" #define MOK_MANAGER L"\\MokManager.efi" @@ -228,7 +230,7 @@ static CHECK_STATUS check_db_cert_in_ram(EFI_SIGNATURE_LIST *CertList, EFI_SIGNATURE_DATA *Cert; UINTN CertCount, Index; BOOLEAN IsFound = FALSE; - EFI_GUID CertType = EfiCertX509Guid; + EFI_GUID CertType = X509_GUID; while ((dbsize > 0) && (dbsize >= CertList->SignatureListSize)) { if (CompareGuid (&CertList->SignatureType, &CertType) == 0) { @@ -364,11 +366,11 @@ static EFI_STATUS check_blacklist (WIN_CERTIFICATE_EFI_PKCS *cert, EFI_SIGNATURE_LIST *dbx = (EFI_SIGNATURE_LIST *)vendor_dbx; if (check_db_hash_in_ram(dbx, vendor_dbx_size, sha256hash, - SHA256_DIGEST_SIZE, EfiHashSha256Guid) == + SHA256_DIGEST_SIZE, EFI_CERT_SHA256_GUID) == DATA_FOUND) return EFI_ACCESS_DENIED; if (check_db_hash_in_ram(dbx, vendor_dbx_size, sha1hash, - SHA1_DIGEST_SIZE, EfiHashSha1Guid) == + SHA1_DIGEST_SIZE, EFI_CERT_SHA1_GUID) == DATA_FOUND) return EFI_ACCESS_DENIED; if (check_db_cert_in_ram(dbx, vendor_dbx_size, cert, @@ -376,10 +378,10 @@ static EFI_STATUS check_blacklist (WIN_CERTIFICATE_EFI_PKCS *cert, return EFI_ACCESS_DENIED; if (check_db_hash(L"dbx", secure_var, sha256hash, SHA256_DIGEST_SIZE, - EfiHashSha256Guid) == DATA_FOUND) + EFI_CERT_SHA256_GUID) == DATA_FOUND) return EFI_ACCESS_DENIED; if (check_db_hash(L"dbx", secure_var, sha1hash, SHA1_DIGEST_SIZE, - EfiHashSha1Guid) == DATA_FOUND) + EFI_CERT_SHA1_GUID) == DATA_FOUND) return EFI_ACCESS_DENIED; if (check_db_cert(L"dbx", secure_var, cert, sha256hash) == DATA_FOUND) return EFI_ACCESS_DENIED; @@ -397,13 +399,13 @@ static EFI_STATUS check_whitelist (WIN_CERTIFICATE_EFI_PKCS *cert, EFI_GUID shim_var = SHIM_LOCK_GUID; if (check_db_hash(L"db", secure_var, sha256hash, SHA256_DIGEST_SIZE, - EfiHashSha256Guid) == DATA_FOUND) + EFI_CERT_SHA256_GUID) == DATA_FOUND) return EFI_SUCCESS; if (check_db_hash(L"db", secure_var, sha1hash, SHA1_DIGEST_SIZE, - EfiHashSha1Guid) == DATA_FOUND) + EFI_CERT_SHA1_GUID) == DATA_FOUND) return EFI_SUCCESS; if (check_db_hash(L"MokList", shim_var, sha256hash, SHA256_DIGEST_SIZE, - EfiHashSha256Guid) == DATA_FOUND) + EFI_CERT_SHA256_GUID) == DATA_FOUND) return EFI_SUCCESS; if (check_db_cert(L"db", secure_var, cert, sha256hash) == DATA_FOUND) return EFI_SUCCESS; diff --git a/signature.h b/signature.h deleted file mode 100644 index 722dbe64..00000000 --- a/signature.h +++ /dev/null @@ -1,43 +0,0 @@ -#define SHA256_DIGEST_SIZE 32 - -EFI_GUID EfiHashSha1Guid = { 0x826ca512, 0xcf10, 0x4ac9, {0xb1, 0x87, 0xbe, 0x1, 0x49, 0x66, 0x31, 0xbd }}; -EFI_GUID EfiHashSha256Guid = { 0xc1c41626, 0x504c, 0x4092, {0xac, 0xa9, 0x41, 0xf9, 0x36, 0x93, 0x43, 0x28 }}; -EFI_GUID EfiCertX509Guid = { 0xa5c059a1, 0x94e4, 0x4aa7, {0x87, 0xb5, 0xab, 0x15, 0x5c, 0x2b, 0xf0, 0x72 }}; - -typedef struct { - /// - /// An identifier which identifies the agent which added the signature to the list. - /// - EFI_GUID SignatureOwner; - /// - /// The format of the signature is defined by the SignatureType. - /// - UINT8 SignatureData[1]; -} __attribute__ ((packed)) EFI_SIGNATURE_DATA; - -typedef struct { - /// - /// Type of the signature. GUID signature types are defined in below. - /// - EFI_GUID SignatureType; - /// - /// Total size of the signature list, including this header. - /// - UINT32 SignatureListSize; - /// - /// Size of the signature header which precedes the array of signatures. - /// - UINT32 SignatureHeaderSize; - /// - /// Size of each signature. - /// - UINT32 SignatureSize; - /// - /// Header before the array of signatures. The format of this header is specified - /// by the SignatureType. - /// UINT8 SignatureHeader[SignatureHeaderSize]; - /// - /// An array of signatures. Each signature is SignatureSize bytes in length. - /// EFI_SIGNATURE_DATA Signatures[][SignatureSize]; - /// -} __attribute__ ((packed)) EFI_SIGNATURE_LIST; -- cgit v1.2.3 From 7f0208a0f93ac83635e1d5971387e5fbfdaaf734 Mon Sep 17 00:00:00 2001 From: Gary Ching-Pang Lin Date: Thu, 26 Sep 2013 11:58:02 -0400 Subject: Merge variable retrieving functions --- MokManager.c | 34 +++-------------------- include/variables.h | 2 +- lib/Makefile | 2 +- lib/variables.c | 1 - shim.c | 78 +++++++++++++++++------------------------------------ 5 files changed, 31 insertions(+), 86 deletions(-) (limited to 'lib') diff --git a/MokManager.c b/MokManager.c index b01c65ec..805017b6 100644 --- a/MokManager.c +++ b/MokManager.c @@ -9,6 +9,7 @@ #include "guid.h" #include "console.h" +#include "variables.h" #include "simple_file.h" #include "efiauthenticated.h" @@ -50,32 +51,6 @@ typedef struct { CHAR16 Password[SB_PASSWORD_LEN]; } __attribute__ ((packed)) MokSBvar; -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) { - console_notify(L"Unable to allocate variable buffer"); - return EFI_OUT_OF_RESOURCES; - } - - efi_status = uefi_call_wrapper(RT->GetVariable, 5, name, &guid, - attributes, size, *buffer); - - return efi_status; -} - static EFI_STATUS get_sha1sum (void *Data, int DataSize, UINT8 *hash) { EFI_STATUS status; @@ -904,7 +879,7 @@ static EFI_STATUS delete_keys (void *MokDel, UINTN MokDelSize) UINT8 auth[PASSWORD_CRYPT_SIZE]; UINTN auth_size = PASSWORD_CRYPT_SIZE; UINT32 attributes; - void *MokListData = NULL; + UINT8 *MokListData = NULL; UINTN MokListDataSize = 0; MokListNode *mok, *del_key; INTN mok_num, del_num; @@ -929,9 +904,8 @@ static EFI_STATUS delete_keys (void *MokDel, UINTN MokDelSize) if (efi_status != EFI_SUCCESS) return EFI_ACCESS_DENIED; - efi_status = get_variable(L"MokList", shim_lock_guid, &attributes, - &MokListDataSize, &MokListData); - + efi_status = get_variable_attr (L"MokList", &MokListData, &MokListDataSize, + shim_lock_guid, &attributes); if (attributes & EFI_VARIABLE_RUNTIME_ACCESS) { console_alertbox((CHAR16 *[]){L"MokList is compromised!", L"Erase all keys in MokList!", diff --git a/include/variables.h b/include/variables.h index c171bd53..b207dbf3 100644 --- a/include/variables.h +++ b/include/variables.h @@ -1,6 +1,6 @@ #include -#include /* for SHA256_DIGEST_SIZE */ +#include /* for SHA256_DIGEST_SIZE */ #define certlist_for_each_certentry(cl, cl_init, s, s_init) \ for (cl = (EFI_SIGNATURE_LIST *)(cl_init), s = (s_init); \ diff --git a/lib/Makefile b/lib/Makefile index 43907005..e85c1fd5 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -1,6 +1,6 @@ TARGET = lib.a -LIBFILES = simple_file.o guid.o console.o execute.o configtable.o shell.o +LIBFILES = simple_file.o guid.o console.o execute.o configtable.o shell.o variables.o ARCH = $(shell uname -m | sed s,i[3456789]86,ia32,) diff --git a/lib/variables.c b/lib/variables.c index 9db64809..81bd34db 100644 --- a/lib/variables.c +++ b/lib/variables.c @@ -27,7 +27,6 @@ #include #include #include -#include #include EFI_STATUS diff --git a/shim.c b/shim.c index 9ffc94a6..c2d54c44 100644 --- a/shim.c +++ b/shim.c @@ -43,6 +43,7 @@ #include "ucs2.h" #include "guid.h" +#include "variables.h" #include "efiauthenticated.h" #define FALLBACK L"\\fallback.efi" @@ -81,32 +82,6 @@ typedef struct { UINT8 *Mok; } MokListNode; -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; -} - /* * Perform basic bounds checking of the intra-image pointers */ @@ -270,15 +245,14 @@ static CHECK_STATUS check_db_cert(CHAR16 *dbname, EFI_GUID guid, EFI_STATUS efi_status; EFI_SIGNATURE_LIST *CertList; UINTN dbsize = 0; - UINT32 attributes; - void *db; + UINT8 *db; - efi_status = get_variable(dbname, guid, &attributes, &dbsize, &db); + efi_status = get_variable(dbname, &db, &dbsize, guid); if (efi_status != EFI_SUCCESS) return VAR_NOT_FOUND; - CertList = db; + CertList = (EFI_SIGNATURE_LIST *)db; rc = check_db_cert_in_ram(CertList, dbsize, data, hash); @@ -336,17 +310,16 @@ static CHECK_STATUS check_db_hash(CHAR16 *dbname, EFI_GUID guid, UINT8 *data, { EFI_STATUS efi_status; EFI_SIGNATURE_LIST *CertList; - UINT32 attributes; UINTN dbsize = 0; - void *db; + UINT8 *db; - efi_status = get_variable(dbname, guid, &attributes, &dbsize, &db); + efi_status = get_variable(dbname, &db, &dbsize, guid); if (efi_status != EFI_SUCCESS) { return VAR_NOT_FOUND; } - CertList = db; + CertList = (EFI_SIGNATURE_LIST *)db; CHECK_STATUS rc = check_db_hash_in_ram(CertList, dbsize, data, SignatureSize, CertType); @@ -423,15 +396,16 @@ static BOOLEAN secure_mode (void) { EFI_STATUS status; EFI_GUID global_var = EFI_GLOBAL_VARIABLE; - UINTN charsize = sizeof(char); + UINTN len; + UINT8 *Data; UINT8 sb, setupmode; - UINT32 attributes; if (insecure_mode) return FALSE; - status = get_variable(L"SecureBoot", global_var, &attributes, &charsize, - (void *)&sb); + status = get_variable(L"SecureBoot", &Data, &len, global_var); + sb = *Data; + FreePool(Data); /* FIXME - more paranoia here? */ if (status != EFI_SUCCESS || sb != 1) { @@ -440,8 +414,9 @@ static BOOLEAN secure_mode (void) return FALSE; } - status = get_variable(L"SetupMode", global_var, &attributes, &charsize, - (void *)&setupmode); + status = get_variable(L"SetupMode", &Data, &len, global_var); + setupmode = *Data; + FreePool(Data); if (status == EFI_SUCCESS && setupmode == 1) { if (verbose) @@ -629,12 +604,12 @@ done: static EFI_STATUS verify_mok (void) { EFI_GUID shim_lock_guid = SHIM_LOCK_GUID; EFI_STATUS status = EFI_SUCCESS; - void *MokListData = NULL; + UINT8 *MokListData = NULL; UINTN MokListDataSize = 0; UINT32 attributes; - status = get_variable(L"MokList", shim_lock_guid, &attributes, - &MokListDataSize, &MokListData); + status = get_variable_attr(L"MokList", &MokListData, &MokListDataSize, + shim_lock_guid, &attributes); if (attributes & EFI_VARIABLE_RUNTIME_ACCESS) { Print(L"MokList is compromised!\nErase all keys in MokList!\n"); @@ -1325,12 +1300,10 @@ EFI_STATUS mirror_mok_list() { EFI_GUID shim_lock_guid = SHIM_LOCK_GUID; EFI_STATUS efi_status; - UINT32 attributes; - void *Data = NULL; + UINT8 *Data = NULL; UINTN DataSize = 0; - efi_status = get_variable(L"MokList", shim_lock_guid, &attributes, - &DataSize, &Data); + efi_status = get_variable(L"MokList", &Data, &DataSize, shim_lock_guid); if (efi_status != EFI_SUCCESS) { goto done; @@ -1400,12 +1373,12 @@ static EFI_STATUS check_mok_sb (void) { EFI_GUID shim_lock_guid = SHIM_LOCK_GUID; EFI_STATUS status = EFI_SUCCESS; - void *MokSBState = NULL; + UINT8 *MokSBState = NULL; UINTN MokSBStateSize = 0; UINT32 attributes; - status = get_variable(L"MokSBState", shim_lock_guid, &attributes, - &MokSBStateSize, &MokSBState); + status = get_variable_attr(L"MokSBState", &MokSBState, &MokSBStateSize, + shim_lock_guid, &attributes); if (status != EFI_SUCCESS) return EFI_ACCESS_DENIED; @@ -1517,7 +1490,6 @@ EFI_STATUS efi_main (EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *passed_systab) EFI_STATUS efi_status; UINT8 verbose_check; UINTN verbose_check_size; - UINT32 attributes; EFI_GUID global_var = EFI_GLOBAL_VARIABLE; /* @@ -1536,8 +1508,8 @@ EFI_STATUS efi_main (EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *passed_systab) InitializeLib(image_handle, systab); verbose_check_size = 1; - efi_status = get_variable(L"SHIM_VERBOSE", global_var, &attributes, - &verbose_check_size, (void *)&verbose_check); + efi_status = get_variable(L"SHIM_VERBOSE", (void *)&verbose_check, + &verbose_check_size, global_var); if (!EFI_ERROR(efi_status)) verbose = verbose_check; -- cgit v1.2.3 From 59dcd9d1b8c45027d9aa5a1958579ae9872df6c7 Mon Sep 17 00:00:00 2001 From: Gary Ching-Pang Lin Date: Thu, 26 Sep 2013 11:58:03 -0400 Subject: integrate security override --- include/security_policy.h | 4 ++- lib/Makefile | 2 +- lib/security_policy.c | 77 +++++++++++------------------------------------ shim.c | 11 +++++++ 4 files changed, 33 insertions(+), 61 deletions(-) (limited to 'lib') diff --git a/include/security_policy.h b/include/security_policy.h index a1c1002d..b0109ce0 100644 --- a/include/security_policy.h +++ b/include/security_policy.h @@ -1,5 +1,7 @@ +typedef EFI_STATUS (*SecurityHook) (void *data, UINT32 len); + EFI_STATUS -security_policy_install(void); +security_policy_install(SecurityHook authentication); EFI_STATUS security_policy_uninstall(void); void diff --git a/lib/Makefile b/lib/Makefile index e85c1fd5..c1b9ab34 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -1,6 +1,6 @@ TARGET = lib.a -LIBFILES = simple_file.o guid.o console.o execute.o configtable.o shell.o variables.o +LIBFILES = simple_file.o guid.o console.o execute.o configtable.o shell.o variables.o security_policy.o ARCH = $(shell uname -m | sed s,i[3456789]86,ia32,) diff --git a/lib/security_policy.c b/lib/security_policy.c index e7becbf4..f1b08420 100644 --- a/lib/security_policy.c +++ b/lib/security_policy.c @@ -10,7 +10,6 @@ #include #include -#include #include #include #include @@ -50,59 +49,7 @@ struct _EFI_SECURITY_PROTOCOL { static UINT8 *security_policy_esl = NULL; static UINTN security_policy_esl_len; - -static EFI_STATUS -security_policy_check_mok(void *data, UINTN len) -{ - EFI_STATUS status; - UINT8 hash[SHA256_DIGEST_SIZE]; - UINT32 attr; - UINT8 *VarData; - UINTN VarLen; - - /* first check is MokSBState. If we're in insecure mode, boot - * anyway regardless of dbx contents */ - status = get_variable_attr(L"MokSBState", &VarData, &VarLen, - MOK_OWNER, &attr); - if (status == EFI_SUCCESS) { - UINT8 MokSBState = VarData[0]; - - FreePool(VarData); - if ((attr & EFI_VARIABLE_RUNTIME_ACCESS) == 0 - && MokSBState) - return EFI_SUCCESS; - } - - status = sha256_get_pecoff_digest_mem(data, len, hash); - if (status != EFI_SUCCESS) - return status; - - if (find_in_variable_esl(L"dbx", SIG_DB, hash, SHA256_DIGEST_SIZE) - == EFI_SUCCESS) - /* MOK list cannot override dbx */ - return EFI_SECURITY_VIOLATION; - - status = get_variable_attr(L"MokList", &VarData, &VarLen, MOK_OWNER, - &attr); - if (status != EFI_SUCCESS) - goto check_tmplist; - - FreePool(VarData); - - if (attr & EFI_VARIABLE_RUNTIME_ACCESS) - goto check_tmplist; - - if (find_in_variable_esl(L"MokList", MOK_OWNER, hash, SHA256_DIGEST_SIZE) == EFI_SUCCESS) - return EFI_SUCCESS; - - check_tmplist: - if (security_policy_esl - && find_in_esl(security_policy_esl, security_policy_esl_len, hash, - SHA256_DIGEST_SIZE) == EFI_SUCCESS) - return EFI_SUCCESS; - - return EFI_SECURITY_VIOLATION; -} +static SecurityHook extra_check = NULL; static EFI_SECURITY_FILE_AUTHENTICATION_STATE esfas = NULL; static EFI_SECURITY2_FILE_AUTHENTICATION es2fa = NULL; @@ -143,7 +90,10 @@ security2_policy_authentication ( if (status == EFI_SUCCESS) return status; - auth = security_policy_check_mok(FileBuffer, FileSize); + if (extra_check) + auth = extra_check(FileBuffer, FileSize); + else + return EFI_SECURITY_VIOLATION; if (auth == EFI_SECURITY_VIOLATION || auth == EFI_ACCESS_DENIED) /* return previous status, which is the correct one @@ -202,7 +152,10 @@ security_policy_authentication ( if (status != EFI_SUCCESS) goto out; - status = security_policy_check_mok(FileBuffer, FileSize); + if (extra_check) + status = extra_check(FileBuffer, FileSize); + else + status = EFI_SECURITY_VIOLATION; FreePool(FileBuffer); if (status == EFI_ACCESS_DENIED || status == EFI_SECURITY_VIOLATION) @@ -307,7 +260,7 @@ asm ( ); EFI_STATUS -security_policy_install(void) +security_policy_install(SecurityHook hook) { EFI_SECURITY_PROTOCOL *security_protocol; EFI_SECURITY2_PROTOCOL *security2_protocol = NULL; @@ -325,8 +278,8 @@ security_policy_install(void) &security2_protocol); status = uefi_call_wrapper(BS->LocateProtocol, 3, - &SECURITY_PROTOCOL_GUID, NULL, - &security_protocol); + &SECURITY_PROTOCOL_GUID, NULL, + &security_protocol); if (status != EFI_SUCCESS) /* This one is mandatory, so there's a serious problem */ return status; @@ -341,6 +294,9 @@ security_policy_install(void) security_protocol->FileAuthenticationState = thunk_security_policy_authentication; + if (hook) + extra_check = hook; + return EFI_SUCCESS; } @@ -380,6 +336,9 @@ security_policy_uninstall(void) es2fa = NULL; } + if (extra_check) + extra_check = NULL; + return EFI_SUCCESS; } diff --git a/shim.c b/shim.c index c2d54c44..f644f3f0 100644 --- a/shim.c +++ b/shim.c @@ -45,6 +45,7 @@ #include "guid.h" #include "variables.h" #include "efiauthenticated.h" +#include "security_policy.h" #define FALLBACK L"\\fallback.efi" #define MOK_MANAGER L"\\MokManager.efi" @@ -1537,6 +1538,11 @@ EFI_STATUS efi_main (EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *passed_systab) &shim_lock_guid, EFI_NATIVE_INTERFACE, &shim_lock_interface); + /* + * Install the security protocol hook + */ + security_policy_install(shim_verify); + /* * Enter MokManager if necessary */ @@ -1560,6 +1566,11 @@ EFI_STATUS efi_main (EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *passed_systab) uefi_call_wrapper(BS->UninstallProtocolInterface, 3, handle, &shim_lock_guid, &shim_lock_interface); + /* + * Clean up the security protocol hook + */ + security_policy_uninstall(); + /* * Free the space allocated for the alternative 2nd stage loader */ -- cgit v1.2.3 From bc71a15ed5d1912075f8c48be0243fdb1d35ac88 Mon Sep 17 00:00:00 2001 From: Peter Jones Date: Tue, 1 Oct 2013 14:03:16 -0400 Subject: Make verbose stuff use console_notify Signed-off-by: Peter Jones --- Makefile | 4 ++-- MokManager.c | 29 ----------------------------- console_control.h | 44 -------------------------------------------- include/console_control.h | 46 ++++++++++++++++++++++++++++++++++++++++++++++ lib/Makefile | 2 +- lib/console_control.c | 32 ++++++++++++++++++++++++++++++++ shim.c | 16 +++++++++++----- 7 files changed, 92 insertions(+), 81 deletions(-) delete mode 100644 console_control.h create mode 100644 include/console_control.h create mode 100644 lib/console_control.c (limited to 'lib') diff --git a/Makefile b/Makefile index 1752ef5b..40103eb3 100644 --- a/Makefile +++ b/Makefile @@ -38,9 +38,9 @@ VERSION = 0.4 TARGET = shim.efi MokManager.efi.signed fallback.efi.signed OBJS = shim.o netboot.o cert.o replacements.o KEYS = shim_cert.h ocsp.* ca.* shim.crt shim.csr shim.p12 shim.pem shim.key -SOURCES = shim.c shim.h netboot.c include/PeImage.h include/wincert.h replacements.c replacements.h +SOURCES = shim.c shim.h netboot.c include/PeImage.h include/wincert.h include/console.h replacements.c replacements.h include/console_control.h MOK_OBJS = MokManager.o PasswordCrypt.o crypt_blowfish.o -MOK_SOURCES = MokManager.c shim.h console_control.h PasswordCrypt.c PasswordCrypt.h crypt_blowfish.c crypt_blowfish.h +MOK_SOURCES = MokManager.c shim.h include/console_control.h PasswordCrypt.c PasswordCrypt.h crypt_blowfish.c crypt_blowfish.h FALLBACK_OBJS = fallback.o FALLBACK_SRCS = fallback.c diff --git a/MokManager.c b/MokManager.c index 5e9321a5..5d86e330 100644 --- a/MokManager.c +++ b/MokManager.c @@ -6,7 +6,6 @@ #include "shim.h" #include "PeImage.h" #include "PasswordCrypt.h" -#include "console_control.h" #include "guid.h" #include "console.h" @@ -1749,34 +1748,6 @@ static EFI_STATUS check_mok_request(EFI_HANDLE image_handle) return EFI_SUCCESS; } -static VOID setup_console (int text) -{ - EFI_STATUS status; - EFI_GUID console_control_guid = EFI_CONSOLE_CONTROL_PROTOCOL_GUID; - EFI_CONSOLE_CONTROL_PROTOCOL *concon; - static EFI_CONSOLE_CONTROL_SCREEN_MODE mode = - EfiConsoleControlScreenGraphics; - EFI_CONSOLE_CONTROL_SCREEN_MODE new_mode; - - status = LibLocateProtocol(&console_control_guid, (VOID **)&concon); - if (status != EFI_SUCCESS) - return; - - if (text) { - new_mode = EfiConsoleControlScreenText; - - status = uefi_call_wrapper(concon->GetMode, 4, concon, &mode, - 0, 0); - /* If that didn't work, assume it's graphics */ - if (status != EFI_SUCCESS) - mode = EfiConsoleControlScreenGraphics; - } else { - new_mode = mode; - } - - uefi_call_wrapper(concon->SetMode, 2, concon, new_mode); -} - static EFI_STATUS setup_rand (void) { EFI_TIME time; diff --git a/console_control.h b/console_control.h deleted file mode 100644 index 5fb8a4ae..00000000 --- a/console_control.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef _SHIM_CONSOLE_CONTROL_H -#define _SHIM_CONSOLE_CONTROL_H 1 - -#define EFI_CONSOLE_CONTROL_PROTOCOL_GUID \ - { 0xf42f7782, 0x12e, 0x4c12, {0x99, 0x56, 0x49, 0xf9, 0x43, 0x4, 0xf7, 0x21} } - -typedef struct _EFI_CONSOLE_CONTROL_PROTOCOL EFI_CONSOLE_CONTROL_PROTOCOL; - -typedef enum { - EfiConsoleControlScreenText, - EfiConsoleControlScreenGraphics, - EfiConsoleControlScreenMaxValue -} EFI_CONSOLE_CONTROL_SCREEN_MODE; - -typedef -EFI_STATUS -(EFIAPI *EFI_CONSOLE_CONTROL_PROTOCOL_GET_MODE) ( - IN EFI_CONSOLE_CONTROL_PROTOCOL *This, - OUT EFI_CONSOLE_CONTROL_SCREEN_MODE *Mode, - OUT BOOLEAN *GopUgaExists, OPTIONAL - OUT BOOLEAN *StdInLocked OPTIONAL - ); - -typedef -EFI_STATUS -(EFIAPI *EFI_CONSOLE_CONTROL_PROTOCOL_SET_MODE) ( - IN EFI_CONSOLE_CONTROL_PROTOCOL *This, - IN EFI_CONSOLE_CONTROL_SCREEN_MODE Mode - ); - -typedef -EFI_STATUS -(EFIAPI *EFI_CONSOLE_CONTROL_PROTOCOL_LOCK_STD_IN) ( - IN EFI_CONSOLE_CONTROL_PROTOCOL *This, - IN CHAR16 *Password - ); - -struct _EFI_CONSOLE_CONTROL_PROTOCOL { - EFI_CONSOLE_CONTROL_PROTOCOL_GET_MODE GetMode; - EFI_CONSOLE_CONTROL_PROTOCOL_SET_MODE SetMode; - EFI_CONSOLE_CONTROL_PROTOCOL_LOCK_STD_IN LockStdIn; -}; - -#endif /* _SHIM_CONSOLE_CONTROL_H */ diff --git a/include/console_control.h b/include/console_control.h new file mode 100644 index 00000000..aec6f41d --- /dev/null +++ b/include/console_control.h @@ -0,0 +1,46 @@ +#ifndef _SHIM_CONSOLE_CONTROL_H +#define _SHIM_CONSOLE_CONTROL_H 1 + +#define EFI_CONSOLE_CONTROL_PROTOCOL_GUID \ + { 0xf42f7782, 0x12e, 0x4c12, {0x99, 0x56, 0x49, 0xf9, 0x43, 0x4, 0xf7, 0x21} } + +typedef struct _EFI_CONSOLE_CONTROL_PROTOCOL EFI_CONSOLE_CONTROL_PROTOCOL; + +typedef enum { + EfiConsoleControlScreenText, + EfiConsoleControlScreenGraphics, + EfiConsoleControlScreenMaxValue +} EFI_CONSOLE_CONTROL_SCREEN_MODE; + +typedef +EFI_STATUS +(EFIAPI *EFI_CONSOLE_CONTROL_PROTOCOL_GET_MODE) ( + IN EFI_CONSOLE_CONTROL_PROTOCOL *This, + OUT EFI_CONSOLE_CONTROL_SCREEN_MODE *Mode, + OUT BOOLEAN *GopUgaExists, OPTIONAL + OUT BOOLEAN *StdInLocked OPTIONAL + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_CONSOLE_CONTROL_PROTOCOL_SET_MODE) ( + IN EFI_CONSOLE_CONTROL_PROTOCOL *This, + IN EFI_CONSOLE_CONTROL_SCREEN_MODE Mode + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_CONSOLE_CONTROL_PROTOCOL_LOCK_STD_IN) ( + IN EFI_CONSOLE_CONTROL_PROTOCOL *This, + IN CHAR16 *Password + ); + +struct _EFI_CONSOLE_CONTROL_PROTOCOL { + EFI_CONSOLE_CONTROL_PROTOCOL_GET_MODE GetMode; + EFI_CONSOLE_CONTROL_PROTOCOL_SET_MODE SetMode; + EFI_CONSOLE_CONTROL_PROTOCOL_LOCK_STD_IN LockStdIn; +}; + +extern VOID setup_console (int text); + +#endif /* _SHIM_CONSOLE_CONTROL_H */ diff --git a/lib/Makefile b/lib/Makefile index c1b9ab34..f2b9091d 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -1,6 +1,6 @@ TARGET = lib.a -LIBFILES = simple_file.o guid.o console.o execute.o configtable.o shell.o variables.o security_policy.o +LIBFILES = simple_file.o guid.o console.o execute.o configtable.o shell.o variables.o security_policy.o console_control.o ARCH = $(shell uname -m | sed s,i[3456789]86,ia32,) diff --git a/lib/console_control.c b/lib/console_control.c new file mode 100644 index 00000000..604a60f5 --- /dev/null +++ b/lib/console_control.c @@ -0,0 +1,32 @@ +#include +#include + +#include "console_control.h" + +VOID setup_console (int text) +{ + EFI_STATUS status; + EFI_GUID console_control_guid = EFI_CONSOLE_CONTROL_PROTOCOL_GUID; + EFI_CONSOLE_CONTROL_PROTOCOL *concon; + static EFI_CONSOLE_CONTROL_SCREEN_MODE mode = + EfiConsoleControlScreenGraphics; + EFI_CONSOLE_CONTROL_SCREEN_MODE new_mode; + + status = LibLocateProtocol(&console_control_guid, (VOID **)&concon); + if (status != EFI_SUCCESS) + return; + + if (text) { + new_mode = EfiConsoleControlScreenText; + + status = uefi_call_wrapper(concon->GetMode, 4, concon, &mode, + 0, 0); + /* If that didn't work, assume it's graphics */ + if (status != EFI_SUCCESS) + mode = EfiConsoleControlScreenGraphics; + } else { + new_mode = mode; + } + + uefi_call_wrapper(concon->SetMode, 2, concon, new_mode); +} diff --git a/shim.c b/shim.c index 8c4ef656..a72e0910 100644 --- a/shim.c +++ b/shim.c @@ -43,10 +43,12 @@ #include "replacements.h" #include "ucs2.h" +#include "console_control.h" #include "guid.h" #include "variables.h" #include "efiauthenticated.h" #include "security_policy.h" +#include "console.h" #define FALLBACK L"\\fallback.efi" #define MOK_MANAGER L"\\MokManager.efi" @@ -446,7 +448,7 @@ static BOOLEAN secure_mode (void) /* FIXME - more paranoia here? */ if (status != EFI_SUCCESS || sb != 1) { if (verbose) - Print(L"Secure boot not enabled\n"); + console_notify(L"Secure boot not enabled\n"); return FALSE; } @@ -456,7 +458,7 @@ static BOOLEAN secure_mode (void) if (status == EFI_SUCCESS && setupmode == 1) { if (verbose) - Print(L"Platform is in setup mode\n"); + console_notify(L"Platform is in setup mode\n"); return FALSE; } @@ -720,7 +722,7 @@ static EFI_STATUS verify_buffer (char *data, int datasize, if (status == EFI_SUCCESS) { if (verbose) - Print(L"Binary is whitelisted\n"); + console_notify(L"Binary is whitelisted\n"); return status; } @@ -733,7 +735,7 @@ static EFI_STATUS verify_buffer (char *data, int datasize, SHA256_DIGEST_SIZE)) { status = EFI_SUCCESS; if (verbose) - Print(L"Binary is verified by the vendor certificate\n"); + console_notify(L"Binary is verified by the vendor certificate\n"); return status; } @@ -747,7 +749,7 @@ static EFI_STATUS verify_buffer (char *data, int datasize, SHA256_DIGEST_SIZE)) { status = EFI_SUCCESS; if (verbose) - Print(L"Binary is verified by the vendor certificate\n"); + console_notify(L"Binary is verified by the vendor certificate\n"); return status; } @@ -1590,6 +1592,8 @@ EFI_STATUS efi_main (EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *passed_systab) */ InitializeLib(image_handle, systab); + setup_console(1); + verbose_check_size = 1; efi_status = get_variable(L"SHIM_VERBOSE", (void *)&verbose_check, &verbose_check_size, global_var); @@ -1665,5 +1669,7 @@ EFI_STATUS efi_main (EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *passed_systab) if (load_options_size > 0) FreePool(second_stage); + setup_console(0); + return efi_status; } -- cgit v1.2.3 From 417077f8de33214b2942f5a6d8ff6af217b4f5dd Mon Sep 17 00:00:00 2001 From: Peter Jones Date: Tue, 1 Oct 2013 14:03:16 -0400 Subject: Merge console_control.h and console.h Since these are topically the same thing, they can live together. Signed-off-by: Peter Jones --- Makefile | 4 ++-- MokManager.c | 1 - include/console.h | 47 +++++++++++++++++++++++++++++++++++++++++++++++ include/console_control.h | 46 ---------------------------------------------- lib/Makefile | 2 +- lib/console.c | 29 +++++++++++++++++++++++++++++ lib/console_control.c | 32 -------------------------------- shim.c | 1 - 8 files changed, 79 insertions(+), 83 deletions(-) delete mode 100644 include/console_control.h delete mode 100644 lib/console_control.c (limited to 'lib') diff --git a/Makefile b/Makefile index 40103eb3..581be0ac 100644 --- a/Makefile +++ b/Makefile @@ -38,9 +38,9 @@ VERSION = 0.4 TARGET = shim.efi MokManager.efi.signed fallback.efi.signed OBJS = shim.o netboot.o cert.o replacements.o KEYS = shim_cert.h ocsp.* ca.* shim.crt shim.csr shim.p12 shim.pem shim.key -SOURCES = shim.c shim.h netboot.c include/PeImage.h include/wincert.h include/console.h replacements.c replacements.h include/console_control.h +SOURCES = shim.c shim.h netboot.c include/PeImage.h include/wincert.h include/console.h replacements.c replacements.h MOK_OBJS = MokManager.o PasswordCrypt.o crypt_blowfish.o -MOK_SOURCES = MokManager.c shim.h include/console_control.h PasswordCrypt.c PasswordCrypt.h crypt_blowfish.c crypt_blowfish.h +MOK_SOURCES = MokManager.c shim.h include/console.h PasswordCrypt.c PasswordCrypt.h crypt_blowfish.c crypt_blowfish.h FALLBACK_OBJS = fallback.o FALLBACK_SRCS = fallback.c diff --git a/MokManager.c b/MokManager.c index 5d86e330..de0eb59a 100644 --- a/MokManager.c +++ b/MokManager.c @@ -2,7 +2,6 @@ #include #include #include -#include "console_control.h" #include "shim.h" #include "PeImage.h" #include "PasswordCrypt.h" diff --git a/include/console.h b/include/console.h index 7eb8a0be..d699d278 100644 --- a/include/console.h +++ b/include/console.h @@ -1,3 +1,6 @@ +#ifndef _SHIM_LIB_CONSOLE_H +#define _SHIM_LIB_CONSOLE_H 1 + EFI_INPUT_KEY console_get_keystroke(void); void @@ -19,3 +22,47 @@ console_notify(CHAR16 *string); void console_reset(void); #define NOSEL 0x7fffffff + +#define EFI_CONSOLE_CONTROL_PROTOCOL_GUID \ + { 0xf42f7782, 0x12e, 0x4c12, {0x99, 0x56, 0x49, 0xf9, 0x43, 0x4, 0xf7, 0x21} } + +typedef struct _EFI_CONSOLE_CONTROL_PROTOCOL EFI_CONSOLE_CONTROL_PROTOCOL; + +typedef enum { + EfiConsoleControlScreenText, + EfiConsoleControlScreenGraphics, + EfiConsoleControlScreenMaxValue +} EFI_CONSOLE_CONTROL_SCREEN_MODE; + +typedef +EFI_STATUS +(EFIAPI *EFI_CONSOLE_CONTROL_PROTOCOL_GET_MODE) ( + IN EFI_CONSOLE_CONTROL_PROTOCOL *This, + OUT EFI_CONSOLE_CONTROL_SCREEN_MODE *Mode, + OUT BOOLEAN *GopUgaExists, OPTIONAL + OUT BOOLEAN *StdInLocked OPTIONAL + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_CONSOLE_CONTROL_PROTOCOL_SET_MODE) ( + IN EFI_CONSOLE_CONTROL_PROTOCOL *This, + IN EFI_CONSOLE_CONTROL_SCREEN_MODE Mode + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_CONSOLE_CONTROL_PROTOCOL_LOCK_STD_IN) ( + IN EFI_CONSOLE_CONTROL_PROTOCOL *This, + IN CHAR16 *Password + ); + +struct _EFI_CONSOLE_CONTROL_PROTOCOL { + EFI_CONSOLE_CONTROL_PROTOCOL_GET_MODE GetMode; + EFI_CONSOLE_CONTROL_PROTOCOL_SET_MODE SetMode; + EFI_CONSOLE_CONTROL_PROTOCOL_LOCK_STD_IN LockStdIn; +}; + +extern VOID setup_console (int text); + +#endif /* _SHIM_LIB_CONSOLE_H */ diff --git a/include/console_control.h b/include/console_control.h deleted file mode 100644 index aec6f41d..00000000 --- a/include/console_control.h +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef _SHIM_CONSOLE_CONTROL_H -#define _SHIM_CONSOLE_CONTROL_H 1 - -#define EFI_CONSOLE_CONTROL_PROTOCOL_GUID \ - { 0xf42f7782, 0x12e, 0x4c12, {0x99, 0x56, 0x49, 0xf9, 0x43, 0x4, 0xf7, 0x21} } - -typedef struct _EFI_CONSOLE_CONTROL_PROTOCOL EFI_CONSOLE_CONTROL_PROTOCOL; - -typedef enum { - EfiConsoleControlScreenText, - EfiConsoleControlScreenGraphics, - EfiConsoleControlScreenMaxValue -} EFI_CONSOLE_CONTROL_SCREEN_MODE; - -typedef -EFI_STATUS -(EFIAPI *EFI_CONSOLE_CONTROL_PROTOCOL_GET_MODE) ( - IN EFI_CONSOLE_CONTROL_PROTOCOL *This, - OUT EFI_CONSOLE_CONTROL_SCREEN_MODE *Mode, - OUT BOOLEAN *GopUgaExists, OPTIONAL - OUT BOOLEAN *StdInLocked OPTIONAL - ); - -typedef -EFI_STATUS -(EFIAPI *EFI_CONSOLE_CONTROL_PROTOCOL_SET_MODE) ( - IN EFI_CONSOLE_CONTROL_PROTOCOL *This, - IN EFI_CONSOLE_CONTROL_SCREEN_MODE Mode - ); - -typedef -EFI_STATUS -(EFIAPI *EFI_CONSOLE_CONTROL_PROTOCOL_LOCK_STD_IN) ( - IN EFI_CONSOLE_CONTROL_PROTOCOL *This, - IN CHAR16 *Password - ); - -struct _EFI_CONSOLE_CONTROL_PROTOCOL { - EFI_CONSOLE_CONTROL_PROTOCOL_GET_MODE GetMode; - EFI_CONSOLE_CONTROL_PROTOCOL_SET_MODE SetMode; - EFI_CONSOLE_CONTROL_PROTOCOL_LOCK_STD_IN LockStdIn; -}; - -extern VOID setup_console (int text); - -#endif /* _SHIM_CONSOLE_CONTROL_H */ diff --git a/lib/Makefile b/lib/Makefile index f2b9091d..c1b9ab34 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -1,6 +1,6 @@ TARGET = lib.a -LIBFILES = simple_file.o guid.o console.o execute.o configtable.o shell.o variables.o security_policy.o console_control.o +LIBFILES = simple_file.o guid.o console.o execute.o configtable.o shell.o variables.o security_policy.o ARCH = $(shell uname -m | sed s,i[3456789]86,ia32,) diff --git a/lib/console.c b/lib/console.c index af01f035..72d64271 100644 --- a/lib/console.c +++ b/lib/console.c @@ -1,5 +1,6 @@ /* * Copyright 2012 + * Copyright 2013 Red Hat Inc. * * see COPYING file */ @@ -400,3 +401,31 @@ console_reset(void) uefi_call_wrapper(co->SetMode, 2, co, 0); uefi_call_wrapper(co->ClearScreen, 1, co); } + +VOID setup_console (int text) +{ + EFI_STATUS status; + EFI_GUID console_control_guid = EFI_CONSOLE_CONTROL_PROTOCOL_GUID; + EFI_CONSOLE_CONTROL_PROTOCOL *concon; + static EFI_CONSOLE_CONTROL_SCREEN_MODE mode = + EfiConsoleControlScreenGraphics; + EFI_CONSOLE_CONTROL_SCREEN_MODE new_mode; + + status = LibLocateProtocol(&console_control_guid, (VOID **)&concon); + if (status != EFI_SUCCESS) + return; + + if (text) { + new_mode = EfiConsoleControlScreenText; + + status = uefi_call_wrapper(concon->GetMode, 4, concon, &mode, + 0, 0); + /* If that didn't work, assume it's graphics */ + if (status != EFI_SUCCESS) + mode = EfiConsoleControlScreenGraphics; + } else { + new_mode = mode; + } + + uefi_call_wrapper(concon->SetMode, 2, concon, new_mode); +} diff --git a/lib/console_control.c b/lib/console_control.c deleted file mode 100644 index 604a60f5..00000000 --- a/lib/console_control.c +++ /dev/null @@ -1,32 +0,0 @@ -#include -#include - -#include "console_control.h" - -VOID setup_console (int text) -{ - EFI_STATUS status; - EFI_GUID console_control_guid = EFI_CONSOLE_CONTROL_PROTOCOL_GUID; - EFI_CONSOLE_CONTROL_PROTOCOL *concon; - static EFI_CONSOLE_CONTROL_SCREEN_MODE mode = - EfiConsoleControlScreenGraphics; - EFI_CONSOLE_CONTROL_SCREEN_MODE new_mode; - - status = LibLocateProtocol(&console_control_guid, (VOID **)&concon); - if (status != EFI_SUCCESS) - return; - - if (text) { - new_mode = EfiConsoleControlScreenText; - - status = uefi_call_wrapper(concon->GetMode, 4, concon, &mode, - 0, 0); - /* If that didn't work, assume it's graphics */ - if (status != EFI_SUCCESS) - mode = EfiConsoleControlScreenGraphics; - } else { - new_mode = mode; - } - - uefi_call_wrapper(concon->SetMode, 2, concon, new_mode); -} diff --git a/shim.c b/shim.c index a72e0910..3c55a5a4 100644 --- a/shim.c +++ b/shim.c @@ -43,7 +43,6 @@ #include "replacements.h" #include "ucs2.h" -#include "console_control.h" #include "guid.h" #include "variables.h" #include "efiauthenticated.h" -- cgit v1.2.3 From bb2fe4cfb3fc050e4ef0dbb6af0c53a4f75200c9 Mon Sep 17 00:00:00 2001 From: Peter Jones Date: Tue, 1 Oct 2013 14:03:16 -0400 Subject: Conditionalize overriding the security policy. Make OVERRIDE_SECURITY_POLICY a build option. Signed-off-by: Peter Jones --- Makefile | 4 ++++ include/security_policy.h | 7 +++++++ lib/security_policy.c | 2 ++ shim.c | 4 ++++ 4 files changed, 17 insertions(+) (limited to 'lib') diff --git a/Makefile b/Makefile index 581be0ac..311a2c9b 100644 --- a/Makefile +++ b/Makefile @@ -21,6 +21,10 @@ CFLAGS = -ggdb -O0 -fno-stack-protector -fno-strict-aliasing -fpic \ "-DDEFAULT_LOADER=L\"$(DEFAULT_LOADER)\"" \ "-DDEFAULT_LOADER_CHAR=\"$(DEFAULT_LOADER)\"" \ $(EFI_INCLUDES) + +ifneq ($(origin OVERRIDE_SECURITY_POLICY), undefined) + CFLAGS += -DOVERRIDE_SECURITY_POLICY +endif ifeq ($(ARCH),x86_64) CFLAGS += -DEFI_FUNCTION_WRAPPER -DGNU_EFI_USE_MS_ABI endif diff --git a/include/security_policy.h b/include/security_policy.h index b0109ce0..7854db11 100644 --- a/include/security_policy.h +++ b/include/security_policy.h @@ -1,3 +1,7 @@ +#ifndef _SHIM_LIB_SECURITY_POLICY_H +#define _SHIM_LIB_SECURITY_POLICY_H 1 + +#if defined(OVERRIDE_SECURITY_POLICY) typedef EFI_STATUS (*SecurityHook) (void *data, UINT32 len); EFI_STATUS @@ -6,3 +10,6 @@ EFI_STATUS security_policy_uninstall(void); void security_protocol_set_hashes(unsigned char *esl, int len); +#endif /* OVERRIDE_SECURITY_POLICY */ + +#endif /* SHIM_LIB_SECURITY_POLICY_H */ diff --git a/lib/security_policy.c b/lib/security_policy.c index f1b08420..9af3a107 100644 --- a/lib/security_policy.c +++ b/lib/security_policy.c @@ -14,6 +14,7 @@ #include #include +#if defined(OVERRIDE_SECURITY_POLICY) #include /* @@ -348,3 +349,4 @@ security_protocol_set_hashes(unsigned char *esl, int len) security_policy_esl = esl; security_policy_esl_len = len; } +#endif /* OVERRIDE_SECURITY_POLICY */ diff --git a/shim.c b/shim.c index 3c55a5a4..b7256291 100644 --- a/shim.c +++ b/shim.c @@ -1629,10 +1629,12 @@ EFI_STATUS efi_main (EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *passed_systab) &shim_lock_guid, EFI_NATIVE_INTERFACE, &shim_lock_interface); +#if defined(OVERRIDE_SECURITY_POLICY) /* * Install the security protocol hook */ security_policy_install(shim_verify); +#endif /* * Enter MokManager if necessary @@ -1657,10 +1659,12 @@ EFI_STATUS efi_main (EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *passed_systab) uefi_call_wrapper(BS->UninstallProtocolInterface, 3, handle, &shim_lock_guid, &shim_lock_interface); +#if defined(OVERRIDE_SECURITY_POLICY) /* * Clean up the security protocol hook */ security_policy_uninstall(); +#endif /* * Free the space allocated for the alternative 2nd stage loader -- cgit v1.2.3 From 7076ec11b094b49e087545ebb48e255c92b44c2a Mon Sep 17 00:00:00 2001 From: Peter Jones Date: Tue, 1 Oct 2013 14:38:09 -0400 Subject: Clean up warnings. Signed-off-by: Peter Jones --- lib/Makefile | 4 +++- lib/execute.c | 2 +- lib/simple_file.c | 9 +++++---- 3 files changed, 9 insertions(+), 6 deletions(-) (limited to 'lib') diff --git a/lib/Makefile b/lib/Makefile index c1b9ab34..adb03477 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -11,7 +11,9 @@ EFI_CRT_OBJS = $(EFI_PATH)/crt0-efi-$(ARCH).o EFI_LDS = $(EFI_PATH)/elf_$(ARCH)_efi.lds CFLAGS = -ggdb -O0 -fno-stack-protector -fno-strict-aliasing -fpic \ - -fshort-wchar -Wall -mno-red-zone -DBUILD_EFI $(EFI_INCLUDES) + -fshort-wchar -Wall -mno-red-zone -DBUILD_EFI -fno-builtin \ + -Werror \ + $(EFI_INCLUDES) ifeq ($(ARCH),x86_64) CFLAGS += -DEFI_FUNCTION_WRAPPER -DGNU_EFI_USE_MS_ABI endif diff --git a/lib/execute.c b/lib/execute.c index 8d726eb8..42d71c87 100644 --- a/lib/execute.c +++ b/lib/execute.c @@ -103,7 +103,7 @@ execute(EFI_HANDLE image, CHAR16 *name) CHAR16 *PathName; status = uefi_call_wrapper(BS->HandleProtocol, 3, image, - &IMAGE_PROTOCOL, &li); + &IMAGE_PROTOCOL, (void **)&li); if (status != EFI_SUCCESS) return status; diff --git a/lib/simple_file.c b/lib/simple_file.c index e2882728..3af0ec8d 100644 --- a/lib/simple_file.c +++ b/lib/simple_file.c @@ -25,7 +25,7 @@ simple_file_open_by_handle(EFI_HANDLE device, CHAR16 *name, EFI_FILE **file, UIN EFI_FILE *root; efi_status = uefi_call_wrapper(BS->HandleProtocol, 3, device, - &SIMPLE_FS_PROTOCOL, &drive); + &SIMPLE_FS_PROTOCOL, (void **)&drive); if (efi_status != EFI_SUCCESS) { Print(L"Unable to find simple file protocol (%d)\n", efi_status); @@ -56,7 +56,7 @@ simple_file_open(EFI_HANDLE image, CHAR16 *name, EFI_FILE **file, UINT64 mode) CHAR16 *PathName = NULL; efi_status = uefi_call_wrapper(BS->HandleProtocol, 3, image, - &IMAGE_PROTOCOL, &li); + &IMAGE_PROTOCOL, (void **)&li); if (efi_status != EFI_SUCCESS) return simple_file_open_by_handle(image, name, file, mode); @@ -116,7 +116,7 @@ simple_dir_read_all_by_handle(EFI_HANDLE image, EFI_FILE *file, CHAR16* name, EF return EFI_OUT_OF_RESOURCES; int i; for (i = 0; i < *count; i++) { - int len = size; + UINTN len = size; uefi_call_wrapper(file->Read, 3, file, &len, ptr); ptr += len; size -= len; @@ -223,7 +223,8 @@ simple_volume_selector(CHAR16 **title, CHAR16 **selected, EFI_HANDLE *h) status = uefi_call_wrapper(BS->HandleProtocol, 3, vol_handles[i], - &SIMPLE_FS_PROTOCOL, &drive); + &SIMPLE_FS_PROTOCOL, + (void **)&drive); if (status != EFI_SUCCESS || !drive) continue; -- cgit v1.2.3 From aed556c4abc0ecb408684ac3544ff3ec04bad109 Mon Sep 17 00:00:00 2001 From: Peter Jones Date: Wed, 2 Oct 2013 10:02:01 -0400 Subject: CompareMem expects void * and gcc complains. Sorry about that. Signed-off-by: Peter Jones --- lib/configtable.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/configtable.c b/lib/configtable.c index 735ce8f8..e2d92bf0 100644 --- a/lib/configtable.c +++ b/lib/configtable.c @@ -101,7 +101,7 @@ configtable_find_image(const EFI_DEVICE_PATH *DevicePath) break; } - if (CompareMem(dp, DevicePath, Size) == 0) { + if (CompareMem(dp, (void *)DevicePath, Size) == 0) { #ifdef DEBUG_CONFIG Print(L"***FOUND\n"); console_get_keystroke(); -- cgit v1.2.3 From 0fb089ee14e92bd1f6909deaf4d32a926053edcd Mon Sep 17 00:00:00 2001 From: Peter Jones Date: Thu, 3 Oct 2013 11:11:09 -0400 Subject: Add ident-like blobs to shim.efi for version checking. I feel dirty. --- .gitignore | 1 + Makefile | 14 +++++++++++--- include/console.h | 2 ++ lib/console.c | 14 ++++++++++++++ shim.c | 4 ++++ version.c.in | 8 ++++++++ version.h | 8 ++++++++ 7 files changed, 48 insertions(+), 3 deletions(-) create mode 100644 version.c.in create mode 100644 version.h (limited to 'lib') diff --git a/.gitignore b/.gitignore index 85da8e77..586bc246 100644 --- a/.gitignore +++ b/.gitignore @@ -23,3 +23,4 @@ shim_cert.h *.srl *.srl.old *.tar.* +version.c diff --git a/Makefile b/Makefile index 53c4e000..4a8b5531 100644 --- a/Makefile +++ b/Makefile @@ -40,9 +40,9 @@ LDFLAGS = -nostdlib -znocombreloc -T $(EFI_LDS) -shared -Bsymbolic -L$(EFI_PATH VERSION = 0.4 TARGET = shim.efi MokManager.efi.signed fallback.efi.signed -OBJS = shim.o netboot.o cert.o replacements.o +OBJS = shim.o netboot.o cert.o replacements.o version.o KEYS = shim_cert.h ocsp.* ca.* shim.crt shim.csr shim.p12 shim.pem shim.key shim.cer -SOURCES = shim.c shim.h netboot.c include/PeImage.h include/wincert.h include/console.h replacements.c replacements.h +SOURCES = shim.c shim.h netboot.c include/PeImage.h include/wincert.h include/console.h replacements.c replacements.h version.c version.h MOK_OBJS = MokManager.o PasswordCrypt.o crypt_blowfish.o MOK_SOURCES = MokManager.c shim.h include/console.h PasswordCrypt.c PasswordCrypt.h crypt_blowfish.c crypt_blowfish.h FALLBACK_OBJS = fallback.o @@ -61,6 +61,12 @@ shim_cert.h: shim.cer hexdump -v -e '1/1 "0x%02x, "' $< >> $@ echo "};" >> $@ +version.c : version.c.in + sed -e "s,@@VERSION@@,$(VERSION)," \ + -e "s,@@UNAME@@,$(shell uname -a)," \ + -e "s,@@COMMIT@@,$(shell if [ -d .git ] ; then git log -1 --pretty=format:%H ; elif [ -f commit ]; then cat commit ; else echo commit id not available; fi)," \ + < version.c.in > version.c + certdb/secmod.db: shim.crt -mkdir certdb certutil -A -n 'my CA' -d certdb/ -t CT,CT,CT -i ca.crt @@ -115,7 +121,7 @@ clean: $(MAKE) -C Cryptlib/OpenSSL clean $(MAKE) -C lib clean rm -rf $(TARGET) $(OBJS) $(MOK_OBJS) $(FALLBACK_OBJS) $(KEYS) certdb - rm -f *.debug *.so *.efi *.tar.* + rm -f *.debug *.so *.efi *.tar.* version.c GITTAG = $(VERSION) @@ -125,6 +131,7 @@ test-archive: @git archive --format=tar $(shell git branch | awk '/^*/ { print $$2 }') | ( cd /tmp/shim-$(VERSION)-tmp/ ; tar x ) @git diff | ( cd /tmp/shim-$(VERSION)-tmp/ ; patch -s -p1 -b -z .gitdiff ) @mv /tmp/shim-$(VERSION)-tmp/ /tmp/shim-$(VERSION)/ + @git log -1 --pretty=format:%H > /tmp/shim-$(VERSION)/commit @dir=$$PWD; cd /tmp; tar -c --bzip2 -f $$dir/shim-$(VERSION).tar.bz2 shim-$(VERSION) @rm -rf /tmp/shim-$(VERSION) @echo "The archive is in shim-$(VERSION).tar.bz2" @@ -135,6 +142,7 @@ archive: @mkdir -p /tmp/shim-$(VERSION)-tmp @git archive --format=tar $(GITTAG) | ( cd /tmp/shim-$(VERSION)-tmp/ ; tar x ) @mv /tmp/shim-$(VERSION)-tmp/ /tmp/shim-$(VERSION)/ + @git log -1 --pretty=format:%H > /tmp/shim-$(VERSION)/commit @dir=$$PWD; cd /tmp; tar -c --bzip2 -f $$dir/shim-$(VERSION).tar.bz2 shim-$(VERSION) @rm -rf /tmp/shim-$(VERSION) @echo "The archive is in shim-$(VERSION).tar.bz2" diff --git a/include/console.h b/include/console.h index d699d278..fbeb7e68 100644 --- a/include/console.h +++ b/include/console.h @@ -20,6 +20,8 @@ console_alertbox(CHAR16 **title); void console_notify(CHAR16 *string); void +console_notify_ascii(CHAR8 *string); +void console_reset(void); #define NOSEL 0x7fffffff diff --git a/lib/console.c b/lib/console.c index 72d64271..44b08f25 100644 --- a/lib/console.c +++ b/lib/console.c @@ -312,6 +312,20 @@ console_notify(CHAR16 *string) console_alertbox(str_arr); } +void +console_notify_ascii(CHAR8 *string) +{ + CHAR16 *str = AllocateZeroPool((strlena(string) + 1) * 2); + int i, j; + + if (!str) + return; + + for (i = 0, j = 1; string[i] != '\0'; i++, j+=2) + str[j] = string[i]; + console_notify(str); +} + #define ARRAY_SIZE(a) (sizeof (a) / sizeof ((a)[0])) /* Copy of gnu-efi-3.0 with the added secure boot strings */ diff --git a/shim.c b/shim.c index 690cb091..873fd2ed 100644 --- a/shim.c +++ b/shim.c @@ -48,6 +48,7 @@ #include "efiauthenticated.h" #include "security_policy.h" #include "console.h" +#include "version.h" #define FALLBACK L"\\fallback.efi" #define MOK_MANAGER L"\\MokManager.efi" @@ -1668,6 +1669,9 @@ EFI_STATUS efi_main (EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *passed_systab) if (!EFI_ERROR(efi_status)) verbose = verbose_check; + if (verbose) + console_notify_ascii(shim_version); + /* Set the second stage loader */ set_second_stage (image_handle); diff --git a/version.c.in b/version.c.in new file mode 100644 index 00000000..9e71970d --- /dev/null +++ b/version.c.in @@ -0,0 +1,8 @@ + +#include "version.h" + +CHAR8 shim_version[] = + "UEFI SHIM\n" + "$Version: @@VERSION@@ $\n" + "$BuildMachine: @@UNAME@@ $\n" + "$Commit: @@COMMIT@@ $\n"; diff --git a/version.h b/version.h new file mode 100644 index 00000000..7fb3d81b --- /dev/null +++ b/version.h @@ -0,0 +1,8 @@ +#ifndef _SHIM_VERSION_H +#define _SHIM_VERSION_H 1 + +#include + +extern CHAR8 shim_version[]; + +#endif /* SHIM_VERSION_H */ -- cgit v1.2.3 From 4ab978a3697c88827f4099fe5774031caf5baf44 Mon Sep 17 00:00:00 2001 From: Peter Jones Date: Fri, 4 Oct 2013 11:51:09 -0400 Subject: Try to actually make debug printing look reasonable. Signed-off-by: Peter Jones --- include/console.h | 22 ++++++++++++++++++++-- lib/console.c | 33 +++++++++++++++++++-------------- shim.c | 32 ++++++++------------------------ 3 files changed, 47 insertions(+), 40 deletions(-) (limited to 'lib') diff --git a/include/console.h b/include/console.h index fbeb7e68..e6c2818f 100644 --- a/include/console.h +++ b/include/console.h @@ -20,8 +20,6 @@ console_alertbox(CHAR16 **title); void console_notify(CHAR16 *string); void -console_notify_ascii(CHAR8 *string); -void console_reset(void); #define NOSEL 0x7fffffff @@ -66,5 +64,25 @@ struct _EFI_CONSOLE_CONTROL_PROTOCOL { }; extern VOID setup_console (int text); +extern VOID setup_verbosity(VOID); +extern UINT8 verbose; +#define dprint(fmt, ...) ({ \ + UINTN __dprint_ret = 0; \ + if (verbose) \ + __dprint_ret = Print((fmt), ##__VA_ARGS__); \ + __dprint_ret; \ + }) +#define dprinta(fmt, ...) ({ \ + UINTN __dprinta_ret = 0; \ + if (verbose) { \ + UINTN __dprinta_i; \ + CHAR16 *__dprinta_str = AllocateZeroPool((strlena(fmt) + 1) * 2); \ + for (__dprinta_i = 0; fmt[__dprinta_i] != '\0'; __dprinta_i++) \ + __dprinta_str[__dprinta_i] = fmt[__dprinta_i]; \ + __dprinta_ret = Print((__dprinta_str), ##__VA_ARGS__); \ + FreePool(__dprinta_str); \ + } \ + __dprinta_ret; \ + }) #endif /* _SHIM_LIB_CONSOLE_H */ diff --git a/lib/console.c b/lib/console.c index 44b08f25..1f8f59ca 100644 --- a/lib/console.c +++ b/lib/console.c @@ -8,6 +8,7 @@ #include #include +#include #include static int min(int a, int b) @@ -312,20 +313,6 @@ console_notify(CHAR16 *string) console_alertbox(str_arr); } -void -console_notify_ascii(CHAR8 *string) -{ - CHAR16 *str = AllocateZeroPool((strlena(string) + 1) * 2); - int i, j; - - if (!str) - return; - - for (i = 0, j = 1; string[i] != '\0'; i++, j+=2) - str[j] = string[i]; - console_notify(str); -} - #define ARRAY_SIZE(a) (sizeof (a) / sizeof ((a)[0])) /* Copy of gnu-efi-3.0 with the added secure boot strings */ @@ -416,6 +403,24 @@ console_reset(void) uefi_call_wrapper(co->ClearScreen, 1, co); } +UINT8 verbose; + +VOID +setup_verbosity(VOID) +{ + EFI_STATUS status; + EFI_GUID global_var = EFI_GLOBAL_VARIABLE; + UINT8 verbose_check; + UINTN verbose_check_size; + + verbose_check_size = 1; + status = get_variable(L"SHIM_VERBOSE", (void *)&verbose_check, + &verbose_check_size, global_var); + verbose = 0; + if (!EFI_ERROR(status)) + verbose = verbose_check; +} + VOID setup_console (int text) { EFI_STATUS status; diff --git a/shim.c b/shim.c index 51dfc26d..502a91dd 100644 --- a/shim.c +++ b/shim.c @@ -59,7 +59,6 @@ static EFI_STATUS (EFIAPI *entry_point) (EFI_HANDLE image_handle, EFI_SYSTEM_TAB static CHAR16 *second_stage; static void *load_options; static UINT32 load_options_size; -static UINT8 verbose; EFI_GUID SHIM_LOCK_GUID = { 0x605dab50, 0xe046, 0x4300, {0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23} }; @@ -731,12 +730,8 @@ static EFI_STATUS verify_buffer (char *data, int datasize, * databases */ status = check_whitelist(cert, sha256hash, sha1hash); - - if (status == EFI_SUCCESS) { - if (verbose) - console_notify(L"Binary is whitelisted\n"); + if (status == EFI_SUCCESS) return status; - } /* * Check against the shim build key @@ -746,8 +741,6 @@ static EFI_STATUS verify_buffer (char *data, int datasize, shim_cert, sizeof(shim_cert), sha256hash, SHA256_DIGEST_SIZE)) { status = EFI_SUCCESS; - if (verbose) - console_notify(L"Binary is verified by the vendor certificate\n"); return status; } @@ -760,12 +753,9 @@ static EFI_STATUS verify_buffer (char *data, int datasize, vendor_cert, vendor_cert_size, sha256hash, SHA256_DIGEST_SIZE)) { status = EFI_SUCCESS; - if (verbose) - console_notify(L"Binary is verified by the vendor certificate\n"); return status; } - Print(L"Invalid signature\n"); status = EFI_ACCESS_DENIED; return status; @@ -896,9 +886,12 @@ static EFI_STATUS handle_image (void *data, unsigned int datasize, if (secure_mode ()) { efi_status = verify_buffer(data, datasize, &context); - if (efi_status != EFI_SUCCESS) { - Print(L"Verification failed\n"); + if (EFI_ERROR(efi_status)) { + console_error(L"Verification failed", efi_status); return efi_status; + } else { + if (verbose) + console_notify(L"Verification succeeded"); } } @@ -1681,9 +1674,6 @@ EFI_STATUS efi_main (EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *passed_systab) static SHIM_LOCK shim_lock_interface; EFI_HANDLE handle = NULL; EFI_STATUS efi_status; - UINT8 verbose_check; - UINTN verbose_check_size; - EFI_GUID global_var = EFI_GLOBAL_VARIABLE; verification_method = VERIFIED_BY_NOTHING; @@ -1708,15 +1698,9 @@ EFI_STATUS efi_main (EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *passed_systab) InitializeLib(image_handle, systab); setup_console(1); + setup_verbosity(); - verbose_check_size = 1; - efi_status = get_variable(L"SHIM_VERBOSE", (void *)&verbose_check, - &verbose_check_size, global_var); - if (!EFI_ERROR(efi_status)) - verbose = verbose_check; - - if (verbose) - console_notify_ascii(shim_version); + dprinta(shim_version); /* Set the second stage loader */ set_second_stage (image_handle); -- cgit v1.2.3 From 29d9c7c32799b3f9d95c8c971af827a049931801 Mon Sep 17 00:00:00 2001 From: Peter Jones Date: Fri, 4 Oct 2013 13:54:35 -0400 Subject: Put SHIM_VERBOSE under shim's guid, not global. Signed-off-by: Peter Jones --- lib/console.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/console.c b/lib/console.c index 1f8f59ca..2fc8db3a 100644 --- a/lib/console.c +++ b/lib/console.c @@ -11,6 +11,8 @@ #include #include +static EFI_GUID SHIM_LOCK_GUID = { 0x605dab50, 0xe046, 0x4300, {0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23} }; + static int min(int a, int b) { if (a < b) @@ -409,13 +411,13 @@ VOID setup_verbosity(VOID) { EFI_STATUS status; - EFI_GUID global_var = EFI_GLOBAL_VARIABLE; + EFI_GUID guid = SHIM_LOCK_GUID; UINT8 verbose_check; UINTN verbose_check_size; verbose_check_size = 1; status = get_variable(L"SHIM_VERBOSE", (void *)&verbose_check, - &verbose_check_size, global_var); + &verbose_check_size, guid); verbose = 0; if (!EFI_ERROR(status)) verbose = verbose_check; -- cgit v1.2.3 From 6caa9bad715eba8ce423527f8b876a636327b0be Mon Sep 17 00:00:00 2001 From: Andrew Boie Date: Tue, 12 Nov 2013 10:31:59 -0500 Subject: allow 32-bit compilation with 64-bit compiler Also removed unused LIB_PATH from some Makefiles. Change-Id: I7d28d18f7531b51b6121a2ffb88bcaedec57c467 Signed-off-by: Andrew Boie --- Cryptlib/Makefile | 5 +++-- Cryptlib/OpenSSL/Makefile | 4 +--- Makefile | 3 +++ lib/Makefile | 3 +++ 4 files changed, 10 insertions(+), 5 deletions(-) (limited to 'lib') diff --git a/Cryptlib/Makefile b/Cryptlib/Makefile index a05a4db0..d24e59e7 100644 --- a/Cryptlib/Makefile +++ b/Cryptlib/Makefile @@ -1,7 +1,5 @@ ARCH = $(shell uname -m | sed s,i[3456789]86,ia32,) -LIB_PATH = /usr/lib64 - EFI_INCLUDE = /usr/include/efi EFI_INCLUDES = -nostdinc -IInclude -I$(EFI_INCLUDE) -I$(EFI_INCLUDE)/$(ARCH) -I$(EFI_INCLUDE)/protocol EFI_PATH = /usr/lib64/gnuefi @@ -14,6 +12,9 @@ CFLAGS = -ggdb -O0 -I. -fno-stack-protector -fno-strict-aliasing -fpic -fshort- ifeq ($(ARCH),x86_64) CFLAGS += -DEFI_FUNCTION_WRAPPER -DGNU_EFI_USE_MS_ABI endif +ifeq ($(ARCH),ia32) + CFLAGS += -m32 +endif LDFLAGS = -nostdlib -znocombreloc TARGET = libcryptlib.a diff --git a/Cryptlib/OpenSSL/Makefile b/Cryptlib/OpenSSL/Makefile index 3d5a87cd..8e2f2a6f 100644 --- a/Cryptlib/OpenSSL/Makefile +++ b/Cryptlib/OpenSSL/Makefile @@ -1,7 +1,5 @@ ARCH = $(shell uname -m | sed s,i[3456789]86,ia32,) -LIB_PATH = /usr/lib64 - EFI_INCLUDE = /usr/include/efi EFI_INCLUDES = -I../Include -I$(EFI_INCLUDE) -I$(EFI_INCLUDE)/$(ARCH) -I$(EFI_INCLUDE)/protocol EFI_PATH = /usr/lib64/gnuefi @@ -15,7 +13,7 @@ ifeq ($(ARCH),x86_64) CFLAGS += -DEFI_FUNCTION_WRAPPER -DGNU_EFI_USE_MS_ABI -DSIXTY_FOUR_BIT_LONG endif ifeq ($(ARCH),ia32) - CFLAGS += -DTHIRTY_TWO_BIT + CFLAGS += -m32 -DTHIRTY_TWO_BIT endif LDFLAGS = -nostdlib -znocombreloc diff --git a/Makefile b/Makefile index d619ff49..e65d28d3 100644 --- a/Makefile +++ b/Makefile @@ -28,6 +28,9 @@ endif ifeq ($(ARCH),x86_64) CFLAGS += -DEFI_FUNCTION_WRAPPER -DGNU_EFI_USE_MS_ABI endif +ifeq ($(ARCH),ia32) + CFLAGS += -m32 +endif ifneq ($(origin VENDOR_CERT_FILE), undefined) CFLAGS += -DVENDOR_CERT_FILE=\"$(VENDOR_CERT_FILE)\" endif diff --git a/lib/Makefile b/lib/Makefile index adb03477..a9c9cf66 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -17,6 +17,9 @@ CFLAGS = -ggdb -O0 -fno-stack-protector -fno-strict-aliasing -fpic \ ifeq ($(ARCH),x86_64) CFLAGS += -DEFI_FUNCTION_WRAPPER -DGNU_EFI_USE_MS_ABI endif +ifeq ($(ARCH),ia32) + CFLAGS += -m32 +endif lib.a: $(LIBFILES) ar rcs lib.a $(LIBFILES) -- cgit v1.2.3 From 28cd5c6b9a797cda2e166b90c29c972613080c1a Mon Sep 17 00:00:00 2001 From: Peter Jones Date: Thu, 21 Nov 2013 11:48:24 -0500 Subject: Fix wrong sizeof(). CHAR16* vs CHAR16**, so the result is the same on all platforms. Detected by coverity. Signed-off-by: Peter Jones --- lib/shell.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/shell.c b/lib/shell.c index 51de4e0d..7337834a 100644 --- a/lib/shell.c +++ b/lib/shell.c @@ -35,7 +35,7 @@ argsplit(EFI_HANDLE image, int *argc, CHAR16*** ARGV) (*argc)++; /* we counted spaces, so add one for initial */ - *ARGV = AllocatePool(*argc * sizeof(*ARGV)); + *ARGV = AllocatePool(*argc * sizeof(**ARGV)); if (!*ARGV) { return EFI_OUT_OF_RESOURCES; } -- cgit v1.2.3 From 040f08c24960bf9076c07d92c46d5f32a1f186d3 Mon Sep 17 00:00:00 2001 From: Peter Jones Date: Thu, 21 Nov 2013 11:48:24 -0500 Subject: Initialize entries before we pass it to another function. Coverity scan noticed that entries is uninitialized when we pass its location to another function. Signed-off-by: Peter Jones --- lib/simple_file.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/simple_file.c b/lib/simple_file.c index 3af0ec8d..d345d870 100644 --- a/lib/simple_file.c +++ b/lib/simple_file.c @@ -415,7 +415,7 @@ simple_file_selector(EFI_HANDLE *im, CHAR16 **title, CHAR16 *name, CHAR16 *filter, CHAR16 **result) { EFI_STATUS status; - CHAR16 **entries; + CHAR16 **entries = NULL; EFI_FILE_INFO *dmp; int count, select, len; CHAR16 *newname, *selected; -- cgit v1.2.3 From 17621118315466dc878cf468d8c15ffadcb50482 Mon Sep 17 00:00:00 2001 From: Peter Jones Date: Thu, 21 Nov 2013 11:48:24 -0500 Subject: Error check the right thing in get_variable_attr() when allocating. Signed-off-by: Peter Jones --- lib/variables.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/variables.c b/lib/variables.c index 81bd34db..3a9735e6 100644 --- a/lib/variables.c +++ b/lib/variables.c @@ -224,7 +224,7 @@ get_variable_attr(CHAR16 *var, UINT8 **data, UINTN *len, EFI_GUID owner, return efi_status; *data = AllocateZeroPool(*len); - if (!data) + if (!*data) return EFI_OUT_OF_RESOURCES; efi_status = uefi_call_wrapper(RT->GetVariable, 5, var, &owner, -- cgit v1.2.3 From dcc523811b7763036682ba42cc83cbf88f42a8f2 Mon Sep 17 00:00:00 2001 From: Gary Ching-Pang Lin Date: Wed, 25 Jun 2014 10:02:18 -0400 Subject: MokManager: handle the error status from ReadKeyStroke On some machines, even though the key event was signaled, ReadKeyStroke still got EFI_NOT_READY. This commit handles the error status to avoid console_get_keystroke from returning unexpected keys. Signed-off-by: Gary Ching-Pang Lin Conflicts: MokManager.c --- MokManager.c | 17 +++++++++++++---- include/console.h | 4 ++-- lib/console.c | 26 ++++++++++++++++++-------- 3 files changed, 33 insertions(+), 14 deletions(-) (limited to 'lib') diff --git a/MokManager.c b/MokManager.c index 0ab308f7..50cb9d7f 100644 --- a/MokManager.c +++ b/MokManager.c @@ -488,13 +488,19 @@ static EFI_STATUS list_keys (void *KeyList, UINTN KeyListSize, CHAR16 *title) return EFI_SUCCESS; } -static UINT8 get_line (UINT32 *length, CHAR16 *line, UINT32 line_max, UINT8 show) +static EFI_STATUS get_line (UINT32 *length, CHAR16 *line, UINT32 line_max, UINT8 show) { EFI_INPUT_KEY key; + EFI_STATUS status; unsigned int count = 0; do { - key = console_get_keystroke(); + status = console_get_keystroke(&key); + if (EFI_ERROR (status)) { + console_error(L"Failed to read the keystroke", status); + *length = 0; + return status; + } if ((count >= line_max && key.UnicodeChar != CHAR_BACKSPACE) || @@ -525,7 +531,7 @@ static UINT8 get_line (UINT32 *length, CHAR16 *line, UINT32 line_max, UINT8 show *length = count; - return 1; + return EFI_SUCCESS; } static EFI_STATUS compute_pw_hash (void *Data, UINTN DataSize, UINT8 *password, @@ -989,6 +995,7 @@ static INTN mok_deletion_prompt (void *MokDel, UINTN MokDelSize) static CHAR16 get_password_charater (CHAR16 *prompt) { SIMPLE_TEXT_OUTPUT_MODE SavedMode; + EFI_STATUS status; CHAR16 *message[2]; CHAR16 character; UINTN length; @@ -1003,7 +1010,9 @@ static CHAR16 get_password_charater (CHAR16 *prompt) message[1] = NULL; length = StrLen(message[0]); console_print_box_at(message, -1, -length-4, -5, length+4, 3, 0, 1); - get_line(&pw_length, &character, 1, 0); + status = get_line(&pw_length, &character, 1, 0); + if (EFI_ERROR(status)) + character = 0; console_restore_mode(&SavedMode); diff --git a/include/console.h b/include/console.h index e6c2818f..9c793ea5 100644 --- a/include/console.h +++ b/include/console.h @@ -1,8 +1,8 @@ #ifndef _SHIM_LIB_CONSOLE_H #define _SHIM_LIB_CONSOLE_H 1 -EFI_INPUT_KEY -console_get_keystroke(void); +EFI_STATUS +console_get_keystroke(EFI_INPUT_KEY *key); void console_print_box_at(CHAR16 *str_arr[], int highlight, int start_col, int start_row, int size_cols, int size_rows, int offset, int lines); void diff --git a/lib/console.c b/lib/console.c index 2fc8db3a..41ed83a3 100644 --- a/lib/console.c +++ b/lib/console.c @@ -40,16 +40,18 @@ SetMem16(CHAR16 *dst, UINT32 n, CHAR16 c) } } -EFI_INPUT_KEY -console_get_keystroke(void) +EFI_STATUS +console_get_keystroke(EFI_INPUT_KEY *key) { - EFI_INPUT_KEY key; UINTN EventIndex; + EFI_STATUS status; - uefi_call_wrapper(BS->WaitForEvent, 3, 1, &ST->ConIn->WaitForKey, &EventIndex); - uefi_call_wrapper(ST->ConIn->ReadKeyStroke, 2, ST->ConIn, &key); + do { + uefi_call_wrapper(BS->WaitForEvent, 3, 1, &ST->ConIn->WaitForKey, &EventIndex); + status = uefi_call_wrapper(ST->ConIn->ReadKeyStroke, 2, ST->ConIn, key); + } while (status == EFI_NOT_READY); - return key; + return status; } void @@ -162,6 +164,8 @@ console_print_box(CHAR16 *str_arr[], int highlight) { SIMPLE_TEXT_OUTPUT_MODE SavedConsoleMode; SIMPLE_TEXT_OUTPUT_INTERFACE *co = ST->ConOut; + EFI_INPUT_KEY key; + CopyMem(&SavedConsoleMode, co->Mode, sizeof(SavedConsoleMode)); uefi_call_wrapper(co->EnableCursor, 2, co, FALSE); uefi_call_wrapper(co->SetAttribute, 2, co, EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE); @@ -169,7 +173,7 @@ console_print_box(CHAR16 *str_arr[], int highlight) console_print_box_at(str_arr, highlight, 0, 0, -1, -1, 0, count_lines(str_arr)); - console_get_keystroke(); + console_get_keystroke(&key); uefi_call_wrapper(co->EnableCursor, 2, co, SavedConsoleMode.CursorVisible); @@ -184,6 +188,7 @@ console_select(CHAR16 *title[], CHAR16* selectors[], int start) SIMPLE_TEXT_OUTPUT_MODE SavedConsoleMode; SIMPLE_TEXT_OUTPUT_INTERFACE *co = ST->ConOut; EFI_INPUT_KEY k; + EFI_STATUS status; int selector; int selector_lines = count_lines(selectors); int selector_max_cols = 0; @@ -237,7 +242,12 @@ console_select(CHAR16 *title[], CHAR16* selectors[], int start) size_cols, size_rows, 0, lines); do { - k = console_get_keystroke(); + status = console_get_keystroke(&k); + if (EFI_ERROR (status)) { + Print(L"Failed to read the keystroke: %r", status); + selector = -1; + break; + } if (k.ScanCode == SCAN_ESC) { selector = -1; -- cgit v1.2.3 From d8d7464f2cdd86ae01293086119463bf4a6b4a9c Mon Sep 17 00:00:00 2001 From: Gary Ching-Pang Lin Date: Wed, 25 Jun 2014 10:15:31 -0400 Subject: Remove the duplicate calls in lib/console.c Signed-off-by: Gary Ching-Pang Lin --- lib/console.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'lib') diff --git a/lib/console.c b/lib/console.c index 41ed83a3..83ee679e 100644 --- a/lib/console.c +++ b/lib/console.c @@ -175,8 +175,6 @@ console_print_box(CHAR16 *str_arr[], int highlight) console_get_keystroke(&key); - uefi_call_wrapper(co->EnableCursor, 2, co, SavedConsoleMode.CursorVisible); - uefi_call_wrapper(co->EnableCursor, 2, co, SavedConsoleMode.CursorVisible); uefi_call_wrapper(co->SetCursorPosition, 3, co, SavedConsoleMode.CursorColumn, SavedConsoleMode.CursorRow); uefi_call_wrapper(co->SetAttribute, 2, co, SavedConsoleMode.Attribute); @@ -272,8 +270,6 @@ console_select(CHAR16 *title[], CHAR16* selectors[], int start) } while (!(k.ScanCode == SCAN_NULL && k.UnicodeChar == CHAR_CARRIAGE_RETURN)); - uefi_call_wrapper(co->EnableCursor, 2, co, SavedConsoleMode.CursorVisible); - uefi_call_wrapper(co->EnableCursor, 2, co, SavedConsoleMode.CursorVisible); uefi_call_wrapper(co->SetCursorPosition, 3, co, SavedConsoleMode.CursorColumn, SavedConsoleMode.CursorRow); uefi_call_wrapper(co->SetAttribute, 2, co, SavedConsoleMode.Attribute); -- cgit v1.2.3 From 7a72592b75879542e9ebd808868f83a78bdfbbc6 Mon Sep 17 00:00:00 2001 From: Gary Ching-Pang Lin Date: Wed, 25 Jun 2014 10:55:12 -0400 Subject: Check the secure variables with the lib functions There are functions defined in lib to check the secure variables. Use the functions to shun the duplicate code. Signed-off-by: Gary Ching-Pang Lin Conflicts: shim.c --- lib/variables.c | 14 ++++++++++---- shim.c | 32 ++------------------------------ 2 files changed, 12 insertions(+), 34 deletions(-) (limited to 'lib') diff --git a/lib/variables.c b/lib/variables.c index 3a9735e6..4c64d7e4 100644 --- a/lib/variables.c +++ b/lib/variables.c @@ -284,9 +284,12 @@ variable_is_setupmode(void) /* set to 1 because we return true if SetupMode doesn't exist */ UINT8 SetupMode = 1; UINTN DataSize = sizeof(SetupMode); + EFI_STATUS status; - uefi_call_wrapper(RT->GetVariable, 5, L"SetupMode", &GV_GUID, NULL, - &DataSize, &SetupMode); + status = uefi_call_wrapper(RT->GetVariable, 5, L"SetupMode", &GV_GUID, NULL, + &DataSize, &SetupMode); + if (EFI_ERROR(status)) + return 1; return SetupMode; } @@ -297,10 +300,13 @@ variable_is_secureboot(void) /* return false if variable doesn't exist */ UINT8 SecureBoot = 0; UINTN DataSize; + EFI_STATUS status; DataSize = sizeof(SecureBoot); - uefi_call_wrapper(RT->GetVariable, 5, L"SecureBoot", &GV_GUID, NULL, - &DataSize, &SecureBoot); + status = uefi_call_wrapper(RT->GetVariable, 5, L"SecureBoot", &GV_GUID, NULL, + &DataSize, &SecureBoot); + if (EFI_ERROR(status)) + return 0; return SecureBoot; } diff --git a/shim.c b/shim.c index 210e778a..14fb601c 100644 --- a/shim.c +++ b/shim.c @@ -475,44 +475,16 @@ static EFI_STATUS check_whitelist (WIN_CERTIFICATE_EFI_PKCS *cert, static BOOLEAN secure_mode (void) { - EFI_STATUS status; - EFI_GUID global_var = EFI_GLOBAL_VARIABLE; - UINTN len; - UINT8 *Data; - UINT8 sb, setupmode; - if (user_insecure_mode) return FALSE; - status = get_variable(L"SecureBoot", &Data, &len, global_var); - if (status != EFI_SUCCESS) { + if (variable_is_secureboot() != 1) { if (verbose && !in_protocol) console_notify(L"Secure boot not enabled"); return FALSE; } - sb = *Data; - FreePool(Data); - - if (sb != 1) { - if (verbose && !in_protocol) - console_notify(L"Secure boot not enabled"); - return FALSE; - } - - /* If we /do/ have "SecureBoot", but /don't/ have "SetupMode", - * then the implementation is bad, but we assume that secure boot is - * enabled according to the status of "SecureBoot". If we have both - * of them, then "SetupMode" may tell us additional data, and we need - * to consider it. - */ - status = get_variable(L"SetupMode", &Data, &len, global_var); - if (status != EFI_SUCCESS) - return TRUE; - - setupmode = *Data; - FreePool(Data); - if (setupmode == 1) { + if (variable_is_setupmode() == 1) { if (verbose && !in_protocol) console_notify(L"Platform is in setup mode"); return FALSE; -- cgit v1.2.3 From 9ea3d9b401ed73ae95b60e6b566f9293af3ac4d7 Mon Sep 17 00:00:00 2001 From: Peter Jones Date: Wed, 25 Jun 2014 10:55:56 -0400 Subject: Make sure we default to assuming we're locked down. If "SecureBoot" exists but "SetupMode" does not, assume "SetupMode" says we're not in Setup Mode. Signed-off-by: Peter Jones --- include/variables.h | 2 +- lib/variables.c | 8 ++++---- shim.c | 8 +++++++- 3 files changed, 12 insertions(+), 6 deletions(-) (limited to 'lib') diff --git a/include/variables.h b/include/variables.h index b207dbf3..deed269c 100644 --- a/include/variables.h +++ b/include/variables.h @@ -50,7 +50,7 @@ SETOSIndicationsAndReboot(UINT64 indications); int variable_is_secureboot(void); int -variable_is_setupmode(void); +variable_is_setupmode(int default_return); EFI_STATUS variable_enroll_hash(CHAR16 *var, EFI_GUID owner, UINT8 hash[SHA256_DIGEST_SIZE]); diff --git a/lib/variables.c b/lib/variables.c index 4c64d7e4..59d7d054 100644 --- a/lib/variables.c +++ b/lib/variables.c @@ -139,7 +139,7 @@ SetSecureVariable(CHAR16 *var, UINT8 *Data, UINTN len, EFI_GUID owner, /* Microsoft request: Bugs in some UEFI platforms mean that PK or any * other secure variable can be updated or deleted programmatically, * so prevent */ - if (!variable_is_setupmode()) + if (!variable_is_setupmode(1)) return EFI_SECURITY_VIOLATION; if (createtimebased) { @@ -279,17 +279,17 @@ find_in_variable_esl(CHAR16* var, EFI_GUID owner, UINT8 *key, UINTN keylen) } int -variable_is_setupmode(void) +variable_is_setupmode(int default_return) { /* set to 1 because we return true if SetupMode doesn't exist */ - UINT8 SetupMode = 1; + UINT8 SetupMode = default_return; UINTN DataSize = sizeof(SetupMode); EFI_STATUS status; status = uefi_call_wrapper(RT->GetVariable, 5, L"SetupMode", &GV_GUID, NULL, &DataSize, &SetupMode); if (EFI_ERROR(status)) - return 1; + return default_return; return SetupMode; } diff --git a/shim.c b/shim.c index 14fb601c..fe73ec1a 100644 --- a/shim.c +++ b/shim.c @@ -484,7 +484,13 @@ static BOOLEAN secure_mode (void) return FALSE; } - if (variable_is_setupmode() == 1) { + /* If we /do/ have "SecureBoot", but /don't/ have "SetupMode", + * then the implementation is bad, but we assume that secure boot is + * enabled according to the status of "SecureBoot". If we have both + * of them, then "SetupMode" may tell us additional data, and we need + * to consider it. + */ + if (variable_is_setupmode(0) == 1) { if (verbose && !in_protocol) console_notify(L"Platform is in setup mode"); return FALSE; -- cgit v1.2.3 From f7a182154e19e99e1eb88f5fe8111a37e68cda8e Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Tue, 12 Aug 2014 10:54:05 -0400 Subject: Factor out x86-isms and add cross compile support This patch cleans up and refactors the Makefiles to better allow new architectures to be added: - remove unused Makefile definitions - import Makefile definitions from top level rather than redefining - move x86 specific CFLAGS to inside ifeq() blocks - remove x86 inline asm - allow $(FORMAT) to be overridden: this is necessary as there exists no EFI or PE/COFF aware objcopy for ARM Signed-off-by: Ard Biesheuvel --- Cryptlib/Makefile | 16 ++++++---------- Cryptlib/OpenSSL/Makefile | 15 ++++++--------- Makefile | 45 +++++++++++++++++++++++++++------------------ lib/Makefile | 14 ++++---------- netboot.c | 10 +--------- 5 files changed, 44 insertions(+), 56 deletions(-) (limited to 'lib') diff --git a/Cryptlib/Makefile b/Cryptlib/Makefile index 678baaca..73a1e2b2 100644 --- a/Cryptlib/Makefile +++ b/Cryptlib/Makefile @@ -1,19 +1,15 @@ -ARCH = $(shell uname -m | sed s,i[3456789]86,ia32,) -EFI_INCLUDE = /usr/include/efi -EFI_INCLUDES = -nostdinc -IInclude -I$(EFI_INCLUDE) -I$(EFI_INCLUDE)/$(ARCH) -I$(EFI_INCLUDE)/protocol -EFI_PATH = /usr/lib64/gnuefi - -LIB_GCC = $(shell $(CC) -print-libgcc-file-name) -EFI_LIBS = -lefi -lgnuefi $(LIB_GCC) +EFI_INCLUDES = -IInclude -I$(EFI_INCLUDE) -I$(EFI_INCLUDE)/$(ARCH) -I$(EFI_INCLUDE)/protocol CFLAGS = -ggdb -O0 -I. -fno-stack-protector -fno-strict-aliasing -fpic -fshort-wchar \ - -Wall $(EFI_INCLUDES) -mno-red-zone -maccumulate-outgoing-args -mno-sse -mno-mmx + -Wall $(EFI_INCLUDES) + ifeq ($(ARCH),x86_64) - CFLAGS += -DEFI_FUNCTION_WRAPPER -DGNU_EFI_USE_MS_ABI + CFLAGS += -mno-mmx -mno-sse -mno-red-zone -nostdinc -maccumulate-outgoing-args \ + -DEFI_FUNCTION_WRAPPER -DGNU_EFI_USE_MS_ABI endif ifeq ($(ARCH),ia32) - CFLAGS += -m32 + CFLAGS += -mno-mmx -mno-sse -mno-red-zone -nostdinc -maccumulate-outgoing-args -m32 endif LDFLAGS = -nostdlib -znocombreloc diff --git a/Cryptlib/OpenSSL/Makefile b/Cryptlib/OpenSSL/Makefile index 8e2f2a6f..90975801 100644 --- a/Cryptlib/OpenSSL/Makefile +++ b/Cryptlib/OpenSSL/Makefile @@ -1,19 +1,16 @@ -ARCH = $(shell uname -m | sed s,i[3456789]86,ia32,) -EFI_INCLUDE = /usr/include/efi EFI_INCLUDES = -I../Include -I$(EFI_INCLUDE) -I$(EFI_INCLUDE)/$(ARCH) -I$(EFI_INCLUDE)/protocol -EFI_PATH = /usr/lib64/gnuefi -LIB_GCC = $(shell $(CC) -print-libgcc-file-name) -EFI_LIBS = -lefi -lgnuefi $(LIB_GCC) - -CFLAGS = -ggdb -O0 -I. -I.. -I../Include/ -Icrypto -fno-stack-protector -fno-strict-aliasing -fpic -fshort-wchar -nostdinc -mno-mmx -mno-sse -mno-red-zone -maccumulate-outgoing-args \ +CFLAGS = -ggdb -O0 -I. -I.. -I../Include/ -Icrypto -fno-stack-protector -fno-strict-aliasing -fpic -fshort-wchar -nostdinc \ -Wall $(EFI_INCLUDES) -DOPENSSL_SYSNAME_UWIN -DOPENSSL_SYS_UEFI -DL_ENDIAN -D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE -DOPENSSL_NO_CAMELLIA -DOPENSSL_NO_SEED -DOPENSSL_NO_RC5 -DOPENSSL_NO_MDC2 -DOPENSSL_NO_SOCK -DOPENSSL_NO_CMS -DOPENSSL_NO_JPAKE -DOPENSSL_NO_CAPIENG -DOPENSSL_NO_ERR -DOPENSSL_NO_KRB5 -DOPENSSL_NO_DYNAMIC_ENGINE -DGETPID_IS_MEANINGLESS -DOPENSSL_NO_STDIO -DOPENSSL_NO_FP_API -DOPENSSL_NO_DGRAM -DOPENSSL_NO_SHA0 -DOPENSSL_NO_LHASH -DOPENSSL_NO_HW -DOPENSSL_NO_OCSP -DOPENSSL_NO_LOCKING -DOPENSSL_NO_DEPRECATED -DOPENSSL_SMALL_FOOTPRINT -DPEDANTIC + ifeq ($(ARCH),x86_64) - CFLAGS += -DEFI_FUNCTION_WRAPPER -DGNU_EFI_USE_MS_ABI -DSIXTY_FOUR_BIT_LONG + CFLAGS += -mno-mmx -mno-sse -mno-red-zone -maccumulate-outgoing-args \ + -DEFI_FUNCTION_WRAPPER -DGNU_EFI_USE_MS_ABI -DSIXTY_FOUR_BIT_LONG endif ifeq ($(ARCH),ia32) - CFLAGS += -m32 -DTHIRTY_TWO_BIT + CFLAGS += -mno-mmx -mno-sse -mno-red-zone -maccumulate-outgoing-args \ + -m32 -DTHIRTY_TWO_BIT endif LDFLAGS = -nostdlib -znocombreloc diff --git a/Makefile b/Makefile index df190a25..f65bb3b8 100644 --- a/Makefile +++ b/Makefile @@ -1,10 +1,14 @@ -ARCH = $(shell uname -m | sed s,i[3456789]86,ia32,) +CC = $(CROSS_COMPILE)gcc +LD = $(CROSS_COMPILE)ld +OBJCOPY = $(CROSS_COMPILE)objcopy + +ARCH = $(shell $(CC) -dumpmachine | cut -f1 -d- | sed s,i[3456789]86,ia32,) SUBDIRS = Cryptlib lib LIB_PATH = /usr/lib64 -EFI_INCLUDE = /usr/include/efi +EFI_INCLUDE := /usr/include/efi EFI_INCLUDES = -nostdinc -ICryptlib -ICryptlib/Include -I$(EFI_INCLUDE) -I$(EFI_INCLUDE)/$(ARCH) -I$(EFI_INCLUDE)/protocol -Iinclude EFI_PATH := /usr/lib64/gnuefi @@ -16,9 +20,7 @@ EFI_LDS = elf_$(ARCH)_efi.lds DEFAULT_LOADER := \\\\grub.efi CFLAGS = -ggdb -O0 -fno-stack-protector -fno-strict-aliasing -fpic \ - -fshort-wchar -Wall -Wsign-compare -Werror \ - -mno-red-zone -maccumulate-outgoing-args \ - -mno-mmx -mno-sse -fno-builtin \ + -fshort-wchar -Wall -Wsign-compare -Werror -fno-builtin \ "-DDEFAULT_LOADER=L\"$(DEFAULT_LOADER)\"" \ "-DDEFAULT_LOADER_CHAR=\"$(DEFAULT_LOADER)\"" \ $(EFI_INCLUDES) @@ -26,12 +28,15 @@ CFLAGS = -ggdb -O0 -fno-stack-protector -fno-strict-aliasing -fpic \ ifneq ($(origin OVERRIDE_SECURITY_POLICY), undefined) CFLAGS += -DOVERRIDE_SECURITY_POLICY endif + ifeq ($(ARCH),x86_64) - CFLAGS += -DEFI_FUNCTION_WRAPPER -DGNU_EFI_USE_MS_ABI + CFLAGS += -mno-mmx -mno-sse -mno-red-zone -nostdinc -maccumulate-outgoing-args \ + -DEFI_FUNCTION_WRAPPER -DGNU_EFI_USE_MS_ABI endif ifeq ($(ARCH),ia32) - CFLAGS += -m32 + CFLAGS += -mno-mmx -mno-sse -mno-red-zone -nostdinc -maccumulate-outgoing-args -m32 endif + ifneq ($(origin VENDOR_CERT_FILE), undefined) CFLAGS += -DVENDOR_CERT_FILE=\"$(VENDOR_CERT_FILE)\" endif @@ -95,26 +100,28 @@ MokManager.so: $(MOK_OBJS) Cryptlib/libcryptlib.a Cryptlib/OpenSSL/libopenssl.a $(LD) -o $@ $(LDFLAGS) $^ $(EFI_LIBS) lib/lib.a Cryptlib/libcryptlib.a: - $(MAKE) -C Cryptlib EFI_PATH=$(EFI_PATH) EFI_INCLUDE=$(EFI_INCLUDE) ARCH=$(ARCH) + $(MAKE) -C Cryptlib Cryptlib/OpenSSL/libopenssl.a: - $(MAKE) -C Cryptlib/OpenSSL EFI_PATH=$(EFI_PATH) EFI_INCLUDE=$(EFI_INCLUDE) ARCH=$(ARCH) + $(MAKE) -C Cryptlib/OpenSSL lib/lib.a: - $(MAKE) -C lib EFI_PATH=$(EFI_PATH) EFI_INCLUDE=$(EFI_INCLUDE) ARCH=$(ARCH) + $(MAKE) -C lib + +FORMAT ?= --target efi-app-$(ARCH) %.efi: %.so - objcopy -j .text -j .sdata -j .data \ - -j .dynamic -j .dynsym -j .rel \ - -j .rela -j .reloc -j .eh_frame \ + $(OBJCOPY) -j .text -j .sdata -j .data \ + -j .dynamic -j .dynsym -j .rel* \ + -j .rela* -j .reloc -j .eh_frame \ -j .vendor_cert \ - --target=efi-app-$(ARCH) $^ $@ - objcopy -j .text -j .sdata -j .data \ - -j .dynamic -j .dynsym -j .rel \ - -j .rela -j .reloc -j .eh_frame \ + $(FORMAT) $^ $@ + $(OBJCOPY) -j .text -j .sdata -j .data \ + -j .dynamic -j .dynsym -j .rel* \ + -j .rela* -j .reloc -j .eh_frame \ -j .debug_info -j .debug_abbrev -j .debug_aranges \ -j .debug_line -j .debug_str -j .debug_ranges \ - --target=efi-app-$(ARCH) $^ $@.debug + $(FORMAT) $^ $@.debug %.efi.signed: %.efi certdb/secmod.db pesign -n certdb -i $< -c "shim" -s -o $@ -f @@ -151,3 +158,5 @@ archive: tag @dir=$$PWD; cd /tmp; tar -c --bzip2 -f $$dir/shim-$(VERSION).tar.bz2 shim-$(VERSION) @rm -rf /tmp/shim-$(VERSION) @echo "The archive is in shim-$(VERSION).tar.bz2" + +export ARCH CC LD OBJCOPY EFI_INCLUDE diff --git a/lib/Makefile b/lib/Makefile index a9c9cf66..ebd21a14 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -2,23 +2,17 @@ TARGET = lib.a LIBFILES = simple_file.o guid.o console.o execute.o configtable.o shell.o variables.o security_policy.o -ARCH = $(shell uname -m | sed s,i[3456789]86,ia32,) - -EFI_INCLUDE = /usr/include/efi EFI_INCLUDES = -I$(EFI_INCLUDE) -I$(EFI_INCLUDE)/$(ARCH) -I$(EFI_INCLUDE)/protocol -I../include -EFI_CRT_OBJS = $(EFI_PATH)/crt0-efi-$(ARCH).o -EFI_LDS = $(EFI_PATH)/elf_$(ARCH)_efi.lds - CFLAGS = -ggdb -O0 -fno-stack-protector -fno-strict-aliasing -fpic \ - -fshort-wchar -Wall -mno-red-zone -DBUILD_EFI -fno-builtin \ - -Werror \ + -fshort-wchar -Wall -DBUILD_EFI -fno-builtin -Werror \ $(EFI_INCLUDES) + ifeq ($(ARCH),x86_64) - CFLAGS += -DEFI_FUNCTION_WRAPPER -DGNU_EFI_USE_MS_ABI + CFLAGS += -mno-red-zone -DEFI_FUNCTION_WRAPPER -DGNU_EFI_USE_MS_ABI endif ifeq ($(ARCH),ia32) - CFLAGS += -m32 + CFLAGS += -mno-red-zone -m32 endif lib.a: $(LIBFILES) diff --git a/netboot.c b/netboot.c index 5ef53f75..238937d3 100644 --- a/netboot.c +++ b/netboot.c @@ -40,15 +40,7 @@ #include "netboot.h" #include "str.h" -static inline unsigned short int __swap16(unsigned short int x) -{ - __asm__("xchgb %b0,%h0" - : "=q" (x) - : "0" (x)); - return x; -} - -#define ntohs(x) __swap16(x) +#define ntohs(x) __builtin_bswap16(x) /* supported both by GCC and clang */ #define htons(x) ntohs(x) static EFI_PXE_BASE_CODE *pxe; -- cgit v1.2.3