diff --git a/.gitignore b/.gitignore index d0d9129..312a0e3 100644 --- a/.gitignore +++ b/.gitignore @@ -25,3 +25,5 @@ shim_cert.h *.srl.old *.tar.* version.c +cov-int/ +scan-results/ diff --git a/.syntastic_c_config b/.syntastic_c_config index b93723b..507d008 100644 --- a/.syntastic_c_config +++ b/.syntastic_c_config @@ -1,16 +1,3 @@ --I/home/pjones/devel/github.com/shim/master/Cryptlib/OpenSSL --I/home/pjones/devel/github.com/shim/master/Cryptlib/OpenSSL/.. --I/home/pjones/devel/github.com/shim/master/Cryptlib/OpenSSL/../Include/ --I/home/pjones/devel/github.com/shim/master/Cryptlib/OpenSSL/crypto --I/usr/lib/gcc/x86_64-redhat-linux/7/include --I/home/pjones/devel/github.com/shim/master/Cryptlib/OpenSSL/../Include --I/usr/include/efi --I/usr/include/efi/x86_64 --I/usr/include/efi/protocol --I/home/pjones/devel/github.com/shim/master/Cryptlib/OpenSSL/crypto/asn1 --I/home/pjones/devel/github.com/shim/master/Cryptlib/OpenSSL/crypto/evp --I/home/pjones/devel/github.com/shim/master/Cryptlib/OpenSSL/crypto/modes --I/home/pjones/devel/github.com/shim/master/Cryptlib/OpenSSL/crypto/include -DL_ENDIAN -D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE @@ -29,18 +16,22 @@ -Werror=sign-compare -ffreestanding -std=gnu89 --I/usr/lib/gcc/x86_64-redhat-linux/7/include -nostdinc --I/home/pjones/devel/github.com/shim/master/Cryptlib --I/home/pjones/devel/github.com/shim/master/Cryptlib/Include --I/usr/include/efi --I/usr/include/efi/x86_64 --I/usr/include/efi/protocol --I/home/pjones/devel/github.com/shim/master/include +-I/usr/lib/gcc/x86_64-redhat-linux/7/include +-Iinclude +-ICryptlib/ +-ICryptlib/Include/ +-ICryptlib/OpenSSL/ +-ICryptlib/OpenSSL/crypto/ +-I/usr/include/efi/ +-I/usr/include/efi/x86_64/ +-I/usr/include/efi/protocol/ +-ICryptlib/OpenSSL/crypto/asn1/ +-ICryptlib/OpenSSL/crypto/evp/ +-ICryptlib/OpenSSL/crypto/modes/ +-ICryptlib/OpenSSL/crypto/include/ -iquote -/home/pjones/devel/github.com/shim/master --iquote -/home/pjones/devel/github.com/shim/master +. -mno-mmx -mno-sse -mno-red-zone diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..6cebdbc --- /dev/null +++ b/.travis.yml @@ -0,0 +1,17 @@ +language: c +cache: ccache +branches: + except: + - travis + +matrix: + include: + - os: linux + dist: trusty + services: docker + +before_install: + - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then docker pull vathpela/efi-ci-rawhide:v0 ; fi + +script: + - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then docker run vathpela/efi-ci-rawhide:v0 /bin/sh -c "cd /root/ && ./build.sh --branch \"$TRAVIS_BRANCH\" --commit \"$TRAVIS_COMMIT\" --commit-range \"$TRAVIS_COMMIT_RANGE\" --event-type \"$TRAVIS_EVENT_TYPE\" --pull-request \"$TRAVIS_PULL_REQUEST\" --pr-branch \"$TRAVIS_PULL_REQUEST_BRANCH\" --pr-sha \"$TRAVIS_PULL_REQUEST_SHA\" --remote \"$TRAVIS_PULL_REQUEST_SLUG\" --repo \"$TRAVIS_REPO_SLUG\" --test-subject shim" ; fi diff --git a/BUILDING b/BUILDING index 461b85c..533c646 100644 --- a/BUILDING +++ b/BUILDING @@ -27,12 +27,14 @@ Variables you should set to customize the build: Variables you could set to customize the build: - ENABLE_SHIM_CERT - if this variable is defined one the make command line, shim will + if this variable is defined on the make command line, shim will generate keys during the build and sign MokManager and fallback with them, and the signed version will be what gets installed with the install targets - ENABLE_HTTPBOOT build support for http booting +- REQUIRE_TPM + if tpm logging or extends return an error code, treat that as a fatal error. - ARCH This allows you to do a build for a different arch that we support. For instance, on x86_64 you could do "setarch linux32 make ARCH=ia32" to get diff --git a/Cryptlib/Include/OpenSslSupport.h b/Cryptlib/Include/OpenSslSupport.h index d7650b3..b38043c 100644 --- a/Cryptlib/Include/OpenSslSupport.h +++ b/Cryptlib/Include/OpenSslSupport.h @@ -17,11 +17,11 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #include #include -#include -#include -#include -#include -#include +#include "Base.h" +#include "Library/BaseLib.h" +#include "Library/BaseMemoryLib.h" +#include "Library/MemoryAllocationLib.h" +#include "Library/DebugLib.h" /* * Include stddef.h to avoid redefining "offsetof" @@ -380,5 +380,6 @@ extern FILE *stdout; #define atoi(nptr) AsciiStrDecimalToUintn(nptr) #define gettimeofday(tvp,tz) do { (tvp)->tv_sec = time(NULL); (tvp)->tv_usec = 0; } while (0) #define gmtime_r(timer,result) (result = NULL) +#define abort() #endif diff --git a/Cryptlib/InternalCryptLib.h b/Cryptlib/InternalCryptLib.h index 92cc963..e9a4c20 100644 --- a/Cryptlib/InternalCryptLib.h +++ b/Cryptlib/InternalCryptLib.h @@ -15,11 +15,11 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #ifndef __INTERNAL_CRYPT_LIB_H__ #define __INTERNAL_CRYPT_LIB_H__ -#include -#include -#include -#include -#include +#include "Library/BaseLib.h" +#include "Library/BaseMemoryLib.h" +#include "Library/MemoryAllocationLib.h" +#include "Library/DebugLib.h" +#include "Library/BaseCryptLib.h" #include "OpenSslSupport.h" diff --git a/Cryptlib/Library/BaseLib.h b/Cryptlib/Library/BaseLib.h index c29919e..5d32684 100644 --- a/Cryptlib/Library/BaseLib.h +++ b/Cryptlib/Library/BaseLib.h @@ -5,4 +5,5 @@ UINT32 WriteUnaligned32 (UINT32 *Buffer, UINT32 Value); UINTN AsciiStrSize (CHAR8 *string); char *AsciiStrnCpy(char *Destination, char *Source, UINTN count); char *AsciiStrCat(char *Destination, char *Source); +CHAR8 *AsciiStrCpy(CHAR8 *Destination, CHAR8 *Source); UINTN AsciiStrDecimalToUintn(const char *String); diff --git a/Cryptlib/Makefile b/Cryptlib/Makefile index bf9d0dc..2aa5695 100644 --- a/Cryptlib/Makefile +++ b/Cryptlib/Makefile @@ -5,14 +5,16 @@ CFLAGS = -ggdb -O0 -I$(TOPDIR) -iquote $(TOPDIR) -fno-stack-protector -fno-stri -Wall $(EFI_INCLUDES) -std=gnu89 \ -ffreestanding -I$(shell $(CC) -print-file-name=include) +CLANG_BUGS = $(if $(findstring gcc,$(CC)),-maccumulate-outgoing-args,) + ifeq ($(ARCH),x86_64) - CFLAGS += -mno-mmx -mno-sse -mno-red-zone -nostdinc -maccumulate-outgoing-args \ - -DEFI_FUNCTION_WRAPPER -DGNU_EFI_USE_MS_ABI -DNO_BUILTIN_VA_FUNCS \ - -DMDE_CPU_X64 + CFLAGS += -mno-mmx -mno-sse -mno-red-zone -nostdinc $(CLANG_BUGS) \ + -m64 -DEFI_FUNCTION_WRAPPER -DGNU_EFI_USE_MS_ABI \ + -DNO_BUILTIN_VA_FUNCS -DMDE_CPU_X64 endif ifeq ($(ARCH),ia32) - CFLAGS += -mno-mmx -mno-sse -mno-red-zone -nostdinc -maccumulate-outgoing-args -m32 \ - -DMDE_CPU_IA32 + CFLAGS += -mno-mmx -mno-sse -mno-red-zone -nostdinc \ + $(CLANG_BUGS) -m32 -DMDE_CPU_IA32 endif ifeq ($(ARCH),aarch64) CFLAGS += -DMDE_CPU_AARCH64 @@ -40,7 +42,7 @@ OBJS = Hash/CryptMd4Null.o \ Pk/CryptTs.o \ Pk/CryptX509.o \ Pk/CryptAuthenticode.o \ - Pem/CryptPem.o \ + Pem/CryptPemNull.o \ SysCall/CrtWrapper.o \ SysCall/TimerWrapper.o \ SysCall/BaseMemAllocation.o \ diff --git a/Cryptlib/OpenSSL/Makefile b/Cryptlib/OpenSSL/Makefile index b61b66d..916feac 100644 --- a/Cryptlib/OpenSSL/Makefile +++ b/Cryptlib/OpenSSL/Makefile @@ -8,14 +8,16 @@ CFLAGS = -ggdb -O0 -I$(TOPDIR) -I$(TOPDIR)/.. -I$(TOPDIR)/../Include/ -I$(TOPDI -ffreestanding -std=gnu89 -I$(shell $(CC) -print-file-name=include) \ -Wall $(EFI_INCLUDES) -DL_ENDIAN -D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE -DOPENSSL_SMALL_FOOTPRINT -DPEDANTIC +CLANG_BUGS = $(if $(findstring gcc,$(CC)),-maccumulate-outgoing-args,) + ifeq ($(ARCH),x86_64) - CFLAGS += -mno-mmx -mno-sse -mno-red-zone -maccumulate-outgoing-args \ - -DEFI_FUNCTION_WRAPPER -DGNU_EFI_USE_MS_ABI \ + CFLAGS += -mno-mmx -mno-sse -mno-red-zone $(CLANG_BUGS) \ + -m64 -DEFI_FUNCTION_WRAPPER -DGNU_EFI_USE_MS_ABI \ -UNO_BUILTIN_VA_FUNCS -DMDE_CPU_X64 endif ifeq ($(ARCH),ia32) - CFLAGS += -mno-mmx -mno-sse -mno-red-zone -maccumulate-outgoing-args \ - -m32 -DMDE_CPU_IA32 + CFLAGS += -mno-mmx -mno-sse -mno-red-zone -nostdinc \ + $(CLANG_BUGS) -m32 -DMDE_CPU_IA32 endif ifeq ($(ARCH),aarch64) CFLAGS += -O2 -DMDE_CPU_AARCH64 diff --git a/Cryptlib/Pem/CryptPem.c b/Cryptlib/Pem/CryptPem.c deleted file mode 100644 index 51e648b..0000000 --- a/Cryptlib/Pem/CryptPem.c +++ /dev/null @@ -1,135 +0,0 @@ -/** @file - PEM (Privacy Enhanced Mail) Format Handler Wrapper Implementation over OpenSSL. - -Copyright (c) 2010 - 2013, 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 "InternalCryptLib.h" -#include - -/** - Callback function for password phrase conversion used for retrieving the encrypted PEM. - - @param[out] Buf Pointer to the buffer to write the passphrase to. - @param[in] Size Maximum length of the passphrase (i.e. the size of Buf). - @param[in] Flag A flag which is set to 0 when reading and 1 when writing. - @param[in] Key Key data to be passed to the callback routine. - - @retval The number of characters in the passphrase or 0 if an error occurred. - -**/ -INTN -PasswordCallback ( - OUT CHAR8 *Buf, - IN INTN Size, - IN INTN Flag, - IN VOID *Key - ) -{ - INTN KeyLength; - - ZeroMem ((VOID *) Buf, (UINTN) Size); - if (Key != NULL) { - // - // Duplicate key phrase directly. - // - KeyLength = (INTN) AsciiStrLen ((CHAR8 *)Key); - KeyLength = (KeyLength > Size ) ? Size : KeyLength; - CopyMem (Buf, Key, (UINTN) KeyLength); - return KeyLength; - } else { - return 0; - } -} - -/** - Retrieve the RSA Private Key from the password-protected PEM key data. - - @param[in] PemData Pointer to the PEM-encoded key data to be retrieved. - @param[in] PemSize Size of the PEM key data in bytes. - @param[in] Password NULL-terminated passphrase used for encrypted PEM key data. - @param[out] RsaContext Pointer to new-generated RSA context which contain the retrieved - RSA private key component. Use RsaFree() function to free the - resource. - - If PemData is NULL, then return FALSE. - If RsaContext is NULL, then return FALSE. - - @retval TRUE RSA Private Key was retrieved successfully. - @retval FALSE Invalid PEM key data or incorrect password. - -**/ -BOOLEAN -EFIAPI -RsaGetPrivateKeyFromPem ( - IN CONST UINT8 *PemData, - IN UINTN PemSize, - IN CONST CHAR8 *Password, - OUT VOID **RsaContext - ) -{ - BOOLEAN Status; - BIO *PemBio; - - // - // Check input parameters. - // - if (PemData == NULL || RsaContext == NULL || PemSize > INT_MAX) { - return FALSE; - } - - // - // Add possible block-cipher descriptor for PEM data decryption. - // NOTE: Only support most popular ciphers (3DES, AES) for the encrypted PEM. - // - if (EVP_add_cipher (EVP_des_ede3_cbc ()) == 0) { - return FALSE; - } - if (EVP_add_cipher (EVP_aes_128_cbc ()) == 0) { - return FALSE; - } - if (EVP_add_cipher (EVP_aes_192_cbc ()) == 0) { - return FALSE; - } - if (EVP_add_cipher (EVP_aes_256_cbc ()) == 0) { - return FALSE; - } - - Status = FALSE; - - // - // Read encrypted PEM Data. - // - PemBio = BIO_new (BIO_s_mem ()); - if (PemBio == NULL) { - goto _Exit; - } - - if (BIO_write (PemBio, PemData, (int) PemSize) <= 0) { - goto _Exit; - } - - // - // Retrieve RSA Private Key from encrypted PEM data. - // - *RsaContext = PEM_read_bio_RSAPrivateKey (PemBio, NULL, (pem_password_cb *) &PasswordCallback, (void *) Password); - if (*RsaContext != NULL) { - Status = TRUE; - } - -_Exit: - // - // Release Resources. - // - BIO_free (PemBio); - - return Status; -} diff --git a/Cryptlib/Pem/CryptPemNull.c b/Cryptlib/Pem/CryptPemNull.c new file mode 100644 index 0000000..8c9e4f0 --- /dev/null +++ b/Cryptlib/Pem/CryptPemNull.c @@ -0,0 +1,44 @@ +/** @file + PEM (Privacy Enhanced Mail) Format Handler Wrapper Implementation which does + not provide real capabilities. + +Copyright (c) 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 "InternalCryptLib.h" + +/** + Retrieve the RSA Private Key from the password-protected PEM key data. + + Return FALSE to indicate this interface is not supported. + + @param[in] PemData Pointer to the PEM-encoded key data to be retrieved. + @param[in] PemSize Size of the PEM key data in bytes. + @param[in] Password NULL-terminated passphrase used for encrypted PEM key data. + @param[out] RsaContext Pointer to new-generated RSA context which contain the retrieved + RSA private key component. Use RsaFree() function to free the + resource. + + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +RsaGetPrivateKeyFromPem ( + IN CONST UINT8 *PemData, + IN UINTN PemSize, + IN CONST CHAR8 *Password, + OUT VOID **RsaContext + ) +{ + ASSERT (FALSE); + return FALSE; +} diff --git a/Make.coverity b/Make.coverity new file mode 100644 index 0000000..1ffeced --- /dev/null +++ b/Make.coverity @@ -0,0 +1,48 @@ +COV_EMAIL=$(call get-config,coverity.email) +COV_TOKEN=$(call get-config,coverity.token) +COV_URL=$(call get-config,coverity.url) +COV_FILE=$(NAME)-coverity-$(VERSION)-$(COMMIT_ID).tar.bz2 + +cov-int : clean-shim-objs + make $(DASHJ) Cryptlib/OpenSSL/libopenssl.a Cryptlib/libcryptlib.a + cov-build --dir cov-int make $(DASHJ) all + +cov-int-all : clean + cov-build --dir cov-int make $(DASHJ) all + +cov-clean : + @rm -vf $(NAME)-coverity-*.tar.* + @if [[ -d cov-int ]]; then rm -rf cov-int && echo "removed 'cov-int'"; fi + +cov-file : | $(COV_FILE) + +$(COV_FILE) : | cov-int + tar caf $@ cov-int + +cov-upload : + @if [[ -n "$(COV_URL)" ]] && \ + [[ -n "$(COV_TOKEN)" ]] && \ + [[ -n "$(COV_EMAIL)" ]] ; \ + then \ + echo curl --form token=$(COV_TOKEN) --form email="$(COV_EMAIL)" --form file=@"$(COV_FILE)" --form version=$(VERSION).1 --form description="$(COMMIT_ID)" "$(COV_URL)" ; \ + curl --form token=$(COV_TOKEN) --form email="$(COV_EMAIL)" --form file=@"$(COV_FILE)" --form version=$(VERSION).1 --form description="$(COMMIT_ID)" "$(COV_URL)" ; \ + else \ + echo Coverity output is in $(COV_FILE) ; \ + fi + +coverity : | cov-test +coverity : cov-int cov-file cov-upload + +coverity-all : | cov-test +coverity-all : cov-int-all cov-file cov-upload + +clean : | cov-clean + +COV_BUILD ?= $(shell x=$$(which --skip-alias --skip-functions cov-build 2>/dev/null) ; [ -n "$$x" ] && echo 1) +ifeq ($(COV_BUILD),) + COV_BUILD_ERROR = $(error cov-build not found) +endif + +cov-test : ; $(COV_BUILD_ERROR) + +.PHONY : coverity cov-upload cov-clean cov-file cov-test diff --git a/Make.defaults b/Make.defaults new file mode 100644 index 0000000..bbfc1d7 --- /dev/null +++ b/Make.defaults @@ -0,0 +1,131 @@ +COMPILER ?= gcc +CC = $(CROSS_COMPILE)$(COMPILER) +LD = $(CROSS_COMPILE)ld +OBJCOPY = $(CROSS_COMPILE)objcopy +OPENSSL ?= openssl +HEXDUMP ?= hexdump +INSTALL ?= install +PK12UTIL ?= pk12util +CERTUTIL ?= certutil +PESIGN ?= pesign +SBSIGN ?= sbsign +prefix ?= /usr +prefix := $(abspath $(prefix)) +datadir ?= $(prefix)/share/ +PKGNAME ?= shim +ESPROOTDIR ?= boot/efi/ +EFIBOOTDIR ?= $(ESPROOTDIR)EFI/BOOT/ +TARGETDIR ?= $(ESPROOTDIR)EFI/$(EFIDIR)/ +DATATARGETDIR ?= $(datadir)/$(PKGNAME)/$(VERSION)$(DASHRELEASE)/$(ARCH_SUFFIX)/ +DEBUGINFO ?= $(prefix)/lib/debug/ +DEBUGSOURCE ?= $(prefix)/src/debug/ +OSLABEL ?= $(EFIDIR) +DEFAULT_LOADER ?= \\\\grub$(ARCH_SUFFIX).efi +DASHJ ?= -j$(shell echo $$(($$(grep -c "^model name" /proc/cpuinfo) + 1))) + +ARCH ?= $(shell $(CC) -dumpmachine | cut -f1 -d- | sed s,i[3456789]86,ia32,) +OBJCOPY_GTE224 = $(shell expr `$(OBJCOPY) --version |grep ^"GNU objcopy" | sed 's/^.*\((.*)\|version\) //g' | cut -f1-2 -d.` \>= 2.24) + +SUBDIRS = $(TOPDIR)/Cryptlib $(TOPDIR)/lib + +EFI_INCLUDE ?= /usr/include/efi +EFI_INCLUDES = -nostdinc -I$(TOPDIR)/Cryptlib -I$(TOPDIR)/Cryptlib/Include \ + -I$(EFI_INCLUDE) -I$(EFI_INCLUDE)/$(ARCH) -I$(EFI_INCLUDE)/protocol \ + -I$(TOPDIR)/include -iquote $(TOPDIR) -iquote $(shell pwd) + +EFI_CRT_OBJS = $(EFI_PATH)/crt0-efi-$(ARCH).o +EFI_LDS = $(TOPDIR)/elf_$(ARCH)_efi.lds + +CLANG_BUGS = $(if $(findstring gcc,$(CC)),-maccumulate-outgoing-args,) + +COMMIT_ID ?= $(shell if [ -e .git ] ; then git log -1 --pretty=format:%H ; elif [ -f commit ]; then cat commit ; else echo master; fi) + +ifeq ($(ARCH),x86_64) + ARCH_CFLAGS ?= -mno-mmx -mno-sse -mno-red-zone -nostdinc \ + $(CLANG_BUGS) -m64 \ + -DEFI_FUNCTION_WRAPPER -DGNU_EFI_USE_MS_ABI \ + -DNO_BUILTIN_VA_FUNCS -DMDE_CPU_X64 \ + -DPAGE_SIZE=4096 + LIBDIR ?= $(prefix)/lib64 + ARCH_SUFFIX ?= x64 + ARCH_SUFFIX_UPPER ?= X64 + ARCH_LDFLAGS ?= +endif +ifeq ($(ARCH),ia32) + ARCH_CFLAGS ?= -mno-mmx -mno-sse -mno-red-zone -nostdinc \ + $(CLANG_BUGS) -m32 \ + -DMDE_CPU_IA32 -DPAGE_SIZE=4096 + LIBDIR ?= $(prefix)/lib + ARCH_SUFFIX ?= ia32 + ARCH_SUFFIX_UPPER ?= IA32 + ARCH_LDFLAGS ?= + ARCH_CFLAGS ?= -m32 +endif +ifeq ($(ARCH),aarch64) + ARCH_CFLAGS ?= -DMDE_CPU_AARCH64 -DPAGE_SIZE=4096 -mstrict-align + LIBDIR ?= $(prefix)/lib64 + ARCH_SUFFIX ?= aa64 + ARCH_SUFFIX_UPPER ?= AA64 + FORMAT := -O binary + SUBSYSTEM := 0xa + ARCH_LDFLAGS += --defsym=EFI_SUBSYSTEM=$(SUBSYSTEM) + ARCH_CFLAGS ?= +endif +ifeq ($(ARCH),arm) + ARCH_CFLAGS ?= -DMDE_CPU_ARM -DPAGE_SIZE=4096 -mstrict-align + LIBDIR ?= $(prefix)/lib + ARCH_SUFFIX ?= arm + ARCH_SUFFIX_UPPER ?= ARM + FORMAT := -O binary + SUBSYSTEM := 0xa + ARCH_LDFLAGS += --defsym=EFI_SUBSYSTEM=$(SUBSYSTEM) +endif + +CFLAGS = -ggdb -O0 -fno-stack-protector -fno-strict-aliasing -fpic \ + -fshort-wchar -Wall -Wsign-compare -Werror -fno-builtin \ + -Werror=sign-compare -ffreestanding -std=gnu89 \ + -I$(shell $(CC) $(ARCH_CFLAGS) -print-file-name=include) \ + "-DDEFAULT_LOADER=L\"$(DEFAULT_LOADER)\"" \ + "-DDEFAULT_LOADER_CHAR=\"$(DEFAULT_LOADER)\"" \ + $(EFI_INCLUDES) $(ARCH_CFLAGS) + +ifneq ($(origin OVERRIDE_SECURITY_POLICY), undefined) + CFLAGS += -DOVERRIDE_SECURITY_POLICY +endif + +ifneq ($(origin ENABLE_HTTPBOOT), undefined) + CFLAGS += -DENABLE_HTTPBOOT +endif + +ifneq ($(origin REQUIRE_TPM), undefined) + CFLAGS += -DREQUIRE_TPM +endif + +LIB_GCC = $(shell $(CC) $(ARCH_CFLAGS) -print-libgcc-file-name) +EFI_LIBS = -lefi -lgnuefi --start-group Cryptlib/libcryptlib.a Cryptlib/OpenSSL/libopenssl.a --end-group $(LIB_GCC) +FORMAT ?= --target efi-app-$(ARCH) +EFI_PATH ?= $(LIBDIR)/gnuefi + +MMSTEM ?= mm$(ARCH_SUFFIX) +MMNAME = $(MMSTEM).efi +MMSONAME = $(MMSTEM).so +FBSTEM ?= fb$(ARCH_SUFFIX) +FBNAME = $(FBSTEM).efi +FBSONAME = $(FBSTEM).so +SHIMSTEM ?= shim$(ARCH_SUFFIX) +SHIMNAME = $(SHIMSTEM).efi +SHIMSONAME = $(SHIMSTEM).so +SHIMHASHNAME = $(SHIMSTEM).hash +BOOTEFINAME ?= BOOT$(ARCH_SUFFIX_UPPER).EFI +BOOTCSVNAME ?= BOOT$(ARCH_SUFFIX_UPPER).CSV + +CFLAGS += "-DEFI_ARCH=L\"$(ARCH_SUFFIX)\"" "-DDEBUGDIR=L\"/usr/lib/debug/usr/share/shim/$(ARCH_SUFFIX)-$(VERSION)$(DASHRELEASE)/\"" + +ifneq ($(origin VENDOR_CERT_FILE), undefined) + CFLAGS += -DVENDOR_CERT_FILE=\"$(VENDOR_CERT_FILE)\" +endif +ifneq ($(origin VENDOR_DBX_FILE), undefined) + CFLAGS += -DVENDOR_DBX_FILE=\"$(VENDOR_DBX_FILE)\" +endif + +LDFLAGS = --hash-style=sysv -nostdlib -znocombreloc -T $(EFI_LDS) -shared -Bsymbolic -L$(EFI_PATH) -L$(LIBDIR) -LCryptlib -LCryptlib/OpenSSL $(EFI_CRT_OBJS) --build-id=sha1 $(ARCH_LDFLAGS) --no-undefined diff --git a/Make.rules b/Make.rules new file mode 100644 index 0000000..2f1d4a7 --- /dev/null +++ b/Make.rules @@ -0,0 +1,3 @@ +define get-config +$(shell git config --local --get "shim.$(1)") +endef diff --git a/Make.scan-build b/Make.scan-build new file mode 100644 index 0000000..4177906 --- /dev/null +++ b/Make.scan-build @@ -0,0 +1,20 @@ +SCAN_BUILD ?= $(shell x=$$(which --skip-alias --skip-functions scan-build 2>/dev/null) ; [ -n "$$x" ] && echo 1) +ifeq ($(SCAN_BUILD),) + SCAN_BUILD_ERROR = $(error scan-build not found) +endif + +scan-test : ; $(SCAN_BUILD_ERROR) + +scan-clean : + @if [[ -d scan-results ]]; then rm -rf scan-results && echo "removed 'scan-results'"; fi + +scan-build : | scan-test +scan-build : clean-shim-objs + make $(DASHJ) Cryptlib/OpenSSL/libopenssl.a Cryptlib/libcryptlib.a + scan-build -o scan-results make $(DASHJ) CC=clang all + +scan-build-all : | scan-test +scan-build-all : clean + scan-build -o scan-results make $(DASHJ) CC=clang all + +.PHONY : scan-build scan-clean diff --git a/Makefile b/Makefile index 0328737..115e7f0 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,7 @@ -VERSION = 13 +default : all + +NAME = shim +VERSION = 15 ifneq ($(origin RELEASE),undefined) DASHRELEASE ?= -$(RELEASE) else @@ -8,130 +11,16 @@ endif ifeq ($(MAKELEVEL),0) TOPDIR ?= $(shell pwd) endif +ifeq ($(TOPDIR),) +override TOPDIR := $(shell pwd) +endif override TOPDIR := $(abspath $(TOPDIR)) VPATH = $(TOPDIR) -CC = $(CROSS_COMPILE)gcc -LD = $(CROSS_COMPILE)ld -OBJCOPY = $(CROSS_COMPILE)objcopy -OPENSSL ?= openssl -HEXDUMP ?= hexdump -INSTALL ?= install -PK12UTIL ?= pk12util -CERTUTIL ?= certutil -PESIGN ?= pesign -SBSIGN ?= sbsign -prefix ?= /usr -prefix := $(abspath $(prefix)) -datadir ?= $(prefix)/share/ -PKGNAME ?= shim -ESPROOTDIR ?= boot/efi/ -EFIBOOTDIR ?= $(ESPROOTDIR)EFI/BOOT/ -TARGETDIR ?= $(ESPROOTDIR)EFI/$(EFIDIR)/ -DATATARGETDIR ?= $(datadir)/$(PKGNAME)/$(VERSION)$(DASHRELEASE)/$(ARCH_SUFFIX)/ -DEBUGINFO ?= $(prefix)/lib/debug/ -DEBUGSOURCE ?= $(prefix)/src/debug/ -OSLABEL ?= $(EFIDIR) -DEFAULT_LOADER ?= \\\\grub$(ARCH_SUFFIX).efi - -ARCH ?= $(shell $(CC) -dumpmachine | cut -f1 -d- | sed s,i[3456789]86,ia32,) -OBJCOPY_GTE224 = $(shell expr `$(OBJCOPY) --version |grep ^"GNU objcopy" | sed 's/^.*\((.*)\|version\) //g' | cut -f1-2 -d.` \>= 2.24) - -SUBDIRS = $(TOPDIR)/Cryptlib $(TOPDIR)/lib - -EFI_INCLUDE := /usr/include/efi -EFI_INCLUDES = -nostdinc -I$(TOPDIR)/Cryptlib -I$(TOPDIR)/Cryptlib/Include \ - -I$(EFI_INCLUDE) -I$(EFI_INCLUDE)/$(ARCH) -I$(EFI_INCLUDE)/protocol \ - -I$(TOPDIR)/include -iquote $(TOPDIR) -iquote $(shell pwd) - -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) - -EFI_CRT_OBJS = $(EFI_PATH)/crt0-efi-$(ARCH).o -EFI_LDS = $(TOPDIR)/elf_$(ARCH)_efi.lds - -CFLAGS = -ggdb -O0 -fno-stack-protector -fno-strict-aliasing -fpic \ - -fshort-wchar -Wall -Wsign-compare -Werror -fno-builtin \ - -Werror=sign-compare -ffreestanding -std=gnu89 \ - -I$(shell $(CC) -print-file-name=include) \ - "-DDEFAULT_LOADER=L\"$(DEFAULT_LOADER)\"" \ - "-DDEFAULT_LOADER_CHAR=\"$(DEFAULT_LOADER)\"" \ - $(EFI_INCLUDES) - -COMMITID ?= $(shell if [ -d .git ] ; then git log -1 --pretty=format:%H ; elif [ -f commit ]; then cat commit ; else echo commit id not available; fi) - -ifneq ($(origin OVERRIDE_SECURITY_POLICY), undefined) - CFLAGS += -DOVERRIDE_SECURITY_POLICY -endif - -ifneq ($(origin ENABLE_HTTPBOOT), undefined) - CFLAGS += -DENABLE_HTTPBOOT -endif - -ifeq ($(ARCH),x86_64) - CFLAGS += -mno-mmx -mno-sse -mno-red-zone -nostdinc \ - -maccumulate-outgoing-args \ - -DEFI_FUNCTION_WRAPPER -DGNU_EFI_USE_MS_ABI \ - -DNO_BUILTIN_VA_FUNCS -DMDE_CPU_X64 -DPAGE_SIZE=4096 - LIBDIR ?= $(prefix)/lib64 - ARCH_SUFFIX ?= x64 - ARCH_SUFFIX_UPPER ?= X64 - ARCH_LDFLAGS ?= -endif -ifeq ($(ARCH),ia32) - CFLAGS += -mno-mmx -mno-sse -mno-red-zone -nostdinc \ - -maccumulate-outgoing-args -m32 \ - -DMDE_CPU_IA32 -DPAGE_SIZE=4096 - LIBDIR ?= $(prefix)/lib - ARCH_SUFFIX ?= ia32 - ARCH_SUFFIX_UPPER ?= IA32 - ARCH_LDFLAGS ?= -endif -ifeq ($(ARCH),aarch64) - CFLAGS += -DMDE_CPU_AARCH64 -DPAGE_SIZE=4096 -mstrict-align - LIBDIR ?= $(prefix)/lib64 - ARCH_SUFFIX ?= aa64 - ARCH_SUFFIX_UPPER ?= AA64 - FORMAT := -O binary - SUBSYSTEM := 0xa - ARCH_LDFLAGS += --defsym=EFI_SUBSYSTEM=$(SUBSYSTEM) -endif -ifeq ($(ARCH),arm) - CFLAGS += -DMDE_CPU_ARM -DPAGE_SIZE=4096 -mstrict-align - LIBDIR ?= $(prefix)/lib - ARCH_SUFFIX ?= arm - ARCH_SUFFIX_UPPER ?= ARM - FORMAT := -O binary - SUBSYSTEM := 0xa - ARCH_LDFLAGS += --defsym=EFI_SUBSYSTEM=$(SUBSYSTEM) -endif - -FORMAT ?= --target efi-app-$(ARCH) -EFI_PATH ?= $(LIBDIR)/gnuefi - -MMSTEM ?= mm$(ARCH_SUFFIX) -MMNAME = $(MMSTEM).efi -MMSONAME = $(MMSTEM).so -FBSTEM ?= fb$(ARCH_SUFFIX) -FBNAME = $(FBSTEM).efi -FBSONAME = $(FBSTEM).so -SHIMSTEM ?= shim$(ARCH_SUFFIX) -SHIMNAME = $(SHIMSTEM).efi -SHIMSONAME = $(SHIMSTEM).so -SHIMHASHNAME = $(SHIMSTEM).hash -BOOTEFINAME ?= BOOT$(ARCH_SUFFIX_UPPER).EFI -BOOTCSVNAME ?= BOOT$(ARCH_SUFFIX_UPPER).CSV - -CFLAGS += "-DEFI_ARCH=L\"$(ARCH_SUFFIX)\"" "-DDEBUGDIR=L\"/usr/lib/debug/usr/share/shim/$(ARCH_SUFFIX)-$(VERSION)$(DASHRELEASE)/\"" - -ifneq ($(origin VENDOR_CERT_FILE), undefined) - CFLAGS += -DVENDOR_CERT_FILE=\"$(VENDOR_CERT_FILE)\" -endif -ifneq ($(origin VENDOR_DBX_FILE), undefined) - CFLAGS += -DVENDOR_DBX_FILE=\"$(VENDOR_DBX_FILE)\" -endif - -LDFLAGS = --hash-style=sysv -nostdlib -znocombreloc -T $(EFI_LDS) -shared -Bsymbolic -L$(EFI_PATH) -L$(LIBDIR) -LCryptlib -LCryptlib/OpenSSL $(EFI_CRT_OBJS) --build-id=sha1 $(ARCH_LDFLAGS) +include $(TOPDIR)/Make.defaults +include $(TOPDIR)/Make.rules +include $(TOPDIR)/Make.coverity +include $(TOPDIR)/Make.scan-build TARGETS = $(SHIMNAME) TARGETS += $(SHIMNAME).debug $(MMNAME).debug $(FBNAME).debug @@ -144,17 +33,17 @@ CFLAGS += -DENABLE_SHIM_CERT else TARGETS += $(MMNAME) $(FBNAME) endif -OBJS = shim.o netboot.o cert.o replacements.o tpm.o version.o errlog.o +OBJS = shim.o mok.o netboot.o cert.o replacements.o tpm.o version.o errlog.o KEYS = shim_cert.h ocsp.* ca.* shim.crt shim.csr shim.p12 shim.pem shim.key shim.cer -ORIG_SOURCES = shim.c shim.h netboot.c include/PeImage.h include/wincert.h include/console.h replacements.c replacements.h tpm.c tpm.h version.h errlog.c +ORIG_SOURCES = shim.c mok.c netboot.c replacements.c tpm.c errlog.c shim.h version.h $(wildcard include/*.h) MOK_OBJS = MokManager.o PasswordCrypt.o crypt_blowfish.o -ORIG_MOK_SOURCES = MokManager.c shim.h include/console.h PasswordCrypt.c PasswordCrypt.h crypt_blowfish.c crypt_blowfish.h -FALLBACK_OBJS = fallback.o tpm.o +ORIG_MOK_SOURCES = MokManager.c PasswordCrypt.c crypt_blowfish.c shim.h $(wildcard include/*.h) +FALLBACK_OBJS = fallback.o tpm.o errlog.o ORIG_FALLBACK_SRCS = fallback.c ifneq ($(origin ENABLE_HTTPBOOT), undefined) OBJS += httpboot.o - SOURCES += httpboot.c httpboot.h + SOURCES += httpboot.c include/httpboot.h endif SOURCES = $(foreach source,$(ORIG_SOURCES),$(TOPDIR)/$(source)) version.c @@ -177,8 +66,8 @@ shim_cert.h: shim.cer version.c : $(TOPDIR)/version.c.in sed -e "s,@@VERSION@@,$(VERSION)," \ - -e "s,@@UNAME@@,$(shell uname -a)," \ - -e "s,@@COMMIT@@,$(COMMITID)," \ + -e "s,@@UNAME@@,$(shell uname -s -m -p -i -o)," \ + -e "s,@@COMMIT@@,$(COMMIT_ID)," \ < $< > $@ certdb/secmod.db: shim.crt @@ -220,9 +109,9 @@ Cryptlib/OpenSSL/libopenssl.a: mkdir -p Cryptlib/OpenSSL/crypto/{x509v3,x509,txt_db,stack,sha,rsa,rc4,rand,pkcs7,pkcs12,pem,ocsp,objects,modes,md5,lhash,kdf,hmac,evp,err,dso,dh,conf,comp,cmac,buffer,bn,bio,async{,/arch},asn1,aes}/ $(MAKE) VPATH=$(TOPDIR)/Cryptlib/OpenSSL TOPDIR=$(TOPDIR)/Cryptlib/OpenSSL -C Cryptlib/OpenSSL -f $(TOPDIR)/Cryptlib/OpenSSL/Makefile -lib/lib.a: +lib/lib.a: | $(TOPDIR)/lib/Makefile $(wildcard $(TOPDIR)/include/*.[ch]) if [ ! -d lib ]; then mkdir lib ; fi - $(MAKE) VPATH=$(TOPDIR)/lib TOPDIR=$(TOPDIR) CFLAGS="$(CFLAGS)" -C lib -f $(TOPDIR)/lib/Makefile + $(MAKE) VPATH=$(TOPDIR)/lib TOPDIR=$(TOPDIR) CFLAGS="$(CFLAGS)" -C lib -f $(TOPDIR)/lib/Makefile lib.a buildid : $(TOPDIR)/buildid.c $(CC) -Og -g3 -Wall -Werror -Wextra -o $@ $< -lelf @@ -331,13 +220,16 @@ else $(PESIGN) -n certdb -i $< -c "shim" -s -o $@ -f endif -clean: OBJS=$(wildcard *.o) -clean: +clean-shim-objs: + $(MAKE) -C lib -f $(TOPDIR)/lib/Makefile clean + @rm -rvf $(TARGET) *.o $(SHIM_OBJS) $(MOK_OBJS) $(FALLBACK_OBJS) $(KEYS) certdb $(BOOTCSVNAME) + @rm -vf *.debug *.so *.efi *.efi.* *.tar.* version.c buildid + @rm -vf Cryptlib/*.[oa] Cryptlib/*/*.[oa] + @git clean -f -d -e 'Cryptlib/OpenSSL/*' + +clean: clean-shim-objs $(MAKE) -C Cryptlib -f $(TOPDIR)/Cryptlib/Makefile clean $(MAKE) -C Cryptlib/OpenSSL -f $(TOPDIR)/Cryptlib/OpenSSL/Makefile clean - $(MAKE) -C lib -f $(TOPDIR)/lib/Makefile clean - rm -rf $(TARGET) $(OBJS) $(MOK_OBJS) $(FALLBACK_OBJS) $(KEYS) certdb $(BOOTCSVNAME) - rm -f *.debug *.so *.efi *.efi.* *.tar.* version.c buildid GITTAG = $(VERSION) diff --git a/MokManager.c b/MokManager.c index 55af321..df9b6fe 100644 --- a/MokManager.c +++ b/MokManager.c @@ -6,15 +6,8 @@ #include #include #include -#include "shim.h" -#include "PeImage.h" -#include "PasswordCrypt.h" -#include "guid.h" -#include "console.h" -#include "variables.h" -#include "simple_file.h" -#include "efiauthenticated.h" +#include "shim.h" #define PASSWORD_MAX 256 #define PASSWORD_MIN 1 @@ -26,23 +19,9 @@ #define SHIM_VENDOR L"Shim" #endif -EFI_GUID SHIM_LOCK_GUID = { 0x605dab50, 0xe046, 0x4300, {0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23} }; -EFI_GUID EFI_CERT_SHA224_GUID = { 0xb6e5233, 0xa65c, 0x44c9, {0x94, 0x7, 0xd9, 0xab, 0x83, 0xbf, 0xc8, 0xbd} }; -EFI_GUID EFI_CERT_SHA384_GUID = { 0xff3e5307, 0x9fd0, 0x48c9, {0x85, 0xf1, 0x8a, 0xd5, 0x6c, 0x70, 0x1e, 0x1} }; -EFI_GUID EFI_CERT_SHA512_GUID = { 0x93e0fae, 0xa6c4, 0x4f50, {0x9f, 0x1b, 0xd4, 0x1e, 0x2b, 0x89, 0xc1, 0x9a} }; - #define CERT_STRING L"Select an X509 certificate to enroll:\n\n" #define HASH_STRING L"Select a file to trust:\n\n" -struct menu_item { - CHAR16 *text; - INTN (* callback)(void *data, void *data2, void *data3); - void *data; - void *data2; - void *data3; - UINTN colour; -}; - typedef struct { UINT32 MokSize; UINT8 *Mok; @@ -61,9 +40,13 @@ typedef struct { CHAR16 Password[SB_PASSWORD_LEN]; } __attribute__ ((packed)) MokDBvar; -static EFI_STATUS get_sha1sum (void *Data, int DataSize, UINT8 *hash) +typedef struct { + INT32 Timeout; +} __attribute__ ((packed)) MokTimeoutvar; + +static EFI_STATUS get_sha1sum(void *Data, int DataSize, UINT8 * hash) { - EFI_STATUS status; + EFI_STATUS efi_status; unsigned int ctxsize; void *ctx = NULL; @@ -77,80 +60,68 @@ static EFI_STATUS get_sha1sum (void *Data, int DataSize, UINT8 *hash) if (!Sha1Init(ctx)) { console_notify(L"Unable to initialise hash"); - status = EFI_OUT_OF_RESOURCES; + efi_status = EFI_OUT_OF_RESOURCES; goto done; } if (!(Sha1Update(ctx, Data, DataSize))) { console_notify(L"Unable to generate hash"); - status = EFI_OUT_OF_RESOURCES; + efi_status = EFI_OUT_OF_RESOURCES; goto done; } if (!(Sha1Final(ctx, hash))) { console_notify(L"Unable to finalise hash"); - status = EFI_OUT_OF_RESOURCES; + efi_status = EFI_OUT_OF_RESOURCES; goto done; } - status = EFI_SUCCESS; + efi_status = EFI_SUCCESS; done: - return status; + return efi_status; } -static BOOLEAN is_sha2_hash (EFI_GUID Type) +static BOOLEAN is_sha2_hash(EFI_GUID Type) { - EFI_GUID Sha224 = EFI_CERT_SHA224_GUID; - EFI_GUID Sha256 = EFI_CERT_SHA256_GUID; - EFI_GUID Sha384 = EFI_CERT_SHA384_GUID; - EFI_GUID Sha512 = EFI_CERT_SHA512_GUID; - - if (CompareGuid(&Type, &Sha224) == 0) + if (CompareGuid(&Type, &EFI_CERT_SHA224_GUID) == 0) return TRUE; - else if (CompareGuid(&Type, &Sha256) == 0) + else if (CompareGuid(&Type, &EFI_CERT_SHA256_GUID) == 0) return TRUE; - else if (CompareGuid(&Type, &Sha384) == 0) + else if (CompareGuid(&Type, &EFI_CERT_SHA384_GUID) == 0) return TRUE; - else if (CompareGuid(&Type, &Sha512) == 0) + else if (CompareGuid(&Type, &EFI_CERT_SHA512_GUID) == 0) return TRUE; return FALSE; } -static UINT32 sha_size (EFI_GUID Type) +static UINT32 sha_size(EFI_GUID Type) { - EFI_GUID Sha1 = EFI_CERT_SHA1_GUID; - EFI_GUID Sha224 = EFI_CERT_SHA224_GUID; - EFI_GUID Sha256 = EFI_CERT_SHA256_GUID; - EFI_GUID Sha384 = EFI_CERT_SHA384_GUID; - EFI_GUID Sha512 = EFI_CERT_SHA512_GUID; - - if (CompareGuid(&Type, &Sha1) == 0) + if (CompareGuid(&Type, &EFI_CERT_SHA1_GUID) == 0) return SHA1_DIGEST_SIZE; - else if (CompareGuid(&Type, &Sha224) == 0) + else if (CompareGuid(&Type, &EFI_CERT_SHA224_GUID) == 0) return SHA224_DIGEST_LENGTH; - else if (CompareGuid(&Type, &Sha256) == 0) + else if (CompareGuid(&Type, &EFI_CERT_SHA256_GUID) == 0) return SHA256_DIGEST_SIZE; - else if (CompareGuid(&Type, &Sha384) == 0) + else if (CompareGuid(&Type, &EFI_CERT_SHA384_GUID) == 0) return SHA384_DIGEST_LENGTH; - else if (CompareGuid(&Type, &Sha512) == 0) + else if (CompareGuid(&Type, &EFI_CERT_SHA512_GUID) == 0) return SHA512_DIGEST_LENGTH; return 0; } -static BOOLEAN is_valid_siglist (EFI_GUID Type, UINT32 SigSize) +static BOOLEAN is_valid_siglist(EFI_GUID Type, UINT32 SigSize) { - EFI_GUID CertType = X509_GUID; UINT32 hash_sig_size; - if (CompareGuid (&Type, &CertType) == 0 && SigSize != 0) + if (CompareGuid (&Type, &X509_GUID) == 0 && SigSize != 0) return TRUE; - if (!is_sha2_hash (Type)) + if (!is_sha2_hash(Type)) return FALSE; - hash_sig_size = sha_size (Type) + sizeof(EFI_GUID); + hash_sig_size = sha_size(Type) + sizeof(EFI_GUID); if (SigSize != hash_sig_size) return FALSE; @@ -165,12 +136,12 @@ static UINT32 count_keys(void *Data, UINTN DataSize) void *end = Data + DataSize; while ((dbsize > 0) && (dbsize >= CertList->SignatureListSize)) { - /* Use ptr arithmetics to ensure bounded access. Do not allow 0 - * SignatureListSize that will cause endless loop. - */ - if ((void *)(CertList + 1) > end || CertList->SignatureListSize == 0) { - console_notify(L"Invalid MOK detected! Ignoring MOK List."); + * SignatureListSize that will cause endless loop. */ + if ((void *)(CertList + 1) > end + || CertList->SignatureListSize == 0) { + console_notify + (L"Invalid MOK detected! Ignoring MOK List."); return 0; } @@ -180,7 +151,8 @@ static UINT32 count_keys(void *Data, UINTN DataSize) return 0; } - if (!is_valid_siglist(CertList->SignatureType, CertList->SignatureSize)) { + if (!is_valid_siglist + (CertList->SignatureType, CertList->SignatureSize)) { console_errorbox(L"Invalid signature list found"); return 0; } @@ -188,23 +160,22 @@ static UINT32 count_keys(void *Data, UINTN DataSize) MokNum++; dbsize -= CertList->SignatureListSize; CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + - CertList->SignatureListSize); + CertList->SignatureListSize); } return MokNum; } -static MokListNode *build_mok_list(UINT32 num, void *Data, UINTN DataSize) { +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 = X509_GUID; UINTN dbsize = DataSize; UINTN count = 0; void *end = Data + DataSize; list = AllocatePool(sizeof(MokListNode) * num); - if (!list) { console_notify(L"Unable to allocate MOK list"); return NULL; @@ -212,7 +183,8 @@ static MokListNode *build_mok_list(UINT32 num, void *Data, UINTN DataSize) { while ((dbsize > 0) && (dbsize >= CertList->SignatureListSize)) { /* CertList out of bounds? */ - if ((void *)(CertList + 1) > end || CertList->SignatureListSize == 0) { + if ((void *)(CertList + 1) > end + || CertList->SignatureListSize == 0) { FreePool(list); return NULL; } @@ -221,28 +193,29 @@ static MokListNode *build_mok_list(UINT32 num, void *Data, UINTN DataSize) { in count_keys() */ Cert = (EFI_SIGNATURE_DATA *) (((UINT8 *) CertList) + - sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize); - + sizeof(EFI_SIGNATURE_LIST) + + CertList->SignatureHeaderSize); /* Cert out of bounds? */ - if ((void *)(Cert + 1) > end || CertList->SignatureSize <= sizeof(EFI_GUID)) { + if ((void *)(Cert + 1) > end + || CertList->SignatureSize <= sizeof(EFI_GUID)) { FreePool(list); return NULL; } list[count].Type = CertList->SignatureType; - if (CompareGuid (&CertList->SignatureType, &CertType) == 0) { + if (CompareGuid (&CertList->SignatureType, &X509_GUID) == 0) { list[count].MokSize = CertList->SignatureSize - - sizeof(EFI_GUID); + sizeof(EFI_GUID); list[count].Mok = (void *)Cert->SignatureData; } else { list[count].MokSize = CertList->SignatureListSize - - sizeof(EFI_SIGNATURE_LIST); + sizeof(EFI_SIGNATURE_LIST); list[count].Mok = (void *)Cert; } /* MOK out of bounds? */ if (list[count].MokSize > (unsigned long)end - - (unsigned long)list[count].Mok) { + (unsigned long)list[count].Mok) { FreePool(list); return NULL; } @@ -250,7 +223,7 @@ static MokListNode *build_mok_list(UINT32 num, void *Data, UINTN DataSize) { count++; dbsize -= CertList->SignatureListSize; CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + - CertList->SignatureListSize); + CertList->SignatureListSize); } return list; @@ -270,10 +243,10 @@ static NidName nidname[] = { {-1, NULL} }; -static CHAR16* get_x509_name (X509_NAME *X509Name) +static CHAR16 *get_x509_name(X509_NAME * X509Name) { - CHAR16 name[NAME_LINE_MAX+1]; - CHAR16 part[NAME_LINE_MAX+1]; + CHAR16 name[NAME_LINE_MAX + 1]; + CHAR16 part[NAME_LINE_MAX + 1]; char str[NAME_LINE_MAX]; int i, len, rest, first; @@ -282,8 +255,8 @@ static CHAR16* get_x509_name (X509_NAME *X509Name) first = 1; for (i = 0; nidname[i].name != NULL; i++) { int add; - len = X509_NAME_get_text_by_NID (X509Name, nidname[i].nid, - str, NAME_LINE_MAX); + len = X509_NAME_get_text_by_NID(X509Name, nidname[i].nid, + str, NAME_LINE_MAX); if (len <= 0) continue; @@ -313,23 +286,23 @@ static CHAR16* get_x509_name (X509_NAME *X509Name) return NULL; } -static CHAR16* get_x509_time (ASN1_TIME *time) +static CHAR16 *get_x509_time(ASN1_TIME * time) { - BIO *bio = BIO_new (BIO_s_mem()); + BIO *bio = BIO_new(BIO_s_mem()); char str[30]; int len; - ASN1_TIME_print (bio, time); + ASN1_TIME_print(bio, time); len = BIO_read(bio, str, 29); if (len < 0) len = 0; str[len] = '\0'; - BIO_free (bio); + BIO_free(bio); return PoolPrint(L"%a", str); } -static void show_x509_info (X509 *X509Cert, UINT8 *hash) +static void show_x509_info(X509 * X509Cert, UINT8 * hash) { ASN1_INTEGER *serial; BIGNUM *bnser; @@ -393,9 +366,9 @@ static void show_x509_info (X509 *X509Cert, UINT8 *hash) fields++; } - for (i=0; i<10; i++) + for (i = 0; i < 10; i++) CatPrint(&hash_string1, L"%02x ", hash[i]); - for (i=10; i<20; i++) + for (i = 10; i < 20; i++) CatPrint(&hash_string2, L"%02x ", hash[i]); if (hash_string1.str) @@ -410,8 +383,9 @@ static void show_x509_info (X509 *X509Cert, UINT8 *hash) i = 0; extusage = X509_get_ext_d2i(X509Cert, NID_ext_key_usage, NULL, NULL); - text = AllocateZeroPool(sizeof(CHAR16 *) * (fields*3 + sk_ASN1_OBJECT_num(extusage) + 3)); - + text = AllocateZeroPool(sizeof(CHAR16 *) * + (fields * 3 + + sk_ASN1_OBJECT_num(extusage) + 3)); if (extusage) { int j = 0; @@ -471,38 +445,33 @@ static void show_x509_info (X509 *X509Cert, UINT8 *hash) console_print_box(text, -1); - for (i=0; text[i] != NULL; i++) + for (i = 0; text[i] != NULL; i++) FreePool(text[i]); FreePool(text); } -static void show_sha_digest (EFI_GUID Type, UINT8 *hash) +static void show_sha_digest(EFI_GUID Type, UINT8 * hash) { - EFI_GUID Sha1 = EFI_CERT_SHA1_GUID; - EFI_GUID Sha224 = EFI_CERT_SHA224_GUID; - EFI_GUID Sha256 = EFI_CERT_SHA256_GUID; - EFI_GUID Sha384 = EFI_CERT_SHA384_GUID; - EFI_GUID Sha512 = EFI_CERT_SHA512_GUID; CHAR16 *text[5]; POOL_PRINT hash_string1; POOL_PRINT hash_string2; int i; int length; - if (CompareGuid(&Type, &Sha1) == 0) { + if (CompareGuid(&Type, &EFI_CERT_SHA1_GUID) == 0) { length = SHA1_DIGEST_SIZE; text[0] = L"SHA1 hash"; - } else if (CompareGuid(&Type, &Sha224) == 0) { + } else if (CompareGuid(&Type, &EFI_CERT_SHA224_GUID) == 0) { length = SHA224_DIGEST_LENGTH; text[0] = L"SHA224 hash"; - } else if (CompareGuid(&Type, &Sha256) == 0) { + } else if (CompareGuid(&Type, &EFI_CERT_SHA256_GUID) == 0) { length = SHA256_DIGEST_SIZE; text[0] = L"SHA256 hash"; - } else if (CompareGuid(&Type, &Sha384) == 0) { + } else if (CompareGuid(&Type, &EFI_CERT_SHA384_GUID) == 0) { length = SHA384_DIGEST_LENGTH; text[0] = L"SHA384 hash"; - } else if (CompareGuid(&Type, &Sha512) == 0) { + } else if (CompareGuid(&Type, &EFI_CERT_SHA512_GUID) == 0) { length = SHA512_DIGEST_LENGTH; text[0] = L"SHA512 hash"; } else { @@ -514,9 +483,9 @@ static void show_sha_digest (EFI_GUID Type, UINT8 *hash) text[1] = L""; - for (i=0; i= hash_num) + key_num = rc = console_select(selection, menu_strings, key_num); + if (rc < 0 || key_num >= hash_num) break; - hash = (UINT8 *)Mok + sig_size*key_num + sizeof(EFI_GUID); + hash = (UINT8 *) Mok + sig_size * key_num + sizeof(EFI_GUID); show_sha_digest(Type, hash); } - for (i=0; menu_strings[i] != NULL; i++) + for (i = 0; menu_strings[i] != NULL; i++) FreePool(menu_strings[i]); FreePool(menu_strings); } -static void show_mok_info (EFI_GUID Type, void *Mok, UINTN MokSize) +static void show_mok_info(EFI_GUID Type, void *Mok, UINTN MokSize) { EFI_STATUS efi_status; - EFI_GUID CertType = X509_GUID; if (!Mok || MokSize == 0) return; - if (CompareGuid (&Type, &CertType) == 0) { + if (CompareGuid (&Type, &X509_GUID) == 0) { UINT8 hash[SHA1_DIGEST_SIZE]; X509 *X509Cert; - efi_status = get_sha1sum(Mok, MokSize, hash); - if (efi_status != EFI_SUCCESS) { + efi_status = get_sha1sum(Mok, MokSize, hash); + if (EFI_ERROR(efi_status)) { console_notify(L"Failed to compute MOK fingerprint"); return; } if (X509ConstructCertificate(Mok, MokSize, - (UINT8 **) &X509Cert) && X509Cert != NULL) { + (UINT8 **) & X509Cert) + && X509Cert != NULL) { show_x509_info(X509Cert, hash); X509_free(X509Cert); } else { @@ -613,12 +584,13 @@ static void show_mok_info (EFI_GUID Type, void *Mok, UINTN MokSize) } } -static EFI_STATUS list_keys (void *KeyList, UINTN KeyListSize, CHAR16 *title) +static EFI_STATUS list_keys(void *KeyList, UINTN KeyListSize, CHAR16 * title) { UINTN MokNum = 0; MokListNode *keys = NULL; UINT32 key_num = 0; CHAR16 **menu_strings; + CHAR16 *selection[] = { title, NULL }; unsigned int i; if (KeyListSize < (sizeof(EFI_SIGNATURE_LIST) + @@ -639,56 +611,55 @@ static EFI_STATUS list_keys (void *KeyList, UINTN KeyListSize, CHAR16 *title) } menu_strings = AllocateZeroPool(sizeof(CHAR16 *) * (MokNum + 2)); - if (!menu_strings) return EFI_OUT_OF_RESOURCES; - for (i=0; i= MokNum) + if (rc < 0 || key_num >= MokNum) break; show_mok_info(keys[key_num].Type, keys[key_num].Mok, keys[key_num].MokSize); } - for (i=0; menu_strings[i] != NULL; i++) + for (i = 0; menu_strings[i] != NULL; i++) FreePool(menu_strings[i]); - FreePool(menu_strings); - FreePool(keys); return EFI_SUCCESS; } -static EFI_STATUS 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; + EFI_STATUS efi_status; unsigned int count = 0; do { - status = console_get_keystroke(&key); - if (EFI_ERROR (status)) { - console_error(L"Failed to read the keystroke", status); + efi_status = console_get_keystroke(&key); + if (EFI_ERROR(efi_status)) { + console_error(L"Failed to read the keystroke", + efi_status); *length = 0; - return status; + return efi_status; } if ((count >= line_max && key.UnicodeChar != CHAR_BACKSPACE) || key.UnicodeChar == CHAR_NULL || - key.UnicodeChar == CHAR_TAB || + key.UnicodeChar == CHAR_TAB || key.UnicodeChar == CHAR_LINEFEED || key.UnicodeChar == CHAR_CARRIAGE_RETURN) { continue; @@ -698,35 +669,34 @@ static EFI_STATUS get_line (UINT32 *length, CHAR16 *line, UINT32 line_max, UINT8 continue; } else if (key.UnicodeChar == CHAR_BACKSPACE) { if (show) { - Print(L"\b"); + console_print(L"\b"); } line[--count] = '\0'; continue; } if (show) { - Print(L"%c", key.UnicodeChar); + console_print(L"%c", key.UnicodeChar); } line[count++] = key.UnicodeChar; } while (key.UnicodeChar != CHAR_CARRIAGE_RETURN); - Print(L"\n"); + console_print(L"\n"); *length = count; return EFI_SUCCESS; } -static EFI_STATUS compute_pw_hash (void *Data, UINTN DataSize, UINT8 *password, - UINT32 pw_length, UINT8 *hash) +static EFI_STATUS compute_pw_hash(void *Data, UINTN DataSize, UINT8 * password, + UINT32 pw_length, UINT8 * hash) { - EFI_STATUS status; + EFI_STATUS efi_status; unsigned int ctxsize; void *ctx = NULL; ctxsize = Sha256GetContextSize(); ctx = AllocatePool(ctxsize); - if (!ctx) { console_notify(L"Unable to allocate memory for hash context"); return EFI_OUT_OF_RESOURCES; @@ -734,67 +704,67 @@ static EFI_STATUS compute_pw_hash (void *Data, UINTN DataSize, UINT8 *password, if (!Sha256Init(ctx)) { console_notify(L"Unable to initialise hash"); - status = EFI_OUT_OF_RESOURCES; + efi_status = EFI_OUT_OF_RESOURCES; goto done; } if (Data && DataSize) { if (!(Sha256Update(ctx, Data, DataSize))) { console_notify(L"Unable to generate hash"); - status = EFI_OUT_OF_RESOURCES; + efi_status = EFI_OUT_OF_RESOURCES; goto done; } } if (!(Sha256Update(ctx, password, pw_length))) { console_notify(L"Unable to generate hash"); - status = EFI_OUT_OF_RESOURCES; + efi_status = EFI_OUT_OF_RESOURCES; goto done; } if (!(Sha256Final(ctx, hash))) { console_notify(L"Unable to finalise hash"); - status = EFI_OUT_OF_RESOURCES; + efi_status = EFI_OUT_OF_RESOURCES; goto done; } - status = EFI_SUCCESS; + efi_status = EFI_SUCCESS; done: - return status; + return efi_status; } -static void console_save_and_set_mode (SIMPLE_TEXT_OUTPUT_MODE *SavedMode) +static void console_save_and_set_mode(SIMPLE_TEXT_OUTPUT_MODE * SavedMode) { + SIMPLE_TEXT_OUTPUT_INTERFACE *co = ST->ConOut; + if (!SavedMode) { - Print(L"Invalid parameter: SavedMode\n"); + console_print(L"Invalid parameter: SavedMode\n"); return; } - CopyMem(SavedMode, ST->ConOut->Mode, sizeof(SIMPLE_TEXT_OUTPUT_MODE)); - uefi_call_wrapper(ST->ConOut->EnableCursor, 2, ST->ConOut, FALSE); - uefi_call_wrapper(ST->ConOut->SetAttribute, 2, ST->ConOut, - EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE); + CopyMem(SavedMode, co->Mode, sizeof(SIMPLE_TEXT_OUTPUT_MODE)); + co->EnableCursor(co, FALSE); + co->SetAttribute(co, EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE); } -static void console_restore_mode (SIMPLE_TEXT_OUTPUT_MODE *SavedMode) +static void console_restore_mode(SIMPLE_TEXT_OUTPUT_MODE * SavedMode) { - uefi_call_wrapper(ST->ConOut->EnableCursor, 2, ST->ConOut, - SavedMode->CursorVisible); - uefi_call_wrapper(ST->ConOut->SetCursorPosition, 3, ST->ConOut, - SavedMode->CursorColumn, SavedMode->CursorRow); - uefi_call_wrapper(ST->ConOut->SetAttribute, 2, ST->ConOut, - SavedMode->Attribute); + SIMPLE_TEXT_OUTPUT_INTERFACE *co = ST->ConOut; + + co->EnableCursor(co, SavedMode->CursorVisible); + co->SetCursorPosition(co, SavedMode->CursorColumn, + SavedMode->CursorRow); + co->SetAttribute(co, SavedMode->Attribute); } -static INTN reset_system () +static INTN reset_system() { - uefi_call_wrapper(RT->ResetSystem, 4, EfiResetWarm, - EFI_SUCCESS, 0, NULL); + gRT->ResetSystem(EfiResetWarm, EFI_SUCCESS, 0, NULL); console_notify(L"Failed to reboot\n"); return -1; } -static UINT32 get_password (CHAR16 *prompt, CHAR16 *password, UINT32 max) +static UINT32 get_password(CHAR16 * prompt, CHAR16 * password, UINT32 max) { SIMPLE_TEXT_OUTPUT_MODE SavedMode; CHAR16 *str; @@ -816,7 +786,7 @@ static UINT32 get_password (CHAR16 *prompt, CHAR16 *password, UINT32 max) message[0] = str; message[1] = NULL; length = StrLen(message[0]); - console_print_box_at(message, -1, -length-4, -5, length+4, 3, 0, 1); + console_print_box_at(message, -1, -length - 4, -5, length + 4, 3, 0, 1); get_line(&pw_length, password, max, 0); console_restore_mode(&SavedMode); @@ -826,11 +796,11 @@ static UINT32 get_password (CHAR16 *prompt, CHAR16 *password, UINT32 max) return pw_length; } -static EFI_STATUS match_password (PASSWORD_CRYPT *pw_crypt, - void *Data, UINTN DataSize, - UINT8 *auth, CHAR16 *prompt) +static EFI_STATUS match_password(PASSWORD_CRYPT * pw_crypt, + void *Data, UINTN DataSize, + UINT8 * auth, CHAR16 * prompt) { - EFI_STATUS status; + EFI_STATUS efi_status; UINT8 hash[128]; UINT8 *auth_hash; UINT32 auth_size; @@ -841,7 +811,7 @@ static EFI_STATUS match_password (PASSWORD_CRYPT *pw_crypt, if (pw_crypt) { auth_hash = pw_crypt->hash; - auth_size = get_hash_size (pw_crypt->method); + auth_size = get_hash_size(pw_crypt->method); if (auth_size == 0) return EFI_INVALID_PARAMETER; } else if (auth) { @@ -869,15 +839,18 @@ static EFI_STATUS match_password (PASSWORD_CRYPT *pw_crypt, pw_ascii[i] = (char)password[i]; pw_ascii[pw_length] = '\0'; - status = password_crypt(pw_ascii, pw_length, pw_crypt, hash); + efi_status = password_crypt(pw_ascii, pw_length, + pw_crypt, hash); } else { /* * For backward compatibility */ - status = compute_pw_hash(Data, DataSize, (UINT8 *)password, - pw_length * sizeof(CHAR16), hash); + efi_status = compute_pw_hash(Data, DataSize, + (UINT8 *) password, + pw_length * sizeof(CHAR16), + hash); } - if (status != EFI_SUCCESS) { + if (EFI_ERROR(efi_status)) { console_errorbox(L"Unable to generate password hash"); fail_count++; continue; @@ -898,30 +871,23 @@ static EFI_STATUS match_password (PASSWORD_CRYPT *pw_crypt, return EFI_SUCCESS; } -static EFI_STATUS write_db (CHAR16 *db_name, void *MokNew, UINTN MokNewSize) +static EFI_STATUS write_db(CHAR16 * db_name, void *MokNew, UINTN MokNewSize) { - EFI_GUID shim_lock_guid = SHIM_LOCK_GUID; - EFI_STATUS status; + EFI_STATUS efi_status; UINT32 attributes; void *old_data = NULL; void *new_data = NULL; UINTN old_size; UINTN new_size; - status = uefi_call_wrapper(RT->SetVariable, 5, db_name, - &shim_lock_guid, - EFI_VARIABLE_NON_VOLATILE - | EFI_VARIABLE_BOOTSERVICE_ACCESS - | EFI_VARIABLE_APPEND_WRITE, - MokNewSize, MokNew); - if (status == EFI_SUCCESS || status != EFI_INVALID_PARAMETER) { - return status; - } + /* Do not use EFI_VARIABLE_APPEND_WRITE due to faulty firmwares. + * ref: https://github.com/rhboot/shim/issues/55 + * https://github.com/rhboot/shim/issues/105 */ - status = get_variable_attr(db_name, (UINT8 **)&old_data, &old_size, - shim_lock_guid, &attributes); - if (EFI_ERROR(status) && status != EFI_NOT_FOUND) { - return status; + efi_status = get_variable_attr(db_name, (UINT8 **)&old_data, &old_size, + SHIM_LOCK_GUID, &attributes); + if (EFI_ERROR(efi_status) && efi_status != EFI_NOT_FOUND) { + return efi_status; } /* Check if the old db is compromised or not */ @@ -934,19 +900,17 @@ static EFI_STATUS write_db (CHAR16 *db_name, void *MokNew, UINTN MokNewSize) new_size = old_size + MokNewSize; new_data = AllocatePool(new_size); if (new_data == NULL) { - status = EFI_OUT_OF_RESOURCES; + efi_status = EFI_OUT_OF_RESOURCES; goto out; } CopyMem(new_data, old_data, old_size); CopyMem(new_data + old_size, MokNew, MokNewSize); - status = uefi_call_wrapper(RT->SetVariable, 5, db_name, - &shim_lock_guid, - EFI_VARIABLE_NON_VOLATILE - | EFI_VARIABLE_BOOTSERVICE_ACCESS, - new_size, new_data); - + efi_status = gRT->SetVariable(db_name, &SHIM_LOCK_GUID, + EFI_VARIABLE_NON_VOLATILE | + EFI_VARIABLE_BOOTSERVICE_ACCESS, + new_size, new_data); out: if (old_size > 0) { FreePool(old_data); @@ -956,13 +920,12 @@ out: FreePool(new_data); } - return status; + return efi_status; } -static EFI_STATUS store_keys (void *MokNew, UINTN MokNewSize, int authenticate, - BOOLEAN MokX) +static EFI_STATUS store_keys(void *MokNew, UINTN MokNewSize, int authenticate, + BOOLEAN MokX) { - EFI_GUID shim_lock_guid = SHIM_LOCK_GUID; EFI_STATUS efi_status; CHAR16 *db_name; CHAR16 *auth_name; @@ -979,44 +942,43 @@ static EFI_STATUS store_keys (void *MokNew, UINTN MokNewSize, int authenticate, } if (authenticate) { - efi_status = uefi_call_wrapper(RT->GetVariable, 5, auth_name, - &shim_lock_guid, - &attributes, &auth_size, auth); - - if (efi_status != EFI_SUCCESS || + efi_status = gRT->GetVariable(auth_name, &SHIM_LOCK_GUID, + &attributes, &auth_size, auth); + if (EFI_ERROR(efi_status) || (auth_size != SHA256_DIGEST_SIZE && auth_size != PASSWORD_CRYPT_SIZE)) { if (MokX) - console_error(L"Failed to get MokXAuth", efi_status); + console_error(L"Failed to get MokXAuth", + efi_status); else - console_error(L"Failed to get MokAuth", efi_status); + console_error(L"Failed to get MokAuth", + efi_status); return efi_status; } if (auth_size == PASSWORD_CRYPT_SIZE) { - efi_status = match_password((PASSWORD_CRYPT *)auth, + efi_status = match_password((PASSWORD_CRYPT *) auth, NULL, 0, NULL, NULL); } else { efi_status = match_password(NULL, MokNew, MokNewSize, auth, NULL); } - if (efi_status != EFI_SUCCESS) + if (EFI_ERROR(efi_status)) return EFI_ACCESS_DENIED; } if (!MokNewSize) { /* Delete MOK */ - efi_status = uefi_call_wrapper(RT->SetVariable, 5, db_name, - &shim_lock_guid, - EFI_VARIABLE_NON_VOLATILE - | EFI_VARIABLE_BOOTSERVICE_ACCESS, - 0, NULL); + efi_status = gRT->SetVariable(db_name, &SHIM_LOCK_GUID, + EFI_VARIABLE_NON_VOLATILE | + EFI_VARIABLE_BOOTSERVICE_ACCESS, + 0, NULL); } else { /* Write new MOK */ efi_status = write_db(db_name, MokNew, MokNewSize); } - if (efi_status != EFI_SUCCESS) { + if (EFI_ERROR(efi_status)) { console_error(L"Failed to set variable", efi_status); return efi_status; } @@ -1024,11 +986,11 @@ static EFI_STATUS store_keys (void *MokNew, UINTN MokNewSize, int authenticate, return EFI_SUCCESS; } -static EFI_STATUS mok_enrollment_prompt (void *MokNew, UINTN MokNewSize, int auth, - BOOLEAN MokX) +static EFI_STATUS mok_enrollment_prompt(void *MokNew, UINTN MokNewSize, + int auth, BOOLEAN MokX) { - EFI_GUID shim_lock_guid = SHIM_LOCK_GUID; EFI_STATUS efi_status; + CHAR16 *enroll_p[] = { L"Enroll the key(s)?", NULL }; CHAR16 *title; if (MokX) @@ -1037,73 +999,66 @@ static EFI_STATUS mok_enrollment_prompt (void *MokNew, UINTN MokNewSize, int aut title = L"[Enroll MOK]"; efi_status = list_keys(MokNew, MokNewSize, title); - if (efi_status != EFI_SUCCESS) + if (EFI_ERROR(efi_status)) return efi_status; - if (console_yes_no((CHAR16 *[]){L"Enroll the key(s)?", NULL}) == 0) + if (console_yes_no(enroll_p) == 0) return EFI_ABORTED; efi_status = store_keys(MokNew, MokNewSize, auth, MokX); - - if (efi_status != EFI_SUCCESS) { + if (EFI_ERROR(efi_status)) { console_notify(L"Failed to enroll keys\n"); return efi_status; } if (auth) { if (MokX) { - LibDeleteVariable(L"MokXNew", &shim_lock_guid); - LibDeleteVariable(L"MokXAuth", &shim_lock_guid); + LibDeleteVariable(L"MokXNew", &SHIM_LOCK_GUID); + LibDeleteVariable(L"MokXAuth", &SHIM_LOCK_GUID); } else { - LibDeleteVariable(L"MokNew", &shim_lock_guid); - LibDeleteVariable(L"MokAuth", &shim_lock_guid); + LibDeleteVariable(L"MokNew", &SHIM_LOCK_GUID); + LibDeleteVariable(L"MokAuth", &SHIM_LOCK_GUID); } } - if (MokNew) - FreePool (MokNew); - return EFI_SUCCESS; } -static EFI_STATUS mok_reset_prompt (BOOLEAN MokX) +static EFI_STATUS mok_reset_prompt(BOOLEAN MokX) { - EFI_GUID shim_lock_guid = SHIM_LOCK_GUID; EFI_STATUS efi_status; - CHAR16 *prompt; + CHAR16 *prompt[] = { NULL, NULL }; - uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut); + ST->ConOut->ClearScreen(ST->ConOut); if (MokX) - prompt = L"Erase all stored keys in MokListX?"; + prompt[0] = L"Erase all stored keys in MokListX?"; else - prompt = L"Erase all stored keys in MokList?"; - if (console_yes_no((CHAR16 *[]){prompt, NULL }) == 0) + prompt[0] = L"Erase all stored keys in MokList?"; + + if (console_yes_no(prompt) == 0) return EFI_ABORTED; efi_status = store_keys(NULL, 0, TRUE, MokX); - - if (efi_status != EFI_SUCCESS) { + if (EFI_ERROR(efi_status)) { console_notify(L"Failed to erase keys\n"); return efi_status; } if (MokX) { - LibDeleteVariable(L"MokXNew", &shim_lock_guid); - LibDeleteVariable(L"MokXAuth", &shim_lock_guid); + LibDeleteVariable(L"MokXNew", &SHIM_LOCK_GUID); + LibDeleteVariable(L"MokXAuth", &SHIM_LOCK_GUID); } else { - LibDeleteVariable(L"MokNew", &shim_lock_guid); - LibDeleteVariable(L"MokAuth", &shim_lock_guid); + LibDeleteVariable(L"MokNew", &SHIM_LOCK_GUID); + LibDeleteVariable(L"MokAuth", &SHIM_LOCK_GUID); } return EFI_SUCCESS; } -static EFI_STATUS write_back_mok_list (MokListNode *list, INTN key_num, - BOOLEAN MokX) +static EFI_STATUS write_back_mok_list(MokListNode * list, INTN key_num, + BOOLEAN MokX) { - EFI_GUID shim_lock_guid = SHIM_LOCK_GUID; - EFI_GUID CertType = X509_GUID; EFI_STATUS efi_status; EFI_SIGNATURE_LIST *CertList; EFI_SIGNATURE_DATA *CertData; @@ -1122,7 +1077,7 @@ static EFI_STATUS write_back_mok_list (MokListNode *list, INTN key_num, continue; DataSize += sizeof(EFI_SIGNATURE_LIST); - if (CompareGuid(&(list[i].Type), &CertType) == 0) + if (CompareGuid(&(list[i].Type), &X509_GUID) == 0) DataSize += sizeof(EFI_GUID); DataSize += list[i].MokSize; } @@ -1137,40 +1092,41 @@ static EFI_STATUS write_back_mok_list (MokListNode *list, INTN key_num, if (list[i].Mok == NULL) continue; - CertList = (EFI_SIGNATURE_LIST *)ptr; - CertData = (EFI_SIGNATURE_DATA *)(((uint8_t *)ptr) + - sizeof(EFI_SIGNATURE_LIST)); + CertList = (EFI_SIGNATURE_LIST *) ptr; + CertData = (EFI_SIGNATURE_DATA *) (((uint8_t *) ptr) + + sizeof(EFI_SIGNATURE_LIST)); CertList->SignatureType = list[i].Type; CertList->SignatureHeaderSize = 0; - if (CompareGuid(&(list[i].Type), &CertType) == 0) { + if (CompareGuid(&(list[i].Type), &X509_GUID) == 0) { CertList->SignatureListSize = list[i].MokSize + - sizeof(EFI_SIGNATURE_LIST) + - sizeof(EFI_GUID); - CertList->SignatureSize = list[i].MokSize + sizeof(EFI_GUID); + sizeof(EFI_SIGNATURE_LIST) + sizeof(EFI_GUID); + CertList->SignatureSize = + list[i].MokSize + sizeof(EFI_GUID); - CertData->SignatureOwner = shim_lock_guid; - CopyMem(CertData->SignatureData, list[i].Mok, list[i].MokSize); + CertData->SignatureOwner = SHIM_LOCK_GUID; + CopyMem(CertData->SignatureData, list[i].Mok, + list[i].MokSize); } else { CertList->SignatureListSize = list[i].MokSize + - sizeof(EFI_SIGNATURE_LIST); - CertList->SignatureSize = sha_size(list[i].Type) + sizeof(EFI_GUID); + sizeof(EFI_SIGNATURE_LIST); + CertList->SignatureSize = + sha_size(list[i].Type) + sizeof(EFI_GUID); CopyMem(CertData, list[i].Mok, list[i].MokSize); } - ptr = (uint8_t *)ptr + CertList->SignatureListSize; + ptr = (uint8_t *) ptr + CertList->SignatureListSize; } - efi_status = uefi_call_wrapper(RT->SetVariable, 5, db_name, - &shim_lock_guid, - EFI_VARIABLE_NON_VOLATILE - | EFI_VARIABLE_BOOTSERVICE_ACCESS, - DataSize, Data); + efi_status = gRT->SetVariable(db_name, &SHIM_LOCK_GUID, + EFI_VARIABLE_NON_VOLATILE | + EFI_VARIABLE_BOOTSERVICE_ACCESS, + DataSize, Data); if (Data) FreePool(Data); - if (efi_status != EFI_SUCCESS) { + if (EFI_ERROR(efi_status)) { console_error(L"Failed to set variable", efi_status); return efi_status; } @@ -1178,14 +1134,13 @@ static EFI_STATUS write_back_mok_list (MokListNode *list, INTN key_num, return EFI_SUCCESS; } -static void delete_cert (void *key, UINT32 key_size, - MokListNode *mok, INTN mok_num) +static void delete_cert(void *key, UINT32 key_size, + MokListNode * mok, INTN mok_num) { - EFI_GUID CertType = X509_GUID; int i; for (i = 0; i < mok_num; i++) { - if (CompareGuid(&(mok[i].Type), &CertType) != 0) + if (CompareGuid(&(mok[i].Type), &X509_GUID) != 0) continue; if (mok[i].MokSize == key_size && @@ -1197,8 +1152,8 @@ static void delete_cert (void *key, UINT32 key_size, } } -static int match_hash (UINT8 *hash, UINT32 hash_size, int start, - void *hash_list, UINT32 list_num) +static int match_hash(UINT8 * hash, UINT32 hash_size, int start, + void *hash_list, UINT32 list_num) { UINT8 *ptr; UINTN i; @@ -1213,19 +1168,19 @@ static int match_hash (UINT8 *hash, UINT32 hash_size, int start, return -1; } -static void mem_move (void *dest, void *src, UINTN size) +static void mem_move(void *dest, void *src, UINTN size) { UINT8 *d, *s; UINTN i; - d = (UINT8 *)dest; - s = (UINT8 *)src; + d = (UINT8 *) dest; + s = (UINT8 *) src; for (i = 0; i < size; i++) d[i] = s[i]; } -static void delete_hash_in_list (EFI_GUID Type, UINT8 *hash, UINT32 hash_size, - MokListNode *mok, INTN mok_num) +static void delete_hash_in_list(EFI_GUID Type, UINT8 * hash, UINT32 hash_size, + MokListNode * mok, INTN mok_num) { UINT32 sig_size; UINT32 list_num; @@ -1242,8 +1197,7 @@ static void delete_hash_in_list (EFI_GUID Type, UINT8 *hash, UINT32 hash_size, list_num = mok[i].MokSize / sig_size; - del_ind = match_hash(hash, hash_size, 0, mok[i].Mok, - list_num); + del_ind = match_hash(hash, hash_size, 0, mok[i].Mok, list_num); while (del_ind >= 0) { /* Remove the hash */ if (sig_size == mok[i].MokSize) { @@ -1254,7 +1208,7 @@ static void delete_hash_in_list (EFI_GUID Type, UINT8 *hash, UINT32 hash_size, start = mok[i].Mok + del_ind * sig_size; end = start + sig_size; - remain = mok[i].MokSize - (del_ind + 1)*sig_size; + remain = mok[i].MokSize - (del_ind + 1) * sig_size; mem_move(start, end, remain); mok[i].MokSize -= sig_size; @@ -1266,8 +1220,8 @@ static void delete_hash_in_list (EFI_GUID Type, UINT8 *hash, UINT32 hash_size, } } -static void delete_hash_list (EFI_GUID Type, void *hash_list, UINT32 list_size, - MokListNode *mok, INTN mok_num) +static void delete_hash_list(EFI_GUID Type, void *hash_list, UINT32 list_size, + MokListNode * mok, INTN mok_num) { UINT32 hash_size; UINT32 hash_num; @@ -1275,7 +1229,7 @@ static void delete_hash_list (EFI_GUID Type, void *hash_list, UINT32 list_size, UINT8 *hash; UINT32 i; - hash_size = sha_size (Type); + hash_size = sha_size(Type); sig_size = hash_size + sizeof(EFI_GUID); if (list_size < sig_size) return; @@ -1285,26 +1239,23 @@ static void delete_hash_list (EFI_GUID Type, void *hash_list, UINT32 list_size, hash = hash_list + sizeof(EFI_GUID); for (i = 0; i < hash_num; i++) { - delete_hash_in_list (Type, hash, hash_size, mok, mok_num); + delete_hash_in_list(Type, hash, hash_size, mok, mok_num); hash += sig_size; } } -static EFI_STATUS delete_keys (void *MokDel, UINTN MokDelSize, BOOLEAN MokX) +static EFI_STATUS delete_keys(void *MokDel, UINTN MokDelSize, BOOLEAN MokX) { - EFI_GUID shim_lock_guid = SHIM_LOCK_GUID; - EFI_GUID CertType = X509_GUID; EFI_STATUS efi_status; CHAR16 *db_name; CHAR16 *auth_name; - CHAR16 *err_str1; - CHAR16 *err_str2; + CHAR16 *err_strs[] = { NULL, NULL, NULL }; UINT8 auth[PASSWORD_CRYPT_SIZE]; UINTN auth_size = PASSWORD_CRYPT_SIZE; UINT32 attributes; UINT8 *MokListData = NULL; UINTN MokListDataSize = 0; - MokListNode *mok, *del_key; + MokListNode *mok = NULL, *del_key = NULL; INTN mok_num, del_num; int i; @@ -1316,12 +1267,11 @@ static EFI_STATUS delete_keys (void *MokDel, UINTN MokDelSize, BOOLEAN MokX) auth_name = L"MokDelAuth"; } - efi_status = uefi_call_wrapper(RT->GetVariable, 5, auth_name, - &shim_lock_guid, - &attributes, &auth_size, auth); - - if (efi_status != EFI_SUCCESS || - (auth_size != SHA256_DIGEST_SIZE && auth_size != PASSWORD_CRYPT_SIZE)) { + efi_status = gRT->GetVariable(auth_name, &SHIM_LOCK_GUID, &attributes, + &auth_size, auth); + if (EFI_ERROR(efi_status) || + (auth_size != SHA256_DIGEST_SIZE + && auth_size != PASSWORD_CRYPT_SIZE)) { if (MokX) console_error(L"Failed to get MokXDelAuth", efi_status); else @@ -1330,17 +1280,18 @@ static EFI_STATUS delete_keys (void *MokDel, UINTN MokDelSize, BOOLEAN MokX) } if (auth_size == PASSWORD_CRYPT_SIZE) { - efi_status = match_password((PASSWORD_CRYPT *)auth, NULL, 0, + efi_status = match_password((PASSWORD_CRYPT *) auth, NULL, 0, NULL, NULL); } else { - efi_status = match_password(NULL, MokDel, MokDelSize, auth, NULL); + efi_status = + match_password(NULL, MokDel, MokDelSize, auth, NULL); } - if (efi_status != EFI_SUCCESS) + if (EFI_ERROR(efi_status)) return EFI_ACCESS_DENIED; - efi_status = get_variable_attr (db_name, &MokListData, &MokListDataSize, - shim_lock_guid, &attributes); - if (efi_status != EFI_SUCCESS) { + efi_status = get_variable_attr(db_name, &MokListData, &MokListDataSize, + SHIM_LOCK_GUID, &attributes); + if (EFI_ERROR(efi_status)) { if (MokX) console_errorbox(L"Failed to retrieve MokListX"); else @@ -1348,19 +1299,18 @@ static EFI_STATUS delete_keys (void *MokDel, UINTN MokDelSize, BOOLEAN MokX) return EFI_ABORTED; } else if (attributes & EFI_VARIABLE_RUNTIME_ACCESS) { if (MokX) { - err_str1 = L"MokListX is compromised!"; - err_str2 = L"Erase all keys in MokListX!"; + err_strs[0] = L"MokListX is compromised!"; + err_strs[1] = L"Erase all keys in MokListX!"; } else { - err_str1 = L"MokList is compromised!"; - err_str2 = L"Erase all keys in MokList!"; + err_strs[0] = L"MokList is compromised!"; + err_strs[1] = L"Erase all keys in MokList!"; } - console_alertbox((CHAR16 *[]){err_str1, err_str2, NULL}); - uefi_call_wrapper(RT->SetVariable, 5, db_name, - &shim_lock_guid, - EFI_VARIABLE_NON_VOLATILE | - EFI_VARIABLE_BOOTSERVICE_ACCESS, - 0, NULL); - return EFI_ACCESS_DENIED; + console_alertbox(err_strs); + gRT->SetVariable(db_name, &SHIM_LOCK_GUID, + EFI_VARIABLE_NON_VOLATILE | + EFI_VARIABLE_BOOTSERVICE_ACCESS, 0, NULL); + efi_status = EFI_ACCESS_DENIED; + goto error; } /* Nothing to do */ @@ -1371,18 +1321,16 @@ static EFI_STATUS delete_keys (void *MokDel, UINTN MokDelSize, BOOLEAN MokX) mok_num = count_keys(MokListData, MokListDataSize); if (mok_num == 0) { if (MokX) { - err_str1 = L"Failed to construct the key list of MokListX"; - err_str2 = L"Reset MokListX!"; + err_strs[0] = L"Failed to construct the key list of MokListX"; + err_strs[1] = L"Reset MokListX!"; } else { - err_str1 = L"Failed to construct the key list of MokList"; - err_str2 = L"Reset MokList!"; + err_strs[0] = L"Failed to construct the key list of MokList"; + err_strs[1] = L"Reset MokList!"; } - console_alertbox((CHAR16 *[]){err_str1, err_str2, NULL}); - uefi_call_wrapper(RT->SetVariable, 5, db_name, - &shim_lock_guid, - EFI_VARIABLE_NON_VOLATILE | - EFI_VARIABLE_BOOTSERVICE_ACCESS, - 0, NULL); + console_alertbox(err_strs); + gRT->SetVariable(db_name, &SHIM_LOCK_GUID, + EFI_VARIABLE_NON_VOLATILE | + EFI_VARIABLE_BOOTSERVICE_ACCESS, 0, NULL); efi_status = EFI_ABORTED; goto error; } @@ -1407,7 +1355,7 @@ static EFI_STATUS delete_keys (void *MokDel, UINTN MokDelSize, BOOLEAN MokX) /* Search and destroy */ for (i = 0; i < del_num; i++) { - if (CompareGuid(&(del_key[i].Type), &CertType) == 0) { + if (CompareGuid(&(del_key[i].Type), &X509_GUID) == 0) { delete_cert(del_key[i].Mok, del_key[i].MokSize, mok, mok_num); } else if (is_sha2_hash(del_key[i].Type)) { @@ -1429,10 +1377,11 @@ error: return efi_status; } -static EFI_STATUS mok_deletion_prompt (void *MokDel, UINTN MokDelSize, BOOLEAN MokX) +static EFI_STATUS mok_deletion_prompt(void *MokDel, UINTN MokDelSize, + BOOLEAN MokX) { - EFI_GUID shim_lock_guid = SHIM_LOCK_GUID; EFI_STATUS efi_status; + CHAR16 *delete_p[] = { L"Delete the key(s)?", NULL }; CHAR16 *title; if (MokX) @@ -1441,25 +1390,24 @@ static EFI_STATUS mok_deletion_prompt (void *MokDel, UINTN MokDelSize, BOOLEAN M title = L"[Delete MOK]"; efi_status = list_keys(MokDel, MokDelSize, title); - if (efi_status != EFI_SUCCESS) + if (EFI_ERROR(efi_status)) return efi_status; - if (console_yes_no((CHAR16 *[]){L"Delete the key(s)?", NULL}) == 0) + if (console_yes_no(delete_p) == 0) return EFI_ABORTED; efi_status = delete_keys(MokDel, MokDelSize, MokX); - - if (efi_status != EFI_SUCCESS) { + if (EFI_ERROR(efi_status)) { console_notify(L"Failed to delete keys"); return efi_status; } if (MokX) { - LibDeleteVariable(L"MokXDel", &shim_lock_guid); - LibDeleteVariable(L"MokXDelAuth", &shim_lock_guid); + LibDeleteVariable(L"MokXDel", &SHIM_LOCK_GUID); + LibDeleteVariable(L"MokXDelAuth", &SHIM_LOCK_GUID); } else { - LibDeleteVariable(L"MokDel", &shim_lock_guid); - LibDeleteVariable(L"MokDelAuth", &shim_lock_guid); + LibDeleteVariable(L"MokDel", &SHIM_LOCK_GUID); + LibDeleteVariable(L"MokDelAuth", &SHIM_LOCK_GUID); } if (MokDel) @@ -1468,10 +1416,10 @@ static EFI_STATUS mok_deletion_prompt (void *MokDel, UINTN MokDelSize, BOOLEAN M return EFI_SUCCESS; } -static CHAR16 get_password_charater (CHAR16 *prompt) +static CHAR16 get_password_charater(CHAR16 * prompt) { SIMPLE_TEXT_OUTPUT_MODE SavedMode; - EFI_STATUS status; + EFI_STATUS efi_status; CHAR16 *message[2]; CHAR16 character; UINTN length; @@ -1485,9 +1433,9 @@ static CHAR16 get_password_charater (CHAR16 *prompt) message[0] = prompt; message[1] = NULL; length = StrLen(message[0]); - console_print_box_at(message, -1, -length-4, -5, length+4, 3, 0, 1); - status = get_line(&pw_length, &character, 1, 0); - if (EFI_ERROR(status)) + console_print_box_at(message, -1, -length - 4, -5, length + 4, 3, 0, 1); + efi_status = get_line(&pw_length, &character, 1, 0); + if (EFI_ERROR(efi_status)) character = 0; console_restore_mode(&SavedMode); @@ -1495,8 +1443,8 @@ static CHAR16 get_password_charater (CHAR16 *prompt) return character; } -static EFI_STATUS mok_sb_prompt (void *MokSB, UINTN MokSBSize) { - EFI_GUID shim_lock_guid = SHIM_LOCK_GUID; +static EFI_STATUS mok_sb_prompt(void *MokSB, UINTN MokSBSize) +{ EFI_STATUS efi_status; SIMPLE_TEXT_OUTPUT_MODE SavedMode; MokSBvar *var = MokSB; @@ -1507,13 +1455,15 @@ static EFI_STATUS mok_sb_prompt (void *MokSB, UINTN MokSBSize) { UINT8 sbval = 1; UINT8 pos1, pos2, pos3; int ret; + CHAR16 *disable_sb[] = { L"Disable Secure Boot", NULL }; + CHAR16 *enable_sb[] = { L"Enable Secure Boot", NULL }; if (MokSBSize != sizeof(MokSBvar)) { console_notify(L"Invalid MokSB variable contents"); return EFI_INVALID_PARAMETER; } - uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut); + ST->ConOut->ClearScreen(ST->ConOut); message[0] = L"Change Secure Boot state"; message[1] = NULL; @@ -1523,17 +1473,17 @@ static EFI_STATUS mok_sb_prompt (void *MokSB, UINTN MokSBSize) { console_restore_mode(&SavedMode); while (fail_count < 3) { - RandomBytes (&pos1, sizeof(pos1)); + RandomBytes(&pos1, sizeof(pos1)); pos1 = (pos1 % var->PWLen); do { - RandomBytes (&pos2, sizeof(pos2)); + RandomBytes(&pos2, sizeof(pos2)); pos2 = (pos2 % var->PWLen); } while (pos2 == pos1); do { - RandomBytes (&pos3, sizeof(pos3)); - pos3 = (pos3 % var->PWLen) ; + RandomBytes(&pos3, sizeof(pos3)); + pos3 = (pos3 % var->PWLen); } while (pos3 == pos2 || pos3 == pos1); str = PoolPrint(L"Enter password character %d: ", pos1 + 1); @@ -1563,7 +1513,7 @@ static EFI_STATUS mok_sb_prompt (void *MokSB, UINTN MokSBSize) { if (pass1 != var->Password[pos1] || pass2 != var->Password[pos2] || pass3 != var->Password[pos3]) { - Print(L"Invalid character\n"); + console_print(L"Invalid character\n"); fail_count++; } else { break; @@ -1576,47 +1526,40 @@ static EFI_STATUS mok_sb_prompt (void *MokSB, UINTN MokSBSize) { } if (var->MokSBState == 0) - ret = console_yes_no((CHAR16 *[]){L"Disable Secure Boot", NULL}); + ret = console_yes_no(disable_sb); else - ret = console_yes_no((CHAR16 *[]){L"Enable Secure Boot", NULL}); + ret = console_yes_no(enable_sb); if (ret == 0) { - LibDeleteVariable(L"MokSB", &shim_lock_guid); + LibDeleteVariable(L"MokSB", &SHIM_LOCK_GUID); return EFI_ABORTED; } if (var->MokSBState == 0) { - efi_status = uefi_call_wrapper(RT->SetVariable, - 5, L"MokSBState", - &shim_lock_guid, - EFI_VARIABLE_NON_VOLATILE | - EFI_VARIABLE_BOOTSERVICE_ACCESS, - 1, &sbval); - if (efi_status != EFI_SUCCESS) { + efi_status = gRT->SetVariable(L"MokSBState", &SHIM_LOCK_GUID, + EFI_VARIABLE_NON_VOLATILE | + EFI_VARIABLE_BOOTSERVICE_ACCESS, + 1, &sbval); + if (EFI_ERROR(efi_status)) { console_notify(L"Failed to set Secure Boot state"); return efi_status; } } else { - efi_status = uefi_call_wrapper(RT->SetVariable, - 5, L"MokSBState", - &shim_lock_guid, - EFI_VARIABLE_NON_VOLATILE | - EFI_VARIABLE_BOOTSERVICE_ACCESS, - 0, NULL); - if (efi_status != EFI_SUCCESS) { + efi_status = gRT->SetVariable(L"MokSBState", &SHIM_LOCK_GUID, + EFI_VARIABLE_NON_VOLATILE | + EFI_VARIABLE_BOOTSERVICE_ACCESS, + 0, NULL); + if (EFI_ERROR(efi_status)) { console_notify(L"Failed to delete Secure Boot state"); return efi_status; } } - if (MokSB) - FreePool(MokSB); - return EFI_SUCCESS; } -static EFI_STATUS mok_db_prompt (void *MokDB, UINTN MokDBSize) { - EFI_GUID shim_lock_guid = SHIM_LOCK_GUID; +static EFI_STATUS mok_db_prompt(void *MokDB, UINTN MokDBSize) +{ EFI_STATUS efi_status; SIMPLE_TEXT_OUTPUT_MODE SavedMode; MokDBvar *var = MokDB; @@ -1627,13 +1570,15 @@ static EFI_STATUS mok_db_prompt (void *MokDB, UINTN MokDBSize) { UINT8 dbval = 1; UINT8 pos1, pos2, pos3; int ret; + CHAR16 *ignore_db[] = { L"Ignore DB certs/hashes", NULL }; + CHAR16 *use_db[] = { L"Use DB certs/hashes", NULL }; if (MokDBSize != sizeof(MokDBvar)) { console_notify(L"Invalid MokDB variable contents"); return EFI_INVALID_PARAMETER; } - uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut); + ST->ConOut->ClearScreen(ST->ConOut); message[0] = L"Change DB state"; message[1] = NULL; @@ -1643,17 +1588,17 @@ static EFI_STATUS mok_db_prompt (void *MokDB, UINTN MokDBSize) { console_restore_mode(&SavedMode); while (fail_count < 3) { - RandomBytes (&pos1, sizeof(pos1)); + RandomBytes(&pos1, sizeof(pos1)); pos1 = (pos1 % var->PWLen); do { - RandomBytes (&pos2, sizeof(pos2)); + RandomBytes(&pos2, sizeof(pos2)); pos2 = (pos2 % var->PWLen); } while (pos2 == pos1); do { - RandomBytes (&pos3, sizeof(pos3)); - pos3 = (pos3 % var->PWLen) ; + RandomBytes(&pos3, sizeof(pos3)); + pos3 = (pos3 % var->PWLen); } while (pos3 == pos2 || pos3 == pos1); str = PoolPrint(L"Enter password character %d: ", pos1 + 1); @@ -1683,7 +1628,7 @@ static EFI_STATUS mok_db_prompt (void *MokDB, UINTN MokDBSize) { if (pass1 != var->Password[pos1] || pass2 != var->Password[pos2] || pass3 != var->Password[pos3]) { - Print(L"Invalid character\n"); + console_print(L"Invalid character\n"); fail_count++; } else { break; @@ -1696,57 +1641,52 @@ static EFI_STATUS mok_db_prompt (void *MokDB, UINTN MokDBSize) { } if (var->MokDBState == 0) - ret = console_yes_no((CHAR16 *[]){L"Ignore DB certs/hashes", NULL}); + ret = console_yes_no(ignore_db); else - ret = console_yes_no((CHAR16 *[]){L"Use DB certs/hashes", NULL}); + ret = console_yes_no(use_db); if (ret == 0) { - LibDeleteVariable(L"MokDB", &shim_lock_guid); + LibDeleteVariable(L"MokDB", &SHIM_LOCK_GUID); return EFI_ABORTED; } if (var->MokDBState == 0) { - efi_status = uefi_call_wrapper(RT->SetVariable, - 5, L"MokDBState", - &shim_lock_guid, - EFI_VARIABLE_NON_VOLATILE | - EFI_VARIABLE_BOOTSERVICE_ACCESS, - 1, &dbval); - if (efi_status != EFI_SUCCESS) { + efi_status = gRT->SetVariable(L"MokDBState", &SHIM_LOCK_GUID, + EFI_VARIABLE_NON_VOLATILE | + EFI_VARIABLE_BOOTSERVICE_ACCESS, + 1, &dbval); + if (EFI_ERROR(efi_status)) { console_notify(L"Failed to set DB state"); return efi_status; } } else { - efi_status = uefi_call_wrapper(RT->SetVariable, 5, - L"MokDBState", - &shim_lock_guid, - EFI_VARIABLE_NON_VOLATILE | - EFI_VARIABLE_BOOTSERVICE_ACCESS, - 0, NULL); - if (efi_status != EFI_SUCCESS) { + efi_status = gRT->SetVariable(L"MokDBState", &SHIM_LOCK_GUID, + EFI_VARIABLE_NON_VOLATILE | + EFI_VARIABLE_BOOTSERVICE_ACCESS, + 0, NULL); + if (EFI_ERROR(efi_status)) { console_notify(L"Failed to delete DB state"); return efi_status; } } - if (MokDB) - FreePool(MokDB); - return EFI_SUCCESS; } -static EFI_STATUS mok_pw_prompt (void *MokPW, UINTN MokPWSize) { - EFI_GUID shim_lock_guid = SHIM_LOCK_GUID; +static EFI_STATUS mok_pw_prompt(void *MokPW, UINTN MokPWSize) +{ EFI_STATUS efi_status; UINT8 hash[PASSWORD_CRYPT_SIZE]; UINT8 clear = 0; + CHAR16 *clear_p[] = { L"Clear MOK password?", NULL }; + CHAR16 *set_p[] = { L"Set MOK password?", NULL }; if (MokPWSize != SHA256_DIGEST_SIZE && MokPWSize != PASSWORD_CRYPT_SIZE) { console_notify(L"Invalid MokPW variable contents"); return EFI_INVALID_PARAMETER; } - uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut); + ST->ConOut->ClearScreen(ST->ConOut); SetMem(hash, PASSWORD_CRYPT_SIZE, 0); @@ -1759,58 +1699,51 @@ static EFI_STATUS mok_pw_prompt (void *MokPW, UINTN MokPWSize) { } if (clear) { - if (console_yes_no((CHAR16 *[]){L"Clear MOK password?", NULL}) == 0) + if (console_yes_no(clear_p) == 0) return EFI_ABORTED; - uefi_call_wrapper(RT->SetVariable, 5, L"MokPWStore", - &shim_lock_guid, - EFI_VARIABLE_NON_VOLATILE - | EFI_VARIABLE_BOOTSERVICE_ACCESS, - 0, NULL); + gRT->SetVariable(L"MokPWStore", &SHIM_LOCK_GUID, + EFI_VARIABLE_NON_VOLATILE | + EFI_VARIABLE_BOOTSERVICE_ACCESS, 0, NULL); goto mokpw_done; } if (MokPWSize == PASSWORD_CRYPT_SIZE) { - efi_status = match_password((PASSWORD_CRYPT *)MokPW, NULL, 0, + efi_status = match_password((PASSWORD_CRYPT *) MokPW, NULL, 0, NULL, L"Confirm MOK passphrase: "); } else { efi_status = match_password(NULL, NULL, 0, MokPW, L"Confirm MOK passphrase: "); } - if (efi_status != EFI_SUCCESS) { + if (EFI_ERROR(efi_status)) { console_notify(L"Password limit reached"); return efi_status; } - if (console_yes_no((CHAR16 *[]){L"Set MOK password?", NULL}) == 0) + if (console_yes_no(set_p) == 0) return EFI_ABORTED; - efi_status = uefi_call_wrapper(RT->SetVariable, 5, - L"MokPWStore", - &shim_lock_guid, - EFI_VARIABLE_NON_VOLATILE | - EFI_VARIABLE_BOOTSERVICE_ACCESS, - MokPWSize, MokPW); - if (efi_status != EFI_SUCCESS) { + efi_status = gRT->SetVariable(L"MokPWStore", &SHIM_LOCK_GUID, + EFI_VARIABLE_NON_VOLATILE | + EFI_VARIABLE_BOOTSERVICE_ACCESS, + MokPWSize, MokPW); + if (EFI_ERROR(efi_status)) { console_notify(L"Failed to set MOK password"); return efi_status; } mokpw_done: - LibDeleteVariable(L"MokPW", &shim_lock_guid); - - if (MokPW) - FreePool(MokPW); + LibDeleteVariable(L"MokPW", &SHIM_LOCK_GUID); return EFI_SUCCESS; } -static BOOLEAN verify_certificate(UINT8 *cert, UINTN size) +static BOOLEAN verify_certificate(UINT8 * cert, UINTN size) { X509 *X509Cert; UINTN length; - if (!cert || size < 0) + if (!cert || size < 4) return FALSE; /* @@ -1825,13 +1758,13 @@ static BOOLEAN verify_certificate(UINT8 *cert, UINTN size) return FALSE; } - length = (cert[2]<<8 | cert[3]); + length = (cert[2] << 8 | cert[3]); if (length != (size - 4)) { console_notify(L"Invalid X509 certificate: Inconsistent size"); return FALSE; } - if (!(X509ConstructCertificate(cert, size, (UINT8 **) &X509Cert)) || + if (!(X509ConstructCertificate(cert, size, (UINT8 **) & X509Cert)) || X509Cert == NULL) { console_notify(L"Invalid X509 certificate"); return FALSE; @@ -1841,10 +1774,9 @@ static BOOLEAN verify_certificate(UINT8 *cert, UINTN size) return TRUE; } -static EFI_STATUS enroll_file (void *data, UINTN datasize, BOOLEAN hash) +static EFI_STATUS enroll_file(void *data, UINTN datasize, BOOLEAN hash) { - EFI_STATUS status = EFI_SUCCESS; - EFI_GUID shim_lock_guid = SHIM_LOCK_GUID; + EFI_STATUS efi_status = EFI_SUCCESS; EFI_SIGNATURE_LIST *CertList; EFI_SIGNATURE_DATA *CertData; UINTN mokbuffersize; @@ -1854,42 +1786,38 @@ static EFI_STATUS enroll_file (void *data, UINTN datasize, BOOLEAN hash) UINT8 sha256[SHA256_DIGEST_SIZE]; UINT8 sha1[SHA1_DIGEST_SIZE]; SHIM_LOCK *shim_lock; - EFI_GUID shim_guid = SHIM_LOCK_GUID; PE_COFF_LOADER_IMAGE_CONTEXT context; - - status = LibLocateProtocol(&shim_guid, (VOID **)&shim_lock); - if (status != EFI_SUCCESS) + efi_status = LibLocateProtocol(&SHIM_LOCK_GUID, + (VOID **) &shim_lock); + if (EFI_ERROR(efi_status)) goto out; mokbuffersize = sizeof(EFI_SIGNATURE_LIST) + sizeof(EFI_GUID) + - SHA256_DIGEST_SIZE; + SHA256_DIGEST_SIZE; mokbuffer = AllocatePool(mokbuffersize); - if (!mokbuffer) goto out; - status = shim_lock->Context(data, datasize, &context); - - if (status != EFI_SUCCESS) + efi_status = shim_lock->Context(data, datasize, &context); + if (EFI_ERROR(efi_status)) goto out; - - status = shim_lock->Hash(data, datasize, &context, sha256, - sha1); - if (status != EFI_SUCCESS) + efi_status = shim_lock->Hash(data, datasize, &context, sha256, + sha1); + if (EFI_ERROR(efi_status)) goto out; CertList = mokbuffer; CertList->SignatureType = EFI_CERT_SHA256_GUID; CertList->SignatureSize = 16 + SHA256_DIGEST_SIZE; - CertData = (EFI_SIGNATURE_DATA *)(((UINT8 *)mokbuffer) + - sizeof(EFI_SIGNATURE_LIST)); + CertData = (EFI_SIGNATURE_DATA *) (((UINT8 *) mokbuffer) + + sizeof(EFI_SIGNATURE_LIST)); CopyMem(CertData->SignatureData, sha256, SHA256_DIGEST_SIZE); } else { mokbuffersize = datasize + sizeof(EFI_SIGNATURE_LIST) + - sizeof(EFI_GUID); + sizeof(EFI_GUID); mokbuffer = AllocatePool(mokbuffersize); if (!mokbuffer) @@ -1902,67 +1830,68 @@ static EFI_STATUS enroll_file (void *data, UINTN datasize, BOOLEAN hash) memcpy(mokbuffer + sizeof(EFI_SIGNATURE_LIST) + 16, data, datasize); - CertData = (EFI_SIGNATURE_DATA *)(((UINT8 *)mokbuffer) + - sizeof(EFI_SIGNATURE_LIST)); + CertData = (EFI_SIGNATURE_DATA *) (((UINT8 *) mokbuffer) + + sizeof(EFI_SIGNATURE_LIST)); } CertList->SignatureListSize = mokbuffersize; CertList->SignatureHeaderSize = 0; - CertData->SignatureOwner = shim_lock_guid; + CertData->SignatureOwner = SHIM_LOCK_GUID; if (!hash) { if (!verify_certificate(CertData->SignatureData, datasize)) goto out; } - status = mok_enrollment_prompt(mokbuffer, mokbuffersize, FALSE, FALSE); + efi_status = mok_enrollment_prompt(mokbuffer, mokbuffersize, + FALSE, FALSE); out: if (mokbuffer) FreePool(mokbuffer); - return status; + return efi_status; } static EFI_STATUS mok_hash_enroll(void) { EFI_STATUS efi_status; - CHAR16 *file_name = NULL; + CHAR16 *file_name = NULL; EFI_HANDLE im = NULL; EFI_FILE *file = NULL; UINTN filesize; void *data; + CHAR16 *selections[] = { + L"Select Binary", + L"", + L"The Selected Binary will have its hash Enrolled", + L"This means it will subsequently Boot with no prompting", + L"Remember to make sure it is a genuine binary before enrolling its hash", + NULL + }; - simple_file_selector(&im, (CHAR16 *[]){ - L"Select Binary", - L"", - L"The Selected Binary will have its hash Enrolled", - L"This means it will Subsequently Boot with no prompting", - L"Remember to make sure it is a genuine binary before Enroling its hash", - NULL - }, L"\\", L"", &file_name); + simple_file_selector(&im, selections, L"\\", L"", &file_name); if (!file_name) return EFI_INVALID_PARAMETER; efi_status = simple_file_open(im, file_name, &file, EFI_FILE_MODE_READ); - - if (efi_status != EFI_SUCCESS) { + if (EFI_ERROR(efi_status)) { console_error(L"Unable to open file", efi_status); return efi_status; } simple_file_read_all(file, &filesize, &data); - simple_file_close(file); - + file->Close(file); if (!filesize) { console_error(L"Unable to read file", efi_status); return EFI_BAD_BUFFER_SIZE; } efi_status = enroll_file(data, filesize, TRUE); - - if (efi_status != EFI_SUCCESS) - console_error(L"Hash failed (did you select a valid EFI binary?)", efi_status); + if (EFI_ERROR(efi_status)) + console_error( + L"Hash failed (did you select a valid EFI binary?)", + efi_status); FreePool(data); @@ -1976,7 +1905,7 @@ static CHAR16 *der_suffix[] = { NULL }; -static BOOLEAN check_der_suffix (CHAR16 *file_name) +static BOOLEAN check_der_suffix(CHAR16 * file_name) { CHAR16 suffix[5]; int i; @@ -1985,9 +1914,9 @@ static BOOLEAN check_der_suffix (CHAR16 *file_name) return FALSE; suffix[0] = '\0'; - StrCat(suffix, file_name + StrLen(file_name) - 4); + StrnCat(suffix, file_name + StrLen(file_name) - 4, 4); - StrLwr (suffix); + StrLwr(suffix); for (i = 0; der_suffix[i] != NULL; i++) { if (StrCmp(suffix, der_suffix[i]) == 0) { return TRUE; @@ -2000,43 +1929,44 @@ static BOOLEAN check_der_suffix (CHAR16 *file_name) static EFI_STATUS mok_key_enroll(void) { EFI_STATUS efi_status; - CHAR16 *file_name = NULL; + CHAR16 *file_name = NULL; EFI_HANDLE im = NULL; EFI_FILE *file = NULL; UINTN filesize; void *data; + CHAR16 *selections[] = { + L"Select Key", + L"", + L"The selected key will be enrolled into the MOK database", + L"This means any binaries signed with it will be run without prompting", + L"Remember to make sure it is a genuine key before Enrolling it", + NULL + }; + CHAR16 *alert[] = { + L"Unsupported Format", + L"", + L"Only DER encoded certificate (*.cer/der/crt) is supported", + NULL + }; - simple_file_selector(&im, (CHAR16 *[]){ - L"Select Key", - L"", - L"The selected key will be enrolled into the MOK database", - L"This means any binaries signed with it will be run without prompting", - L"Remember to make sure it is a genuine key before Enroling it", - NULL - }, L"\\", L"", &file_name); + simple_file_selector(&im, selections, L"\\", L"", &file_name); if (!file_name) return EFI_INVALID_PARAMETER; if (!check_der_suffix(file_name)) { - console_alertbox((CHAR16 *[]){ - L"Unsupported Format", - L"", - L"Only DER encoded certificate (*.cer/der/crt) is supported", - NULL}); + console_alertbox(alert); return EFI_UNSUPPORTED; } efi_status = simple_file_open(im, file_name, &file, EFI_FILE_MODE_READ); - - if (efi_status != EFI_SUCCESS) { + if (EFI_ERROR(efi_status)) { console_error(L"Unable to open file", efi_status); return efi_status; } simple_file_read_all(file, &filesize, &data); - simple_file_close(file); - + file->Close(file); if (!filesize) { console_error(L"Unable to read file", efi_status); return EFI_BAD_BUFFER_SIZE; @@ -2048,9 +1978,8 @@ static EFI_STATUS mok_key_enroll(void) return efi_status; } -static BOOLEAN verify_pw(BOOLEAN *protected) +static BOOLEAN verify_pw(BOOLEAN * protected) { - EFI_GUID shim_lock_guid = SHIM_LOCK_GUID; EFI_STATUS efi_status; SIMPLE_TEXT_OUTPUT_MODE SavedMode; UINT8 pwhash[PASSWORD_CRYPT_SIZE]; @@ -2060,40 +1989,38 @@ static BOOLEAN verify_pw(BOOLEAN *protected) *protected = FALSE; - efi_status = uefi_call_wrapper(RT->GetVariable, 5, L"MokPWStore", - &shim_lock_guid, &attributes, &size, - pwhash); - + efi_status = gRT->GetVariable(L"MokPWStore", &SHIM_LOCK_GUID, &attributes, + &size, pwhash); /* * If anything can attack the password it could just set it to a * known value, so there's no safety advantage in failing to validate * purely because of a failure to read the variable */ - if (efi_status != EFI_SUCCESS || + if (EFI_ERROR(efi_status) || (size != SHA256_DIGEST_SIZE && size != PASSWORD_CRYPT_SIZE)) return TRUE; if (attributes & EFI_VARIABLE_RUNTIME_ACCESS) return TRUE; - uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut); + ST->ConOut->ClearScreen(ST->ConOut); /* Draw the background */ console_save_and_set_mode(&SavedMode); - message[0] = PoolPrint (L"%s UEFI key management", SHIM_VENDOR); + message[0] = PoolPrint(L"%s UEFI key management", SHIM_VENDOR); message[1] = NULL; console_print_box_at(message, -1, 0, 0, -1, -1, 1, 1); FreePool(message[0]); console_restore_mode(&SavedMode); if (size == PASSWORD_CRYPT_SIZE) { - efi_status = match_password((PASSWORD_CRYPT *)pwhash, NULL, 0, + efi_status = match_password((PASSWORD_CRYPT *) pwhash, NULL, 0, NULL, L"Enter MOK password:"); } else { efi_status = match_password(NULL, NULL, 0, pwhash, L"Enter MOK password:"); } - if (efi_status != EFI_SUCCESS) { + if (EFI_ERROR(efi_status)) { console_notify(L"Password limit reached"); return FALSE; } @@ -2105,37 +2032,57 @@ static BOOLEAN verify_pw(BOOLEAN *protected) static int draw_countdown() { + SIMPLE_TEXT_OUTPUT_INTERFACE *co = ST->ConOut; + SIMPLE_INPUT_INTERFACE *ci = ST->ConIn; SIMPLE_TEXT_OUTPUT_MODE SavedMode; EFI_INPUT_KEY key; - EFI_STATUS status; + EFI_STATUS efi_status; UINTN cols, rows; CHAR16 *title[2]; - CHAR16 *message = L"Press any key to perform MOK management"; - int timeout = 10, wait = 10000000; + CHAR16 *message = L"Press any key to perform MOK management"; + void *MokTimeout = NULL; + MokTimeoutvar *var; + UINTN MokTimeoutSize = 0; + int timeout, wait = 10000000; - console_save_and_set_mode (&SavedMode); + efi_status = get_variable(L"MokTimeout", (UINT8 **) &MokTimeout, + &MokTimeoutSize, SHIM_LOCK_GUID); + if (EFI_ERROR(efi_status)) { + timeout = 10; + } else { + var = MokTimeout; + timeout = (int)var->Timeout; + FreePool(MokTimeout); + LibDeleteVariable(L"MokTimeout", &SHIM_LOCK_GUID); + } - title[0] = PoolPrint (L"%s UEFI key management", SHIM_VENDOR); + if (timeout < 0) + return timeout; + + console_save_and_set_mode(&SavedMode); + + title[0] = PoolPrint(L"%s UEFI key management", SHIM_VENDOR); title[1] = NULL; console_print_box_at(title, -1, 0, 0, -1, -1, 1, 1); - uefi_call_wrapper(ST->ConOut->QueryMode, 4, ST->ConOut, - ST->ConOut->Mode->Mode, &cols, &rows); + co->QueryMode(co, co->Mode->Mode, &cols, &rows); - PrintAt((cols - StrLen(message))/2, rows/2, message); + console_print_at((cols - StrLen(message)) / 2, rows / 2, message); while (1) { if (timeout > 1) - PrintAt(2, rows - 3, L"Booting in %d seconds ", timeout); + console_print_at(2, rows - 3, + L"Booting in %d seconds ", + timeout); else if (timeout) - PrintAt(2, rows - 3, L"Booting in %d second ", timeout); + console_print_at(2, rows - 3, + L"Booting in %d second ", + timeout); - status = WaitForSingleEvent(ST->ConIn->WaitForKey, wait); - - if (status != EFI_TIMEOUT) { + efi_status = WaitForSingleEvent(ci->WaitForKey, wait); + if (efi_status != EFI_TIMEOUT) { /* Clear the key in the queue */ - uefi_call_wrapper(ST->ConIn->ReadKeyStroke, 2, - ST->ConIn, &key); + ci->ReadKeyStroke(ci, &key); break; } @@ -2166,7 +2113,7 @@ typedef enum { MOK_HASH_ENROLL } mok_menu_item; -static void free_menu(mok_menu_item *menu_item, CHAR16 **menu_strings) +static void free_menu(mok_menu_item * menu_item, CHAR16 ** menu_strings) { if (menu_strings) FreePool(menu_strings); @@ -2184,21 +2131,21 @@ static EFI_STATUS enter_mok_menu(EFI_HANDLE image_handle, void *MokXNew, UINTN MokXNewSize, void *MokXDel, UINTN MokXDelSize) { - CHAR16 **menu_strings; - mok_menu_item *menu_item; + CHAR16 **menu_strings = NULL; + mok_menu_item *menu_item = NULL; int choice = 0; int mok_changed = 0; EFI_STATUS efi_status; - EFI_GUID shim_lock_guid = SHIM_LOCK_GUID; UINT8 auth[PASSWORD_CRYPT_SIZE]; UINTN auth_size = PASSWORD_CRYPT_SIZE; UINT32 attributes; BOOLEAN protected; + CHAR16 *mok_mgmt_p[] = { L"Perform MOK management", NULL }; EFI_STATUS ret = EFI_SUCCESS; if (verify_pw(&protected) == FALSE) return EFI_ACCESS_DENIED; - + if (protected == FALSE && draw_countdown() == 0) goto out; @@ -2209,36 +2156,32 @@ static EFI_STATUS enter_mok_menu(EFI_HANDLE image_handle, UINT32 MokXAuth = 0; UINT32 MokXDelAuth = 0; - efi_status = uefi_call_wrapper(RT->GetVariable, 5, L"MokAuth", - &shim_lock_guid, - &attributes, &auth_size, auth); - - if ((efi_status == EFI_SUCCESS) && - (auth_size == SHA256_DIGEST_SIZE || auth_size == PASSWORD_CRYPT_SIZE)) + efi_status = gRT->GetVariable(L"MokAuth", &SHIM_LOCK_GUID, + &attributes, &auth_size, auth); + if (!EFI_ERROR(efi_status) && + (auth_size == SHA256_DIGEST_SIZE || + auth_size == PASSWORD_CRYPT_SIZE)) MokAuth = 1; - efi_status = uefi_call_wrapper(RT->GetVariable, 5, L"MokDelAuth", - &shim_lock_guid, - &attributes, &auth_size, auth); - - if ((efi_status == EFI_SUCCESS) && - (auth_size == SHA256_DIGEST_SIZE || auth_size == PASSWORD_CRYPT_SIZE)) + efi_status = gRT->GetVariable(L"MokDelAuth", &SHIM_LOCK_GUID, + &attributes, &auth_size, auth); + if (!EFI_ERROR(efi_status) && + (auth_size == SHA256_DIGEST_SIZE || + auth_size == PASSWORD_CRYPT_SIZE)) MokDelAuth = 1; - efi_status = uefi_call_wrapper(RT->GetVariable, 5, L"MokXAuth", - &shim_lock_guid, - &attributes, &auth_size, auth); - - if ((efi_status == EFI_SUCCESS) && - (auth_size == SHA256_DIGEST_SIZE || auth_size == PASSWORD_CRYPT_SIZE)) + efi_status = gRT->GetVariable(L"MokXAuth", &SHIM_LOCK_GUID, + &attributes, &auth_size, auth); + if (!EFI_ERROR(efi_status) && + (auth_size == SHA256_DIGEST_SIZE || + auth_size == PASSWORD_CRYPT_SIZE)) MokXAuth = 1; - efi_status = uefi_call_wrapper(RT->GetVariable, 5, L"MokXDelAuth", - &shim_lock_guid, - &attributes, &auth_size, auth); - - if ((efi_status == EFI_SUCCESS) && - (auth_size == SHA256_DIGEST_SIZE || auth_size == PASSWORD_CRYPT_SIZE)) + efi_status = gRT->GetVariable(L"MokXDelAuth", &SHIM_LOCK_GUID, + &attributes, &auth_size, auth); + if (!EFI_ERROR(efi_status) && + (auth_size == SHA256_DIGEST_SIZE || + auth_size == PASSWORD_CRYPT_SIZE)) MokXDelAuth = 1; if (MokNew || MokAuth) @@ -2262,13 +2205,12 @@ static EFI_STATUS enter_mok_menu(EFI_HANDLE image_handle, if (MokDB) menucount++; - menu_strings = AllocateZeroPool(sizeof(CHAR16 *) * (menucount + 1)); - + menu_strings = AllocateZeroPool(sizeof(CHAR16 *) * + (menucount + 1)); if (!menu_strings) return EFI_OUT_OF_RESOURCES; menu_item = AllocateZeroPool(sizeof(mok_menu_item) * menucount); - if (!menu_item) { FreePool(menu_strings); return EFI_OUT_OF_RESOURCES; @@ -2344,9 +2286,7 @@ static EFI_STATUS enter_mok_menu(EFI_HANDLE image_handle, menu_strings[i] = NULL; - choice = console_select((CHAR16 *[]){ L"Perform MOK management", NULL }, - menu_strings, 0); - + choice = console_select(mok_mgmt_p, menu_strings, 0); if (choice < 0) goto out; @@ -2357,41 +2297,87 @@ static EFI_STATUS enter_mok_menu(EFI_HANDLE image_handle, efi_status = mok_reset_prompt(FALSE); break; case MOK_ENROLL_MOK: - efi_status = mok_enrollment_prompt(MokNew, MokNewSize, TRUE, FALSE); - if (efi_status == EFI_SUCCESS) + if (!MokNew) { + console_print(L"MokManager: internal error: %s", + L"MokNew was !NULL but is now NULL\n"); + ret = EFI_ABORTED; + goto out; + } + efi_status = mok_enrollment_prompt(MokNew, MokNewSize, + TRUE, FALSE); + if (!EFI_ERROR(efi_status)) MokNew = NULL; break; case MOK_DELETE_MOK: - efi_status = mok_deletion_prompt(MokDel, MokDelSize, FALSE); - if (efi_status == EFI_SUCCESS) + if (!MokDel) { + console_print(L"MokManager: internal error: %s", + L"MokDel was !NULL but is now NULL\n"); + ret = EFI_ABORTED; + goto out; + } + efi_status = mok_deletion_prompt(MokDel, MokDelSize, + FALSE); + if (!EFI_ERROR(efi_status)) MokDel = NULL; break; case MOK_RESET_MOKX: efi_status = mok_reset_prompt(TRUE); break; case MOK_ENROLL_MOKX: - efi_status = mok_enrollment_prompt(MokXNew, MokXNewSize, TRUE, TRUE); - if (efi_status == EFI_SUCCESS) + if (!MokXNew) { + console_print(L"MokManager: internal error: %s", + L"MokXNew was !NULL but is now NULL\n"); + ret = EFI_ABORTED; + goto out; + } + efi_status = mok_enrollment_prompt(MokXNew, MokXNewSize, + TRUE, TRUE); + if (!EFI_ERROR(efi_status)) MokXNew = NULL; break; case MOK_DELETE_MOKX: - efi_status = mok_deletion_prompt(MokXDel, MokXDelSize, TRUE); - if (efi_status == EFI_SUCCESS) + if (!MokXDel) { + console_print(L"MokManager: internal error: %s", + L"MokXDel was !NULL but is now NULL\n"); + ret = EFI_ABORTED; + goto out; + } + efi_status = mok_deletion_prompt(MokXDel, MokXDelSize, + TRUE); + if (!EFI_ERROR(efi_status)) MokXDel = NULL; break; case MOK_CHANGE_SB: + if (!MokSB) { + console_print(L"MokManager: internal error: %s", + L"MokSB was !NULL but is now NULL\n"); + ret = EFI_ABORTED; + goto out; + } efi_status = mok_sb_prompt(MokSB, MokSBSize); - if (efi_status == EFI_SUCCESS) + if (!EFI_ERROR(efi_status)) MokSB = NULL; break; case MOK_SET_PW: + if (!MokPW) { + console_print(L"MokManager: internal error: %s", + L"MokPW was !NULL but is now NULL\n"); + ret = EFI_ABORTED; + goto out; + } efi_status = mok_pw_prompt(MokPW, MokPWSize); - if (efi_status == EFI_SUCCESS) + if (!EFI_ERROR(efi_status)) MokPW = NULL; break; case MOK_CHANGE_DB: + if (!MokDB) { + console_print(L"MokManager: internal error: %s", + L"MokDB was !NULL but is now NULL\n"); + ret = EFI_ABORTED; + goto out; + } efi_status = mok_db_prompt(MokDB, MokDBSize); - if (efi_status == EFI_SUCCESS) + if (!EFI_ERROR(efi_status)) MokDB = NULL; break; case MOK_KEY_ENROLL: @@ -2402,10 +2388,12 @@ static EFI_STATUS enter_mok_menu(EFI_HANDLE image_handle, break; } - if (efi_status == EFI_SUCCESS) + if (!EFI_ERROR(efi_status)) mok_changed = 1; free_menu(menu_item, menu_strings); + menu_item = NULL; + menu_strings = NULL; } out: @@ -2421,7 +2409,6 @@ out: static EFI_STATUS check_mok_request(EFI_HANDLE image_handle) { - EFI_GUID shim_lock_guid = SHIM_LOCK_GUID; UINTN MokNewSize = 0, MokDelSize = 0, MokSBSize = 0, MokPWSize = 0; UINTN MokDBSize = 0, MokXNewSize = 0, MokXDelSize = 0; void *MokNew = NULL; @@ -2431,76 +2418,76 @@ static EFI_STATUS check_mok_request(EFI_HANDLE image_handle) void *MokDB = NULL; void *MokXNew = NULL; void *MokXDel = NULL; - EFI_STATUS status; + EFI_STATUS efi_status; - status = get_variable(L"MokNew", (UINT8 **)&MokNew, &MokNewSize, - shim_lock_guid); - if (status == EFI_SUCCESS) { - if (LibDeleteVariable(L"MokNew", &shim_lock_guid) != EFI_SUCCESS) { + efi_status = get_variable(L"MokNew", (UINT8 **) & MokNew, &MokNewSize, + SHIM_LOCK_GUID); + if (!EFI_ERROR(efi_status)) { + efi_status = LibDeleteVariable(L"MokNew", &SHIM_LOCK_GUID); + if (EFI_ERROR(efi_status)) console_notify(L"Failed to delete MokNew"); - } - } else if (EFI_ERROR(status) && status != EFI_NOT_FOUND) { - console_error(L"Could not retrieve MokNew", status); + } else if (EFI_ERROR(efi_status) && efi_status != EFI_NOT_FOUND) { + console_error(L"Could not retrieve MokNew", efi_status); } - status = get_variable(L"MokDel", (UINT8 **)&MokDel, &MokDelSize, - shim_lock_guid); - if (status == EFI_SUCCESS) { - if (LibDeleteVariable(L"MokDel", &shim_lock_guid) != EFI_SUCCESS) { + efi_status = get_variable(L"MokDel", (UINT8 **) & MokDel, &MokDelSize, + SHIM_LOCK_GUID); + if (!EFI_ERROR(efi_status)) { + efi_status = LibDeleteVariable(L"MokDel", &SHIM_LOCK_GUID); + if (EFI_ERROR(efi_status)) console_notify(L"Failed to delete MokDel"); - } - } else if (EFI_ERROR(status) && status != EFI_NOT_FOUND) { - console_error(L"Could not retrieve MokDel", status); + } else if (EFI_ERROR(efi_status) && efi_status != EFI_NOT_FOUND) { + console_error(L"Could not retrieve MokDel", efi_status); } - status = get_variable(L"MokSB", (UINT8 **)&MokSB, &MokSBSize, - shim_lock_guid); - if (status == EFI_SUCCESS) { - if (LibDeleteVariable(L"MokSB", &shim_lock_guid) != EFI_SUCCESS) { + efi_status = get_variable(L"MokSB", (UINT8 **) & MokSB, &MokSBSize, + SHIM_LOCK_GUID); + if (!EFI_ERROR(efi_status)) { + efi_status = LibDeleteVariable(L"MokSB", &SHIM_LOCK_GUID); + if (EFI_ERROR(efi_status)) console_notify(L"Failed to delete MokSB"); - } - } else if (EFI_ERROR(status) && status != EFI_NOT_FOUND) { - console_error(L"Could not retrieve MokSB", status); + } else if (EFI_ERROR(efi_status) && efi_status != EFI_NOT_FOUND) { + console_error(L"Could not retrieve MokSB", efi_status); } - status = get_variable(L"MokPW", (UINT8 **)&MokPW, &MokPWSize, - shim_lock_guid); - if (status == EFI_SUCCESS) { - if (LibDeleteVariable(L"MokPW", &shim_lock_guid) != EFI_SUCCESS) { + efi_status = get_variable(L"MokPW", (UINT8 **) & MokPW, &MokPWSize, + SHIM_LOCK_GUID); + if (!EFI_ERROR(efi_status)) { + efi_status = LibDeleteVariable(L"MokPW", &SHIM_LOCK_GUID); + if (EFI_ERROR(efi_status)) console_notify(L"Failed to delete MokPW"); - } - } else if (EFI_ERROR(status) && status != EFI_NOT_FOUND) { - console_error(L"Could not retrieve MokPW", status); + } else if (EFI_ERROR(efi_status) && efi_status != EFI_NOT_FOUND) { + console_error(L"Could not retrieve MokPW", efi_status); } - status = get_variable(L"MokDB", (UINT8 **)&MokDB, &MokDBSize, - shim_lock_guid); - if (status == EFI_SUCCESS) { - if (LibDeleteVariable(L"MokDB", &shim_lock_guid) != EFI_SUCCESS) { + efi_status = get_variable(L"MokDB", (UINT8 **) & MokDB, &MokDBSize, + SHIM_LOCK_GUID); + if (!EFI_ERROR(efi_status)) { + efi_status = LibDeleteVariable(L"MokDB", &SHIM_LOCK_GUID); + if (EFI_ERROR(efi_status)) console_notify(L"Failed to delete MokDB"); - } - } else if (EFI_ERROR(status) && status != EFI_NOT_FOUND) { - console_error(L"Could not retrieve MokDB", status); + } else if (EFI_ERROR(efi_status) && efi_status != EFI_NOT_FOUND) { + console_error(L"Could not retrieve MokDB", efi_status); } - status = get_variable(L"MokXNew", (UINT8 **)&MokXNew, &MokXNewSize, - shim_lock_guid); - if (status == EFI_SUCCESS) { - if (LibDeleteVariable(L"MokXNew", &shim_lock_guid) != EFI_SUCCESS) { + efi_status = get_variable(L"MokXNew", (UINT8 **) & MokXNew, + &MokXNewSize, SHIM_LOCK_GUID); + if (!EFI_ERROR(efi_status)) { + efi_status = LibDeleteVariable(L"MokXNew", &SHIM_LOCK_GUID); + if (EFI_ERROR(efi_status)) console_notify(L"Failed to delete MokXNew"); - } - } else if (EFI_ERROR(status) && status != EFI_NOT_FOUND) { - console_error(L"Could not retrieve MokXNew", status); + } else if (EFI_ERROR(efi_status) && efi_status != EFI_NOT_FOUND) { + console_error(L"Could not retrieve MokXNew", efi_status); } - status = get_variable(L"MokXDel", (UINT8 **)&MokXDel, &MokXDelSize, - shim_lock_guid); - if (status == EFI_SUCCESS) { - if (LibDeleteVariable(L"MokXDel", &shim_lock_guid) != EFI_SUCCESS) { + efi_status = get_variable(L"MokXDel", (UINT8 **) & MokXDel, + &MokXDelSize, SHIM_LOCK_GUID); + if (!EFI_ERROR(efi_status)) { + efi_status = LibDeleteVariable(L"MokXDel", &SHIM_LOCK_GUID); + if (EFI_ERROR(efi_status)) console_notify(L"Failed to delete MokXDel"); - } - } else if (EFI_ERROR(status) && status != EFI_NOT_FOUND) { - console_error(L"Could not retrieve MokXDel", status); + } else if (EFI_ERROR(efi_status) && efi_status != EFI_NOT_FOUND) { + console_error(L"Could not retrieve MokXDel", efi_status); } enter_mok_menu(image_handle, MokNew, MokNewSize, MokDel, MokDelSize, @@ -2508,71 +2495,67 @@ static EFI_STATUS check_mok_request(EFI_HANDLE image_handle) MokXNew, MokXNewSize, MokXDel, MokXDelSize); if (MokNew) - FreePool (MokNew); + FreePool(MokNew); if (MokDel) - FreePool (MokDel); + FreePool(MokDel); if (MokSB) - FreePool (MokSB); + FreePool(MokSB); if (MokPW) - FreePool (MokPW); + FreePool(MokPW); if (MokDB) - FreePool (MokDB); + FreePool(MokDB); if (MokXNew) - FreePool (MokXNew); + FreePool(MokXNew); if (MokXDel) - FreePool (MokXDel); + FreePool(MokXDel); - LibDeleteVariable(L"MokAuth", &shim_lock_guid); - LibDeleteVariable(L"MokDelAuth", &shim_lock_guid); - LibDeleteVariable(L"MokXAuth", &shim_lock_guid); - LibDeleteVariable(L"MokXDelAuth", &shim_lock_guid); + LibDeleteVariable(L"MokAuth", &SHIM_LOCK_GUID); + LibDeleteVariable(L"MokDelAuth", &SHIM_LOCK_GUID); + LibDeleteVariable(L"MokXAuth", &SHIM_LOCK_GUID); + LibDeleteVariable(L"MokXDelAuth", &SHIM_LOCK_GUID); return EFI_SUCCESS; } -static EFI_STATUS setup_rand (void) +static EFI_STATUS setup_rand(void) { EFI_TIME time; EFI_STATUS efi_status; UINT64 seed; BOOLEAN status; - efi_status = uefi_call_wrapper(RT->GetTime, 2, &time, NULL); - - if (efi_status != EFI_SUCCESS) + efi_status = gRT->GetTime(&time, NULL); + if (EFI_ERROR(efi_status)) return efi_status; - seed = ((UINT64)time.Year << 48) | ((UINT64)time.Month << 40) | - ((UINT64)time.Day << 32) | ((UINT64)time.Hour << 24) | - ((UINT64)time.Minute << 16) | ((UINT64)time.Second << 8) | - ((UINT64)time.Daylight); - - status = RandomSeed((UINT8 *)&seed, sizeof(seed)); + seed = ((UINT64) time.Year << 48) | ((UINT64) time.Month << 40) | + ((UINT64) time.Day << 32) | ((UINT64) time.Hour << 24) | + ((UINT64) time.Minute << 16) | ((UINT64) time.Second << 8) | + ((UINT64) time.Daylight); + status = RandomSeed((UINT8 *) & seed, sizeof(seed)); if (!status) return EFI_ABORTED; return EFI_SUCCESS; } -EFI_STATUS efi_main (EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *systab) +EFI_STATUS efi_main(EFI_HANDLE image_handle, EFI_SYSTEM_TABLE * systab) { EFI_STATUS efi_status; InitializeLib(image_handle, systab); - setup_console(1); - setup_rand(); efi_status = check_mok_request(image_handle); - setup_console(0); + console_fini(); return efi_status; } diff --git a/PasswordCrypt.c b/PasswordCrypt.c index 2494549..2eb971d 100644 --- a/PasswordCrypt.c +++ b/PasswordCrypt.c @@ -3,8 +3,8 @@ #include #include #include -#include "PasswordCrypt.h" -#include "crypt_blowfish.h" + +#include "shim.h" #define TRAD_DES_HASH_SIZE 13 /* (64/6+1) + (12/6) */ #define BSDI_DES_HASH_SIZE 20 /* (64/6+1) + (24/6) + 4 + 1 */ @@ -286,7 +286,7 @@ static EFI_STATUS blowfish_crypt (const char *key, const char *salt, UINT8 *hash EFI_STATUS password_crypt (const char *password, UINT32 pw_length, const PASSWORD_CRYPT *pw_crypt, UINT8 *hash) { - EFI_STATUS status; + EFI_STATUS efi_status; if (!pw_crypt) return EFI_INVALID_PARAMETER; @@ -294,32 +294,36 @@ EFI_STATUS password_crypt (const char *password, UINT32 pw_length, switch (pw_crypt->method) { case TRADITIONAL_DES: case EXTEND_BSDI_DES: - status = EFI_UNSUPPORTED; + efi_status = EFI_UNSUPPORTED; break; case MD5_BASED: - status = md5_crypt (password, pw_length, (char *)pw_crypt->salt, - pw_crypt->salt_size, hash); + efi_status = md5_crypt (password, pw_length, + (char *)pw_crypt->salt, + pw_crypt->salt_size, hash); break; case SHA256_BASED: - status = sha256_crypt(password, pw_length, (char *)pw_crypt->salt, - pw_crypt->salt_size, pw_crypt->iter_count, - hash); + efi_status = sha256_crypt(password, pw_length, + (char *)pw_crypt->salt, + pw_crypt->salt_size, + pw_crypt->iter_count, hash); break; case SHA512_BASED: - status = sha512_crypt(password, pw_length, (char *)pw_crypt->salt, - pw_crypt->salt_size, pw_crypt->iter_count, - hash); + efi_status = sha512_crypt(password, pw_length, + (char *)pw_crypt->salt, + pw_crypt->salt_size, + pw_crypt->iter_count, hash); break; case BLOWFISH_BASED: if (pw_crypt->salt_size != (7 + 22 + 1)) { - status = EFI_INVALID_PARAMETER; + efi_status = EFI_INVALID_PARAMETER; break; } - status = blowfish_crypt(password, (char *)pw_crypt->salt, hash); + efi_status = blowfish_crypt(password, (char *)pw_crypt->salt, + hash); break; default: return EFI_INVALID_PARAMETER; } - return status; + return efi_status; } diff --git a/README b/README index ec9403a..0703049 100644 --- a/README +++ b/README @@ -9,8 +9,8 @@ will relocate and execute the binary. shim will also install a protocol which permits the second-stage bootloader to perform similar binary validation. This protocol has a GUID as described in the shim.h header file and provides a single entry point. On 64-bit systems -this entry point expects to be called with SysV ABI rather than MSABI, and -so calls to it should not be wrapped. +this entry point expects to be called with SysV ABI rather than MSABI, so calls +to it should not be wrapped. On systems with a TPM chip enabled and supported by the system firmware, shim will extend various PCRs with the digests of the targets it is diff --git a/README.tpm b/README.tpm index 261bcd0..b7314f1 100644 --- a/README.tpm +++ b/README.tpm @@ -3,6 +3,8 @@ The following PCRs are extended by shim: PCR4: - the Authenticode hash of the binary being loaded will be extended into PCR4 before SB verification. +- the hash of any binary for which Verify is called through the shim_lock + protocol PCR7: - Any certificate in one of our certificate databases that matches a binary diff --git a/TODO b/TODO index c86c94d..a2cad71 100644 --- a/TODO +++ b/TODO @@ -1,14 +1,31 @@ - Versioned protocol: - Make shim and the bootloaders using it express how enlightened they - are to one another, so we can stop earlier without tricks like the one - above - - Make a LoadImage/CheckImage/StartImage based protocol + are to one another, so we can stop earlier without tricks + - Make EFI_LOADED_IMAGE_2 protocol and a LOAD_IMAGE protocol with + LoadImage/CheckImage/StartImage. +- Implement EFI_CERT_X509_SHA{256,384,512} revocation checks + - It doesn't necessarily have to include timestamp checking support +- Make the openssl code supply the Pkcs7Verify() API, and use the system + one (instead) if it is available. + - And make building it optional +- Get meb30's multiple-certs patch merged - Hashing of option roms: - hash option roms and add them to MokListRT - probably belongs in MokManager + - And some PCR? - Ability to specify second stage as a device path - including vendor path that means "parent of this image's path" - including vendor path that means "this image" - including path that's like Fv() to embed images. +- Make all build options be able to be set in 'git config --local shim.OPTION' + - Make the build dump those to stdout as well +- make debuginfo paths configurable +- make arch dependent names configurable +- Make it easier to avoid CryptPem +- Make an easy strip+implant tool for our embedded cert lists +- Post process full path names out of __FILE__ / __BASE_FILE__ entries in + the string table :/ +- Make build.log an artifact of building. +- KEK for Mok. (koike expressed an interest in working on this.) # vim:filetype=mail:tw=74 diff --git a/commit b/commit deleted file mode 100644 index fc0d353..0000000 --- a/commit +++ /dev/null @@ -1 +0,0 @@ -5e827007b3d95c4ce999422462248f5e7d3f270f \ No newline at end of file diff --git a/crypt_blowfish.c b/crypt_blowfish.c index 366a81a..54fc514 100644 --- a/crypt_blowfish.c +++ b/crypt_blowfish.c @@ -47,7 +47,7 @@ #include /* Just to make sure the prototypes match the actual definitions */ -#include "crypt_blowfish.h" +#include "shim.h" typedef unsigned int BF_word; typedef signed int BF_word_signed; diff --git a/errlog.c b/errlog.c index fd78933..18be482 100644 --- a/errlog.c +++ b/errlog.c @@ -7,10 +7,6 @@ #include "shim.h" -#ifdef LogError -#undef LogError -#endif - static CHAR16 **errs = NULL; static UINTN nerrs = 0; @@ -51,16 +47,16 @@ VLogError(const char *file, int line, const char *func, CHAR16 *fmt, va_list arg } EFI_STATUS -LogError(const char *file, int line, const char *func, CHAR16 *fmt, ...) +LogError_(const char *file, int line, const char *func, CHAR16 *fmt, ...) { va_list args; - EFI_STATUS status; + EFI_STATUS efi_status; va_start(args, fmt); - status = VLogError(file, line, func, fmt, args); + efi_status = VLogError(file, line, func, fmt, args); va_end(args); - return status; + return efi_status; } VOID @@ -72,7 +68,7 @@ PrintErrors(VOID) return; for (i = 0; i < nerrs; i++) - Print(L"%s", errs[i]); + console_print(L"%s", errs[i]); } VOID diff --git a/fallback.c b/fallback.c index 46894af..c3f5583 100644 --- a/fallback.c +++ b/fallback.c @@ -10,18 +10,13 @@ #include #include -#include "ucs2.h" -#include "variables.h" -#include "tpm.h" +#include "shim.h" EFI_LOADED_IMAGE *this_image = NULL; -EFI_GUID SHIM_LOCK_GUID = { 0x605dab50, 0xe046, 0x4300, {0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23} }; - int get_fallback_verbose(void) { - EFI_GUID guid = SHIM_LOCK_GUID; UINT8 *data = NULL; UINTN dataSize = 0; EFI_STATUS efi_status; @@ -32,20 +27,22 @@ get_fallback_verbose(void) return state; efi_status = get_variable(L"FALLBACK_VERBOSE", - &data, &dataSize, guid); + &data, &dataSize, SHIM_LOCK_GUID); if (EFI_ERROR(efi_status)) { state = 0; return state; } + state = 0; for (i = 0; i < dataSize; i++) { if (data[i]) { state = 1; - return state; + break; } } - state = 0; + if (data) + FreePool(data); return state; } @@ -53,7 +50,7 @@ get_fallback_verbose(void) ({ \ UINTN ret_ = 0; \ if (get_fallback_verbose()) \ - ret_ = Print((fmt), ##__VA_ARGS__); \ + ret_ = console_print((fmt), ##__VA_ARGS__); \ ret_; \ }) @@ -61,8 +58,8 @@ get_fallback_verbose(void) ({ UINTN line_ = __LINE__; \ UINTN ret_ = 0; \ if (get_fallback_verbose()) { \ - Print(L"%a:%d: ", __func__, line_); \ - ret_ = Print((fmt), ##__VA_ARGS__); \ + console_print(L"%a:%d: ", __func__, line_); \ + ret_ = console_print((fmt), ##__VA_ARGS__); \ } \ ret_; \ }) @@ -100,31 +97,32 @@ FindSubDevicePath(EFI_DEVICE_PATH *In, UINT8 Type, UINT8 SubType, static EFI_STATUS get_file_size(EFI_FILE_HANDLE fh, UINTN *retsize) { - EFI_STATUS rc; + EFI_STATUS efi_status; void *buffer = NULL; UINTN bs = 0; - EFI_GUID finfo = EFI_FILE_INFO_ID; /* The API here is "Call it once with bs=0, it fills in bs, * then allocate a buffer and ask again to get it filled. */ - rc = uefi_call_wrapper(fh->GetInfo, 4, fh, &finfo, &bs, NULL); - if (rc == EFI_BUFFER_TOO_SMALL) { - buffer = AllocateZeroPool(bs); - if (!buffer) { - Print(L"Could not allocate memory\n"); - return EFI_OUT_OF_RESOURCES; - } - rc = uefi_call_wrapper(fh->GetInfo, 4, fh, &finfo, - &bs, buffer); + efi_status = fh->GetInfo(fh, &EFI_FILE_INFO_GUID, &bs, NULL); + if (EFI_ERROR(efi_status) && efi_status != EFI_BUFFER_TOO_SMALL) + return efi_status; + if (bs == 0) + return EFI_SUCCESS; + + buffer = AllocateZeroPool(bs); + if (!buffer) { + console_print(L"Could not allocate memory\n"); + return EFI_OUT_OF_RESOURCES; } + efi_status = fh->GetInfo(fh, &EFI_FILE_INFO_GUID, &bs, buffer); /* This checks *either* the error from the first GetInfo, if it isn't - * the EFI_BUFFER_TOO_SMALL we're expecting, or the second GetInfo call - * in *any* case. */ - if (EFI_ERROR(rc)) { - Print(L"Could not get file info: %d\n", rc); + * the EFI_BUFFER_TOO_SMALL we're expecting, or the second GetInfo + * call in *any* case. */ + if (EFI_ERROR(efi_status)) { + console_print(L"Could not get file info: %r\n", efi_status); if (buffer) FreePool(buffer); - return rc; + return efi_status; } EFI_FILE_INFO *fi = buffer; *retsize = fi->FileSize; @@ -136,38 +134,46 @@ EFI_STATUS read_file(EFI_FILE_HANDLE fh, CHAR16 *fullpath, CHAR16 **buffer, UINT64 *bs) { EFI_FILE_HANDLE fh2; - EFI_STATUS rc = uefi_call_wrapper(fh->Open, 5, fh, &fh2, fullpath, - EFI_FILE_READ_ONLY, 0); - if (EFI_ERROR(rc)) { - Print(L"Couldn't open \"%s\": %d\n", fullpath, rc); - return rc; + EFI_STATUS efi_status; + + efi_status = fh->Open(fh, &fh2, fullpath, EFI_FILE_READ_ONLY, 0); + if (EFI_ERROR(efi_status)) { + console_print(L"Couldn't open \"%s\": %r\n", fullpath, efi_status); + return efi_status; } UINTN len = 0; CHAR16 *b = NULL; - rc = get_file_size(fh2, &len); - if (EFI_ERROR(rc)) { - uefi_call_wrapper(fh2->Close, 1, fh2); - return rc; + efi_status = get_file_size(fh2, &len); + if (EFI_ERROR(efi_status)) { + console_print(L"Could not get file size for \"%s\": %r\n", + fullpath, efi_status); + fh2->Close(fh2); + return efi_status; + } + + if (len > 1024 * PAGE_SIZE) { + fh2->Close(fh2); + return EFI_BAD_BUFFER_SIZE; } b = AllocateZeroPool(len + 2); if (!buffer) { - Print(L"Could not allocate memory\n"); - uefi_call_wrapper(fh2->Close, 1, fh2); + console_print(L"Could not allocate memory\n"); + fh2->Close(fh2); return EFI_OUT_OF_RESOURCES; } - rc = uefi_call_wrapper(fh->Read, 3, fh, &len, b); - if (EFI_ERROR(rc)) { + efi_status = fh->Read(fh, &len, b); + if (EFI_ERROR(efi_status)) { FreePool(buffer); - uefi_call_wrapper(fh2->Close, 1, fh2); - Print(L"Could not read file: %d\n", rc); - return rc; + fh2->Close(fh2); + console_print(L"Could not read file: %r\n", efi_status); + return efi_status; } *buffer = b; *bs = len; - uefi_call_wrapper(fh2->Close, 1, fh2); + fh2->Close(fh2); return EFI_SUCCESS; } @@ -182,7 +188,7 @@ make_full_path(CHAR16 *dirname, CHAR16 *filename, CHAR16 **out, UINT64 *outlen) CHAR16 *fullpath = AllocateZeroPool(len*sizeof(CHAR16)); if (!fullpath) { - Print(L"Could not allocate memory\n"); + console_print(L"Could not allocate memory\n"); return EFI_OUT_OF_RESOURCES; } @@ -210,8 +216,7 @@ add_boot_option(EFI_DEVICE_PATH *hddp, EFI_DEVICE_PATH *fulldp, static int i = 0; CHAR16 varname[] = L"Boot0000"; CHAR16 hexmap[] = L"0123456789ABCDEF"; - EFI_GUID global = EFI_GLOBAL_VARIABLE; - EFI_STATUS rc; + EFI_STATUS efi_status; for(; i <= 0xffff; i++) { varname[4] = hexmap[(i & 0xf000) >> 12]; @@ -219,7 +224,7 @@ add_boot_option(EFI_DEVICE_PATH *hddp, EFI_DEVICE_PATH *fulldp, varname[6] = hexmap[(i & 0x00f0) >> 4]; varname[7] = hexmap[(i & 0x000f) >> 0]; - void *var = LibGetVariable(varname, &global); + void *var = LibGetVariable(varname, &GV_GUID); if (!var) { int size = sizeof(UINT32) + sizeof (UINT16) + StrLen(label)*2 + 2 + DevicePathSize(hddp) + @@ -237,9 +242,9 @@ add_boot_option(EFI_DEVICE_PATH *hddp, EFI_DEVICE_PATH *fulldp, cursor += DevicePathSize(hddp); StrCpy((CHAR16 *)cursor, arguments); - Print(L"Creating boot entry \"%s\" with label \"%s\" " - L"for file \"%s\"\n", - varname, label, filename); + console_print(L"Creating boot entry \"%s\" with label \"%s\" " + L"for file \"%s\"\n", + varname, label, filename); if (!first_new_option) { first_new_option = DuplicateDevicePath(fulldp); @@ -247,17 +252,18 @@ add_boot_option(EFI_DEVICE_PATH *hddp, EFI_DEVICE_PATH *fulldp, first_new_option_size = StrLen(arguments) * sizeof (CHAR16); } - rc = uefi_call_wrapper(RT->SetVariable, 5, varname, - &global, EFI_VARIABLE_NON_VOLATILE | - EFI_VARIABLE_BOOTSERVICE_ACCESS | - EFI_VARIABLE_RUNTIME_ACCESS, - size, data); + efi_status = gRT->SetVariable(varname, &GV_GUID, + EFI_VARIABLE_NON_VOLATILE | + EFI_VARIABLE_BOOTSERVICE_ACCESS | + EFI_VARIABLE_RUNTIME_ACCESS, + size, data); FreePool(data); - if (EFI_ERROR(rc)) { - Print(L"Could not create variable: %d\n", rc); - return rc; + if (EFI_ERROR(efi_status)) { + console_print(L"Could not create variable: %r\n", + efi_status); + return efi_status; } CHAR16 *newbootorder = AllocateZeroPool(sizeof (CHAR16) @@ -275,10 +281,11 @@ add_boot_option(EFI_DEVICE_PATH *hddp, EFI_DEVICE_PATH *fulldp, bootorder = newbootorder; nbootorder += 1; #ifdef DEBUG_FALLBACK - Print(L"nbootorder: %d\nBootOrder: ", nbootorder); + console_print(L"nbootorder: %d\nBootOrder: ", + nbootorder); for (j = 0 ; j < nbootorder ; j++) - Print(L"%04x ", bootorder[j]); - Print(L"\n"); + console_print(L"%04x ", bootorder[j]); + console_print(L"\n"); #endif return EFI_SUCCESS; @@ -412,8 +419,7 @@ find_boot_option(EFI_DEVICE_PATH *dp, EFI_DEVICE_PATH *fulldp, int i = 0; CHAR16 varname[] = L"Boot0000"; CHAR16 hexmap[] = L"0123456789ABCDEF"; - EFI_GUID global = EFI_GLOBAL_VARIABLE; - EFI_STATUS rc; + EFI_STATUS efi_status; UINTN max_candidate_size = calc_masked_boot_option_size(size); CHAR8 *candidate = AllocateZeroPool(max_candidate_size); @@ -429,9 +435,9 @@ find_boot_option(EFI_DEVICE_PATH *dp, EFI_DEVICE_PATH *fulldp, varname[7] = hexmap[(bootorder[i] & 0x000f) >> 0]; UINTN candidate_size = max_candidate_size; - rc = uefi_call_wrapper(RT->GetVariable, 5, varname, &global, - NULL, &candidate_size, candidate); - if (EFI_ERROR(rc)) + efi_status = gRT->GetVariable(varname, &GV_GUID, NULL, + &candidate_size, candidate); + if (EFI_ERROR(efi_status)) continue; if (candidate_size != size) { @@ -466,9 +472,8 @@ set_boot_order(void) { CHAR16 *oldbootorder; UINTN size; - EFI_GUID global = EFI_GLOBAL_VARIABLE; - oldbootorder = LibGetVariableAndSize(L"BootOrder", &global, &size); + oldbootorder = LibGetVariableAndSize(L"BootOrder", &GV_GUID, &size); if (oldbootorder) { nbootorder = size / sizeof (CHAR16); bootorder = oldbootorder; @@ -482,9 +487,8 @@ update_boot_order(void) { UINTN size; UINTN len = 0; - EFI_GUID global = EFI_GLOBAL_VARIABLE; CHAR16 *newbootorder = NULL; - EFI_STATUS rc; + EFI_STATUS efi_status; size = nbootorder * sizeof(CHAR16); newbootorder = AllocateZeroPool(size); @@ -496,19 +500,18 @@ update_boot_order(void) UINTN j; for (j = 0 ; j < size / sizeof (CHAR16); j++) VerbosePrintUnprefixed(L"%04x ", newbootorder[j]); - Print(L"\n"); - rc = uefi_call_wrapper(RT->GetVariable, 5, L"BootOrder", &global, - NULL, &len, NULL); - if (rc == EFI_BUFFER_TOO_SMALL) - LibDeleteVariable(L"BootOrder", &global); + console_print(L"\n"); + efi_status = gRT->GetVariable(L"BootOrder", &GV_GUID, NULL, &len, NULL); + if (efi_status == EFI_BUFFER_TOO_SMALL) + LibDeleteVariable(L"BootOrder", &GV_GUID); - rc = uefi_call_wrapper(RT->SetVariable, 5, L"BootOrder", &global, - EFI_VARIABLE_NON_VOLATILE | - EFI_VARIABLE_BOOTSERVICE_ACCESS | - EFI_VARIABLE_RUNTIME_ACCESS, - size, newbootorder); + efi_status = gRT->SetVariable(L"BootOrder", &GV_GUID, + EFI_VARIABLE_NON_VOLATILE | + EFI_VARIABLE_BOOTSERVICE_ACCESS | + EFI_VARIABLE_RUNTIME_ACCESS, + size, newbootorder); FreePool(newbootorder); - return rc; + return efi_status; } EFI_STATUS @@ -516,11 +519,11 @@ add_to_boot_list(CHAR16 *dirname, CHAR16 *filename, CHAR16 *label, CHAR16 *argum { CHAR16 *fullpath = NULL; UINT64 pathlen = 0; - EFI_STATUS rc = EFI_SUCCESS; + EFI_STATUS efi_status; - rc = make_full_path(dirname, filename, &fullpath, &pathlen); - if (EFI_ERROR(rc)) - return rc; + efi_status = make_full_path(dirname, filename, &fullpath, &pathlen); + if (EFI_ERROR(efi_status)) + return efi_status; EFI_DEVICE_PATH *full_device_path = NULL; EFI_DEVICE_PATH *dp = NULL; @@ -528,20 +531,21 @@ add_to_boot_list(CHAR16 *dirname, CHAR16 *filename, CHAR16 *label, CHAR16 *argum full_device_path = FileDevicePath(this_image->DeviceHandle, fullpath); if (!full_device_path) { - rc = EFI_OUT_OF_RESOURCES; + efi_status = EFI_OUT_OF_RESOURCES; goto err; } dps = DevicePathToStr(full_device_path); VerbosePrint(L"file DP: %s\n", dps); FreePool(dps); - rc = FindSubDevicePath(full_device_path, - MEDIA_DEVICE_PATH, MEDIA_HARDDRIVE_DP, &dp); - if (EFI_ERROR(rc)) { - if (rc == EFI_NOT_FOUND) { + efi_status = FindSubDevicePath(full_device_path, + MEDIA_DEVICE_PATH, MEDIA_HARDDRIVE_DP, + &dp); + if (EFI_ERROR(efi_status)) { + if (efi_status == EFI_NOT_FOUND) { dp = full_device_path; } else { - rc = EFI_OUT_OF_RESOURCES; + efi_status = EFI_OUT_OF_RESOURCES; goto err; } } @@ -566,9 +570,11 @@ add_to_boot_list(CHAR16 *dirname, CHAR16 *filename, CHAR16 *label, CHAR16 *argum } UINT16 option; - rc = find_boot_option(dp, full_device_path, fullpath, label, arguments, &option); - if (EFI_ERROR(rc)) { - add_boot_option(dp, full_device_path, fullpath, label, arguments); + efi_status = find_boot_option(dp, full_device_path, fullpath, label, + arguments, &option); + if (EFI_ERROR(efi_status)) { + add_boot_option(dp, full_device_path, fullpath, label, + arguments); } else if (option != 0) { CHAR16 *newbootorder; newbootorder = AllocateZeroPool(sizeof (CHAR16) * nbootorder); @@ -590,7 +596,7 @@ err: FreePool(dp); if (fullpath) FreePool(fullpath); - return rc; + return efi_status; } EFI_STATUS @@ -628,21 +634,22 @@ try_boot_csv(EFI_FILE_HANDLE fh, CHAR16 *dirname, CHAR16 *filename) { CHAR16 *fullpath = NULL; UINT64 pathlen = 0; - EFI_STATUS rc; + EFI_STATUS efi_status; - rc = make_full_path(dirname, filename, &fullpath, &pathlen); - if (EFI_ERROR(rc)) - return rc; + efi_status = make_full_path(dirname, filename, &fullpath, &pathlen); + if (EFI_ERROR(efi_status)) + return efi_status; VerbosePrint(L"Found file \"%s\"\n", fullpath); CHAR16 *buffer; UINT64 bs; - rc = read_file(fh, fullpath, &buffer, &bs); - if (EFI_ERROR(rc)) { - Print(L"Could not read file \"%s\": %d\n", fullpath, rc); + efi_status = read_file(fh, fullpath, &buffer, &bs); + if (EFI_ERROR(efi_status)) { + console_print(L"Could not read file \"%s\": %r\n", + fullpath, efi_status); FreePool(fullpath); - return rc; + return efi_status; } FreePool(fullpath); @@ -685,31 +692,37 @@ try_boot_csv(EFI_FILE_HANDLE fh, CHAR16 *dirname, CHAR16 *filename) EFI_STATUS find_boot_csv(EFI_FILE_HANDLE fh, CHAR16 *dirname) { - EFI_STATUS rc; + EFI_STATUS efi_status; void *buffer = NULL; UINTN bs = 0; - EFI_GUID finfo = EFI_FILE_INFO_ID; /* The API here is "Call it once with bs=0, it fills in bs, * then allocate a buffer and ask again to get it filled. */ - rc = uefi_call_wrapper(fh->GetInfo, 4, fh, &finfo, &bs, NULL); - if (rc == EFI_BUFFER_TOO_SMALL) { - buffer = AllocateZeroPool(bs); - if (!buffer) { - Print(L"Could not allocate memory\n"); - return EFI_OUT_OF_RESOURCES; - } - rc = uefi_call_wrapper(fh->GetInfo, 4, fh, &finfo, - &bs, buffer); + efi_status = fh->GetInfo(fh, &EFI_FILE_INFO_GUID, &bs, NULL); + if (EFI_ERROR(efi_status) && efi_status != EFI_BUFFER_TOO_SMALL) { + console_print(L"Could not get directory info for \\EFI\\%s\\: %r\n", + dirname, efi_status); + return efi_status; } + if (bs == 0) + return EFI_SUCCESS; + + buffer = AllocateZeroPool(bs); + if (!buffer) { + console_print(L"Could not allocate memory\n"); + return EFI_OUT_OF_RESOURCES; + } + + efi_status = fh->GetInfo(fh, &EFI_FILE_INFO_GUID, &bs, buffer); /* This checks *either* the error from the first GetInfo, if it isn't - * the EFI_BUFFER_TOO_SMALL we're expecting, or the second GetInfo call - * in *any* case. */ - if (EFI_ERROR(rc)) { - Print(L"Could not get info for \"%s\": %d\n", dirname, rc); + * the EFI_BUFFER_TOO_SMALL we're expecting, or the second GetInfo + * call in *any* case. */ + if (EFI_ERROR(efi_status)) { + console_print(L"Could not get info for \"%s\": %r\n", dirname, + efi_status); if (buffer) FreePool(buffer); - return rc; + return efi_status; } EFI_FILE_INFO *fi = buffer; @@ -725,12 +738,12 @@ find_boot_csv(EFI_FILE_HANDLE fh, CHAR16 *dirname) bs = 0; do { bs = 0; - rc = uefi_call_wrapper(fh->Read, 3, fh, &bs, NULL); - if (EFI_ERROR(rc) && rc != EFI_BUFFER_TOO_SMALL) { - Print(L"Could not read \\EFI\\%s\\: %d\n", dirname, rc); - if (buffer) - FreePool(buffer); - return rc; + efi_status = fh->Read(fh, &bs, NULL); + if (EFI_ERROR(efi_status) && + efi_status != EFI_BUFFER_TOO_SMALL) { + console_print(L"Could not read \\EFI\\%s\\: %r\n", + dirname, efi_status); + return efi_status; } /* If there's no data to read, don't try to allocate 0 bytes * and read the data... */ @@ -739,15 +752,16 @@ find_boot_csv(EFI_FILE_HANDLE fh, CHAR16 *dirname) buffer = AllocateZeroPool(bs); if (!buffer) { - Print(L"Could not allocate memory\n"); + console_print(L"Could not allocate memory\n"); return EFI_OUT_OF_RESOURCES; } - rc = uefi_call_wrapper(fh->Read, 3, fh, &bs, buffer); - if (EFI_ERROR(rc)) { - Print(L"Could not read \\EFI\\%s\\: %d\n", dirname, rc); + efi_status = fh->Read(fh, &bs, buffer); + if (EFI_ERROR(efi_status)) { + console_print(L"Could not read \\EFI\\%s\\: %r\n", + dirname, efi_status); FreePool(buffer); - return rc; + return efi_status; } if (bs == 0) @@ -766,105 +780,108 @@ find_boot_csv(EFI_FILE_HANDLE fh, CHAR16 *dirname) buffer = NULL; } while (bs != 0); - rc = EFI_SUCCESS; + efi_status = EFI_SUCCESS; if (bootarchcsv) { EFI_FILE_HANDLE fh2; - rc = uefi_call_wrapper(fh->Open, 5, fh, &fh2, - bootarchcsv, EFI_FILE_READ_ONLY, 0); - if (EFI_ERROR(rc) || fh2 == NULL) { - Print(L"Couldn't open \\EFI\\%s\\%s: %d\n", - dirname, bootarchcsv, rc); + efi_status = fh->Open(fh, &fh2, bootarchcsv, + EFI_FILE_READ_ONLY, 0); + if (EFI_ERROR(efi_status) || fh2 == NULL) { + console_print(L"Couldn't open \\EFI\\%s\\%s: %r\n", + dirname, bootarchcsv, efi_status); } else { - rc = try_boot_csv(fh2, dirname, bootarchcsv); - uefi_call_wrapper(fh2->Close, 1, fh2); + efi_status = try_boot_csv(fh2, dirname, bootarchcsv); + fh2->Close(fh2); + if (EFI_ERROR(efi_status)) + console_print(L"Could not process \\EFI\\%s\\%s: %r\n", + dirname, bootarchcsv, efi_status); } } - if ((EFI_ERROR(rc) || !bootarchcsv) && bootcsv) { + if ((EFI_ERROR(efi_status) || !bootarchcsv) && bootcsv) { EFI_FILE_HANDLE fh2; - rc = uefi_call_wrapper(fh->Open, 5, fh, &fh2, - bootcsv, EFI_FILE_READ_ONLY, 0); - if (EFI_ERROR(rc) || fh2 == NULL) { - Print(L"Couldn't open \\EFI\\%s\\%s: %d\n", - dirname, bootcsv, rc); + efi_status = fh->Open(fh, &fh2, bootcsv, + EFI_FILE_READ_ONLY, 0); + if (EFI_ERROR(efi_status) || fh2 == NULL) { + console_print(L"Couldn't open \\EFI\\%s\\%s: %r\n", + dirname, bootcsv, efi_status); } else { - rc = try_boot_csv(fh2, dirname, bootcsv); - uefi_call_wrapper(fh2->Close, 1, fh2); + efi_status = try_boot_csv(fh2, dirname, bootcsv); + fh2->Close(fh2); + if (EFI_ERROR(efi_status)) + console_print(L"Could not process \\EFI\\%s\\%s: %r\n", + dirname, bootarchcsv, efi_status); } } - rc = EFI_SUCCESS; - - return rc; + return EFI_SUCCESS; } EFI_STATUS find_boot_options(EFI_HANDLE device) { - EFI_STATUS rc = EFI_SUCCESS; - + EFI_STATUS efi_status; EFI_FILE_IO_INTERFACE *fio = NULL; - rc = uefi_call_wrapper(BS->HandleProtocol, 3, device, - &FileSystemProtocol, (void **)&fio); - if (EFI_ERROR(rc)) { - Print(L"Couldn't find file system: %d\n", rc); - return rc; + + efi_status = gBS->HandleProtocol(device, &FileSystemProtocol, + (void **) &fio); + if (EFI_ERROR(efi_status)) { + console_print(L"Couldn't find file system: %r\n", efi_status); + return efi_status; } /* EFI_FILE_HANDLE is a pointer to an EFI_FILE, and I have * *no idea* what frees the memory allocated here. Hopefully * Close() does. */ EFI_FILE_HANDLE fh = NULL; - rc = uefi_call_wrapper(fio->OpenVolume, 2, fio, &fh); - if (EFI_ERROR(rc) || fh == NULL) { - Print(L"Couldn't open file system: %d\n", rc); - return rc; + efi_status = fio->OpenVolume(fio, &fh); + if (EFI_ERROR(efi_status) || fh == NULL) { + console_print(L"Couldn't open file system: %r\n", efi_status); + return efi_status; } EFI_FILE_HANDLE fh2 = NULL; - rc = uefi_call_wrapper(fh->Open, 5, fh, &fh2, L"EFI", - EFI_FILE_READ_ONLY, 0); - if (EFI_ERROR(rc) || fh2 == NULL) { - Print(L"Couldn't open EFI: %d\n", rc); - uefi_call_wrapper(fh->Close, 1, fh); - return rc; + efi_status = fh->Open(fh, &fh2, L"EFI", EFI_FILE_READ_ONLY, 0); + if (EFI_ERROR(efi_status) || fh2 == NULL) { + console_print(L"Couldn't open EFI: %r\n", efi_status); + fh->Close(fh); + return efi_status; } - rc = uefi_call_wrapper(fh2->SetPosition, 2, fh2, 0); - if (EFI_ERROR(rc)) { - Print(L"Couldn't set file position: %d\n", rc); - uefi_call_wrapper(fh2->Close, 1, fh2); - uefi_call_wrapper(fh->Close, 1, fh); - return rc; + efi_status = fh2->SetPosition(fh2, 0); + if (EFI_ERROR(efi_status)) { + console_print(L"Couldn't set file position: %r\n", efi_status); + fh2->Close(fh2); + fh->Close(fh); + return efi_status; } void *buffer; UINTN bs; do { bs = 0; - rc = uefi_call_wrapper(fh2->Read, 3, fh2, &bs, NULL); - if (rc == EFI_BUFFER_TOO_SMALL || - (rc == EFI_SUCCESS && bs != 0)) { - buffer = AllocateZeroPool(bs); - if (!buffer) { - Print(L"Could not allocate memory\n"); - /* sure, this might work, why not? */ - uefi_call_wrapper(fh2->Close, 1, fh2); - uefi_call_wrapper(fh->Close, 1, fh); - return EFI_OUT_OF_RESOURCES; - } - - rc = uefi_call_wrapper(fh2->Read, 3, fh2, &bs, buffer); + efi_status = fh2->Read(fh2, &bs, NULL); + if (EFI_ERROR(efi_status) && efi_status != EFI_BUFFER_TOO_SMALL) { + console_print(L"Could not read \\EFI\\: %r\n", efi_status); + return efi_status; } if (bs == 0) break; - if (EFI_ERROR(rc)) { - Print(L"Could not read \\EFI\\: %d\n", rc); + buffer = AllocateZeroPool(bs); + if (!buffer) { + console_print(L"Could not allocate memory\n"); + /* sure, this might work, why not? */ + fh2->Close(fh2); + fh->Close(fh); + return EFI_OUT_OF_RESOURCES; + } + + efi_status = fh2->Read(fh2, &bs, buffer); + if (EFI_ERROR(efi_status)) { if (buffer) { FreePool(buffer); buffer = NULL; } - uefi_call_wrapper(fh2->Close, 1, fh2); - uefi_call_wrapper(fh->Close, 1, fh); - return rc; + fh2->Close(fh2); + fh->Close(fh); + return efi_status; } EFI_FILE_INFO *fi = buffer; @@ -883,74 +900,77 @@ find_boot_options(EFI_HANDLE device) VerbosePrint(L"Found directory named \"%s\"\n", fi->FileName); EFI_FILE_HANDLE fh3; - rc = uefi_call_wrapper(fh->Open, 5, fh2, &fh3, fi->FileName, - EFI_FILE_READ_ONLY, 0); - if (EFI_ERROR(rc)) { - Print(L"%d Couldn't open %s: %d\n", __LINE__, fi->FileName, rc); + efi_status = fh2->Open(fh2, &fh3, fi->FileName, + EFI_FILE_READ_ONLY, 0); + if (EFI_ERROR(efi_status)) { + console_print(L"%d Couldn't open %s: %r\n", __LINE__, + fi->FileName, efi_status); FreePool(buffer); buffer = NULL; continue; } - rc = find_boot_csv(fh3, fi->FileName); + efi_status = find_boot_csv(fh3, fi->FileName); + fh3->Close(fh3); FreePool(buffer); buffer = NULL; - if (rc == EFI_OUT_OF_RESOURCES) + if (efi_status == EFI_OUT_OF_RESOURCES) break; } while (1); - if (rc == EFI_SUCCESS && nbootorder > 0) - rc = update_boot_order(); + if (!EFI_ERROR(efi_status) && nbootorder > 0) + efi_status = update_boot_order(); - uefi_call_wrapper(fh2->Close, 1, fh2); - uefi_call_wrapper(fh->Close, 1, fh); - return rc; + fh2->Close(fh2); + fh->Close(fh); + return efi_status; } static EFI_STATUS try_start_first_option(EFI_HANDLE parent_image_handle) { - EFI_STATUS rc; + EFI_STATUS efi_status; EFI_HANDLE image_handle; if (!first_new_option) { return EFI_SUCCESS; } - rc = uefi_call_wrapper(BS->LoadImage, 6, 0, parent_image_handle, - first_new_option, NULL, 0, - &image_handle); - if (EFI_ERROR(rc)) { + efi_status = gBS->LoadImage(0, parent_image_handle, first_new_option, + NULL, 0, &image_handle); + if (EFI_ERROR(efi_status)) { CHAR16 *dps = DevicePathToStr(first_new_option); UINTN s = DevicePathSize(first_new_option); unsigned int i; UINT8 *dpv = (void *)first_new_option; - Print(L"LoadImage failed: %d\nDevice path: \"%s\"\n", rc, dps); + console_print(L"LoadImage failed: %r\nDevice path: \"%s\"\n", + efi_status, dps); for (i = 0; i < s; i++) { if (i > 0 && i % 16 == 0) - Print(L"\n"); - Print(L"%02x ", dpv[i]); + console_print(L"\n"); + console_print(L"%02x ", dpv[i]); } - Print(L"\n"); + console_print(L"\n"); - uefi_call_wrapper(BS->Stall, 1, 500000000); - return rc; + msleep(500000000); + return efi_status; } EFI_LOADED_IMAGE *image; - rc = uefi_call_wrapper(BS->HandleProtocol, 3, image_handle, &LoadedImageProtocol, (void *)&image); - if (!EFI_ERROR(rc)) { + efi_status = gBS->HandleProtocol(image_handle, &LoadedImageProtocol, + (void *) &image); + if (!EFI_ERROR(efi_status)) { image->LoadOptions = first_new_option_args; image->LoadOptionsSize = first_new_option_size; } - rc = uefi_call_wrapper(BS->StartImage, 3, image_handle, NULL, NULL); - if (EFI_ERROR(rc)) { - Print(L"StartImage failed: %d\n", rc); - uefi_call_wrapper(BS->Stall, 1, 500000000); + efi_status = gBS->StartImage(image_handle, NULL, NULL); + if (EFI_ERROR(efi_status)) { + console_print(L"StartImage failed: %r\n", efi_status); + msleep(500000000); } - return rc; + return efi_status; } extern EFI_STATUS @@ -960,31 +980,33 @@ static void __attribute__((__optimize__("0"))) debug_hook(void) { - EFI_GUID guid = SHIM_LOCK_GUID; UINT8 *data = NULL; UINTN dataSize = 0; EFI_STATUS efi_status; volatile register int x = 0; extern char _etext, _edata; - efi_status = get_variable(L"SHIM_DEBUG", &data, &dataSize, guid); + efi_status = get_variable(L"SHIM_DEBUG", &data, &dataSize, + SHIM_LOCK_GUID); if (EFI_ERROR(efi_status)) { return; } + if (data) + FreePool(data); if (x) return; x = 1; - Print(L"add-symbol-file "DEBUGDIR - L"fb" EFI_ARCH L".efi.debug %p -s .data %p\n", &_etext, - &_edata); + console_print(L"add-symbol-file "DEBUGDIR + L"fb" EFI_ARCH L".efi.debug %p -s .data %p\n", + &_etext, &_edata); } EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *systab) { - EFI_STATUS rc; + EFI_STATUS efi_status; InitializeLib(image, systab); @@ -993,39 +1015,41 @@ efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *systab) */ debug_hook(); - rc = uefi_call_wrapper(BS->HandleProtocol, 3, image, &LoadedImageProtocol, (void *)&this_image); - if (EFI_ERROR(rc)) { - Print(L"Error: could not find loaded image: %d\n", rc); - return rc; + efi_status = gBS->HandleProtocol(image, &LoadedImageProtocol, + (void *) &this_image); + if (EFI_ERROR(efi_status)) { + console_print(L"Error: could not find loaded image: %r\n", + efi_status); + return efi_status; } - Print(L"System BootOrder not found. Initializing defaults.\n"); + console_print(L"System BootOrder not found. Initializing defaults.\n"); set_boot_order(); - rc = find_boot_options(this_image->DeviceHandle); - if (EFI_ERROR(rc)) { - Print(L"Error: could not find boot options: %d\n", rc); - return rc; + efi_status = find_boot_options(this_image->DeviceHandle); + if (EFI_ERROR(efi_status)) { + console_print(L"Error: could not find boot options: %r\n", + efi_status); + return efi_status; } - rc = fallback_should_prefer_reset(); - if (EFI_ERROR(rc)) { + efi_status = fallback_should_prefer_reset(); + if (EFI_ERROR(efi_status)) { VerbosePrint(L"tpm not present, starting the first image\n"); try_start_first_option(image); } else { VerbosePrint(L"tpm present, resetting system\n"); } - Print(L"Reset System\n"); + console_print(L"Reset System\n"); if (get_fallback_verbose()) { - Print(L"Verbose enabled, sleeping for half a second\n"); - uefi_call_wrapper(BS->Stall, 1, 500000); + console_print(L"Verbose enabled, sleeping for half a second\n"); + msleep(500000); } - uefi_call_wrapper(RT->ResetSystem, 4, EfiResetCold, - EFI_SUCCESS, 0, NULL); + gRT->ResetSystem(EfiResetCold, EFI_SUCCESS, 0, NULL); return EFI_SUCCESS; } diff --git a/httpboot.c b/httpboot.c index e4657c1..3622e85 100644 --- a/httpboot.c +++ b/httpboot.c @@ -33,19 +33,8 @@ #include #include -#include "str.h" -#include "Http.h" -#include "Ip4Config2.h" -#include "Ip6Config.h" -extern UINT8 in_protocol; - -#define perror(fmt, ...) ({ \ - UINTN __perror_ret = 0; \ - if (!in_protocol) \ - __perror_ret = Print((fmt), ##__VA_ARGS__); \ - __perror_ret; \ - }) +#include "shim.h" static UINTN ascii_to_int (CONST CHAR8 *str) @@ -105,10 +94,11 @@ find_httpboot (EFI_HANDLE device) { EFI_DEVICE_PATH *unpacked; EFI_DEVICE_PATH *Node; - EFI_DEVICE_PATH *NextNode; MAC_ADDR_DEVICE_PATH *MacNode; URI_DEVICE_PATH *UriNode; UINTN uri_size; + BOOLEAN ip_found = FALSE; + BOOLEAN ret = FALSE; if (uri) { FreePool(uri); @@ -128,50 +118,60 @@ find_httpboot (EFI_HANDLE device) } Node = unpacked; - /* Traverse the device path to find IPv4()/Uri() or IPv6()/Uri() */ + /* Traverse the device path to find IPv4()/.../Uri() or + * IPv6()/.../Uri() */ while (!IsDevicePathEnd(Node)) { /* Save the MAC node so we can match the net card later */ if (DevicePathType(Node) == MESSAGING_DEVICE_PATH && DevicePathSubType(Node) == MSG_MAC_ADDR_DP) { MacNode = (MAC_ADDR_DEVICE_PATH *)Node; - CopyMem(&mac_addr, &MacNode->MacAddress, sizeof(EFI_MAC_ADDRESS)); - } - - if (DevicePathType(Node) == MESSAGING_DEVICE_PATH && - (DevicePathSubType(Node) == MSG_IPv4_DP || - DevicePathSubType(Node) == MSG_IPv6_DP)) { - /* Save the IP node so we can set up the connection later */ + CopyMem(&mac_addr, &MacNode->MacAddress, + sizeof(EFI_MAC_ADDRESS)); + } else if (DevicePathType(Node) == MESSAGING_DEVICE_PATH && + (DevicePathSubType(Node) == MSG_IPv4_DP || + DevicePathSubType(Node) == MSG_IPv6_DP)) { + /* Save the IP node so we can set up the connection */ + /* later */ if (DevicePathSubType(Node) == MSG_IPv6_DP) { - CopyMem(&ip6_node, Node, sizeof(IPv6_DEVICE_PATH)); + CopyMem(&ip6_node, Node, + sizeof(IPv6_DEVICE_PATH)); is_ip6 = TRUE; } else { - CopyMem(&ip4_node, Node, sizeof(IPv4_DEVICE_PATH)); + CopyMem(&ip4_node, Node, + sizeof(IPv4_DEVICE_PATH)); is_ip6 = FALSE; } - Node = NextDevicePathNode(Node); + ip_found = TRUE; + } else if (ip_found == TRUE && + (DevicePathType(Node) == MESSAGING_DEVICE_PATH && + DevicePathSubType(Node) == MSG_URI_DP)) { + EFI_DEVICE_PATH *NextNode; + + /* Check if the URI node is the last node since the */ + /* RAMDISK node could be appended, and we don't need */ + /* to download the second stage loader in that case. */ NextNode = NextDevicePathNode(Node); - if (DevicePathType(Node) == MESSAGING_DEVICE_PATH && - DevicePathSubType(Node) == MSG_URI_DP && - IsDevicePathEnd(NextNode)) { - /* Save the current URI */ - UriNode = (URI_DEVICE_PATH *)Node; - uri_size = strlena(UriNode->Uri); - uri = AllocatePool(uri_size + 1); - if (!uri) { - perror(L"Failed to allocate uri\n"); - return FALSE; - } - CopyMem(uri, UriNode->Uri, uri_size + 1); - FreePool(unpacked); - return TRUE; + if (!IsDevicePathEnd(NextNode)) + goto out; + + /* Save the current URI */ + UriNode = (URI_DEVICE_PATH *)Node; + uri_size = strlena(UriNode->Uri); + uri = AllocatePool(uri_size + 1); + if (!uri) { + perror(L"Failed to allocate uri\n"); + goto out; } + CopyMem(uri, UriNode->Uri, uri_size + 1); + ret = TRUE; + goto out; } Node = NextDevicePathNode(Node); } - +out: FreePool(unpacked); - return FALSE; + return ret; } static EFI_STATUS @@ -247,7 +247,6 @@ extract_hostname (CONST CHAR8 *url, CHAR8 **hostname) static EFI_HANDLE get_nic_handle (EFI_MAC_ADDRESS *mac) { - EFI_GUID http_binding_guid = EFI_HTTP_SERVICE_BINDING_PROTOCOL_GUID; EFI_DEVICE_PATH *unpacked = NULL; EFI_DEVICE_PATH *Node; EFI_DEVICE_PATH *temp_path = NULL; @@ -256,17 +255,14 @@ get_nic_handle (EFI_MAC_ADDRESS *mac) EFI_HANDLE *buffer; UINTN NoHandles; UINTN i; - EFI_STATUS status; + EFI_STATUS efi_status; /* Get the list of handles that support the HTTP service binding protocol */ - status = uefi_call_wrapper(BS->LocateHandleBuffer, 5, - ByProtocol, - &http_binding_guid, - NULL, - &NoHandles, - &buffer); - if (EFI_ERROR(status)) + efi_status = gBS->LocateHandleBuffer(ByProtocol, + &EFI_HTTP_BINDING_GUID, + NULL, &NoHandles, &buffer); + if (EFI_ERROR(efi_status)) return NULL; for (i = 0; i < NoHandles; i++) { @@ -303,7 +299,7 @@ out: } static BOOLEAN -is_unspecified_addr (EFI_IPv6_ADDRESS ip6) +is_unspecified_ip6addr (EFI_IPv6_ADDRESS ip6) { UINT8 i; @@ -315,82 +311,117 @@ is_unspecified_addr (EFI_IPv6_ADDRESS ip6) return TRUE; } +static inline void +print_ip6_addr(EFI_IPv6_ADDRESS ip6addr) +{ + perror(L"%x:%x:%x:%x:%x:%x:%x:%x\n", + ip6addr.Addr[0] << 8 | ip6addr.Addr[1], + ip6addr.Addr[2] << 8 | ip6addr.Addr[3], + ip6addr.Addr[4] << 8 | ip6addr.Addr[5], + ip6addr.Addr[6] << 8 | ip6addr.Addr[7], + ip6addr.Addr[8] << 8 | ip6addr.Addr[9], + ip6addr.Addr[10] << 8 | ip6addr.Addr[11], + ip6addr.Addr[12] << 8 | ip6addr.Addr[13], + ip6addr.Addr[14] << 8 | ip6addr.Addr[15]); +} + static EFI_STATUS set_ip6(EFI_HANDLE *nic, IPv6_DEVICE_PATH *ip6node) { - EFI_GUID ip6_config_guid = EFI_IP6_CONFIG_PROTOCOL_GUID; EFI_IP6_CONFIG_PROTOCOL *ip6cfg; EFI_IP6_CONFIG_MANUAL_ADDRESS ip6; EFI_IPv6_ADDRESS gateway; - EFI_STATUS status; + EFI_STATUS efi_status; - status = uefi_call_wrapper(BS->HandleProtocol, 3, - nic, - &ip6_config_guid, - (VOID **)&ip6cfg); - if (EFI_ERROR (status)) - return status; + efi_status = gBS->HandleProtocol(nic, &EFI_IP6_CONFIG_GUID, + (VOID **)&ip6cfg); + if (EFI_ERROR(efi_status)) + return efi_status; ip6.Address = ip6node->LocalIpAddress; ip6.PrefixLength = ip6node->PrefixLength; ip6.IsAnycast = FALSE; - status = uefi_call_wrapper(ip6cfg->SetData, 4, - ip6cfg, - Ip6ConfigDataTypeManualAddress, - sizeof(ip6), - &ip6); - if (EFI_ERROR (status)) - return status; + efi_status = ip6cfg->SetData(ip6cfg, Ip6ConfigDataTypeManualAddress, + sizeof(ip6), &ip6); + if (EFI_ERROR(efi_status)) { + perror(L"Failed to set IPv6 Address:\nIP: "); + print_ip6_addr(ip6.Address); + perror(L"Prefix Length: %u\n", ip6.PrefixLength); + return efi_status; + } gateway = ip6node->GatewayIpAddress; - if (is_unspecified_addr(gateway)) + if (is_unspecified_ip6addr(gateway)) return EFI_SUCCESS; - status = uefi_call_wrapper(ip6cfg->SetData, 4, - ip6cfg, - Ip6ConfigDataTypeGateway, - sizeof(gateway), - &gateway); - if (EFI_ERROR (status)) - return status; + efi_status = ip6cfg->SetData(ip6cfg, Ip6ConfigDataTypeGateway, + sizeof(gateway), &gateway); + if (EFI_ERROR(efi_status)) { + perror(L"Failed to set IPv6 Gateway:\nIP: "); + print_ip6_addr(gateway); + return efi_status; + } return EFI_SUCCESS; } +static BOOLEAN +is_unspecified_ip4addr (EFI_IPv4_ADDRESS ip4) +{ + UINT8 i; + + for (i = 0; i<4; i++) { + if (ip4.Addr[i] != 0) + return FALSE; + } + + return TRUE; +} + +static inline void +print_ip4_addr(EFI_IPv4_ADDRESS ip4addr) +{ + perror(L"%u.%u.%u.%u\n", + ip4addr.Addr[0], ip4addr.Addr[1], + ip4addr.Addr[2], ip4addr.Addr[3]); +} + static EFI_STATUS set_ip4(EFI_HANDLE *nic, IPv4_DEVICE_PATH *ip4node) { - EFI_GUID ip4_config2_guid = EFI_IP4_CONFIG2_PROTOCOL_GUID; EFI_IP4_CONFIG2_PROTOCOL *ip4cfg2; EFI_IP4_CONFIG2_MANUAL_ADDRESS ip4; EFI_IPv4_ADDRESS gateway; - EFI_STATUS status; + EFI_STATUS efi_status; - status = uefi_call_wrapper(BS->HandleProtocol, 3, - nic, - &ip4_config2_guid, - (VOID **)&ip4cfg2); - if (EFI_ERROR (status)) - return status; + efi_status = gBS->HandleProtocol(nic, &EFI_IP4_CONFIG2_GUID, + (VOID **)&ip4cfg2); + if (EFI_ERROR(efi_status)) + return efi_status; ip4.Address = ip4node->LocalIpAddress; ip4.SubnetMask = ip4node->SubnetMask; - status = uefi_call_wrapper(ip4cfg2->SetData, 4, - ip4cfg2, - Ip4Config2DataTypeManualAddress, - sizeof(ip4), - &ip4); - if (EFI_ERROR (status)) - return status; + efi_status = ip4cfg2->SetData(ip4cfg2, Ip4Config2DataTypeManualAddress, + sizeof(ip4), &ip4); + if (EFI_ERROR(efi_status)) { + perror(L"Failed to Set IPv4 Address:\nIP: "); + print_ip4_addr(ip4.Address); + perror(L"Mask: "); + print_ip4_addr(ip4.SubnetMask); + return efi_status; + } gateway = ip4node->GatewayIpAddress; - status = uefi_call_wrapper(ip4cfg2->SetData, 4, - ip4cfg2, - Ip4Config2DataTypeGateway, - sizeof(gateway), - &gateway); - if (EFI_ERROR (status)) - return status; + if (is_unspecified_ip4addr(gateway)) + return EFI_SUCCESS; + + efi_status = ip4cfg2->SetData(ip4cfg2, Ip4Config2DataTypeGateway, + sizeof(gateway), &gateway); + if (EFI_ERROR(efi_status)) { + perror(L"Failed to Set IPv4 Gateway:\nGateway: "); + print_ip4_addr(gateway); + return efi_status; + } return EFI_SUCCESS; } @@ -425,7 +456,7 @@ configure_http (EFI_HTTP_PROTOCOL *http, BOOLEAN is_ip6) http_mode.AccessPoint.IPv6Node = &ip6node; } - return uefi_call_wrapper(http->Configure, 2, http, &http_mode); + return http->Configure(http, &http_mode); } static EFI_STATUS @@ -437,7 +468,7 @@ send_http_request (EFI_HTTP_PROTOCOL *http, CHAR8 *hostname, CHAR8 *uri) EFI_HTTP_HEADER headers[3]; BOOLEAN request_done; CHAR16 *Url = NULL; - EFI_STATUS status; + EFI_STATUS efi_status; EFI_STATUS event_status; /* Convert the ascii string to the UCS2 string */ @@ -466,35 +497,33 @@ send_http_request (EFI_HTTP_PROTOCOL *http, CHAR8 *hostname, CHAR8 *uri) tx_token.Message = &tx_message; tx_token.Event = NULL; request_done = FALSE; - status = uefi_call_wrapper(BS->CreateEvent, 5, - EVT_NOTIFY_SIGNAL, - TPL_NOTIFY, - httpnotify, - &request_done, - &tx_token.Event); - if (EFI_ERROR(status)) { - perror(L"Failed to Create Event for HTTP request: %r\n", status); + efi_status = gBS->CreateEvent(EVT_NOTIFY_SIGNAL, TPL_NOTIFY, + httpnotify, &request_done, + &tx_token.Event); + if (EFI_ERROR(efi_status)) { + perror(L"Failed to Create Event for HTTP request: %r\n", + efi_status); goto no_event; } /* Send out the request */ - status = uefi_call_wrapper(http->Request, 2, http, &tx_token); - if (EFI_ERROR(status)) { - perror(L"HTTP request failed: %r\n", status); + efi_status = http->Request(http, &tx_token); + if (EFI_ERROR(efi_status)) { + perror(L"HTTP request failed: %r\n", efi_status); goto error; } /* Wait for the response */ while (!request_done) - uefi_call_wrapper(http->Poll, 1, http); + http->Poll(http); if (EFI_ERROR(tx_token.Status)) { perror(L"HTTP request: %r\n", tx_token.Status); - status = tx_token.Status; + efi_status = tx_token.Status; } error: - event_status = uefi_call_wrapper(BS->CloseEvent, 1, tx_token.Event); + event_status = gBS->CloseEvent(tx_token.Event); if (EFI_ERROR(event_status)) { perror(L"Failed to close Event for HTTP request: %r\n", event_status); @@ -504,7 +533,7 @@ no_event: if (Url) FreePool(Url); - return status; + return efi_status; } static EFI_STATUS @@ -517,7 +546,7 @@ receive_http_response(EFI_HTTP_PROTOCOL *http, VOID **buffer, UINT64 *buf_size) BOOLEAN response_done; UINTN i, downloaded; CHAR8 rx_buffer[9216]; - EFI_STATUS status; + EFI_STATUS efi_status; EFI_STATUS event_status; /* Initialize the rx message and buffer */ @@ -532,31 +561,29 @@ receive_http_response(EFI_HTTP_PROTOCOL *http, VOID **buffer, UINT64 *buf_size) rx_token.Message = &rx_message; rx_token.Event = NULL; response_done = FALSE; - status = uefi_call_wrapper(BS->CreateEvent, 5, - EVT_NOTIFY_SIGNAL, - TPL_NOTIFY, - httpnotify, - &response_done, - &rx_token.Event); - if (EFI_ERROR(status)) { - perror(L"Failed to Create Event for HTTP response: %r\n", status); + efi_status = gBS->CreateEvent(EVT_NOTIFY_SIGNAL, TPL_NOTIFY, + httpnotify, &response_done, + &rx_token.Event); + if (EFI_ERROR(efi_status)) { + perror(L"Failed to Create Event for HTTP response: %r\n", + efi_status); goto no_event; } /* Notify the firmware to receive the HTTP messages */ - status = uefi_call_wrapper(http->Response, 2, http, &rx_token); - if (EFI_ERROR(status)) { - perror(L"HTTP response failed: %r\n", status); + efi_status = http->Response(http, &rx_token); + if (EFI_ERROR(efi_status)) { + perror(L"HTTP response failed: %r\n", efi_status); goto error; } /* Wait for the response */ while (!response_done) - uefi_call_wrapper(http->Poll, 1, http); + http->Poll(http); if (EFI_ERROR(rx_token.Status)) { perror(L"HTTP response: %r\n", rx_token.Status); - status = rx_token.Status; + efi_status = rx_token.Status; goto error; } @@ -565,7 +592,7 @@ receive_http_response(EFI_HTTP_PROTOCOL *http, VOID **buffer, UINT64 *buf_size) if (http_status != HTTP_STATUS_200_OK) { perror(L"HTTP Status Code: %d\n", convert_http_status_code(http_status)); - status = EFI_ABORTED; + efi_status = EFI_ABORTED; goto error; } @@ -605,23 +632,23 @@ receive_http_response(EFI_HTTP_PROTOCOL *http, VOID **buffer, UINT64 *buf_size) rx_token.Status = EFI_NOT_READY; response_done = FALSE; - status = uefi_call_wrapper(http->Response, 2, http, &rx_token); - if (EFI_ERROR(status)) { - perror(L"HTTP response failed: %r\n", status); + efi_status = http->Response(http, &rx_token); + if (EFI_ERROR(efi_status)) { + perror(L"HTTP response failed: %r\n", efi_status); goto error; } while (!response_done) - uefi_call_wrapper(http->Poll, 1, http); + http->Poll(http); if (EFI_ERROR(rx_token.Status)) { perror(L"HTTP response: %r\n", rx_token.Status); - status = rx_token.Status; + efi_status = rx_token.Status; goto error; } if (rx_message.BodyLength + downloaded > *buf_size) { - status = EFI_BAD_BUFFER_SIZE; + efi_status = EFI_BAD_BUFFER_SIZE; goto error; } @@ -631,17 +658,17 @@ receive_http_response(EFI_HTTP_PROTOCOL *http, VOID **buffer, UINT64 *buf_size) } error: - event_status = uefi_call_wrapper(BS->CloseEvent, 1, rx_token.Event); + event_status = gBS->CloseEvent(rx_token.Event); if (EFI_ERROR(event_status)) { perror(L"Failed to close Event for HTTP response: %r\n", event_status); } no_event: - if (EFI_ERROR(status) && *buffer) + if (EFI_ERROR(efi_status) && *buffer) FreePool(*buffer); - return status; + return efi_status; } static EFI_STATUS @@ -649,64 +676,61 @@ http_fetch (EFI_HANDLE image, EFI_HANDLE device, CHAR8 *hostname, CHAR8 *uri, BOOLEAN is_ip6, VOID **buffer, UINT64 *buf_size) { - EFI_GUID http_binding_guid = EFI_HTTP_SERVICE_BINDING_PROTOCOL_GUID; - EFI_GUID http_protocol_guid = EFI_HTTP_PROTOCOL_GUID; EFI_SERVICE_BINDING *service; EFI_HANDLE http_handle; EFI_HTTP_PROTOCOL *http; - EFI_STATUS status; + EFI_STATUS efi_status; EFI_STATUS child_status; *buffer = NULL; *buf_size = 0; /* Open HTTP Service Binding Protocol */ - status = uefi_call_wrapper(BS->OpenProtocol, 6, device, - &http_binding_guid, (VOID **)&service, - image, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL); - if (EFI_ERROR (status)) - return status; + efi_status = gBS->OpenProtocol(device, &EFI_HTTP_BINDING_GUID, + (VOID **) &service, image, NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL); + if (EFI_ERROR(efi_status)) + return efi_status; /* Create the ChildHandle from the Service Binding */ /* Set the handle to NULL to request a new handle */ http_handle = NULL; - status = uefi_call_wrapper(service->CreateChild, 2, service, - &http_handle); - if (EFI_ERROR (status)) - return status; + efi_status = service->CreateChild(service, &http_handle); + if (EFI_ERROR(efi_status)) { + perror(L"Failed to create the ChildHandle\n"); + return efi_status; + } /* Get the http protocol */ - status = uefi_call_wrapper(BS->HandleProtocol, 3, http_handle, - &http_protocol_guid, (VOID **)&http); - if (EFI_ERROR (status)) { + efi_status = gBS->HandleProtocol(http_handle, &EFI_HTTP_PROTOCOL_GUID, + (VOID **) &http); + if (EFI_ERROR(efi_status)) { perror(L"Failed to get http\n"); goto error; } - status = configure_http(http, is_ip6); - if (EFI_ERROR (status)) { - perror(L"Failed to configure http: %r\n", status); + efi_status = configure_http(http, is_ip6); + if (EFI_ERROR(efi_status)) { + perror(L"Failed to configure http: %r\n", efi_status); goto error; } - status = send_http_request(http, hostname, uri); - if (EFI_ERROR(status)) { - perror(L"Failed to send HTTP request: %r\n", status); + efi_status = send_http_request(http, hostname, uri); + if (EFI_ERROR(efi_status)) { + perror(L"Failed to send HTTP request: %r\n", efi_status); goto error; } - status = receive_http_response(http, buffer, buf_size); - if (EFI_ERROR(status)) { - perror(L"Failed to receive HTTP response: %r\n", status); + efi_status = receive_http_response(http, buffer, buf_size); + if (EFI_ERROR(efi_status)) { + perror(L"Failed to receive HTTP response: %r\n", efi_status); goto error; } error: - child_status = uefi_call_wrapper(service->DestroyChild, 2, service, - http_handle); - - if (EFI_ERROR(status)) { - return status; + child_status = service->DestroyChild(service, http_handle); + if (EFI_ERROR(efi_status)) { + return efi_status; } else if (EFI_ERROR(child_status)) { return child_status; } @@ -717,7 +741,7 @@ error: EFI_STATUS httpboot_fetch_buffer (EFI_HANDLE image, VOID **buffer, UINT64 *buf_size) { - EFI_STATUS status; + EFI_STATUS efi_status; EFI_HANDLE nic; CHAR8 *next_loader = NULL; CHAR8 *next_uri = NULL; @@ -729,16 +753,16 @@ httpboot_fetch_buffer (EFI_HANDLE image, VOID **buffer, UINT64 *buf_size) next_loader = translate_slashes(DEFAULT_LOADER_CHAR); /* Create the URI for the next loader based on the original URI */ - status = generate_next_uri(uri, next_loader, &next_uri); - if (EFI_ERROR (status)) { - perror(L"Next URI: %a, %r\n", next_uri, status); + efi_status = generate_next_uri(uri, next_loader, &next_uri); + if (EFI_ERROR(efi_status)) { + perror(L"Next URI: %a, %r\n", next_uri, efi_status); goto error; } /* Extract the hostname (or IP) from URI */ - status = extract_hostname(uri, &hostname); - if (EFI_ERROR (status)) { - perror(L"hostname: %a, %r\n", hostname, status); + efi_status = extract_hostname(uri, &hostname); + if (EFI_ERROR(efi_status)) { + perror(L"hostname: %a, %r\n", hostname, efi_status); goto error; } @@ -746,6 +770,7 @@ httpboot_fetch_buffer (EFI_HANDLE image, VOID **buffer, UINT64 *buf_size) also supports the HTTP service binding protocol */ nic = get_nic_handle(&mac_addr); if (!nic) { + efi_status = EFI_NOT_FOUND; goto error; } @@ -753,19 +778,19 @@ httpboot_fetch_buffer (EFI_HANDLE image, VOID **buffer, UINT64 *buf_size) information in the device path node. We have to set up the connection on our own for the further operations. */ if (!is_ip6) - status = set_ip4(nic, &ip4_node); + efi_status = set_ip4(nic, &ip4_node); else - status = set_ip6(nic, &ip6_node); - if (EFI_ERROR (status)) { - perror(L"Failed to set IP for HTTPBoot: %r\n", status); + efi_status = set_ip6(nic, &ip6_node); + if (EFI_ERROR(efi_status)) { + perror(L"Failed to set IP for HTTPBoot: %r\n", efi_status); goto error; } /* Use HTTP protocl to fetch the remote file */ - status = http_fetch (image, nic, hostname, next_uri, is_ip6, - buffer, buf_size); - if (EFI_ERROR (status)) { - perror(L"Failed to fetch image: %r\n", status); + efi_status = http_fetch (image, nic, hostname, next_uri, is_ip6, + buffer, buf_size); + if (EFI_ERROR(efi_status)) { + perror(L"Failed to fetch image: %r\n", efi_status); goto error; } @@ -777,5 +802,5 @@ error: if (hostname) FreePool(hostname); - return status; + return efi_status; } diff --git a/include/Http.h b/include/Http.h index cd77703..4b3746a 100644 --- a/include/Http.h +++ b/include/Http.h @@ -19,18 +19,8 @@ **/ -#ifndef __EFI_HTTP_PROTOCOL_H__ -#define __EFI_HTTP_PROTOCOL_H__ - -#define EFI_HTTP_SERVICE_BINDING_PROTOCOL_GUID \ - { \ - 0xbdc8e6af, 0xd9bc, 0x4379, {0xa7, 0x2a, 0xe0, 0xc4, 0xe7, 0x5d, 0xae, 0x1c } \ - } - -#define EFI_HTTP_PROTOCOL_GUID \ - { \ - 0x7a59b29b, 0x910b, 0x4171, {0x82, 0x42, 0xa8, 0x5a, 0x0d, 0xf2, 0x5b, 0x5b } \ - } +#ifndef SHIM_HTTP_H +#define SHIM_HTTP_H typedef struct _EFI_HTTP_PROTOCOL EFI_HTTP_PROTOCOL; @@ -514,4 +504,4 @@ struct _EFI_HTTP_PROTOCOL { EFI_HTTP_POLL Poll; }; -#endif +#endif /* SHIM_HTTP_H */ diff --git a/include/Ip4Config2.h b/include/Ip4Config2.h index b4f1d84..efacaf8 100644 --- a/include/Ip4Config2.h +++ b/include/Ip4Config2.h @@ -15,16 +15,11 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. This Protocol is introduced in UEFI Specification 2.5 **/ -#ifndef __EFI_IP4CONFIG2_PROTOCOL_H__ -#define __EFI_IP4CONFIG2_PROTOCOL_H__ +#ifndef SHIM_IP4CONFIG2_H +#define SHIM_IP4CONFIG2_H #include -#define EFI_IP4_CONFIG2_PROTOCOL_GUID \ - { \ - 0x5b446ed1, 0xe30b, 0x4faa, {0x87, 0x1a, 0x36, 0x54, 0xec, 0xa3, 0x60, 0x80 } \ - } - typedef struct _EFI_IP4_CONFIG2_PROTOCOL EFI_IP4_CONFIG2_PROTOCOL; @@ -312,4 +307,4 @@ struct _EFI_IP4_CONFIG2_PROTOCOL { EFI_IP4_CONFIG2_UNREGISTER_NOTIFY UnregisterDataNotify; }; -#endif +#endif /* SHIM_IP4CONFIG2_H */ diff --git a/include/Ip6Config.h b/include/Ip6Config.h index 003e50e..f99ce01 100644 --- a/include/Ip6Config.h +++ b/include/Ip6Config.h @@ -12,16 +12,11 @@ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. **/ -#ifndef __EFI_IP6CONFIG_PROTOCOL_H__ -#define __EFI_IP6CONFIG_PROTOCOL_H__ +#ifndef SHIM_IP6CONFIG_H +#define SHIM_IP6CONFIG_H #include -#define EFI_IP6_CONFIG_PROTOCOL_GUID \ - { \ - 0x937fe521, 0x95ae, 0x4d1a, {0x89, 0x29, 0x48, 0xbc, 0xd9, 0x0a, 0xd3, 0x1a } \ - } - typedef struct _EFI_IP6_CONFIG_PROTOCOL EFI_IP6_CONFIG_PROTOCOL; /// @@ -363,4 +358,4 @@ struct _EFI_IP6_CONFIG_PROTOCOL { EFI_IP6_CONFIG_UNREGISTER_NOTIFY UnregisterDataNotify; }; -#endif +#endif /* SHIM_IP6CONFIG_H */ diff --git a/PasswordCrypt.h b/include/PasswordCrypt.h similarity index 84% rename from PasswordCrypt.h rename to include/PasswordCrypt.h index b726f32..cadad72 100644 --- a/PasswordCrypt.h +++ b/include/PasswordCrypt.h @@ -1,5 +1,5 @@ -#ifndef __PASSWORD_CRYPT_H__ -#define __PASSWORD_CRYPT_H__ +#ifndef SHIM_PASSWORDCRYPT_H +#define SHIM_PASSWORDCRYPT_H enum HashMethod { TRADITIONAL_DES = 0, @@ -24,4 +24,4 @@ EFI_STATUS password_crypt (const char *password, UINT32 pw_length, const PASSWORD_CRYPT *pw_hash, UINT8 *hash); UINT16 get_hash_size (const UINT16 method); -#endif /* __PASSWORD_CRYPT_H__ */ +#endif /* SHIM_PASSWORDCRYPT_H */ diff --git a/include/PeImage.h b/include/PeImage.h index 17f186c..a606e8b 100644 --- a/include/PeImage.h +++ b/include/PeImage.h @@ -19,8 +19,8 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. **/ -#ifndef __PE_IMAGE_H__ -#define __PE_IMAGE_H__ +#ifndef SHIM_PEIMAGE_H +#define SHIM_PEIMAGE_H #include @@ -786,4 +786,4 @@ typedef struct { EFI_IMAGE_OPTIONAL_HEADER_UNION *PEHdr; } PE_COFF_LOADER_IMAGE_CONTEXT; -#endif +#endif /* SHIM_PEIMAGE_H */ diff --git a/include/configtable.h b/include/configtable.h index fa2b505..0c9dfdc 100644 --- a/include/configtable.h +++ b/include/configtable.h @@ -1,3 +1,6 @@ +#ifndef SHIM_CONFIGTABLE_H +#define SHIM_CONFIGTABLE_H + /* definitions straight from TianoCore */ typedef UINT32 EFI_IMAGE_EXECUTION_ACTION; @@ -66,3 +69,4 @@ configtable_find_image(const EFI_DEVICE_PATH *DevicePath); int configtable_image_is_forbidden(const EFI_DEVICE_PATH *DevicePath); +#endif /* SHIM_CONFIGTABLE_H */ diff --git a/include/console.h b/include/console.h index e9cf285..deb4fa3 100644 --- a/include/console.h +++ b/include/console.h @@ -1,8 +1,18 @@ -#ifndef _SHIM_LIB_CONSOLE_H -#define _SHIM_LIB_CONSOLE_H 1 +#ifndef SHIM_CONSOLE_H +#define SHIM_CONSOLE_H + +#define Print(fmt, ...) \ + ({"Do not directly call Print() use console_print() instead" = 1;}); + +#define PrintAt(fmt, ...) \ + ({"Do not directly call PrintAt() use console_print_at() instead" = 1;}); EFI_STATUS console_get_keystroke(EFI_INPUT_KEY *key); +UINTN +console_print(const CHAR16 *fmt, ...); +UINTN +console_print_at(UINTN col, UINTN row, const CHAR16 *fmt, ...); void console_print_box_at(CHAR16 *str_arr[], int highlight, int start_col, int start_row, @@ -26,9 +36,6 @@ 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 { @@ -42,7 +49,7 @@ 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 *GopUgaExists, OPTIONAL OUT BOOLEAN *StdInLocked OPTIONAL ); @@ -66,26 +73,14 @@ struct _EFI_CONSOLE_CONTROL_PROTOCOL { EFI_CONSOLE_CONTROL_PROTOCOL_LOCK_STD_IN LockStdIn; }; -extern VOID setup_console (int text); +extern VOID console_fini(VOID); 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; \ +extern UINT32 verbose; +#define dprint(fmt, ...) ({ \ + UINTN __dprint_ret = 0; \ + if (verbose) \ + __dprint_ret = console_print((fmt), ##__VA_ARGS__); \ + __dprint_ret; \ }) extern EFI_STATUS print_crypto_errors(EFI_STATUS rc, char *file, const char *func, int line); @@ -93,4 +88,8 @@ extern EFI_STATUS print_crypto_errors(EFI_STATUS rc, char *file, const char *fun extern VOID msleep(unsigned long msecs); -#endif /* _SHIM_LIB_CONSOLE_H */ +/* This is used in various things to determine if we should print to the + * console */ +extern UINT8 in_protocol; + +#endif /* SHIM_CONSOLE_H */ diff --git a/crypt_blowfish.h b/include/crypt_blowfish.h similarity index 88% rename from crypt_blowfish.h rename to include/crypt_blowfish.h index dc3bd56..8d4dd4d 100644 --- a/crypt_blowfish.h +++ b/include/crypt_blowfish.h @@ -14,9 +14,10 @@ * See crypt_blowfish.c for more information. */ -#ifndef _CRYPT_BLOWFISH_H -#define _CRYPT_BLOWFISH_H +#ifndef SHIM_CRYPT_BLOWFISH_H +#define SHIM_CRYPT_BLOWFISH_H char *crypt_blowfish_rn(const char *key, const char *setting, char *output, int size); -#endif + +#endif /* SHIM_CRYPT_BLOWFISH_H */ diff --git a/include/efiauthenticated.h b/include/efiauthenticated.h index f7d6bcb..7157ffd 100644 --- a/include/efiauthenticated.h +++ b/include/efiauthenticated.h @@ -1,222 +1,193 @@ -#ifndef _INC_EFIAUTHENTICATED_H -#define _INC_EFIAUTHENTICATED_H +#ifndef SHIM_EFIAUTHENTICATED_H +#define SHIM_EFIAUTHENTICATED_H + #include -//*********************************************************************** -// Signature Database -//*********************************************************************** -/// -/// The format of a signature database. -/// + +/*********************************************************************** + * Signature Database + ***********************************************************************/ +/* + * The format of a signature database. + */ #pragma pack(1) 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]; + /* + * 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]; } 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]; - /// + /* + * Type of the signature. GUID signature types are defined 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]; } EFI_SIGNATURE_LIST; #pragma pack() -// -// _WIN_CERTIFICATE.wCertificateType -// +/* + * WIN_CERTIFICATE.wCertificateType + */ #define WIN_CERT_TYPE_PKCS_SIGNED_DATA 0x0002 #define WIN_CERT_TYPE_EFI_PKCS115 0x0EF0 #define WIN_CERT_TYPE_EFI_GUID 0x0EF1 -#define EFI_CERT_X509_GUID \ - (EFI_GUID){ \ - 0xa5c059a1, 0x94e4, 0x4aa7, {0x87, 0xb5, 0xab, 0x15, 0x5c, 0x2b, 0xf0, 0x72} \ - } - -#define EFI_CERT_RSA2048_GUID \ - (EFI_GUID){ \ - 0x3c5766e8, 0x269c, 0x4e34, {0xaa, 0x14, 0xed, 0x77, 0x6e, 0x85, 0xb3, 0xb6} \ - } - - -#define EFI_CERT_TYPE_PKCS7_GUID \ - (EFI_GUID){ \ - 0x4aafd29d, 0x68df, 0x49ee, {0x8a, 0xa9, 0x34, 0x7d, 0x37, 0x56, 0x65, 0xa7} \ - } - -/// -/// WIN_CERTIFICATE_UEFI_GUID.CertType -/// -#define EFI_CERT_TYPE_RSA2048_SHA256_GUID \ - {0xa7717414, 0xc616, 0x4977, {0x94, 0x20, 0x84, 0x47, 0x12, 0xa7, 0x35, 0xbf } } - -/// -/// WIN_CERTIFICATE_UEFI_GUID.CertData -/// +/* + * WIN_CERTIFICATE_UEFI_GUID.CertData + */ typedef struct { - EFI_GUID HashType; - UINT8 PublicKey[256]; - UINT8 Signature[256]; + EFI_GUID HashType; + UINT8 PublicKey[256]; + UINT8 Signature[256]; } EFI_CERT_BLOCK_RSA_2048_SHA256; - -/// -/// Certificate which encapsulates a GUID-specific digital signature -/// +/* + * Certificate which encapsulates a GUID-specific digital signature + */ typedef struct { - /// - /// This is the standard WIN_CERTIFICATE header, where - /// wCertificateType is set to WIN_CERT_TYPE_UEFI_GUID. - /// - WIN_CERTIFICATE Hdr; - /// - /// This is the unique id which determines the - /// format of the CertData. . - /// - EFI_GUID CertType; - /// - /// The following is the certificate data. The format of - /// the data is determined by the CertType. - /// If CertType is EFI_CERT_TYPE_RSA2048_SHA256_GUID, - /// the CertData will be EFI_CERT_BLOCK_RSA_2048_SHA256 structure. - /// - UINT8 CertData[1]; + /* + * This is the standard WIN_CERTIFICATE header, where wCertificateType is + * set to WIN_CERT_TYPE_UEFI_GUID. + */ + WIN_CERTIFICATE Hdr; + /* + * This is the unique id which determines the format of the CertData. + */ + EFI_GUID CertType; + /* + * The following is the certificate data. The format of the data is + * determined by the CertType. If CertType is + * EFI_CERT_TYPE_RSA2048_SHA256_GUID, the CertData will be + * EFI_CERT_BLOCK_RSA_2048_SHA256 structure. + */ + UINT8 CertData[1]; } WIN_CERTIFICATE_UEFI_GUID; - -/// -/// Certificate which encapsulates the RSASSA_PKCS1-v1_5 digital signature. -/// -/// The WIN_CERTIFICATE_UEFI_PKCS1_15 structure is derived from -/// WIN_CERTIFICATE and encapsulate the information needed to -/// implement the RSASSA-PKCS1-v1_5 digital signature algorithm as -/// specified in RFC2437. -/// -typedef struct { - /// - /// This is the standard WIN_CERTIFICATE header, where - /// wCertificateType is set to WIN_CERT_TYPE_UEFI_PKCS1_15. - /// - WIN_CERTIFICATE Hdr; - /// - /// This is the hashing algorithm which was performed on the - /// UEFI executable when creating the digital signature. - /// - EFI_GUID HashAlgorithm; - /// - /// The following is the actual digital signature. The - /// size of the signature is the same size as the key - /// (1024-bit key is 128 bytes) and can be determined by - /// subtracting the length of the other parts of this header - /// from the total length of the certificate as found in - /// Hdr.dwLength. - /// - /// UINT8 Signature[]; - /// +/* + * Certificate which encapsulates the RSASSA_PKCS1-v1_5 digital signature. + * + * The WIN_CERTIFICATE_UEFI_PKCS1_15 structure is derived from + * WIN_CERTIFICATE and encapsulate the information needed to implement the + * RSASSA-PKCS1-v1_5 digital signature algorithm as specified in RFC2437. + */ +typedef struct { + /* + * This is the standard WIN_CERTIFICATE header, where + * wCertificateType is set to WIN_CERT_TYPE_UEFI_PKCS1_15. + */ + WIN_CERTIFICATE Hdr; + /* + * This is the hashing algorithm which was performed on the UEFI + * executable when creating the digital signature. + */ + EFI_GUID HashAlgorithm; + /* + * The following is the actual digital signature. The size of the + * signature is the same size as the key (1024-bit key is 128 bytes) + * and can be determined by subtracting the length of the other parts + * of this header from the total length of the certificate as found + * in Hdr.dwLength. + */ + //UINT8 Signature[]; } WIN_CERTIFICATE_EFI_PKCS1_15; -#define OFFSET_OF(TYPE, Field) ((UINTN) &(((TYPE *)0)->Field)) - -/// -/// Attributes of Authenticated Variable -/// +/* + * Attributes of Authenticated Variable + */ #define EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS 0x00000010 #define EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS 0x00000020 #define EFI_VARIABLE_APPEND_WRITE 0x00000040 -/// -/// AuthInfo is a WIN_CERTIFICATE using the wCertificateType -/// WIN_CERTIFICATE_UEFI_GUID and the CertType -/// EFI_CERT_TYPE_RSA2048_SHA256_GUID. If the attribute specifies -/// authenticated access, then the Data buffer should begin with an -/// authentication descriptor prior to the data payload and DataSize -/// should reflect the the data.and descriptor size. The caller -/// shall digest the Monotonic Count value and the associated data -/// for the variable update using the SHA-256 1-way hash algorithm. -/// The ensuing the 32-byte digest will be signed using the private -/// key associated w/ the public/private 2048-bit RSA key-pair. The -/// WIN_CERTIFICATE shall be used to describe the signature of the -/// Variable data *Data. In addition, the signature will also -/// include the MonotonicCount value to guard against replay attacks. -/// +/* + * AuthInfo is a WIN_CERTIFICATE using the wCertificateType + * WIN_CERTIFICATE_UEFI_GUID and the CertType + * EFI_CERT_TYPE_RSA2048_SHA256_GUID. If the attribute specifies + * authenticated access, then the Data buffer should begin with an + * authentication descriptor prior to the data payload and DataSize should + * reflect the the data.and descriptor size. The caller shall digest the + * Monotonic Count value and the associated data for the variable update + * using the SHA-256 1-way hash algorithm. The ensuing the 32-byte digest + * will be signed using the private key associated w/ the public/private + * 2048-bit RSA key-pair. The WIN_CERTIFICATE shall be used to describe the + * signature of the Variable data *Data. In addition, the signature will also + * include the MonotonicCount value to guard against replay attacks. + */ typedef struct { - /// - /// Included in the signature of - /// AuthInfo.Used to ensure freshness/no - /// replay. Incremented during each - /// "Write" access. - /// - UINT64 MonotonicCount; - /// - /// Provides the authorization for the variable - /// access. It is a signature across the - /// variable data and the Monotonic Count - /// value. Caller uses Private key that is - /// associated with a public key that has been - /// provisioned via the key exchange. - /// - WIN_CERTIFICATE_UEFI_GUID AuthInfo; + /* + * Included in the signature of AuthInfo.Used to ensure freshness/no + * replay. Incremented during each "Write" access. + */ + UINT64 MonotonicCount; + /* + * Provides the authorization for the variable access. It is a + * signature across the variable data and the Monotonic Count value. + * Caller uses Private key that is associated with a public key that + * has been provisioned via the key exchange. + */ + WIN_CERTIFICATE_UEFI_GUID AuthInfo; } EFI_VARIABLE_AUTHENTICATION; -/// -/// When the attribute EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS is -/// set, then the Data buffer shall begin with an instance of a complete (and serialized) -/// EFI_VARIABLE_AUTHENTICATION_2 descriptor. The descriptor shall be followed by the new -/// variable value and DataSize shall reflect the combined size of the descriptor and the new -/// variable value. The authentication descriptor is not part of the variable data and is not -/// returned by subsequent calls to GetVariable(). -/// +/* + * When the attribute EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS is + * set, then the Data buffer shall begin with an instance of a complete (and + * serialized) EFI_VARIABLE_AUTHENTICATION_2 descriptor. The descriptor shall + * be followed by the new variable value and DataSize shall reflect the + * combined size of the descriptor and the new variable value. The + * authentication descriptor is not part of the variable data and is not + * returned by subsequent calls to GetVariable(). + */ typedef struct { - /// - /// For the TimeStamp value, components Pad1, Nanosecond, TimeZone, Daylight and - /// Pad2 shall be set to 0. This means that the time shall always be expressed in GMT. - /// - EFI_TIME TimeStamp; - /// - /// Only a CertType of EFI_CERT_TYPE_PKCS7_GUID is accepted. - /// - WIN_CERTIFICATE_UEFI_GUID AuthInfo; - } EFI_VARIABLE_AUTHENTICATION_2; + /* + * For the TimeStamp value, components Pad1, Nanosecond, TimeZone, + * Daylight and Pad2 shall be set to 0. This means that the time + * shall always be expressed in GMT. + */ + EFI_TIME TimeStamp; + /* + * Only a CertType of EFI_CERT_TYPE_PKCS7_GUID is accepted. + */ + WIN_CERTIFICATE_UEFI_GUID AuthInfo; +} EFI_VARIABLE_AUTHENTICATION_2; -/// -/// Size of AuthInfo prior to the data payload. -/// -#define AUTHINFO_SIZE ((OFFSET_OF (EFI_VARIABLE_AUTHENTICATION, AuthInfo)) + \ - (OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID, CertData)) + \ +/* + * Size of AuthInfo prior to the data payload. + */ +#define AUTHINFO_SIZE ((offsetof(EFI_VARIABLE_AUTHENTICATION, AuthInfo)) + \ + (offsetof(WIN_CERTIFICATE_UEFI_GUID, CertData)) + \ sizeof (EFI_CERT_BLOCK_RSA_2048_SHA256)) -#define AUTHINFO2_SIZE(VarAuth2) ((OFFSET_OF (EFI_VARIABLE_AUTHENTICATION_2, AuthInfo)) + \ +#define AUTHINFO2_SIZE(VarAuth2) ((offsetof(EFI_VARIABLE_AUTHENTICATION_2, AuthInfo)) + \ (UINTN) ((EFI_VARIABLE_AUTHENTICATION_2 *) (VarAuth2))->AuthInfo.Hdr.dwLength) -#define OFFSET_OF_AUTHINFO2_CERT_DATA ((OFFSET_OF (EFI_VARIABLE_AUTHENTICATION_2, AuthInfo)) + \ - (OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID, CertData))) +#define OFFSET_OF_AUTHINFO2_CERT_DATA ((offsetof(EFI_VARIABLE_AUTHENTICATION_2, AuthInfo)) + \ + (offsetof(WIN_CERTIFICATE_UEFI_GUID, CertData))) -#endif +#endif /* SHIM_EFIAUTHENTICATED_H */ diff --git a/include/errors.h b/include/errors.h index 0da4bb5..21978bd 100644 --- a/include/errors.h +++ b/include/errors.h @@ -1,3 +1,6 @@ +#ifndef SHIM_ERRORS_H +#define SHIM_ERRORS_H + #include #ifndef EFI_INCOMPATIBLE_VERSION @@ -7,3 +10,4 @@ #define EFI_SECURITY_VIOLATION EFIERR(26) #endif +#endif /* SHIM_ERRORS_H */ diff --git a/include/execute.h b/include/execute.h index 9aecbff..18d2fa2 100644 --- a/include/execute.h +++ b/include/execute.h @@ -1,5 +1,10 @@ +#ifndef SHIM_LIB_EXECUTE_H +#define SHIM_LIB_EXECUTE_H + EFI_STATUS generate_path(CHAR16* name, EFI_LOADED_IMAGE *li, EFI_DEVICE_PATH **path, CHAR16 **PathName); EFI_STATUS execute(EFI_HANDLE image, CHAR16 *name); + +#endif /* SHIM_LIB_EXECUTE_H */ diff --git a/include/guid.h b/include/guid.h index 86b709b..81689d6 100644 --- a/include/guid.h +++ b/include/guid.h @@ -1,14 +1,38 @@ +#ifndef SHIM_GUID_H +#define SHIM_GUID_H + #include +extern EFI_GUID BDS_GUID; extern EFI_GUID GV_GUID; extern EFI_GUID SIG_DB; extern EFI_GUID X509_GUID; 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_FILE_INFO_GUID; +extern EFI_GUID EFI_FILE_SYSTEM_INFO_GUID; +extern EFI_GUID EFI_CERT_RSA2048_GUID; extern EFI_GUID EFI_CERT_SHA1_GUID; extern EFI_GUID EFI_CERT_SHA256_GUID; -extern EFI_GUID MOK_OWNER; +extern EFI_GUID EFI_CERT_SHA224_GUID; +extern EFI_GUID EFI_CERT_SHA384_GUID; +extern EFI_GUID EFI_CERT_SHA512_GUID; +extern EFI_GUID EFI_CERT_TYPE_PKCS7_GUID; +extern EFI_GUID EFI_CERT_TYPE_RSA2048_SHA256_GUID; +extern EFI_GUID EFI_CERT_TYPE_X509_GUID; +extern EFI_GUID EFI_CONSOLE_CONTROL_GUID; +extern EFI_GUID EFI_HTTP_BINDING_GUID; +extern EFI_GUID EFI_HTTP_PROTOCOL_GUID; +extern EFI_GUID EFI_IP4_CONFIG2_GUID; +extern EFI_GUID EFI_IP6_CONFIG_GUID; +extern EFI_GUID EFI_LOADED_IMAGE_GUID; +extern EFI_GUID EFI_TPM_GUID; +extern EFI_GUID EFI_TPM2_GUID; +extern EFI_GUID EFI_SECURE_BOOT_DB_GUID; +extern EFI_GUID EFI_SIMPLE_FILE_SYSTEM_GUID; extern EFI_GUID SECURITY_PROTOCOL_GUID; extern EFI_GUID SECURITY2_PROTOCOL_GUID; +extern EFI_GUID SHIM_LOCK_GUID; + +#endif /* SHIM_GUID_H */ diff --git a/hexdump.h b/include/hexdump.h similarity index 89% rename from hexdump.h rename to include/hexdump.h index d5ece4d..d337b57 100644 --- a/hexdump.h +++ b/include/hexdump.h @@ -80,7 +80,7 @@ hexdump(UINT8 *data, UINTN size) { UINTN display_offset = (UINTN)data & 0xffffffff; UINTN offset = 0; - //Print(L"hexdump: data=0x%016x size=0x%x\n", data, size); + //console_print(L"hexdump: data=0x%016x size=0x%x\n", data, size); while (offset < size) { CHAR16 hexbuf[49]; @@ -90,15 +90,15 @@ hexdump(UINT8 *data, UINTN size) sz = format_hex(data+offset, size-offset, hexbuf); if (sz == 0) return; - uefi_call_wrapper(BS->Stall, 1, 200000); + msleep(200000); format_text(data+offset, size-offset, txtbuf); - Print(L"%08x %s %s\n", display_offset, hexbuf, txtbuf); - uefi_call_wrapper(BS->Stall, 1, 200000); + console_print(L"%08x %s %s\n", display_offset, hexbuf, txtbuf); + msleep(200000); display_offset += sz; offset += sz; } } -#endif +#endif /* STATIC_HEXDUMP_H */ diff --git a/httpboot.h b/include/httpboot.h similarity index 87% rename from httpboot.h rename to include/httpboot.h index 527a856..b47f6a9 100644 --- a/httpboot.h +++ b/include/httpboot.h @@ -31,11 +31,11 @@ * Corporation. */ -#ifndef _HTTPBOOT_H_ -#define _HTTPBOOT_H_ +#ifndef SHIM_HTTPBOOT_H +#define SHIM_HTTPBOOT_H -BOOLEAN find_httpboot (EFI_DEVICE_PATH *devpath); +extern BOOLEAN find_httpboot(EFI_HANDLE device); +extern EFI_STATUS httpboot_fetch_buffer(EFI_HANDLE image, VOID **buffer, + UINT64 *buf_size); -EFI_STATUS httpboot_fetch_buffer (EFI_HANDLE image, VOID **buffer, UINT64 *buf_size); - -#endif +#endif /* SHIM_HTTPBOOT_H */ diff --git a/netboot.h b/include/netboot.h similarity index 73% rename from netboot.h rename to include/netboot.h index 6417373..d1ad125 100644 --- a/netboot.h +++ b/include/netboot.h @@ -1,9 +1,10 @@ -#ifndef _NETBOOT_H_ -#define _NETBOOT_H_ +#ifndef SHIM_NETBOOT_H +#define SHIM_NETBOOT_H extern BOOLEAN findNetboot(EFI_HANDLE image_handle); extern EFI_STATUS parseNetbootinfo(EFI_HANDLE image_handle); extern EFI_STATUS FetchNetbootimage(EFI_HANDLE image_handle, VOID **buffer, UINT64 *bufsiz); -#endif + +#endif /* SHIM_NETBOOT_H */ diff --git a/replacements.h b/include/replacements.h similarity index 96% rename from replacements.h rename to include/replacements.h index e38cded..ab2a5a5 100644 --- a/replacements.h +++ b/include/replacements.h @@ -27,7 +27,9 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef SHIM_REPLACEMENTS_H -#define SHIM_REPLACEMENTS_H 1 +#define SHIM_REPLACEMENTS_H + +extern EFI_SYSTEM_TABLE *get_active_systab(void); typedef enum { VERIFIED_BY_NOTHING, diff --git a/include/security_policy.h b/include/security_policy.h index 7854db1..7cfbfd0 100644 --- a/include/security_policy.h +++ b/include/security_policy.h @@ -1,5 +1,5 @@ -#ifndef _SHIM_LIB_SECURITY_POLICY_H -#define _SHIM_LIB_SECURITY_POLICY_H 1 +#ifndef SHIM_SECURITY_POLICY_H +#define SHIM_SECURITY_POLICY_H #if defined(OVERRIDE_SECURITY_POLICY) typedef EFI_STATUS (*SecurityHook) (void *data, UINT32 len); @@ -12,4 +12,4 @@ void security_protocol_set_hashes(unsigned char *esl, int len); #endif /* OVERRIDE_SECURITY_POLICY */ -#endif /* SHIM_LIB_SECURITY_POLICY_H */ +#endif /* SHIM_SECURITY_POLICY_H */ diff --git a/include/shell.h b/include/shell.h index 9cb5d47..fec5013 100644 --- a/include/shell.h +++ b/include/shell.h @@ -1,2 +1,7 @@ +#ifndef SHIM_SHELL_H +#define SHIM_SHELL_H + EFI_STATUS argsplit(EFI_HANDLE image, int *argc, CHAR16*** ARGV); + +#endif /* SHIM_SHELL_H */ diff --git a/include/simple_file.h b/include/simple_file.h index fe4fd97..7b01965 100644 --- a/include/simple_file.h +++ b/include/simple_file.h @@ -1,3 +1,6 @@ +#ifndef SHIM_SIMPLE_FILE_H +#define SHIM_SIMPLE_FILE_H + EFI_STATUS simple_file_open (EFI_HANDLE image, CHAR16 *name, EFI_FILE **file, UINT64 mode); EFI_STATUS @@ -6,8 +9,6 @@ EFI_STATUS simple_file_read_all(EFI_FILE *file, UINTN *size, void **buffer); EFI_STATUS simple_file_write_all(EFI_FILE *file, UINTN size, void *buffer); -void -simple_file_close(EFI_FILE *file); EFI_STATUS simple_dir_read_all(EFI_HANDLE image, CHAR16 *name, EFI_FILE_INFO **Entries, int *count); @@ -19,3 +20,5 @@ simple_file_selector(EFI_HANDLE *im, CHAR16 **title, CHAR16 *name, CHAR16 *filter, CHAR16 **result); EFI_STATUS simple_volume_selector(CHAR16 **title, CHAR16 **selected, EFI_HANDLE *h); + +#endif /* SHIM_SIMPLE_FILE_H */ diff --git a/tpm.h b/include/tpm.h similarity index 96% rename from tpm.h rename to include/tpm.h index d11b545..746e871 100644 --- a/tpm.h +++ b/include/tpm.h @@ -1,7 +1,7 @@ -#include +#ifndef SHIM_TPM_H +#define SHIM_TPM_H -#define EFI_TPM_GUID {0xf541796d, 0xa62e, 0x4954, {0xa7, 0x75, 0x95, 0x84, 0xf6, 0x1b, 0x9c, 0xdd }}; -#define EFI_TPM2_GUID {0x607f766c, 0x7455, 0x42be, {0x93, 0x0b, 0xe4, 0xd7, 0x6d, 0xb2, 0x72, 0x0f }}; +#include #define TPM_ALG_SHA 0x00000004 #define EV_IPL 0x0000000d @@ -186,3 +186,6 @@ typedef UINT32 TCG_EVENTTYPE; #define EV_EFI_VARIABLE_AUTHORITY (EV_EFI_EVENT_BASE + 0xE0) #define PE_COFF_IMAGE 0x0000000000000010 + +#endif /* SHIM_TPM_H */ +// vim:fenc=utf-8:tw=75 diff --git a/ucs2.h b/include/ucs2.h similarity index 88% rename from ucs2.h rename to include/ucs2.h index 010d096..806774c 100644 --- a/ucs2.h +++ b/include/ucs2.h @@ -36,6 +36,8 @@ #ifndef SHIM_UCS2_H #define SHIM_UCS2_H +#include + static inline INTN __attribute__((unused)) StrCaseCmp(CHAR16 *s0, CHAR16 *s1) @@ -89,6 +91,24 @@ StrCSpn(const CHAR16 *s, const CHAR16 *reject) return ret; } +/* + * Test if an entire buffer is nothing but NUL characters. This + * implementation "gracefully" ignores the difference between the + * UTF-8/ASCII 1-byte NUL and the UCS-2 2-byte NUL. + */ +static inline bool +__attribute__((__unused__)) +is_all_nuls(UINT8 *data, UINTN data_size) +{ + UINTN i; + + for (i = 0; i < data_size; i++) { + if (data[i] != 0) + return false; + } + return true; +} + static inline UINTN __attribute__((__unused__)) count_ucs2_strings(UINT8 *data, UINTN data_size) diff --git a/include/variables.h b/include/variables.h index deed269..8566a1a 100644 --- a/include/variables.h +++ b/include/variables.h @@ -1,5 +1,7 @@ -#include +#ifndef SHIM_VARIABLES_H +#define SHIM_VARIABLES_H +#include #include /* for SHA256_DIGEST_SIZE */ #define certlist_for_each_certentry(cl, cl_init, s, s_init) \ @@ -57,3 +59,5 @@ variable_enroll_hash(CHAR16 *var, EFI_GUID owner, EFI_STATUS variable_create_esl(void *cert, int cert_len, EFI_GUID *type, EFI_GUID *owner, void **out, int *outlen); + +#endif /* SHIM_VARIABLES_H */ diff --git a/include/version.h b/include/version.h deleted file mode 100644 index 09fd44a..0000000 --- a/include/version.h +++ /dev/null @@ -1,8 +0,0 @@ -#define VERSION "1.3.4" - -static void -version(const char *progname) -{ - printf("%s " VERSION "\n", progname); -} - diff --git a/include/wincert.h b/include/wincert.h index 68d1974..a3ce12a 100644 --- a/include/wincert.h +++ b/include/wincert.h @@ -1,5 +1,5 @@ -#ifndef _INC_WINCERT_H -#define _INC_WINCERT_H +#ifndef SHIM_WINCERT_H +#define SHIM_WINCERT_H /// /// The WIN_CERTIFICATE structure is part of the PE/COFF specification. @@ -30,4 +30,4 @@ typedef struct { } WIN_CERTIFICATE; -#endif +#endif /* SHIM_WINCERT_H */ diff --git a/lib/configtable.c b/lib/configtable.c index edf2ed7..df047f0 100644 --- a/lib/configtable.c +++ b/lib/configtable.c @@ -8,8 +8,7 @@ #include #include -#include -#include +#include "shim.h" void * configtable_get_table(EFI_GUID *guid) @@ -46,26 +45,26 @@ configtable_find_image(const EFI_DEVICE_PATH *DevicePath) int i; for (i = 0; i < entries; i++) { #ifdef DEBUG_CONFIG - Print(L"InfoSize = %d Action = %d\n", e->InfoSize, e->Action); + console_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", + console_print(L"Data: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]); d += 16; - Print(L"Data: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", + console_print(L"Data: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]); d += 16; - Print(L"Data: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", + console_print(L"Data: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]); d += 16; - Print(L"Data: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", + console_print(L"Data: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]); d += 16; - Print(L"Data: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", + console_print(L"Data: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]); d += 16; - Print(L"Data: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", + console_print(L"Data: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]); #endif CHAR16 *name = (CHAR16 *)(e->Data); @@ -77,33 +76,33 @@ configtable_find_image(const EFI_DEVICE_PATH *DevicePath) 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); + console_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 || ((unsigned)((dp->Length[1] << 8) + dp->Length[0]) > e->InfoSize)) { /* Parse error, table corrupt, bail */ - Print(L"Image Execution Information table corrupt\n"); + console_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); + console_print(L"Path: %s\n", DevicePathToStr(dp)); + console_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"); + console_print(L"Image Execution Information table corrupt\n"); break; } if (CompareMem(dp, (void *)DevicePath, Size) == 0) { #ifdef DEBUG_CONFIG - Print(L"***FOUND\n"); + console_print(L"***FOUND\n"); console_get_keystroke(); #endif return e; @@ -112,7 +111,7 @@ configtable_find_image(const EFI_DEVICE_PATH *DevicePath) } #ifdef DEBUG_CONFIG - Print(L"***NOT FOUND\n"); + console_print(L"***NOT FOUND\n"); console_get_keystroke(); #endif @@ -135,7 +134,7 @@ configtable_image_is_forbidden(const EFI_DEVICE_PATH *DevicePath) || 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"); + console_print(L"SIGNATURE IS IN DBX, FORBIDDING EXECUTION\n"); #endif return 1; } diff --git a/lib/console.c b/lib/console.c index cd8d1de..3aee41c 100644 --- a/lib/console.c +++ b/lib/console.c @@ -8,21 +8,10 @@ #include #include #include -#include -#include -#include -#include -#include -#include -static EFI_GUID SHIM_LOCK_GUID = { 0x605dab50, 0xe046, 0x4300, {0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23} }; +#include "shim.h" -static int min(int a, int b) -{ - if (a < b) - return a; - return b; -} +static UINT8 console_text_mode = 0; static int count_lines(CHAR16 *str_arr[]) @@ -47,17 +36,95 @@ SetMem16(CHAR16 *dst, UINT32 n, CHAR16 c) EFI_STATUS console_get_keystroke(EFI_INPUT_KEY *key) { + SIMPLE_INPUT_INTERFACE *ci = ST->ConIn; UINTN EventIndex; - EFI_STATUS status; + EFI_STATUS efi_status; 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); + gBS->WaitForEvent(1, &ci->WaitForKey, &EventIndex); + efi_status = ci->ReadKeyStroke(ci, key); + } while (efi_status == EFI_NOT_READY); - return status; + return efi_status; } +static VOID setup_console (int text) +{ + EFI_STATUS efi_status; + EFI_CONSOLE_CONTROL_PROTOCOL *concon; + static EFI_CONSOLE_CONTROL_SCREEN_MODE mode = + EfiConsoleControlScreenGraphics; + EFI_CONSOLE_CONTROL_SCREEN_MODE new_mode; + + efi_status = LibLocateProtocol(&EFI_CONSOLE_CONTROL_GUID, + (VOID **)&concon); + if (EFI_ERROR(efi_status)) + return; + + if (text) { + new_mode = EfiConsoleControlScreenText; + + efi_status = concon->GetMode(concon, &mode, 0, 0); + /* If that didn't work, assume it's graphics */ + if (EFI_ERROR(efi_status)) + mode = EfiConsoleControlScreenGraphics; + if (text < 0) { + if (mode == EfiConsoleControlScreenGraphics) + console_text_mode = 0; + else + console_text_mode = 1; + return; + } + } else { + new_mode = mode; + } + + concon->SetMode(concon, new_mode); + console_text_mode = text; +} + +VOID console_fini(VOID) +{ + if (console_text_mode) + setup_console(0); +} + +UINTN +console_print(const CHAR16 *fmt, ...) +{ + va_list args; + UINTN ret; + + if (!console_text_mode) + setup_console(1); + + va_start(args, fmt); + ret = VPrint(fmt, args); + va_end(args); + + return ret; +} + +UINTN +console_print_at(UINTN col, UINTN row, const CHAR16 *fmt, ...) +{ + SIMPLE_TEXT_OUTPUT_INTERFACE *co = ST->ConOut; + va_list args; + UINTN ret; + + if (!console_text_mode) + setup_console(1); + + co->SetCursorPosition(co, col, row); + + va_start(args, fmt); + ret = VPrint(fmt, args); + va_end(args); + + return ret; +} + + void console_print_box_at(CHAR16 *str_arr[], int highlight, int start_col, int start_row, @@ -72,7 +139,10 @@ console_print_box_at(CHAR16 *str_arr[], int highlight, if (lines == 0) return; - uefi_call_wrapper(co->QueryMode, 4, co, co->Mode->Mode, &cols, &rows); + if (!console_text_mode) + setup_console(1); + + co->QueryMode(co, co->Mode->Mode, &cols, &rows); /* last row on screen is unusable without scrolling, so ignore it */ rows--; @@ -92,8 +162,8 @@ console_print_box_at(CHAR16 *str_arr[], int highlight, start_row = 0; if (start_col > (int)cols || start_row > (int)rows) { - Print(L"Starting Position (%d,%d) is off screen\n", - start_col, start_row); + console_print(L"Starting Position (%d,%d) is off screen\n", + start_col, start_row); return; } if (size_cols + start_col > (int)cols) @@ -106,7 +176,7 @@ console_print_box_at(CHAR16 *str_arr[], int highlight, Line = AllocatePool((size_cols+1)*sizeof(CHAR16)); if (!Line) { - Print(L"Failed Allocation\n"); + console_print(L"Failed Allocation\n"); return; } @@ -115,8 +185,8 @@ console_print_box_at(CHAR16 *str_arr[], int highlight, 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); + co->SetCursorPosition(co, start_col, start_row); + co->OutputString(co, Line); int start; if (offset == 0) @@ -147,19 +217,21 @@ console_print_box_at(CHAR16 *str_arr[], int highlight, 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); + co->SetAttribute(co, EFI_LIGHTGRAY | + EFI_BACKGROUND_BLACK); + co->SetCursorPosition(co, start_col, i); + co->OutputString(co, Line); if (line >= 0 && line == highlight) - uefi_call_wrapper(co->SetAttribute, 2, co, EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE); + co->SetAttribute(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); + co->SetCursorPosition(co, start_col, i); + co->OutputString(co, Line); FreePool (Line); @@ -172,18 +244,22 @@ console_print_box(CHAR16 *str_arr[], int highlight) SIMPLE_TEXT_OUTPUT_INTERFACE *co = ST->ConOut; EFI_INPUT_KEY key; + if (!console_text_mode) + setup_console(1); + 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); + co->EnableCursor(co, FALSE); + co->SetAttribute(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(&key); - 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); + co->EnableCursor(co, SavedConsoleMode.CursorVisible); + co->SetCursorPosition(co, SavedConsoleMode.CursorColumn, + SavedConsoleMode.CursorRow); + co->SetAttribute(co, SavedConsoleMode.Attribute); } int @@ -192,7 +268,7 @@ console_select(CHAR16 *title[], CHAR16* selectors[], unsigned int start) SIMPLE_TEXT_OUTPUT_MODE SavedConsoleMode; SIMPLE_TEXT_OUTPUT_INTERFACE *co = ST->ConOut; EFI_INPUT_KEY k; - EFI_STATUS status; + EFI_STATUS efi_status; int selector; unsigned int selector_lines = count_lines(selectors); int selector_max_cols = 0; @@ -201,7 +277,10 @@ console_select(CHAR16 *title[], CHAR16* selectors[], unsigned int start) unsigned int selector_offset; UINTN cols, rows; - uefi_call_wrapper(co->QueryMode, 4, co, co->Mode->Mode, &cols, &rows); + if (!console_text_mode) + setup_console(1); + + co->QueryMode(co, co->Mode->Mode, &cols, &rows); for (i = 0; i < selector_lines; i++) { int len = StrLen(selectors[i]); @@ -210,8 +289,6 @@ console_select(CHAR16 *title[], CHAR16* selectors[], unsigned int start) selector_max_cols = len; } - if (start < 0) - start = 0; if (start >= selector_lines) start = selector_lines - 1; @@ -238,8 +315,8 @@ console_select(CHAR16 *title[], CHAR16* selectors[], unsigned int start) } 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); + co->EnableCursor(co, FALSE); + co->SetAttribute(co, EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE); console_print_box_at(title, -1, 0, 0, -1, -1, 1, count_lines(title)); @@ -247,9 +324,10 @@ console_select(CHAR16 *title[], CHAR16* selectors[], unsigned int start) size_cols, size_rows, 0, lines); do { - status = console_get_keystroke(&k); - if (EFI_ERROR (status)) { - Print(L"Failed to read the keystroke: %r", status); + efi_status = console_get_keystroke(&k); + if (EFI_ERROR (efi_status)) { + console_print(L"Failed to read the keystroke: %r", + efi_status); selector = -1; break; } @@ -277,9 +355,10 @@ console_select(CHAR16 *title[], CHAR16* selectors[], unsigned 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->SetCursorPosition, 3, co, SavedConsoleMode.CursorColumn, SavedConsoleMode.CursorRow); - uefi_call_wrapper(co->SetAttribute, 2, co, SavedConsoleMode.Attribute); + co->EnableCursor(co, SavedConsoleMode.CursorVisible); + co->SetCursorPosition(co, SavedConsoleMode.CursorColumn, + SavedConsoleMode.CursorRow); + co->SetAttribute(co, SavedConsoleMode.Attribute); if (selector < 0) /* ESC pressed */ @@ -291,13 +370,15 @@ console_select(CHAR16 *title[], CHAR16* selectors[], unsigned int start) int console_yes_no(CHAR16 *str_arr[]) { - return console_select(str_arr, (CHAR16 *[]){ L"No", L"Yes", NULL }, 0); + CHAR16 *yes_no[] = { L"No", L"Yes", NULL }; + return console_select(str_arr, yes_no, 0); } void console_alertbox(CHAR16 **title) { - console_select(title, (CHAR16 *[]){ L"OK", 0 }, 0); + CHAR16 *okay[] = { L"OK", NULL }; + console_select(title, okay, 0); } void @@ -374,13 +455,13 @@ static struct { static CHAR16 * err_string ( - IN EFI_STATUS Status + IN EFI_STATUS efi_status ) { UINTN Index; for (Index = 0; error_table[Index].Desc; Index +=1) { - if (error_table[Index].Code == Status) { + if (error_table[Index].Code == efi_status) { return error_table[Index].Desc; } } @@ -389,7 +470,7 @@ err_string ( } void -console_error(CHAR16 *err, EFI_STATUS status) +console_error(CHAR16 *err, EFI_STATUS efi_status) { CHAR16 **err_arr = (CHAR16 *[]){ L"ERROR", @@ -399,8 +480,8 @@ console_error(CHAR16 *err, EFI_STATUS status) }; CHAR16 str[512]; - SPrint(str, sizeof(str), L"%s: (0x%x) %s", err, status, err_string(status)); - + SPrint(str, sizeof(str), L"%s: (0x%x) %s", err, efi_status, + err_string(efi_status)); err_arr[2] = str; @@ -412,80 +493,69 @@ console_reset(void) { SIMPLE_TEXT_OUTPUT_INTERFACE *co = ST->ConOut; - uefi_call_wrapper(co->Reset, 2, co, TRUE); + if (!console_text_mode) + setup_console(1); + + co->Reset(co, TRUE); /* set mode 0 - required to be 80x25 */ - uefi_call_wrapper(co->SetMode, 2, co, 0); - uefi_call_wrapper(co->ClearScreen, 1, co); + co->SetMode(co, 0); + co->ClearScreen(co); } -UINT8 verbose; +UINT32 verbose = 0; VOID setup_verbosity(VOID) { - EFI_STATUS status; - EFI_GUID guid = SHIM_LOCK_GUID; - UINT8 verbose_check; + EFI_STATUS efi_status; + UINT8 *verbose_check_ptr = NULL; UINTN verbose_check_size; - verbose_check_size = 1; - status = get_variable(L"SHIM_VERBOSE", (void *)&verbose_check, - &verbose_check_size, guid); - verbose = 0; - if (!EFI_ERROR(status)) - verbose = verbose_check; -} - -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; + verbose_check_size = sizeof(verbose); + efi_status = get_variable(L"SHIM_VERBOSE", &verbose_check_ptr, + &verbose_check_size, SHIM_LOCK_GUID); + if (!EFI_ERROR(efi_status)) { + verbose = *(__typeof__(verbose) *)verbose_check_ptr; + verbose &= (1ULL << (8 * verbose_check_size)) - 1ULL; + FreePool(verbose_check_ptr); } - uefi_call_wrapper(concon->SetMode, 2, concon, new_mode); + setup_console(-1); } +/* Included here because they mess up the definition of va_list and friends */ +#include +#include +#include + static int print_errors_cb(const char *str, size_t len, void *u) { - Print(L"%a", str); + console_print(L"%a", str); return len; } EFI_STATUS -print_crypto_errors(EFI_STATUS rc, char *file, const char *func, int line) +print_crypto_errors(EFI_STATUS efi_status, + char *file, const char *func, int line) { - if (!(verbose && EFI_ERROR(rc))) - return rc; + if (!(verbose && EFI_ERROR(efi_status))) + return efi_status; - Print(L"SSL Error: %a:%d %a(): %r\n", file, line, func, rc); + console_print(L"SSL Error: %a:%d %a(): %r\n", file, line, func, + efi_status); ERR_print_errors_cb(print_errors_cb, NULL); - return rc; + return efi_status; } VOID msleep(unsigned long msecs) { - uefi_call_wrapper(BS->Stall, 1, msecs); + gBS->Stall(msecs); } + +/* This is used in various things to determine if we should print to the + * console */ +UINT8 in_protocol = 0; diff --git a/lib/execute.c b/lib/execute.c index 89328c6..3aff28a 100644 --- a/lib/execute.c +++ b/lib/execute.c @@ -41,8 +41,7 @@ #include #include -#include -#include +#include "shim.h" EFI_STATUS generate_path(CHAR16* name, EFI_LOADED_IMAGE *li, EFI_DEVICE_PATH **path, CHAR16 **PathName) @@ -74,7 +73,7 @@ generate_path(CHAR16* name, EFI_LOADED_IMAGE *li, EFI_DEVICE_PATH **path, CHAR16 *PathName = AllocatePool((pathlen + 1 + StrLen(name))*sizeof(CHAR16)); if (!*PathName) { - Print(L"Failed to allocate path buffer\n"); + console_print(L"Failed to allocate path buffer\n"); efi_status = EFI_OUT_OF_RESOURCES; goto error; } @@ -96,32 +95,30 @@ error: EFI_STATUS execute(EFI_HANDLE image, CHAR16 *name) { - EFI_STATUS status; + EFI_STATUS efi_status; EFI_HANDLE h; EFI_LOADED_IMAGE *li; EFI_DEVICE_PATH *devpath; CHAR16 *PathName; - status = uefi_call_wrapper(BS->HandleProtocol, 3, image, - &IMAGE_PROTOCOL, (void **)&li); - if (status != EFI_SUCCESS) - return status; + efi_status = gBS->HandleProtocol(image, &IMAGE_PROTOCOL, + (void **) &li); + if (EFI_ERROR(efi_status)) + return efi_status; - - status = generate_path(name, li, &devpath, &PathName); - if (status != EFI_SUCCESS) - return status; + efi_status = generate_path(name, li, &devpath, &PathName); + if (EFI_ERROR(efi_status)) + return efi_status; - status = uefi_call_wrapper(BS->LoadImage, 6, FALSE, image, - devpath, NULL, 0, &h); - if (status != EFI_SUCCESS) + efi_status = gBS->LoadImage(FALSE, image, devpath, NULL, 0, &h); + if (EFI_ERROR(efi_status)) goto out; - - status = uefi_call_wrapper(BS->StartImage, 3, h, NULL, NULL); - uefi_call_wrapper(BS->UnloadImage, 1, h); + + efi_status = gBS->StartImage(h, NULL, NULL); + gBS->UnloadImage(h); out: FreePool(PathName); FreePool(devpath); - return status; + return efi_status; } diff --git a/lib/guid.c b/lib/guid.c index 5f5a03f..57c02fb 100644 --- a/lib/guid.c +++ b/lib/guid.c @@ -4,19 +4,36 @@ * see COPYING file */ -#include +#include "shim.h" -/* all the necessary guids */ +EFI_GUID BDS_GUID = { 0x8108ac4e, 0x9f11, 0x4d59, { 0x85, 0x0e, 0xe2, 0x1a, 0x52, 0x2c, 0x59, 0xb2 } }; 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_FILE_INFO_GUID = EFI_FILE_INFO_ID; +EFI_GUID EFI_FILE_SYSTEM_INFO_GUID = EFI_FILE_SYSTEM_INFO_ID; +EFI_GUID EFI_CERT_RSA2048_GUID = { 0x3c5766e8, 0x269c, 0x4e34, {0xaa, 0x14, 0xed, 0x77, 0x6e, 0x85, 0xb3, 0xb6} }; 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 EFI_CERT_SHA224_GUID = { 0xb6e5233, 0xa65c, 0x44c9, {0x94, 0x7, 0xd9, 0xab, 0x83, 0xbf, 0xc8, 0xbd} }; +EFI_GUID EFI_CERT_SHA384_GUID = { 0xff3e5307, 0x9fd0, 0x48c9, {0x85, 0xf1, 0x8a, 0xd5, 0x6c, 0x70, 0x1e, 0x1} }; +EFI_GUID EFI_CERT_SHA512_GUID = { 0x93e0fae, 0xa6c4, 0x4f50, {0x9f, 0x1b, 0xd4, 0x1e, 0x2b, 0x89, 0xc1, 0x9a} }; +EFI_GUID EFI_CERT_TYPE_PKCS7_GUID = { 0x4aafd29d, 0x68df, 0x49ee, {0x8a, 0xa9, 0x34, 0x7d, 0x37, 0x56, 0x65, 0xa7} }; +EFI_GUID EFI_CERT_TYPE_RSA2048_SHA256_GUID = { 0xa7717414, 0xc616, 0x4977, {0x94, 0x20, 0x84, 0x47, 0x12, 0xa7, 0x35, 0xbf } }; +EFI_GUID EFI_CERT_TYPE_X509_GUID = { 0xa5c059a1, 0x94e4, 0x4aa7, {0x87, 0xb5, 0xab, 0x15, 0x5c, 0x2b, 0xf0, 0x72} }; +EFI_GUID EFI_CONSOLE_CONTROL_GUID = { 0xf42f7782, 0x12e, 0x4c12, {0x99, 0x56, 0x49, 0xf9, 0x43, 0x4, 0xf7, 0x21} }; +EFI_GUID EFI_HTTP_BINDING_GUID = { 0xbdc8e6af, 0xd9bc, 0x4379, {0xa7, 0x2a, 0xe0, 0xc4, 0xe7, 0x5d, 0xae, 0x1c } }; +EFI_GUID EFI_HTTP_PROTOCOL_GUID = { 0x7a59b29b, 0x910b, 0x4171, {0x82, 0x42, 0xa8, 0x5a, 0x0d, 0xf2, 0x5b, 0x5b } }; +EFI_GUID EFI_IP4_CONFIG2_GUID = { 0x5b446ed1, 0xe30b, 0x4faa, {0x87, 0x1a, 0x36, 0x54, 0xec, 0xa3, 0x60, 0x80 } }; +EFI_GUID EFI_IP6_CONFIG_GUID = { 0x937fe521, 0x95ae, 0x4d1a, {0x89, 0x29, 0x48, 0xbc, 0xd9, 0x0a, 0xd3, 0x1a } }; +EFI_GUID EFI_LOADED_IMAGE_GUID = EFI_LOADED_IMAGE_PROTOCOL_GUID; +EFI_GUID EFI_TPM_GUID = { 0xf541796d, 0xa62e, 0x4954, {0xa7, 0x75, 0x95, 0x84, 0xf6, 0x1b, 0x9c, 0xdd } }; +EFI_GUID EFI_TPM2_GUID = { 0x607f766c, 0x7455, 0x42be, {0x93, 0x0b, 0xe4, 0xd7, 0x6d, 0xb2, 0x72, 0x0f } }; +EFI_GUID EFI_SECURE_BOOT_DB_GUID = { 0xd719b2cb, 0x3d3a, 0x4596, { 0xa3, 0xbc, 0xda, 0xd0, 0x0e, 0x67, 0x65, 0x6f } }; +EFI_GUID EFI_SIMPLE_FILE_SYSTEM_GUID = SIMPLE_FILE_SYSTEM_PROTOCOL; EFI_GUID SECURITY_PROTOCOL_GUID = { 0xA46423E3, 0x4617, 0x49f1, {0xB9, 0xFF, 0xD1, 0xBF, 0xA9, 0x11, 0x58, 0x39 } }; EFI_GUID SECURITY2_PROTOCOL_GUID = { 0x94ab2f58, 0x1438, 0x4ef1, {0x91, 0x52, 0x18, 0x94, 0x1a, 0x3a, 0x0e, 0x68 } }; +EFI_GUID SHIM_LOCK_GUID = {0x605dab50, 0xe046, 0x4300, {0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23 } }; diff --git a/lib/security_policy.c b/lib/security_policy.c index 53a2580..211f1cf 100644 --- a/lib/security_policy.c +++ b/lib/security_policy.c @@ -9,7 +9,8 @@ #include #include -#include +#include "shim.h" + #include #include #include @@ -80,16 +81,14 @@ security2_policy_authentication ( BOOLEAN BootPolicy ) { - EFI_STATUS status, auth; + EFI_STATUS efi_status, auth; /* Chain original security policy */ - status = uefi_call_wrapper(es2fa, 5, This, DevicePath, FileBuffer, - FileSize, BootPolicy); - + efi_status = es2fa(This, DevicePath, FileBuffer, FileSize, BootPolicy); /* if OK, don't bother with MOK check */ - if (status == EFI_SUCCESS) - return status; + if (!EFI_ERROR(efi_status)) + return efi_status; if (extra_check) auth = extra_check(FileBuffer, FileSize); @@ -100,7 +99,7 @@ security2_policy_authentication ( /* return previous status, which is the correct one * for the platform: may be either EFI_ACCESS_DENIED * or EFI_SECURITY_VIOLATION */ - return status; + return efi_status; return auth; } @@ -112,7 +111,7 @@ security_policy_authentication ( const EFI_DEVICE_PATH_PROTOCOL *DevicePathConst ) { - EFI_STATUS status, fail_status; + EFI_STATUS efi_status, fail_status; EFI_DEVICE_PATH *DevPath = DuplicateDevicePath((EFI_DEVICE_PATH *)DevicePathConst), *OrigDevPath = DevPath; @@ -121,50 +120,49 @@ security_policy_authentication ( VOID *FileBuffer; UINTN FileSize; CHAR16* DevPathStr; + EFI_GUID SIMPLE_FS_PROTOCOL = EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID; /* Chain original security policy */ - status = uefi_call_wrapper(esfas, 3, This, AuthenticationStatus, - DevicePathConst); - + efi_status = esfas(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) + if (!EFI_ERROR(efi_status)) goto out; /* capture failure status: may be either EFI_ACCESS_DENIED or * EFI_SECURITY_VIOLATION */ - fail_status = status; + fail_status = efi_status; - status = uefi_call_wrapper(BS->LocateDevicePath, 3, - &SIMPLE_FS_PROTOCOL, &DevPath, &h); - if (status != EFI_SUCCESS) + efi_status = gBS->LocateDevicePath(&SIMPLE_FS_PROTOCOL, &DevPath, &h); + if (EFI_ERROR(efi_status)) goto out; DevPathStr = DevicePathToStr(DevPath); - status = simple_file_open_by_handle(h, DevPathStr, &f, - EFI_FILE_MODE_READ); + efi_status = simple_file_open_by_handle(h, DevPathStr, &f, + EFI_FILE_MODE_READ); FreePool(DevPathStr); - if (status != EFI_SUCCESS) + if (EFI_ERROR(efi_status)) goto out; - status = simple_file_read_all(f, &FileSize, &FileBuffer); - simple_file_close(f); - if (status != EFI_SUCCESS) + efi_status = simple_file_read_all(f, &FileSize, &FileBuffer); + f->Close(f); + if (EFI_ERROR(efi_status)) goto out; if (extra_check) - status = extra_check(FileBuffer, FileSize); + efi_status = extra_check(FileBuffer, FileSize); else - status = EFI_SECURITY_VIOLATION; + efi_status = EFI_SECURITY_VIOLATION; FreePool(FileBuffer); - if (status == EFI_ACCESS_DENIED || status == EFI_SECURITY_VIOLATION) + if (efi_status == EFI_ACCESS_DENIED || + efi_status == EFI_SECURITY_VIOLATION) /* return what the platform originally said */ - status = fail_status; + efi_status = fail_status; out: FreePool(OrigDevPath); - return status; + return efi_status; } @@ -265,7 +263,7 @@ security_policy_install(SecurityHook hook) { EFI_SECURITY_PROTOCOL *security_protocol; EFI_SECURITY2_PROTOCOL *security2_protocol = NULL; - EFI_STATUS status; + EFI_STATUS efi_status; if (esfas) /* Already Installed */ @@ -274,20 +272,18 @@ security_policy_install(SecurityHook hook) /* 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, + LibLocateProtocol(&SECURITY2_PROTOCOL_GUID, (VOID **) &security2_protocol); - status = uefi_call_wrapper(BS->LocateProtocol, 3, - &SECURITY_PROTOCOL_GUID, NULL, - (VOID **) &security_protocol); - if (status != EFI_SUCCESS) + efi_status = LibLocateProtocol(&SECURITY_PROTOCOL_GUID, + (VOID **) &security_protocol); + if (EFI_ERROR(efi_status)) /* This one is mandatory, so there's a serious problem */ - return status; + return efi_status; if (security2_protocol) { es2fa = security2_protocol->FileAuthentication; - security2_protocol->FileAuthentication = + security2_protocol->FileAuthentication = (EFI_SECURITY2_FILE_AUTHENTICATION) thunk_security2_policy_authentication; } @@ -304,17 +300,15 @@ security_policy_install(SecurityHook hook) EFI_STATUS security_policy_uninstall(void) { - EFI_STATUS status; + EFI_STATUS efi_status; if (esfas) { EFI_SECURITY_PROTOCOL *security_protocol; - status = uefi_call_wrapper(BS->LocateProtocol, 3, - &SECURITY_PROTOCOL_GUID, NULL, - (VOID **) &security_protocol); - - if (status != EFI_SUCCESS) - return status; + efi_status = LibLocateProtocol(&SECURITY_PROTOCOL_GUID, + (VOID **) &security_protocol); + if (EFI_ERROR(efi_status)) + return efi_status; security_protocol->FileAuthenticationState = esfas; esfas = NULL; @@ -326,12 +320,10 @@ security_policy_uninstall(void) if (es2fa) { EFI_SECURITY2_PROTOCOL *security2_protocol; - status = uefi_call_wrapper(BS->LocateProtocol, 3, - &SECURITY2_PROTOCOL_GUID, NULL, - (VOID **) &security2_protocol); - - if (status != EFI_SUCCESS) - return status; + efi_status = LibLocateProtocol(&SECURITY2_PROTOCOL_GUID, + (VOID **) &security2_protocol); + if (EFI_ERROR(efi_status)) + return efi_status; security2_protocol->FileAuthentication = es2fa; es2fa = NULL; diff --git a/lib/shell.c b/lib/shell.c index afd3952..e46e7fd 100644 --- a/lib/shell.c +++ b/lib/shell.c @@ -8,22 +8,23 @@ #include #include -#include +#include "shim.h" EFI_STATUS argsplit(EFI_HANDLE image, int *argc, CHAR16*** ARGV) { unsigned int i, count = 1; - EFI_STATUS status; + EFI_STATUS efi_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; + efi_status = gBS->HandleProtocol(image, &LoadedImageProtocol, + (VOID **) &info); + if (EFI_ERROR(efi_status)) { + console_print(L"Failed to get arguments\n"); + return efi_status; } for (i = 0; i < info->LoadOptionsSize; i += 2) { @@ -33,7 +34,8 @@ argsplit(EFI_HANDLE image, int *argc, CHAR16*** ARGV) } } - (*argc)++; /* we counted spaces, so add one for initial */ + /* we counted spaces, so add one for initial */ + (*argc)++; *ARGV = AllocatePool(*argc * sizeof(**ARGV)); if (!*ARGV) { diff --git a/lib/simple_file.c b/lib/simple_file.c index d345d87..3bf92ed 100644 --- a/lib/simple_file.c +++ b/lib/simple_file.c @@ -7,15 +7,7 @@ #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; +#include "shim.h" EFI_STATUS simple_file_open_by_handle(EFI_HANDLE device, CHAR16 *name, EFI_FILE **file, UINT64 mode) @@ -24,23 +16,21 @@ simple_file_open_by_handle(EFI_HANDLE device, CHAR16 *name, EFI_FILE **file, UIN EFI_FILE_IO_INTERFACE *drive; EFI_FILE *root; - efi_status = uefi_call_wrapper(BS->HandleProtocol, 3, device, - &SIMPLE_FS_PROTOCOL, (void **)&drive); - - if (efi_status != EFI_SUCCESS) { - Print(L"Unable to find simple file protocol (%d)\n", efi_status); + efi_status = gBS->HandleProtocol(device, &EFI_SIMPLE_FILE_SYSTEM_GUID, + (void **)&drive); + if (EFI_ERROR(efi_status)) { + console_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); + efi_status = drive->OpenVolume(drive, &root); + if (EFI_ERROR(efi_status)) { + console_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); + efi_status = root->Open(root, file, name, mode, 0); error: return efi_status; @@ -55,16 +45,14 @@ simple_file_open(EFI_HANDLE image, CHAR16 *name, EFI_FILE **file, UINT64 mode) EFI_DEVICE_PATH *loadpath = NULL; CHAR16 *PathName = NULL; - efi_status = uefi_call_wrapper(BS->HandleProtocol, 3, image, - &IMAGE_PROTOCOL, (void **)&li); - - if (efi_status != EFI_SUCCESS) + efi_status = gBS->HandleProtocol(image, &IMAGE_PROTOCOL, + (void **) &li); + if (EFI_ERROR(efi_status)) 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); + if (EFI_ERROR(efi_status)) { + console_print(L"Unable to generate load path for %s\n", name); return efi_status; } @@ -82,33 +70,32 @@ 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; + EFI_STATUS efi_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"); + + efi_status = file->GetInfo(file, &EFI_FILE_INFO_GUID, &size, fi); + if (EFI_ERROR(efi_status)) { + console_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; + console_print(L"Not a directory %s\n", name); + efi_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) + efi_status = file->Read(file, &len, buf); + if (EFI_ERROR(efi_status) || len == 0) break; (*count)++; size += len; } - uefi_call_wrapper(file->SetPosition, 2, file, 0); + file->SetPosition(file, 0); char *ptr = AllocatePool(size); *entries = (EFI_FILE_INFO *)ptr; @@ -117,18 +104,18 @@ simple_dir_read_all_by_handle(EFI_HANDLE image, EFI_FILE *file, CHAR16* name, EF int i; for (i = 0; i < *count; i++) { UINTN len = size; - uefi_call_wrapper(file->Read, 3, file, &len, ptr); + file->Read(file, &len, ptr); ptr += len; size -= len; } - status = EFI_SUCCESS; + efi_status = EFI_SUCCESS; out: - simple_file_close(file); - if (status != EFI_SUCCESS && *entries) { + file->Close(file); + if (EFI_ERROR(efi_status) && *entries) { FreePool(*entries); *entries = NULL; } - return status; + return efi_status; } EFI_STATUS @@ -136,12 +123,12 @@ simple_dir_read_all(EFI_HANDLE image, CHAR16 *name, EFI_FILE_INFO **entries, int *count) { EFI_FILE *file; - EFI_STATUS status; + EFI_STATUS efi_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; + efi_status = simple_file_open(image, name, &file, EFI_FILE_MODE_READ); + if (EFI_ERROR(efi_status)) { + console_print(L"failed to open file %s: %d\n", name, efi_status); + return efi_status; } return simple_dir_read_all_by_handle(image, file, name, entries, count); @@ -156,12 +143,10 @@ simple_file_read_all(EFI_FILE *file, UINTN *size, void **buffer) *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"); + efi_status = file->GetInfo(file, &EFI_FILE_INFO_GUID, size, fi); + if (EFI_ERROR(efi_status)) { + console_print(L"Failed to get file info\n"); return efi_status; } @@ -169,11 +154,11 @@ simple_file_read_all(EFI_FILE *file, UINTN *size, void **buffer) *buffer = AllocatePool(*size); if (!*buffer) { - Print(L"Failed to allocate buffer of size %d\n", *size); + console_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); + efi_status = file->Read(file, size, *buffer); return efi_status; } @@ -183,29 +168,24 @@ 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); - + efi_status = file->Write(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; + EFI_STATUS efi_status; CHAR16 **entries; int val; - uefi_call_wrapper(BS->LocateHandleBuffer, 5, ByProtocol, - &SIMPLE_FS_PROTOCOL, NULL, &count, &vol_handles); - + efi_status = gBS->LocateHandleBuffer(ByProtocol, + &EFI_SIMPLE_FILE_SYSTEM_GUID, + NULL, &count, &vol_handles); + if (EFI_ERROR(efi_status)) + return efi_status; if (!count || !vol_handles) return EFI_NOT_FOUND; @@ -221,25 +201,23 @@ simple_volume_selector(CHAR16 **title, CHAR16 **selected, EFI_HANDLE *h) CHAR16 *name; EFI_FILE_IO_INTERFACE *drive; - status = uefi_call_wrapper(BS->HandleProtocol, 3, - vol_handles[i], - &SIMPLE_FS_PROTOCOL, - (void **)&drive); - if (status != EFI_SUCCESS || !drive) + efi_status = gBS->HandleProtocol(vol_handles[i], + &EFI_SIMPLE_FILE_SYSTEM_GUID, + (void **) &drive); + if (EFI_ERROR(efi_status) || !drive) continue; - status = uefi_call_wrapper(drive->OpenVolume, 2, drive, &root); - if (status != EFI_SUCCESS) + efi_status = drive->OpenVolume(drive, &root); + if (EFI_ERROR(efi_status)) continue; - status = uefi_call_wrapper(root->GetInfo, 4, root, &FS_INFO, + efi_status = root->GetInfo(root, &EFI_FILE_SYSTEM_INFO_GUID, &size, fi); - if (status != EFI_SUCCESS) + if (EFI_ERROR(efi_status)) continue; name = fi->VolumeLabel; - - if (!name || StrLen(name) == 0 || StrCmp(name, L" ") == 0) + if (!name || StrLen(name) == 0 || StrCmp(name, L" ") == 0) name = DevicePathToStr(DevicePathFromHandle(vol_handles[i])); entries[i] = AllocatePool((StrLen(name) + 2) * sizeof(CHAR16)); @@ -269,7 +247,6 @@ simple_volume_selector(CHAR16 **title, CHAR16 **selected, EFI_HANDLE *h) FreePool(entries); FreePool(vol_handles); - return EFI_SUCCESS; } @@ -277,7 +254,7 @@ EFI_STATUS simple_dir_filter(EFI_HANDLE image, CHAR16 *name, CHAR16 *filter, CHAR16 ***result, int *count, EFI_FILE_INFO **entries) { - EFI_STATUS status; + EFI_STATUS efi_status; int tot, offs = StrLen(filter), i, c, filtercount = 1; EFI_FILE_INFO *next; void *ptr; @@ -308,9 +285,8 @@ simple_dir_filter(EFI_HANDLE image, CHAR16 *name, CHAR16 *filter, *count = 0; - status = simple_dir_read_all(image, name, entries, &tot); - - if (status != EFI_SUCCESS) + efi_status = simple_dir_read_all(image, name, entries, &tot); + if (EFI_ERROR(efi_status)) goto out; ptr = next = *entries; @@ -326,7 +302,7 @@ simple_dir_filter(EFI_HANDLE image, CHAR16 *name, CHAR16 *filter, break; } } - ptr += OFFSET_OF(EFI_FILE_INFO, FileName) + (len + 1)*sizeof(CHAR16); + ptr += offsetof(EFI_FILE_INFO, FileName) + (len + 1)*sizeof(CHAR16); next = ptr; } if (*count) @@ -347,7 +323,7 @@ simple_dir_filter(EFI_HANDLE image, CHAR16 *name, CHAR16 *filter, if (next->Attribute & EFI_FILE_DIRECTORY) { (*result)[(*count)] = PoolPrint(L"%s/", next->FileName); if (!(*result)[(*count)]) { - Print(L"Failed to allocate buffer"); + console_print(L"Failed to allocate buffer"); return EFI_OUT_OF_RESOURCES; } (*count)++; @@ -360,7 +336,7 @@ simple_dir_filter(EFI_HANDLE image, CHAR16 *name, CHAR16 *filter, if (StrCmp(&next->FileName[len - offs], filterarr[c]) == 0) { (*result)[(*count)] = StrDuplicate(next->FileName); if (!(*result)[(*count)]) { - Print(L"Failed to allocate buffer"); + console_print(L"Failed to allocate buffer"); return EFI_OUT_OF_RESOURCES; } (*count)++; @@ -370,7 +346,7 @@ simple_dir_filter(EFI_HANDLE image, CHAR16 *name, CHAR16 *filter, break; } - next: + next: if (StrCmp(next->FileName, L"..") == 0) { /* place .. directory first */ CHAR16 *tmp = (*result)[(*count) - 1]; @@ -379,7 +355,7 @@ simple_dir_filter(EFI_HANDLE image, CHAR16 *name, CHAR16 *filter, (*result)[0] = tmp; } - ptr += OFFSET_OF(EFI_FILE_INFO, FileName) + (len + 1)*sizeof(CHAR16); + ptr += offsetof(EFI_FILE_INFO, FileName) + (len + 1)*sizeof(CHAR16); next = ptr; } if (*count == 0) { @@ -387,10 +363,10 @@ simple_dir_filter(EFI_HANDLE image, CHAR16 *name, CHAR16 *filter, (*result)[(*count)++] = L"./"; } (*result)[*count] = NULL; - status = EFI_SUCCESS; + efi_status = EFI_SUCCESS; out: - if (status != EFI_SUCCESS) { + if (EFI_ERROR(efi_status)) { if (*entries) FreePool(*entries); *entries = NULL; @@ -398,7 +374,7 @@ simple_dir_filter(EFI_HANDLE image, CHAR16 *name, CHAR16 *filter, FreePool(*result); *result = NULL; } - return status; + return efi_status; } static void @@ -411,12 +387,12 @@ free_entries(CHAR16 **entries, int count) } void -simple_file_selector(EFI_HANDLE *im, CHAR16 **title, CHAR16 *name, - CHAR16 *filter, CHAR16 **result) +simple_file_selector(EFI_HANDLE * im, CHAR16 ** title, CHAR16 * name, + CHAR16 * filter, CHAR16 ** result) { - EFI_STATUS status; + EFI_STATUS efi_status; CHAR16 **entries = NULL; - EFI_FILE_INFO *dmp; + EFI_FILE_INFO *dmp = NULL; int count, select, len; CHAR16 *newname, *selected; @@ -436,18 +412,18 @@ simple_file_selector(EFI_HANDLE *im, CHAR16 **title, CHAR16 *name, *im = h; } - newname = AllocatePool((StrLen(name) + 1)*sizeof(CHAR16)); + 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; +redo: + efi_status = simple_dir_filter(*im, name, filter, &entries, &count, + &dmp); + if (EFI_ERROR(efi_status)) + goto out_free; select = console_select(title, entries, 0); if (select < 0) @@ -469,9 +445,6 @@ simple_file_selector(EFI_HANDLE *im, CHAR16 **title, CHAR16 *name, } else if (StrCmp(selected, L"../") == 0) { int i; - i = StrLen(name) - 1; - - for (i = StrLen(name); i > 0; --i) { if (name[i] == '\\') break; @@ -489,11 +462,12 @@ simple_file_selector(EFI_HANDLE *im, CHAR16 **title, CHAR16 *name, goto redo; } } - newname = AllocatePool((StrLen(name) + len + 2)*sizeof(CHAR16)); + 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); @@ -509,7 +483,7 @@ simple_file_selector(EFI_HANDLE *im, CHAR16 **title, CHAR16 *name, goto redo; } - *result = AllocatePool((StrLen(name) + len + 2)*sizeof(CHAR16)); + *result = AllocatePool((StrLen(name) + len + 2) * sizeof(CHAR16)); if (*result) { StrCpy(*result, name); if (name[StrLen(name) - 1] != '\\') @@ -517,12 +491,12 @@ simple_file_selector(EFI_HANDLE *im, CHAR16 **title, CHAR16 *name, StrCat(*result, selected); } - out_free: - FreePool(dmp); +out_free: + if (dmp) + FreePool(dmp); if (entries) { free_entries(entries, count); FreePool(entries); } - out_free_name: FreePool(name); } diff --git a/lib/variables.c b/lib/variables.c index 59d7d05..9c2e7d0 100644 --- a/lib/variables.c +++ b/lib/variables.c @@ -11,23 +11,18 @@ * 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 + * 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 "shim.h" EFI_STATUS variable_create_esl(void *cert, int cert_len, EFI_GUID *type, EFI_GUID *owner, @@ -56,76 +51,75 @@ variable_create_esl(void *cert, int cert_len, EFI_GUID *type, EFI_GUID *owner, return EFI_SUCCESS; } - EFI_STATUS -CreateTimeBasedPayload ( - IN OUT UINTN *DataSize, - IN OUT UINT8 **Data - ) +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; - } + EFI_STATUS efi_status; + UINT8 *NewData; + UINT8 *Payload; + UINTN PayloadSize; + EFI_VARIABLE_AUTHENTICATION_2 *DescriptorData; + UINTN DescriptorSize; + EFI_TIME Time; - if ((Payload != NULL) && (PayloadSize != 0)) { - CopyMem (NewData + DescriptorSize, Payload, PayloadSize); - } + 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; - DescriptorData = (EFI_VARIABLE_AUTHENTICATION_2 *) (NewData); + DescriptorSize = offsetof(EFI_VARIABLE_AUTHENTICATION_2, AuthInfo) + + offsetof(WIN_CERTIFICATE_UEFI_GUID, CertData); + NewData = (UINT8 *) AllocateZeroPool(DescriptorSize + PayloadSize); + if (NewData == NULL) { + return EFI_OUT_OF_RESOURCES; + } - 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 ((Payload != NULL) && (PayloadSize != 0)) { + CopyMem(NewData + DescriptorSize, Payload, PayloadSize); + } + + DescriptorData = (EFI_VARIABLE_AUTHENTICATION_2 *) (NewData); + + ZeroMem(&Time, sizeof(EFI_TIME)); + efi_status = gRT->GetTime(&Time, NULL); + if (EFI_ERROR(efi_status)) { + FreePool(NewData); + return efi_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 = + offsetof(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_PKCS7_GUID; + + /* + * 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); - } + if (Payload != NULL) { + FreePool(Payload); + } #endif - - *DataSize = DescriptorSize + PayloadSize; - *Data = NewData; - return EFI_SUCCESS; + + *DataSize = DescriptorSize + PayloadSize; + *Data = NewData; + return EFI_SUCCESS; } EFI_STATUS @@ -146,8 +140,9 @@ SetSecureVariable(CHAR16 *var, UINT8 *Data, UINTN len, EFI_GUID owner, 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); + if (EFI_ERROR(efi_status)) { + console_print(L"Failed to create %s certificate %d\n", + var, efi_status); return efi_status; } @@ -158,19 +153,18 @@ SetSecureVariable(CHAR16 *var, UINT8 *Data, UINTN len, EFI_GUID owner, 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); + if (EFI_ERROR(efi_status)) { + console_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); - + efi_status = gRT->SetVariable(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; } @@ -181,8 +175,9 @@ GetOSIndications(void) 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) + efi_status = gRT->GetVariable(L"OsIndicationsSupported", &GV_GUID, + NULL, &DataSize, &indications); + if (EFI_ERROR(efi_status)) return 0; return indications; @@ -194,17 +189,15 @@ 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) + efi_status = gRT->SetVariable(L"OsIndications", &GV_GUID, + EFI_VARIABLE_NON_VOLATILE | + EFI_VARIABLE_RUNTIME_ACCESS | + EFI_VARIABLE_BOOTSERVICE_ACCESS, + DataSize, &indications); + if (EFI_ERROR(efi_status)) return efi_status; - uefi_call_wrapper(RT->ResetSystem, 4, EfiResetWarm, EFI_SUCCESS, 0, NULL); + gRT->ResetSystem(EfiResetWarm, EFI_SUCCESS, 0, NULL); /* does not return */ return EFI_SUCCESS; @@ -218,19 +211,19 @@ get_variable_attr(CHAR16 *var, UINT8 **data, UINTN *len, EFI_GUID owner, *len = 0; - efi_status = uefi_call_wrapper(RT->GetVariable, 5, var, &owner, - NULL, len, NULL); - if (efi_status != EFI_BUFFER_TOO_SMALL) + efi_status = gRT->GetVariable(var, &owner, NULL, len, NULL); + if (efi_status != EFI_BUFFER_TOO_SMALL) { + if (!EFI_ERROR(efi_status)) /* this should never happen */ + return EFI_PROTOCOL_ERROR; return efi_status; + } *data = AllocateZeroPool(*len); if (!*data) return EFI_OUT_OF_RESOURCES; - - efi_status = uefi_call_wrapper(RT->GetVariable, 5, var, &owner, - attributes, len, *data); - if (efi_status != EFI_SUCCESS) { + efi_status = gRT->GetVariable(var, &owner, attributes, len, *data); + if (EFI_ERROR(efi_status)) { FreePool(*data); *data = NULL; } @@ -263,19 +256,19 @@ find_in_esl(UINT8 *Data, UINTN DataSize, UINT8 *key, UINTN keylen) EFI_STATUS find_in_variable_esl(CHAR16* var, EFI_GUID owner, UINT8 *key, UINTN keylen) { - UINTN DataSize; - UINT8 *Data; - EFI_STATUS status; + UINTN DataSize = 0; + UINT8 *Data = NULL; + EFI_STATUS efi_status; - status = get_variable(var, &Data, &DataSize, owner); - if (status != EFI_SUCCESS) - return status; + efi_status = get_variable(var, &Data, &DataSize, owner); + if (EFI_ERROR(efi_status)) + return efi_status; - status = find_in_esl(Data, DataSize, key, keylen); + efi_status = find_in_esl(Data, DataSize, key, keylen); FreePool(Data); - return status; + return efi_status; } int @@ -284,11 +277,11 @@ variable_is_setupmode(int default_return) /* set to 1 because we return true if SetupMode doesn't exist */ UINT8 SetupMode = default_return; UINTN DataSize = sizeof(SetupMode); - EFI_STATUS status; + EFI_STATUS efi_status; - status = uefi_call_wrapper(RT->GetVariable, 5, L"SetupMode", &GV_GUID, NULL, - &DataSize, &SetupMode); - if (EFI_ERROR(status)) + efi_status = gRT->GetVariable(L"SetupMode", &GV_GUID, NULL, + &DataSize, &SetupMode); + if (EFI_ERROR(efi_status)) return default_return; return SetupMode; @@ -300,12 +293,12 @@ variable_is_secureboot(void) /* return false if variable doesn't exist */ UINT8 SecureBoot = 0; UINTN DataSize; - EFI_STATUS status; + EFI_STATUS efi_status; DataSize = sizeof(SecureBoot); - status = uefi_call_wrapper(RT->GetVariable, 5, L"SecureBoot", &GV_GUID, NULL, - &DataSize, &SecureBoot); - if (EFI_ERROR(status)) + efi_status = gRT->GetVariable(L"SecureBoot", &GV_GUID, NULL, + &DataSize, &SecureBoot); + if (EFI_ERROR(efi_status)) return 0; return SecureBoot; @@ -315,14 +308,15 @@ EFI_STATUS variable_enroll_hash(CHAR16 *var, EFI_GUID owner, UINT8 hash[SHA256_DIGEST_SIZE]) { - EFI_STATUS status; + EFI_STATUS efi_status; - if (find_in_variable_esl(var, owner, hash, SHA256_DIGEST_SIZE) - == EFI_SUCCESS) + efi_status = find_in_variable_esl(var, owner, hash, SHA256_DIGEST_SIZE); + if (!EFI_ERROR(efi_status)) /* hash already present */ return EFI_ALREADY_STARTED; - UINT8 sig[sizeof(EFI_SIGNATURE_LIST) + sizeof(EFI_SIGNATURE_DATA) - 1 + SHA256_DIGEST_SIZE]; + 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)); @@ -330,16 +324,16 @@ variable_enroll_hash(CHAR16 *var, EFI_GUID owner, l->SignatureListSize = sizeof(sig); l->SignatureSize = 16 +32; /* UEFI defined */ CopyMem(&d->SignatureData, hash, SHA256_DIGEST_SIZE); - d->SignatureOwner = MOK_OWNER; + d->SignatureOwner = SHIM_LOCK_GUID; if (CompareGuid(&owner, &SIG_DB) == 0) - status = SetSecureVariable(var, sig, sizeof(sig), owner, - EFI_VARIABLE_APPEND_WRITE, 0); + efi_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; + efi_status = gRT->SetVariable(var, &owner, + EFI_VARIABLE_NON_VOLATILE | + EFI_VARIABLE_BOOTSERVICE_ACCESS | + EFI_VARIABLE_APPEND_WRITE, + sizeof(sig), sig); + return efi_status; } diff --git a/model.c b/model.c new file mode 100644 index 0000000..d0bfa54 --- /dev/null +++ b/model.c @@ -0,0 +1,136 @@ +/* + * model.c - modeling file for coverity + * Copyright 2017 Peter Jones + * + */ + +#ifndef __COVERITY__ +/* This is so vim's Syntastic checker won't yell about all these. */ +extern void __coverity_string_size_sanitize__(int); +extern void __coverity_negative_sink__(int); +extern void __coverity_alloc_nosize__(void); +extern void *__coverity_alloc__(int); +extern void __coverity_sleep__(); +extern void __coverity_tainted_data_sanitize__(void *); +#endif + +void * +OBJ_dup(void *o) +{ + __coverity_alloc_nosize__(); +} + +int +UTF8_getc(const unsigned char *str, int len, unsigned long *val) +{ + /* You can't quite express the right thing here, so instead we're + * telling covscan that if len is a certain value, the string has + * been checked for having a NUL at the right place. Ideally what + * we'd tell it is it's never allowed to give us a string shorter + * than a certain length if certain bits (i.e. the UTF-8 surrogate + * length bits) are set. */ + if (len <= 0) { + __coverity_string_size_sanitize__(0); + return 0; + } else if (len <= 6) { + __coverity_string_size_sanitize__(0); + return len; + } + return -2; +} + +typedef unsigned long long u64; +typedef struct { + unsigned long long hi; + unsigned long long lo; +} u128; + +void +gcm_gmult_4bit(u64 Xi[2], u128 Htable[16]) +{ + __coverity_tainted_data_sanitize__(Htable); +} + +void +msleep(int n) +{ + __coverity_sleep__(); +} + +/* From MdePkg/Include/Base.h or so */ +typedef unsigned long long UINT64; +typedef unsigned long UINTN; +typedef long INTN; +typedef UINT64 EFI_PHYSICAL_ADDRESS; +typedef UINTN RETURN_STATUS; +typedef RETURN_STATUS EFI_STATUS; + +#define MAX_BIT (1ULL << (sizeof (INTN) * 8 - 1)) +#define MAX_INTN ((INTN)~MAX_BIT) + +#define ENCODE_ERROR(StatusCode) ((RETURN_STATUS)(MAX_BIT | (StatusCode))) +#define ENCODE_WARNING(StatusCode) ((RETURN_STATUS)(StatusCode)) +#define RETURN_ERROR(StatusCode) (((INTN)(RETURN_STATUS)(StatusCode)) < 0) +#define RETURN_SUCCESS 0 +#define RETURN_INVALID_PARAMETER ENCODE_ERROR (2) +#define RETURN_OUT_OF_RESOURCES ENCODE_ERROR (9) + +/* From MdePkg/Include/Uefi/UefiBaseType.h */ +#define EFI_SUCCESS RETURN_SUCCESS +#define EFI_INVALID_PARAMETER RETURN_INVALID_PARAMETER +#define EFI_OUT_OF_RESOURCES RETURN_OUT_OF_RESOURCES + +#define EFI_PAGE_MASK 0xFFF +#define EFI_PAGE_SHIFT 12 +#define EFI_SIZE_TO_PAGES(a) (((a) >> EFI_PAGE_SHIFT) + (((a) & EFI_PAGE_MASK) ? 1 : 0)) +#define EFI_PAGES_TO_SIZE(a) ((a) << EFI_PAGE_SHIFT) + +/* From MdePkg/Include/Uefi/UefiMultiPhase.h */ +typedef enum { + EfiReservedMemoryType, + EfiLoaderCode, + EfiLoaderData, + EfiBootServicesCode, + EfiBootServicesData, + EfiRuntimeServicesCode, + EfiRuntimeServicesData, + EfiConventionalMemory, + EfiUnusableMemory, + EfiACPIReclaimMemory, + EfiACPIMemoryNVS, + EfiMemoryMappedIO, + EfiMemoryMappedIOPortSpace, + EfiPalCode, + EfiPersistentMemory, + EfiMaxMemoryType +} EFI_MEMORY_TYPE; + +/* From MdePkg/Include/Uefi/UefiSpec.h */ +typedef enum { + AllocateAnyPages, + AllocateMaxAddress, + AllocateAddress, + MaxAllocateType +} EFI_ALLOCATE_TYPE; + +EFI_STATUS +AllocatePages(EFI_ALLOCATE_TYPE Type, + EFI_MEMORY_TYPE MemoryType, + unsigned long Pages, + EFI_PHYSICAL_ADDRESS *Memory) +{ + int has_memory; + unsigned long bytes = EFI_PAGES_TO_SIZE(Pages); + + if (Pages >= (unsigned long)((-1L) >> EFI_PAGE_SHIFT)) + return EFI_INVALID_PARAMETER; + + __coverity_negative_sink__(bytes); + if (has_memory) { + *Memory = (EFI_PHYSICAL_ADDRESS)__coverity_alloc__(bytes); + return EFI_SUCCESS; + } + return EFI_OUT_OF_RESOURCES; +} + +// vim:fenc=utf-8:tw=75 diff --git a/mok.c b/mok.c new file mode 100644 index 0000000..3867521 --- /dev/null +++ b/mok.c @@ -0,0 +1,334 @@ +/* + * mok.c + * Copyright 2017 Peter Jones + * + * Distributed under terms of the GPLv3 license. + */ + +#include "shim.h" + +/* + * Check if a variable exists + */ +static BOOLEAN check_var(CHAR16 *varname) +{ + EFI_STATUS efi_status; + UINTN size = sizeof(UINT32); + UINT32 MokVar; + UINT32 attributes; + + efi_status = gRT->GetVariable(varname, &SHIM_LOCK_GUID, &attributes, + &size, (void *)&MokVar); + if (!EFI_ERROR(efi_status) || efi_status == EFI_BUFFER_TOO_SMALL) + return TRUE; + + return FALSE; +} + +/* + * If the OS has set any of these variables we need to drop into MOK and + * handle them appropriately + */ +static EFI_STATUS check_mok_request(EFI_HANDLE image_handle) +{ + EFI_STATUS efi_status; + + if (check_var(L"MokNew") || check_var(L"MokSB") || + check_var(L"MokPW") || check_var(L"MokAuth") || + check_var(L"MokDel") || check_var(L"MokDB") || + check_var(L"MokXNew") || check_var(L"MokXDel") || + check_var(L"MokXAuth")) { + efi_status = start_image(image_handle, MOK_MANAGER); + + if (EFI_ERROR(efi_status)) { + perror(L"Failed to start MokManager: %r\n", efi_status); + return efi_status; + } + } + + return EFI_SUCCESS; +} + +/* + * MoK variables that need to have their storage validated. + * + * The order here is important, since this is where we measure for the + * tpm as well. + */ +struct mok_state_variable { + CHAR16 *name; + char *name8; + CHAR16 *rtname; + EFI_GUID *guid; + UINT8 *data; + UINTN data_size; + /* + * These two are indirect pointers just to make initialization + * saner... + */ + UINT8 **addend_source; + UINT32 *addend_size; + UINT32 yes_attr; + UINT32 no_attr; + UINT32 flags; + UINTN pcr; + UINT8 *state; +}; + +#define MOK_MIRROR_KEYDB 0x01 +#define MOK_MIRROR_DELETE_FIRST 0x02 +#define MOK_VARIABLE_MEASURE 0x04 +#define MOK_VARIABLE_LOG 0x08 + +struct mok_state_variable mok_state_variables[] = { + {.name = L"MokList", + .name8 = "MokList", + .rtname = L"MokListRT", + .guid = &SHIM_LOCK_GUID, + .yes_attr = EFI_VARIABLE_BOOTSERVICE_ACCESS | + EFI_VARIABLE_NON_VOLATILE, + .no_attr = EFI_VARIABLE_RUNTIME_ACCESS, + .addend_source = &vendor_cert, + .addend_size = &vendor_cert_size, + .flags = MOK_MIRROR_KEYDB | + MOK_VARIABLE_LOG, + .pcr = 14, + }, + {.name = L"MokListX", + .name8 = "MokListX", + .rtname = L"MokListXRT", + .guid = &SHIM_LOCK_GUID, + .yes_attr = EFI_VARIABLE_BOOTSERVICE_ACCESS | + EFI_VARIABLE_NON_VOLATILE, + .no_attr = EFI_VARIABLE_RUNTIME_ACCESS, + .flags = MOK_MIRROR_KEYDB | + MOK_VARIABLE_LOG, + .pcr = 14, + }, + {.name = L"MokSBState", + .name8 = "MokSBState", + .rtname = L"MokSBStateRT", + .guid = &SHIM_LOCK_GUID, + .yes_attr = EFI_VARIABLE_BOOTSERVICE_ACCESS | + EFI_VARIABLE_NON_VOLATILE, + .no_attr = EFI_VARIABLE_RUNTIME_ACCESS, + .flags = MOK_MIRROR_DELETE_FIRST | + MOK_VARIABLE_MEASURE | + MOK_VARIABLE_LOG, + .pcr = 14, + .state = &user_insecure_mode, + }, + {.name = L"MokDBState", + .name8 = "MokDBState", + .rtname = L"MokIgnoreDB", + .guid = &SHIM_LOCK_GUID, + .yes_attr = EFI_VARIABLE_BOOTSERVICE_ACCESS | + EFI_VARIABLE_NON_VOLATILE, + .no_attr = EFI_VARIABLE_RUNTIME_ACCESS, + .state = &ignore_db, + }, + { NULL, } +}; + +static EFI_STATUS mirror_one_mok_variable(struct mok_state_variable *v) +{ + EFI_STATUS efi_status = EFI_SUCCESS; + void *FullData = NULL; + UINTN FullDataSize = 0; + uint8_t *p = NULL; + + if ((v->flags & MOK_MIRROR_KEYDB) && + v->addend_source && *v->addend_source && + v->addend_size && *v->addend_size) { + EFI_SIGNATURE_LIST *CertList = NULL; + EFI_SIGNATURE_DATA *CertData = NULL; + FullDataSize = v->data_size + + sizeof (*CertList) + + sizeof (EFI_GUID) + + *v->addend_size; + FullData = AllocatePool(FullDataSize); + if (!FullData) { + perror(L"Failed to allocate space for MokListRT\n"); + return EFI_OUT_OF_RESOURCES; + } + p = FullData; + + if (!EFI_ERROR(efi_status) && v->data_size > 0) { + CopyMem(p, v->data, v->data_size); + p += v->data_size; + } + CertList = (EFI_SIGNATURE_LIST *)p; + p += sizeof (*CertList); + CertData = (EFI_SIGNATURE_DATA *)p; + p += sizeof (EFI_GUID); + + CertList->SignatureType = EFI_CERT_TYPE_X509_GUID; + CertList->SignatureListSize = *v->addend_size + + sizeof (*CertList) + + sizeof (*CertData) + -1; + CertList->SignatureHeaderSize = 0; + CertList->SignatureSize = *v->addend_size + sizeof (EFI_GUID); + + CertData->SignatureOwner = SHIM_LOCK_GUID; + CopyMem(p, *v->addend_source, *v->addend_size); + + if (v->data && v->data_size) + FreePool(v->data); + v->data = FullData; + v->data_size = FullDataSize; + } else { + FullDataSize = v->data_size; + FullData = v->data; + } + + if (FullDataSize) { + efi_status = gRT->SetVariable(v->rtname, v->guid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | + EFI_VARIABLE_RUNTIME_ACCESS, + FullDataSize, FullData); + if (EFI_ERROR(efi_status)) { + perror(L"Failed to set %s: %r\n", + v->rtname, efi_status); + } + } + + return efi_status; +} + +/* + * Verify our non-volatile MoK state. This checks the variables above + * accessable and have valid attributes. If they don't, it removes + * them. If any of them can't be removed, our ability to do this is + * comprimized, so return EFI_SECURITY_VIOLATION. + * + * Any variable that isn't deleted and has ->measure == TRUE is then + * measured into the tpm. + * + * Any variable with a ->rtname element is then mirrored to a + * runtime-accessable version. The new ones won't be marked NV, so the OS + * can't modify them. + */ +EFI_STATUS import_mok_state(EFI_HANDLE image_handle) +{ + UINTN i; + EFI_STATUS ret = EFI_SUCCESS; + EFI_STATUS efi_status; + + user_insecure_mode = 0; + ignore_db = 0; + + for (i = 0; mok_state_variables[i].name != NULL; i++) { + struct mok_state_variable *v = &mok_state_variables[i]; + UINT32 attrs = 0; + BOOLEAN delete = FALSE, present, addend; + + efi_status = get_variable_attr(v->name, + &v->data, &v->data_size, + *v->guid, &attrs); + if (efi_status == EFI_NOT_FOUND) + continue; + if (EFI_ERROR(efi_status)) { + perror(L"Could not verify %s: %r\n", v->name, + efi_status); + /* + * don't clobber EFI_SECURITY_VIOLATION from some + * other variable in the list. + */ + if (ret != EFI_SECURITY_VIOLATION) + ret = efi_status; + continue; + } + + if (!(attrs & v->yes_attr)) { + perror(L"Variable %s is missing attributes:\n", + v->name); + perror(L" 0x%08x should have 0x%08x set.\n", + attrs, v->yes_attr); + delete = TRUE; + } + if (attrs & v->no_attr) { + perror(L"Variable %s has incorrect attribute:\n", + v->name); + perror(L" 0x%08x should not have 0x%08x set.\n", + attrs, v->no_attr); + delete = TRUE; + } + if (delete == TRUE) { + perror(L"Deleting bad variable %s\n", v->name); + efi_status = LibDeleteVariable(v->name, v->guid); + if (EFI_ERROR(efi_status)) { + perror(L"Failed to erase %s\n", v->name); + ret = EFI_SECURITY_VIOLATION; + } + FreePool(v->data); + v->data = NULL; + v->data_size = 0; + continue; + } + + if (v->data && v->data_size == sizeof(UINT8) && v->state) { + *v->state = v->data[0]; + } + + present = (v->data && v->data_size) ? TRUE : FALSE; + addend = (v->addend_source && v->addend_size && + *v->addend_source && *v->addend_size) + ? TRUE : FALSE; + + if (v->flags & MOK_VARIABLE_MEASURE && present) { + /* + * Measure this into PCR 7 in the Microsoft format + */ + efi_status = tpm_measure_variable(v->name, *v->guid, + v->data_size, + v->data); + if (EFI_ERROR(efi_status)) { + if (ret != EFI_SECURITY_VIOLATION) + ret = efi_status; + } + } + + if (v->flags & MOK_VARIABLE_LOG && present) { + /* + * Log this variable into whichever PCR the table + * says. + */ + EFI_PHYSICAL_ADDRESS datap = + (EFI_PHYSICAL_ADDRESS)(UINTN)v->data, + efi_status = tpm_log_event(datap, v->data_size, + v->pcr, (CHAR8 *)v->name8); + if (EFI_ERROR(efi_status)) { + if (ret != EFI_SECURITY_VIOLATION) + ret = efi_status; + } + } + + if (v->rtname && present && addend) { + if (v->flags & MOK_MIRROR_DELETE_FIRST) + LibDeleteVariable(v->rtname, v->guid); + + efi_status = mirror_one_mok_variable(v); + if (EFI_ERROR(efi_status) && + ret != EFI_SECURITY_VIOLATION) + ret = efi_status; + } + } + + /* + * Enter MokManager if necessary. Any actual *changes* here will + * cause MokManager to demand a machine reboot, so this is safe to + * have after the entire loop. + */ + efi_status = check_mok_request(image_handle); + if (EFI_ERROR(efi_status)) { + if (ret != EFI_SECURITY_VIOLATION) + ret = efi_status; + return ret; + } + + + return ret; +} + +// vim:fenc=utf-8:tw=75 diff --git a/netboot.c b/netboot.c index e5ef7d7..58babfb 100644 --- a/netboot.c +++ b/netboot.c @@ -34,9 +34,8 @@ */ #include "shim.h" + #include -#include "netboot.h" -#include "str.h" #define ntohs(x) __builtin_bswap16(x) /* supported both by GCC and clang */ #define htons(x) ntohs(x) @@ -59,11 +58,11 @@ typedef struct { */ BOOLEAN findNetboot(EFI_HANDLE device) { - EFI_STATUS status; + EFI_STATUS efi_status; - status = uefi_call_wrapper(BS->HandleProtocol, 3, device, - &PxeBaseCodeProtocol, (VOID **)&pxe); - if (status != EFI_SUCCESS) { + efi_status = gBS->HandleProtocol(device, &PxeBaseCodeProtocol, + (VOID **) &pxe); + if (EFI_ERROR(efi_status)) { pxe = NULL; return FALSE; } @@ -196,12 +195,12 @@ static BOOLEAN extract_tftp_info(CHAR8 *url) memset(ip6inv, 0, sizeof(ip6inv)); if (strncmp((UINT8 *)url, (UINT8 *)"tftp://", 7)) { - Print(L"URLS MUST START WITH tftp://\n"); + console_print(L"URLS MUST START WITH tftp://\n"); return FALSE; } start = url + 7; if (*start != '[') { - Print(L"TFTP SERVER MUST BE ENCLOSED IN [..]\n"); + console_print(L"TFTP SERVER MUST BE ENCLOSED IN [..]\n"); return FALSE; } @@ -210,12 +209,12 @@ static BOOLEAN extract_tftp_info(CHAR8 *url) while ((*end != '\0') && (*end != ']')) { end++; if (end - start >= (int)sizeof(ip6str)) { - Print(L"TFTP URL includes malformed IPv6 address\n"); + console_print(L"TFTP URL includes malformed IPv6 address\n"); return FALSE; } } if (*end == '\0') { - Print(L"TFTP SERVER MUST BE ENCLOSED IN [..]\n"); + console_print(L"TFTP SERVER MUST BE ENCLOSED IN [..]\n"); return FALSE; } memset(ip6str, 0, sizeof(ip6str)); @@ -257,10 +256,20 @@ static EFI_STATUS parseDhcp4() { CHAR8 *template = (CHAR8 *)translate_slashes(DEFAULT_LOADER_CHAR); INTN template_len = strlen(template) + 1; + EFI_PXE_BASE_CODE_DHCPV4_PACKET* pkt_v4 = (EFI_PXE_BASE_CODE_DHCPV4_PACKET *)&pxe->Mode->DhcpAck.Dhcpv4; - INTN dir_len = strnlena(pxe->Mode->DhcpAck.Dhcpv4.BootpBootFile, 127); + if(pxe->Mode->ProxyOfferReceived) { + /* + * Proxy should not have precedence. Check if DhcpAck + * contained boot info. + */ + if(pxe->Mode->DhcpAck.Dhcpv4.BootpBootFile[0] == '\0') + pkt_v4 = &pxe->Mode->ProxyOffer.Dhcpv4; + } + + INTN dir_len = strnlena(pkt_v4->BootpBootFile, 127); INTN i; - UINT8 *dir = pxe->Mode->DhcpAck.Dhcpv4.BootpBootFile; + UINT8 *dir = pkt_v4->BootpBootFile; for (i = dir_len; i >= 0; i--) { if (dir[i] == '/') @@ -281,7 +290,7 @@ static EFI_STATUS parseDhcp4() if (dir_len == 0 && dir[0] != '/' && template[0] == '/') template++; strcata(full_path, template); - memcpy(&tftp_addr.v4, pxe->Mode->DhcpAck.Dhcpv4.BootpSiAddr, 4); + memcpy(&tftp_addr.v4, pkt_v4->BootpSiAddr, 4); return EFI_SUCCESS; } @@ -289,7 +298,7 @@ static EFI_STATUS parseDhcp4() EFI_STATUS parseNetbootinfo(EFI_HANDLE image_handle) { - EFI_STATUS rc; + EFI_STATUS efi_status; if (!pxe) return EFI_NOT_READY; @@ -301,33 +310,32 @@ EFI_STATUS parseNetbootinfo(EFI_HANDLE image_handle) * if its ipv4 or ipv6 */ if (pxe->Mode->UsingIpv6){ - rc = parseDhcp6(); + efi_status = parseDhcp6(); } else - rc = parseDhcp4(); - return rc; + efi_status = parseDhcp4(); + return efi_status; } EFI_STATUS FetchNetbootimage(EFI_HANDLE image_handle, VOID **buffer, UINT64 *bufsiz) { - EFI_STATUS rc; + EFI_STATUS efi_status; EFI_PXE_BASE_CODE_TFTP_OPCODE read = EFI_PXE_BASE_CODE_TFTP_READ_FILE; BOOLEAN overwrite = FALSE; BOOLEAN nobuffer = FALSE; UINTN blksz = 512; - Print(L"Fetching Netboot Image\n"); + console_print(L"Fetching Netboot Image\n"); if (*buffer == NULL) { *buffer = AllocatePool(4096 * 1024); if (!*buffer) - return EFI_OUT_OF_RESOURCES; + return EFI_OUT_OF_RESOURCES; *bufsiz = 4096 * 1024; } try_again: - rc = uefi_call_wrapper(pxe->Mtftp, 10, pxe, read, *buffer, overwrite, - bufsiz, &blksz, &tftp_addr, full_path, NULL, nobuffer); - - if (rc == EFI_BUFFER_TOO_SMALL) { + efi_status = pxe->Mtftp(pxe, read, *buffer, overwrite, bufsiz, &blksz, + &tftp_addr, full_path, NULL, nobuffer); + if (efi_status == EFI_BUFFER_TOO_SMALL) { /* try again, doubling buf size */ *bufsiz *= 2; FreePool(*buffer); @@ -337,8 +345,8 @@ try_again: goto try_again; } - if (rc != EFI_SUCCESS && *buffer) { + if (EFI_ERROR(efi_status) && *buffer) { FreePool(*buffer); } - return rc; + return efi_status; } diff --git a/replacements.c b/replacements.c index 898b42b..944c779 100644 --- a/replacements.c +++ b/replacements.c @@ -50,13 +50,19 @@ #include #include #include + #include "shim.h" -#include "replacements.h" -#include "console.h" -#include "errors.h" static EFI_SYSTEM_TABLE *systab; +EFI_SYSTEM_TABLE * +get_active_systab(void) +{ + if (systab) + return systab; + return ST; +} + static typeof(systab->BootServices->LoadImage) system_load_image; static typeof(systab->BootServices->StartImage) system_start_image; static typeof(systab->BootServices->Exit) system_exit; @@ -73,6 +79,7 @@ unhook_system_services(void) systab->BootServices->LoadImage = system_load_image; systab->BootServices->StartImage = system_start_image; systab->BootServices->ExitBootServices = system_exit_boot_services; + gBS = systab->BootServices; } static EFI_STATUS EFIAPI @@ -80,80 +87,67 @@ load_image(BOOLEAN BootPolicy, EFI_HANDLE ParentImageHandle, EFI_DEVICE_PATH *DevicePath, VOID *SourceBuffer, UINTN SourceSize, EFI_HANDLE *ImageHandle) { - EFI_STATUS status; - unhook_system_services(); + EFI_STATUS efi_status; - status = systab->BootServices->LoadImage(BootPolicy, - ParentImageHandle, DevicePath, - SourceBuffer, SourceSize, ImageHandle); + unhook_system_services(); + efi_status = gBS->LoadImage(BootPolicy, ParentImageHandle, DevicePath, + SourceBuffer, SourceSize, ImageHandle); hook_system_services(systab); - if (EFI_ERROR(status)) + if (EFI_ERROR(efi_status)) last_loaded_image = NULL; else last_loaded_image = *ImageHandle; - return status; + return efi_status; } static EFI_STATUS EFIAPI -start_image(EFI_HANDLE image_handle, UINTN *exit_data_size, CHAR16 **exit_data) +replacement_start_image(EFI_HANDLE image_handle, UINTN *exit_data_size, CHAR16 **exit_data) { - EFI_STATUS status; + EFI_STATUS efi_status; unhook_system_services(); - /* We have to uninstall shim's protocol here, because if we're - * On the fallback.efi path, then our call pathway is: - * - * shim->fallback->shim->grub - * ^ ^ ^ - * | | \- gets protocol #0 - * | \- installs its protocol (#1) - * \- installs its protocol (#0) - * and if we haven't removed this, then grub will get the *first* - * shim's protocol, but it'll get the second shim's systab - * replacements. So even though it will participate and verify - * the kernel, the systab never finds out. - */ if (image_handle == last_loaded_image) { loader_is_participating = 1; uninstall_shim_protocols(); } - status = systab->BootServices->StartImage(image_handle, exit_data_size, exit_data); - if (EFI_ERROR(status)) { + efi_status = gBS->StartImage(image_handle, exit_data_size, exit_data); + if (EFI_ERROR(efi_status)) { if (image_handle == last_loaded_image) { - EFI_STATUS status2 = install_shim_protocols(); + EFI_STATUS efi_status2 = install_shim_protocols(); - if (EFI_ERROR(status2)) { - Print(L"Something has gone seriously wrong: %d\n", - status2); - Print(L"shim cannot continue, sorry.\n"); + if (EFI_ERROR(efi_status2)) { + console_print(L"Something has gone seriously wrong: %r\n", + efi_status2); + console_print(L"shim cannot continue, sorry.\n"); msleep(5000000); - systab->RuntimeServices->ResetSystem( - EfiResetShutdown, - EFI_SECURITY_VIOLATION, 0, NULL); + gRT->ResetSystem(EfiResetShutdown, + EFI_SECURITY_VIOLATION, + 0, NULL); } } hook_system_services(systab); loader_is_participating = 0; } - return status; + return efi_status; } static EFI_STATUS EFIAPI exit_boot_services(EFI_HANDLE image_key, UINTN map_key) { - if (loader_is_participating || verification_method == VERIFIED_BY_HASH) { + if (loader_is_participating || + verification_method == VERIFIED_BY_HASH) { unhook_system_services(); - EFI_STATUS status; - status = systab->BootServices->ExitBootServices(image_key, map_key); - if (status != EFI_SUCCESS) + EFI_STATUS efi_status; + efi_status = gBS->ExitBootServices(image_key, map_key); + if (EFI_ERROR(efi_status)) hook_system_services(systab); - return status; + return efi_status; } - Print(L"Bootloader has not verified loaded image.\n"); - Print(L"System is compromised. halting.\n"); + console_print(L"Bootloader has not verified loaded image.\n"); + console_print(L"System is compromised. halting.\n"); msleep(5000000); - systab->RuntimeServices->ResetSystem(EfiResetShutdown, EFI_SECURITY_VIOLATION, 0, NULL); + gRT->ResetSystem(EfiResetShutdown, EFI_SECURITY_VIOLATION, 0, NULL); return EFI_SECURITY_VIOLATION; } @@ -161,41 +155,41 @@ static EFI_STATUS EFIAPI do_exit(EFI_HANDLE ImageHandle, EFI_STATUS ExitStatus, UINTN ExitDataSize, CHAR16 *ExitData) { - EFI_STATUS status; + EFI_STATUS efi_status; shim_fini(); - status = systab->BootServices->Exit(ImageHandle, ExitStatus, - ExitDataSize, ExitData); - if (EFI_ERROR(status)) { - EFI_STATUS status2 = shim_init(); + efi_status = gBS->Exit(ImageHandle, ExitStatus, + ExitDataSize, ExitData); + if (EFI_ERROR(efi_status)) { + EFI_STATUS efi_status2 = shim_init(); - if (EFI_ERROR(status2)) { - Print(L"Something has gone seriously wrong: %r\n", - status2); - Print(L"shim cannot continue, sorry.\n"); + if (EFI_ERROR(efi_status2)) { + console_print(L"Something has gone seriously wrong: %r\n", + efi_status2); + console_print(L"shim cannot continue, sorry.\n"); msleep(5000000); - systab->RuntimeServices->ResetSystem( - EfiResetShutdown, - EFI_SECURITY_VIOLATION, 0, NULL); + gRT->ResetSystem(EfiResetShutdown, + EFI_SECURITY_VIOLATION, 0, NULL); } } - return status; + return efi_status; } void hook_system_services(EFI_SYSTEM_TABLE *local_systab) { systab = local_systab; + gBS = systab->BootServices; /* We need to hook various calls to make this work... */ /* We need LoadImage() hooked so that fallback.c can load shim * without having to fake LoadImage as well. This allows it * to call the system LoadImage(), and have us track the output - * and mark loader_is_participating in start_image. This means - * anything added by fallback has to be verified by the system db, - * which we want to preserve anyway, since that's all launching + * and mark loader_is_participating in replacement_start_image. This + * means anything added by fallback has to be verified by the system + * db, which we want to preserve anyway, since that's all launching * through BDS gives us. */ system_load_image = systab->BootServices->LoadImage; systab->BootServices->LoadImage = load_image; @@ -203,7 +197,7 @@ hook_system_services(EFI_SYSTEM_TABLE *local_systab) /* we need StartImage() so that we can allow chain booting to an * image trusted by the firmware */ system_start_image = systab->BootServices->StartImage; - systab->BootServices->StartImage = start_image; + systab->BootServices->StartImage = replacement_start_image; /* we need to hook ExitBootServices() so a) we can enforce the policy * and b) we can unwrap when we're done. */ @@ -215,12 +209,14 @@ void unhook_exit(void) { systab->BootServices->Exit = system_exit; + gBS = systab->BootServices; } void hook_exit(EFI_SYSTEM_TABLE *local_systab) { systab = local_systab; + gBS = local_systab->BootServices; /* we need to hook Exit() so that we can allow users to quit the * bootloader and still e.g. start a new one or run an internal diff --git a/shim.c b/shim.c index c6ad2cd..05fc650 100644 --- a/shim.c +++ b/shim.c @@ -50,29 +50,16 @@ #include -#define FALLBACK L"\\fb" EFI_ARCH L".efi" -#define MOK_MANAGER L"\\mm" EFI_ARCH L".efi" +#include #define OID_EKU_MODSIGN "1.3.6.1.4.1.2312.16.1.2" static EFI_SYSTEM_TABLE *systab; static EFI_HANDLE global_image_handle; -static EFI_STATUS (EFIAPI *entry_point) (EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *system_table); static CHAR16 *second_stage; static void *load_options; static UINT32 load_options_size; -static UINT8 in_protocol; - -#define perror(fmt, ...) ({ \ - UINTN __perror_ret = 0; \ - if (!in_protocol) \ - __perror_ret = Print((fmt), ##__VA_ARGS__); \ - LogError(fmt, ##__VA_ARGS__); \ - __perror_ret; \ - }) - -EFI_GUID SHIM_LOCK_GUID = { 0x605dab50, 0xe046, 0x4300, {0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23} }; /* * The vendor certificate used for validating the second stage loader @@ -114,11 +101,17 @@ typedef struct { /* * Perform basic bounds checking of the intra-image pointers */ -static void *ImageAddress (void *image, unsigned int size, unsigned int address) +static void *ImageAddress (void *image, uint64_t size, uint64_t address) { + /* ensure our local pointer isn't bigger than our size */ if (address > size) return NULL; + /* Insure our math won't overflow */ + if (UINT64_MAX - address < (uint64_t)(intptr_t)image) + return NULL; + + /* return the absolute pointer */ return image + address; } @@ -232,7 +225,7 @@ static EFI_STATUS relocate_coff (PE_COFF_LOADER_IMAGE_CONTEXT *context, EFI_IMAGE_BASE_RELOCATION *RelocBase, *RelocBaseEnd; UINT64 Adjust; UINT16 *Reloc, *RelocEnd; - char *Fixup, *FixupBase, *FixupData = NULL; + char *Fixup, *FixupBase; UINT16 *Fixup16; UINT32 *Fixup32; UINT64 *Fixup64; @@ -240,11 +233,6 @@ static EFI_STATUS relocate_coff (PE_COFF_LOADER_IMAGE_CONTEXT *context, void *ImageEnd = (char *)orig + size; int n = 0; - if (image_is_64_bit(context->PEHdr)) - context->PEHdr->Pe32Plus.OptionalHeader.ImageBase = (UINT64)(unsigned long)data; - else - context->PEHdr->Pe32.OptionalHeader.ImageBase = (UINT32)(unsigned long)data; - /* Alright, so here's how this works: * * context->RelocDir gives us two things: @@ -292,8 +280,14 @@ static EFI_STATUS relocate_coff (PE_COFF_LOADER_IMAGE_CONTEXT *context, while (RelocBase < RelocBaseEnd) { Reloc = (UINT16 *) ((char *) RelocBase + sizeof (EFI_IMAGE_BASE_RELOCATION)); - if ((RelocBase->SizeOfBlock == 0) || (RelocBase->SizeOfBlock > context->RelocDir->Size)) { - perror(L"Reloc %d block size %d is invalid\n", n, RelocBase->SizeOfBlock); + if (RelocBase->SizeOfBlock == 0) { + perror(L"Reloc %d block size 0 is invalid\n", n); + return EFI_UNSUPPORTED; + } else if (RelocBase->SizeOfBlock > context->RelocDir->Size) { + perror(L"Reloc %d block size %d greater than reloc dir" + "size %d, which is invalid\n", n, + RelocBase->SizeOfBlock, + context->RelocDir->Size); return EFI_UNSUPPORTED; } @@ -318,39 +312,21 @@ static EFI_STATUS relocate_coff (PE_COFF_LOADER_IMAGE_CONTEXT *context, case EFI_IMAGE_REL_BASED_HIGH: Fixup16 = (UINT16 *) Fixup; *Fixup16 = (UINT16) (*Fixup16 + ((UINT16) ((UINT32) Adjust >> 16))); - if (FixupData != NULL) { - *(UINT16 *) FixupData = *Fixup16; - FixupData = FixupData + sizeof (UINT16); - } break; case EFI_IMAGE_REL_BASED_LOW: Fixup16 = (UINT16 *) Fixup; *Fixup16 = (UINT16) (*Fixup16 + (UINT16) Adjust); - if (FixupData != NULL) { - *(UINT16 *) FixupData = *Fixup16; - FixupData = FixupData + sizeof (UINT16); - } break; case EFI_IMAGE_REL_BASED_HIGHLOW: Fixup32 = (UINT32 *) Fixup; *Fixup32 = *Fixup32 + (UINT32) Adjust; - if (FixupData != NULL) { - FixupData = ALIGN_POINTER (FixupData, sizeof (UINT32)); - *(UINT32 *)FixupData = *Fixup32; - FixupData = FixupData + sizeof (UINT32); - } break; case EFI_IMAGE_REL_BASED_DIR64: Fixup64 = (UINT64 *) Fixup; *Fixup64 = *Fixup64 + (UINT64) Adjust; - if (FixupData != NULL) { - FixupData = ALIGN_POINTER (FixupData, sizeof(UINT64)); - *(UINT64 *)(FixupData) = *Fixup64; - FixupData = FixupData + sizeof(UINT64); - } break; default: @@ -439,10 +415,9 @@ static CHECK_STATUS check_db_cert_in_ram(EFI_SIGNATURE_LIST *CertList, EFI_SIGNATURE_DATA *Cert; UINTN CertSize; BOOLEAN IsFound = FALSE; - EFI_GUID CertType = X509_GUID; while ((dbsize > 0) && (dbsize >= CertList->SignatureListSize)) { - if (CompareGuid (&CertList->SignatureType, &CertType) == 0) { + if (CompareGuid (&CertList->SignatureType, &EFI_CERT_TYPE_X509_GUID) == 0) { Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize); CertSize = CertList->SignatureSize - sizeof(EFI_GUID); if (verify_x509(Cert->SignatureData, CertSize)) { @@ -454,8 +429,8 @@ static CHECK_STATUS check_db_cert_in_ram(EFI_SIGNATURE_LIST *CertList, hash, SHA256_DIGEST_SIZE); if (IsFound) { tpm_measure_variable(dbname, guid, CertSize, Cert->SignatureData); - return DATA_FOUND; drain_openssl_errors(); + return DATA_FOUND; } else { LogError(L"AuthenticodeVerify(): %d\n", IsFound); } @@ -482,7 +457,7 @@ static CHECK_STATUS check_db_cert(CHAR16 *dbname, EFI_GUID guid, UINT8 *db; efi_status = get_variable(dbname, &db, &dbsize, guid); - if (efi_status != EFI_SUCCESS) + if (EFI_ERROR(efi_status)) return VAR_NOT_FOUND; CertList = (EFI_SIGNATURE_LIST *)db; @@ -549,8 +524,7 @@ static CHECK_STATUS check_db_hash(CHAR16 *dbname, EFI_GUID guid, UINT8 *data, UINT8 *db; efi_status = get_variable(dbname, &db, &dbsize, guid); - - if (efi_status != EFI_SUCCESS) { + if (EFI_ERROR(efi_status)) { return VAR_NOT_FOUND; } @@ -571,52 +545,50 @@ static CHECK_STATUS check_db_hash(CHAR16 *dbname, EFI_GUID guid, UINT8 *data, static EFI_STATUS check_blacklist (WIN_CERTIFICATE_EFI_PKCS *cert, UINT8 *sha256hash, UINT8 *sha1hash) { - EFI_GUID secure_var = EFI_IMAGE_SECURITY_DATABASE_GUID; - EFI_GUID shim_var = SHIM_LOCK_GUID; EFI_SIGNATURE_LIST *dbx = (EFI_SIGNATURE_LIST *)vendor_dbx; if (check_db_hash_in_ram(dbx, vendor_dbx_size, sha256hash, - SHA256_DIGEST_SIZE, EFI_CERT_SHA256_GUID, - L"dbx", secure_var) == - DATA_FOUND) { + SHA256_DIGEST_SIZE, EFI_CERT_SHA256_GUID, L"dbx", + EFI_SECURE_BOOT_DB_GUID) == DATA_FOUND) { LogError(L"binary sha256hash found in vendor dbx\n"); return EFI_SECURITY_VIOLATION; } if (check_db_hash_in_ram(dbx, vendor_dbx_size, sha1hash, - SHA1_DIGEST_SIZE, EFI_CERT_SHA1_GUID, - L"dbx", secure_var) == - DATA_FOUND) { + SHA1_DIGEST_SIZE, EFI_CERT_SHA1_GUID, L"dbx", + EFI_SECURE_BOOT_DB_GUID) == DATA_FOUND) { LogError(L"binary sha1hash found in vendor dbx\n"); return EFI_SECURITY_VIOLATION; } - if (cert && check_db_cert_in_ram(dbx, vendor_dbx_size, cert, - sha256hash, L"dbx", - secure_var) == DATA_FOUND) { + if (cert && + check_db_cert_in_ram(dbx, vendor_dbx_size, cert, sha256hash, L"dbx", + EFI_SECURE_BOOT_DB_GUID) == DATA_FOUND) { LogError(L"cert sha256hash found in vendor dbx\n"); return EFI_SECURITY_VIOLATION; } - if (check_db_hash(L"dbx", secure_var, sha256hash, SHA256_DIGEST_SIZE, - EFI_CERT_SHA256_GUID) == DATA_FOUND) { + if (check_db_hash(L"dbx", EFI_SECURE_BOOT_DB_GUID, sha256hash, + SHA256_DIGEST_SIZE, EFI_CERT_SHA256_GUID) == DATA_FOUND) { LogError(L"binary sha256hash found in system dbx\n"); return EFI_SECURITY_VIOLATION; } - if (check_db_hash(L"dbx", secure_var, sha1hash, SHA1_DIGEST_SIZE, - EFI_CERT_SHA1_GUID) == DATA_FOUND) { + if (check_db_hash(L"dbx", EFI_SECURE_BOOT_DB_GUID, sha1hash, + SHA1_DIGEST_SIZE, EFI_CERT_SHA1_GUID) == DATA_FOUND) { LogError(L"binary sha1hash found in system dbx\n"); return EFI_SECURITY_VIOLATION; } - if (cert && check_db_cert(L"dbx", secure_var, cert, sha256hash) == - DATA_FOUND) { + if (cert && + check_db_cert(L"dbx", EFI_SECURE_BOOT_DB_GUID, + cert, sha256hash) == DATA_FOUND) { LogError(L"cert sha256hash found in system dbx\n"); return EFI_SECURITY_VIOLATION; } - if (check_db_hash(L"MokListX", shim_var, sha256hash, SHA256_DIGEST_SIZE, - EFI_CERT_SHA256_GUID) == DATA_FOUND) { + if (check_db_hash(L"MokListX", SHIM_LOCK_GUID, sha256hash, + SHA256_DIGEST_SIZE, EFI_CERT_SHA256_GUID) == DATA_FOUND) { LogError(L"binary sha256hash found in Mok dbx\n"); return EFI_SECURITY_VIOLATION; } - if (cert && check_db_cert(L"MokListX", shim_var, cert, sha256hash) == - DATA_FOUND) { + if (cert && + check_db_cert(L"MokListX", SHIM_LOCK_GUID, + cert, sha256hash) == DATA_FOUND) { LogError(L"cert sha256hash found in Mok dbx\n"); return EFI_SECURITY_VIOLATION; } @@ -637,18 +609,15 @@ static void update_verification_method(verification_method_t method) static EFI_STATUS check_whitelist (WIN_CERTIFICATE_EFI_PKCS *cert, UINT8 *sha256hash, UINT8 *sha1hash) { - EFI_GUID secure_var = EFI_IMAGE_SECURITY_DATABASE_GUID; - EFI_GUID shim_var = SHIM_LOCK_GUID; - if (!ignore_db) { - if (check_db_hash(L"db", secure_var, sha256hash, SHA256_DIGEST_SIZE, + if (check_db_hash(L"db", EFI_SECURE_BOOT_DB_GUID, sha256hash, SHA256_DIGEST_SIZE, EFI_CERT_SHA256_GUID) == DATA_FOUND) { update_verification_method(VERIFIED_BY_HASH); return EFI_SUCCESS; } else { LogError(L"check_db_hash(db, sha256hash) != DATA_FOUND\n"); } - if (check_db_hash(L"db", secure_var, sha1hash, SHA1_DIGEST_SIZE, + if (check_db_hash(L"db", EFI_SECURE_BOOT_DB_GUID, sha1hash, SHA1_DIGEST_SIZE, EFI_CERT_SHA1_GUID) == DATA_FOUND) { verification_method = VERIFIED_BY_HASH; update_verification_method(VERIFIED_BY_HASH); @@ -656,7 +625,7 @@ static EFI_STATUS check_whitelist (WIN_CERTIFICATE_EFI_PKCS *cert, } else { LogError(L"check_db_hash(db, sha1hash) != DATA_FOUND\n"); } - if (cert && check_db_cert(L"db", secure_var, cert, sha256hash) + if (cert && check_db_cert(L"db", EFI_SECURE_BOOT_DB_GUID, cert, sha256hash) == DATA_FOUND) { verification_method = VERIFIED_BY_CERT; update_verification_method(VERIFIED_BY_CERT); @@ -666,16 +635,17 @@ static EFI_STATUS check_whitelist (WIN_CERTIFICATE_EFI_PKCS *cert, } } - if (check_db_hash(L"MokList", shim_var, sha256hash, SHA256_DIGEST_SIZE, - EFI_CERT_SHA256_GUID) == DATA_FOUND) { + if (check_db_hash(L"MokList", SHIM_LOCK_GUID, sha256hash, + SHA256_DIGEST_SIZE, EFI_CERT_SHA256_GUID) + == DATA_FOUND) { verification_method = VERIFIED_BY_HASH; update_verification_method(VERIFIED_BY_HASH); return EFI_SUCCESS; } else { LogError(L"check_db_hash(MokList, sha256hash) != DATA_FOUND\n"); } - if (cert && check_db_cert(L"MokList", shim_var, cert, sha256hash) == - DATA_FOUND) { + if (cert && check_db_cert(L"MokList", SHIM_LOCK_GUID, cert, sha256hash) + == DATA_FOUND) { verification_method = VERIFIED_BY_CERT; update_verification_method(VERIFIED_BY_CERT); return EFI_SUCCESS; @@ -724,14 +694,14 @@ static BOOLEAN secure_mode (void) #define check_size_line(data, datasize_in, hashbase, hashsize, l) ({ \ if ((unsigned long)hashbase > \ (unsigned long)data + datasize_in) { \ - status = EFI_INVALID_PARAMETER; \ + efi_status = EFI_INVALID_PARAMETER; \ perror(L"shim.c:%d Invalid hash base 0x%016x\n", l, \ hashbase); \ goto done; \ } \ if ((unsigned long)hashbase + hashsize > \ (unsigned long)data + datasize_in) { \ - status = EFI_INVALID_PARAMETER; \ + efi_status = EFI_INVALID_PARAMETER; \ perror(L"shim.c:%d Invalid hash size 0x%016x\n", l, \ hashsize); \ goto done; \ @@ -758,15 +728,11 @@ static EFI_STATUS generate_hash (char *data, unsigned int datasize_in, unsigned int datasize; EFI_IMAGE_SECTION_HEADER *Section; EFI_IMAGE_SECTION_HEADER *SectionHeader = NULL; - EFI_STATUS status = EFI_SUCCESS; + EFI_STATUS efi_status = EFI_SUCCESS; EFI_IMAGE_DOS_HEADER *DosHdr = (void *)data; unsigned int PEHdr_offset = 0; - if (datasize_in < 0) { - perror(L"Invalid data size\n"); - return EFI_INVALID_PARAMETER; - } - size = datasize = (unsigned int)datasize_in; + size = datasize = datasize_in; if (datasize <= sizeof (*DosHdr) || DosHdr->e_magic != EFI_IMAGE_DOS_SIGNATURE) { @@ -788,7 +754,7 @@ static EFI_STATUS generate_hash (char *data, unsigned int datasize_in, if (!Sha256Init(sha256ctx) || !Sha1Init(sha1ctx)) { perror(L"Unable to initialise hash\n"); - status = EFI_OUT_OF_RESOURCES; + efi_status = EFI_OUT_OF_RESOURCES; goto done; } @@ -801,7 +767,7 @@ static EFI_STATUS generate_hash (char *data, unsigned int datasize_in, if (!(Sha256Update(sha256ctx, hashbase, hashsize)) || !(Sha1Update(sha1ctx, hashbase, hashsize))) { perror(L"Unable to generate hash\n"); - status = EFI_OUT_OF_RESOURCES; + efi_status = EFI_OUT_OF_RESOURCES; goto done; } @@ -814,7 +780,7 @@ static EFI_STATUS generate_hash (char *data, unsigned int datasize_in, if (!(Sha256Update(sha256ctx, hashbase, hashsize)) || !(Sha1Update(sha1ctx, hashbase, hashsize))) { perror(L"Unable to generate hash\n"); - status = EFI_OUT_OF_RESOURCES; + efi_status = EFI_OUT_OF_RESOURCES; goto done; } @@ -824,7 +790,7 @@ static EFI_STATUS generate_hash (char *data, unsigned int datasize_in, hashsize = context->SizeOfHeaders - (unsigned long)((char *)dd - data); if (hashsize > datasize_in) { perror(L"Data Directory size %d is invalid\n", hashsize); - status = EFI_INVALID_PARAMETER; + efi_status = EFI_INVALID_PARAMETER; goto done; } check_size(data, datasize_in, hashbase, hashsize); @@ -832,7 +798,7 @@ static EFI_STATUS generate_hash (char *data, unsigned int datasize_in, if (!(Sha256Update(sha256ctx, hashbase, hashsize)) || !(Sha1Update(sha1ctx, hashbase, hashsize))) { perror(L"Unable to generate hash\n"); - status = EFI_OUT_OF_RESOURCES; + efi_status = EFI_OUT_OF_RESOURCES; goto done; } @@ -852,14 +818,14 @@ static EFI_STATUS generate_hash (char *data, unsigned int datasize_in, (index * sizeof(*SectionPtr))); if (!SectionPtr) { perror(L"Malformed section %d\n", index); - status = EFI_INVALID_PARAMETER; + efi_status = EFI_INVALID_PARAMETER; goto done; } /* Validate section size is within image. */ if (SectionPtr->SizeOfRawData > datasize - SumOfBytesHashed - SumOfSectionBytes) { perror(L"Malformed section %d size\n", index); - status = EFI_INVALID_PARAMETER; + efi_status = EFI_INVALID_PARAMETER; goto done; } SumOfSectionBytes += SectionPtr->SizeOfRawData; @@ -868,7 +834,7 @@ static EFI_STATUS generate_hash (char *data, unsigned int datasize_in, SectionHeader = (EFI_IMAGE_SECTION_HEADER *) AllocateZeroPool (sizeof (EFI_IMAGE_SECTION_HEADER) * context->PEHdr->Pe32.FileHeader.NumberOfSections); if (SectionHeader == NULL) { perror(L"Unable to allocate section header\n"); - status = EFI_OUT_OF_RESOURCES; + efi_status = EFI_OUT_OF_RESOURCES; goto done; } @@ -878,6 +844,19 @@ static EFI_STATUS generate_hash (char *data, unsigned int datasize_in, sizeof (UINT32) + sizeof (EFI_IMAGE_FILE_HEADER) + context->PEHdr->Pe32.FileHeader.SizeOfOptionalHeader); + /* But check it again just for better error messaging, and so + * clang-analyzer doesn't get confused. */ + if (Section == NULL) { + uint64_t addr; + + addr = PEHdr_offset + sizeof(UINT32) + sizeof(EFI_IMAGE_FILE_HEADER) + + context->PEHdr->Pe32.FileHeader.SizeOfOptionalHeader; + perror(L"Malformed file header.\n"); + perror(L"Image address for Section 0 is 0x%016llx\n", addr); + perror(L"File size is 0x%016llx\n", datasize); + efi_status = EFI_INVALID_PARAMETER; + goto done; + } /* Sort the section headers */ for (index = 0; index < context->PEHdr->Pe32.FileHeader.NumberOfSections; index++) { @@ -900,7 +879,7 @@ static EFI_STATUS generate_hash (char *data, unsigned int datasize_in, if (!hashbase) { perror(L"Malformed section header\n"); - status = EFI_INVALID_PARAMETER; + efi_status = EFI_INVALID_PARAMETER; goto done; } @@ -908,7 +887,7 @@ static EFI_STATUS generate_hash (char *data, unsigned int datasize_in, if (Section->SizeOfRawData > datasize - Section->PointerToRawData) { perror(L"Malformed section raw size %d\n", index); - status = EFI_INVALID_PARAMETER; + efi_status = EFI_INVALID_PARAMETER; goto done; } hashsize = (unsigned int) Section->SizeOfRawData; @@ -917,7 +896,7 @@ static EFI_STATUS generate_hash (char *data, unsigned int datasize_in, if (!(Sha256Update(sha256ctx, hashbase, hashsize)) || !(Sha1Update(sha1ctx, hashbase, hashsize))) { perror(L"Unable to generate hash\n"); - status = EFI_OUT_OF_RESOURCES; + efi_status = EFI_OUT_OF_RESOURCES; goto done; } SumOfBytesHashed += Section->SizeOfRawData; @@ -931,11 +910,11 @@ static EFI_STATUS generate_hash (char *data, unsigned int datasize_in, if ((datasize - SumOfBytesHashed < context->SecDir->Size) || (SumOfBytesHashed + hashsize != context->SecDir->VirtualAddress)) { perror(L"Malformed binary after Attribute Certificate Table\n"); - Print(L"datasize: %u SumOfBytesHashed: %u SecDir->Size: %lu\n", - datasize, SumOfBytesHashed, context->SecDir->Size); - Print(L"hashsize: %u SecDir->VirtualAddress: 0x%08lx\n", - hashsize, context->SecDir->VirtualAddress); - status = EFI_INVALID_PARAMETER; + console_print(L"datasize: %u SumOfBytesHashed: %u SecDir->Size: %lu\n", + datasize, SumOfBytesHashed, context->SecDir->Size); + console_print(L"hashsize: %u SecDir->VirtualAddress: 0x%08lx\n", + hashsize, context->SecDir->VirtualAddress); + efi_status = EFI_INVALID_PARAMETER; goto done; } check_size(data, datasize_in, hashbase, hashsize); @@ -943,14 +922,16 @@ static EFI_STATUS generate_hash (char *data, unsigned int datasize_in, if (!(Sha256Update(sha256ctx, hashbase, hashsize)) || !(Sha1Update(sha1ctx, hashbase, hashsize))) { perror(L"Unable to generate hash\n"); - status = EFI_OUT_OF_RESOURCES; + efi_status = EFI_OUT_OF_RESOURCES; goto done; } +#if 1 + } +#else // we have to migrate to doing this later :/ SumOfBytesHashed += hashsize; } -#if 0 // we have to migrate to doing this later :/ /* Hash all remaining data */ if (datasize > SumOfBytesHashed) { hashbase = data + SumOfBytesHashed; @@ -961,7 +942,7 @@ static EFI_STATUS generate_hash (char *data, unsigned int datasize_in, if (!(Sha256Update(sha256ctx, hashbase, hashsize)) || !(Sha1Update(sha1ctx, hashbase, hashsize))) { perror(L"Unable to generate hash\n"); - status = EFI_OUT_OF_RESOURCES; + efi_status = EFI_OUT_OF_RESOURCES; goto done; } @@ -972,7 +953,7 @@ static EFI_STATUS generate_hash (char *data, unsigned int datasize_in, if (!(Sha256Final(sha256ctx, sha256hash)) || !(Sha1Final(sha1ctx, sha1hash))) { perror(L"Unable to finalise hash\n"); - status = EFI_OUT_OF_RESOURCES; + efi_status = EFI_OUT_OF_RESOURCES; goto done; } @@ -984,34 +965,7 @@ done: if (sha256ctx) FreePool(sha256ctx); - return status; -} - -/* - * Ensure that the MOK database hasn't been set or modified from an OS - */ -static EFI_STATUS verify_mok (void) { - EFI_GUID shim_lock_guid = SHIM_LOCK_GUID; - EFI_STATUS status = EFI_SUCCESS; - UINT8 *MokListData = NULL; - UINTN MokListDataSize = 0; - UINT32 attributes; - - status = get_variable_attr(L"MokList", &MokListData, &MokListDataSize, - shim_lock_guid, &attributes); - - if (!EFI_ERROR(status) && attributes & EFI_VARIABLE_RUNTIME_ACCESS) { - perror(L"MokList is compromised!\nErase all keys in MokList!\n"); - if (LibDeleteVariable(L"MokList", &shim_lock_guid) != EFI_SUCCESS) { - perror(L"Failed to erase MokList\n"); - return EFI_SECURITY_VIOLATION; - } - } - - if (MokListData) - FreePool(MokListData); - - return EFI_SUCCESS; + return efi_status; } /* @@ -1021,10 +975,12 @@ static EFI_STATUS verify_buffer (char *data, int datasize, PE_COFF_LOADER_IMAGE_CONTEXT *context, UINT8 *sha256hash, UINT8 *sha1hash) { - EFI_STATUS status = EFI_SECURITY_VIOLATION; + EFI_STATUS efi_status = EFI_SECURITY_VIOLATION; WIN_CERTIFICATE_EFI_PKCS *cert = NULL; unsigned int size = datasize; - EFI_GUID shim_var = SHIM_LOCK_GUID; + + if (datasize < 0) + return EFI_INVALID_PARAMETER; if (context->SecDir->Size != 0) { if (context->SecDir->Size >= size) { @@ -1060,41 +1016,32 @@ static EFI_STATUS verify_buffer (char *data, int datasize, */ drain_openssl_errors(); - status = generate_hash(data, datasize, context, sha256hash, sha1hash); - if (status != EFI_SUCCESS) { - LogError(L"generate_hash: %r\n", status); - return status; - } - - /* - * Check that the MOK database hasn't been modified - */ - status = verify_mok(); - if (status != EFI_SUCCESS) { - LogError(L"verify_mok: %r\n", status); - return status; + efi_status = generate_hash(data, datasize, context, sha256hash, sha1hash); + if (EFI_ERROR(efi_status)) { + LogError(L"generate_hash: %r\n", efi_status); + return efi_status; } /* * Ensure that the binary isn't blacklisted */ - status = check_blacklist(cert, sha256hash, sha1hash); - if (status != EFI_SUCCESS) { + efi_status = check_blacklist(cert, sha256hash, sha1hash); + if (EFI_ERROR(efi_status)) { perror(L"Binary is blacklisted\n"); - LogError(L"Binary is blacklisted: %r\n", status); - return status; + LogError(L"Binary is blacklisted: %r\n", efi_status); + return efi_status; } /* * Check whether the binary is whitelisted in any of the firmware * databases */ - status = check_whitelist(cert, sha256hash, sha1hash); - if (status == EFI_SUCCESS) { - drain_openssl_errors(); - return status; + efi_status = check_whitelist(cert, sha256hash, sha1hash); + if (EFI_ERROR(efi_status)) { + LogError(L"check_whitelist(): %r\n", efi_status); } else { - LogError(L"check_whitelist(): %r\n", status); + drain_openssl_errors(); + return efi_status; } if (cert) { @@ -1108,10 +1055,11 @@ static EFI_STATUS verify_buffer (char *data, int datasize, shim_cert, sizeof(shim_cert), sha256hash, SHA256_DIGEST_SIZE)) { update_verification_method(VERIFIED_BY_CERT); - tpm_measure_variable(L"Shim", shim_var, sizeof(shim_cert), shim_cert); - status = EFI_SUCCESS; + tpm_measure_variable(L"Shim", SHIM_LOCK_GUID, + sizeof(shim_cert), shim_cert); + efi_status = EFI_SUCCESS; drain_openssl_errors(); - return status; + return efi_status; } else { LogError(L"AuthenticodeVerify(shim_cert) failed\n"); } @@ -1126,10 +1074,11 @@ static EFI_STATUS verify_buffer (char *data, int datasize, vendor_cert, vendor_cert_size, sha256hash, SHA256_DIGEST_SIZE)) { update_verification_method(VERIFIED_BY_CERT); - tpm_measure_variable(L"Shim", shim_var, vendor_cert_size, vendor_cert); - status = EFI_SUCCESS; + tpm_measure_variable(L"Shim", SHIM_LOCK_GUID, + vendor_cert_size, vendor_cert); + efi_status = EFI_SUCCESS; drain_openssl_errors(); - return status; + return efi_status; } else { LogError(L"AuthenticodeVerify(vendor_cert) failed\n"); } @@ -1138,8 +1087,8 @@ static EFI_STATUS verify_buffer (char *data, int datasize, LogError(L"Binary is not whitelisted\n"); crypterr(EFI_SECURITY_VIOLATION); PrintErrors(); - status = EFI_SECURITY_VIOLATION; - return status; + efi_status = EFI_SECURITY_VIOLATION; + return efi_status; } /* @@ -1266,7 +1215,9 @@ static EFI_STATUS read_header(void *data, unsigned int datasize, return EFI_UNSUPPORTED; } - if (context->SecDir->VirtualAddress >= datasize) { + if (context->SecDir->VirtualAddress > datasize || + (context->SecDir->VirtualAddress == datasize && + context->SecDir->Size > 0)) { perror(L"Malformed security header\n"); return EFI_INVALID_PARAMETER; } @@ -1277,7 +1228,10 @@ static EFI_STATUS read_header(void *data, unsigned int datasize, * Once the image has been loaded it needs to be validated and relocated */ static EFI_STATUS handle_image (void *data, unsigned int datasize, - EFI_LOADED_IMAGE *li) + EFI_LOADED_IMAGE *li, + EFI_IMAGE_ENTRY_POINT *entry_point, + EFI_PHYSICAL_ADDRESS *alloc_address, + UINTN *alloc_pages) { EFI_STATUS efi_status; char *buffer; @@ -1286,7 +1240,6 @@ static EFI_STATUS handle_image (void *data, unsigned int datasize, char *base, *end; PE_COFF_LOADER_IMAGE_CONTEXT context; unsigned int alignment, alloc_size; - EFI_PHYSICAL_ADDRESS alloc_address; int found_entry_point = 0; UINT8 sha1hash[SHA1_DIGEST_SIZE]; UINT8 sha256hash[SHA256_DIGEST_SIZE]; @@ -1295,7 +1248,7 @@ static EFI_STATUS handle_image (void *data, unsigned int datasize, * The binary header contains relevant context and section pointers */ efi_status = read_header(data, datasize, &context); - if (efi_status != EFI_SUCCESS) { + if (EFI_ERROR(efi_status)) { perror(L"Failed to read header: %r\n", efi_status); return efi_status; } @@ -1305,11 +1258,19 @@ static EFI_STATUS handle_image (void *data, unsigned int datasize, */ efi_status = generate_hash(data, datasize, &context, sha256hash, sha1hash); - if (efi_status != EFI_SUCCESS) + if (EFI_ERROR(efi_status)) return efi_status; /* Measure the binary into the TPM */ +#ifdef REQUIRE_TPM + efi_status = +#endif tpm_log_pe((EFI_PHYSICAL_ADDRESS)(UINTN)data, datasize, sha1hash, 4); +#ifdef REQUIRE_TPM + if (efi_status != EFI_SUCCESS) { + return efi_status; + } +#endif if (secure_mode ()) { efi_status = verify_buffer(data, datasize, &context, @@ -1320,7 +1281,7 @@ static EFI_STATUS handle_image (void *data, unsigned int datasize, return efi_status; } else { if (verbose) - console_notify(L"Verification succeeded"); + console_print(L"Verification succeeded\n"); } } @@ -1344,27 +1305,23 @@ static EFI_STATUS handle_image (void *data, unsigned int datasize, alloc_size = ALIGN_VALUE(context.ImageSize + context.SectionAlignment, PAGE_SIZE); + *alloc_pages = alloc_size / PAGE_SIZE; - efi_status = uefi_call_wrapper (BS->AllocatePages, 4, - AllocateAnyPages, - EfiLoaderCode, - alloc_size / PAGE_SIZE, - &alloc_address); - - if (efi_status != EFI_SUCCESS) { + efi_status = gBS->AllocatePages(AllocateAnyPages, EfiLoaderCode, + *alloc_pages, alloc_address); + if (EFI_ERROR(efi_status)) { perror(L"Failed to allocate image buffer\n"); return EFI_OUT_OF_RESOURCES; } - buffer = (void *)ALIGN_VALUE((unsigned long)alloc_address, alignment); + buffer = (void *)ALIGN_VALUE((unsigned long)*alloc_address, alignment); CopyMem(buffer, data, context.SizeOfHeaders); - entry_point = ImageAddress(buffer, context.ImageSize, context.EntryPoint); - if (!entry_point) { + *entry_point = ImageAddress(buffer, context.ImageSize, context.EntryPoint); + if (!*entry_point) { perror(L"Entry point is invalid\n"); - uefi_call_wrapper(BS->FreePages, 2, alloc_address, - alloc_size / PAGE_SIZE); + gBS->FreePages(*alloc_address, *alloc_pages); return EFI_UNSUPPORTED; } @@ -1398,8 +1355,7 @@ static EFI_STATUS handle_image (void *data, unsigned int datasize, if (end < base) { perror(L"Section %d has negative size\n", i); - uefi_call_wrapper(BS->FreePages, 2, alloc_address, - alloc_size / PAGE_SIZE); + gBS->FreePages(*alloc_address, *alloc_pages); return EFI_UNSUPPORTED; } @@ -1478,7 +1434,7 @@ static EFI_STATUS handle_image (void *data, unsigned int datasize, efi_status = relocate_coff(&context, RelocSection, data, buffer); - if (efi_status != EFI_SUCCESS) { + if (EFI_ERROR(efi_status)) { perror(L"Relocation failed: %r\n", efi_status); FreePool(buffer); return efi_status; @@ -1493,8 +1449,10 @@ static EFI_STATUS handle_image (void *data, unsigned int datasize, li->ImageSize = context.ImageSize; /* Pass the load options to the second stage loader */ - li->LoadOptions = load_options; - li->LoadOptionsSize = load_options_size; + if ( load_options ) { + li->LoadOptions = load_options; + li->LoadOptionsSize = load_options_size; + } if (!found_entry_point) { perror(L"Entry point is not within sections\n"); @@ -1511,20 +1469,20 @@ static EFI_STATUS handle_image (void *data, unsigned int datasize, static int should_use_fallback(EFI_HANDLE image_handle) { - EFI_GUID loaded_image_protocol = LOADED_IMAGE_PROTOCOL; EFI_LOADED_IMAGE *li; unsigned int pathlen = 0; CHAR16 *bootpath = NULL; EFI_FILE_IO_INTERFACE *fio = NULL; EFI_FILE *vh = NULL; EFI_FILE *fh = NULL; - EFI_STATUS rc; + EFI_STATUS efi_status; int ret = 0; - rc = uefi_call_wrapper(BS->HandleProtocol, 3, image_handle, - &loaded_image_protocol, (void **)&li); - if (EFI_ERROR(rc)) { - perror(L"Could not get image for bootx64.efi: %r\n", rc); + efi_status = gBS->HandleProtocol(image_handle, &EFI_LOADED_IMAGE_GUID, + (void **)&li); + if (EFI_ERROR(efi_status)) { + perror(L"Could not get image for bootx64.efi: %r\n", + efi_status); return 0; } @@ -1545,27 +1503,28 @@ should_use_fallback(EFI_HANDLE image_handle) if (pathlen < 5 || StrCaseCmp(bootpath + pathlen - 4, L".EFI")) goto error; - rc = uefi_call_wrapper(BS->HandleProtocol, 3, li->DeviceHandle, - &FileSystemProtocol, (void **)&fio); - if (EFI_ERROR(rc)) { - perror(L"Could not get fio for li->DeviceHandle: %r\n", rc); + efi_status = gBS->HandleProtocol(li->DeviceHandle, &FileSystemProtocol, + (void **) &fio); + if (EFI_ERROR(efi_status)) { + perror(L"Could not get fio for li->DeviceHandle: %r\n", + efi_status); goto error; } - rc = uefi_call_wrapper(fio->OpenVolume, 2, fio, &vh); - if (EFI_ERROR(rc)) { - perror(L"Could not open fio volume: %r\n", rc); + efi_status = fio->OpenVolume(fio, &vh); + if (EFI_ERROR(efi_status)) { + perror(L"Could not open fio volume: %r\n", efi_status); goto error; } - rc = uefi_call_wrapper(vh->Open, 5, vh, &fh, L"\\EFI\\BOOT" FALLBACK, - EFI_FILE_MODE_READ, 0); - if (EFI_ERROR(rc)) { + efi_status = vh->Open(vh, &fh, L"\\EFI\\BOOT" FALLBACK, + EFI_FILE_MODE_READ, 0); + if (EFI_ERROR(efi_status)) { /* Do not print the error here - this is an acceptable case * for removable media, where we genuinely don't want * fallback.efi to exist. - * Print(L"Could not open \"\\EFI\\BOOT%s\": %d\n", FALLBACK, - * rc); + * Print(L"Could not open \"\\EFI\\BOOT%s\": %r\n", FALLBACK, + * efi_status); */ goto error; } @@ -1573,9 +1532,9 @@ should_use_fallback(EFI_HANDLE image_handle) ret = 1; error: if (fh) - uefi_call_wrapper(fh->Close, 1, fh); + fh->Close(fh); if (vh) - uefi_call_wrapper(vh->Close, 1, vh); + vh->Close(vh); if (bootpath) FreePool(bootpath); @@ -1586,8 +1545,9 @@ error: * Generate the path of an executable given shim's path and the name * of the executable */ -static EFI_STATUS generate_path(EFI_LOADED_IMAGE *li, CHAR16 *ImagePath, - CHAR16 **PathName) +static EFI_STATUS generate_path_from_image_path(EFI_LOADED_IMAGE *li, + CHAR16 *ImagePath, + CHAR16 **PathName) { EFI_DEVICE_PATH *devpath; unsigned int i; @@ -1678,8 +1638,6 @@ error: static EFI_STATUS load_image (EFI_LOADED_IMAGE *li, void **data, int *datasize, CHAR16 *PathName) { - EFI_GUID simple_file_system_protocol = SIMPLE_FILE_SYSTEM_PROTOCOL; - EFI_GUID file_info_id = EFI_FILE_INFO_ID; EFI_STATUS efi_status; EFI_HANDLE device; EFI_FILE_INFO *fileinfo = NULL; @@ -1692,18 +1650,15 @@ static EFI_STATUS load_image (EFI_LOADED_IMAGE *li, void **data, /* * Open the device */ - efi_status = uefi_call_wrapper(BS->HandleProtocol, 3, device, - &simple_file_system_protocol, - (void **)&drive); - - if (efi_status != EFI_SUCCESS) { + efi_status = gBS->HandleProtocol(device, &EFI_SIMPLE_FILE_SYSTEM_GUID, + (void **) &drive); + if (EFI_ERROR(efi_status)) { perror(L"Failed to find fs: %r\n", efi_status); goto error; } - efi_status = uefi_call_wrapper(drive->OpenVolume, 2, drive, &root); - - if (efi_status != EFI_SUCCESS) { + efi_status = drive->OpenVolume(drive, &root); + if (EFI_ERROR(efi_status)) { perror(L"Failed to open fs: %r\n", efi_status); goto error; } @@ -1711,10 +1666,8 @@ static EFI_STATUS load_image (EFI_LOADED_IMAGE *li, void **data, /* * And then open the file */ - efi_status = uefi_call_wrapper(root->Open, 5, root, &grub, PathName, - EFI_FILE_MODE_READ, 0); - - if (efi_status != EFI_SUCCESS) { + efi_status = root->Open(root, &grub, PathName, EFI_FILE_MODE_READ, 0); + if (EFI_ERROR(efi_status)) { perror(L"Failed to open %s - %r\n", PathName, efi_status); goto error; } @@ -1731,9 +1684,8 @@ static EFI_STATUS load_image (EFI_LOADED_IMAGE *li, void **data, * Find out how big the file is in order to allocate the storage * buffer */ - efi_status = uefi_call_wrapper(grub->GetInfo, 4, grub, &file_info_id, - &buffersize, fileinfo); - + efi_status = grub->GetInfo(grub, &EFI_FILE_INFO_GUID, &buffersize, + fileinfo); if (efi_status == EFI_BUFFER_TOO_SMALL) { FreePool(fileinfo); fileinfo = AllocatePool(buffersize); @@ -1742,20 +1694,17 @@ static EFI_STATUS load_image (EFI_LOADED_IMAGE *li, void **data, efi_status = EFI_OUT_OF_RESOURCES; goto error; } - efi_status = uefi_call_wrapper(grub->GetInfo, 4, grub, - &file_info_id, &buffersize, - fileinfo); + efi_status = grub->GetInfo(grub, &EFI_FILE_INFO_GUID, + &buffersize, fileinfo); } - if (efi_status != EFI_SUCCESS) { + if (EFI_ERROR(efi_status)) { perror(L"Unable to get file info: %r\n", efi_status); goto error; } buffersize = fileinfo->FileSize; - *data = AllocatePool(buffersize); - if (!*data) { perror(L"Unable to allocate file buffer\n"); efi_status = EFI_OUT_OF_RESOURCES; @@ -1765,18 +1714,15 @@ static EFI_STATUS load_image (EFI_LOADED_IMAGE *li, void **data, /* * Perform the actual read */ - efi_status = uefi_call_wrapper(grub->Read, 3, grub, &buffersize, - *data); - + efi_status = grub->Read(grub, &buffersize, *data); if (efi_status == EFI_BUFFER_TOO_SMALL) { FreePool(*data); *data = AllocatePool(buffersize); - efi_status = uefi_call_wrapper(grub->Read, 3, grub, - &buffersize, *data); + efi_status = grub->Read(grub, &buffersize, *data); } - - if (efi_status != EFI_SUCCESS) { - perror(L"Unexpected return from initial read: %r, buffersize %x\n", efi_status, buffersize); + if (EFI_ERROR(efi_status)) { + perror(L"Unexpected return from initial read: %r, buffersize %x\n", + efi_status, buffersize); goto error; } @@ -1802,54 +1748,75 @@ error: */ EFI_STATUS shim_verify (void *buffer, UINT32 size) { - EFI_STATUS status = EFI_SUCCESS; + EFI_STATUS efi_status = EFI_SUCCESS; PE_COFF_LOADER_IMAGE_CONTEXT context; UINT8 sha1hash[SHA1_DIGEST_SIZE]; UINT8 sha256hash[SHA256_DIGEST_SIZE]; + if ((INT32)size < 0) + return EFI_INVALID_PARAMETER; + loader_is_participating = 1; in_protocol = 1; - if (!secure_mode()) + efi_status = read_header(buffer, size, &context); + if (EFI_ERROR(efi_status)) goto done; - status = read_header(buffer, size, &context); - if (status != EFI_SUCCESS) + efi_status = generate_hash(buffer, size, &context, + sha256hash, sha1hash); + if (EFI_ERROR(efi_status)) goto done; - status = generate_hash(buffer, size, &context, sha256hash, sha1hash); - if (status != EFI_SUCCESS) + /* Measure the binary into the TPM */ +#ifdef REQUIRE_TPM + efi_status = +#endif + tpm_log_pe((EFI_PHYSICAL_ADDRESS)(UINTN)buffer, size, sha1hash, 4); +#ifdef REQUIRE_TPM + if (EFI_ERROR(efi_status)) goto done; +#endif - status = verify_buffer(buffer, size, &context, sha256hash, sha1hash); + if (!secure_mode()) { + efi_status = EFI_SUCCESS; + goto done; + } + + efi_status = verify_buffer(buffer, size, &context, + sha256hash, sha1hash); done: in_protocol = 0; - return status; + return efi_status; } static EFI_STATUS shim_hash (char *data, int datasize, PE_COFF_LOADER_IMAGE_CONTEXT *context, UINT8 *sha256hash, UINT8 *sha1hash) { - EFI_STATUS status; + EFI_STATUS efi_status; + + if (datasize < 0) + return EFI_INVALID_PARAMETER; in_protocol = 1; - status = generate_hash(data, datasize, context, sha256hash, sha1hash); + efi_status = generate_hash(data, datasize, context, + sha256hash, sha1hash); in_protocol = 0; - return status; + return efi_status; } static EFI_STATUS shim_read_header(void *data, unsigned int datasize, PE_COFF_LOADER_IMAGE_CONTEXT *context) { - EFI_STATUS status; + EFI_STATUS efi_status; in_protocol = 1; - status = read_header(data, datasize, context); + efi_status = read_header(data, datasize, context); in_protocol = 0; - return status; + return efi_status; } /* @@ -1857,9 +1824,11 @@ static EFI_STATUS shim_read_header(void *data, unsigned int datasize, */ EFI_STATUS start_image(EFI_HANDLE image_handle, CHAR16 *ImagePath) { - EFI_GUID loaded_image_protocol = LOADED_IMAGE_PROTOCOL; EFI_STATUS efi_status; EFI_LOADED_IMAGE *li, li_bak; + EFI_IMAGE_ENTRY_POINT entry_point; + EFI_PHYSICAL_ADDRESS alloc_address; + UINTN alloc_pages; CHAR16 *PathName = NULL; void *sourcebuffer = NULL; UINT64 sourcesize = 0; @@ -1870,10 +1839,9 @@ EFI_STATUS start_image(EFI_HANDLE image_handle, CHAR16 *ImagePath) * We need to refer to the loaded image protocol on the running * binary in order to find our path */ - efi_status = uefi_call_wrapper(BS->HandleProtocol, 3, image_handle, - &loaded_image_protocol, (void **)&li); - - if (efi_status != EFI_SUCCESS) { + efi_status = gBS->HandleProtocol(image_handle, &EFI_LOADED_IMAGE_GUID, + (void **)&li); + if (EFI_ERROR(efi_status)) { perror(L"Unable to init protocol\n"); return efi_status; } @@ -1881,33 +1849,36 @@ EFI_STATUS start_image(EFI_HANDLE image_handle, CHAR16 *ImagePath) /* * Build a new path from the existing one plus the executable name */ - efi_status = generate_path(li, ImagePath, &PathName); - - if (efi_status != EFI_SUCCESS) { - perror(L"Unable to generate path %s: %r\n", ImagePath, efi_status); + efi_status = generate_path_from_image_path(li, ImagePath, &PathName); + if (EFI_ERROR(efi_status)) { + perror(L"Unable to generate path %s: %r\n", ImagePath, + efi_status); goto done; } if (findNetboot(li->DeviceHandle)) { efi_status = parseNetbootinfo(image_handle); - if (efi_status != EFI_SUCCESS) { + if (EFI_ERROR(efi_status)) { perror(L"Netboot parsing failed: %r\n", efi_status); return EFI_PROTOCOL_ERROR; } efi_status = FetchNetbootimage(image_handle, &sourcebuffer, &sourcesize); - if (efi_status != EFI_SUCCESS) { - perror(L"Unable to fetch TFTP image: %r\n", efi_status); + if (EFI_ERROR(efi_status)) { + perror(L"Unable to fetch TFTP image: %r\n", + efi_status); return efi_status; } data = sourcebuffer; datasize = sourcesize; #if defined(ENABLE_HTTPBOOT) } else if (find_httpboot(li->DeviceHandle)) { - efi_status = httpboot_fetch_buffer (image_handle, &sourcebuffer, + efi_status = httpboot_fetch_buffer (image_handle, + &sourcebuffer, &sourcesize); - if (efi_status != EFI_SUCCESS) { - perror(L"Unable to fetch HTTP image: %r\n", efi_status); + if (EFI_ERROR(efi_status)) { + perror(L"Unable to fetch HTTP image: %r\n", + efi_status); return efi_status; } data = sourcebuffer; @@ -1918,15 +1889,20 @@ EFI_STATUS start_image(EFI_HANDLE image_handle, CHAR16 *ImagePath) * Read the new executable off disk */ efi_status = load_image(li, &data, &datasize, PathName); - - if (efi_status != EFI_SUCCESS) { - perror(L"Failed to load image %s: %r\n", PathName, efi_status); + if (EFI_ERROR(efi_status)) { + perror(L"Failed to load image %s: %r\n", + PathName, efi_status); PrintErrors(); ClearErrors(); goto done; } } + if (datasize < 0) { + efi_status = EFI_INVALID_PARAMETER; + goto done; + } + /* * We need to modify the loaded image protocol entry before running * the new binary, so back it up @@ -1936,9 +1912,9 @@ EFI_STATUS start_image(EFI_HANDLE image_handle, CHAR16 *ImagePath) /* * Verify and, if appropriate, relocate and execute the executable */ - efi_status = handle_image(data, datasize, li); - - if (efi_status != EFI_SUCCESS) { + efi_status = handle_image(data, datasize, li, &entry_point, + &alloc_address, &alloc_pages); + if (EFI_ERROR(efi_status)) { perror(L"Failed to load image: %r\n", efi_status); PrintErrors(); ClearErrors(); @@ -1951,7 +1927,7 @@ EFI_STATUS start_image(EFI_HANDLE image_handle, CHAR16 *ImagePath) /* * The binary is trusted and relocated. Run it */ - efi_status = uefi_call_wrapper(entry_point, 2, image_handle, systab); + efi_status = entry_point(image_handle, systab); /* * Restore our original loaded image values @@ -1980,8 +1956,8 @@ EFI_STATUS init_grub(EFI_HANDLE image_handle) if (efi_status == EFI_SECURITY_VIOLATION || efi_status == EFI_ACCESS_DENIED) { efi_status = start_image(image_handle, MOK_MANAGER); - if (efi_status != EFI_SUCCESS) { - Print(L"start_image() returned %r\n", efi_status); + if (EFI_ERROR(efi_status)) { + console_print(L"start_image() returned %r\n", efi_status); msleep(2000000); return efi_status; } @@ -1990,363 +1966,14 @@ EFI_STATUS init_grub(EFI_HANDLE image_handle) use_fb ? FALLBACK : second_stage); } - if (efi_status != EFI_SUCCESS) { - Print(L"start_image() returned %r\n", efi_status); + if (EFI_ERROR(efi_status)) { + console_print(L"start_image() returned %r\n", efi_status); msleep(2000000); } return efi_status; } -/* - * Measure some of the MOK variables into the TPM. We measure the entirety - * of MokList into PCR 14, and also measure the raw MokSBState there. PCR 7 - * will be extended with MokSBState in the Microsoft format, and we'll - * measure any matching hashes or certificates later on in order to behave - * consistently with the PCR 7 spec. - */ -EFI_STATUS measure_mok() -{ - EFI_GUID shim_lock_guid = SHIM_LOCK_GUID; - EFI_STATUS efi_status, ret = EFI_SUCCESS; - UINT8 *Data = NULL; - UINTN DataSize = 0; - - efi_status = get_variable(L"MokList", &Data, &DataSize, shim_lock_guid); - if (!EFI_ERROR(efi_status)) { - efi_status = tpm_log_event((EFI_PHYSICAL_ADDRESS)(UINTN)Data, - DataSize, 14, (CHAR8 *)"MokList"); - FreePool(Data); - - if (EFI_ERROR(efi_status)) - ret = efi_status; - - } else { - ret = efi_status; - } - - efi_status = get_variable(L"MokListX", &Data, &DataSize, shim_lock_guid); - if (!EFI_ERROR(efi_status)) { - efi_status = tpm_log_event((EFI_PHYSICAL_ADDRESS)(UINTN)Data, - DataSize, 14, (CHAR8 *)"MokListX"); - FreePool(Data); - - if (EFI_ERROR(efi_status) && !EFI_ERROR(ret)) - ret = efi_status; - - } else if (!EFI_ERROR(ret)) { - ret = efi_status; - } - - efi_status = get_variable(L"MokSBState", &Data, &DataSize, - shim_lock_guid); - if (!EFI_ERROR(efi_status)) { - efi_status = tpm_measure_variable(L"MokSBState", - shim_lock_guid, - DataSize, Data); - if (!EFI_ERROR(efi_status)) { - efi_status = tpm_log_event((EFI_PHYSICAL_ADDRESS) - (UINTN)Data, DataSize, 14, - (CHAR8 *)"MokSBState"); - } - - FreePool(Data); - - if (EFI_ERROR(efi_status) && !EFI_ERROR(ret)) - ret = efi_status; - } else if (!EFI_ERROR(ret)) { - ret = efi_status; - } - - return efi_status; -} - -/* - * Copy the boot-services only MokList variable to the runtime-accessible - * MokListRT variable. It's not marked NV, so the OS can't modify it. - */ -EFI_STATUS mirror_mok_list() -{ - EFI_GUID shim_lock_guid = SHIM_LOCK_GUID; - EFI_STATUS efi_status; - UINT8 *Data = NULL; - UINTN DataSize = 0; - void *FullData = NULL; - UINTN FullDataSize = 0; - EFI_SIGNATURE_LIST *CertList = NULL; - EFI_SIGNATURE_DATA *CertData = NULL; - uint8_t *p = NULL; - - efi_status = get_variable(L"MokList", &Data, &DataSize, shim_lock_guid); - if (efi_status != EFI_SUCCESS) - DataSize = 0; - - if (vendor_cert_size) { - FullDataSize = DataSize - + sizeof (*CertList) - + sizeof (EFI_GUID) - + vendor_cert_size - ; - FullData = AllocatePool(FullDataSize); - if (!FullData) { - perror(L"Failed to allocate space for MokListRT\n"); - return EFI_OUT_OF_RESOURCES; - } - p = FullData; - - if (efi_status == EFI_SUCCESS && DataSize > 0) { - CopyMem(p, Data, DataSize); - p += DataSize; - } - CertList = (EFI_SIGNATURE_LIST *)p; - p += sizeof (*CertList); - CertData = (EFI_SIGNATURE_DATA *)p; - p += sizeof (EFI_GUID); - - CertList->SignatureType = EFI_CERT_X509_GUID; - CertList->SignatureListSize = vendor_cert_size - + sizeof (*CertList) - + sizeof (*CertData) - -1; - CertList->SignatureHeaderSize = 0; - CertList->SignatureSize = vendor_cert_size + sizeof (EFI_GUID); - - CertData->SignatureOwner = SHIM_LOCK_GUID; - CopyMem(p, vendor_cert, vendor_cert_size); - } else { - FullDataSize = DataSize; - FullData = Data; - } - - if (FullDataSize) { - efi_status = uefi_call_wrapper(RT->SetVariable, 5, L"MokListRT", - &shim_lock_guid, - EFI_VARIABLE_BOOTSERVICE_ACCESS - | EFI_VARIABLE_RUNTIME_ACCESS, - FullDataSize, FullData); - if (efi_status != EFI_SUCCESS) { - perror(L"Failed to set MokListRT: %r\n", efi_status); - } - } - - return efi_status; -} - -/* - * Copy the boot-services only MokListX variable to the runtime-accessible - * MokListXRT variable. It's not marked NV, so the OS can't modify it. - */ -EFI_STATUS mirror_mok_list_x() -{ - EFI_GUID shim_lock_guid = SHIM_LOCK_GUID; - EFI_STATUS efi_status; - UINT8 *Data = NULL; - UINTN DataSize = 0; - - efi_status = get_variable(L"MokListX", &Data, &DataSize, shim_lock_guid); - if (efi_status != EFI_SUCCESS) - return efi_status; - - efi_status = uefi_call_wrapper(RT->SetVariable, 5, L"MokListXRT", - &shim_lock_guid, - EFI_VARIABLE_BOOTSERVICE_ACCESS - | EFI_VARIABLE_RUNTIME_ACCESS, - DataSize, Data); - if (efi_status != EFI_SUCCESS) { - console_error(L"Failed to set MokListRT", efi_status); - } - - return efi_status; -} - -/* - * Copy the boot-services only MokSBState variable to the runtime-accessible - * MokSBStateRT variable. It's not marked NV, so the OS can't modify it. - */ -EFI_STATUS mirror_mok_sb_state() -{ - EFI_GUID shim_lock_guid = SHIM_LOCK_GUID; - EFI_STATUS efi_status; - UINT8 *Data = NULL; - UINTN DataSize = 0; - - efi_status = get_variable(L"MokSBState", &Data, &DataSize, shim_lock_guid); - if (efi_status == EFI_SUCCESS) { - UINT8 *Data_RT = NULL; - UINTN DataSize_RT = 0; - - efi_status = get_variable(L"MokSBStateRT", &Data_RT, - &DataSize_RT, shim_lock_guid); - if (efi_status == EFI_SUCCESS) { - efi_status = uefi_call_wrapper(RT->SetVariable, 5, - L"MokSBStateRT", - &shim_lock_guid, - EFI_VARIABLE_BOOTSERVICE_ACCESS - | EFI_VARIABLE_RUNTIME_ACCESS - | EFI_VARIABLE_NON_VOLATILE, - 0, NULL); - } - - efi_status = uefi_call_wrapper(RT->SetVariable, 5, - L"MokSBStateRT", - &shim_lock_guid, - EFI_VARIABLE_BOOTSERVICE_ACCESS - | EFI_VARIABLE_RUNTIME_ACCESS, - DataSize, Data); - if (efi_status != EFI_SUCCESS) { - console_error(L"Failed to set MokSBStateRT", efi_status); - } - } - return efi_status; -} - -/* - * Check if a variable exists - */ -static BOOLEAN check_var(CHAR16 *varname) -{ - EFI_STATUS efi_status; - EFI_GUID shim_lock_guid = SHIM_LOCK_GUID; - UINTN size = sizeof(UINT32); - UINT32 MokVar; - UINT32 attributes; - - efi_status = uefi_call_wrapper(RT->GetVariable, 5, varname, - &shim_lock_guid, &attributes, - &size, (void *)&MokVar); - - if (efi_status == EFI_SUCCESS || efi_status == EFI_BUFFER_TOO_SMALL) - return TRUE; - - return FALSE; -} - -/* - * If the OS has set any of these variables we need to drop into MOK and - * handle them appropriately - */ -EFI_STATUS check_mok_request(EFI_HANDLE image_handle) -{ - EFI_STATUS efi_status; - - if (check_var(L"MokNew") || check_var(L"MokSB") || - check_var(L"MokPW") || check_var(L"MokAuth") || - check_var(L"MokDel") || check_var(L"MokDB") || - check_var(L"MokXNew") || check_var(L"MokXDel") || - check_var(L"MokXAuth")) { - efi_status = start_image(image_handle, MOK_MANAGER); - - if (efi_status != EFI_SUCCESS) { - perror(L"Failed to start MokManager: %r\n", efi_status); - return efi_status; - } - } - - return EFI_SUCCESS; -} - -/* - * Verify that MokSBState is valid, and if appropriate set insecure mode - */ -static EFI_STATUS check_mok_sb (void) -{ - EFI_GUID shim_lock_guid = SHIM_LOCK_GUID; - EFI_STATUS status = EFI_SUCCESS; - UINT8 MokSBState; - UINTN MokSBStateSize = sizeof(MokSBState); - UINT32 attributes; - - user_insecure_mode = 0; - ignore_db = 0; - - status = uefi_call_wrapper(RT->GetVariable, 5, L"MokSBState", &shim_lock_guid, - &attributes, &MokSBStateSize, &MokSBState); - if (status != EFI_SUCCESS) - return EFI_SECURITY_VIOLATION; - - /* - * Delete and ignore the variable if it's been set from or could be - * modified by the OS - */ - if (attributes & EFI_VARIABLE_RUNTIME_ACCESS) { - perror(L"MokSBState is compromised! Clearing it\n"); - if (LibDeleteVariable(L"MokSBState", &shim_lock_guid) != EFI_SUCCESS) { - perror(L"Failed to erase MokSBState\n"); - } - status = EFI_SECURITY_VIOLATION; - } else { - if (MokSBState == 1) { - user_insecure_mode = 1; - } - } - - return status; -} - -/* - * Verify that MokDBState is valid, and if appropriate set ignore db mode - */ - -static EFI_STATUS check_mok_db (void) -{ - EFI_GUID shim_lock_guid = SHIM_LOCK_GUID; - EFI_STATUS status = EFI_SUCCESS; - UINT8 MokDBState; - UINTN MokDBStateSize = sizeof(MokDBState); - UINT32 attributes; - - status = uefi_call_wrapper(RT->GetVariable, 5, L"MokDBState", &shim_lock_guid, - &attributes, &MokDBStateSize, &MokDBState); - if (status != EFI_SUCCESS) - return EFI_SECURITY_VIOLATION; - - ignore_db = 0; - - /* - * Delete and ignore the variable if it's been set from or could be - * modified by the OS - */ - if (attributes & EFI_VARIABLE_RUNTIME_ACCESS) { - perror(L"MokDBState is compromised! Clearing it\n"); - if (LibDeleteVariable(L"MokDBState", &shim_lock_guid) != EFI_SUCCESS) { - perror(L"Failed to erase MokDBState\n"); - } - status = EFI_SECURITY_VIOLATION; - } else { - if (MokDBState == 1) { - ignore_db = 1; - } - } - - return status; -} - -static EFI_STATUS mok_ignore_db() -{ - EFI_GUID shim_lock_guid = SHIM_LOCK_GUID; - EFI_STATUS efi_status = EFI_SUCCESS; - UINT8 Data = 1; - UINTN DataSize = sizeof(UINT8); - - check_mok_db(); - - if (ignore_db) { - efi_status = uefi_call_wrapper(RT->SetVariable, 5, L"MokIgnoreDB", - &shim_lock_guid, - EFI_VARIABLE_BOOTSERVICE_ACCESS - | EFI_VARIABLE_RUNTIME_ACCESS, - DataSize, (void *)&Data); - if (efi_status != EFI_SUCCESS) { - perror(L"Failed to set MokIgnoreDB: %r\n", efi_status); - } - } - - return efi_status; - -} - -EFI_GUID bds_guid = { 0x8108ac4e, 0x9f11, 0x4d59, { 0x85, 0x0e, 0xe2, 0x1a, 0x52, 0x2c, 0x59, 0xb2 } }; - static inline EFI_STATUS get_load_option_optional_data(UINT8 *data, UINTN data_size, UINT8 **od, UINTN *ods) @@ -2466,8 +2093,8 @@ static int is_our_path(EFI_LOADED_IMAGE *li, CHAR16 *path, UINTN len) if (!dppath) return 0; - Print(L"dppath: %s\n", dppath); - Print(L"path: %s\n", path); + dprint(L"dppath: %s\n", dppath); + dprint(L"path: %s\n", path); if (StrnCaseCmp(dppath, path, len)) ret = 0; @@ -2480,7 +2107,7 @@ static int is_our_path(EFI_LOADED_IMAGE *li, CHAR16 *path, UINTN len) */ EFI_STATUS set_second_stage (EFI_HANDLE image_handle) { - EFI_STATUS status; + EFI_STATUS efi_status; EFI_LOADED_IMAGE *li = NULL; CHAR16 *start = NULL; int remaining_size = 0; @@ -2492,11 +2119,11 @@ EFI_STATUS set_second_stage (EFI_HANDLE image_handle) load_options = NULL; load_options_size = 0; - status = uefi_call_wrapper(BS->HandleProtocol, 3, image_handle, - &LoadedImageProtocol, (void **) &li); - if (status != EFI_SUCCESS) { - perror (L"Failed to get load options: %r\n", status); - return status; + efi_status = gBS->HandleProtocol(image_handle, &LoadedImageProtocol, + (void **) &li); + if (EFI_ERROR(efi_status)) { + perror (L"Failed to get load options: %r\n", efi_status); + return efi_status; } /* So, load options are a giant pain in the ass. If we're invoked @@ -2566,10 +2193,16 @@ EFI_STATUS set_second_stage (EFI_HANDLE image_handle) if (li->LoadOptionsSize > 16) { if (CompareGuid((EFI_GUID *)(li->LoadOptions + (li->LoadOptionsSize - 16)), - &bds_guid) == 0) + &BDS_GUID) == 0) li->LoadOptionsSize -= 16; } + /* + * Apparently sometimes we get L"\0\0"? Which isn't useful at all. + */ + if (is_all_nuls(li->LoadOptions, li->LoadOptionsSize)) + return EFI_SUCCESS; + /* * Check and see if this is just a list of strings. If it's an * EFI_LOAD_OPTION, it'll be 0, since we know EndEntire device path @@ -2588,11 +2221,11 @@ EFI_STATUS set_second_stage (EFI_HANDLE image_handle) * We at least didn't find /enough/ strings. See if it works * as an EFI_LOAD_OPTION. */ - status = get_load_option_optional_data(li->LoadOptions, - li->LoadOptionsSize, - (UINT8 **)&start, - &loader_len); - if (status != EFI_SUCCESS) + efi_status = get_load_option_optional_data(li->LoadOptions, + li->LoadOptionsSize, + (UINT8 **)&start, + &loader_len); + if (EFI_ERROR(efi_status)) return EFI_SUCCESS; remaining_size = 0; @@ -2726,24 +2359,46 @@ static EFI_HANDLE shim_lock_handle; EFI_STATUS install_shim_protocols(void) { - EFI_GUID shim_lock_guid = SHIM_LOCK_GUID; + SHIM_LOCK *shim_lock; EFI_STATUS efi_status; - if (!secure_mode()) - return EFI_SUCCESS; + /* + * Did another instance of shim earlier already install the + * protocol? If so, get rid of it. + * + * We have to uninstall shim's protocol here, because if we're + * On the fallback.efi path, then our call pathway is: + * + * shim->fallback->shim->grub + * ^ ^ ^ + * | | \- gets protocol #0 + * | \- installs its protocol (#1) + * \- installs its protocol (#0) + * and if we haven't removed this, then grub will get the *first* + * shim's protocol, but it'll get the second shim's systab + * replacements. So even though it will participate and verify + * the kernel, the systab never finds out. + */ + efi_status = LibLocateProtocol(&SHIM_LOCK_GUID, (VOID **)&shim_lock); + if (!EFI_ERROR(efi_status)) + uninstall_shim_protocols(); /* * Install the protocol */ - efi_status = uefi_call_wrapper(BS->InstallProtocolInterface, 4, - &shim_lock_handle, &shim_lock_guid, - EFI_NATIVE_INTERFACE, &shim_lock_interface); + efi_status = gBS->InstallProtocolInterface(&shim_lock_handle, + &SHIM_LOCK_GUID, + EFI_NATIVE_INTERFACE, + &shim_lock_interface); if (EFI_ERROR(efi_status)) { console_error(L"Could not install security protocol", efi_status); return efi_status; } + if (!secure_mode()) + return EFI_SUCCESS; + #if defined(OVERRIDE_SECURITY_POLICY) /* * Install the security protocol hook @@ -2757,7 +2412,11 @@ install_shim_protocols(void) void uninstall_shim_protocols(void) { - EFI_GUID shim_lock_guid = SHIM_LOCK_GUID; + /* + * If we're back here then clean everything up before exiting + */ + gBS->UninstallProtocolInterface(shim_lock_handle, &SHIM_LOCK_GUID, + &shim_lock_interface); if (!secure_mode()) return; @@ -2768,21 +2427,13 @@ uninstall_shim_protocols(void) */ security_policy_uninstall(); #endif - - /* - * If we're back here then clean everything up before exiting - */ - uefi_call_wrapper(BS->UninstallProtocolInterface, 3, shim_lock_handle, - &shim_lock_guid, &shim_lock_interface); } EFI_STATUS shim_init(void) { - EFI_STATUS status = EFI_SUCCESS; - setup_console(1); setup_verbosity(); - dprinta(shim_version); + dprint(L"%a", shim_version); /* Set the second stage loader */ set_second_stage (global_image_handle); @@ -2799,20 +2450,20 @@ shim_init(void) } hook_exit(systab); - - status = install_shim_protocols(); } - return status; + + return install_shim_protocols(); } void shim_fini(void) { + /* + * Remove our protocols + */ + uninstall_shim_protocols(); + if (secure_mode()) { - /* - * Remove our protocols - */ - uninstall_shim_protocols(); /* * Remove our hooks from system services. @@ -2827,7 +2478,7 @@ shim_fini(void) if (load_options_size > 0 && second_stage) FreePool(second_stage); - setup_console(0); + console_fini(); } extern EFI_STATUS @@ -2837,7 +2488,6 @@ static void __attribute__((__optimize__("0"))) debug_hook(void) { - EFI_GUID guid = SHIM_LOCK_GUID; UINT8 *data = NULL; UINTN dataSize = 0; EFI_STATUS efi_status; @@ -2847,18 +2497,21 @@ debug_hook(void) if (x) return; - efi_status = get_variable(L"SHIM_DEBUG", &data, &dataSize, guid); + efi_status = get_variable(L"SHIM_DEBUG", &data, &dataSize, + SHIM_LOCK_GUID); if (EFI_ERROR(efi_status)) { return; } - Print(L"add-symbol-file "DEBUGDIR - L"shim" EFI_ARCH L".efi.debug 0x%08x -s .data 0x%08x\n", &_text, - &_data); + FreePool(data); - Print(L"Pausing for debugger attachment.\n"); - Print(L"To disable this, remove the EFI variable SHIM_DEBUG-%g .\n", - &guid); + console_print(L"add-symbol-file "DEBUGDIR + L"shim" EFI_ARCH L".efi.debug 0x%08x -s .data 0x%08x\n", + &_text, &_data); + + console_print(L"Pausing for debugger attachment.\n"); + console_print(L"To disable this, remove the EFI variable SHIM_DEBUG-%g .\n", + &SHIM_LOCK_GUID); x = 1; while (x++) { /* Make this so it can't /totally/ DoS us. */ @@ -2891,6 +2544,13 @@ efi_main (EFI_HANDLE passed_image_handle, EFI_SYSTEM_TABLE *passed_systab) vendor_dbx_size = cert_table.vendor_dbx_size; vendor_cert = (UINT8 *)&cert_table + cert_table.vendor_cert_offset; vendor_dbx = (UINT8 *)&cert_table + cert_table.vendor_dbx_offset; + CHAR16 *msgs[] = { + L"import_mok_state() failed\n", + L"shim_int() failed\n", + NULL + }; + int msg = 0; + /* * Set up the shim lock protocol so that grub and MokManager can @@ -2916,67 +2576,33 @@ efi_main (EFI_HANDLE passed_image_handle, EFI_SYSTEM_TABLE *passed_systab) debug_hook(); /* - * Measure the MOK variables + * Before we do anything else, validate our non-volatile, + * boot-services-only state variables are what we think they are. */ - efi_status = measure_mok(); - if (efi_status != EFI_SUCCESS && efi_status != EFI_NOT_FOUND) { - Print(L"Something has gone seriously wrong: %r\n", efi_status); - Print(L"Shim was unable to measure state into the TPM\n"); + efi_status = import_mok_state(image_handle); + if (EFI_ERROR(efi_status)) { +die: + console_print(L"Something has gone seriously wrong: %s: %r\n", + msgs[msg], efi_status); msleep(5000000); - uefi_call_wrapper(systab->RuntimeServices->ResetSystem, 4, - EfiResetShutdown, EFI_SECURITY_VIOLATION, - 0, NULL); + gRT->ResetSystem(EfiResetShutdown, EFI_SECURITY_VIOLATION, + 0, NULL); } - /* - * Check whether the user has configured the system to run in - * insecure mode - */ - check_mok_sb(); - efi_status = shim_init(); if (EFI_ERROR(efi_status)) { - Print(L"Something has gone seriously wrong: %r\n", efi_status); - Print(L"shim cannot continue, sorry.\n"); - msleep(5000000); - uefi_call_wrapper(systab->RuntimeServices->ResetSystem, 4, - EfiResetShutdown, EFI_SECURITY_VIOLATION, - 0, NULL); + msg = 1; + goto die; } /* * Tell the user that we're in insecure mode if necessary */ if (user_insecure_mode) { - Print(L"Booting in insecure mode\n"); + console_print(L"Booting in insecure mode\n"); msleep(2000000); } - /* - * Enter MokManager if necessary - */ - efi_status = check_mok_request(image_handle); - - /* - * Copy the MOK list to a runtime variable so the kernel can - * make use of it - */ - efi_status = mirror_mok_list(); - - efi_status = mirror_mok_list_x(); - - /* - * Copy the MOK SB State to a runtime variable so the kernel can - * make use of it - */ - efi_status = mirror_mok_sb_state(); - - /* - * Create the runtime MokIgnoreDB variable so the kernel can - * make use of it - */ - efi_status = mok_ignore_db(); - /* * Hand over control to the second stage bootloader */ diff --git a/shim.h b/shim.h index 9126253..2b359d8 100644 --- a/shim.h +++ b/shim.h @@ -1,12 +1,128 @@ #ifndef SHIM_H_ #define SHIM_H_ +#if defined __GNUC__ && defined __GNUC_MINOR__ +# define GNUC_PREREQ(maj, min) \ + ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min)) +#else +# define GNUC_PREREQ(maj, min) 0 +#endif +#if defined __clang_major__ && defined __clang_minor__ +# define CLANG_PREREQ(maj, min) \ + ((__clang_major__ << 16) + __clang_minor__ >= ((maj) << 16) + (min)) +#else +# define CLANG_PREREQ(maj, min) 0 +#endif + +#if defined(__x86_64__) +#if !defined(GNU_EFI_USE_MS_ABI) +#error On x86_64 you must use ms_abi (GNU_EFI_USE_MS_ABI) in gnu-efi and shim. +#endif +/* gcc 4.5.4 is the first documented release with -mabi=ms */ +#if !GNUC_PREREQ(4, 7) && !CLANG_PREREQ(3, 4) +#error On x86_64 you must have a compiler new enough to support __attribute__((__ms_abi__)) +#endif +#endif + #include #include +#undef uefi_call_wrapper -#include "PeImage.h" +#include -extern EFI_GUID SHIM_LOCK_GUID; +#define min(a, b) ({(a) < (b) ? (a) : (b);}) + +#ifdef __x86_64__ +#ifndef DEFAULT_LOADER +#define DEFAULT_LOADER L"\\grubx64.efi" +#endif +#ifndef DEFAULT_LOADER_CHAR +#define DEFAULT_LOADER_CHAR "\\grubx64.efi" +#endif +#ifndef EFI_ARCH +#define EFI_ARCH L"x64" +#endif +#ifndef DEBUGDIR +#define DEBUGDIR L"/usr/lib/debug/usr/share/shim/x64/" +#endif +#endif + +#if defined(__i686__) || defined(__i386__) +#ifndef DEFAULT_LOADER +#define DEFAULT_LOADER L"\\grubia32.efi" +#endif +#ifndef DEFAULT_LOADER_CHAR +#define DEFAULT_LOADER_CHAR "\\grubia32.efi" +#endif +#ifndef EFI_ARCH +#define EFI_ARCH L"ia32" +#endif +#ifndef DEBUGDIR +#define DEBUGDIR L"/usr/lib/debug/usr/share/shim/ia32/" +#endif +#endif + +#if defined(__aarch64__) +#ifndef DEFAULT_LOADER +#define DEFAULT_LOADER L"\\grubaa64.efi" +#endif +#ifndef DEFAULT_LOADER_CHAR +#define DEFAULT_LOADER_CHAR "\\grubaa64.efi" +#endif +#ifndef EFI_ARCH +#define EFI_ARCH L"aa64" +#endif +#ifndef DEBUGDIR +#define DEBUGDIR L"/usr/lib/debug/usr/share/shim/aa64/" +#endif +#endif + +#if defined(__arm__) +#ifndef DEFAULT_LOADER +#define DEFAULT_LOADER L"\\grubarm.efi" +#endif +#ifndef DEFAULT_LOADER_CHAR +#define DEFAULT_LOADER_CHAR "\\grubarm.efi" +#endif +#ifndef EFI_ARCH +#define EFI_ARCH L"arm" +#endif +#ifndef DEBUGDIR +#define DEBUGDIR L"/usr/lib/debug/usr/share/shim/arm/" +#endif +#endif + +#define FALLBACK L"\\fb" EFI_ARCH L".efi" +#define MOK_MANAGER L"\\mm" EFI_ARCH L".efi" + +#include "include/configtable.h" +#include "include/console.h" +#include "include/crypt_blowfish.h" +#include "include/efiauthenticated.h" +#include "include/errors.h" +#include "include/execute.h" +#include "include/guid.h" +#include "include/Http.h" +#include "include/httpboot.h" +#include "include/Ip4Config2.h" +#include "include/Ip6Config.h" +#include "include/netboot.h" +#include "include/PasswordCrypt.h" +#include "include/PeImage.h" +#include "include/replacements.h" +#if defined(OVERRIDE_SECURITY_POLICY) +#include "include/security_policy.h" +#endif +#include "include/simple_file.h" +#include "include/str.h" +#include "include/tpm.h" +#include "include/ucs2.h" +#include "include/variables.h" + +#include "version.h" +#ifdef ENABLE_SHIM_CERT +#include "shim_cert.h" +#endif INTERFACE_DECL(_SHIM_LOCK); @@ -43,88 +159,30 @@ typedef struct _SHIM_LOCK { extern EFI_STATUS shim_init(void); extern void shim_fini(void); -extern EFI_STATUS LogError(const char *file, int line, const char *func, CHAR16 *fmt, ...); +extern EFI_STATUS LogError_(const char *file, int line, const char *func, CHAR16 *fmt, ...); extern EFI_STATUS VLogError(const char *file, int line, const char *func, CHAR16 *fmt, va_list args); extern VOID PrintErrors(VOID); extern VOID ClearErrors(VOID); +extern EFI_STATUS start_image(EFI_HANDLE image_handle, CHAR16 *ImagePath); +extern EFI_STATUS import_mok_state(EFI_HANDLE image_handle); -#ifdef __x86_64__ -#ifndef DEFAULT_LOADER -#define DEFAULT_LOADER L"\\grubx64.efi" -#endif -#ifndef DEFAULT_LOADER_CHAR -#define DEFAULT_LOADER_CHAR "\\grubx64.efi" -#endif -#ifndef EFI_ARCH -#define EFI_ARCH L"x64" -#endif -#ifndef DEBUGDIR -#define DEBUGDIR L"/usr/lub/debug/usr/share/shim/x64/" -#endif -#endif +extern UINT32 vendor_cert_size; +extern UINT32 vendor_dbx_size; +extern UINT8 *vendor_cert; +extern UINT8 *vendor_dbx; -#if defined(__i686__) || defined(__i386__) -#ifndef DEFAULT_LOADER -#define DEFAULT_LOADER L"\\grubia32.efi" -#endif -#ifndef DEFAULT_LOADER_CHAR -#define DEFAULT_LOADER_CHAR "\\grubia32.efi" -#endif -#ifndef EFI_ARCH -#define EFI_ARCH L"ia32" -#endif -#ifndef DEBUGDIR -#define DEBUGDIR L"/usr/lub/debug/usr/share/shim/ia32/" -#endif -#endif +extern UINT8 user_insecure_mode; +extern UINT8 ignore_db; +extern UINT8 in_protocol; -#if defined(__aarch64__) -#ifndef DEFAULT_LOADER -#define DEFAULT_LOADER L"\\grubaa64.efi" -#endif -#ifndef DEFAULT_LOADER_CHAR -#define DEFAULT_LOADER_CHAR "\\grubaa64.efi" -#endif -#ifndef EFI_ARCH -#define EFI_ARCH L"aa64" -#endif -#ifndef DEBUGDIR -#define DEBUGDIR L"/usr/lub/debug/usr/share/shim/aa64/" -#endif -#endif - -#if defined(__arm__) -#ifndef DEFAULT_LOADER -#define DEFAULT_LOADER L"\\grubarm.efi" -#endif -#ifndef DEFAULT_LOADER_CHAR -#define DEFAULT_LOADER_CHAR "\\grubarm.efi" -#endif -#ifndef EFI_ARCH -#define EFI_ARCH L"arm" -#endif -#ifndef DEBUGDIR -#define DEBUGDIR L"/usr/lub/debug/usr/share/shim/arm/" -#endif -#endif - -#include "netboot.h" -#include "httpboot.h" -#include "replacements.h" -#include "tpm.h" -#include "ucs2.h" - -#include "guid.h" -#include "variables.h" -#include "efiauthenticated.h" -#include "security_policy.h" -#include "console.h" -#include "version.h" - -#ifdef ENABLE_SHIM_CERT -#include "shim_cert.h" -#endif - -#define LogError(fmt, ...) LogError(__FILE__, __LINE__, __func__, fmt, ## __VA_ARGS__) +#define perror_(file, line, func, fmt, ...) ({ \ + UINTN __perror_ret = 0; \ + if (!in_protocol) \ + __perror_ret = console_print((fmt), ##__VA_ARGS__); \ + LogError_(file, line, func, fmt, ##__VA_ARGS__); \ + __perror_ret; \ + }) +#define perror(fmt, ...) perror_(__FILE__, __LINE__, __func__, fmt, ## __VA_ARGS__) +#define LogError(fmt, ...) LogError_(__FILE__, __LINE__, __func__, fmt, ## __VA_ARGS__) #endif /* SHIM_H_ */ diff --git a/tpm.c b/tpm.c index 05b3c6f..674e69b 100644 --- a/tpm.c +++ b/tpm.c @@ -3,17 +3,7 @@ #include #include -#include "tpm.h" - -extern UINT8 in_protocol; - -#define perror(fmt, ...) ({ \ - UINTN __perror_ret = 0; \ - if (!in_protocol) \ - __perror_ret = Print((fmt), ##__VA_ARGS__); \ - __perror_ret; \ - }) - +#include "shim.h" typedef struct { CHAR16 *VariableName; @@ -25,22 +15,18 @@ typedef struct { UINTN measuredcount = 0; VARIABLE_RECORD *measureddata = NULL; -EFI_GUID tpm_guid = EFI_TPM_GUID; -EFI_GUID tpm2_guid = EFI_TPM2_GUID; - static BOOLEAN tpm_present(efi_tpm_protocol_t *tpm) { - EFI_STATUS status; + EFI_STATUS efi_status; TCG_EFI_BOOT_SERVICE_CAPABILITY caps; UINT32 flags; EFI_PHYSICAL_ADDRESS eventlog, lastevent; caps.Size = (UINT8)sizeof(caps); - status = uefi_call_wrapper(tpm->status_check, 5, tpm, &caps, &flags, - &eventlog, &lastevent); - - if (status != EFI_SUCCESS || caps.TPMDeactivatedFlag - || !caps.TPMPresentFlag) + efi_status = tpm->status_check(tpm, &caps, &flags, + &eventlog, &lastevent); + if (EFI_ERROR(efi_status) || + caps.TPMDeactivatedFlag || !caps.TPMPresentFlag) return FALSE; return TRUE; @@ -50,18 +36,19 @@ static EFI_STATUS tpm2_get_caps(efi_tpm2_protocol_t *tpm, EFI_TCG2_BOOT_SERVICE_CAPABILITY *caps, BOOLEAN *old_caps) { - EFI_STATUS status; + EFI_STATUS efi_status; caps->Size = (UINT8)sizeof(*caps); - status = uefi_call_wrapper(tpm->get_capability, 2, tpm, caps); - - if (status != EFI_SUCCESS) - return status; + efi_status = tpm->get_capability(tpm, caps); + if (EFI_ERROR(efi_status)) + return efi_status; if (caps->StructureVersion.Major == 1 && caps->StructureVersion.Minor == 0) *old_caps = TRUE; + else + *old_caps = FALSE; return EFI_SUCCESS; } @@ -115,8 +102,7 @@ static EFI_STATUS trigger_tcg2_final_events_table(efi_tpm2_protocol_t *tpm2, else log_fmt = EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2; - return uefi_call_wrapper(tpm2->get_event_log, 5, tpm2, log_fmt, - &start, &end, &truncated); + return tpm2->get_event_log(tpm2, log_fmt, &start, &end, &truncated); } static EFI_STATUS tpm_locate_protocol(efi_tpm_protocol_t **tpm, @@ -124,19 +110,19 @@ static EFI_STATUS tpm_locate_protocol(efi_tpm_protocol_t **tpm, BOOLEAN *old_caps_p, EFI_TCG2_BOOT_SERVICE_CAPABILITY *capsp) { - EFI_STATUS status; + EFI_STATUS efi_status; *tpm = NULL; *tpm2 = NULL; - status = LibLocateProtocol(&tpm2_guid, (VOID **)tpm2); + efi_status = LibLocateProtocol(&EFI_TPM2_GUID, (VOID **)tpm2); /* TPM 2.0 */ - if (status == EFI_SUCCESS) { + if (!EFI_ERROR(efi_status)) { BOOLEAN old_caps; EFI_TCG2_BOOT_SERVICE_CAPABILITY caps; - status = tpm2_get_caps(*tpm2, &caps, &old_caps); - if (EFI_ERROR(status)) - return status; + efi_status = tpm2_get_caps(*tpm2, &caps, &old_caps); + if (EFI_ERROR(efi_status)) + return efi_status; if (tpm2_present(&caps, old_caps)) { if (old_caps_p) @@ -146,9 +132,9 @@ static EFI_STATUS tpm_locate_protocol(efi_tpm_protocol_t **tpm, return EFI_SUCCESS; } } else { - status = LibLocateProtocol(&tpm_guid, (VOID **)tpm); - if (EFI_ERROR(status)) - return status; + efi_status = LibLocateProtocol(&EFI_TPM_GUID, (VOID **)tpm); + if (EFI_ERROR(efi_status)) + return efi_status; if (tpm_present(*tpm)) return EFI_SUCCESS; @@ -161,25 +147,35 @@ static EFI_STATUS tpm_log_event_raw(EFI_PHYSICAL_ADDRESS buf, UINTN size, UINT8 pcr, const CHAR8 *log, UINTN logsize, UINT32 type, CHAR8 *hash) { - EFI_STATUS status; + EFI_STATUS efi_status; efi_tpm_protocol_t *tpm; efi_tpm2_protocol_t *tpm2; BOOLEAN old_caps; EFI_TCG2_BOOT_SERVICE_CAPABILITY caps; - status = tpm_locate_protocol(&tpm, &tpm2, &old_caps, &caps); - if (EFI_ERROR(status)) { - return status; + efi_status = tpm_locate_protocol(&tpm, &tpm2, &old_caps, &caps); + if (EFI_ERROR(efi_status)) { +#ifdef REQUIRE_TPM + perror(L"TPM logging failed: %r\n", efi_status); + return efi_status; +#else + if (efi_status != EFI_NOT_FOUND) { + perror(L"TPM logging failed: %r\n", efi_status); + return efi_status; + } +#endif } else if (tpm2) { EFI_TCG2_EVENT *event; EFI_TCG2_EVENT_LOG_BITMAP supported_logs; supported_logs = tpm2_get_supported_logs(tpm2, &caps, old_caps); - status = trigger_tcg2_final_events_table(tpm2, supported_logs); - if (EFI_ERROR(status)) { - perror(L"Unable to trigger tcg2 final events table: %r\n", status); - return status; + efi_status = trigger_tcg2_final_events_table(tpm2, + supported_logs); + if (EFI_ERROR(efi_status)) { + perror(L"Unable to trigger tcg2 final events table: %r\n", + efi_status); + return efi_status; } event = AllocatePool(sizeof(*event) + logsize); @@ -196,26 +192,26 @@ static EFI_STATUS tpm_log_event_raw(EFI_PHYSICAL_ADDRESS buf, UINTN size, CopyMem(event->Event, (VOID *)log, logsize); if (hash) { /* TPM 2 systems will generate the appropriate hash - themselves if we pass PE_COFF_IMAGE + themselves if we pass PE_COFF_IMAGE. In case that + fails we fall back to measuring without it. */ - status = uefi_call_wrapper(tpm2->hash_log_extend_event, - 5, tpm2, PE_COFF_IMAGE, buf, - (UINT64) size, event); - } else { - status = uefi_call_wrapper(tpm2->hash_log_extend_event, - 5, tpm2, 0, buf, - (UINT64) size, event); + efi_status = tpm2->hash_log_extend_event(tpm2, + PE_COFF_IMAGE, buf, (UINT64) size, event); + } + + if (!hash || EFI_ERROR(efi_status)) { + efi_status = tpm2->hash_log_extend_event(tpm2, + 0, buf, (UINT64) size, event); } FreePool(event); - return status; + return efi_status; } else if (tpm) { TCG_PCR_EVENT *event; UINT32 eventnum = 0; EFI_PHYSICAL_ADDRESS lastevent; - status = LibLocateProtocol(&tpm_guid, (VOID **)&tpm); - - if (status != EFI_SUCCESS) + efi_status = LibLocateProtocol(&EFI_TPM_GUID, (VOID **)&tpm); + if (EFI_ERROR(efi_status)) return EFI_SUCCESS; if (!tpm_present(tpm)) @@ -237,18 +233,15 @@ static EFI_STATUS tpm_log_event_raw(EFI_PHYSICAL_ADDRESS buf, UINTN size, hash rather than allowing the firmware to attempt to calculate it */ CopyMem(event->digest, hash, sizeof(event->digest)); - status = uefi_call_wrapper(tpm->log_extend_event, 7, - tpm, 0, 0, TPM_ALG_SHA, - event, &eventnum, - &lastevent); + efi_status = tpm->log_extend_event(tpm, 0, 0, + TPM_ALG_SHA, event, &eventnum, &lastevent); } else { - status = uefi_call_wrapper(tpm->log_extend_event, 7, - tpm, buf, (UINT64)size, - TPM_ALG_SHA, event, - &eventnum, &lastevent); + efi_status = tpm->log_extend_event(tpm, buf, + (UINT64)size, TPM_ALG_SHA, event, &eventnum, + &lastevent); } FreePool(event); - return status; + return efi_status; } return EFI_SUCCESS; @@ -335,7 +328,7 @@ static EFI_STATUS tpm_record_data_measurement(CHAR16 *VarName, EFI_GUID VendorGu EFI_STATUS tpm_measure_variable(CHAR16 *VarName, EFI_GUID VendorGuid, UINTN VarSize, VOID *VarData) { - EFI_STATUS Status; + EFI_STATUS efi_status; UINTN VarNameLength; EFI_VARIABLE_DATA_TREE *VarLog; UINT32 VarLogSize; @@ -365,14 +358,14 @@ EFI_STATUS tpm_measure_variable(CHAR16 *VarName, EFI_GUID VendorGuid, UINTN VarS CopyMem ((CHAR16 *)VarLog->UnicodeName + VarNameLength, VarData, VarSize); - Status = tpm_log_event_raw((EFI_PHYSICAL_ADDRESS)(intptr_t)VarLog, - VarLogSize, 7, (CHAR8 *)VarLog, VarLogSize, - EV_EFI_VARIABLE_AUTHORITY, NULL); + efi_status = tpm_log_event_raw((EFI_PHYSICAL_ADDRESS)(intptr_t)VarLog, + VarLogSize, 7, (CHAR8 *)VarLog, VarLogSize, + EV_EFI_VARIABLE_AUTHORITY, NULL); FreePool(VarLog); - if (Status != EFI_SUCCESS) - return Status; + if (EFI_ERROR(efi_status)) + return efi_status; return tpm_record_data_measurement(VarName, VendorGuid, VarSize, VarData); @@ -381,12 +374,12 @@ EFI_STATUS tpm_measure_variable(CHAR16 *VarName, EFI_GUID VendorGuid, UINTN VarS EFI_STATUS fallback_should_prefer_reset(void) { - EFI_STATUS status; + EFI_STATUS efi_status; efi_tpm_protocol_t *tpm; efi_tpm2_protocol_t *tpm2; - status = tpm_locate_protocol(&tpm, &tpm2, NULL, NULL); - if (EFI_ERROR(status)) + efi_status = tpm_locate_protocol(&tpm, &tpm2, NULL, NULL); + if (EFI_ERROR(efi_status)) return EFI_NOT_FOUND; return EFI_SUCCESS; }