diff --git a/shim-0.4.tar.bz2 b/shim-0.4.tar.bz2 deleted file mode 100644 index d724527..0000000 --- a/shim-0.4.tar.bz2 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:442c5ea22e50aeea816fc83e4a328e48d9429eefb706fa55de3d7c8b05aea0e7 -size 966676 diff --git a/shim-0.7.tar.bz2 b/shim-0.7.tar.bz2 new file mode 100644 index 0000000..666a3ca --- /dev/null +++ b/shim-0.7.tar.bz2 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b85cabcdedfcf256e357dc2a8a0131a32f3b4619155a174465db47326c8102b7 +size 988071 diff --git a/shim-bnc798043-no-doulbe-separators.patch b/shim-bnc798043-no-doulbe-separators.patch deleted file mode 100644 index f9ff606..0000000 --- a/shim-bnc798043-no-doulbe-separators.patch +++ /dev/null @@ -1,59 +0,0 @@ -From cf7f87688efab2712f41b47eaad32e75ec730653 Mon Sep 17 00:00:00 2001 -From: Gary Ching-Pang Lin -Date: Fri, 1 Mar 2013 18:04:06 +0800 -Subject: [PATCH] Remove double-separators from the bootpath - ---- - shim.c | 27 ++++++++++++++++++++------- - 1 file changed, 20 insertions(+), 7 deletions(-) - -diff --git a/shim.c b/shim.c -index 0622c72..806f065 100644 ---- a/shim.c -+++ b/shim.c -@@ -969,7 +969,7 @@ static EFI_STATUS generate_path(EFI_LOADED_IMAGE *li, CHAR16 *ImagePath, - { - EFI_DEVICE_PATH *devpath; - EFI_HANDLE device; -- int i; -+ int i, j, last = -1; - unsigned int pathlen = 0; - EFI_STATUS efi_status = EFI_SUCCESS; - CHAR16 *bootpath; -@@ -989,14 +989,27 @@ static EFI_STATUS generate_path(EFI_LOADED_IMAGE *li, CHAR16 *ImagePath, - if (bootpath[i] == '/') - bootpath[i] = '\\'; - } -+ - for (i=pathlen; i>0; i--) { -- if (bootpath[i] == '\\' && bootpath[i-1] != '\\') -- break; -+ if (bootpath[i] == '\\' && bootpath[i-1] == '\\') -+ bootpath[i] = '/'; -+ else if (last == -1 && bootpath[i] == '\\') -+ last = i; -+ } -+ -+ if (last == -1 && bootpath[0] == '\\') -+ last = 0; -+ bootpath[last+1] = '\0'; -+ -+ if (last > 0) { -+ for (i = 0, j = 0; bootpath[i] != '\0'; i++) { -+ if (bootpath[i] != '/') { -+ bootpath[j] = bootpath[i]; -+ j++; -+ } -+ } -+ bootpath[j] = '\0'; - } -- if (bootpath[i] == '\\') -- bootpath[i+1] = '\0'; -- else -- bootpath[0] = '\0'; - - while (*ImagePath == '\\') - ImagePath++; --- -1.8.1.4 - diff --git a/shim-bnc804631-fix-broken-bootpath.patch b/shim-bnc804631-fix-broken-bootpath.patch deleted file mode 100644 index a4700c8..0000000 --- a/shim-bnc804631-fix-broken-bootpath.patch +++ /dev/null @@ -1,64 +0,0 @@ -From bfffac234fabdf8110e8e8c53557d57d61320098 Mon Sep 17 00:00:00 2001 -From: Gary Ching-Pang Lin -Date: Thu, 21 Feb 2013 17:49:29 +0800 -Subject: [PATCH] Fix the broken bootpath - -- The file path from DevicePathToStr may use slash as the file - seperator. Change all slashes to backslashes to avoid the strange - bootpath. -- Remove the redundant backslashes. -- ImagePath no longer requires the leading backslash. -- Fix a memory leak - -Based on the patch from Michal Marek ---- - shim.c | 22 +++++++++++++++++----- - 1 file changed, 17 insertions(+), 5 deletions(-) - -diff --git a/shim.c b/shim.c -index 94b9710..0622c72 100644 ---- a/shim.c -+++ b/shim.c -@@ -981,15 +981,25 @@ static EFI_STATUS generate_path(EFI_LOADED_IMAGE *li, CHAR16 *ImagePath, - - pathlen = StrLen(bootpath); - -+ /* -+ * DevicePathToStr() concatenates two nodes with '/'. -+ * Convert '/' to '\\'. -+ */ -+ for (i = 0; i < pathlen; i++) { -+ if (bootpath[i] == '/') -+ bootpath[i] = '\\'; -+ } - for (i=pathlen; i>0; i--) { -- if (bootpath[i] == '\\') -+ if (bootpath[i] == '\\' && bootpath[i-1] != '\\') - break; - } -+ if (bootpath[i] == '\\') -+ bootpath[i+1] = '\0'; -+ else -+ bootpath[0] = '\0'; - -- bootpath[i+1] = '\0'; -- -- if (i == 0 || bootpath[i-i] == '\\') -- bootpath[i] = '\0'; -+ while (*ImagePath == '\\') -+ ImagePath++; - - *PathName = AllocatePool(StrSize(bootpath) + StrSize(ImagePath)); - -@@ -1007,6 +1017,8 @@ static EFI_STATUS generate_path(EFI_LOADED_IMAGE *li, CHAR16 *ImagePath, - *grubpath = FileDevicePath(device, *PathName); - - error: -+ FreePool(bootpath); -+ - return efi_status; - } - --- -1.8.1.4 - diff --git a/shim-bnc807760-change-pxe-2nd-loader-name.patch b/shim-bnc807760-change-pxe-2nd-loader-name.patch deleted file mode 100644 index 1b015a3..0000000 --- a/shim-bnc807760-change-pxe-2nd-loader-name.patch +++ /dev/null @@ -1,58 +0,0 @@ -From 9cf8c7fefdcfb5930cb96091676a67cc0c0402b9 Mon Sep 17 00:00:00 2001 -From: Gary Ching-Pang Lin -Date: Thu, 7 Mar 2013 11:59:44 +0800 -Subject: [PATCH] Define the PXE 2nd stage loader in the beginning of the file - -Make it easier to change the PXE 2nd stage loader. ---- - netboot.c | 12 +++++++----- - 1 file changed, 7 insertions(+), 5 deletions(-) - -diff --git a/netboot.c b/netboot.c -index 90fb9cb..ae723c7 100644 ---- a/netboot.c -+++ b/netboot.c -@@ -39,6 +39,7 @@ - #include "shim.h" - #include "netboot.h" - -+#define DEFAULT_LOADER "/grub.efi" - - static inline unsigned short int __swap16(unsigned short int x) - { -@@ -238,7 +239,7 @@ static BOOLEAN extract_tftp_info(char *url) - { - char *start, *end; - char ip6str[128]; -- char *template = "/grubx64.efi"; -+ char *template = DEFAULT_LOADER; - - if (strncmp((UINT8 *)url, (UINT8 *)"tftp://", 7)) { - Print(L"URLS MUST START WITH tftp://\n"); -@@ -294,9 +295,11 @@ static EFI_STATUS parseDhcp6() - - static EFI_STATUS parseDhcp4() - { -- char *template = "/grubx64.efi"; -- char *tmp = AllocatePool(16); -+ char *template = DEFAULT_LOADER; -+ char *tmp; -+ int len = strlen((CHAR8 *)template); - -+ tmp = AllocatePool(len+1); - - if (!tmp) - return EFI_OUT_OF_RESOURCES; -@@ -304,8 +307,7 @@ static EFI_STATUS parseDhcp4() - - memcpy(&tftp_addr.v4, pxe->Mode->DhcpAck.Dhcpv4.BootpSiAddr, 4); - -- memcpy(tmp, template, 12); -- tmp[13] = '\0'; -+ memcpy(tmp, template, len+1); - full_path = tmp; - - /* Note we don't capture the filename option here because we know its shim.efi --- -1.8.1.4 - diff --git a/shim-bnc808106-correct-certcount.patch b/shim-bnc808106-correct-certcount.patch deleted file mode 100644 index c6ba95f..0000000 --- a/shim-bnc808106-correct-certcount.patch +++ /dev/null @@ -1,34 +0,0 @@ -From 37b8af226ea8e3af467944b3b6253218ba13838c Mon Sep 17 00:00:00 2001 -From: Gary Ching-Pang Lin -Date: Fri, 8 Mar 2013 14:44:50 +0800 -Subject: [PATCH] Correct the certificate count of the signature list - ---- - shim.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/shim.c b/shim.c -index 806f065..7219d53 100644 ---- a/shim.c -+++ b/shim.c -@@ -230,7 +230,7 @@ static CHECK_STATUS check_db_cert_in_ram(EFI_SIGNATURE_LIST *CertList, - - while ((dbsize > 0) && (dbsize >= CertList->SignatureListSize)) { - if (CompareGuid (&CertList->SignatureType, &CertType) == 0) { -- CertCount = (CertList->SignatureListSize - CertList->SignatureHeaderSize) / CertList->SignatureSize; -+ CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize; - Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize); - for (Index = 0; Index < CertCount; Index++) { - IsFound = AuthenticodeVerify (data->CertData, -@@ -295,7 +295,7 @@ static CHECK_STATUS check_db_hash_in_ram(EFI_SIGNATURE_LIST *CertList, - BOOLEAN IsFound = FALSE; - - while ((dbsize > 0) && (dbsize >= CertList->SignatureListSize)) { -- CertCount = (CertList->SignatureListSize - CertList->SignatureHeaderSize) / CertList->SignatureSize; -+ CertCount = (CertList->SignatureListSize -sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize; - Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize); - if (CompareGuid(&CertList->SignatureType, &CertType) == 0) { - for (Index = 0; Index < CertCount; Index++) { --- -1.8.1.4 - diff --git a/shim-bnc841426-silence-shim-protocols.patch b/shim-bnc841426-silence-shim-protocols.patch deleted file mode 100644 index 0524ec9..0000000 --- a/shim-bnc841426-silence-shim-protocols.patch +++ /dev/null @@ -1,789 +0,0 @@ -From f60d64b0e119ad7df60d9111fc94fe7ded65750f Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Thu, 20 Jun 2013 12:41:14 -0400 -Subject: [PATCH 1/3] Don't print that fallback isn't found in - should_use_fallback() - -The call can simply fail if it isn't found - which will be the case on -removeable install media. - -Signed-off-by: Peter Jones ---- - shim.c | 7 ++++++- - 1 file changed, 6 insertions(+), 1 deletion(-) - -diff --git a/shim.c b/shim.c -index 47e3812..895b594 100644 ---- a/shim.c -+++ b/shim.c -@@ -951,7 +951,12 @@ should_use_fallback(EFI_HANDLE image_handle) - rc = uefi_call_wrapper(vh->Open, 5, vh, &fh, L"\\EFI\\BOOT" FALLBACK, - EFI_FILE_MODE_READ, 0); - if (EFI_ERROR(rc)) { -- Print(L"Could not open \"\\EFI\\BOOT%s\": %d\n", FALLBACK, rc); -+ /* 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); -+ */ - uefi_call_wrapper(vh->Close, 1, vh); - return 0; - } --- -1.8.1.4 - - -From abe44733163c3ef8da96c09dadd8e54e65f9bdab Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Thu, 25 Jul 2013 10:51:05 -0400 -Subject: [PATCH 2/3] Don't print things on the screen by default when - everything works. - -There's no point to this text, and it generally confuses people. - -Signed-off-by: Peter Jones ---- - shim.c | 26 +++++++++++++++++++++----- - 1 file changed, 21 insertions(+), 5 deletions(-) - -diff --git a/shim.c b/shim.c -index 895b594..137290d 100644 ---- a/shim.c -+++ b/shim.c -@@ -53,6 +53,7 @@ static EFI_STATUS (EFIAPI *entry_point) (EFI_HANDLE image_handle, EFI_SYSTEM_TAB - static CHAR16 *second_stage; - static void *load_options; - static UINT32 load_options_size; -+static UINT8 verbose; - - /* - * The vendor certificate used for validating the second stage loader -@@ -431,7 +432,8 @@ static BOOLEAN secure_mode (void) - - /* FIXME - more paranoia here? */ - if (status != EFI_SUCCESS || sb != 1) { -- Print(L"Secure boot not enabled\n"); -+ if (verbose) -+ Print(L"Secure boot not enabled\n"); - return FALSE; - } - -@@ -439,7 +441,8 @@ static BOOLEAN secure_mode (void) - (void *)&setupmode); - - if (status == EFI_SUCCESS && setupmode == 1) { -- Print(L"Platform is in setup mode\n"); -+ if (verbose) -+ Print(L"Platform is in setup mode\n"); - return FALSE; - } - -@@ -699,7 +702,8 @@ static EFI_STATUS verify_buffer (char *data, int datasize, - status = check_whitelist(cert, sha256hash, sha1hash); - - if (status == EFI_SUCCESS) { -- Print(L"Binary is whitelisted\n"); -+ if (verbose) -+ Print(L"Binary is whitelisted\n"); - return status; - } - -@@ -711,7 +715,8 @@ static EFI_STATUS verify_buffer (char *data, int datasize, - shim_cert, sizeof(shim_cert), sha256hash, - SHA256_DIGEST_SIZE)) { - status = EFI_SUCCESS; -- Print(L"Binary is verified by the vendor certificate\n"); -+ if (verbose) -+ Print(L"Binary is verified by the vendor certificate\n"); - return status; - } - -@@ -724,7 +729,8 @@ static EFI_STATUS verify_buffer (char *data, int datasize, - vendor_cert, vendor_cert_size, sha256hash, - SHA256_DIGEST_SIZE)) { - status = EFI_SUCCESS; -- Print(L"Binary is verified by the vendor certificate\n"); -+ if (verbose) -+ Print(L"Binary is verified by the vendor certificate\n"); - return status; - } - -@@ -1501,6 +1507,10 @@ EFI_STATUS efi_main (EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *passed_systab) - static SHIM_LOCK shim_lock_interface; - EFI_HANDLE handle = NULL; - EFI_STATUS efi_status; -+ UINT8 verbose_check; -+ UINTN verbose_check_size; -+ UINT32 attributes; -+ EFI_GUID global_var = EFI_GLOBAL_VARIABLE; - - /* - * Set up the shim lock protocol so that grub and MokManager can -@@ -1517,6 +1527,12 @@ EFI_STATUS efi_main (EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *passed_systab) - */ - InitializeLib(image_handle, systab); - -+ verbose_check_size = 1; -+ efi_status = get_variable(L"SHIM_VERBOSE", global_var, &attributes, -+ &verbose_check_size, (void *)&verbose_check); -+ if (!EFI_ERROR(efi_status)) -+ verbose = verbose_check; -+ - /* Set the second stage loader */ - set_second_stage (image_handle); - --- -1.8.1.4 - - -From 3a131108f7b86af4fe5ed0021374467feb98bd54 Mon Sep 17 00:00:00 2001 -From: Gary Ching-Pang Lin -Date: Tue, 1 Oct 2013 11:58:52 +0800 -Subject: [PATCH 3/3] Keep silent in shim protocol - -On some machines, grub2 hung on shim_verify() which tried to output -messages. This commit silences the functions used in the shim -protocols to avoid system hang. ---- - shim.c | 178 +++++++++++++++++++++++++++++++++++++++-------------------------- - 1 file changed, 106 insertions(+), 72 deletions(-) - -diff --git a/shim.c b/shim.c -index 137290d..a0de14e 100644 ---- a/shim.c -+++ b/shim.c -@@ -54,6 +54,9 @@ static CHAR16 *second_stage; - static void *load_options; - static UINT32 load_options_size; - static UINT8 verbose; -+static UINT8 in_protocol; -+ -+#define ERROR(...) if(!in_protocol) {Print(__VA_ARGS__);} - - /* - * The vendor certificate used for validating the second stage loader -@@ -94,7 +97,7 @@ static EFI_STATUS get_variable (CHAR16 *name, EFI_GUID guid, UINT32 *attributes, - *buffer = AllocatePool(*size); - - if (!*buffer) { -- Print(L"Unable to allocate variable buffer\n"); -+ ERROR(L"Unable to allocate variable buffer\n"); - return EFI_OUT_OF_RESOURCES; - } - -@@ -134,7 +137,7 @@ static EFI_STATUS relocate_coff (PE_COFF_LOADER_IMAGE_CONTEXT *context, - context->PEHdr->Pe32Plus.OptionalHeader.ImageBase = (UINT64)data; - - if (context->NumberOfRvaAndSizes <= EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) { -- Print(L"Image has no relocation entry\n"); -+ ERROR(L"Image has no relocation entry\n"); - return EFI_UNSUPPORTED; - } - -@@ -142,7 +145,7 @@ static EFI_STATUS relocate_coff (PE_COFF_LOADER_IMAGE_CONTEXT *context, - RelocBaseEnd = ImageAddress(data, size, context->RelocDir->VirtualAddress + context->RelocDir->Size - 1); - - if (!RelocBase || !RelocBaseEnd) { -- Print(L"Reloc table overflows binary\n"); -+ ERROR(L"Reloc table overflows binary\n"); - return EFI_UNSUPPORTED; - } - -@@ -153,13 +156,13 @@ static EFI_STATUS relocate_coff (PE_COFF_LOADER_IMAGE_CONTEXT *context, - RelocEnd = (UINT16 *) ((char *) RelocBase + RelocBase->SizeOfBlock); - - if ((void *)RelocEnd < data || (void *)RelocEnd > ImageEnd) { -- Print(L"Reloc entry overflows binary\n"); -+ ERROR(L"Reloc entry overflows binary\n"); - return EFI_UNSUPPORTED; - } - - FixupBase = ImageAddress(data, size, RelocBase->VirtualAddress); - if (!FixupBase) { -- Print(L"Invalid fixupbase\n"); -+ ERROR(L"Invalid fixupbase\n"); - return EFI_UNSUPPORTED; - } - -@@ -208,7 +211,7 @@ static EFI_STATUS relocate_coff (PE_COFF_LOADER_IMAGE_CONTEXT *context, - break; - - default: -- Print(L"Unknown relocation\n"); -+ ERROR(L"Unknown relocation\n"); - return EFI_UNSUPPORTED; - } - Reloc += 1; -@@ -432,7 +435,7 @@ static BOOLEAN secure_mode (void) - - /* FIXME - more paranoia here? */ - if (status != EFI_SUCCESS || sb != 1) { -- if (verbose) -+ if (verbose && !in_protocol) - Print(L"Secure boot not enabled\n"); - return FALSE; - } -@@ -441,7 +444,7 @@ static BOOLEAN secure_mode (void) - (void *)&setupmode); - - if (status == EFI_SUCCESS && setupmode == 1) { -- if (verbose) -+ if (verbose && !in_protocol) - Print(L"Platform is in setup mode\n"); - return FALSE; - } -@@ -477,12 +480,12 @@ static EFI_STATUS generate_hash (char *data, int datasize, - sha1ctx = AllocatePool(sha1ctxsize); - - if (!sha256ctx || !sha1ctx) { -- Print(L"Unable to allocate memory for hash context\n"); -+ ERROR(L"Unable to allocate memory for hash context\n"); - return EFI_OUT_OF_RESOURCES; - } - - if (!Sha256Init(sha256ctx) || !Sha1Init(sha1ctx)) { -- Print(L"Unable to initialise hash\n"); -+ ERROR(L"Unable to initialise hash\n"); - status = EFI_OUT_OF_RESOURCES; - goto done; - } -@@ -494,7 +497,7 @@ static EFI_STATUS generate_hash (char *data, int datasize, - - if (!(Sha256Update(sha256ctx, hashbase, hashsize)) || - !(Sha1Update(sha1ctx, hashbase, hashsize))) { -- Print(L"Unable to generate hash\n"); -+ ERROR(L"Unable to generate hash\n"); - status = EFI_OUT_OF_RESOURCES; - goto done; - } -@@ -506,7 +509,7 @@ static EFI_STATUS generate_hash (char *data, int datasize, - - if (!(Sha256Update(sha256ctx, hashbase, hashsize)) || - !(Sha1Update(sha1ctx, hashbase, hashsize))) { -- Print(L"Unable to generate hash\n"); -+ ERROR(L"Unable to generate hash\n"); - status = EFI_OUT_OF_RESOURCES; - goto done; - } -@@ -518,7 +521,7 @@ static EFI_STATUS generate_hash (char *data, int datasize, - - if (!(Sha256Update(sha256ctx, hashbase, hashsize)) || - !(Sha1Update(sha1ctx, hashbase, hashsize))) { -- Print(L"Unable to generate hash\n"); -+ ERROR(L"Unable to generate hash\n"); - status = EFI_OUT_OF_RESOURCES; - goto done; - } -@@ -539,14 +542,14 @@ static EFI_STATUS generate_hash (char *data, int datasize, - } - - if (SumOfSectionBytes >= datasize) { -- Print(L"Malformed binary: %x %x\n", SumOfSectionBytes, size); -+ ERROR(L"Malformed binary: %x %x\n", SumOfSectionBytes, size); - status = EFI_INVALID_PARAMETER; - goto done; - } - - SectionHeader = (EFI_IMAGE_SECTION_HEADER *) AllocateZeroPool (sizeof (EFI_IMAGE_SECTION_HEADER) * context->PEHdr->Pe32.FileHeader.NumberOfSections); - if (SectionHeader == NULL) { -- Print(L"Unable to allocate section header\n"); -+ ERROR(L"Unable to allocate section header\n"); - status = EFI_OUT_OF_RESOURCES; - goto done; - } -@@ -572,14 +575,14 @@ static EFI_STATUS generate_hash (char *data, int datasize, - hashsize = (unsigned int) Section->SizeOfRawData; - - if (!hashbase) { -- Print(L"Malformed section header\n"); -+ ERROR(L"Malformed section header\n"); - status = EFI_INVALID_PARAMETER; - goto done; - } - - if (!(Sha256Update(sha256ctx, hashbase, hashsize)) || - !(Sha1Update(sha1ctx, hashbase, hashsize))) { -- Print(L"Unable to generate hash\n"); -+ ERROR(L"Unable to generate hash\n"); - status = EFI_OUT_OF_RESOURCES; - goto done; - } -@@ -596,7 +599,7 @@ static EFI_STATUS generate_hash (char *data, int datasize, - - if (!(Sha256Update(sha256ctx, hashbase, hashsize)) || - !(Sha1Update(sha1ctx, hashbase, hashsize))) { -- Print(L"Unable to generate hash\n"); -+ ERROR(L"Unable to generate hash\n"); - status = EFI_OUT_OF_RESOURCES; - goto done; - } -@@ -604,7 +607,7 @@ static EFI_STATUS generate_hash (char *data, int datasize, - - if (!(Sha256Final(sha256ctx, sha256hash)) || - !(Sha1Final(sha1ctx, sha1hash))) { -- Print(L"Unable to finalise hash\n"); -+ ERROR(L"Unable to finalise hash\n"); - status = EFI_OUT_OF_RESOURCES; - goto done; - } -@@ -634,9 +637,9 @@ static EFI_STATUS verify_mok (void) { - &MokListDataSize, &MokListData); - - if (attributes & EFI_VARIABLE_RUNTIME_ACCESS) { -- Print(L"MokList is compromised!\nErase all keys in MokList!\n"); -+ ERROR(L"MokList is compromised!\nErase all keys in MokList!\n"); - if (LibDeleteVariable(L"MokList", &shim_lock_guid) != EFI_SUCCESS) { -- Print(L"Failed to erase MokList\n"); -+ ERROR(L"Failed to erase MokList\n"); - } - status = EFI_ACCESS_DENIED; - return status; -@@ -658,19 +661,19 @@ static EFI_STATUS verify_buffer (char *data, int datasize, - unsigned int size = datasize; - - if (context->SecDir->Size == 0) { -- Print(L"Empty security header\n"); -+ ERROR(L"Empty security header\n"); - return EFI_INVALID_PARAMETER; - } - - cert = ImageAddress (data, size, context->SecDir->VirtualAddress); - - if (!cert) { -- Print(L"Certificate located outside the image\n"); -+ ERROR(L"Certificate located outside the image\n"); - return EFI_INVALID_PARAMETER; - } - - if (cert->Hdr.wCertificateType != WIN_CERT_TYPE_PKCS_SIGNED_DATA) { -- Print(L"Unsupported certificate type %x\n", -+ ERROR(L"Unsupported certificate type %x\n", - cert->Hdr.wCertificateType); - return EFI_UNSUPPORTED; - } -@@ -691,7 +694,7 @@ static EFI_STATUS verify_buffer (char *data, int datasize, - status = check_blacklist(cert, sha256hash, sha1hash); - - if (status != EFI_SUCCESS) { -- Print(L"Binary is blacklisted\n"); -+ ERROR(L"Binary is blacklisted\n"); - return status; - } - -@@ -702,7 +705,7 @@ static EFI_STATUS verify_buffer (char *data, int datasize, - status = check_whitelist(cert, sha256hash, sha1hash); - - if (status == EFI_SUCCESS) { -- if (verbose) -+ if (verbose && !in_protocol) - Print(L"Binary is whitelisted\n"); - return status; - } -@@ -715,7 +718,7 @@ static EFI_STATUS verify_buffer (char *data, int datasize, - shim_cert, sizeof(shim_cert), sha256hash, - SHA256_DIGEST_SIZE)) { - status = EFI_SUCCESS; -- if (verbose) -+ if (verbose && !in_protocol) - Print(L"Binary is verified by the vendor certificate\n"); - return status; - } -@@ -729,12 +732,12 @@ static EFI_STATUS verify_buffer (char *data, int datasize, - vendor_cert, vendor_cert_size, sha256hash, - SHA256_DIGEST_SIZE)) { - status = EFI_SUCCESS; -- if (verbose) -+ if (verbose && !in_protocol) - Print(L"Binary is verified by the vendor certificate\n"); - return status; - } - -- Print(L"Invalid signature\n"); -+ ERROR(L"Invalid signature\n"); - status = EFI_ACCESS_DENIED; - - return status; -@@ -750,7 +753,7 @@ static EFI_STATUS read_header(void *data, unsigned int datasize, - EFI_IMAGE_OPTIONAL_HEADER_UNION *PEHdr = data; - - if (datasize < sizeof(EFI_IMAGE_DOS_HEADER)) { -- Print(L"Invalid image\n"); -+ ERROR(L"Invalid image\n"); - return EFI_UNSUPPORTED; - } - -@@ -758,22 +761,22 @@ static EFI_STATUS read_header(void *data, unsigned int datasize, - PEHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)((char *)data + DosHdr->e_lfanew); - - if ((((UINT8 *)PEHdr - (UINT8 *)data) + sizeof(EFI_IMAGE_OPTIONAL_HEADER_UNION)) > datasize) { -- Print(L"Invalid image\n"); -+ ERROR(L"Invalid image\n"); - return EFI_UNSUPPORTED; - } - - if (PEHdr->Te.Signature != EFI_IMAGE_NT_SIGNATURE) { -- Print(L"Unsupported image type\n"); -+ ERROR(L"Unsupported image type\n"); - return EFI_UNSUPPORTED; - } - - if (PEHdr->Pe32.FileHeader.Characteristics & EFI_IMAGE_FILE_RELOCS_STRIPPED) { -- Print(L"Unsupported image - Relocations have been stripped\n"); -+ ERROR(L"Unsupported image - Relocations have been stripped\n"); - return EFI_UNSUPPORTED; - } - - if (PEHdr->Pe32.OptionalHeader.Magic != EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) { -- Print(L"Only 64-bit images supported\n"); -+ ERROR(L"Only 64-bit images supported\n"); - return EFI_UNSUPPORTED; - } - -@@ -789,22 +792,23 @@ static EFI_STATUS read_header(void *data, unsigned int datasize, - context->SecDir = (EFI_IMAGE_DATA_DIRECTORY *) &PEHdr->Pe32Plus.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]; - - if (context->ImageSize < context->SizeOfHeaders) { -- Print(L"Invalid image\n"); -+ ERROR(L"Invalid image\n"); - return EFI_UNSUPPORTED; - } - - if (((UINT8 *)context->SecDir - (UINT8 *)data) > (datasize - sizeof(EFI_IMAGE_DATA_DIRECTORY))) { -- Print(L"Invalid image\n"); -+ ERROR(L"Invalid image\n"); - return EFI_UNSUPPORTED; - } - - if (context->SecDir->VirtualAddress >= datasize) { -- Print(L"Malformed security header\n"); -+ ERROR(L"Malformed security header\n"); - return EFI_INVALID_PARAMETER; - } - return EFI_SUCCESS; - } - -+ - /* - * Once the image has been loaded it needs to be validated and relocated - */ -@@ -823,7 +827,7 @@ static EFI_STATUS handle_image (void *data, unsigned int datasize, - */ - efi_status = read_header(data, datasize, &context); - if (efi_status != EFI_SUCCESS) { -- Print(L"Failed to read header\n"); -+ ERROR(L"Failed to read header\n"); - return efi_status; - } - -@@ -834,7 +838,7 @@ static EFI_STATUS handle_image (void *data, unsigned int datasize, - efi_status = verify_buffer(data, datasize, &context); - - if (efi_status != EFI_SUCCESS) { -- Print(L"Verification failed\n"); -+ ERROR(L"Verification failed\n"); - return efi_status; - } - } -@@ -842,7 +846,7 @@ static EFI_STATUS handle_image (void *data, unsigned int datasize, - buffer = AllocatePool(context.ImageSize); - - if (!buffer) { -- Print(L"Failed to allocate image buffer\n"); -+ ERROR(L"Failed to allocate image buffer\n"); - return EFI_OUT_OF_RESOURCES; - } - -@@ -862,7 +866,7 @@ static EFI_STATUS handle_image (void *data, unsigned int datasize, - end = ImageAddress (buffer, context.ImageSize, Section->VirtualAddress + size - 1); - - if (!base || !end) { -- Print(L"Invalid section size\n"); -+ ERROR(L"Invalid section size\n"); - return EFI_UNSUPPORTED; - } - -@@ -881,7 +885,7 @@ static EFI_STATUS handle_image (void *data, unsigned int datasize, - efi_status = relocate_coff(&context, buffer); - - if (efi_status != EFI_SUCCESS) { -- Print(L"Relocation failed\n"); -+ ERROR(L"Relocation failed\n"); - FreePool(buffer); - return efi_status; - } -@@ -899,7 +903,7 @@ static EFI_STATUS handle_image (void *data, unsigned int datasize, - li->LoadOptionsSize = load_options_size; - - if (!entry_point) { -- Print(L"Invalid entry point\n"); -+ ERROR(L"Invalid entry point\n"); - FreePool(buffer); - return EFI_UNSUPPORTED; - } -@@ -922,7 +926,7 @@ should_use_fallback(EFI_HANDLE image_handle) - rc = uefi_call_wrapper(BS->HandleProtocol, 3, image_handle, - &loaded_image_protocol, (void **)&li); - if (EFI_ERROR(rc)) { -- Print(L"Could not get image for bootx64.efi: %d\n", rc); -+ ERROR(L"Could not get image for bootx64.efi: %d\n", rc); - return 0; - } - -@@ -944,13 +948,13 @@ should_use_fallback(EFI_HANDLE image_handle) - rc = uefi_call_wrapper(BS->HandleProtocol, 3, li->DeviceHandle, - &FileSystemProtocol, (void **)&fio); - if (EFI_ERROR(rc)) { -- Print(L"Could not get fio for li->DeviceHandle: %d\n", rc); -+ ERROR(L"Could not get fio for li->DeviceHandle: %d\n", rc); - return 0; - } - - rc = uefi_call_wrapper(fio->OpenVolume, 2, fio, &vh); - if (EFI_ERROR(rc)) { -- Print(L"Could not open fio volume: %d\n", rc); -+ ERROR(L"Could not open fio volume: %d\n", rc); - return 0; - } - -@@ -1029,7 +1033,7 @@ static EFI_STATUS generate_path(EFI_LOADED_IMAGE *li, CHAR16 *ImagePath, - *PathName = AllocatePool(StrSize(bootpath) + StrSize(ImagePath)); - - if (!*PathName) { -- Print(L"Failed to allocate path buffer\n"); -+ ERROR(L"Failed to allocate path buffer\n"); - efi_status = EFI_OUT_OF_RESOURCES; - goto error; - } -@@ -1072,14 +1076,14 @@ static EFI_STATUS load_image (EFI_LOADED_IMAGE *li, void **data, - (void **)&drive); - - if (efi_status != EFI_SUCCESS) { -- Print(L"Failed to find fs\n"); -+ ERROR(L"Failed to find fs\n"); - goto error; - } - - efi_status = uefi_call_wrapper(drive->OpenVolume, 2, drive, &root); - - if (efi_status != EFI_SUCCESS) { -- Print(L"Failed to open fs\n"); -+ ERROR(L"Failed to open fs\n"); - goto error; - } - -@@ -1090,14 +1094,14 @@ static EFI_STATUS load_image (EFI_LOADED_IMAGE *li, void **data, - EFI_FILE_MODE_READ, 0); - - if (efi_status != EFI_SUCCESS) { -- Print(L"Failed to open %s - %lx\n", PathName, efi_status); -+ ERROR(L"Failed to open %s - %lx\n", PathName, efi_status); - goto error; - } - - fileinfo = AllocatePool(buffersize); - - if (!fileinfo) { -- Print(L"Unable to allocate file info buffer\n"); -+ ERROR(L"Unable to allocate file info buffer\n"); - efi_status = EFI_OUT_OF_RESOURCES; - goto error; - } -@@ -1113,7 +1117,7 @@ static EFI_STATUS load_image (EFI_LOADED_IMAGE *li, void **data, - FreePool(fileinfo); - fileinfo = AllocatePool(buffersize); - if (!fileinfo) { -- Print(L"Unable to allocate file info buffer\n"); -+ ERROR(L"Unable to allocate file info buffer\n"); - efi_status = EFI_OUT_OF_RESOURCES; - goto error; - } -@@ -1123,7 +1127,7 @@ static EFI_STATUS load_image (EFI_LOADED_IMAGE *li, void **data, - } - - if (efi_status != EFI_SUCCESS) { -- Print(L"Unable to get file info\n"); -+ ERROR(L"Unable to get file info\n"); - goto error; - } - -@@ -1132,7 +1136,7 @@ static EFI_STATUS load_image (EFI_LOADED_IMAGE *li, void **data, - *data = AllocatePool(buffersize); - - if (!*data) { -- Print(L"Unable to allocate file buffer\n"); -+ ERROR(L"Unable to allocate file buffer\n"); - efi_status = EFI_OUT_OF_RESOURCES; - goto error; - } -@@ -1151,7 +1155,7 @@ static EFI_STATUS load_image (EFI_LOADED_IMAGE *li, void **data, - } - - if (efi_status != EFI_SUCCESS) { -- Print(L"Unexpected return from initial read: %x, buffersize %x\n", efi_status, buffersize); -+ ERROR(L"Unexpected return from initial read: %x, buffersize %x\n", efi_status, buffersize); - goto error; - } - -@@ -1180,15 +1184,45 @@ EFI_STATUS shim_verify (void *buffer, UINT32 size) - EFI_STATUS status; - PE_COFF_LOADER_IMAGE_CONTEXT context; - -- if (!secure_mode()) -- return EFI_SUCCESS; -+ in_protocol = 1; -+ -+ if (!secure_mode()) { -+ status = EFI_SUCCESS; -+ goto done; -+ } - - status = read_header(buffer, size, &context); - - if (status != EFI_SUCCESS) -- return status; -+ goto done; - - status = verify_buffer(buffer, size, &context); -+done: -+ in_protocol = 0; -+ return status; -+} -+ -+static EFI_STATUS shim_hash (char *data, int datasize, -+ PE_COFF_LOADER_IMAGE_CONTEXT *context, -+ UINT8 *sha256hash, UINT8 *sha1hash) -+{ -+ EFI_STATUS status; -+ -+ in_protocol = 1; -+ status = generate_hash(data, datasize, context, sha256hash, sha1hash); -+ in_protocol = 0; -+ -+ return status; -+} -+ -+static EFI_STATUS shim_read_header(void *data, unsigned int datasize, -+ PE_COFF_LOADER_IMAGE_CONTEXT *context) -+{ -+ EFI_STATUS status; -+ -+ in_protocol = 1; -+ status = read_header(data, datasize, context); -+ in_protocol = 0; - - return status; - } -@@ -1216,7 +1250,7 @@ EFI_STATUS start_image(EFI_HANDLE image_handle, CHAR16 *ImagePath) - &loaded_image_protocol, (void **)&li); - - if (efi_status != EFI_SUCCESS) { -- Print(L"Unable to init protocol\n"); -+ ERROR(L"Unable to init protocol\n"); - return efi_status; - } - -@@ -1226,20 +1260,20 @@ EFI_STATUS start_image(EFI_HANDLE image_handle, CHAR16 *ImagePath) - efi_status = generate_path(li, ImagePath, &path, &PathName); - - if (efi_status != EFI_SUCCESS) { -- Print(L"Unable to generate path: %s\n", ImagePath); -+ ERROR(L"Unable to generate path: %s\n", ImagePath); - goto done; - } - - if (findNetboot(image_handle)) { - efi_status = parseNetbootinfo(image_handle); - if (efi_status != EFI_SUCCESS) { -- Print(L"Netboot parsing failed: %d\n", efi_status); -+ ERROR(L"Netboot parsing failed: %d\n", efi_status); - return EFI_PROTOCOL_ERROR; - } - efi_status = FetchNetbootimage(image_handle, &sourcebuffer, - &sourcesize); - if (efi_status != EFI_SUCCESS) { -- Print(L"Unable to fetch TFTP image\n"); -+ ERROR(L"Unable to fetch TFTP image\n"); - return efi_status; - } - data = sourcebuffer; -@@ -1251,7 +1285,7 @@ EFI_STATUS start_image(EFI_HANDLE image_handle, CHAR16 *ImagePath) - efi_status = load_image(li, &data, &datasize, PathName); - - if (efi_status != EFI_SUCCESS) { -- Print(L"Failed to load image\n"); -+ ERROR(L"Failed to load image\n"); - goto done; - } - } -@@ -1268,7 +1302,7 @@ EFI_STATUS start_image(EFI_HANDLE image_handle, CHAR16 *ImagePath) - efi_status = handle_image(data, datasize, li); - - if (efi_status != EFI_SUCCESS) { -- Print(L"Failed to load image\n"); -+ ERROR(L"Failed to load image\n"); - CopyMem(li, &li_bak, sizeof(li_bak)); - goto done; - } -@@ -1336,7 +1370,7 @@ EFI_STATUS mirror_mok_list() - | EFI_VARIABLE_RUNTIME_ACCESS, - DataSize, Data); - if (efi_status != EFI_SUCCESS) { -- Print(L"Failed to set MokListRT %d\n", efi_status); -+ ERROR(L"Failed to set MokListRT %d\n", efi_status); - } - - done: -@@ -1378,7 +1412,7 @@ EFI_STATUS check_mok_request(EFI_HANDLE image_handle) - efi_status = start_image(image_handle, MOK_MANAGER); - - if (efi_status != EFI_SUCCESS) { -- Print(L"Failed to start MokManager\n"); -+ ERROR(L"Failed to start MokManager\n"); - return efi_status; - } - } -@@ -1409,9 +1443,9 @@ static EFI_STATUS check_mok_sb (void) - * modified by the OS - */ - if (attributes & EFI_VARIABLE_RUNTIME_ACCESS) { -- Print(L"MokSBState is compromised! Clearing it\n"); -+ ERROR(L"MokSBState is compromised! Clearing it\n"); - if (LibDeleteVariable(L"MokSBState", &shim_lock_guid) != EFI_SUCCESS) { -- Print(L"Failed to erase MokSBState\n"); -+ ERROR(L"Failed to erase MokSBState\n"); - } - status = EFI_ACCESS_DENIED; - } else { -@@ -1442,7 +1476,7 @@ EFI_STATUS set_second_stage (EFI_HANDLE image_handle) - status = uefi_call_wrapper(BS->HandleProtocol, 3, image_handle, - &LoadedImageProtocol, (void **) &li); - if (status != EFI_SUCCESS) { -- Print (L"Failed to get load options\n"); -+ ERROR (L"Failed to get load options\n"); - return status; - } - -@@ -1486,7 +1520,7 @@ EFI_STATUS set_second_stage (EFI_HANDLE image_handle) - if (loader_len > 0) { - loader_str = AllocatePool((loader_len + 1) * sizeof(CHAR16)); - if (!loader_str) { -- Print(L"Failed to allocate loader string\n"); -+ ERROR(L"Failed to allocate loader string\n"); - return EFI_OUT_OF_RESOURCES; - } - for (i = 0; i < loader_len; i++) -@@ -1517,8 +1551,8 @@ EFI_STATUS efi_main (EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *passed_systab) - * call back in and use shim functions - */ - shim_lock_interface.Verify = shim_verify; -- shim_lock_interface.Hash = generate_hash; -- shim_lock_interface.Context = read_header; -+ shim_lock_interface.Hash = shim_hash; -+ shim_lock_interface.Context = shim_read_header; - - systab = passed_systab; - --- -1.8.1.4 - diff --git a/shim-correct-user_insecure-usage.patch b/shim-correct-user_insecure-usage.patch new file mode 100644 index 0000000..ed7619d --- /dev/null +++ b/shim-correct-user_insecure-usage.patch @@ -0,0 +1,93 @@ +commit d95b24bd02cf41cca9adebd95f10609d6424d2b3 +Author: Matthew Garrett +Date: Tue Nov 19 10:09:13 2013 -0500 + + Clarify meaning of insecure_mode + + insecure_mode was intended to indicate that the user had explicity disabled + checks with mokutil, which means it wasn't the opposite of secure_mode(). + Change the names to clarify this and don't show the insecure mode message + unless the user has explicitly enabled that mode. + + Signed-off-by: Matthew Garrett + +diff --git a/replacements.c b/replacements.c +index bac5e5d..5ea5c32 100644 +--- a/replacements.c ++++ b/replacements.c +@@ -64,13 +64,9 @@ static typeof(systab->BootServices->StartImage) system_start_image; + static typeof(systab->BootServices->Exit) system_exit; + static typeof(systab->BootServices->ExitBootServices) system_exit_boot_services; + +-extern UINT8 insecure_mode; +- + void + unhook_system_services(void) + { +- if (insecure_mode) +- return; + systab->BootServices->Exit = system_exit; + systab->BootServices->StartImage = system_start_image; + systab->BootServices->ExitBootServices = system_exit_boot_services; +@@ -123,8 +119,6 @@ exit(EFI_HANDLE ImageHandle, EFI_STATUS ExitStatus, + void + hook_system_services(EFI_SYSTEM_TABLE *local_systab) + { +- if (insecure_mode) +- return; + systab = local_systab; + + /* We need to hook various calls to make this work... */ +diff --git a/shim.c b/shim.c +index 9ae1936..524f5fc 100644 +--- a/shim.c ++++ b/shim.c +@@ -85,7 +85,7 @@ int loader_is_participating; + + #define EFI_IMAGE_SECURITY_DATABASE_GUID { 0xd719b2cb, 0x3d3a, 0x4596, { 0xa3, 0xbc, 0xda, 0xd0, 0x0e, 0x67, 0x65, 0x6f }} + +-UINT8 insecure_mode; ++UINT8 user_insecure_mode; + UINT8 ignore_db; + + typedef enum { +@@ -456,7 +456,7 @@ static BOOLEAN secure_mode (void) + UINT8 *Data; + UINT8 sb, setupmode; + +- if (insecure_mode) ++ if (user_insecure_mode) + return FALSE; + + status = get_variable(L"SecureBoot", &Data, &len, global_var); +@@ -1534,7 +1534,7 @@ static EFI_STATUS check_mok_sb (void) + UINTN MokSBStateSize = 0; + UINT32 attributes; + +- insecure_mode = 0; ++ user_insecure_mode = 0; + ignore_db = 0; + + status = get_variable_attr(L"MokSBState", &MokSBState, &MokSBStateSize, +@@ -1555,7 +1555,7 @@ static EFI_STATUS check_mok_sb (void) + status = EFI_ACCESS_DENIED; + } else { + if (*(UINT8 *)MokSBState == 1) { +- insecure_mode = 1; ++ user_insecure_mode = 1; + } + } + +@@ -1753,10 +1753,10 @@ EFI_STATUS efi_main (EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *passed_systab) + /* + * Tell the user that we're in insecure mode if necessary + */ +- if (!secure_mode()) { ++ if (user_insecure_mode) { + Print(L"Booting in insecure mode\n"); + uefi_call_wrapper(BS->Stall, 1, 2000000); +- } else { ++ } else if (secure_mode()) { + /* + * Install our hooks for ExitBootServices() and StartImage() + */ diff --git a/shim-fix-dhcpv4-path-generation.patch b/shim-fix-dhcpv4-path-generation.patch new file mode 100644 index 0000000..1d78463 --- /dev/null +++ b/shim-fix-dhcpv4-path-generation.patch @@ -0,0 +1,165 @@ +From e62b69a5b0b87c6df7a4fc23906134945309e927 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Wed, 20 Nov 2013 12:20:23 -0500 +Subject: [PATCH 1/2] Fix path generation for Dhcpv4 bootloader. + +Right now we always look for e.g. "\grubx64.efi", which is completely +wrong. This makes it look for the path shim was loaded from and modify +that to end in a sanitized version of our default loader name. + +Resolves: rhbz#1032583 + +Signed-off-by: Peter Jones +--- + include/str.h | 45 +++++++++++++++++++++++++++++++++++++++++++++ + netboot.c | 28 +++++++++++++++++++++------- + 2 files changed, 66 insertions(+), 7 deletions(-) + create mode 100644 include/str.h + +diff --git a/include/str.h b/include/str.h +new file mode 100644 +index 0000000..0f3e003 +--- /dev/null ++++ b/include/str.h +@@ -0,0 +1,45 @@ ++#ifndef SHIM_STR_H ++#define SHIM_STR_H ++ ++static inline ++__attribute__((unused)) ++unsigned long strnlena(const CHAR8 *s, unsigned long n) ++{ ++ unsigned long i; ++ for (i = 0; i <= n; i++) ++ if (s[i] == '\0') ++ break; ++ return i; ++} ++ ++static inline ++__attribute__((unused)) ++CHAR8 * ++strncpya(CHAR8 *dest, const CHAR8 *src, unsigned long n) ++{ ++ unsigned long i; ++ ++ for (i = 0; i < n && src[i] != '\0'; i++) ++ dest[i] = src[i]; ++ for (; i < n; i++) ++ dest[i] = '\0'; ++ ++ return dest; ++} ++ ++static inline ++__attribute__((unused)) ++CHAR8 * ++strcata(CHAR8 *dest, const CHAR8 *src) ++{ ++ unsigned long dest_len = strlena(dest); ++ unsigned long i; ++ ++ for (i = 0; src[i] != '\0'; i++) ++ dest[dest_len + i] = src[i]; ++ dest[dest_len + i] = '\0'; ++ ++ return dest; ++} ++ ++#endif /* SHIM_STR_H */ +diff --git a/netboot.c b/netboot.c +index a83c82a..1732dc7 100644 +--- a/netboot.c ++++ b/netboot.c +@@ -38,6 +38,7 @@ + #include + #include "shim.h" + #include "netboot.h" ++#include "str.h" + + static inline unsigned short int __swap16(unsigned short int x) + { +@@ -305,19 +306,32 @@ static EFI_STATUS parseDhcp6() + + static EFI_STATUS parseDhcp4() + { +- CHAR8 *template = (CHAR8 *)DEFAULT_LOADER_CHAR; +- full_path = AllocateZeroPool(strlen(template)+1); ++ CHAR8 *template = (CHAR8 *)translate_slashes(DEFAULT_LOADER_CHAR); ++ UINTN template_len = strlen(template) + 1; ++ ++ UINTN dir_len = strnlena(pxe->Mode->DhcpAck.Dhcpv4.BootpBootFile, 127); ++ UINTN i; ++ UINT8 *dir = pxe->Mode->DhcpAck.Dhcpv4.BootpBootFile; ++ ++ for (i = dir_len; i >= 0; i--) { ++ if (dir[i] == '/') ++ break; ++ } ++ dir_len = (i >= 0) ? i + 1 : 0; ++ ++ full_path = AllocateZeroPool(dir_len + template_len); + + if (!full_path) + return EFI_OUT_OF_RESOURCES; + ++ if (dir_len > 0) { ++ strncpya(full_path, dir, dir_len); ++ if (full_path[dir_len-1] == '/' && template[0] == '/') ++ full_path[dir_len-1] = '\0'; ++ } ++ strcata(full_path, template); + memcpy(&tftp_addr.v4, pxe->Mode->DhcpAck.Dhcpv4.BootpSiAddr, 4); + +- memcpy(full_path, template, strlen(template)); +- +- /* Note we don't capture the filename option here because we know its shim.efi +- * We instead assume the filename at the end of the path is going to be grubx64.efi +- */ + return EFI_SUCCESS; + } + +-- +1.8.1.4 + + +From 27129a5a05d1947e6f7479766e8281d50d6031f6 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Thu, 21 Nov 2013 11:26:08 -0500 +Subject: [PATCH 2/2] Lengths that might be -1 can't be unsigned, Peter. + +Signed-off-by: Peter Jones +--- + netboot.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +diff --git a/netboot.c b/netboot.c +index 1732dc7..07e2773 100644 +--- a/netboot.c ++++ b/netboot.c +@@ -307,10 +307,10 @@ static EFI_STATUS parseDhcp6() + static EFI_STATUS parseDhcp4() + { + CHAR8 *template = (CHAR8 *)translate_slashes(DEFAULT_LOADER_CHAR); +- UINTN template_len = strlen(template) + 1; ++ INTN template_len = strlen(template) + 1; + +- UINTN dir_len = strnlena(pxe->Mode->DhcpAck.Dhcpv4.BootpBootFile, 127); +- UINTN i; ++ INTN dir_len = strnlena(pxe->Mode->DhcpAck.Dhcpv4.BootpBootFile, 127); ++ INTN i; + UINT8 *dir = pxe->Mode->DhcpAck.Dhcpv4.BootpBootFile; + + for (i = dir_len; i >= 0; i--) { +@@ -329,6 +329,8 @@ static EFI_STATUS parseDhcp4() + if (full_path[dir_len-1] == '/' && template[0] == '/') + full_path[dir_len-1] = '\0'; + } ++ if (dir_len == 0 && dir[0] != '/' && template[0] == '/') ++ template++; + strcata(full_path, template); + memcpy(&tftp_addr.v4, pxe->Mode->DhcpAck.Dhcpv4.BootpSiAddr, 4); + +-- +1.8.1.4 + diff --git a/shim-fix-pointer-casting.patch b/shim-fix-pointer-casting.patch deleted file mode 100644 index af3edd9..0000000 --- a/shim-fix-pointer-casting.patch +++ /dev/null @@ -1,61 +0,0 @@ -From 23002e8e5c03800845afae8aaa7e42770c3e5d17 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Tue, 11 Jun 2013 14:58:25 -0400 -Subject: [PATCH] Fix some pointer casting issues. - -This also fixes the size of an empty vendor_cert or dbx_cert. - -Signed-off-by: Peter Jones ---- - cert.S | 2 +- - shim.c | 9 +++++---- - 2 files changed, 6 insertions(+), 5 deletions(-) - -diff --git a/cert.S b/cert.S -index 2ed9b6d..66a05b8 100644 ---- a/cert.S -+++ b/cert.S -@@ -32,5 +32,5 @@ vendor_cert: - .size vendor_cert_size, 4 - .section .vendor_cert, "a", @progbits - vendor_cert_size: -- .long 1 -+ .long 0 - #endif -diff --git a/shim.c b/shim.c -index 94b9710..7d43f04 100644 ---- a/shim.c -+++ b/shim.c -@@ -59,7 +59,7 @@ static UINT32 load_options_size; - */ - extern UINT8 vendor_cert[]; - extern UINT32 vendor_cert_size; --extern EFI_SIGNATURE_LIST *vendor_dbx; -+extern UINT8 vendor_dbx[]; - extern UINT32 vendor_dbx_size; - - #define EFI_IMAGE_SECURITY_DATABASE_GUID { 0xd719b2cb, 0x3d3a, 0x4596, { 0xa3, 0xbc, 0xda, 0xd0, 0x0e, 0x67, 0x65, 0x6f }} -@@ -359,16 +359,17 @@ static EFI_STATUS check_blacklist (WIN_CERTIFICATE_EFI_PKCS *cert, - UINT8 *sha256hash, UINT8 *sha1hash) - { - EFI_GUID secure_var = EFI_IMAGE_SECURITY_DATABASE_GUID; -+ EFI_SIGNATURE_LIST *dbx = (EFI_SIGNATURE_LIST *)vendor_dbx; - -- if (check_db_hash_in_ram(vendor_dbx, vendor_dbx_size, sha256hash, -+ if (check_db_hash_in_ram(dbx, vendor_dbx_size, sha256hash, - SHA256_DIGEST_SIZE, EfiHashSha256Guid) == - DATA_FOUND) - return EFI_ACCESS_DENIED; -- if (check_db_hash_in_ram(vendor_dbx, vendor_dbx_size, sha1hash, -+ if (check_db_hash_in_ram(dbx, vendor_dbx_size, sha1hash, - SHA1_DIGEST_SIZE, EfiHashSha1Guid) == - DATA_FOUND) - return EFI_ACCESS_DENIED; -- if (check_db_cert_in_ram(vendor_dbx, vendor_dbx_size, cert, -+ if (check_db_cert_in_ram(dbx, vendor_dbx_size, cert, - sha256hash) == DATA_FOUND) - return EFI_ACCESS_DENIED; - --- -1.8.1.4 - diff --git a/shim-fix-simple-file-selector.patch b/shim-fix-simple-file-selector.patch deleted file mode 100644 index 8e7c9c0..0000000 --- a/shim-fix-simple-file-selector.patch +++ /dev/null @@ -1,149 +0,0 @@ -From ed9cf192de86c58e9c5397afa48de7b6d7bab7a7 Mon Sep 17 00:00:00 2001 -From: Gary Ching-Pang Lin -Date: Thu, 30 May 2013 14:05:59 +0800 -Subject: [PATCH 1/2] simple_file: Allocate buffers for file entries - -The dir filter appends L'/' to the directory entries without -allocating a new buffer, and this could crash the whole program. ---- - lib/simple_file.c | 42 ++++++++++++++++++++++++++++++++++-------- - 1 file changed, 34 insertions(+), 8 deletions(-) - -diff --git a/lib/simple_file.c b/lib/simple_file.c -index 0e5ecd2..e288272 100644 ---- a/lib/simple_file.c -+++ b/lib/simple_file.c -@@ -344,9 +344,12 @@ simple_dir_filter(EFI_HANDLE image, CHAR16 *name, CHAR16 *filter, - goto next; - - if (next->Attribute & EFI_FILE_DIRECTORY) { -- (*result)[(*count)] = next->FileName; -- (*result)[(*count)][len] = '/'; -- (*result)[(*count)++][len + 1] = '\0'; -+ (*result)[(*count)] = PoolPrint(L"%s/", next->FileName); -+ if (!(*result)[(*count)]) { -+ Print(L"Failed to allocate buffer"); -+ return EFI_OUT_OF_RESOURCES; -+ } -+ (*count)++; - goto next; - } - -@@ -354,7 +357,12 @@ simple_dir_filter(EFI_HANDLE image, CHAR16 *name, CHAR16 *filter, - offs = StrLen(filterarr[c]); - - if (StrCmp(&next->FileName[len - offs], filterarr[c]) == 0) { -- (*result)[(*count)++] = next->FileName; -+ (*result)[(*count)] = StrDuplicate(next->FileName); -+ if (!(*result)[(*count)]) { -+ Print(L"Failed to allocate buffer"); -+ return EFI_OUT_OF_RESOURCES; -+ } -+ (*count)++; - } else { - continue; - } -@@ -362,7 +370,7 @@ simple_dir_filter(EFI_HANDLE image, CHAR16 *name, CHAR16 *filter, - } - - next: -- if (StrCmp(next->FileName, L"../") == 0) { -+ if (StrCmp(next->FileName, L"..") == 0) { - /* place .. directory first */ - CHAR16 *tmp = (*result)[(*count) - 1]; - -@@ -392,6 +400,15 @@ simple_dir_filter(EFI_HANDLE image, CHAR16 *name, CHAR16 *filter, - return status; - } - -+static void -+free_entries(CHAR16 **entries, int count) -+{ -+ int i; -+ -+ for (i = 0; i -Date: Thu, 30 May 2013 14:10:56 +0800 -Subject: [PATCH 2/2] Clean lib/, too - ---- - Makefile | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/Makefile b/Makefile -index f64f409..ed47360 100644 ---- a/Makefile -+++ b/Makefile -@@ -109,6 +109,7 @@ lib/lib.a: - clean: - $(MAKE) -C Cryptlib clean - $(MAKE) -C Cryptlib/OpenSSL clean -+ $(MAKE) -C lib clean - rm -rf $(TARGET) $(OBJS) $(MOK_OBJS) $(FALLBACK_OBJS) $(KEYS) certdb - rm -f *.debug *.so *.efi - --- -1.8.1.4 - diff --git a/shim-fix-verify-mok.patch b/shim-fix-verify-mok.patch new file mode 100644 index 0000000..261e1c0 --- /dev/null +++ b/shim-fix-verify-mok.patch @@ -0,0 +1,49 @@ +commit 11495d4019d44dce1487939f91f7d751ffbb9730 +Author: Andrew Boie +Date: Mon Apr 15 14:11:17 2013 -0700 + + fix verify_mok() + + () Fix the return value semantics. If the MokList doesn't + exist, we are OK. If the MokList was compromised but we + were able to erase it, that is OK too. Only if the list + can't be nuked do we return an error. + + () Fix use of potentially uninitialized attribute variable + + () Actually use the return value when called from verify_buffer. + + Change-Id: If16df21d79c52a1726928df96d133390cde4cb7e + Signed-off-by: Andrew Boie + +diff --git a/shim.c b/shim.c +index 23dd0ee..dcb36d0 100644 +--- a/shim.c ++++ b/shim.c +@@ -670,13 +670,12 @@ static EFI_STATUS verify_mok (void) { + status = get_variable_attr(L"MokList", &MokListData, &MokListDataSize, + shim_lock_guid, &attributes); + +- if (attributes & EFI_VARIABLE_RUNTIME_ACCESS) { ++ if (!EFI_ERROR(status) && attributes & EFI_VARIABLE_RUNTIME_ACCESS) { + Print(L"MokList is compromised!\nErase all keys in MokList!\n"); + if (LibDeleteVariable(L"MokList", &shim_lock_guid) != EFI_SUCCESS) { + Print(L"Failed to erase MokList\n"); ++ return EFI_ACCESS_DENIED; + } +- status = EFI_ACCESS_DENIED; +- return status; + } + + if (MokListData) +@@ -722,7 +721,9 @@ static EFI_STATUS verify_buffer (char *data, int datasize, + /* + * Check that the MOK database hasn't been modified + */ +- verify_mok(); ++ status = verify_mok(); ++ if (status != EFI_SUCCESS) ++ return status; + + /* + * Ensure that the binary isn't blacklisted diff --git a/shim-improve-error-messages.patch b/shim-improve-error-messages.patch new file mode 100644 index 0000000..7b40aa7 --- /dev/null +++ b/shim-improve-error-messages.patch @@ -0,0 +1,181 @@ +commit 2f09d0ab290d9b0d8aa14c3243f1d85a20bc34e6 +Author: Andrew Boie +Date: Mon Nov 11 17:29:06 2013 -0800 + + shim: improve error messages + + %r when used in Print() will show a string representation of + an EFI_STATUS code. + + Change-Id: I6db47f5213454603bd66177aca378ad01e9f0bd4 + Signed-off-by: Andrew Boie + +diff --git a/shim.c b/shim.c +index a043779..9ae1936 100644 +--- a/shim.c ++++ b/shim.c +@@ -914,7 +914,7 @@ static EFI_STATUS handle_image (void *data, unsigned int datasize, + */ + efi_status = read_header(data, datasize, &context); + if (efi_status != EFI_SUCCESS) { +- Print(L"Failed to read header\n"); ++ Print(L"Failed to read header: %r\n", efi_status); + return efi_status; + } + +@@ -981,7 +981,7 @@ static EFI_STATUS handle_image (void *data, unsigned int datasize, + efi_status = relocate_coff(&context, buffer); + + if (efi_status != EFI_SUCCESS) { +- Print(L"Relocation failed\n"); ++ Print(L"Relocation failed: %r\n", efi_status); + FreePool(buffer); + return efi_status; + } +@@ -1022,7 +1022,7 @@ should_use_fallback(EFI_HANDLE image_handle) + rc = uefi_call_wrapper(BS->HandleProtocol, 3, image_handle, + &loaded_image_protocol, (void **)&li); + if (EFI_ERROR(rc)) { +- Print(L"Could not get image for bootx64.efi: %d\n", rc); ++ Print(L"Could not get image for bootx64.efi: %r\n", rc); + return 0; + } + +@@ -1044,13 +1044,13 @@ should_use_fallback(EFI_HANDLE image_handle) + rc = uefi_call_wrapper(BS->HandleProtocol, 3, li->DeviceHandle, + &FileSystemProtocol, (void **)&fio); + if (EFI_ERROR(rc)) { +- Print(L"Could not get fio for li->DeviceHandle: %d\n", rc); ++ Print(L"Could not get fio for li->DeviceHandle: %r\n", rc); + return 0; + } + + rc = uefi_call_wrapper(fio->OpenVolume, 2, fio, &vh); + if (EFI_ERROR(rc)) { +- Print(L"Could not open fio volume: %d\n", rc); ++ Print(L"Could not open fio volume: %r\n", rc); + return 0; + } + +@@ -1172,14 +1172,14 @@ static EFI_STATUS load_image (EFI_LOADED_IMAGE *li, void **data, + (void **)&drive); + + if (efi_status != EFI_SUCCESS) { +- Print(L"Failed to find fs\n"); ++ Print(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) { +- Print(L"Failed to open fs\n"); ++ Print(L"Failed to open fs: %r\n", efi_status); + goto error; + } + +@@ -1190,7 +1190,7 @@ static EFI_STATUS load_image (EFI_LOADED_IMAGE *li, void **data, + EFI_FILE_MODE_READ, 0); + + if (efi_status != EFI_SUCCESS) { +- Print(L"Failed to open %s - %lx\n", PathName, efi_status); ++ Print(L"Failed to open %s - %r\n", PathName, efi_status); + goto error; + } + +@@ -1223,7 +1223,7 @@ static EFI_STATUS load_image (EFI_LOADED_IMAGE *li, void **data, + } + + if (efi_status != EFI_SUCCESS) { +- Print(L"Unable to get file info\n"); ++ Print(L"Unable to get file info: %r\n", efi_status); + goto error; + } + +@@ -1251,7 +1251,7 @@ static EFI_STATUS load_image (EFI_LOADED_IMAGE *li, void **data, + } + + if (efi_status != EFI_SUCCESS) { +- Print(L"Unexpected return from initial read: %x, buffersize %x\n", efi_status, buffersize); ++ Print(L"Unexpected return from initial read: %r, buffersize %x\n", efi_status, buffersize); + goto error; + } + +@@ -1328,20 +1328,20 @@ EFI_STATUS start_image(EFI_HANDLE image_handle, CHAR16 *ImagePath) + efi_status = generate_path(li, ImagePath, &path, &PathName); + + if (efi_status != EFI_SUCCESS) { +- Print(L"Unable to generate path: %s\n", ImagePath); ++ Print(L"Unable to generate path %s: %r\n", ImagePath, efi_status); + goto done; + } + + if (findNetboot(image_handle)) { + efi_status = parseNetbootinfo(image_handle); + if (efi_status != EFI_SUCCESS) { +- Print(L"Netboot parsing failed: %d\n", efi_status); ++ Print(L"Netboot parsing failed: %r\n", efi_status); + return EFI_PROTOCOL_ERROR; + } + efi_status = FetchNetbootimage(image_handle, &sourcebuffer, + &sourcesize); + if (efi_status != EFI_SUCCESS) { +- Print(L"Unable to fetch TFTP image\n"); ++ Print(L"Unable to fetch TFTP image: %r\n", efi_status); + return efi_status; + } + data = sourcebuffer; +@@ -1353,7 +1353,7 @@ EFI_STATUS start_image(EFI_HANDLE image_handle, CHAR16 *ImagePath) + efi_status = load_image(li, &data, &datasize, PathName); + + if (efi_status != EFI_SUCCESS) { +- Print(L"Failed to load image\n"); ++ Print(L"Failed to load image %s: %r\n", PathName, efi_status); + goto done; + } + } +@@ -1370,7 +1370,7 @@ EFI_STATUS start_image(EFI_HANDLE image_handle, CHAR16 *ImagePath) + efi_status = handle_image(data, datasize, li); + + if (efi_status != EFI_SUCCESS) { +- Print(L"Failed to load image\n"); ++ Print(L"Failed to load image: %r\n", efi_status); + CopyMem(li, &li_bak, sizeof(li_bak)); + goto done; + } +@@ -1473,7 +1473,7 @@ EFI_STATUS mirror_mok_list() + | EFI_VARIABLE_RUNTIME_ACCESS, + FullDataSize, FullData); + if (efi_status != EFI_SUCCESS) { +- Print(L"Failed to set MokListRT %d\n", efi_status); ++ Print(L"Failed to set MokListRT: %r\n", efi_status); + } + + return efi_status; +@@ -1514,7 +1514,7 @@ EFI_STATUS check_mok_request(EFI_HANDLE image_handle) + efi_status = start_image(image_handle, MOK_MANAGER); + + if (efi_status != EFI_SUCCESS) { +- Print(L"Failed to start MokManager\n"); ++ Print(L"Failed to start MokManager: %r\n", efi_status); + return efi_status; + } + } +@@ -1621,7 +1621,7 @@ static EFI_STATUS mok_ignore_db() + | EFI_VARIABLE_RUNTIME_ACCESS, + DataSize, (void *)&Data); + if (efi_status != EFI_SUCCESS) { +- Print(L"Failed to set MokIgnoreDB %d\n", efi_status); ++ Print(L"Failed to set MokIgnoreDB: %r\n", efi_status); + } + } + +@@ -1648,7 +1648,7 @@ EFI_STATUS set_second_stage (EFI_HANDLE image_handle) + status = uefi_call_wrapper(BS->HandleProtocol, 3, image_handle, + &LoadedImageProtocol, (void **) &li); + if (status != EFI_SUCCESS) { +- Print (L"Failed to get load options\n"); ++ Print (L"Failed to get load options: %r\n", status); + return status; + } + diff --git a/shim-merge-lf-loader-code.patch b/shim-merge-lf-loader-code.patch deleted file mode 100644 index 6692f39..0000000 --- a/shim-merge-lf-loader-code.patch +++ /dev/null @@ -1,5260 +0,0 @@ -From 43a23fadf063d0644d123a8024f9a864ed32135f Mon Sep 17 00:00:00 2001 -From: Matthew Garrett -Date: Sun, 19 May 2013 18:13:01 +0100 -Subject: [PATCH] Port MokManager to Linux Foundation loader UI code - -This is the first stage of porting the MokManager UI to the UI code used -by the Linux Foundation UEFI loader. ---- - Makefile | 9 +- - MokManager.c | 1220 +++++++++++++++----------------------------- - include/PeImage.h | 787 ++++++++++++++++++++++++++++ - include/configtable.h | 68 +++ - include/console.h | 21 + - include/efiauthenticated.h | 222 ++++++++ - include/errors.h | 9 + - include/execute.h | 5 + - include/guid.h | 18 + - include/security_policy.h | 6 + - include/shell.h | 2 + - include/simple_file.h | 21 + - include/variables.h | 59 +++ - include/version.h | 8 + - include/wincert.h | 33 ++ - lib/Makefile | 28 + - lib/configtable.c | 144 ++++++ - lib/console.c | 402 +++++++++++++++ - lib/execute.c | 127 +++++ - lib/guid.c | 47 ++ - lib/security_policy.c | 391 ++++++++++++++ - lib/shell.c | 57 +++ - lib/simple_file.c | 501 ++++++++++++++++++ - lib/variables.c | 340 ++++++++++++ - 24 files changed, 3721 insertions(+), 804 deletions(-) - create mode 100644 include/PeImage.h - create mode 100644 include/configtable.h - create mode 100644 include/console.h - create mode 100644 include/efiauthenticated.h - create mode 100644 include/errors.h - create mode 100644 include/execute.h - create mode 100644 include/guid.h - create mode 100644 include/security_policy.h - create mode 100644 include/shell.h - create mode 100644 include/simple_file.h - create mode 100644 include/variables.h - create mode 100644 include/version.h - create mode 100644 include/wincert.h - create mode 100644 lib/Makefile - create mode 100644 lib/configtable.c - create mode 100644 lib/console.c - create mode 100644 lib/execute.c - create mode 100644 lib/guid.c - create mode 100644 lib/security_policy.c - create mode 100644 lib/shell.c - create mode 100644 lib/simple_file.c - create mode 100644 lib/variables.c - -diff --git a/Makefile b/Makefile -index 287fbcf..b37ceb3 100644 ---- a/Makefile -+++ b/Makefile -@@ -1,6 +1,6 @@ - ARCH = $(shell uname -m | sed s,i[3456789]86,ia32,) - --SUBDIRS = Cryptlib -+SUBDIRS = Cryptlib lib - - LIB_PATH = /usr/lib64 - -@@ -74,8 +74,8 @@ fallback.so: $(FALLBACK_OBJS) - - MokManager.o: $(SOURCES) - --MokManager.so: $(MOK_OBJS) Cryptlib/libcryptlib.a Cryptlib/OpenSSL/libopenssl.a -- $(LD) -o $@ $(LDFLAGS) $^ $(EFI_LIBS) -+MokManager.so: $(MOK_OBJS) Cryptlib/libcryptlib.a Cryptlib/OpenSSL/libopenssl.a lib/lib.a -+ $(LD) -o $@ $(LDFLAGS) $^ $(EFI_LIBS) lib/lib.a - - Cryptlib/libcryptlib.a: - $(MAKE) -C Cryptlib -@@ -83,6 +83,9 @@ Cryptlib/libcryptlib.a: - Cryptlib/OpenSSL/libopenssl.a: - $(MAKE) -C Cryptlib/OpenSSL - -+lib/lib.a: -+ $(MAKE) -C lib -+ - %.efi: %.so - objcopy -j .text -j .sdata -j .data \ - -j .dynamic -j .dynsym -j .rel \ -diff --git a/MokManager.c b/MokManager.c -index 97588cb..60e799a 100644 ---- a/MokManager.c -+++ b/MokManager.c -@@ -6,6 +6,9 @@ - #include "signature.h" - #include "PeImage.h" - -+#include "include/console.h" -+#include "include/simple_file.h" -+ - #define PASSWORD_MAX 16 - #define PASSWORD_MIN 8 - #define SB_PASSWORD_LEN 8 -@@ -16,18 +19,6 @@ - - #define EFI_VARIABLE_APPEND_WRITE 0x00000040 - --#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; -@@ -56,7 +47,7 @@ static EFI_STATUS get_variable (CHAR16 *name, EFI_GUID guid, UINT32 *attributes, - *buffer = AllocatePool(*size); - - if (!*buffer) { -- Print(L"Unable to allocate variable buffer\n"); -+ console_notify(L"Unable to allocate variable buffer"); - return EFI_OUT_OF_RESOURCES; - } - -@@ -88,24 +79,24 @@ static EFI_STATUS get_sha1sum (void *Data, int DataSize, UINT8 *hash) - ctx = AllocatePool(ctxsize); - - if (!ctx) { -- Print(L"Unable to allocate memory for hash context\n"); -+ console_notify(L"Unable to allocate memory for hash context"); - return EFI_OUT_OF_RESOURCES; - } - - if (!Sha1Init(ctx)) { -- Print(L"Unable to initialise hash\n"); -+ console_notify(L"Unable to initialise hash"); - status = EFI_OUT_OF_RESOURCES; - goto done; - } - - if (!(Sha1Update(ctx, Data, DataSize))) { -- Print(L"Unable to generate hash\n"); -+ console_notify(L"Unable to generate hash"); - status = EFI_OUT_OF_RESOURCES; - goto done; - } - - if (!(Sha1Final(ctx, hash))) { -- Print(L"Unable to finalise hash\n"); -+ console_notify(L"Unable to finalise hash"); - status = EFI_OUT_OF_RESOURCES; - goto done; - } -@@ -126,7 +117,7 @@ static UINT32 count_keys(void *Data, UINTN DataSize) - while ((dbsize > 0) && (dbsize >= CertList->SignatureListSize)) { - if ((CompareGuid (&CertList->SignatureType, &CertType) != 0) && - (CompareGuid (&CertList->SignatureType, &HashType) != 0)) { -- Print(L"Doesn't look like a key or hash\n"); -+ console_notify(L"Doesn't look like a key or hash"); - dbsize -= CertList->SignatureListSize; - CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + - CertList->SignatureListSize); -@@ -135,7 +126,7 @@ static UINT32 count_keys(void *Data, UINTN DataSize) - - if ((CompareGuid (&CertList->SignatureType, &CertType) != 0) && - (CertList->SignatureSize != 48)) { -- Print(L"Doesn't look like a valid hash\n"); -+ console_notify(L"Doesn't look like a valid hash"); - dbsize -= CertList->SignatureListSize; - CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + - CertList->SignatureListSize); -@@ -163,7 +154,7 @@ static MokListNode *build_mok_list(UINT32 num, void *Data, UINTN DataSize) { - list = AllocatePool(sizeof(MokListNode) * num); - - if (!list) { -- Print(L"Unable to allocate MOK list\n"); -+ console_notify(L"Unable to allocate MOK list"); - return NULL; - } - -@@ -200,15 +191,17 @@ static MokListNode *build_mok_list(UINT32 num, void *Data, UINTN DataSize) { - return list; - } - --static void print_x509_name (X509_NAME *X509Name, CHAR16 *name) -+static CHAR16* get_x509_name (X509_NAME *X509Name, CHAR16 *name) - { - char *str; -+ CHAR16 *ret = NULL; - - str = X509_NAME_oneline(X509Name, NULL, 0); - if (str) { -- Print(L" %s:\n %a\n", name, str); -+ ret = PoolPrint(L"%s: %a", name, str); - OPENSSL_free(str); - } -+ return ret; - } - - static const char *mon[12]= { -@@ -315,7 +308,7 @@ error: - return; - } - --static void print_x509_time (ASN1_TIME *time, CHAR16 *name) -+static CHAR16* get_x509_time (ASN1_TIME *time, CHAR16 *name) - { - CHAR16 time_string[30]; - -@@ -327,48 +320,126 @@ static void print_x509_time (ASN1_TIME *time, CHAR16 *name) - time_string[0] = '\0'; - } - -- Print(L" %s:\n %s\n", name, time_string); -+ return PoolPrint(L"%s: %s", name, time_string); - } - --static void show_x509_info (X509 *X509Cert) -+static void show_x509_info (X509 *X509Cert, UINT8 *hash) - { - ASN1_INTEGER *serial; - BIGNUM *bnser; - unsigned char hexbuf[30]; - X509_NAME *X509Name; - ASN1_TIME *time; -+ CHAR16 *issuer = NULL; -+ CHAR16 *subject = NULL; -+ CHAR16 *from = NULL; -+ CHAR16 *until = NULL; -+ POOL_PRINT hash_string1; -+ POOL_PRINT hash_string2; -+ POOL_PRINT serial_string; -+ int fields = 0; -+ CHAR16 **text; -+ int i = 0; -+ -+ ZeroMem(&hash_string1, sizeof(hash_string1)); -+ ZeroMem(&hash_string2, sizeof(hash_string2)); -+ ZeroMem(&serial_string, sizeof(serial_string)); - - serial = X509_get_serialNumber(X509Cert); - if (serial) { - int i, n; - bnser = ASN1_INTEGER_to_BN(serial, NULL); - n = BN_bn2bin(bnser, hexbuf); -- Print(L" Serial Number:\n "); -- for (i = 0; i < n-1; i++) { -- Print(L"%02x:", hexbuf[i]); -+ CatPrint(&serial_string, L"Serial Number:"); -+ for (i = 0; i < n; i++) { -+ CatPrint(&serial_string, L"%02x:", hexbuf[i]); - } -- Print(L"%02x\n", hexbuf[n-1]); - } - -+ if (serial_string.str) -+ fields++; -+ - X509Name = X509_get_issuer_name(X509Cert); - if (X509Name) { -- print_x509_name(X509Name, L"Issuer"); -+ issuer = get_x509_name(X509Name, L"Issuer"); -+ if (issuer) -+ fields++; - } - - X509Name = X509_get_subject_name(X509Cert); - if (X509Name) { -- print_x509_name(X509Name, L"Subject"); -+ subject = get_x509_name(X509Name, L"Subject"); -+ if (subject) -+ fields++; - } - - time = X509_get_notBefore(X509Cert); - if (time) { -- print_x509_time(time, L"Validity from"); -+ from = get_x509_time(time, L"Validity from"); -+ if (time) -+ fields++; - } - - time = X509_get_notAfter(X509Cert); - if (time) { -- print_x509_time(time, L"Validity till"); -+ until = get_x509_time(time, L"Validity till"); -+ if (until) -+ fields++; -+ } -+ -+#if 0 -+ CatPrint(&hash_string1, L"SHA1 Fingerprint: "); -+ for (i=0; i<10; i++) -+ CatPrint(&hash_string1, L"%02x ", hash[i]); -+ for (i=10; i<20; i++) -+ CatPrint(&hash_string2, L"%02x ", hash[i]); -+ -+ if (hash_string1.str) -+ fields++; -+ -+ if (hash_string2.str) -+ fields++; -+#endif -+ if (!fields) -+ return; -+ -+ text = AllocateZeroPool(sizeof(CHAR16 *) * (fields + 1)); -+ if (serial_string.str) { -+ text[i] = serial_string.str; -+ i++; -+ } -+ if (issuer) { -+ text[i] = issuer; -+ i++; -+ } -+ if (subject) { -+ text[i] = subject; -+ i++; -+ } -+ if (from) { -+ text[i] = from; -+ i++; -+ } -+ if (until) { -+ text[i] = until; -+ i++; - } -+ if (hash_string1.str) { -+ text[i] = hash_string1.str; -+ i++; -+ } -+ if (hash_string2.str) { -+ text[i] = hash_string2.str; -+ i++; -+ } -+ text[i] = NULL; -+ -+ console_alertbox(text); -+ -+ for (i=0; text[i] != NULL; i++) -+ FreePool(text[i]); -+ -+ FreePool(text); - } - - static void show_mok_info (void *Mok, UINTN MokSize) -@@ -382,28 +453,20 @@ static void show_mok_info (void *Mok, UINTN MokSize) - return; - - if (MokSize != SHA256_DIGEST_SIZE) { -- if (X509ConstructCertificate(Mok, MokSize, -- (UINT8 **) &X509Cert) && X509Cert != NULL) { -- show_x509_info(X509Cert); -- X509_free(X509Cert); -- } else { -- Print(L" Not a valid X509 certificate: %x\n\n", -- ((UINT32 *)Mok)[0]); -- return; -- } -- - efi_status = get_sha1sum(Mok, MokSize, hash); - - if (efi_status != EFI_SUCCESS) { -- Print(L"Failed to compute MOK fingerprint\n"); -+ console_notify(L"Failed to compute MOK fingerprint"); - return; - } - -- Print(L" Fingerprint (SHA1):\n "); -- for (i = 0; i < SHA1_DIGEST_SIZE; i++) { -- Print(L" %02x", hash[i]); -- if (i % 10 == 9) -- Print(L"\n "); -+ if (X509ConstructCertificate(Mok, MokSize, -+ (UINT8 **) &X509Cert) && X509Cert != NULL) { -+ show_x509_info(X509Cert, hash); -+ X509_free(X509Cert); -+ } else { -+ console_notify(L"Not a valid X509 certificate"); -+ return; - } - } else { - Print(L"SHA256 hash:\n "); -@@ -414,58 +477,19 @@ static void show_mok_info (void *Mok, UINTN MokSize) - } - Print(L"\n"); - } -- -- Print(L"\n"); --} -- --static INTN get_number () --{ -- EFI_INPUT_KEY input_key; -- CHAR16 input[10]; -- int count = 0; -- -- do { -- input_key = get_keystroke(); -- -- if ((input_key.UnicodeChar < '0' || -- input_key.UnicodeChar > '9' || -- count >= 10) && -- input_key.UnicodeChar != CHAR_BACKSPACE) { -- continue; -- } -- -- if (count == 0 && input_key.UnicodeChar == CHAR_BACKSPACE) -- continue; -- -- Print(L"%c", input_key.UnicodeChar); -- -- if (input_key.UnicodeChar == CHAR_BACKSPACE) { -- input[--count] = '\0'; -- continue; -- } -- -- input[count++] = input_key.UnicodeChar; -- } while (input_key.UnicodeChar != CHAR_CARRIAGE_RETURN); -- -- if (count == 0) -- return -1; -- -- input[count] = '\0'; -- -- return (INTN)Atoi(input); - } - --static UINT8 list_keys (void *KeyList, UINTN KeyListSize, CHAR16 *title) -+static EFI_STATUS list_keys (void *KeyList, UINTN KeyListSize, CHAR16 *title) - { - UINT32 MokNum = 0; - MokListNode *keys = NULL; - INTN key_num = 0; -- UINT8 initial = 1; -+ CHAR16 **menu_strings; -+ int i; - - if (KeyListSize < (sizeof(EFI_SIGNATURE_LIST) + - sizeof(EFI_SIGNATURE_DATA))) { -- Print(L"No keys\n"); -- Pause(); -+ console_notify(L"No MOK keys found"); - return 0; - } - -@@ -473,41 +497,38 @@ static UINT8 list_keys (void *KeyList, UINTN KeyListSize, CHAR16 *title) - keys = build_mok_list(MokNum, KeyList, KeyListSize); - - if (!keys) { -- Print(L"Failed to construct key list\n"); -+ console_notify(L"Failed to construct key list"); - return 0; - } - -- do { -- uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut); -- if (title) -- Print(L"%s\n", title); -- Print(L"Input the key number to show the details of the key or\n" -- L"type \'0\' to continue\n\n"); -- Print(L"%d key(s) in the key list\n\n", MokNum); -- -- if (key_num > MokNum) { -- Print(L"[Key %d]\n", key_num); -- Print(L"No such key\n\n"); -- } else if (initial != 1 && key_num > 0){ -- Print(L"[Key %d]\n", key_num); -- show_mok_info(keys[key_num-1].Mok, keys[key_num-1].MokSize); -- } -+ menu_strings = AllocateZeroPool(sizeof(CHAR16 *) * (MokNum + 2)); -+ -+ if (!menu_strings) -+ return EFI_OUT_OF_RESOURCES; - -- Print(L"Key Number: "); -+ for (i=0; iResetSystem, 4, EfiResetWarm, -- EFI_SUCCESS, 0, NULL); -- Print(L"Failed to reboot\n"); -- return -1; -- } -+ if (auth) { -+ LibDeleteVariable(L"MokNew", &shim_lock_guid); -+ LibDeleteVariable(L"MokAuth", &shim_lock_guid); - -- return 0; -- } -- } while (line[0] != 'N' && line[0] != 'n'); -- return -1; --} -+ console_notify(L"The system must now be rebooted"); -+ uefi_call_wrapper(RT->ResetSystem, 4, EfiResetWarm, -+ EFI_SUCCESS, 0, NULL); -+ console_notify(L"Failed to reboot"); -+ return -1; -+ } - --static INTN mok_enrollment_prompt_callback (void *MokNew, void *data2, -- void *data3) --{ -- uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut); -- return mok_enrollment_prompt(MokNew, (UINTN)data2, TRUE); -+ return 0; - } - --static INTN mok_reset_prompt (void *MokNew, void *data2, void *data3) -+static INTN mok_reset_prompt () - { - EFI_GUID shim_lock_guid = SHIM_LOCK_GUID; -- CHAR16 line[1]; -- UINT32 length; - EFI_STATUS efi_status; - - uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut); -- Print(L"Erase all stored keys? (y/N): "); -- -- get_line (&length, line, 1, 1); - -- if (line[0] == 'Y' || line[0] == 'y') { -- efi_status = store_keys(NULL, 0, TRUE); -+ if (console_yes_no((CHAR16 *[]){L"Erase all stored keys?", NULL }) == 0) -+ return 0; - -- if (efi_status != EFI_SUCCESS) { -- Print(L"Failed to erase keys\n"); -- return -1; -- } -+ efi_status = store_keys(NULL, 0, TRUE); - -- LibDeleteVariable(L"MokNew", &shim_lock_guid); -- LibDeleteVariable(L"MokAuth", &shim_lock_guid); -- -- Print(L"\nPress a key to reboot system\n"); -- Pause(); -- uefi_call_wrapper(RT->ResetSystem, 4, EfiResetWarm, -- EFI_SUCCESS, 0, NULL); -- Print(L"Failed to reboot\n"); -+ if (efi_status != EFI_SUCCESS) { -+ console_notify(L"Failed to erase keys\n"); - return -1; - } - -- return 0; -+ LibDeleteVariable(L"MokNew", &shim_lock_guid); -+ LibDeleteVariable(L"MokAuth", &shim_lock_guid); -+ -+ console_notify(L"The system must now be rebooted"); -+ uefi_call_wrapper(RT->ResetSystem, 4, EfiResetWarm, -+ EFI_SUCCESS, 0, NULL); -+ console_notify(L"Failed to reboot\n"); -+ return -1; - } - - static EFI_STATUS write_back_mok_list (MokListNode *list, INTN key_num) -@@ -831,7 +828,7 @@ static EFI_STATUS write_back_mok_list (MokListNode *list, INTN key_num) - FreePool(Data); - - if (efi_status != EFI_SUCCESS) { -- Print(L"Failed to set variable %d\n", efi_status); -+ console_error(L"Failed to set variable", efi_status); - return efi_status; - } - -@@ -856,7 +853,7 @@ static EFI_STATUS delete_keys (void *MokDel, UINTN MokDelSize) - &attributes, &auth_size, auth); - - if (efi_status != EFI_SUCCESS || auth_size != SHA256_DIGEST_SIZE) { -- Print(L"Failed to get MokDelAuth %d\n", efi_status); -+ console_error(L"Failed to get MokDelAuth", efi_status); - return efi_status; - } - -@@ -868,9 +865,11 @@ static EFI_STATUS delete_keys (void *MokDel, UINTN MokDelSize) - &MokListDataSize, &MokListData); - - if (attributes & EFI_VARIABLE_RUNTIME_ACCESS) { -- Print(L"MokList is compromised!\nErase all keys in MokList!\n"); -+ console_alertbox((CHAR16 *[]){L"MokList is compromised!", -+ L"Erase all keys in MokList!", -+ NULL}); - if (LibDeleteVariable(L"MokList", &shim_lock_guid) != EFI_SUCCESS) { -- Print(L"Failed to erase MokList\n"); -+ console_notify(L"Failed to erase MokList"); - } - return EFI_ACCESS_DENIED; - } -@@ -911,59 +910,48 @@ static EFI_STATUS delete_keys (void *MokDel, UINTN MokDelSize) - return efi_status; - } - --static INTN mok_deletion_prompt (void *MokDel, void *data2, void *data3) -+static INTN mok_deletion_prompt (void *MokDel, UINTN MokDelSize) - { - EFI_GUID shim_lock_guid = SHIM_LOCK_GUID; -- UINTN MokDelSize = (UINTN)data2; -- CHAR16 line[1]; -- UINT32 length; - EFI_STATUS efi_status; - -- do { -- if (!list_keys(MokDel, MokDelSize, L"[Delete MOK]")) { -- return 0; -- } -- -- Print(L"Delete the key(s)? (y/n): "); -+ if (list_keys(MokDel, MokDelSize, L"[Delete MOK]") != EFI_SUCCESS) { -+ return 0; -+ } - -- get_line (&length, line, 1, 1); -+ if (console_yes_no((CHAR16 *[]){L"Delete the key(s)?", NULL}) == 0) -+ return 0; - -- if (line[0] == 'Y' || line[0] == 'y') { -- efi_status = delete_keys(MokDel, MokDelSize); -+ efi_status = delete_keys(MokDel, MokDelSize); - -- if (efi_status != EFI_SUCCESS) { -- Print(L"Failed to delete keys\n"); -- return -1; -- } -+ if (efi_status != EFI_SUCCESS) { -+ console_notify(L"Failed to delete keys"); -+ return -1; -+ } - -- LibDeleteVariable(L"MokDel", &shim_lock_guid); -- LibDeleteVariable(L"MokDelAuth", &shim_lock_guid); -+ LibDeleteVariable(L"MokDel", &shim_lock_guid); -+ LibDeleteVariable(L"MokDelAuth", &shim_lock_guid); - -- Print(L"\nPress a key to reboot system\n"); -- Pause(); -- uefi_call_wrapper(RT->ResetSystem, 4, EfiResetWarm, -- EFI_SUCCESS, 0, NULL); -- Print(L"Failed to reboot\n"); -- return -1; -- } -- } while (line[0] != 'N' && line[0] != 'n'); -+ console_notify(L"The system must now be rebooted"); -+ uefi_call_wrapper(RT->ResetSystem, 4, EfiResetWarm, -+ EFI_SUCCESS, 0, NULL); -+ console_notify(L"Failed to reboot"); - return -1; - } - --static INTN mok_sb_prompt (void *MokSB, void *data2, void *data3) { -+static INTN mok_sb_prompt (void *MokSB, UINTN MokSBSize) { - EFI_GUID shim_lock_guid = SHIM_LOCK_GUID; - EFI_STATUS efi_status; -- UINTN MokSBSize = (UINTN)data2; - MokSBvar *var = MokSB; - CHAR16 pass1, pass2, pass3; - UINT8 fail_count = 0; - UINT32 length; -- CHAR16 line[1]; - UINT8 sbval = 1; - UINT8 pos1, pos2, pos3; -+ int ret; - - if (MokSBSize != sizeof(MokSBvar)) { -- Print(L"Invalid MokSB variable contents\n"); -+ console_notify(L"Invalid MokSB variable contents"); - return -1; - } - -@@ -1003,61 +991,49 @@ static INTN mok_sb_prompt (void *MokSB, void *data2, void *data3) { - } - - if (fail_count >= 3) { -- Print(L"Password limit reached\n"); -+ console_notify(L"Password limit reached"); - return -1; - } - -- if (var->MokSBState == 0) { -- Print(L"Disable Secure Boot? (y/n): "); -- } else { -- Print(L"Enable Secure Boot? (y/n): "); -- } -+ if (var->MokSBState == 0) -+ ret = console_yes_no((CHAR16 *[]){L"Disable Secure Boot", NULL}); -+ else -+ ret = console_yes_no((CHAR16 *[]){L"Enable Secure Boot", NULL}); - -- do { -- get_line (&length, line, 1, 1); -+ if (ret == 0) { -+ LibDeleteVariable(L"MokSB", &shim_lock_guid); -+ return -1; -+ } - -- if (line[0] == 'Y' || line[0] == 'y') { -- if (var->MokSBState == 0) { -- efi_status = uefi_call_wrapper(RT->SetVariable, -- 5, L"MokSBState", -- &shim_lock_guid, -+ 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) { -- Print(L"Failed to set Secure Boot state\n"); -- return -1; -- } -- } else { -- LibDeleteVariable(L"MokSBState", -- &shim_lock_guid); -- } -- -- LibDeleteVariable(L"MokSB", &shim_lock_guid); -- -- Print(L"Press a key to reboot system\n"); -- Pause(); -- uefi_call_wrapper(RT->ResetSystem, 4, EfiResetWarm, -- EFI_SUCCESS, 0, NULL); -- Print(L"Failed to reboot\n"); -+ 1, &sbval); -+ if (efi_status != EFI_SUCCESS) { -+ console_notify(L"Failed to set Secure Boot state"); - return -1; - } -- } while (line[0] != 'N' && line[0] != 'n'); -+ } else { -+ LibDeleteVariable(L"MokSBState", &shim_lock_guid); -+ } - -+ console_notify(L"The system must now be rebooted"); -+ uefi_call_wrapper(RT->ResetSystem, 4, EfiResetWarm, -+ EFI_SUCCESS, 0, NULL); -+ console_notify(L"Failed to reboot"); - return -1; - } - -- --static INTN mok_pw_prompt (void *MokPW, void *data2, void *data3) { -+static INTN mok_pw_prompt (void *MokPW, UINTN MokPWSize) { - EFI_GUID shim_lock_guid = SHIM_LOCK_GUID; - EFI_STATUS efi_status; -- UINTN MokPWSize = (UINTN)data2; - UINT8 hash[SHA256_DIGEST_SIZE]; -- UINT32 length; -- CHAR16 line[1]; - - if (MokPWSize != SHA256_DIGEST_SIZE) { -- Print(L"Invalid MokPW variable contents\n"); -+ console_notify(L"Invalid MokPW variable contents"); - return -1; - } - -@@ -1066,190 +1042,41 @@ static INTN mok_pw_prompt (void *MokPW, void *data2, void *data3) { - SetMem(hash, SHA256_DIGEST_SIZE, 0); - - if (CompareMem(MokPW, hash, SHA256_DIGEST_SIZE) == 0) { -- Print(L"Clear MOK password? (y/n): "); -- -- do { -- get_line (&length, line, 1, 1); -- -- if (line[0] == 'Y' || line[0] == 'y') { -- LibDeleteVariable(L"MokPWStore", &shim_lock_guid); -- LibDeleteVariable(L"MokPW", &shim_lock_guid); -- } -- } while (line[0] != 'N' && line[0] != 'n'); -+ if (console_yes_no((CHAR16 *[]){L"Clear MOK password?", NULL}) == 0) -+ return 0; - -+ LibDeleteVariable(L"MokPWStore", &shim_lock_guid); -+ LibDeleteVariable(L"MokPW", &shim_lock_guid); - return 0; - } - - efi_status = match_password(NULL, 0, MokPW, L"Confirm MOK passphrase: "); - if (efi_status != EFI_SUCCESS) { -- Print(L"Password limit reached\n"); -+ console_notify(L"Password limit reached"); - return -1; - } - -- Print(L"Set MOK password? (y/n): "); -- -- do { -- get_line (&length, line, 1, 1); -- -- if (line[0] == 'Y' || line[0] == 'y') { -- 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) { -- Print(L"Failed to set MOK password\n"); -- return -1; -- } -- -- LibDeleteVariable(L"MokPW", &shim_lock_guid); -- -- Print(L"Press a key to reboot system\n"); -- Pause(); -- uefi_call_wrapper(RT->ResetSystem, 4, EfiResetWarm, -- EFI_SUCCESS, 0, NULL); -- Print(L"Failed to reboot\n"); -- return -1; -- } -- } while (line[0] != 'N' && line[0] != 'n'); -- -- return 0; --} -- --static UINTN draw_menu (CHAR16 *header, UINTN lines, struct menu_item *items, -- UINTN count) { -- UINTN i; -- -- uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut); -- -- uefi_call_wrapper(ST->ConOut->SetAttribute, 2, ST->ConOut, -- EFI_WHITE | EFI_BACKGROUND_BLACK); -- -- Print(L"%s UEFI key management\n\n", SHIM_VENDOR); -- -- if (header) -- Print(L"%s", header); -- -- for (i = 0; i < count; i++) { -- uefi_call_wrapper(ST->ConOut->SetAttribute, 2, ST->ConOut, -- items[i].colour | EFI_BACKGROUND_BLACK); -- Print(L" %s\n", items[i].text); -- } -- -- uefi_call_wrapper(ST->ConOut->SetCursorPosition, 3, ST->ConOut, 0, 0); -- uefi_call_wrapper(ST->ConOut->EnableCursor, 2, ST->ConOut, TRUE); -- -- return 2 + lines; --} -- --static void free_menu (struct menu_item *items, UINTN count) { -- UINTN i; -+ if (console_yes_no((CHAR16 *[]){L"Set MOK password?", NULL}) == 0) -+ return 0; - -- for (i=0; iSetVariable, 5, -+ L"MokPWStore", -+ &shim_lock_guid, -+ EFI_VARIABLE_NON_VOLATILE | -+ EFI_VARIABLE_BOOTSERVICE_ACCESS, -+ MokPWSize, MokPW); -+ if (efi_status != EFI_SUCCESS) { -+ console_notify(L"Failed to set MOK password"); -+ return -1; - } - -- FreePool(items); --} -- --static void update_time (UINTN position, UINTN timeout) --{ -- uefi_call_wrapper(ST->ConOut->SetCursorPosition, 3, ST->ConOut, 0, -- position); -- -- uefi_call_wrapper(ST->ConOut->SetAttribute, 2, ST->ConOut, -- EFI_BLACK | EFI_BACKGROUND_BLACK); -- -- Print(L" ", timeout); -- -- uefi_call_wrapper(ST->ConOut->SetCursorPosition, 3, ST->ConOut, 0, -- position); -- -- uefi_call_wrapper(ST->ConOut->SetAttribute, 2, ST->ConOut, -- EFI_WHITE | EFI_BACKGROUND_BLACK); -- -- if (timeout > 1) -- Print(L"Booting in %d seconds\n", timeout); -- else if (timeout) -- Print(L"Booting in %d second\n", timeout); --} -- --static void run_menu (CHAR16 *header, UINTN lines, struct menu_item *items, -- UINTN count, UINTN timeout) { -- UINTN index, pos = 0, wait = 0, offset; -- EFI_INPUT_KEY key; -- EFI_STATUS status; -- INTN ret; -- -- if (timeout) -- wait = 10000000; -- -- offset = draw_menu (header, lines, items, count); -- -- while (1) { -- update_time(count + offset + 1, timeout); -- -- uefi_call_wrapper(ST->ConOut->SetCursorPosition, 3, ST->ConOut, -- 0, pos + offset); -- status = WaitForSingleEvent(ST->ConIn->WaitForKey, wait); -- -- if (status == EFI_TIMEOUT) { -- timeout--; -- if (!timeout) { -- free_menu(items, count); -- return; -- } -- continue; -- } -- -- wait = 0; -- timeout = 0; -- -- uefi_call_wrapper(BS->WaitForEvent, 3, 1, -- &ST->ConIn->WaitForKey, &index); -- uefi_call_wrapper(ST->ConIn->ReadKeyStroke, 2, ST->ConIn, -- &key); -- -- switch(key.ScanCode) { -- case SCAN_UP: -- if (pos == 0) -- continue; -- pos--; -- continue; -- break; -- case SCAN_DOWN: -- if (pos == (count - 1)) -- continue; -- pos++; -- continue; -- break; -- } -- -- switch(key.UnicodeChar) { -- case CHAR_LINEFEED: -- case CHAR_CARRIAGE_RETURN: -- if (items[pos].callback == NULL) { -- free_menu(items, count); -- return; -- } -+ LibDeleteVariable(L"MokPW", &shim_lock_guid); - -- ret = items[pos].callback(items[pos].data, -- items[pos].data2, -- items[pos].data3); -- if (ret < 0) { -- Print(L"Press a key to continue\n"); -- Pause(); -- /* Clear the key in the queue */ -- uefi_call_wrapper(ST->ConIn->ReadKeyStroke, 2, -- ST->ConIn, &key); -- } -- draw_menu (header, lines, items, count); -- pos = 0; -- break; -- } -- } -+ console_notify(L"The system must now be rebooted"); -+ uefi_call_wrapper(RT->ResetSystem, 4, EfiResetWarm, EFI_SUCCESS, 0, -+ NULL); -+ console_notify(L"Failed to reboot"); -+ return -1; - } - - static UINTN verify_certificate(void *cert, UINTN size) -@@ -1260,8 +1087,7 @@ static UINTN verify_certificate(void *cert, UINTN size) - - if (!(X509ConstructCertificate(cert, size, (UINT8 **) &X509Cert)) || - X509Cert == NULL) { -- Print(L"Invalid X509 certificate\n"); -- Pause(); -+ console_notify(L"Invalid X509 certificate"); - return FALSE; - } - -@@ -1269,49 +1095,22 @@ static UINTN verify_certificate(void *cert, UINTN size) - return TRUE; - } - --static INTN file_callback (void *data, void *data2, void *data3) { -- EFI_FILE_INFO *buffer = NULL; -- UINTN buffersize = 0, mokbuffersize; -- EFI_STATUS status; -- EFI_FILE *file; -- CHAR16 *filename = data; -- EFI_FILE *parent = data2; -- BOOLEAN hash = !!data3; -- EFI_GUID file_info_guid = EFI_FILE_INFO_ID; -+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_SIGNATURE_LIST *CertList; - EFI_SIGNATURE_DATA *CertData; -+ UINTN mokbuffersize; - void *mokbuffer = NULL; - -- status = uefi_call_wrapper(parent->Open, 5, parent, &file, filename, -- EFI_FILE_MODE_READ, 0); -- -- if (status != EFI_SUCCESS) -- return 1; -- -- status = uefi_call_wrapper(file->GetInfo, 4, file, &file_info_guid, -- &buffersize, buffer); -- -- if (status == EFI_BUFFER_TOO_SMALL) { -- buffer = AllocatePool(buffersize); -- status = uefi_call_wrapper(file->GetInfo, 4, file, -- &file_info_guid, &buffersize, -- buffer); -- } -- -- if (!buffer) -- return 0; -- -- buffersize = buffer->FileSize; -- - if (hash) { -- void *binary; - 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) -@@ -1325,20 +1124,12 @@ static INTN file_callback (void *data, void *data2, void *data3) { - if (!mokbuffer) - goto out; - -- binary = AllocatePool(buffersize); -- -- status = uefi_call_wrapper(file->Read, 3, file, &buffersize, -- binary); -- -- if (status != EFI_SUCCESS) -- goto out; -- -- status = shim_lock->Context(binary, buffersize, &context); -+ status = shim_lock->Context(data, datasize, &context); - - if (status != EFI_SUCCESS) - goto out; -- -- status = shim_lock->Hash(binary, buffersize, &context, sha256, -+ -+ status = shim_lock->Hash(data, datasize, &context, sha256, - sha1); - - if (status != EFI_SUCCESS) -@@ -1351,7 +1142,7 @@ static INTN file_callback (void *data, void *data2, void *data3) { - sizeof(EFI_SIGNATURE_LIST)); - CopyMem(CertData->SignatureData, sha256, SHA256_DIGEST_SIZE); - } else { -- mokbuffersize = buffersize + sizeof(EFI_SIGNATURE_LIST) + -+ mokbuffersize = datasize + sizeof(EFI_SIGNATURE_LIST) + - sizeof(EFI_GUID); - mokbuffer = AllocatePool(mokbuffersize); - -@@ -1360,12 +1151,11 @@ static INTN file_callback (void *data, void *data2, void *data3) { - - CertList = mokbuffer; - CertList->SignatureType = EfiCertX509Guid; -- CertList->SignatureSize = 16 + buffersize; -- status = uefi_call_wrapper(file->Read, 3, file, &buffersize, -- mokbuffer + sizeof(EFI_SIGNATURE_LIST) + 16); -+ CertList->SignatureSize = 16 + datasize; -+ -+ memcpy(mokbuffer + sizeof(EFI_SIGNATURE_LIST) + 16, data, -+ datasize); - -- if (status != EFI_SUCCESS) -- goto out; - CertData = (EFI_SIGNATURE_DATA *)(((UINT8 *)mokbuffer) + - sizeof(EFI_SIGNATURE_LIST)); - } -@@ -1375,316 +1165,100 @@ static INTN file_callback (void *data, void *data2, void *data3) { - CertData->SignatureOwner = shim_lock_guid; - - if (!hash) { -- if (!verify_certificate(CertData->SignatureData, buffersize)) -+ if (!verify_certificate(CertData->SignatureData, datasize)) - goto out; - } - - mok_enrollment_prompt(mokbuffer, mokbuffersize, FALSE); - out: -- if (buffer) -- FreePool(buffer); -- - if (mokbuffer) - FreePool(mokbuffer); - -- return 0; -+ return status; - } - --static INTN directory_callback (void *data, void *data2, void *data3) { -- EFI_FILE_INFO *buffer = NULL; -- UINTN buffersize = 0; -- EFI_STATUS status; -- UINTN dircount = 0, i = 0; -- struct menu_item *dircontent; -- EFI_FILE *dir; -- CHAR16 *filename = data; -- EFI_FILE *root = data2; -- BOOLEAN hash = !!data3; -- -- status = uefi_call_wrapper(root->Open, 5, root, &dir, filename, -- EFI_FILE_MODE_READ, 0); -- -- if (status != EFI_SUCCESS) -- return 1; -- -- while (1) { -- status = uefi_call_wrapper(dir->Read, 3, dir, &buffersize, -- buffer); -- -- if (status == EFI_BUFFER_TOO_SMALL) { -- buffer = AllocatePool(buffersize); -- status = uefi_call_wrapper(dir->Read, 3, dir, -- &buffersize, buffer); -- } -- -- if (status != EFI_SUCCESS) -- return 1; -- -- if (!buffersize) -- break; -- -- if ((StrCmp(buffer->FileName, L".") == 0) || -- (StrCmp(buffer->FileName, L"..") == 0)) -- continue; -- -- dircount++; -- -- FreePool(buffer); -- buffersize = 0; -- } -- -- dircount++; -- -- dircontent = AllocatePool(sizeof(struct menu_item) * dircount); -- -- dircontent[0].text = StrDuplicate(L".."); -- dircontent[0].callback = NULL; -- dircontent[0].colour = EFI_YELLOW; -- i++; -- -- uefi_call_wrapper(dir->SetPosition, 2, dir, 0); -- -- while (1) { -- status = uefi_call_wrapper(dir->Read, 3, dir, &buffersize, -- buffer); -- -- if (status == EFI_BUFFER_TOO_SMALL) { -- buffer = AllocatePool(buffersize); -- status = uefi_call_wrapper(dir->Read, 3, dir, -- &buffersize, buffer); -- } -- -- if (status != EFI_SUCCESS) -- return 1; -+static void mok_hash_enroll(void) -+{ -+ EFI_STATUS efi_status; -+ CHAR16 *file_name = NULL; -+ EFI_HANDLE im = NULL; -+ EFI_FILE *file = NULL; -+ UINTN filesize; -+ void *data; - -- if (!buffersize) -- break; -+ 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); - -- if ((StrCmp(buffer->FileName, L".") == 0) || -- (StrCmp(buffer->FileName, L"..") == 0)) -- continue; -+ if (!file_name) -+ return; - -- if (buffer->Attribute & EFI_FILE_DIRECTORY) { -- dircontent[i].text = StrDuplicate(buffer->FileName); -- dircontent[i].callback = directory_callback; -- dircontent[i].data = dircontent[i].text; -- dircontent[i].data2 = dir; -- dircontent[i].data3 = data3; -- dircontent[i].colour = EFI_YELLOW; -- } else { -- dircontent[i].text = StrDuplicate(buffer->FileName); -- dircontent[i].callback = file_callback; -- dircontent[i].data = dircontent[i].text; -- dircontent[i].data2 = dir; -- dircontent[i].data3 = data3; -- dircontent[i].colour = EFI_WHITE; -- } -+ efi_status = simple_file_open(im, file_name, &file, EFI_FILE_MODE_READ); - -- i++; -- FreePool(buffer); -- buffersize = 0; -- buffer = NULL; -+ if (efi_status != EFI_SUCCESS) { -+ console_error(L"Unable to open file", efi_status); -+ return; - } - -- if (hash) -- run_menu(HASH_STRING, 2, dircontent, dircount, 0); -- else -- run_menu(CERT_STRING, 2, dircontent, dircount, 0); -+ simple_file_read_all(file, &filesize, &data); -+ simple_file_close(file); - -- return 0; --} -- --static INTN filesystem_callback (void *data, void *data2, void *data3) { -- EFI_FILE_INFO *buffer = NULL; -- UINTN buffersize = 0; -- EFI_STATUS status; -- UINTN dircount = 0, i = 0; -- struct menu_item *dircontent; -- EFI_FILE *root = data; -- BOOLEAN hash = !!data3; -- -- uefi_call_wrapper(root->SetPosition, 2, root, 0); -- -- while (1) { -- status = uefi_call_wrapper(root->Read, 3, root, &buffersize, -- buffer); -- -- if (status == EFI_BUFFER_TOO_SMALL) { -- buffer = AllocatePool(buffersize); -- status = uefi_call_wrapper(root->Read, 3, root, -- &buffersize, buffer); -- } -- -- if (status != EFI_SUCCESS) -- return 1; -- -- if (!buffersize) -- break; -- -- if ((StrCmp(buffer->FileName, L".") == 0) || -- (StrCmp(buffer->FileName, L"..") == 0)) -- continue; -- -- dircount++; -- -- FreePool(buffer); -- buffersize = 0; -+ if (!filesize) { -+ console_error(L"Unable to read file", efi_status); -+ return; - } - -- dircount++; -- -- dircontent = AllocatePool(sizeof(struct menu_item) * dircount); -- -- dircontent[0].text = StrDuplicate(L"Return to filesystem list"); -- dircontent[0].callback = NULL; -- dircontent[0].colour = EFI_YELLOW; -- i++; -- -- uefi_call_wrapper(root->SetPosition, 2, root, 0); -- -- while (1) { -- status = uefi_call_wrapper(root->Read, 3, root, &buffersize, -- buffer); -- -- if (status == EFI_BUFFER_TOO_SMALL) { -- buffer = AllocatePool(buffersize); -- status = uefi_call_wrapper(root->Read, 3, root, -- &buffersize, buffer); -- } -- -- if (status != EFI_SUCCESS) -- return 1; -- -- if (!buffersize) -- break; -- -- if ((StrCmp(buffer->FileName, L".") == 0) || -- (StrCmp(buffer->FileName, L"..") == 0)) -- continue; -- -- if (buffer->Attribute & EFI_FILE_DIRECTORY) { -- dircontent[i].text = StrDuplicate(buffer->FileName); -- dircontent[i].callback = directory_callback; -- dircontent[i].data = dircontent[i].text; -- dircontent[i].data2 = root; -- dircontent[i].data3 = data3; -- dircontent[i].colour = EFI_YELLOW; -- } else { -- dircontent[i].text = StrDuplicate(buffer->FileName); -- dircontent[i].callback = file_callback; -- dircontent[i].data = dircontent[i].text; -- dircontent[i].data2 = root; -- dircontent[i].data3 = data3; -- dircontent[i].colour = EFI_WHITE; -- } -- -- i++; -- FreePool(buffer); -- buffer = NULL; -- buffersize = 0; -- } -+ efi_status = enroll_file(data, filesize, TRUE); - -- if (hash) -- run_menu(HASH_STRING, 2, dircontent, dircount, 0); -- else -- run_menu(CERT_STRING, 2, dircontent, dircount, 0); -+ if (efi_status != EFI_SUCCESS) -+ console_error(L"Hash failed (did you select a valid EFI binary?)", efi_status); - -- return 0; -+ FreePool(data); - } - --static INTN find_fs (void *data, void *data2, void *data3) { -- EFI_GUID fs_guid = SIMPLE_FILE_SYSTEM_PROTOCOL; -- UINTN count, i; -- UINTN OldSize, NewSize; -- EFI_HANDLE *filesystem_handles = NULL; -- struct menu_item *filesystems; -- BOOLEAN hash = !!data3; -- -- uefi_call_wrapper(BS->LocateHandleBuffer, 5, ByProtocol, &fs_guid, -- NULL, &count, &filesystem_handles); -- -- if (!count || !filesystem_handles) { -- Print(L"No filesystems?\n"); -- return 1; -- } -- -- count++; -- -- filesystems = AllocatePool(sizeof(struct menu_item) * count); -- -- filesystems[0].text = StrDuplicate(L"Exit"); -- filesystems[0].callback = NULL; -- filesystems[0].colour = EFI_YELLOW; -- -- for (i=1; iHandleProtocol, 3, fs, &fs_guid, -- (void **)&fs_interface); -- -- if (status != EFI_SUCCESS || !fs_interface) -- continue; -- -- path = DevicePathFromHandle(fs); -- -- status = uefi_call_wrapper(fs_interface->OpenVolume, 2, -- fs_interface, &root); -- -- if (status != EFI_SUCCESS || !root) -- continue; -- -- status = uefi_call_wrapper(root->GetInfo, 4, root, -- &file_info_guid, &buffersize, -- buffer); -+static void mok_key_enroll(void) -+{ -+ EFI_STATUS efi_status; -+ CHAR16 *file_name = NULL; -+ EFI_HANDLE im = NULL; -+ EFI_FILE *file = NULL; -+ UINTN filesize; -+ void *data; - -- if (status == EFI_BUFFER_TOO_SMALL) { -- buffer = AllocatePool(buffersize); -- status = uefi_call_wrapper(root->GetInfo, 4, root, -- &file_info_guid, -- &buffersize, buffer); -- } -+ 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); - -- if (status == EFI_SUCCESS) -- VolumeLabel = buffer->VolumeLabel; -- -- if (path) -- filesystems[i].text = DevicePathToStr(path); -- else -- filesystems[i].text = StrDuplicate(L"Unknown device\n"); -- if (VolumeLabel) { -- OldSize = (StrLen(filesystems[i].text) + 1) * sizeof(CHAR16); -- NewSize = OldSize + StrLen(VolumeLabel) * sizeof(CHAR16); -- filesystems[i].text = ReallocatePool(filesystems[i].text, -- OldSize, NewSize); -- StrCat(filesystems[i].text, VolumeLabel); -- } -+ if (!file_name) -+ return; - -- if (buffersize) -- FreePool(buffer); -+ efi_status = simple_file_open(im, file_name, &file, EFI_FILE_MODE_READ); - -- filesystems[i].data = root; -- filesystems[i].data2 = NULL; -- filesystems[i].data3 = data3; -- filesystems[i].callback = filesystem_callback; -- filesystems[i].colour = EFI_YELLOW; -+ if (efi_status != EFI_SUCCESS) { -+ console_error(L"Unable to open file", efi_status); -+ return; - } - -- uefi_call_wrapper(BS->FreePool, 1, filesystem_handles); -+ simple_file_read_all(file, &filesize, &data); -+ simple_file_close(file); - -- if (hash) -- run_menu(HASH_STRING, 2, filesystems, count, 0); -- else -- run_menu(CERT_STRING, 2, filesystems, count, 0); -+ if (!filesize) { -+ console_error(L"Unable to read file", efi_status); -+ return; -+ } - -- return 0; -+ enroll_file(data, filesize, FALSE); -+ FreePool(data); - } - - static BOOLEAN verify_pw(void) -@@ -1714,20 +1288,33 @@ static BOOLEAN verify_pw(void) - - efi_status = match_password(NULL, 0, pwhash, L"Enter MOK password: "); - if (efi_status != EFI_SUCCESS) { -- Print(L"Password limit reached\n"); -+ console_notify(L"Password limit reached"); - return FALSE; - } - - return TRUE; - } - -+typedef enum { -+ MOK_CONTINUE_BOOT, -+ MOK_RESET_MOK, -+ MOK_ENROLL_MOK, -+ MOK_DELETE_MOK, -+ MOK_CHANGE_SB, -+ MOK_SET_PW, -+ MOK_KEY_ENROLL, -+ MOK_HASH_ENROLL -+} mok_menu_item; -+ - static EFI_STATUS enter_mok_menu(EFI_HANDLE image_handle, - void *MokNew, UINTN MokNewSize, - void *MokDel, UINTN MokDelSize, - void *MokSB, UINTN MokSBSize, - void *MokPW, UINTN MokPWSize) - { -- struct menu_item *menu_item; -+ CHAR16 **menu_strings; -+ mok_menu_item *menu_item; -+ int choice = 0; - UINT32 MokAuth = 0; - UINT32 MokDelAuth = 0; - UINTN menucount = 3, i = 0; -@@ -1736,10 +1323,11 @@ static EFI_STATUS enter_mok_menu(EFI_HANDLE image_handle, - UINT8 auth[SHA256_DIGEST_SIZE]; - UINTN auth_size = SHA256_DIGEST_SIZE; - UINT32 attributes; -+ EFI_STATUS ret = EFI_SUCCESS; - - if (verify_pw() == FALSE) - return EFI_ACCESS_DENIED; -- -+ - efi_status = uefi_call_wrapper(RT->GetVariable, 5, L"MokAuth", - &shim_lock_guid, - &attributes, &auth_size, auth); -@@ -1766,78 +1354,108 @@ static EFI_STATUS enter_mok_menu(EFI_HANDLE image_handle, - if (MokPW) - menucount++; - -- menu_item = AllocateZeroPool(sizeof(struct menu_item) * menucount); -+ menu_strings = AllocateZeroPool(sizeof(CHAR16 *) * (menucount + 1)); - -- if (!menu_item) -+ if (!menu_strings) - return EFI_OUT_OF_RESOURCES; - -- menu_item[i].text = StrDuplicate(L"Continue boot"); -- menu_item[i].colour = EFI_WHITE; -- menu_item[i].callback = NULL; -+ menu_item = AllocateZeroPool(sizeof(mok_menu_item) * menucount); -+ -+ if (!menu_item) { -+ FreePool(menu_strings); -+ return EFI_OUT_OF_RESOURCES; -+ } -+ -+ menu_strings[i] = StrDuplicate(L"Continue boot"); -+ menu_item[i] = MOK_CONTINUE_BOOT; - - i++; - - if (MokNew || MokAuth) { - if (!MokNew) { -- menu_item[i].text = StrDuplicate(L"Reset MOK"); -- menu_item[i].colour = EFI_WHITE; -- menu_item[i].callback = mok_reset_prompt; -+ menu_strings[i] = StrDuplicate(L"Reset MOK"); -+ menu_item[i] = MOK_RESET_MOK; - } else { -- menu_item[i].text = StrDuplicate(L"Enroll MOK"); -- menu_item[i].colour = EFI_WHITE; -- menu_item[i].data = MokNew; -- menu_item[i].data2 = (void *)MokNewSize; -- menu_item[i].callback = mok_enrollment_prompt_callback; -+ menu_strings[i] = StrDuplicate(L"Enroll MOK"); -+ menu_item[i] = MOK_ENROLL_MOK; - } - i++; - } - -- if (MokDel || MokDelAuth) { -- menu_item[i].text = StrDuplicate(L"Delete MOK"); -- menu_item[i].colour = EFI_WHITE; -- menu_item[i].data = MokDel; -- menu_item[i].data2 = (void *)MokDelSize; -- menu_item[i].callback = mok_deletion_prompt; -+ if (MokDel || MokDelAuth) { -+ menu_strings[i] = StrDuplicate(L"Delete MOK"); -+ menu_item[i] = MOK_DELETE_MOK; - i++; - } - - if (MokSB) { -- menu_item[i].text = StrDuplicate(L"Change Secure Boot state"); -- menu_item[i].colour = EFI_WHITE; -- menu_item[i].callback = mok_sb_prompt; -- menu_item[i].data = MokSB; -- menu_item[i].data2 = (void *)MokSBSize; -+ menu_strings[i] = StrDuplicate(L"Change Secure Boot state"); -+ menu_item[i] = MOK_CHANGE_SB; - i++; - } - - if (MokPW) { -- menu_item[i].text = StrDuplicate(L"Set MOK password"); -- menu_item[i].colour = EFI_WHITE; -- menu_item[i].callback = mok_pw_prompt; -- menu_item[i].data = MokPW; -- menu_item[i].data2 = (void *)MokPWSize; -+ menu_strings[i] = StrDuplicate(L"Set MOK password"); -+ menu_item[i] = MOK_SET_PW; - i++; - } - -- menu_item[i].text = StrDuplicate(L"Enroll key from disk"); -- menu_item[i].colour = EFI_WHITE; -- menu_item[i].callback = find_fs; -- menu_item[i].data3 = (void *)FALSE; -+ menu_strings[i] = StrDuplicate(L"Enroll key from disk"); -+ menu_item[i] = MOK_KEY_ENROLL; -+ i++; - -+ menu_strings[i] = StrDuplicate(L"Enroll hash from disk"); -+ menu_item[i] = MOK_HASH_ENROLL; - i++; - -- menu_item[i].text = StrDuplicate(L"Enroll hash from disk"); -- menu_item[i].colour = EFI_WHITE; -- menu_item[i].callback = find_fs; -- menu_item[i].data3 = (void *)TRUE; -+ menu_strings[i] = NULL; - -- i++; -+ while (choice >= 0) { -+ choice = console_select((CHAR16 *[]){ L"Perform MOK management", NULL }, -+ menu_strings, 0); - -- run_menu(NULL, 0, menu_item, menucount, 10); -+ if (choice < 0) -+ goto out; - -- uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut); -+ switch (menu_item[choice]) { -+ case MOK_CONTINUE_BOOT: -+ goto out; -+ case MOK_RESET_MOK: -+ mok_reset_prompt(); -+ break; -+ case MOK_ENROLL_MOK: -+ mok_enrollment_prompt(MokNew, MokNewSize, TRUE); -+ break; -+ case MOK_DELETE_MOK: -+ mok_deletion_prompt(MokDel, MokDelSize); -+ break; -+ case MOK_CHANGE_SB: -+ mok_sb_prompt(MokSB, MokSBSize); -+ break; -+ case MOK_SET_PW: -+ mok_pw_prompt(MokPW, MokPWSize); -+ break; -+ case MOK_KEY_ENROLL: -+ mok_key_enroll(); -+ break; -+ case MOK_HASH_ENROLL: -+ mok_hash_enroll(); -+ break; -+ } -+ } - -- return 0; -+out: -+ console_reset(); -+ -+ for (i=0; menu_strings[i] != NULL; i++) -+ FreePool(menu_strings[i]); -+ -+ FreePool(menu_strings); -+ -+ if (menu_item) -+ FreePool(menu_item); -+ -+ return ret; - } - - static EFI_STATUS check_mok_request(EFI_HANDLE image_handle) -@@ -1862,28 +1480,28 @@ static EFI_STATUS check_mok_request(EFI_HANDLE image_handle) - - if (MokNew) { - if (LibDeleteVariable(L"MokNew", &shim_lock_guid) != EFI_SUCCESS) { -- Print(L"Failed to delete MokNew\n"); -+ console_notify(L"Failed to delete MokNew"); - } - FreePool (MokNew); - } - - if (MokDel) { - if (LibDeleteVariable(L"MokDel", &shim_lock_guid) != EFI_SUCCESS) { -- Print(L"Failed to delete MokDel\n"); -+ console_notify(L"Failed to delete MokDel"); - } - FreePool (MokDel); - } - - if (MokSB) { - if (LibDeleteVariable(L"MokSB", &shim_lock_guid) != EFI_SUCCESS) { -- Print(L"Failed to delete MokSB\n"); -+ console_notify(L"Failed to delete MokSB"); - } - FreePool (MokNew); - } - - if (MokPW) { - if (LibDeleteVariable(L"MokPW", &shim_lock_guid) != EFI_SUCCESS) { -- Print(L"Failed to delete MokPW\n"); -+ console_notify(L"Failed to delete MokPW"); - } - FreePool (MokNew); - } -diff --git a/include/PeImage.h b/include/PeImage.h -new file mode 100644 -index 0000000..ec13404 ---- /dev/null -+++ b/include/PeImage.h -@@ -0,0 +1,787 @@ -+/** @file -+ EFI image format for PE32, PE32+ and TE. Please note some data structures are -+ different for PE32 and PE32+. EFI_IMAGE_NT_HEADERS32 is for PE32 and -+ EFI_IMAGE_NT_HEADERS64 is for PE32+. -+ -+ This file is coded to the Visual Studio, Microsoft Portable Executable and -+ Common Object File Format Specification, Revision 8.0 - May 16, 2006. -+ This file also includes some definitions in PI Specification, Revision 1.0. -+ -+Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
-+Portions copyright (c) 2008 - 2009, Apple Inc. 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. -+ -+**/ -+ -+#ifndef __PE_IMAGE_H__ -+#define __PE_IMAGE_H__ -+ -+#include -+ -+#define SIGNATURE_16(A, B) ((A) | (B << 8)) -+#define SIGNATURE_32(A, B, C, D) (SIGNATURE_16 (A, B) | (SIGNATURE_16 (C, D) << 16)) -+#define SIGNATURE_64(A, B, C, D, E, F, G, H) \ -+ (SIGNATURE_32 (A, B, C, D) | ((UINT64) (SIGNATURE_32 (E, F, G, H)) << 32)) -+ -+#define ALIGN_VALUE(Value, Alignment) ((Value) + (((Alignment) - (Value)) & ((Alignment) - 1))) -+#define ALIGN_POINTER(Pointer, Alignment) ((VOID *) (ALIGN_VALUE ((UINTN)(Pointer), (Alignment)))) -+ -+// -+// PE32+ Subsystem type for EFI images -+// -+#define EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION 10 -+#define EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER 11 -+#define EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER 12 -+#define EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER 13 ///< defined PI Specification, 1.0 -+ -+ -+// -+// PE32+ Machine type for EFI images -+// -+#define IMAGE_FILE_MACHINE_I386 0x014c -+#define IMAGE_FILE_MACHINE_IA64 0x0200 -+#define IMAGE_FILE_MACHINE_EBC 0x0EBC -+#define IMAGE_FILE_MACHINE_X64 0x8664 -+#define IMAGE_FILE_MACHINE_ARMTHUMB_MIXED 0x01c2 -+ -+// -+// EXE file formats -+// -+#define EFI_IMAGE_DOS_SIGNATURE SIGNATURE_16('M', 'Z') -+#define EFI_IMAGE_OS2_SIGNATURE SIGNATURE_16('N', 'E') -+#define EFI_IMAGE_OS2_SIGNATURE_LE SIGNATURE_16('L', 'E') -+#define EFI_IMAGE_NT_SIGNATURE SIGNATURE_32('P', 'E', '\0', '\0') -+ -+/// -+/// PE images can start with an optional DOS header, so if an image is run -+/// under DOS it can print an error message. -+/// -+typedef struct { -+ UINT16 e_magic; ///< Magic number. -+ UINT16 e_cblp; ///< Bytes on last page of file. -+ UINT16 e_cp; ///< Pages in file. -+ UINT16 e_crlc; ///< Relocations. -+ UINT16 e_cparhdr; ///< Size of header in paragraphs. -+ UINT16 e_minalloc; ///< Minimum extra paragraphs needed. -+ UINT16 e_maxalloc; ///< Maximum extra paragraphs needed. -+ UINT16 e_ss; ///< Initial (relative) SS value. -+ UINT16 e_sp; ///< Initial SP value. -+ UINT16 e_csum; ///< Checksum. -+ UINT16 e_ip; ///< Initial IP value. -+ UINT16 e_cs; ///< Initial (relative) CS value. -+ UINT16 e_lfarlc; ///< File address of relocation table. -+ UINT16 e_ovno; ///< Overlay number. -+ UINT16 e_res[4]; ///< Reserved words. -+ UINT16 e_oemid; ///< OEM identifier (for e_oeminfo). -+ UINT16 e_oeminfo; ///< OEM information; e_oemid specific. -+ UINT16 e_res2[10]; ///< Reserved words. -+ UINT32 e_lfanew; ///< File address of new exe header. -+} EFI_IMAGE_DOS_HEADER; -+ -+/// -+/// COFF File Header (Object and Image). -+/// -+typedef struct { -+ UINT16 Machine; -+ UINT16 NumberOfSections; -+ UINT32 TimeDateStamp; -+ UINT32 PointerToSymbolTable; -+ UINT32 NumberOfSymbols; -+ UINT16 SizeOfOptionalHeader; -+ UINT16 Characteristics; -+} EFI_IMAGE_FILE_HEADER; -+ -+/// -+/// Size of EFI_IMAGE_FILE_HEADER. -+/// -+#define EFI_IMAGE_SIZEOF_FILE_HEADER 20 -+ -+// -+// Characteristics -+// -+#define EFI_IMAGE_FILE_RELOCS_STRIPPED (1 << 0) ///< 0x0001 Relocation info stripped from file. -+#define EFI_IMAGE_FILE_EXECUTABLE_IMAGE (1 << 1) ///< 0x0002 File is executable (i.e. no unresolved externel references). -+#define EFI_IMAGE_FILE_LINE_NUMS_STRIPPED (1 << 2) ///< 0x0004 Line nunbers stripped from file. -+#define EFI_IMAGE_FILE_LOCAL_SYMS_STRIPPED (1 << 3) ///< 0x0008 Local symbols stripped from file. -+#define EFI_IMAGE_FILE_BYTES_REVERSED_LO (1 << 7) ///< 0x0080 Bytes of machine word are reversed. -+#define EFI_IMAGE_FILE_32BIT_MACHINE (1 << 8) ///< 0x0100 32 bit word machine. -+#define EFI_IMAGE_FILE_DEBUG_STRIPPED (1 << 9) ///< 0x0200 Debugging info stripped from file in .DBG file. -+#define EFI_IMAGE_FILE_SYSTEM (1 << 12) ///< 0x1000 System File. -+#define EFI_IMAGE_FILE_DLL (1 << 13) ///< 0x2000 File is a DLL. -+#define EFI_IMAGE_FILE_BYTES_REVERSED_HI (1 << 15) ///< 0x8000 Bytes of machine word are reversed. -+ -+/// -+/// Header Data Directories. -+/// -+typedef struct { -+ UINT32 VirtualAddress; -+ UINT32 Size; -+} EFI_IMAGE_DATA_DIRECTORY; -+ -+// -+// Directory Entries -+// -+#define EFI_IMAGE_DIRECTORY_ENTRY_EXPORT 0 -+#define EFI_IMAGE_DIRECTORY_ENTRY_IMPORT 1 -+#define EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE 2 -+#define EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION 3 -+#define EFI_IMAGE_DIRECTORY_ENTRY_SECURITY 4 -+#define EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC 5 -+#define EFI_IMAGE_DIRECTORY_ENTRY_DEBUG 6 -+#define EFI_IMAGE_DIRECTORY_ENTRY_COPYRIGHT 7 -+#define EFI_IMAGE_DIRECTORY_ENTRY_GLOBALPTR 8 -+#define EFI_IMAGE_DIRECTORY_ENTRY_TLS 9 -+#define EFI_IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG 10 -+ -+#define EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES 16 -+ -+/// -+/// @attention -+/// EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC means PE32 and -+/// EFI_IMAGE_OPTIONAL_HEADER32 must be used. The data structures only vary -+/// after NT additional fields. -+/// -+#define EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC 0x10b -+ -+/// -+/// Optional Header Standard Fields for PE32. -+/// -+typedef struct { -+ /// -+ /// Standard fields. -+ /// -+ UINT16 Magic; -+ UINT8 MajorLinkerVersion; -+ UINT8 MinorLinkerVersion; -+ UINT32 SizeOfCode; -+ UINT32 SizeOfInitializedData; -+ UINT32 SizeOfUninitializedData; -+ UINT32 AddressOfEntryPoint; -+ UINT32 BaseOfCode; -+ UINT32 BaseOfData; ///< PE32 contains this additional field, which is absent in PE32+. -+ /// -+ /// Optional Header Windows-Specific Fields. -+ /// -+ UINT32 ImageBase; -+ UINT32 SectionAlignment; -+ UINT32 FileAlignment; -+ UINT16 MajorOperatingSystemVersion; -+ UINT16 MinorOperatingSystemVersion; -+ UINT16 MajorImageVersion; -+ UINT16 MinorImageVersion; -+ UINT16 MajorSubsystemVersion; -+ UINT16 MinorSubsystemVersion; -+ UINT32 Win32VersionValue; -+ UINT32 SizeOfImage; -+ UINT32 SizeOfHeaders; -+ UINT32 CheckSum; -+ UINT16 Subsystem; -+ UINT16 DllCharacteristics; -+ UINT32 SizeOfStackReserve; -+ UINT32 SizeOfStackCommit; -+ UINT32 SizeOfHeapReserve; -+ UINT32 SizeOfHeapCommit; -+ UINT32 LoaderFlags; -+ UINT32 NumberOfRvaAndSizes; -+ EFI_IMAGE_DATA_DIRECTORY DataDirectory[EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES]; -+} EFI_IMAGE_OPTIONAL_HEADER32; -+ -+/// -+/// @attention -+/// EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC means PE32+ and -+/// EFI_IMAGE_OPTIONAL_HEADER64 must be used. The data structures only vary -+/// after NT additional fields. -+/// -+#define EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC 0x20b -+ -+/// -+/// Optional Header Standard Fields for PE32+. -+/// -+typedef struct { -+ /// -+ /// Standard fields. -+ /// -+ UINT16 Magic; -+ UINT8 MajorLinkerVersion; -+ UINT8 MinorLinkerVersion; -+ UINT32 SizeOfCode; -+ UINT32 SizeOfInitializedData; -+ UINT32 SizeOfUninitializedData; -+ UINT32 AddressOfEntryPoint; -+ UINT32 BaseOfCode; -+ /// -+ /// Optional Header Windows-Specific Fields. -+ /// -+ UINT64 ImageBase; -+ UINT32 SectionAlignment; -+ UINT32 FileAlignment; -+ UINT16 MajorOperatingSystemVersion; -+ UINT16 MinorOperatingSystemVersion; -+ UINT16 MajorImageVersion; -+ UINT16 MinorImageVersion; -+ UINT16 MajorSubsystemVersion; -+ UINT16 MinorSubsystemVersion; -+ UINT32 Win32VersionValue; -+ UINT32 SizeOfImage; -+ UINT32 SizeOfHeaders; -+ UINT32 CheckSum; -+ UINT16 Subsystem; -+ UINT16 DllCharacteristics; -+ UINT64 SizeOfStackReserve; -+ UINT64 SizeOfStackCommit; -+ UINT64 SizeOfHeapReserve; -+ UINT64 SizeOfHeapCommit; -+ UINT32 LoaderFlags; -+ UINT32 NumberOfRvaAndSizes; -+ EFI_IMAGE_DATA_DIRECTORY DataDirectory[EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES]; -+} EFI_IMAGE_OPTIONAL_HEADER64; -+ -+ -+/// -+/// @attention -+/// EFI_IMAGE_NT_HEADERS32 is for use ONLY by tools. -+/// -+typedef struct { -+ UINT32 Signature; -+ EFI_IMAGE_FILE_HEADER FileHeader; -+ EFI_IMAGE_OPTIONAL_HEADER32 OptionalHeader; -+} EFI_IMAGE_NT_HEADERS32; -+ -+#define EFI_IMAGE_SIZEOF_NT_OPTIONAL32_HEADER sizeof (EFI_IMAGE_NT_HEADERS32) -+ -+/// -+/// @attention -+/// EFI_IMAGE_HEADERS64 is for use ONLY by tools. -+/// -+typedef struct { -+ UINT32 Signature; -+ EFI_IMAGE_FILE_HEADER FileHeader; -+ EFI_IMAGE_OPTIONAL_HEADER64 OptionalHeader; -+} EFI_IMAGE_NT_HEADERS64; -+ -+#define EFI_IMAGE_SIZEOF_NT_OPTIONAL64_HEADER sizeof (EFI_IMAGE_NT_HEADERS64) -+ -+// -+// Other Windows Subsystem Values -+// -+#define EFI_IMAGE_SUBSYSTEM_UNKNOWN 0 -+#define EFI_IMAGE_SUBSYSTEM_NATIVE 1 -+#define EFI_IMAGE_SUBSYSTEM_WINDOWS_GUI 2 -+#define EFI_IMAGE_SUBSYSTEM_WINDOWS_CUI 3 -+#define EFI_IMAGE_SUBSYSTEM_OS2_CUI 5 -+#define EFI_IMAGE_SUBSYSTEM_POSIX_CUI 7 -+ -+/// -+/// Length of ShortName. -+/// -+#define EFI_IMAGE_SIZEOF_SHORT_NAME 8 -+ -+/// -+/// Section Table. This table immediately follows the optional header. -+/// -+typedef struct { -+ UINT8 Name[EFI_IMAGE_SIZEOF_SHORT_NAME]; -+ union { -+ UINT32 PhysicalAddress; -+ UINT32 VirtualSize; -+ } Misc; -+ UINT32 VirtualAddress; -+ UINT32 SizeOfRawData; -+ UINT32 PointerToRawData; -+ UINT32 PointerToRelocations; -+ UINT32 PointerToLinenumbers; -+ UINT16 NumberOfRelocations; -+ UINT16 NumberOfLinenumbers; -+ UINT32 Characteristics; -+} EFI_IMAGE_SECTION_HEADER; -+ -+/// -+/// Size of EFI_IMAGE_SECTION_HEADER. -+/// -+#define EFI_IMAGE_SIZEOF_SECTION_HEADER 40 -+ -+// -+// Section Flags Values -+// -+#define EFI_IMAGE_SCN_TYPE_NO_PAD BIT3 ///< 0x00000008 ///< Reserved. -+#define EFI_IMAGE_SCN_CNT_CODE BIT5 ///< 0x00000020 -+#define EFI_IMAGE_SCN_CNT_INITIALIZED_DATA BIT6 ///< 0x00000040 -+#define EFI_IMAGE_SCN_CNT_UNINITIALIZED_DATA BIT7 ///< 0x00000080 -+ -+#define EFI_IMAGE_SCN_LNK_OTHER BIT8 ///< 0x00000100 ///< Reserved. -+#define EFI_IMAGE_SCN_LNK_INFO BIT9 ///< 0x00000200 ///< Section contains comments or some other type of information. -+#define EFI_IMAGE_SCN_LNK_REMOVE BIT11 ///< 0x00000800 ///< Section contents will not become part of image. -+#define EFI_IMAGE_SCN_LNK_COMDAT BIT12 ///< 0x00001000 -+ -+#define EFI_IMAGE_SCN_ALIGN_1BYTES BIT20 ///< 0x00100000 -+#define EFI_IMAGE_SCN_ALIGN_2BYTES BIT21 ///< 0x00200000 -+#define EFI_IMAGE_SCN_ALIGN_4BYTES (BIT20|BIT21) ///< 0x00300000 -+#define EFI_IMAGE_SCN_ALIGN_8BYTES BIT22 ///< 0x00400000 -+#define EFI_IMAGE_SCN_ALIGN_16BYTES (BIT20|BIT22) ///< 0x00500000 -+#define EFI_IMAGE_SCN_ALIGN_32BYTES (BIT21|BIT22) ///< 0x00600000 -+#define EFI_IMAGE_SCN_ALIGN_64BYTES (BIT20|BIT21|BIT22) ///< 0x00700000 -+ -+#define EFI_IMAGE_SCN_MEM_DISCARDABLE BIT25 ///< 0x02000000 -+#define EFI_IMAGE_SCN_MEM_NOT_CACHED BIT26 ///< 0x04000000 -+#define EFI_IMAGE_SCN_MEM_NOT_PAGED BIT27 ///< 0x08000000 -+#define EFI_IMAGE_SCN_MEM_SHARED BIT28 ///< 0x10000000 -+#define EFI_IMAGE_SCN_MEM_EXECUTE BIT29 ///< 0x20000000 -+#define EFI_IMAGE_SCN_MEM_READ BIT30 ///< 0x40000000 -+#define EFI_IMAGE_SCN_MEM_WRITE BIT31 ///< 0x80000000 -+ -+/// -+/// Size of a Symbol Table Record. -+/// -+#define EFI_IMAGE_SIZEOF_SYMBOL 18 -+ -+// -+// Symbols have a section number of the section in which they are -+// defined. Otherwise, section numbers have the following meanings: -+// -+#define EFI_IMAGE_SYM_UNDEFINED (UINT16) 0 ///< Symbol is undefined or is common. -+#define EFI_IMAGE_SYM_ABSOLUTE (UINT16) -1 ///< Symbol is an absolute value. -+#define EFI_IMAGE_SYM_DEBUG (UINT16) -2 ///< Symbol is a special debug item. -+ -+// -+// Symbol Type (fundamental) values. -+// -+#define EFI_IMAGE_SYM_TYPE_NULL 0 ///< no type. -+#define EFI_IMAGE_SYM_TYPE_VOID 1 ///< no valid type. -+#define EFI_IMAGE_SYM_TYPE_CHAR 2 ///< type character. -+#define EFI_IMAGE_SYM_TYPE_SHORT 3 ///< type short integer. -+#define EFI_IMAGE_SYM_TYPE_INT 4 -+#define EFI_IMAGE_SYM_TYPE_LONG 5 -+#define EFI_IMAGE_SYM_TYPE_FLOAT 6 -+#define EFI_IMAGE_SYM_TYPE_DOUBLE 7 -+#define EFI_IMAGE_SYM_TYPE_STRUCT 8 -+#define EFI_IMAGE_SYM_TYPE_UNION 9 -+#define EFI_IMAGE_SYM_TYPE_ENUM 10 ///< enumeration. -+#define EFI_IMAGE_SYM_TYPE_MOE 11 ///< member of enumeration. -+#define EFI_IMAGE_SYM_TYPE_BYTE 12 -+#define EFI_IMAGE_SYM_TYPE_WORD 13 -+#define EFI_IMAGE_SYM_TYPE_UINT 14 -+#define EFI_IMAGE_SYM_TYPE_DWORD 15 -+ -+// -+// Symbol Type (derived) values. -+// -+#define EFI_IMAGE_SYM_DTYPE_NULL 0 ///< no derived type. -+#define EFI_IMAGE_SYM_DTYPE_POINTER 1 -+#define EFI_IMAGE_SYM_DTYPE_FUNCTION 2 -+#define EFI_IMAGE_SYM_DTYPE_ARRAY 3 -+ -+// -+// Storage classes. -+// -+#define EFI_IMAGE_SYM_CLASS_END_OF_FUNCTION ((UINT8) -1) -+#define EFI_IMAGE_SYM_CLASS_NULL 0 -+#define EFI_IMAGE_SYM_CLASS_AUTOMATIC 1 -+#define EFI_IMAGE_SYM_CLASS_EXTERNAL 2 -+#define EFI_IMAGE_SYM_CLASS_STATIC 3 -+#define EFI_IMAGE_SYM_CLASS_REGISTER 4 -+#define EFI_IMAGE_SYM_CLASS_EXTERNAL_DEF 5 -+#define EFI_IMAGE_SYM_CLASS_LABEL 6 -+#define EFI_IMAGE_SYM_CLASS_UNDEFINED_LABEL 7 -+#define EFI_IMAGE_SYM_CLASS_MEMBER_OF_STRUCT 8 -+#define EFI_IMAGE_SYM_CLASS_ARGUMENT 9 -+#define EFI_IMAGE_SYM_CLASS_STRUCT_TAG 10 -+#define EFI_IMAGE_SYM_CLASS_MEMBER_OF_UNION 11 -+#define EFI_IMAGE_SYM_CLASS_UNION_TAG 12 -+#define EFI_IMAGE_SYM_CLASS_TYPE_DEFINITION 13 -+#define EFI_IMAGE_SYM_CLASS_UNDEFINED_STATIC 14 -+#define EFI_IMAGE_SYM_CLASS_ENUM_TAG 15 -+#define EFI_IMAGE_SYM_CLASS_MEMBER_OF_ENUM 16 -+#define EFI_IMAGE_SYM_CLASS_REGISTER_PARAM 17 -+#define EFI_IMAGE_SYM_CLASS_BIT_FIELD 18 -+#define EFI_IMAGE_SYM_CLASS_BLOCK 100 -+#define EFI_IMAGE_SYM_CLASS_FUNCTION 101 -+#define EFI_IMAGE_SYM_CLASS_END_OF_STRUCT 102 -+#define EFI_IMAGE_SYM_CLASS_FILE 103 -+#define EFI_IMAGE_SYM_CLASS_SECTION 104 -+#define EFI_IMAGE_SYM_CLASS_WEAK_EXTERNAL 105 -+ -+// -+// type packing constants -+// -+#define EFI_IMAGE_N_BTMASK 017 -+#define EFI_IMAGE_N_TMASK 060 -+#define EFI_IMAGE_N_TMASK1 0300 -+#define EFI_IMAGE_N_TMASK2 0360 -+#define EFI_IMAGE_N_BTSHFT 4 -+#define EFI_IMAGE_N_TSHIFT 2 -+ -+// -+// Communal selection types. -+// -+#define EFI_IMAGE_COMDAT_SELECT_NODUPLICATES 1 -+#define EFI_IMAGE_COMDAT_SELECT_ANY 2 -+#define EFI_IMAGE_COMDAT_SELECT_SAME_SIZE 3 -+#define EFI_IMAGE_COMDAT_SELECT_EXACT_MATCH 4 -+#define EFI_IMAGE_COMDAT_SELECT_ASSOCIATIVE 5 -+ -+// -+// the following values only be referred in PeCoff, not defined in PECOFF. -+// -+#define EFI_IMAGE_WEAK_EXTERN_SEARCH_NOLIBRARY 1 -+#define EFI_IMAGE_WEAK_EXTERN_SEARCH_LIBRARY 2 -+#define EFI_IMAGE_WEAK_EXTERN_SEARCH_ALIAS 3 -+ -+/// -+/// Relocation format. -+/// -+typedef struct { -+ UINT32 VirtualAddress; -+ UINT32 SymbolTableIndex; -+ UINT16 Type; -+} EFI_IMAGE_RELOCATION; -+ -+/// -+/// Size of EFI_IMAGE_RELOCATION -+/// -+#define EFI_IMAGE_SIZEOF_RELOCATION 10 -+ -+// -+// I386 relocation types. -+// -+#define EFI_IMAGE_REL_I386_ABSOLUTE 0x0000 ///< Reference is absolute, no relocation is necessary. -+#define EFI_IMAGE_REL_I386_DIR16 0x0001 ///< Direct 16-bit reference to the symbols virtual address. -+#define EFI_IMAGE_REL_I386_REL16 0x0002 ///< PC-relative 16-bit reference to the symbols virtual address. -+#define EFI_IMAGE_REL_I386_DIR32 0x0006 ///< Direct 32-bit reference to the symbols virtual address. -+#define EFI_IMAGE_REL_I386_DIR32NB 0x0007 ///< Direct 32-bit reference to the symbols virtual address, base not included. -+#define EFI_IMAGE_REL_I386_SEG12 0x0009 ///< Direct 16-bit reference to the segment-selector bits of a 32-bit virtual address. -+#define EFI_IMAGE_REL_I386_SECTION 0x000A -+#define EFI_IMAGE_REL_I386_SECREL 0x000B -+#define EFI_IMAGE_REL_I386_REL32 0x0014 ///< PC-relative 32-bit reference to the symbols virtual address. -+ -+// -+// x64 processor relocation types. -+// -+#define IMAGE_REL_AMD64_ABSOLUTE 0x0000 -+#define IMAGE_REL_AMD64_ADDR64 0x0001 -+#define IMAGE_REL_AMD64_ADDR32 0x0002 -+#define IMAGE_REL_AMD64_ADDR32NB 0x0003 -+#define IMAGE_REL_AMD64_REL32 0x0004 -+#define IMAGE_REL_AMD64_REL32_1 0x0005 -+#define IMAGE_REL_AMD64_REL32_2 0x0006 -+#define IMAGE_REL_AMD64_REL32_3 0x0007 -+#define IMAGE_REL_AMD64_REL32_4 0x0008 -+#define IMAGE_REL_AMD64_REL32_5 0x0009 -+#define IMAGE_REL_AMD64_SECTION 0x000A -+#define IMAGE_REL_AMD64_SECREL 0x000B -+#define IMAGE_REL_AMD64_SECREL7 0x000C -+#define IMAGE_REL_AMD64_TOKEN 0x000D -+#define IMAGE_REL_AMD64_SREL32 0x000E -+#define IMAGE_REL_AMD64_PAIR 0x000F -+#define IMAGE_REL_AMD64_SSPAN32 0x0010 -+ -+/// -+/// Based relocation format. -+/// -+typedef struct { -+ UINT32 VirtualAddress; -+ UINT32 SizeOfBlock; -+} EFI_IMAGE_BASE_RELOCATION; -+ -+/// -+/// Size of EFI_IMAGE_BASE_RELOCATION. -+/// -+#define EFI_IMAGE_SIZEOF_BASE_RELOCATION 8 -+ -+// -+// Based relocation types. -+// -+#define EFI_IMAGE_REL_BASED_ABSOLUTE 0 -+#define EFI_IMAGE_REL_BASED_HIGH 1 -+#define EFI_IMAGE_REL_BASED_LOW 2 -+#define EFI_IMAGE_REL_BASED_HIGHLOW 3 -+#define EFI_IMAGE_REL_BASED_HIGHADJ 4 -+#define EFI_IMAGE_REL_BASED_MIPS_JMPADDR 5 -+#define EFI_IMAGE_REL_BASED_ARM_MOV32A 5 -+#define EFI_IMAGE_REL_BASED_ARM_MOV32T 7 -+#define EFI_IMAGE_REL_BASED_IA64_IMM64 9 -+#define EFI_IMAGE_REL_BASED_MIPS_JMPADDR16 9 -+#define EFI_IMAGE_REL_BASED_DIR64 10 -+ -+/// -+/// Line number format. -+/// -+typedef struct { -+ union { -+ UINT32 SymbolTableIndex; ///< Symbol table index of function name if Linenumber is 0. -+ UINT32 VirtualAddress; ///< Virtual address of line number. -+ } Type; -+ UINT16 Linenumber; ///< Line number. -+} EFI_IMAGE_LINENUMBER; -+ -+/// -+/// Size of EFI_IMAGE_LINENUMBER. -+/// -+#define EFI_IMAGE_SIZEOF_LINENUMBER 6 -+ -+// -+// Archive format. -+// -+#define EFI_IMAGE_ARCHIVE_START_SIZE 8 -+#define EFI_IMAGE_ARCHIVE_START "!\n" -+#define EFI_IMAGE_ARCHIVE_END "`\n" -+#define EFI_IMAGE_ARCHIVE_PAD "\n" -+#define EFI_IMAGE_ARCHIVE_LINKER_MEMBER "/ " -+#define EFI_IMAGE_ARCHIVE_LONGNAMES_MEMBER "// " -+ -+/// -+/// Archive Member Headers -+/// -+typedef struct { -+ UINT8 Name[16]; ///< File member name - `/' terminated. -+ UINT8 Date[12]; ///< File member date - decimal. -+ UINT8 UserID[6]; ///< File member user id - decimal. -+ UINT8 GroupID[6]; ///< File member group id - decimal. -+ UINT8 Mode[8]; ///< File member mode - octal. -+ UINT8 Size[10]; ///< File member size - decimal. -+ UINT8 EndHeader[2]; ///< String to end header. (0x60 0x0A). -+} EFI_IMAGE_ARCHIVE_MEMBER_HEADER; -+ -+/// -+/// Size of EFI_IMAGE_ARCHIVE_MEMBER_HEADER. -+/// -+#define EFI_IMAGE_SIZEOF_ARCHIVE_MEMBER_HDR 60 -+ -+ -+// -+// DLL Support -+// -+ -+/// -+/// Export Directory Table. -+/// -+typedef struct { -+ UINT32 Characteristics; -+ UINT32 TimeDateStamp; -+ UINT16 MajorVersion; -+ UINT16 MinorVersion; -+ UINT32 Name; -+ UINT32 Base; -+ UINT32 NumberOfFunctions; -+ UINT32 NumberOfNames; -+ UINT32 AddressOfFunctions; -+ UINT32 AddressOfNames; -+ UINT32 AddressOfNameOrdinals; -+} EFI_IMAGE_EXPORT_DIRECTORY; -+ -+/// -+/// Hint/Name Table. -+/// -+typedef struct { -+ UINT16 Hint; -+ UINT8 Name[1]; -+} EFI_IMAGE_IMPORT_BY_NAME; -+ -+/// -+/// Import Address Table RVA (Thunk Table). -+/// -+typedef struct { -+ union { -+ UINT32 Function; -+ UINT32 Ordinal; -+ EFI_IMAGE_IMPORT_BY_NAME *AddressOfData; -+ } u1; -+} EFI_IMAGE_THUNK_DATA; -+ -+#define EFI_IMAGE_ORDINAL_FLAG BIT31 ///< Flag for PE32. -+#define EFI_IMAGE_SNAP_BY_ORDINAL(Ordinal) ((Ordinal & EFI_IMAGE_ORDINAL_FLAG) != 0) -+#define EFI_IMAGE_ORDINAL(Ordinal) (Ordinal & 0xffff) -+ -+/// -+/// Import Directory Table -+/// -+typedef struct { -+ UINT32 Characteristics; -+ UINT32 TimeDateStamp; -+ UINT32 ForwarderChain; -+ UINT32 Name; -+ EFI_IMAGE_THUNK_DATA *FirstThunk; -+} EFI_IMAGE_IMPORT_DESCRIPTOR; -+ -+ -+/// -+/// Debug Directory Format. -+/// -+typedef struct { -+ UINT32 Characteristics; -+ UINT32 TimeDateStamp; -+ UINT16 MajorVersion; -+ UINT16 MinorVersion; -+ UINT32 Type; -+ UINT32 SizeOfData; -+ UINT32 RVA; ///< The address of the debug data when loaded, relative to the image base. -+ UINT32 FileOffset; ///< The file pointer to the debug data. -+} EFI_IMAGE_DEBUG_DIRECTORY_ENTRY; -+ -+#define EFI_IMAGE_DEBUG_TYPE_CODEVIEW 2 ///< The Visual C++ debug information. -+ -+/// -+/// Debug Data Structure defined in Microsoft C++. -+/// -+#define CODEVIEW_SIGNATURE_NB10 SIGNATURE_32('N', 'B', '1', '0') -+typedef struct { -+ UINT32 Signature; ///< "NB10" -+ UINT32 Unknown; -+ UINT32 Unknown2; -+ UINT32 Unknown3; -+ // -+ // Filename of .PDB goes here -+ // -+} EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY; -+ -+/// -+/// Debug Data Structure defined in Microsoft C++. -+/// -+#define CODEVIEW_SIGNATURE_RSDS SIGNATURE_32('R', 'S', 'D', 'S') -+typedef struct { -+ UINT32 Signature; ///< "RSDS". -+ UINT32 Unknown; -+ UINT32 Unknown2; -+ UINT32 Unknown3; -+ UINT32 Unknown4; -+ UINT32 Unknown5; -+ // -+ // Filename of .PDB goes here -+ // -+} EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY; -+ -+ -+/// -+/// Debug Data Structure defined by Apple Mach-O to Coff utility. -+/// -+#define CODEVIEW_SIGNATURE_MTOC SIGNATURE_32('M', 'T', 'O', 'C') -+typedef struct { -+ UINT32 Signature; ///< "MTOC". -+ EFI_GUID MachOUuid; -+ // -+ // Filename of .DLL (Mach-O with debug info) goes here -+ // -+} EFI_IMAGE_DEBUG_CODEVIEW_MTOC_ENTRY; -+ -+/// -+/// Resource format. -+/// -+typedef struct { -+ UINT32 Characteristics; -+ UINT32 TimeDateStamp; -+ UINT16 MajorVersion; -+ UINT16 MinorVersion; -+ UINT16 NumberOfNamedEntries; -+ UINT16 NumberOfIdEntries; -+ // -+ // Array of EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY entries goes here. -+ // -+} EFI_IMAGE_RESOURCE_DIRECTORY; -+ -+/// -+/// Resource directory entry format. -+/// -+typedef struct { -+ union { -+ struct { -+ UINT32 NameOffset:31; -+ UINT32 NameIsString:1; -+ } s; -+ UINT32 Id; -+ } u1; -+ union { -+ UINT32 OffsetToData; -+ struct { -+ UINT32 OffsetToDirectory:31; -+ UINT32 DataIsDirectory:1; -+ } s; -+ } u2; -+} EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY; -+ -+/// -+/// Resource directory entry for string. -+/// -+typedef struct { -+ UINT16 Length; -+ CHAR16 String[1]; -+} EFI_IMAGE_RESOURCE_DIRECTORY_STRING; -+ -+/// -+/// Resource directory entry for data array. -+/// -+typedef struct { -+ UINT32 OffsetToData; -+ UINT32 Size; -+ UINT32 CodePage; -+ UINT32 Reserved; -+} EFI_IMAGE_RESOURCE_DATA_ENTRY; -+ -+/// -+/// Header format for TE images, defined in the PI Specification, 1.0. -+/// -+typedef struct { -+ UINT16 Signature; ///< The signature for TE format = "VZ". -+ UINT16 Machine; ///< From the original file header. -+ UINT8 NumberOfSections; ///< From the original file header. -+ UINT8 Subsystem; ///< From original optional header. -+ UINT16 StrippedSize; ///< Number of bytes we removed from the header. -+ UINT32 AddressOfEntryPoint; ///< Offset to entry point -- from original optional header. -+ UINT32 BaseOfCode; ///< From original image -- required for ITP debug. -+ UINT64 ImageBase; ///< From original file header. -+ EFI_IMAGE_DATA_DIRECTORY DataDirectory[2]; ///< Only base relocation and debug directory. -+} EFI_TE_IMAGE_HEADER; -+ -+ -+#define EFI_TE_IMAGE_HEADER_SIGNATURE SIGNATURE_16('V', 'Z') -+ -+// -+// Data directory indexes in our TE image header -+// -+#define EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC 0 -+#define EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG 1 -+ -+ -+/// -+/// Union of PE32, PE32+, and TE headers. -+/// -+typedef union { -+ EFI_IMAGE_NT_HEADERS32 Pe32; -+ EFI_IMAGE_NT_HEADERS64 Pe32Plus; -+ EFI_TE_IMAGE_HEADER Te; -+} EFI_IMAGE_OPTIONAL_HEADER_UNION; -+ -+typedef union { -+ EFI_IMAGE_NT_HEADERS32 *Pe32; -+ EFI_IMAGE_NT_HEADERS64 *Pe32Plus; -+ EFI_TE_IMAGE_HEADER *Te; -+ EFI_IMAGE_OPTIONAL_HEADER_UNION *Union; -+} EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION; -+ -+typedef struct { -+ WIN_CERTIFICATE Hdr; -+ UINT8 CertData[1]; -+} WIN_CERTIFICATE_EFI_PKCS; -+ -+#define SHA256_DIGEST_SIZE 32 -+#define WIN_CERT_TYPE_PKCS_SIGNED_DATA 0x0002 -+ -+typedef struct { -+ UINT64 ImageAddress; -+ UINT64 ImageSize; -+ UINT64 EntryPoint; -+ UINTN SizeOfHeaders; -+ UINT16 ImageType; -+ UINT16 NumberOfSections; -+ EFI_IMAGE_SECTION_HEADER *FirstSection; -+ EFI_IMAGE_DATA_DIRECTORY *RelocDir; -+ EFI_IMAGE_DATA_DIRECTORY *SecDir; -+ UINT64 NumberOfRvaAndSizes; -+ EFI_IMAGE_OPTIONAL_HEADER_UNION *PEHdr; -+} PE_COFF_LOADER_IMAGE_CONTEXT; -+ -+#endif -diff --git a/include/configtable.h b/include/configtable.h -new file mode 100644 -index 0000000..fa2b505 ---- /dev/null -+++ b/include/configtable.h -@@ -0,0 +1,68 @@ -+/* definitions straight from TianoCore */ -+ -+typedef UINT32 EFI_IMAGE_EXECUTION_ACTION; -+ -+#define EFI_IMAGE_EXECUTION_AUTHENTICATION 0x00000007 -+#define EFI_IMAGE_EXECUTION_AUTH_UNTESTED 0x00000000 -+#define EFI_IMAGE_EXECUTION_AUTH_SIG_FAILED 0x00000001 -+#define EFI_IMAGE_EXECUTION_AUTH_SIG_PASSED 0x00000002 -+#define EFI_IMAGE_EXECUTION_AUTH_SIG_NOT_FOUND 0x00000003 -+#define EFI_IMAGE_EXECUTION_AUTH_SIG_FOUND 0x00000004 -+#define EFI_IMAGE_EXECUTION_POLICY_FAILED 0x00000005 -+#define EFI_IMAGE_EXECUTION_INITIALIZED 0x00000008 -+ -+typedef struct { -+ /// -+ /// Describes the action taken by the firmware regarding this image. -+ /// -+ EFI_IMAGE_EXECUTION_ACTION Action; -+ /// -+ /// Size of all of the entire structure. -+ /// -+ UINT32 InfoSize; -+ /// -+ /// If this image was a UEFI device driver (for option ROM, for example) this is the -+ /// null-terminated, user-friendly name for the device. If the image was for an application, -+ /// then this is the name of the application. If this cannot be determined, then a simple -+ /// NULL character should be put in this position. -+ /// CHAR16 Name[]; -+ /// -+ -+ /// -+ /// For device drivers, this is the device path of the device for which this device driver -+ /// was intended. In some cases, the driver itself may be stored as part of the system -+ /// firmware, but this field should record the device's path, not the firmware path. For -+ /// applications, this is the device path of the application. If this cannot be determined, -+ /// a simple end-of-path device node should be put in this position. -+ /// EFI_DEVICE_PATH_PROTOCOL DevicePath; -+ /// -+ -+ /// -+ /// Zero or more image signatures. If the image contained no signatures, -+ /// then this field is empty. -+ /// -+ ///EFI_SIGNATURE_LIST Signature; -+ UINT8 Data[]; -+} EFI_IMAGE_EXECUTION_INFO; -+ -+typedef struct { -+ /// -+ /// Number of EFI_IMAGE_EXECUTION_INFO structures. -+ /// -+ UINTN NumberOfImages; -+ /// -+ /// Number of image instances of EFI_IMAGE_EXECUTION_INFO structures. -+ /// -+ EFI_IMAGE_EXECUTION_INFO InformationInfo[]; -+} EFI_IMAGE_EXECUTION_INFO_TABLE; -+ -+ -+void * -+configtable_get_table(EFI_GUID *guid); -+EFI_IMAGE_EXECUTION_INFO_TABLE * -+configtable_get_image_table(void); -+EFI_IMAGE_EXECUTION_INFO * -+configtable_find_image(const EFI_DEVICE_PATH *DevicePath); -+int -+configtable_image_is_forbidden(const EFI_DEVICE_PATH *DevicePath); -+ -diff --git a/include/console.h b/include/console.h -new file mode 100644 -index 0000000..7eb8a0b ---- /dev/null -+++ b/include/console.h -@@ -0,0 +1,21 @@ -+EFI_INPUT_KEY -+console_get_keystroke(void); -+void -+console_print_box_at(CHAR16 *str_arr[], int highlight, int start_col, int start_row, int size_cols, int size_rows, int offset, int lines); -+void -+console_print_box(CHAR16 *str_arr[], int highlight); -+int -+console_yes_no(CHAR16 *str_arr[]); -+int -+console_select(CHAR16 *title[], CHAR16* selectors[], int start); -+void -+console_errorbox(CHAR16 *err); -+void -+console_error(CHAR16 *err, EFI_STATUS); -+void -+console_alertbox(CHAR16 **title); -+void -+console_notify(CHAR16 *string); -+void -+console_reset(void); -+#define NOSEL 0x7fffffff -diff --git a/include/efiauthenticated.h b/include/efiauthenticated.h -new file mode 100644 -index 0000000..f7d6bcb ---- /dev/null -+++ b/include/efiauthenticated.h -@@ -0,0 +1,222 @@ -+#ifndef _INC_EFIAUTHENTICATED_H -+#define _INC_EFIAUTHENTICATED_H -+#include -+//*********************************************************************** -+// 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]; -+} 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]; -+ /// -+} EFI_SIGNATURE_LIST; -+ -+#pragma pack() -+ -+// -+// _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 -+/// -+typedef struct { -+ EFI_GUID HashType; -+ UINT8 PublicKey[256]; -+ UINT8 Signature[256]; -+} EFI_CERT_BLOCK_RSA_2048_SHA256; -+ -+ -+/// -+/// 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]; -+} 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[]; -+ /// -+} WIN_CERTIFICATE_EFI_PKCS1_15; -+ -+#define OFFSET_OF(TYPE, Field) ((UINTN) &(((TYPE *)0)->Field)) -+ -+/// -+/// 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. -+/// -+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; -+} 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(). -+/// -+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; -+ -+/// -+/// Size of AuthInfo prior to the data payload. -+/// -+#define AUTHINFO_SIZE ((OFFSET_OF (EFI_VARIABLE_AUTHENTICATION, AuthInfo)) + \ -+ (OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID, CertData)) + \ -+ sizeof (EFI_CERT_BLOCK_RSA_2048_SHA256)) -+ -+#define AUTHINFO2_SIZE(VarAuth2) ((OFFSET_OF (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))) -+ -+#endif -diff --git a/include/errors.h b/include/errors.h -new file mode 100644 -index 0000000..0da4bb5 ---- /dev/null -+++ b/include/errors.h -@@ -0,0 +1,9 @@ -+#include -+ -+#ifndef EFI_INCOMPATIBLE_VERSION -+#define EFI_INCOMPATIBLE_VERSION EFIERR(25) -+#endif -+#ifndef EFI_SECURITY_VIOLATION -+#define EFI_SECURITY_VIOLATION EFIERR(26) -+#endif -+ -diff --git a/include/execute.h b/include/execute.h -new file mode 100644 -index 0000000..9aecbff ---- /dev/null -+++ b/include/execute.h -@@ -0,0 +1,5 @@ -+EFI_STATUS -+generate_path(CHAR16* name, EFI_LOADED_IMAGE *li, -+ EFI_DEVICE_PATH **path, CHAR16 **PathName); -+EFI_STATUS -+execute(EFI_HANDLE image, CHAR16 *name); -diff --git a/include/guid.h b/include/guid.h -new file mode 100644 -index 0000000..10f865a ---- /dev/null -+++ b/include/guid.h -@@ -0,0 +1,18 @@ -+#include -+ -+#ifndef BUILD_EFI -+const char *guid_to_str(EFI_GUID *guid); -+void str_to_guid(const char *str, EFI_GUID *guid); -+#endif -+ -+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_CERT_SHA256_GUID; -+extern EFI_GUID MOK_OWNER; -+extern EFI_GUID SECURITY_PROTOCOL_GUID; -+extern EFI_GUID SECURITY2_PROTOCOL_GUID; -diff --git a/include/security_policy.h b/include/security_policy.h -new file mode 100644 -index 0000000..a1c1002 ---- /dev/null -+++ b/include/security_policy.h -@@ -0,0 +1,6 @@ -+EFI_STATUS -+security_policy_install(void); -+EFI_STATUS -+security_policy_uninstall(void); -+void -+security_protocol_set_hashes(unsigned char *esl, int len); -diff --git a/include/shell.h b/include/shell.h -new file mode 100644 -index 0000000..9cb5d47 ---- /dev/null -+++ b/include/shell.h -@@ -0,0 +1,2 @@ -+EFI_STATUS -+argsplit(EFI_HANDLE image, int *argc, CHAR16*** ARGV); -diff --git a/include/simple_file.h b/include/simple_file.h -new file mode 100644 -index 0000000..fe4fd97 ---- /dev/null -+++ b/include/simple_file.h -@@ -0,0 +1,21 @@ -+EFI_STATUS -+simple_file_open (EFI_HANDLE image, CHAR16 *name, EFI_FILE **file, UINT64 mode); -+EFI_STATUS -+simple_file_open_by_handle(EFI_HANDLE device, CHAR16 *name, EFI_FILE **file, UINT64 mode); -+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); -+EFI_STATUS -+simple_dir_filter(EFI_HANDLE image, CHAR16 *name, CHAR16 *filter, -+ CHAR16 ***result, int *count, EFI_FILE_INFO **entries); -+void -+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); -diff --git a/include/variables.h b/include/variables.h -new file mode 100644 -index 0000000..c171bd5 ---- /dev/null -+++ b/include/variables.h -@@ -0,0 +1,59 @@ -+#include -+ -+#include /* for SHA256_DIGEST_SIZE */ -+ -+#define certlist_for_each_certentry(cl, cl_init, s, s_init) \ -+ for (cl = (EFI_SIGNATURE_LIST *)(cl_init), s = (s_init); \ -+ s > 0 && s >= cl->SignatureListSize; \ -+ s -= cl->SignatureListSize, \ -+ cl = (EFI_SIGNATURE_LIST *) ((UINT8 *)cl + cl->SignatureListSize)) -+ -+/* -+ * Warning: this assumes (cl)->SignatureHeaderSize is zero. It is for all -+ * the signatures we process (X509, RSA2048, SHA256) -+ */ -+#define certentry_for_each_cert(c, cl) \ -+ for (c = (EFI_SIGNATURE_DATA *)((UINT8 *) (cl) + sizeof(EFI_SIGNATURE_LIST) + (cl)->SignatureHeaderSize); \ -+ (UINT8 *)c < ((UINT8 *)(cl)) + (cl)->SignatureListSize; \ -+ c = (EFI_SIGNATURE_DATA *)((UINT8 *)c + (cl)->SignatureSize)) -+ -+EFI_STATUS -+CreatePkX509SignatureList ( -+ IN UINT8 *X509Data, -+ IN UINTN X509DataSize, -+ IN EFI_GUID owner, -+ OUT EFI_SIGNATURE_LIST **PkCert -+ ); -+EFI_STATUS -+CreateTimeBasedPayload ( -+ IN OUT UINTN *DataSize, -+ IN OUT UINT8 **Data -+ ); -+EFI_STATUS -+SetSecureVariable(CHAR16 *var, UINT8 *Data, UINTN len, EFI_GUID owner, UINT32 options, int createtimebased); -+EFI_STATUS -+get_variable(CHAR16 *var, UINT8 **data, UINTN *len, EFI_GUID owner); -+EFI_STATUS -+get_variable_attr(CHAR16 *var, UINT8 **data, UINTN *len, EFI_GUID owner, -+ UINT32 *attributes); -+EFI_STATUS -+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); -+ -+#define EFI_OS_INDICATIONS_BOOT_TO_FW_UI 0x0000000000000001 -+ -+UINT64 -+GetOSIndications(void); -+EFI_STATUS -+SETOSIndicationsAndReboot(UINT64 indications); -+int -+variable_is_secureboot(void); -+int -+variable_is_setupmode(void); -+EFI_STATUS -+variable_enroll_hash(CHAR16 *var, EFI_GUID owner, -+ UINT8 hash[SHA256_DIGEST_SIZE]); -+EFI_STATUS -+variable_create_esl(void *cert, int cert_len, EFI_GUID *type, EFI_GUID *owner, -+ void **out, int *outlen); -diff --git a/include/version.h b/include/version.h -new file mode 100644 -index 0000000..09fd44a ---- /dev/null -+++ b/include/version.h -@@ -0,0 +1,8 @@ -+#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 -new file mode 100644 -index 0000000..68d1974 ---- /dev/null -+++ b/include/wincert.h -@@ -0,0 +1,33 @@ -+#ifndef _INC_WINCERT_H -+#define _INC_WINCERT_H -+ -+/// -+/// The WIN_CERTIFICATE structure is part of the PE/COFF specification. -+/// -+typedef struct { -+ /// -+ /// The length of the entire certificate, -+ /// including the length of the header, in bytes. -+ /// -+ UINT32 dwLength; -+ /// -+ /// The revision level of the WIN_CERTIFICATE -+ /// structure. The current revision level is 0x0200. -+ /// -+ UINT16 wRevision; -+ /// -+ /// The certificate type. See WIN_CERT_TYPE_xxx for the UEFI -+ /// certificate types. The UEFI specification reserves the range of -+ /// certificate type values from 0x0EF0 to 0x0EFF. -+ /// -+ UINT16 wCertificateType; -+ /// -+ /// The following is the actual certificate. The format of -+ /// the certificate depends on wCertificateType. -+ /// -+ /// UINT8 bCertificate[ANYSIZE_ARRAY]; -+ /// -+} WIN_CERTIFICATE; -+ -+ -+#endif -diff --git a/lib/Makefile b/lib/Makefile -new file mode 100644 -index 0000000..be5f354 ---- /dev/null -+++ b/lib/Makefile -@@ -0,0 +1,28 @@ -+TARGET = lib.a -+ -+LIBFILES = simple_file.o guid.o console.o execute.o configtable.o shell.o -+ -+ARCH = $(shell uname -m | sed s,i[3456789]86,ia32,) -+ -+EFI_INCLUDE = /usr/include/efi -+EFI_INCLUDES = -I$(EFI_INCLUDE) -I$(EFI_INCLUDE)/$(ARCH) -I$(EFI_INCLUDE)/protocol -I../include -+EFI_PATH = /usr/lib64/gnuefi -+ -+EFI_CRT_OBJS = $(EFI_PATH)/crt0-efi-$(ARCH).o -+EFI_LDS = $(EFI_PATH)/elf_$(ARCH)_efi.lds -+ -+CFLAGS = -ggdb -O0 -fno-stack-protector -fno-strict-aliasing -fpic \ -+ -fshort-wchar -Wall -mno-red-zone -DBUILD_EFI $(EFI_INCLUDES) -+ifeq ($(ARCH),x86_64) -+ CFLAGS += -DEFI_FUNCTION_WRAPPER -DGNU_EFI_USE_MS_ABI -+endif -+ -+lib.a: $(LIBFILES) -+ ar rcs lib.a $(LIBFILES) -+ -+all: $(TARGET) -+ -+clean: -+ rm -f lib.a -+ rm -f $(LIBFILES) -+ -diff --git a/lib/configtable.c b/lib/configtable.c -new file mode 100644 -index 0000000..735ce8f ---- /dev/null -+++ b/lib/configtable.c -@@ -0,0 +1,144 @@ -+/* -+ * Copyright 2013 -+ * -+ * see COPYING file -+ * -+ * read some platform configuration tables -+ */ -+#include -+#include -+ -+#include -+#include -+ -+void * -+configtable_get_table(EFI_GUID *guid) -+{ -+ int i; -+ -+ for (i = 0; i < ST->NumberOfTableEntries; i++) { -+ EFI_CONFIGURATION_TABLE *CT = &ST->ConfigurationTable[i]; -+ -+ if (CompareGuid(guid, &CT->VendorGuid) == 0) { -+ return CT->VendorTable; -+ } -+ } -+ return NULL; -+} -+ -+EFI_IMAGE_EXECUTION_INFO_TABLE * -+configtable_get_image_table(void) -+{ -+ return configtable_get_table(&SIG_DB); -+} -+ -+EFI_IMAGE_EXECUTION_INFO * -+configtable_find_image(const EFI_DEVICE_PATH *DevicePath) -+{ -+ EFI_IMAGE_EXECUTION_INFO_TABLE *t = configtable_get_image_table(); -+ -+ if (!t) -+ return NULL; -+ -+ int entries = t->NumberOfImages; -+ EFI_IMAGE_EXECUTION_INFO *e = t->InformationInfo; -+ -+ int i; -+ for (i = 0; i < entries; i++) { -+#ifdef DEBUG_CONFIG -+ Print(L"InfoSize = %d Action = %d\n", e->InfoSize, e->Action); -+ -+ /* print what we have for debugging */ -+ UINT8 *d = (UINT8 *)e; // + sizeof(UINT32)*2; -+ Print(L"Data: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", -+ d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]); -+ d += 16; -+ Print(L"Data: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", -+ d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]); -+ d += 16; -+ Print(L"Data: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", -+ d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]); -+ d += 16; -+ Print(L"Data: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", -+ d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]); -+ d += 16; -+ Print(L"Data: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", -+ d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]); -+ d += 16; -+ Print(L"Data: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", -+ d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]); -+#endif -+ CHAR16 *name = (CHAR16 *)(e->Data); -+ int skip = 0; -+ -+ /* There's a bug in a lot of EFI platforms and they forget to -+ * put the name here. The only real way of detecting it is to -+ * look for either a UC16 NULL or ASCII as UC16 */ -+ if (name[0] == '\0' || (e->Data[1] == 0 && e->Data[3] == 0)) { -+ skip = StrSize(name); -+#ifdef DEBUG_CONFIG -+ Print(L"FOUND NAME %s (%d)\n", name, skip); -+#endif -+ } -+ EFI_DEVICE_PATH *dp = (EFI_DEVICE_PATH *)(e->Data + skip), *dpn = dp; -+ if (dp->Type == 0 || dp->Type > 6 || dp->SubType == 0 -+ || (((dp->Length[1] << 8) + dp->Length[0]) > e->InfoSize)) { -+ /* Parse error, table corrupt, bail */ -+ Print(L"Image Execution Information table corrupt\n"); -+ break; -+ } -+ -+ UINTN Size; -+ DevicePathInstance(&dpn, &Size); -+#ifdef DEBUG_CONFIG -+ Print(L"Path: %s\n", DevicePathToStr(dp)); -+ Print(L"Device Path Size %d\n", Size); -+#endif -+ if (Size > e->InfoSize) { -+ /* parse error; the platform obviously has a -+ * corrupted image table; bail */ -+ Print(L"Image Execution Information table corrupt\n"); -+ break; -+ } -+ -+ if (CompareMem(dp, DevicePath, Size) == 0) { -+#ifdef DEBUG_CONFIG -+ Print(L"***FOUND\n"); -+ console_get_keystroke(); -+#endif -+ return e; -+ } -+ e = (EFI_IMAGE_EXECUTION_INFO *)((UINT8 *)e + e->InfoSize); -+ } -+ -+#ifdef DEBUG_CONFIG -+ Print(L"***NOT FOUND\n"); -+ console_get_keystroke(); -+#endif -+ -+ return NULL; -+} -+ -+int -+configtable_image_is_forbidden(const EFI_DEVICE_PATH *DevicePath) -+{ -+ EFI_IMAGE_EXECUTION_INFO *e = configtable_find_image(DevicePath); -+ -+ /* Image may not be in DB if it gets executed successfully If it is, -+ * and EFI_IMAGE_EXECUTION_INITIALIZED is not set, then the image -+ * isn't authenticated. If there's no signature, usually -+ * EFI_IMAGE_EXECUTION_AUTH_UNTESTED is set, if the hash is in dbx, -+ * EFI_IMAGE_EXECUTION_AUTH_SIG_FOUND is returned, and if the key is -+ * in dbx, EFI_IMAGE_EXECUTION_AUTH_SIG_FAILED is returned*/ -+ -+ if (e && (e->Action == EFI_IMAGE_EXECUTION_AUTH_SIG_FOUND -+ || e->Action == EFI_IMAGE_EXECUTION_AUTH_SIG_FAILED)) { -+ /* this means the images signing key is in dbx */ -+#ifdef DEBUG_CONFIG -+ Print(L"SIGNATURE IS IN DBX, FORBIDDING EXECUTION\n"); -+#endif -+ return 1; -+ } -+ -+ return 0; -+} -diff --git a/lib/console.c b/lib/console.c -new file mode 100644 -index 0000000..af01f03 ---- /dev/null -+++ b/lib/console.c -@@ -0,0 +1,402 @@ -+/* -+ * Copyright 2012 -+ * -+ * see COPYING file -+ */ -+#include -+#include -+ -+#include -+#include -+ -+static int min(int a, int b) -+{ -+ if (a < b) -+ return a; -+ return b; -+} -+ -+static int -+count_lines(CHAR16 *str_arr[]) -+{ -+ int i = 0; -+ -+ while (str_arr[i]) -+ i++; -+ return i; -+} -+ -+static void -+SetMem16(CHAR16 *dst, UINT32 n, CHAR16 c) -+{ -+ int i; -+ -+ for (i = 0; i < n/2; i++) { -+ dst[i] = c; -+ } -+} -+ -+EFI_INPUT_KEY -+console_get_keystroke(void) -+{ -+ EFI_INPUT_KEY key; -+ UINTN EventIndex; -+ -+ uefi_call_wrapper(BS->WaitForEvent, 3, 1, &ST->ConIn->WaitForKey, &EventIndex); -+ uefi_call_wrapper(ST->ConIn->ReadKeyStroke, 2, ST->ConIn, &key); -+ -+ return key; -+} -+ -+void -+console_print_box_at(CHAR16 *str_arr[], int highlight, int start_col, int start_row, int size_cols, int size_rows, int offset, int lines) -+{ -+ int i; -+ SIMPLE_TEXT_OUTPUT_INTERFACE *co = ST->ConOut; -+ UINTN rows, cols; -+ CHAR16 *Line; -+ -+ if (lines == 0) -+ return; -+ -+ uefi_call_wrapper(co->QueryMode, 4, co, co->Mode->Mode, &cols, &rows); -+ -+ /* last row on screen is unusable without scrolling, so ignore it */ -+ rows--; -+ -+ if (size_rows < 0) -+ size_rows = rows + size_rows + 1; -+ if (size_cols < 0) -+ size_cols = cols + size_cols + 1; -+ -+ if (start_col < 0) -+ start_col = (cols + start_col + 2)/2; -+ if (start_row < 0) -+ start_row = (rows + start_row + 2)/2; -+ if (start_col < 0) -+ start_col = 0; -+ if (start_row < 0) -+ start_row = 0; -+ -+ if (start_col > cols || start_row > rows) { -+ Print(L"Starting Position (%d,%d) is off screen\n", -+ start_col, start_row); -+ return; -+ } -+ if (size_cols + start_col > cols) -+ size_cols = cols - start_col; -+ if (size_rows + start_row > rows) -+ size_rows = rows - start_row; -+ -+ if (lines > size_rows - 2) -+ lines = size_rows - 2; -+ -+ Line = AllocatePool((size_cols+1)*sizeof(CHAR16)); -+ if (!Line) { -+ Print(L"Failed Allocation\n"); -+ return; -+ } -+ -+ SetMem16 (Line, size_cols * 2, BOXDRAW_HORIZONTAL); -+ -+ Line[0] = BOXDRAW_DOWN_RIGHT; -+ Line[size_cols - 1] = BOXDRAW_DOWN_LEFT; -+ Line[size_cols] = L'\0'; -+ uefi_call_wrapper(co->SetCursorPosition, 3, co, start_col, start_row); -+ uefi_call_wrapper(co->OutputString, 2, co, Line); -+ -+ int start; -+ if (offset == 0) -+ /* middle */ -+ start = (size_rows - lines)/2 + start_row + offset; -+ else if (offset < 0) -+ /* from bottom */ -+ start = start_row + size_rows - lines + offset - 1; -+ else -+ /* from top */ -+ start = start_row + offset; -+ -+ -+ for (i = start_row + 1; i < size_rows + start_row - 1; i++) { -+ int line = i - start; -+ -+ SetMem16 (Line, size_cols*2, L' '); -+ Line[0] = BOXDRAW_VERTICAL; -+ Line[size_cols - 1] = BOXDRAW_VERTICAL; -+ Line[size_cols] = L'\0'; -+ if (line >= 0 && line < lines) { -+ CHAR16 *s = str_arr[line]; -+ int len = StrLen(s); -+ int col = (size_cols - 2 - len)/2; -+ -+ if (col < 0) -+ col = 0; -+ -+ CopyMem(Line + col + 1, s, min(len, size_cols - 2)*2); -+ } -+ if (line >= 0 && line == highlight) -+ uefi_call_wrapper(co->SetAttribute, 2, co, EFI_LIGHTGRAY | EFI_BACKGROUND_BLACK); -+ uefi_call_wrapper(co->SetCursorPosition, 3, co, start_col, i); -+ uefi_call_wrapper(co->OutputString, 2, co, Line); -+ if (line >= 0 && line == highlight) -+ uefi_call_wrapper(co->SetAttribute, 2, co, EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE); -+ -+ } -+ SetMem16 (Line, size_cols * 2, BOXDRAW_HORIZONTAL); -+ Line[0] = BOXDRAW_UP_RIGHT; -+ Line[size_cols - 1] = BOXDRAW_UP_LEFT; -+ Line[size_cols] = L'\0'; -+ uefi_call_wrapper(co->SetCursorPosition, 3, co, start_col, i); -+ uefi_call_wrapper(co->OutputString, 2, co, Line); -+ -+ FreePool (Line); -+ -+} -+ -+void -+console_print_box(CHAR16 *str_arr[], int highlight) -+{ -+ SIMPLE_TEXT_OUTPUT_MODE SavedConsoleMode; -+ SIMPLE_TEXT_OUTPUT_INTERFACE *co = ST->ConOut; -+ CopyMem(&SavedConsoleMode, co->Mode, sizeof(SavedConsoleMode)); -+ uefi_call_wrapper(co->EnableCursor, 2, co, FALSE); -+ uefi_call_wrapper(co->SetAttribute, 2, co, EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE); -+ -+ console_print_box_at(str_arr, highlight, 0, 0, -1, -1, 0, -+ count_lines(str_arr)); -+ -+ console_get_keystroke(); -+ -+ uefi_call_wrapper(co->EnableCursor, 2, co, SavedConsoleMode.CursorVisible); -+ -+ uefi_call_wrapper(co->EnableCursor, 2, co, SavedConsoleMode.CursorVisible); -+ uefi_call_wrapper(co->SetCursorPosition, 3, co, SavedConsoleMode.CursorColumn, SavedConsoleMode.CursorRow); -+ uefi_call_wrapper(co->SetAttribute, 2, co, SavedConsoleMode.Attribute); -+} -+ -+int -+console_select(CHAR16 *title[], CHAR16* selectors[], int start) -+{ -+ SIMPLE_TEXT_OUTPUT_MODE SavedConsoleMode; -+ SIMPLE_TEXT_OUTPUT_INTERFACE *co = ST->ConOut; -+ EFI_INPUT_KEY k; -+ int selector; -+ int selector_lines = count_lines(selectors); -+ int selector_max_cols = 0; -+ int i, offs_col, offs_row, size_cols, size_rows, lines; -+ int selector_offset; -+ UINTN cols, rows; -+ -+ uefi_call_wrapper(co->QueryMode, 4, co, co->Mode->Mode, &cols, &rows); -+ -+ for (i = 0; i < selector_lines; i++) { -+ int len = StrLen(selectors[i]); -+ -+ if (len > selector_max_cols) -+ selector_max_cols = len; -+ } -+ -+ if (start < 0) -+ start = 0; -+ if (start >= selector_lines) -+ start = selector_lines - 1; -+ -+ offs_col = - selector_max_cols - 4; -+ size_cols = selector_max_cols + 4; -+ -+ if (selector_lines > rows - 10) { -+ int title_lines = count_lines(title); -+ offs_row = title_lines + 1; -+ size_rows = rows - 3 - title_lines; -+ lines = size_rows - 2; -+ } else { -+ offs_row = - selector_lines - 4; -+ size_rows = selector_lines + 2; -+ lines = selector_lines; -+ } -+ -+ if (start > lines) { -+ selector = lines; -+ selector_offset = start - lines; -+ } else { -+ selector = start; -+ selector_offset = 0; -+ } -+ -+ CopyMem(&SavedConsoleMode, co->Mode, sizeof(SavedConsoleMode)); -+ uefi_call_wrapper(co->EnableCursor, 2, co, FALSE); -+ uefi_call_wrapper(co->SetAttribute, 2, co, EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE); -+ -+ console_print_box_at(title, -1, 0, 0, -1, -1, 1, count_lines(title)); -+ -+ console_print_box_at(selectors, selector, offs_col, offs_row, -+ size_cols, size_rows, 0, lines); -+ -+ do { -+ k = console_get_keystroke(); -+ -+ if (k.ScanCode == SCAN_ESC) { -+ selector = -1; -+ break; -+ } -+ -+ if (k.ScanCode == SCAN_UP) { -+ if (selector > 0) -+ selector--; -+ else if (selector_offset > 0) -+ selector_offset--; -+ } else if (k.ScanCode == SCAN_DOWN) { -+ if (selector < lines - 1) -+ selector++; -+ else if (selector_offset < (selector_lines - lines)) -+ selector_offset++; -+ } -+ -+ console_print_box_at(&selectors[selector_offset], selector, -+ offs_col, offs_row, -+ size_cols, size_rows, 0, lines); -+ } while (!(k.ScanCode == SCAN_NULL -+ && k.UnicodeChar == CHAR_CARRIAGE_RETURN)); -+ -+ uefi_call_wrapper(co->EnableCursor, 2, co, SavedConsoleMode.CursorVisible); -+ -+ uefi_call_wrapper(co->EnableCursor, 2, co, SavedConsoleMode.CursorVisible); -+ uefi_call_wrapper(co->SetCursorPosition, 3, co, SavedConsoleMode.CursorColumn, SavedConsoleMode.CursorRow); -+ uefi_call_wrapper(co->SetAttribute, 2, co, SavedConsoleMode.Attribute); -+ -+ if (selector < 0) -+ /* ESC pressed */ -+ return selector; -+ return selector + selector_offset; -+} -+ -+ -+int -+console_yes_no(CHAR16 *str_arr[]) -+{ -+ return console_select(str_arr, (CHAR16 *[]){ L"No", L"Yes", NULL }, 0); -+} -+ -+void -+console_alertbox(CHAR16 **title) -+{ -+ console_select(title, (CHAR16 *[]){ L"OK", 0 }, 0); -+} -+ -+void -+console_errorbox(CHAR16 *err) -+{ -+ CHAR16 **err_arr = (CHAR16 *[]){ -+ L"ERROR", -+ L"", -+ 0, -+ 0, -+ }; -+ -+ err_arr[2] = err; -+ -+ console_alertbox(err_arr); -+} -+ -+void -+console_notify(CHAR16 *string) -+{ -+ CHAR16 **str_arr = (CHAR16 *[]){ -+ 0, -+ 0, -+ }; -+ -+ str_arr[0] = string; -+ -+ console_alertbox(str_arr); -+} -+ -+#define ARRAY_SIZE(a) (sizeof (a) / sizeof ((a)[0])) -+ -+/* Copy of gnu-efi-3.0 with the added secure boot strings */ -+static struct { -+ EFI_STATUS Code; -+ WCHAR *Desc; -+} error_table[] = { -+ { EFI_SUCCESS, L"Success"}, -+ { EFI_LOAD_ERROR, L"Load Error"}, -+ { EFI_INVALID_PARAMETER, L"Invalid Parameter"}, -+ { EFI_UNSUPPORTED, L"Unsupported"}, -+ { EFI_BAD_BUFFER_SIZE, L"Bad Buffer Size"}, -+ { EFI_BUFFER_TOO_SMALL, L"Buffer Too Small"}, -+ { EFI_NOT_READY, L"Not Ready"}, -+ { EFI_DEVICE_ERROR, L"Device Error"}, -+ { EFI_WRITE_PROTECTED, L"Write Protected"}, -+ { EFI_OUT_OF_RESOURCES, L"Out of Resources"}, -+ { EFI_VOLUME_CORRUPTED, L"Volume Corrupt"}, -+ { EFI_VOLUME_FULL, L"Volume Full"}, -+ { EFI_NO_MEDIA, L"No Media"}, -+ { EFI_MEDIA_CHANGED, L"Media changed"}, -+ { EFI_NOT_FOUND, L"Not Found"}, -+ { EFI_ACCESS_DENIED, L"Access Denied"}, -+ { EFI_NO_RESPONSE, L"No Response"}, -+ { EFI_NO_MAPPING, L"No mapping"}, -+ { EFI_TIMEOUT, L"Time out"}, -+ { EFI_NOT_STARTED, L"Not started"}, -+ { EFI_ALREADY_STARTED, L"Already started"}, -+ { EFI_ABORTED, L"Aborted"}, -+ { EFI_ICMP_ERROR, L"ICMP Error"}, -+ { EFI_TFTP_ERROR, L"TFTP Error"}, -+ { EFI_PROTOCOL_ERROR, L"Protocol Error"}, -+ { EFI_INCOMPATIBLE_VERSION, L"Incompatible Version"}, -+ { EFI_SECURITY_VIOLATION, L"Security Violation"}, -+ -+ // warnings -+ { EFI_WARN_UNKOWN_GLYPH, L"Warning Unknown Glyph"}, -+ { EFI_WARN_DELETE_FAILURE, L"Warning Delete Failure"}, -+ { EFI_WARN_WRITE_FAILURE, L"Warning Write Failure"}, -+ { EFI_WARN_BUFFER_TOO_SMALL, L"Warning Buffer Too Small"}, -+ { 0, NULL} -+} ; -+ -+ -+static CHAR16 * -+err_string ( -+ IN EFI_STATUS Status -+ ) -+{ -+ UINTN Index; -+ -+ for (Index = 0; error_table[Index].Desc; Index +=1) { -+ if (error_table[Index].Code == Status) { -+ return error_table[Index].Desc; -+ } -+ } -+ -+ return L""; -+} -+ -+ -+void -+console_error(CHAR16 *err, EFI_STATUS status) -+{ -+ CHAR16 **err_arr = (CHAR16 *[]){ -+ L"ERROR", -+ L"", -+ 0, -+ 0, -+ }; -+ CHAR16 str[512]; -+ -+ SPrint(str, sizeof(str), L"%s: (%d) %s", err, status, err_string(status)); -+ -+ err_arr[2] = str; -+ -+ console_alertbox(err_arr); -+} -+ -+void -+console_reset(void) -+{ -+ SIMPLE_TEXT_OUTPUT_INTERFACE *co = ST->ConOut; -+ -+ uefi_call_wrapper(co->Reset, 2, co, TRUE); -+ /* set mode 0 - required to be 80x25 */ -+ uefi_call_wrapper(co->SetMode, 2, co, 0); -+ uefi_call_wrapper(co->ClearScreen, 1, co); -+} -diff --git a/lib/execute.c b/lib/execute.c -new file mode 100644 -index 0000000..8d726eb ---- /dev/null -+++ b/lib/execute.c -@@ -0,0 +1,127 @@ -+/* -+ * Copyright 2012 -+ * -+ * see COPYING file -+ * -+ * -- -+ * -+ * generate_path is a cut and paste from -+ * -+ * git://github.com/mjg59/shim.git -+ * -+ * Code Copyright 2012 Red Hat, Inc -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * -+ * Redistributions of source code must retain the above copyright -+ * notice, this list of conditions and the following disclaimer. -+ * -+ * Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the -+ * distribution. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, -+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED -+ * OF THE POSSIBILITY OF SUCH DAMAGE. -+ * -+ */ -+ -+#include -+#include -+ -+#include -+#include -+ -+EFI_STATUS -+generate_path(CHAR16* name, EFI_LOADED_IMAGE *li, EFI_DEVICE_PATH **path, CHAR16 **PathName) -+{ -+ unsigned int pathlen; -+ EFI_STATUS efi_status = EFI_SUCCESS; -+ CHAR16 *devpathstr = DevicePathToStr(li->FilePath), -+ *found = NULL; -+ int i; -+ -+ for (i = 0; i < StrLen(devpathstr); i++) { -+ if (devpathstr[i] == '/') -+ devpathstr[i] = '\\'; -+ if (devpathstr[i] == '\\') -+ found = &devpathstr[i]; -+ } -+ if (!found) { -+ pathlen = 0; -+ } else { -+ while (*(found - 1) == '\\') -+ --found; -+ *found = '\0'; -+ pathlen = StrLen(devpathstr); -+ } -+ -+ if (name[0] != '\\') -+ pathlen++; -+ -+ *PathName = AllocatePool((pathlen + 1 + StrLen(name))*sizeof(CHAR16)); -+ -+ if (!*PathName) { -+ Print(L"Failed to allocate path buffer\n"); -+ efi_status = EFI_OUT_OF_RESOURCES; -+ goto error; -+ } -+ -+ StrCpy(*PathName, devpathstr); -+ -+ if (name[0] != '\\') -+ StrCat(*PathName, L"\\"); -+ StrCat(*PathName, name); -+ -+ *path = FileDevicePath(li->DeviceHandle, *PathName); -+ -+error: -+ FreePool(devpathstr); -+ -+ return efi_status; -+} -+ -+EFI_STATUS -+execute(EFI_HANDLE image, CHAR16 *name) -+{ -+ EFI_STATUS status; -+ EFI_HANDLE h; -+ EFI_LOADED_IMAGE *li; -+ EFI_DEVICE_PATH *devpath; -+ CHAR16 *PathName; -+ -+ status = uefi_call_wrapper(BS->HandleProtocol, 3, image, -+ &IMAGE_PROTOCOL, &li); -+ if (status != EFI_SUCCESS) -+ return status; -+ -+ -+ status = generate_path(name, li, &devpath, &PathName); -+ if (status != EFI_SUCCESS) -+ return status; -+ -+ status = uefi_call_wrapper(BS->LoadImage, 6, FALSE, image, -+ devpath, NULL, 0, &h); -+ if (status != EFI_SUCCESS) -+ goto out; -+ -+ status = uefi_call_wrapper(BS->StartImage, 3, h, NULL, NULL); -+ uefi_call_wrapper(BS->UnloadImage, 1, h); -+ -+ out: -+ FreePool(PathName); -+ FreePool(devpath); -+ return status; -+} -diff --git a/lib/guid.c b/lib/guid.c -new file mode 100644 -index 0000000..25db91a ---- /dev/null -+++ b/lib/guid.c -@@ -0,0 +1,47 @@ -+/* -+ * Copyright 2012 -+ * -+ * see COPYING file -+ */ -+ -+#include -+#include -+ -+#ifndef BUILD_EFI -+/* EFI has %g for this, so it's only needed in platform c */ -+const char *guid_to_str(EFI_GUID *guid) -+{ -+ static char str[256]; -+ -+ sprintf(str, "%08x-%04hx-%04hx-%02hhx%02hhx-%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx", -+ guid->Data1, guid->Data2, guid->Data3, -+ guid->Data4[0], guid->Data4[1], guid->Data4[2], -+ guid->Data4[3], guid->Data4[4], guid->Data4[5], -+ guid->Data4[6], guid->Data4[7]); -+ -+ return str; -+} -+ -+void str_to_guid(const char *str, EFI_GUID *guid) -+{ -+ sscanf(str, "%8x-%4hx-%4hx-%2hhx%2hhx-%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx", -+ &guid->Data1, &guid->Data2, &guid->Data3, -+ guid->Data4, guid->Data4 + 1, guid->Data4 + 2, -+ guid->Data4 + 3, guid->Data4 + 4, guid->Data4 + 5, -+ guid->Data4 + 6, guid->Data4 + 7); -+} -+#endif -+ -+/* all the necessary guids */ -+EFI_GUID GV_GUID = EFI_GLOBAL_VARIABLE; -+EFI_GUID SIG_DB = { 0xd719b2cb, 0x3d3a, 0x4596, {0xa3, 0xbc, 0xda, 0xd0, 0xe, 0x67, 0x65, 0x6f }}; -+ -+EFI_GUID X509_GUID = { 0xa5c059a1, 0x94e4, 0x4aa7, {0x87, 0xb5, 0xab, 0x15, 0x5c, 0x2b, 0xf0, 0x72} }; -+EFI_GUID RSA2048_GUID = { 0x3c5766e8, 0x269c, 0x4e34, {0xaa, 0x14, 0xed, 0x77, 0x6e, 0x85, 0xb3, 0xb6} }; -+EFI_GUID PKCS7_GUID = { 0x4aafd29d, 0x68df, 0x49ee, {0x8a, 0xa9, 0x34, 0x7d, 0x37, 0x56, 0x65, 0xa7} }; -+EFI_GUID IMAGE_PROTOCOL = LOADED_IMAGE_PROTOCOL; -+EFI_GUID SIMPLE_FS_PROTOCOL = SIMPLE_FILE_SYSTEM_PROTOCOL; -+EFI_GUID EFI_CERT_SHA256_GUID = { 0xc1c41626, 0x504c, 0x4092, { 0xac, 0xa9, 0x41, 0xf9, 0x36, 0x93, 0x43, 0x28 } }; -+EFI_GUID MOK_OWNER = { 0x605dab50, 0xe046, 0x4300, {0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23} }; -+EFI_GUID SECURITY_PROTOCOL_GUID = { 0xA46423E3, 0x4617, 0x49f1, {0xB9, 0xFF, 0xD1, 0xBF, 0xA9, 0x11, 0x58, 0x39 } }; -+EFI_GUID SECURITY2_PROTOCOL_GUID = { 0x94ab2f58, 0x1438, 0x4ef1, {0x91, 0x52, 0x18, 0x94, 0x1a, 0x3a, 0x0e, 0x68 } }; -diff --git a/lib/security_policy.c b/lib/security_policy.c -new file mode 100644 -index 0000000..e7becbf ---- /dev/null -+++ b/lib/security_policy.c -@@ -0,0 +1,391 @@ -+/* -+ * Copyright 2012 -+ * -+ * see COPYING file -+ * -+ * Install and remove a platform security2 override policy -+ */ -+ -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include -+ -+/* -+ * See the UEFI Platform Initialization manual (Vol2: DXE) for this -+ */ -+struct _EFI_SECURITY2_PROTOCOL; -+struct _EFI_SECURITY_PROTOCOL; -+typedef struct _EFI_SECURITY2_PROTOCOL EFI_SECURITY2_PROTOCOL; -+typedef struct _EFI_SECURITY_PROTOCOL EFI_SECURITY_PROTOCOL; -+typedef EFI_DEVICE_PATH EFI_DEVICE_PATH_PROTOCOL; -+ -+typedef EFI_STATUS (EFIAPI *EFI_SECURITY_FILE_AUTHENTICATION_STATE) ( -+ const EFI_SECURITY_PROTOCOL *This, -+ UINT32 AuthenticationStatus, -+ const EFI_DEVICE_PATH_PROTOCOL *File -+ ); -+typedef EFI_STATUS (EFIAPI *EFI_SECURITY2_FILE_AUTHENTICATION) ( -+ const EFI_SECURITY2_PROTOCOL *This, -+ const EFI_DEVICE_PATH_PROTOCOL *DevicePath, -+ VOID *FileBuffer, -+ UINTN FileSize, -+ BOOLEAN BootPolicy -+ ); -+ -+struct _EFI_SECURITY2_PROTOCOL { -+ EFI_SECURITY2_FILE_AUTHENTICATION FileAuthentication; -+}; -+ -+struct _EFI_SECURITY_PROTOCOL { -+ EFI_SECURITY_FILE_AUTHENTICATION_STATE FileAuthenticationState; -+}; -+ -+ -+static UINT8 *security_policy_esl = NULL; -+static UINTN security_policy_esl_len; -+ -+static EFI_STATUS -+security_policy_check_mok(void *data, UINTN len) -+{ -+ EFI_STATUS status; -+ UINT8 hash[SHA256_DIGEST_SIZE]; -+ UINT32 attr; -+ UINT8 *VarData; -+ UINTN VarLen; -+ -+ /* first check is MokSBState. If we're in insecure mode, boot -+ * anyway regardless of dbx contents */ -+ status = get_variable_attr(L"MokSBState", &VarData, &VarLen, -+ MOK_OWNER, &attr); -+ if (status == EFI_SUCCESS) { -+ UINT8 MokSBState = VarData[0]; -+ -+ FreePool(VarData); -+ if ((attr & EFI_VARIABLE_RUNTIME_ACCESS) == 0 -+ && MokSBState) -+ return EFI_SUCCESS; -+ } -+ -+ status = sha256_get_pecoff_digest_mem(data, len, hash); -+ if (status != EFI_SUCCESS) -+ return status; -+ -+ if (find_in_variable_esl(L"dbx", SIG_DB, hash, SHA256_DIGEST_SIZE) -+ == EFI_SUCCESS) -+ /* MOK list cannot override dbx */ -+ return EFI_SECURITY_VIOLATION; -+ -+ status = get_variable_attr(L"MokList", &VarData, &VarLen, MOK_OWNER, -+ &attr); -+ if (status != EFI_SUCCESS) -+ goto check_tmplist; -+ -+ FreePool(VarData); -+ -+ if (attr & EFI_VARIABLE_RUNTIME_ACCESS) -+ goto check_tmplist; -+ -+ if (find_in_variable_esl(L"MokList", MOK_OWNER, hash, SHA256_DIGEST_SIZE) == EFI_SUCCESS) -+ return EFI_SUCCESS; -+ -+ check_tmplist: -+ if (security_policy_esl -+ && find_in_esl(security_policy_esl, security_policy_esl_len, hash, -+ SHA256_DIGEST_SIZE) == EFI_SUCCESS) -+ return EFI_SUCCESS; -+ -+ return EFI_SECURITY_VIOLATION; -+} -+ -+static EFI_SECURITY_FILE_AUTHENTICATION_STATE esfas = NULL; -+static EFI_SECURITY2_FILE_AUTHENTICATION es2fa = NULL; -+ -+static EFI_STATUS thunk_security_policy_authentication( -+ const EFI_SECURITY_PROTOCOL *This, -+ UINT32 AuthenticationStatus, -+ const EFI_DEVICE_PATH_PROTOCOL *DevicePath -+ ) -+__attribute__((unused)); -+ -+static EFI_STATUS thunk_security2_policy_authentication( -+ const EFI_SECURITY2_PROTOCOL *This, -+ const EFI_DEVICE_PATH_PROTOCOL *DevicePath, -+ VOID *FileBuffer, -+ UINTN FileSize, -+ BOOLEAN BootPolicy -+ ) -+__attribute__((unused)); -+ -+static __attribute__((used)) EFI_STATUS -+security2_policy_authentication ( -+ const EFI_SECURITY2_PROTOCOL *This, -+ const EFI_DEVICE_PATH_PROTOCOL *DevicePath, -+ VOID *FileBuffer, -+ UINTN FileSize, -+ BOOLEAN BootPolicy -+ ) -+{ -+ EFI_STATUS status, auth; -+ -+ /* Chain original security policy */ -+ -+ status = uefi_call_wrapper(es2fa, 5, This, DevicePath, FileBuffer, -+ FileSize, BootPolicy); -+ -+ /* if OK, don't bother with MOK check */ -+ if (status == EFI_SUCCESS) -+ return status; -+ -+ auth = security_policy_check_mok(FileBuffer, FileSize); -+ -+ if (auth == EFI_SECURITY_VIOLATION || auth == EFI_ACCESS_DENIED) -+ /* return previous status, which is the correct one -+ * for the platform: may be either EFI_ACCESS_DENIED -+ * or EFI_SECURITY_VIOLATION */ -+ return status; -+ -+ return auth; -+} -+ -+static __attribute__((used)) EFI_STATUS -+security_policy_authentication ( -+ const EFI_SECURITY_PROTOCOL *This, -+ UINT32 AuthenticationStatus, -+ const EFI_DEVICE_PATH_PROTOCOL *DevicePathConst -+ ) -+{ -+ EFI_STATUS status, fail_status; -+ EFI_DEVICE_PATH *DevPath -+ = DuplicateDevicePath((EFI_DEVICE_PATH *)DevicePathConst), -+ *OrigDevPath = DevPath; -+ EFI_HANDLE h; -+ EFI_FILE *f; -+ VOID *FileBuffer; -+ UINTN FileSize; -+ CHAR16* DevPathStr; -+ -+ /* Chain original security policy */ -+ status = uefi_call_wrapper(esfas, 3, This, AuthenticationStatus, -+ DevicePathConst); -+ -+ /* if OK avoid checking MOK: It's a bit expensive to -+ * read the whole file in again (esfas already did this) */ -+ if (status == EFI_SUCCESS) -+ goto out; -+ -+ /* capture failure status: may be either EFI_ACCESS_DENIED or -+ * EFI_SECURITY_VIOLATION */ -+ fail_status = status; -+ -+ status = uefi_call_wrapper(BS->LocateDevicePath, 3, -+ &SIMPLE_FS_PROTOCOL, &DevPath, &h); -+ if (status != EFI_SUCCESS) -+ goto out; -+ -+ DevPathStr = DevicePathToStr(DevPath); -+ -+ status = simple_file_open_by_handle(h, DevPathStr, &f, -+ EFI_FILE_MODE_READ); -+ FreePool(DevPathStr); -+ if (status != EFI_SUCCESS) -+ goto out; -+ -+ status = simple_file_read_all(f, &FileSize, &FileBuffer); -+ simple_file_close(f); -+ if (status != EFI_SUCCESS) -+ goto out; -+ -+ status = security_policy_check_mok(FileBuffer, FileSize); -+ FreePool(FileBuffer); -+ -+ if (status == EFI_ACCESS_DENIED || status == EFI_SECURITY_VIOLATION) -+ /* return what the platform originally said */ -+ status = fail_status; -+ out: -+ FreePool(OrigDevPath); -+ return status; -+} -+ -+ -+/* Nasty: ELF and EFI have different calling conventions. Here is the map for -+ * calling ELF -> EFI -+ * -+ * 1) rdi -> rcx (32 saved) -+ * 2) rsi -> rdx (32 saved) -+ * 3) rdx -> r8 ( 32 saved) -+ * 4) rcx -> r9 (32 saved) -+ * 5) r8 -> 32(%rsp) (48 saved) -+ * 6) r9 -> 40(%rsp) (48 saved) -+ * 7) pad+0(%rsp) -> 48(%rsp) (64 saved) -+ * 8) pad+8(%rsp) -> 56(%rsp) (64 saved) -+ * 9) pad+16(%rsp) -> 64(%rsp) (80 saved) -+ * 10) pad+24(%rsp) -> 72(%rsp) (80 saved) -+ * 11) pad+32(%rsp) -> 80(%rsp) (96 saved) -+ -+ * -+ * So for a five argument callback, the map is ignore the first two arguments -+ * and then map (EFI -> ELF) assuming pad = 0. -+ * -+ * ARG4 -> ARG1 -+ * ARG3 -> ARG2 -+ * ARG5 -> ARG3 -+ * ARG6 -> ARG4 -+ * ARG11 -> ARG5 -+ * -+ * Calling conventions also differ over volatile and preserved registers in -+ * MS: RBX, RBP, RDI, RSI, R12, R13, R14, and R15 are considered nonvolatile . -+ * In ELF: Registers %rbp, %rbx and %r12 through %r15 “belong” to the calling -+ * function and the called function is required to preserve their values. -+ * -+ * This means when accepting a function callback from MS -> ELF, we have to do -+ * separate preservation on %rdi, %rsi before swizzling the arguments and -+ * handing off to the ELF function. -+ */ -+ -+asm ( -+".type security2_policy_authentication,@function\n" -+"thunk_security2_policy_authentication:\n\t" -+ "mov 0x28(%rsp), %r10 # ARG5\n\t" -+ "push %rdi\n\t" -+ "push %rsi\n\t" -+ "mov %r10, %rdi\n\t" -+ "subq $8, %rsp # space for storing stack pad\n\t" -+ "mov $0x08, %rax\n\t" -+ "mov $0x10, %r10\n\t" -+ "and %rsp, %rax\n\t" -+ "cmovnz %rax, %r11\n\t" -+ "cmovz %r10, %r11\n\t" -+ "subq %r11, %rsp\n\t" -+ "addq $8, %r11\n\t" -+ "mov %r11, (%rsp)\n\t" -+"# five argument swizzle\n\t" -+ "mov %rdi, %r10\n\t" -+ "mov %rcx, %rdi\n\t" -+ "mov %rdx, %rsi\n\t" -+ "mov %r8, %rdx\n\t" -+ "mov %r9, %rcx\n\t" -+ "mov %r10, %r8\n\t" -+ "callq security2_policy_authentication@PLT\n\t" -+ "mov (%rsp), %r11\n\t" -+ "addq %r11, %rsp\n\t" -+ "pop %rsi\n\t" -+ "pop %rdi\n\t" -+ "ret\n" -+); -+ -+asm ( -+".type security_policy_authentication,@function\n" -+"thunk_security_policy_authentication:\n\t" -+ "push %rdi\n\t" -+ "push %rsi\n\t" -+ "subq $8, %rsp # space for storing stack pad\n\t" -+ "mov $0x08, %rax\n\t" -+ "mov $0x10, %r10\n\t" -+ "and %rsp, %rax\n\t" -+ "cmovnz %rax, %r11\n\t" -+ "cmovz %r10, %r11\n\t" -+ "subq %r11, %rsp\n\t" -+ "addq $8, %r11\n\t" -+ "mov %r11, (%rsp)\n\t" -+"# three argument swizzle\n\t" -+ "mov %rcx, %rdi\n\t" -+ "mov %rdx, %rsi\n\t" -+ "mov %r8, %rdx\n\t" -+ "callq security_policy_authentication@PLT\n\t" -+ "mov (%rsp), %r11\n\t" -+ "addq %r11, %rsp\n\t" -+ "pop %rsi\n\t" -+ "pop %rdi\n\t" -+ "ret\n" -+); -+ -+EFI_STATUS -+security_policy_install(void) -+{ -+ EFI_SECURITY_PROTOCOL *security_protocol; -+ EFI_SECURITY2_PROTOCOL *security2_protocol = NULL; -+ EFI_STATUS status; -+ -+ if (esfas) -+ /* Already Installed */ -+ return EFI_ALREADY_STARTED; -+ -+ /* Don't bother with status here. The call is allowed -+ * to fail, since SECURITY2 was introduced in PI 1.2.1 -+ * If it fails, use security2_protocol == NULL as indicator */ -+ uefi_call_wrapper(BS->LocateProtocol, 3, -+ &SECURITY2_PROTOCOL_GUID, NULL, -+ &security2_protocol); -+ -+ status = uefi_call_wrapper(BS->LocateProtocol, 3, -+ &SECURITY_PROTOCOL_GUID, NULL, -+ &security_protocol); -+ if (status != EFI_SUCCESS) -+ /* This one is mandatory, so there's a serious problem */ -+ return status; -+ -+ if (security2_protocol) { -+ es2fa = security2_protocol->FileAuthentication; -+ security2_protocol->FileAuthentication = -+ thunk_security2_policy_authentication; -+ } -+ -+ esfas = security_protocol->FileAuthenticationState; -+ security_protocol->FileAuthenticationState = -+ thunk_security_policy_authentication; -+ -+ return EFI_SUCCESS; -+} -+ -+EFI_STATUS -+security_policy_uninstall(void) -+{ -+ EFI_STATUS status; -+ -+ if (esfas) { -+ EFI_SECURITY_PROTOCOL *security_protocol; -+ -+ status = uefi_call_wrapper(BS->LocateProtocol, 3, -+ &SECURITY_PROTOCOL_GUID, NULL, -+ &security_protocol); -+ -+ if (status != EFI_SUCCESS) -+ return status; -+ -+ security_protocol->FileAuthenticationState = esfas; -+ esfas = NULL; -+ } else { -+ /* nothing installed */ -+ return EFI_NOT_STARTED; -+ } -+ -+ if (es2fa) { -+ EFI_SECURITY2_PROTOCOL *security2_protocol; -+ -+ status = uefi_call_wrapper(BS->LocateProtocol, 3, -+ &SECURITY2_PROTOCOL_GUID, NULL, -+ &security2_protocol); -+ -+ if (status != EFI_SUCCESS) -+ return status; -+ -+ security2_protocol->FileAuthentication = es2fa; -+ es2fa = NULL; -+ } -+ -+ return EFI_SUCCESS; -+} -+ -+void -+security_protocol_set_hashes(unsigned char *esl, int len) -+{ -+ security_policy_esl = esl; -+ security_policy_esl_len = len; -+} -diff --git a/lib/shell.c b/lib/shell.c -new file mode 100644 -index 0000000..51de4e0 ---- /dev/null -+++ b/lib/shell.c -@@ -0,0 +1,57 @@ -+/* -+ * Copyright 2012 -+ * -+ * see COPYING file -+ * -+ * misc shell helper functions -+ */ -+#include -+#include -+ -+#include -+ -+EFI_STATUS -+argsplit(EFI_HANDLE image, int *argc, CHAR16*** ARGV) -+{ -+ int i, count = 1; -+ EFI_STATUS status; -+ EFI_LOADED_IMAGE *info; -+ CHAR16 *start; -+ -+ *argc = 0; -+ -+ status = uefi_call_wrapper(BS->HandleProtocol, 3, image, &LoadedImageProtocol, (VOID **) &info); -+ if (EFI_ERROR(status)) { -+ Print(L"Failed to get arguments\n"); -+ return status; -+ } -+ -+ for (i = 0; i < info->LoadOptionsSize; i += 2) { -+ CHAR16 *c = (CHAR16 *)(info->LoadOptions + i); -+ if (*c == L' ' && *(c+1) != '\0') { -+ (*argc)++; -+ } -+ } -+ -+ (*argc)++; /* we counted spaces, so add one for initial */ -+ -+ *ARGV = AllocatePool(*argc * sizeof(*ARGV)); -+ if (!*ARGV) { -+ return EFI_OUT_OF_RESOURCES; -+ } -+ (*ARGV)[0] = (CHAR16 *)info->LoadOptions; -+ for (i = 0; i < info->LoadOptionsSize; i += 2) { -+ CHAR16 *c = (CHAR16 *)(info->LoadOptions + i); -+ if (*c == L' ') { -+ *c = L'\0'; -+ if (*(c + 1) == '\0') -+ /* strip trailing space */ -+ break; -+ start = c + 1; -+ (*ARGV)[count++] = start; -+ } -+ } -+ -+ return EFI_SUCCESS; -+} -+ -diff --git a/lib/simple_file.c b/lib/simple_file.c -new file mode 100644 -index 0000000..0e5ecd2 ---- /dev/null -+++ b/lib/simple_file.c -@@ -0,0 +1,501 @@ -+/* -+ * Copyright 2012 -+ * -+ * see COPYING file -+ */ -+ -+#include -+#include -+ -+#include -+#include -+#include -+#include /* for generate_path() */ -+ -+static EFI_GUID IMAGE_PROTOCOL = LOADED_IMAGE_PROTOCOL; -+static EFI_GUID SIMPLE_FS_PROTOCOL = SIMPLE_FILE_SYSTEM_PROTOCOL; -+static EFI_GUID FILE_INFO = EFI_FILE_INFO_ID; -+static EFI_GUID FS_INFO = EFI_FILE_SYSTEM_INFO_ID; -+ -+EFI_STATUS -+simple_file_open_by_handle(EFI_HANDLE device, CHAR16 *name, EFI_FILE **file, UINT64 mode) -+{ -+ EFI_STATUS efi_status; -+ EFI_FILE_IO_INTERFACE *drive; -+ EFI_FILE *root; -+ -+ efi_status = uefi_call_wrapper(BS->HandleProtocol, 3, device, -+ &SIMPLE_FS_PROTOCOL, &drive); -+ -+ if (efi_status != EFI_SUCCESS) { -+ Print(L"Unable to find simple file protocol (%d)\n", efi_status); -+ goto error; -+ } -+ -+ efi_status = uefi_call_wrapper(drive->OpenVolume, 2, drive, &root); -+ -+ if (efi_status != EFI_SUCCESS) { -+ Print(L"Failed to open drive volume (%d)\n", efi_status); -+ goto error; -+ } -+ -+ efi_status = uefi_call_wrapper(root->Open, 5, root, file, name, -+ mode, 0); -+ -+ error: -+ return efi_status; -+} -+ -+EFI_STATUS -+simple_file_open(EFI_HANDLE image, CHAR16 *name, EFI_FILE **file, UINT64 mode) -+{ -+ EFI_STATUS efi_status; -+ EFI_HANDLE device; -+ EFI_LOADED_IMAGE *li; -+ EFI_DEVICE_PATH *loadpath = NULL; -+ CHAR16 *PathName = NULL; -+ -+ efi_status = uefi_call_wrapper(BS->HandleProtocol, 3, image, -+ &IMAGE_PROTOCOL, &li); -+ -+ if (efi_status != EFI_SUCCESS) -+ return simple_file_open_by_handle(image, name, file, mode); -+ -+ efi_status = generate_path(name, li, &loadpath, &PathName); -+ -+ if (efi_status != EFI_SUCCESS) { -+ Print(L"Unable to generate load path for %s\n", name); -+ return efi_status; -+ } -+ -+ device = li->DeviceHandle; -+ -+ efi_status = simple_file_open_by_handle(device, PathName, file, mode); -+ -+ FreePool(PathName); -+ FreePool(loadpath); -+ -+ return efi_status; -+} -+ -+EFI_STATUS -+simple_dir_read_all_by_handle(EFI_HANDLE image, EFI_FILE *file, CHAR16* name, EFI_FILE_INFO **entries, -+ int *count) -+{ -+ EFI_STATUS status; -+ char buf[4096]; -+ UINTN size = sizeof(buf); -+ EFI_FILE_INFO *fi = (void *)buf; -+ -+ status = uefi_call_wrapper(file->GetInfo, 4, file, &FILE_INFO, -+ &size, fi); -+ if (status != EFI_SUCCESS) { -+ Print(L"Failed to get file info\n"); -+ goto out; -+ } -+ if ((fi->Attribute & EFI_FILE_DIRECTORY) == 0) { -+ Print(L"Not a directory %s\n", name); -+ status = EFI_INVALID_PARAMETER; -+ goto out; -+ } -+ size = 0; -+ *count = 0; -+ for (;;) { -+ UINTN len = sizeof(buf); -+ status = uefi_call_wrapper(file->Read, 3, file, &len, buf); -+ if (status != EFI_SUCCESS || len == 0) -+ break; -+ (*count)++; -+ size += len; -+ } -+ uefi_call_wrapper(file->SetPosition, 2, file, 0); -+ -+ char *ptr = AllocatePool(size); -+ *entries = (EFI_FILE_INFO *)ptr; -+ if (!*entries) -+ return EFI_OUT_OF_RESOURCES; -+ int i; -+ for (i = 0; i < *count; i++) { -+ int len = size; -+ uefi_call_wrapper(file->Read, 3, file, &len, ptr); -+ ptr += len; -+ size -= len; -+ } -+ status = EFI_SUCCESS; -+ out: -+ simple_file_close(file); -+ if (status != EFI_SUCCESS && *entries) { -+ FreePool(*entries); -+ *entries = NULL; -+ } -+ return status; -+} -+ -+EFI_STATUS -+simple_dir_read_all(EFI_HANDLE image, CHAR16 *name, EFI_FILE_INFO **entries, -+ int *count) -+{ -+ EFI_FILE *file; -+ EFI_STATUS status; -+ -+ status = simple_file_open(image, name, &file, EFI_FILE_MODE_READ); -+ if (status != EFI_SUCCESS) { -+ Print(L"failed to open file %s: %d\n", name, status); -+ return status; -+ } -+ -+ return simple_dir_read_all_by_handle(image, file, name, entries, count); -+} -+ -+EFI_STATUS -+simple_file_read_all(EFI_FILE *file, UINTN *size, void **buffer) -+{ -+ EFI_STATUS efi_status; -+ EFI_FILE_INFO *fi; -+ char buf[1024]; -+ -+ *size = sizeof(buf); -+ fi = (void *)buf; -+ -+ -+ efi_status = uefi_call_wrapper(file->GetInfo, 4, file, &FILE_INFO, -+ size, fi); -+ if (efi_status != EFI_SUCCESS) { -+ Print(L"Failed to get file info\n"); -+ return efi_status; -+ } -+ -+ *size = fi->FileSize; -+ -+ *buffer = AllocatePool(*size); -+ if (!*buffer) { -+ Print(L"Failed to allocate buffer of size %d\n", *size); -+ return EFI_OUT_OF_RESOURCES; -+ } -+ efi_status = uefi_call_wrapper(file->Read, 3, file, size, *buffer); -+ -+ return efi_status; -+} -+ -+ -+EFI_STATUS -+simple_file_write_all(EFI_FILE *file, UINTN size, void *buffer) -+{ -+ EFI_STATUS efi_status; -+ -+ efi_status = uefi_call_wrapper(file->Write, 3, file, &size, buffer); -+ -+ return efi_status; -+} -+ -+void -+simple_file_close(EFI_FILE *file) -+{ -+ uefi_call_wrapper(file->Close, 1, file); -+} -+ -+EFI_STATUS -+simple_volume_selector(CHAR16 **title, CHAR16 **selected, EFI_HANDLE *h) -+{ -+ UINTN count, i; -+ EFI_HANDLE *vol_handles = NULL; -+ EFI_STATUS status; -+ CHAR16 **entries; -+ int val; -+ -+ uefi_call_wrapper(BS->LocateHandleBuffer, 5, ByProtocol, -+ &SIMPLE_FS_PROTOCOL, NULL, &count, &vol_handles); -+ -+ if (!count || !vol_handles) -+ return EFI_NOT_FOUND; -+ -+ entries = AllocatePool(sizeof(CHAR16 *) * (count+1)); -+ if (!entries) -+ return EFI_OUT_OF_RESOURCES; -+ -+ for (i = 0; i < count; i++) { -+ char buf[4096]; -+ UINTN size = sizeof(buf); -+ EFI_FILE_SYSTEM_INFO *fi = (void *)buf; -+ EFI_FILE *root; -+ CHAR16 *name; -+ EFI_FILE_IO_INTERFACE *drive; -+ -+ status = uefi_call_wrapper(BS->HandleProtocol, 3, -+ vol_handles[i], -+ &SIMPLE_FS_PROTOCOL, &drive); -+ if (status != EFI_SUCCESS || !drive) -+ continue; -+ -+ status = uefi_call_wrapper(drive->OpenVolume, 2, drive, &root); -+ if (status != EFI_SUCCESS) -+ continue; -+ -+ status = uefi_call_wrapper(root->GetInfo, 4, root, &FS_INFO, -+ &size, fi); -+ if (status != EFI_SUCCESS) -+ continue; -+ -+ name = fi->VolumeLabel; -+ -+ if (!name || StrLen(name) == 0 || StrCmp(name, L" ") == 0) -+ name = DevicePathToStr(DevicePathFromHandle(vol_handles[i])); -+ -+ entries[i] = AllocatePool((StrLen(name) + 2) * sizeof(CHAR16)); -+ if (!entries[i]) -+ break; -+ StrCpy(entries[i], name); -+ } -+ entries[i] = NULL; -+ -+ val = console_select(title, entries, 0); -+ -+ if (val >= 0) { -+ *selected = AllocatePool((StrLen(entries[val]) + 1) * sizeof(CHAR16)); -+ if (*selected) { -+ StrCpy(*selected , entries[val]); -+ } -+ *h = vol_handles[val]; -+ } else { -+ *selected = NULL; -+ *h = 0; -+ } -+ -+ for (i = 0; i < count; i++) { -+ if (entries[i]) -+ FreePool(entries[i]); -+ } -+ FreePool(entries); -+ FreePool(vol_handles); -+ -+ -+ return EFI_SUCCESS; -+} -+ -+EFI_STATUS -+simple_dir_filter(EFI_HANDLE image, CHAR16 *name, CHAR16 *filter, -+ CHAR16 ***result, int *count, EFI_FILE_INFO **entries) -+{ -+ EFI_STATUS status; -+ int tot, offs = StrLen(filter), i, c, filtercount = 1; -+ EFI_FILE_INFO *next; -+ void *ptr; -+ CHAR16 *newfilter = AllocatePool((StrLen(filter) + 1) * sizeof(CHAR16)), -+ **filterarr; -+ -+ if (!newfilter) -+ return EFI_OUT_OF_RESOURCES; -+ -+ /* just in case efi ever stops writeable strings */ -+ StrCpy(newfilter, filter); -+ -+ for (i = 0; i < offs; i++) { -+ if (filter[i] == '|') -+ filtercount++; -+ } -+ filterarr = AllocatePool(filtercount * sizeof(void *)); -+ if (!filterarr) -+ return EFI_OUT_OF_RESOURCES; -+ c = 0; -+ filterarr[c++] = newfilter; -+ for (i = 0; i < offs; i++) { -+ if (filter[i] == '|') { -+ newfilter[i] = '\0'; -+ filterarr[c++] = &newfilter[i+1]; -+ } -+ } -+ -+ *count = 0; -+ -+ status = simple_dir_read_all(image, name, entries, &tot); -+ -+ if (status != EFI_SUCCESS) -+ goto out; -+ ptr = next = *entries; -+ -+ for (i = 0; i < tot; i++) { -+ int len = StrLen(next->FileName); -+ -+ for (c = 0; c < filtercount; c++) { -+ offs = StrLen(filterarr[c]); -+ -+ if (StrCmp(&next->FileName[len - offs], filterarr[c]) == 0 -+ || (next->Attribute & EFI_FILE_DIRECTORY)) { -+ (*count)++; -+ break; -+ } -+ } -+ ptr += OFFSET_OF(EFI_FILE_INFO, FileName) + (len + 1)*sizeof(CHAR16); -+ next = ptr; -+ } -+ if (*count) -+ *result = AllocatePool(((*count) + 1) * sizeof(void *)); -+ else -+ *result = AllocatePool(2 * sizeof(void *)); -+ -+ *count = 0; -+ ptr = next = *entries; -+ -+ for (i = 0; i < tot; i++) { -+ int len = StrLen(next->FileName); -+ -+ if (StrCmp(next->FileName, L".") == 0) -+ /* ignore . directory */ -+ goto next; -+ -+ if (next->Attribute & EFI_FILE_DIRECTORY) { -+ (*result)[(*count)] = next->FileName; -+ (*result)[(*count)][len] = '/'; -+ (*result)[(*count)++][len + 1] = '\0'; -+ goto next; -+ } -+ -+ for (c = 0; c < filtercount; c++) { -+ offs = StrLen(filterarr[c]); -+ -+ if (StrCmp(&next->FileName[len - offs], filterarr[c]) == 0) { -+ (*result)[(*count)++] = next->FileName; -+ } else { -+ continue; -+ } -+ break; -+ } -+ -+ next: -+ if (StrCmp(next->FileName, L"../") == 0) { -+ /* place .. directory first */ -+ CHAR16 *tmp = (*result)[(*count) - 1]; -+ -+ (*result)[(*count) - 1] = (*result)[0]; -+ (*result)[0] = tmp; -+ } -+ -+ ptr += OFFSET_OF(EFI_FILE_INFO, FileName) + (len + 1)*sizeof(CHAR16); -+ next = ptr; -+ } -+ if (*count == 0) { -+ /* no entries at all ... can happen because top level dir has no . or .. */ -+ (*result)[(*count)++] = L"./"; -+ } -+ (*result)[*count] = NULL; -+ status = EFI_SUCCESS; -+ -+ out: -+ if (status != EFI_SUCCESS) { -+ if (*entries) -+ FreePool(*entries); -+ *entries = NULL; -+ if (*result) -+ FreePool(*result); -+ *result = NULL; -+ } -+ return status; -+} -+ -+void -+simple_file_selector(EFI_HANDLE *im, CHAR16 **title, CHAR16 *name, -+ CHAR16 *filter, CHAR16 **result) -+{ -+ EFI_STATUS status; -+ CHAR16 **entries; -+ EFI_FILE_INFO *dmp; -+ int count, select, len; -+ CHAR16 *newname, *selected; -+ -+ *result = NULL; -+ if (!name) -+ name = L"\\"; -+ if (!filter) -+ filter = L""; -+ if (!*im) { -+ EFI_HANDLE h; -+ CHAR16 *volname; -+ -+ simple_volume_selector(title, &volname, &h); -+ if (!volname) -+ return; -+ FreePool(volname); -+ *im = h; -+ } -+ -+ newname = AllocatePool((StrLen(name) + 1)*sizeof(CHAR16)); -+ if (!newname) -+ return; -+ -+ StrCpy(newname, name); -+ name = newname; -+ -+ redo: -+ status = simple_dir_filter(*im, name, filter, &entries, &count, &dmp); -+ -+ if (status != EFI_SUCCESS) -+ goto out_free_name; -+ -+ select = console_select(title, entries, 0); -+ if (select < 0) -+ /* ESC key */ -+ goto out_free; -+ selected = entries[select]; -+ FreePool(entries); -+ entries = NULL; -+ /* note that memory used by selected is valid until dmp is freed */ -+ len = StrLen(selected); -+ if (selected[len - 1] == '/') { -+ CHAR16 *newname; -+ -+ /* stay where we are */ -+ if (StrCmp(selected, L"./") == 0) { -+ FreePool(dmp); -+ goto redo; -+ } else if (StrCmp(selected, L"../") == 0) { -+ int i; -+ -+ i = StrLen(name) - 1; -+ -+ -+ for (i = StrLen(name); i > 0; --i) { -+ if (name[i] == '\\') -+ break; -+ } -+ if (i == 0) -+ i = 1; -+ -+ if (StrCmp(name, L"\\") != 0 -+ && StrCmp(&name[i], L"..") != 0) { -+ name[i] = '\0'; -+ FreePool(dmp); -+ goto redo; -+ } -+ } -+ newname = AllocatePool((StrLen(name) + len + 2)*sizeof(CHAR16)); -+ if (!newname) -+ goto out_free; -+ StrCpy(newname, name); -+ -+ if (name[StrLen(name) - 1] != '\\') -+ StrCat(newname, L"\\"); -+ StrCat(newname, selected); -+ /* remove trailing / */ -+ newname[StrLen(newname) - 1] = '\0'; -+ -+ FreePool(dmp); -+ FreePool(name); -+ name = newname; -+ -+ goto redo; -+ } -+ *result = AllocatePool((StrLen(name) + len + 2)*sizeof(CHAR16)); -+ if (*result) { -+ StrCpy(*result, name); -+ if (name[StrLen(name) - 1] != '\\') -+ StrCat(*result, L"\\"); -+ StrCat(*result, selected); -+ } -+ -+ out_free: -+ FreePool(dmp); -+ if (entries) -+ FreePool(entries); -+ out_free_name: -+ FreePool(name); -+} -diff --git a/lib/variables.c b/lib/variables.c -new file mode 100644 -index 0000000..9db6480 ---- /dev/null -+++ b/lib/variables.c -@@ -0,0 +1,340 @@ -+/* -+ * Copyright 2012 -+ * -+ * see COPYING file -+ * -+ * Portions of this file are a direct cut and paste from Tianocore -+ * (http://tianocore.sf.net) -+ * -+ * SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.c -+ * -+ * Copyright (c) 2011 - 2012, Intel Corporation. All rights reserved.
-+ * This program and the accompanying materials -+ * are licensed and made available under the terms and conditions of the BSD License -+ * which accompanies this distribution. The full text of the license may be found -+ * at -+ * http://opensource.org/licenses/bsd-license.php -+ * -+ * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, -+ * WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. -+ * -+ */ -+#include -+#include -+ -+#include -+ -+#include -+#include -+#include -+#include -+#include -+ -+EFI_STATUS -+variable_create_esl(void *cert, int cert_len, EFI_GUID *type, EFI_GUID *owner, -+ void **out, int *outlen) -+{ -+ *outlen = cert_len + sizeof(EFI_SIGNATURE_LIST) + sizeof(EFI_GUID); -+ -+ *out = AllocateZeroPool(*outlen); -+ if (!*out) -+ return EFI_OUT_OF_RESOURCES; -+ -+ EFI_SIGNATURE_LIST *sl = *out; -+ -+ sl->SignatureHeaderSize = 0; -+ sl->SignatureType = *type; -+ sl->SignatureSize = cert_len + sizeof(EFI_GUID); -+ sl->SignatureListSize = *outlen; -+ -+ EFI_SIGNATURE_DATA *sd = *out + sizeof(EFI_SIGNATURE_LIST); -+ -+ if (owner) -+ sd->SignatureOwner = *owner; -+ -+ CopyMem(sd->SignatureData, cert, cert_len); -+ -+ return EFI_SUCCESS; -+} -+ -+ -+EFI_STATUS -+CreateTimeBasedPayload ( -+ IN OUT UINTN *DataSize, -+ IN OUT UINT8 **Data -+ ) -+{ -+ EFI_STATUS Status; -+ UINT8 *NewData; -+ UINT8 *Payload; -+ UINTN PayloadSize; -+ EFI_VARIABLE_AUTHENTICATION_2 *DescriptorData; -+ UINTN DescriptorSize; -+ EFI_TIME Time; -+ EFI_GUID efi_cert_type = EFI_CERT_TYPE_PKCS7_GUID; -+ -+ if (Data == NULL || DataSize == NULL) { -+ return EFI_INVALID_PARAMETER; -+ } -+ -+ // -+ // In Setup mode or Custom mode, the variable does not need to be signed but the -+ // parameters to the SetVariable() call still need to be prepared as authenticated -+ // variable. So we create EFI_VARIABLE_AUTHENTICATED_2 descriptor without certificate -+ // data in it. -+ // -+ Payload = *Data; -+ PayloadSize = *DataSize; -+ -+ DescriptorSize = OFFSET_OF(EFI_VARIABLE_AUTHENTICATION_2, AuthInfo) + OFFSET_OF(WIN_CERTIFICATE_UEFI_GUID, CertData); -+ NewData = (UINT8*) AllocateZeroPool (DescriptorSize + PayloadSize); -+ if (NewData == NULL) { -+ return EFI_OUT_OF_RESOURCES; -+ } -+ -+ if ((Payload != NULL) && (PayloadSize != 0)) { -+ CopyMem (NewData + DescriptorSize, Payload, PayloadSize); -+ } -+ -+ DescriptorData = (EFI_VARIABLE_AUTHENTICATION_2 *) (NewData); -+ -+ ZeroMem (&Time, sizeof (EFI_TIME)); -+ Status = uefi_call_wrapper(RT->GetTime,2, &Time, NULL); -+ if (EFI_ERROR (Status)) { -+ FreePool(NewData); -+ return Status; -+ } -+ Time.Pad1 = 0; -+ Time.Nanosecond = 0; -+ Time.TimeZone = 0; -+ Time.Daylight = 0; -+ Time.Pad2 = 0; -+ CopyMem (&DescriptorData->TimeStamp, &Time, sizeof (EFI_TIME)); -+ -+ DescriptorData->AuthInfo.Hdr.dwLength = OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID, CertData); -+ DescriptorData->AuthInfo.Hdr.wRevision = 0x0200; -+ DescriptorData->AuthInfo.Hdr.wCertificateType = WIN_CERT_TYPE_EFI_GUID; -+ DescriptorData->AuthInfo.CertType = efi_cert_type; -+ -+ /* we're expecting an EFI signature list, so don't free the input since -+ * it might not be in a pool */ -+#if 0 -+ if (Payload != NULL) { -+ FreePool(Payload); -+ } -+#endif -+ -+ *DataSize = DescriptorSize + PayloadSize; -+ *Data = NewData; -+ return EFI_SUCCESS; -+} -+ -+EFI_STATUS -+SetSecureVariable(CHAR16 *var, UINT8 *Data, UINTN len, EFI_GUID owner, -+ UINT32 options, int createtimebased) -+{ -+ EFI_SIGNATURE_LIST *Cert; -+ UINTN DataSize; -+ EFI_STATUS efi_status; -+ -+ /* Microsoft request: Bugs in some UEFI platforms mean that PK or any -+ * other secure variable can be updated or deleted programmatically, -+ * so prevent */ -+ if (!variable_is_setupmode()) -+ return EFI_SECURITY_VIOLATION; -+ -+ if (createtimebased) { -+ int ds; -+ efi_status = variable_create_esl(Data, len, &X509_GUID, NULL, -+ (void **)&Cert, &ds); -+ if (efi_status != EFI_SUCCESS) { -+ Print(L"Failed to create %s certificate %d\n", var, efi_status); -+ return efi_status; -+ } -+ -+ DataSize = ds; -+ } else { -+ /* we expect an efi signature list rather than creating it */ -+ Cert = (EFI_SIGNATURE_LIST *)Data; -+ DataSize = len; -+ } -+ efi_status = CreateTimeBasedPayload(&DataSize, (UINT8 **)&Cert); -+ if (efi_status != EFI_SUCCESS) { -+ Print(L"Failed to create time based payload %d\n", efi_status); -+ return efi_status; -+ } -+ -+ efi_status = uefi_call_wrapper(RT->SetVariable, 5, var, &owner, -+ EFI_VARIABLE_NON_VOLATILE -+ | EFI_VARIABLE_RUNTIME_ACCESS -+ | EFI_VARIABLE_BOOTSERVICE_ACCESS -+ | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS -+ | options, -+ DataSize, Cert); -+ -+ return efi_status; -+} -+ -+UINT64 -+GetOSIndications(void) -+{ -+ UINT64 indications; -+ UINTN DataSize = sizeof(indications); -+ EFI_STATUS efi_status; -+ -+ efi_status = uefi_call_wrapper(RT->GetVariable, 5, L"OsIndicationsSupported", &GV_GUID, NULL, &DataSize, &indications); -+ if (efi_status != EFI_SUCCESS) -+ return 0; -+ -+ return indications; -+} -+ -+EFI_STATUS -+SETOSIndicationsAndReboot(UINT64 indications) -+{ -+ UINTN DataSize = sizeof(indications); -+ EFI_STATUS efi_status; -+ -+ efi_status = uefi_call_wrapper(RT->SetVariable, 5, L"OsIndications", -+ &GV_GUID, -+ EFI_VARIABLE_NON_VOLATILE -+ | EFI_VARIABLE_RUNTIME_ACCESS -+ | EFI_VARIABLE_BOOTSERVICE_ACCESS, -+ DataSize, &indications); -+ -+ if (efi_status != EFI_SUCCESS) -+ return efi_status; -+ -+ uefi_call_wrapper(RT->ResetSystem, 4, EfiResetWarm, EFI_SUCCESS, 0, NULL); -+ /* does not return */ -+ -+ return EFI_SUCCESS; -+} -+ -+EFI_STATUS -+get_variable_attr(CHAR16 *var, UINT8 **data, UINTN *len, EFI_GUID owner, -+ UINT32 *attributes) -+{ -+ EFI_STATUS efi_status; -+ -+ *len = 0; -+ -+ efi_status = uefi_call_wrapper(RT->GetVariable, 5, var, &owner, -+ NULL, len, NULL); -+ if (efi_status != EFI_BUFFER_TOO_SMALL) -+ return efi_status; -+ -+ *data = AllocateZeroPool(*len); -+ if (!data) -+ return EFI_OUT_OF_RESOURCES; -+ -+ efi_status = uefi_call_wrapper(RT->GetVariable, 5, var, &owner, -+ attributes, len, *data); -+ -+ if (efi_status != EFI_SUCCESS) { -+ FreePool(*data); -+ *data = NULL; -+ } -+ return efi_status; -+} -+ -+EFI_STATUS -+get_variable(CHAR16 *var, UINT8 **data, UINTN *len, EFI_GUID owner) -+{ -+ return get_variable_attr(var, data, len, owner, NULL); -+} -+ -+EFI_STATUS -+find_in_esl(UINT8 *Data, UINTN DataSize, UINT8 *key, UINTN keylen) -+{ -+ EFI_SIGNATURE_LIST *CertList; -+ -+ certlist_for_each_certentry(CertList, Data, DataSize, DataSize) { -+ if (CertList->SignatureSize != keylen + sizeof(EFI_GUID)) -+ continue; -+ EFI_SIGNATURE_DATA *Cert; -+ -+ certentry_for_each_cert(Cert, CertList) -+ if (CompareMem (Cert->SignatureData, key, keylen) == 0) -+ return EFI_SUCCESS; -+ } -+ return EFI_NOT_FOUND; -+} -+ -+EFI_STATUS -+find_in_variable_esl(CHAR16* var, EFI_GUID owner, UINT8 *key, UINTN keylen) -+{ -+ UINTN DataSize; -+ UINT8 *Data; -+ EFI_STATUS status; -+ -+ status = get_variable(var, &Data, &DataSize, owner); -+ if (status != EFI_SUCCESS) -+ return status; -+ -+ status = find_in_esl(Data, DataSize, key, keylen); -+ -+ FreePool(Data); -+ -+ return status; -+} -+ -+int -+variable_is_setupmode(void) -+{ -+ /* set to 1 because we return true if SetupMode doesn't exist */ -+ UINT8 SetupMode = 1; -+ UINTN DataSize = sizeof(SetupMode); -+ -+ uefi_call_wrapper(RT->GetVariable, 5, L"SetupMode", &GV_GUID, NULL, -+ &DataSize, &SetupMode); -+ -+ return SetupMode; -+} -+ -+int -+variable_is_secureboot(void) -+{ -+ /* return false if variable doesn't exist */ -+ UINT8 SecureBoot = 0; -+ UINTN DataSize; -+ -+ DataSize = sizeof(SecureBoot); -+ uefi_call_wrapper(RT->GetVariable, 5, L"SecureBoot", &GV_GUID, NULL, -+ &DataSize, &SecureBoot); -+ -+ return SecureBoot; -+} -+ -+EFI_STATUS -+variable_enroll_hash(CHAR16 *var, EFI_GUID owner, -+ UINT8 hash[SHA256_DIGEST_SIZE]) -+{ -+ EFI_STATUS status; -+ -+ if (find_in_variable_esl(var, owner, hash, SHA256_DIGEST_SIZE) -+ == EFI_SUCCESS) -+ /* hash already present */ -+ return EFI_ALREADY_STARTED; -+ -+ UINT8 sig[sizeof(EFI_SIGNATURE_LIST) + sizeof(EFI_SIGNATURE_DATA) - 1 + SHA256_DIGEST_SIZE]; -+ EFI_SIGNATURE_LIST *l = (void *)sig; -+ EFI_SIGNATURE_DATA *d = (void *)sig + sizeof(EFI_SIGNATURE_LIST); -+ SetMem(sig, 0, sizeof(sig)); -+ l->SignatureType = EFI_CERT_SHA256_GUID; -+ l->SignatureListSize = sizeof(sig); -+ l->SignatureSize = 16 +32; /* UEFI defined */ -+ CopyMem(&d->SignatureData, hash, SHA256_DIGEST_SIZE); -+ d->SignatureOwner = MOK_OWNER; -+ -+ if (CompareGuid(&owner, &SIG_DB) == 0) -+ status = SetSecureVariable(var, sig, sizeof(sig), owner, -+ EFI_VARIABLE_APPEND_WRITE, 0); -+ else -+ status = uefi_call_wrapper(RT->SetVariable, 5, var, &owner, -+ EFI_VARIABLE_NON_VOLATILE -+ | EFI_VARIABLE_BOOTSERVICE_ACCESS -+ | EFI_VARIABLE_APPEND_WRITE, -+ sizeof(sig), sig); -+ return status; -+} --- -1.8.1.4 - diff --git a/shim-mokmanager-disable-gfx-console.patch b/shim-mokmanager-disable-gfx-console.patch deleted file mode 100644 index 58235bb..0000000 --- a/shim-mokmanager-disable-gfx-console.patch +++ /dev/null @@ -1,149 +0,0 @@ -From c19cef4b4a61c82ba9a2c323659a20ec5d1d7ba2 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Thu, 26 Sep 2013 09:44:50 -0400 -Subject: [PATCH] MokManager needs to disable the graphics console. - -Without this patch, on some machines we never see MokManager's UI. This -protocol has never (I think?) been officially published, and yet I still -have new hardware that needs it. - -If you're looking for a reference, look at: - -EdkCompatibilityPkg/Foundation/Protocol/ConsoleControl/ConsoleControl.c - -in the edk2 tree from Tiano. - -Signed-off-by: Peter Jones ---- - Makefile | 2 +- - MokManager.c | 32 ++++++++++++++++++++++++++++++++ - console_control.h | 44 ++++++++++++++++++++++++++++++++++++++++++++ - 3 files changed, 77 insertions(+), 1 deletion(-) - create mode 100644 console_control.h - -diff --git a/Makefile b/Makefile -index 77f3e52..1e4aed8 100644 ---- a/Makefile -+++ b/Makefile -@@ -37,7 +37,7 @@ OBJS = shim.o netboot.o cert.o dbx.o - KEYS = shim_cert.h ocsp.* ca.* shim.crt shim.csr shim.p12 shim.pem shim.key - SOURCES = shim.c shim.h netboot.c signature.h PeImage.h - MOK_OBJS = MokManager.o PasswordCrypt.o crypt_blowfish.o --MOK_SOURCES = MokManager.c shim.h PasswordCrypt.c PasswordCrypt.h crypt_blowfish.c crypt_blowfish.h -+MOK_SOURCES = MokManager.c shim.h console_control.h PasswordCrypt.c PasswordCrypt.h crypt_blowfish.c crypt_blowfish.h - FALLBACK_OBJS = fallback.o - FALLBACK_SRCS = fallback.c - -diff --git a/MokManager.c b/MokManager.c -index 604129f..01362f2 100644 ---- a/MokManager.c -+++ b/MokManager.c -@@ -6,6 +6,7 @@ - #include "signature.h" - #include "PeImage.h" - #include "PasswordCrypt.h" -+#include "console_control.h" - - #include "include/console.h" - #include "include/simple_file.h" -@@ -1741,6 +1742,34 @@ static EFI_STATUS check_mok_request(EFI_HANDLE image_handle) - return EFI_SUCCESS; - } - -+static VOID setup_console (int text) -+{ -+ EFI_STATUS status; -+ EFI_GUID console_control_guid = EFI_CONSOLE_CONTROL_PROTOCOL_GUID; -+ EFI_CONSOLE_CONTROL_PROTOCOL *concon; -+ static EFI_CONSOLE_CONTROL_SCREEN_MODE mode = -+ EfiConsoleControlScreenGraphics; -+ EFI_CONSOLE_CONTROL_SCREEN_MODE new_mode; -+ -+ status = LibLocateProtocol(&console_control_guid, (VOID **)&concon); -+ if (status != EFI_SUCCESS) -+ return; -+ -+ if (text) { -+ new_mode = EfiConsoleControlScreenText; -+ -+ status = uefi_call_wrapper(concon->GetMode, 4, concon, &mode, -+ 0, 0); -+ /* If that didn't work, assume it's graphics */ -+ if (status != EFI_SUCCESS) -+ mode = EfiConsoleControlScreenGraphics; -+ } else { -+ new_mode = mode; -+ } -+ -+ uefi_call_wrapper(concon->SetMode, 2, concon, new_mode); -+} -+ - static EFI_STATUS setup_rand (void) - { - EFI_TIME time; -@@ -1772,9 +1801,12 @@ EFI_STATUS efi_main (EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *systab) - - InitializeLib(image_handle, systab); - -+ setup_console(1); -+ - setup_rand(); - - efi_status = check_mok_request(image_handle); - -+ setup_console(0); - return efi_status; - } -diff --git a/console_control.h b/console_control.h -new file mode 100644 -index 0000000..5fb8a4a ---- /dev/null -+++ b/console_control.h -@@ -0,0 +1,44 @@ -+#ifndef _SHIM_CONSOLE_CONTROL_H -+#define _SHIM_CONSOLE_CONTROL_H 1 -+ -+#define EFI_CONSOLE_CONTROL_PROTOCOL_GUID \ -+ { 0xf42f7782, 0x12e, 0x4c12, {0x99, 0x56, 0x49, 0xf9, 0x43, 0x4, 0xf7, 0x21} } -+ -+typedef struct _EFI_CONSOLE_CONTROL_PROTOCOL EFI_CONSOLE_CONTROL_PROTOCOL; -+ -+typedef enum { -+ EfiConsoleControlScreenText, -+ EfiConsoleControlScreenGraphics, -+ EfiConsoleControlScreenMaxValue -+} EFI_CONSOLE_CONTROL_SCREEN_MODE; -+ -+typedef -+EFI_STATUS -+(EFIAPI *EFI_CONSOLE_CONTROL_PROTOCOL_GET_MODE) ( -+ IN EFI_CONSOLE_CONTROL_PROTOCOL *This, -+ OUT EFI_CONSOLE_CONTROL_SCREEN_MODE *Mode, -+ OUT BOOLEAN *GopUgaExists, OPTIONAL -+ OUT BOOLEAN *StdInLocked OPTIONAL -+ ); -+ -+typedef -+EFI_STATUS -+(EFIAPI *EFI_CONSOLE_CONTROL_PROTOCOL_SET_MODE) ( -+ IN EFI_CONSOLE_CONTROL_PROTOCOL *This, -+ IN EFI_CONSOLE_CONTROL_SCREEN_MODE Mode -+ ); -+ -+typedef -+EFI_STATUS -+(EFIAPI *EFI_CONSOLE_CONTROL_PROTOCOL_LOCK_STD_IN) ( -+ IN EFI_CONSOLE_CONTROL_PROTOCOL *This, -+ IN CHAR16 *Password -+ ); -+ -+struct _EFI_CONSOLE_CONTROL_PROTOCOL { -+ EFI_CONSOLE_CONTROL_PROTOCOL_GET_MODE GetMode; -+ EFI_CONSOLE_CONTROL_PROTOCOL_SET_MODE SetMode; -+ EFI_CONSOLE_CONTROL_PROTOCOL_LOCK_STD_IN LockStdIn; -+}; -+ -+#endif /* _SHIM_CONSOLE_CONTROL_H */ --- -1.8.1.4 - diff --git a/shim-mokmanager-support-crypt-hash-method.patch b/shim-mokmanager-support-crypt-hash-method.patch deleted file mode 100644 index 374637a..0000000 --- a/shim-mokmanager-support-crypt-hash-method.patch +++ /dev/null @@ -1,1878 +0,0 @@ -From 1c373e8acff0bd08cfd6a596d2df732fd5324627 Mon Sep 17 00:00:00 2001 -From: Gary Ching-Pang Lin -Date: Tue, 15 Jan 2013 18:01:41 +0800 -Subject: [PATCH 1/5] MokManager: support crypt() password hash - -The password format is introduced for the password hash generated by crypt(), -so that the user can import the password hash from /etc/shadow. The packager, -especially those who packages 3rd party drivers, can utilize this feature to -import a 3rd party certificate without interfering the package installation. - -This commit implements the sha256-based crypt() hash function. ---- - Makefile | 6 +-- - MokManager.c | 151 +++++++++++++++++++++++++++++++++++++++++--------------- - PasswordCrypt.c | 124 ++++++++++++++++++++++++++++++++++++++++++++++ - PasswordCrypt.h | 26 ++++++++++ - 4 files changed, 264 insertions(+), 43 deletions(-) - create mode 100644 PasswordCrypt.c - create mode 100644 PasswordCrypt.h - -diff --git a/Makefile b/Makefile -index 50b5898..fa303e4 100644 ---- a/Makefile -+++ b/Makefile -@@ -36,8 +36,8 @@ TARGET = shim.efi MokManager.efi.signed fallback.efi.signed - OBJS = shim.o netboot.o cert.o dbx.o - KEYS = shim_cert.h ocsp.* ca.* shim.crt shim.csr shim.p12 shim.pem shim.key - SOURCES = shim.c shim.h netboot.c signature.h PeImage.h --MOK_OBJS = MokManager.o --MOK_SOURCES = MokManager.c shim.h -+MOK_OBJS = MokManager.o PasswordCrypt.o -+MOK_SOURCES = MokManager.c shim.h PasswordCrypt.c PasswordCrypt.h - FALLBACK_OBJS = fallback.o - FALLBACK_SRCS = fallback.c - -@@ -76,7 +76,7 @@ fallback.o: $(FALLBACK_SRCS) - fallback.so: $(FALLBACK_OBJS) - $(LD) -o $@ $(LDFLAGS) $^ $(EFI_LIBS) - --MokManager.o: $(SOURCES) -+MokManager.o: $(MOK_SOURCES) - - MokManager.so: $(MOK_OBJS) Cryptlib/libcryptlib.a Cryptlib/OpenSSL/libopenssl.a lib/lib.a - $(LD) -o $@ $(LDFLAGS) $^ $(EFI_LIBS) lib/lib.a -diff --git a/MokManager.c b/MokManager.c -index 60e799a..6cf24e6 100644 ---- a/MokManager.c -+++ b/MokManager.c -@@ -5,13 +5,14 @@ - #include "shim.h" - #include "signature.h" - #include "PeImage.h" -+#include "PasswordCrypt.h" - - #include "include/console.h" - #include "include/simple_file.h" - --#define PASSWORD_MAX 16 --#define PASSWORD_MIN 8 --#define SB_PASSWORD_LEN 8 -+#define PASSWORD_MAX 256 -+#define PASSWORD_MIN 1 -+#define SB_PASSWORD_LEN 16 - - #ifndef SHIM_VENDOR - #define SHIM_VENDOR L"Shim" -@@ -28,7 +29,7 @@ typedef struct { - typedef struct { - UINT32 MokSBState; - UINT32 PWLen; -- CHAR16 Password[PASSWORD_MAX]; -+ CHAR16 Password[SB_PASSWORD_LEN]; - } __attribute__ ((packed)) MokSBvar; - - static EFI_STATUS get_variable (CHAR16 *name, EFI_GUID guid, UINT32 *attributes, -@@ -571,8 +572,8 @@ static UINT8 get_line (UINT32 *length, CHAR16 *line, UINT32 line_max, UINT8 show - return 1; - } - --static EFI_STATUS compute_pw_hash (void *MokNew, UINTN MokNewSize, CHAR16 *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; - unsigned int ctxsize; -@@ -592,15 +593,15 @@ static EFI_STATUS compute_pw_hash (void *MokNew, UINTN MokNewSize, CHAR16 *passw - goto done; - } - -- if (MokNew && MokNewSize) { -- if (!(Sha256Update(ctx, MokNew, MokNewSize))) { -+ if (Data && DataSize) { -+ if (!(Sha256Update(ctx, Data, DataSize))) { - console_notify(L"Unable to generate hash"); - status = EFI_OUT_OF_RESOURCES; - goto done; - } - } - -- if (!(Sha256Update(ctx, password, pw_length * sizeof(CHAR16)))) { -+ if (!(Sha256Update(ctx, password, pw_length))) { - console_notify(L"Unable to generate hash"); - status = EFI_OUT_OF_RESOURCES; - goto done; -@@ -617,15 +618,34 @@ done: - return status; - } - --static EFI_STATUS match_password (void *Data, UINTN DataSize, -- UINT8 auth[SHA256_DIGEST_SIZE], -- CHAR16 *prompt) -+static EFI_STATUS match_password (PASSWORD_CRYPT *pw_crypt, -+ void *Data, UINTN DataSize, -+ UINT8 *auth, CHAR16 *prompt) - { -- EFI_STATUS efi_status; -+ EFI_STATUS status; - UINT8 hash[SHA256_DIGEST_SIZE]; -+ UINT8 *auth_hash; -+ UINT32 auth_size; - CHAR16 password[PASSWORD_MAX]; - UINT32 pw_length; - UINT8 fail_count = 0; -+ int i; -+ -+ if (pw_crypt) { -+ /* -+ * Only support sha256 now -+ */ -+ if(pw_crypt->method != SHA256_BASED) -+ return EFI_INVALID_PARAMETER; -+ auth_hash = pw_crypt->hash; -+ /* FIXME assign auth_size according to pw_crypt->method */ -+ auth_size = SHA256_DIGEST_SIZE; -+ } else if (auth) { -+ auth_hash = auth; -+ auth_size = SHA256_DIGEST_SIZE; -+ } else { -+ return EFI_INVALID_PARAMETER; -+ } - - while (fail_count < 3) { - if (prompt) { -@@ -641,16 +661,30 @@ static EFI_STATUS match_password (void *Data, UINTN DataSize, - continue; - } - -- efi_status = compute_pw_hash(Data, DataSize, password, -- pw_length, hash); -+ /* -+ * Compute password hash -+ */ -+ if (pw_crypt) { -+ char pw_ascii[PASSWORD_MAX + 1]; -+ for (i = 0; i < pw_length; i++) -+ pw_ascii[i] = (char)password[i]; -+ pw_ascii[pw_length] = '\0'; - -- if (efi_status != EFI_SUCCESS) { -+ 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); -+ } -+ if (status != EFI_SUCCESS) { - Print(L"Unable to generate password hash\n"); - fail_count++; - continue; - } - -- if (CompareMem(auth, hash, SHA256_DIGEST_SIZE) != 0) { -+ if (CompareMem(auth_hash, hash, auth_size) != 0) { - Print(L"Password doesn't match\n"); - fail_count++; - continue; -@@ -669,23 +703,29 @@ static EFI_STATUS store_keys (void *MokNew, UINTN MokNewSize, int authenticate) - { - EFI_GUID shim_lock_guid = SHIM_LOCK_GUID; - EFI_STATUS efi_status; -- UINT8 auth[SHA256_DIGEST_SIZE]; -- UINTN auth_size; -+ UINT8 auth[PASSWORD_CRYPT_SIZE]; -+ UINTN auth_size = PASSWORD_CRYPT_SIZE; - UINT32 attributes; - - if (authenticate) { -- auth_size = SHA256_DIGEST_SIZE; - 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) { -+ if (efi_status != EFI_SUCCESS || -+ (auth_size != SHA256_DIGEST_SIZE && -+ auth_size != PASSWORD_CRYPT_SIZE)) { - console_error(L"Failed to get MokAuth", efi_status); - return efi_status; - } - -- efi_status = match_password(MokNew, MokNewSize, auth, NULL); -+ if (auth_size == PASSWORD_CRYPT_SIZE) { -+ 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) - return EFI_ACCESS_DENIED; - } -@@ -839,8 +879,8 @@ static EFI_STATUS delete_keys (void *MokDel, UINTN MokDelSize) - { - EFI_GUID shim_lock_guid = SHIM_LOCK_GUID; - EFI_STATUS efi_status; -- UINT8 auth[SHA256_DIGEST_SIZE]; -- UINTN auth_size = SHA256_DIGEST_SIZE; -+ UINT8 auth[PASSWORD_CRYPT_SIZE]; -+ UINTN auth_size = PASSWORD_CRYPT_SIZE; - UINT32 attributes; - void *MokListData = NULL; - UINTN MokListDataSize = 0; -@@ -852,12 +892,18 @@ static EFI_STATUS delete_keys (void *MokDel, UINTN MokDelSize) - &shim_lock_guid, - &attributes, &auth_size, auth); - -- if (efi_status != EFI_SUCCESS || auth_size != SHA256_DIGEST_SIZE) { -+ if (efi_status != EFI_SUCCESS || -+ (auth_size != SHA256_DIGEST_SIZE && auth_size != PASSWORD_CRYPT_SIZE)) { - console_error(L"Failed to get MokDelAuth", efi_status); - return efi_status; - } - -- efi_status = match_password(MokDel, MokDelSize, auth, NULL); -+ if (auth_size == PASSWORD_CRYPT_SIZE) { -+ efi_status = match_password((PASSWORD_CRYPT *)auth, NULL, 0, -+ NULL, NULL); -+ } else { -+ efi_status = match_password(NULL, MokDel, MokDelSize, auth, NULL); -+ } - if (efi_status != EFI_SUCCESS) - return EFI_ACCESS_DENIED; - -@@ -1030,18 +1076,27 @@ static INTN mok_sb_prompt (void *MokSB, UINTN MokSBSize) { - static INTN mok_pw_prompt (void *MokPW, UINTN MokPWSize) { - EFI_GUID shim_lock_guid = SHIM_LOCK_GUID; - EFI_STATUS efi_status; -- UINT8 hash[SHA256_DIGEST_SIZE]; -+ UINT8 hash[PASSWORD_CRYPT_SIZE]; -+ UINT8 clear = 0; - -- if (MokPWSize != SHA256_DIGEST_SIZE) { -+ if (MokPWSize != SHA256_DIGEST_SIZE && MokPWSize != PASSWORD_CRYPT_SIZE) { - console_notify(L"Invalid MokPW variable contents"); - return -1; - } - - uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut); - -- SetMem(hash, SHA256_DIGEST_SIZE, 0); -+ SetMem(hash, PASSWORD_CRYPT_SIZE, 0); -+ -+ if (MokPWSize == PASSWORD_CRYPT_SIZE) { -+ if (CompareMem(MokPW, hash, PASSWORD_CRYPT_SIZE) == 0) -+ clear = 1; -+ } else { -+ if (CompareMem(MokPW, hash, SHA256_DIGEST_SIZE) == 0) -+ clear = 1; -+ } - -- if (CompareMem(MokPW, hash, SHA256_DIGEST_SIZE) == 0) { -+ if (clear) { - if (console_yes_no((CHAR16 *[]){L"Clear MOK password?", NULL}) == 0) - return 0; - -@@ -1050,7 +1105,14 @@ static INTN mok_pw_prompt (void *MokPW, UINTN MokPWSize) { - return 0; - } - -- efi_status = match_password(NULL, 0, MokPW, L"Confirm MOK passphrase: "); -+ if (MokPWSize == PASSWORD_CRYPT_SIZE) { -+ 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) { - console_notify(L"Password limit reached"); - return -1; -@@ -1265,8 +1327,8 @@ static BOOLEAN verify_pw(void) - { - EFI_GUID shim_lock_guid = SHIM_LOCK_GUID; - EFI_STATUS efi_status; -- UINT8 pwhash[SHA256_DIGEST_SIZE]; -- UINTN size = SHA256_DIGEST_SIZE; -+ UINT8 pwhash[PASSWORD_CRYPT_SIZE]; -+ UINTN size = PASSWORD_CRYPT_SIZE; - UINT32 attributes; - - efi_status = uefi_call_wrapper(RT->GetVariable, 5, L"MokPWStore", -@@ -1278,7 +1340,8 @@ static BOOLEAN verify_pw(void) - * 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_status != EFI_SUCCESS || -+ (size != SHA256_DIGEST_SIZE && size != PASSWORD_CRYPT_SIZE)) - return TRUE; - - if (attributes & EFI_VARIABLE_RUNTIME_ACCESS) -@@ -1286,7 +1349,13 @@ static BOOLEAN verify_pw(void) - - uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut); - -- efi_status = match_password(NULL, 0, pwhash, L"Enter MOK password: "); -+ if (size == PASSWORD_CRYPT_SIZE) { -+ 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) { - console_notify(L"Password limit reached"); - return FALSE; -@@ -1320,8 +1389,8 @@ static EFI_STATUS enter_mok_menu(EFI_HANDLE image_handle, - UINTN menucount = 3, i = 0; - EFI_STATUS efi_status; - EFI_GUID shim_lock_guid = SHIM_LOCK_GUID; -- UINT8 auth[SHA256_DIGEST_SIZE]; -- UINTN auth_size = SHA256_DIGEST_SIZE; -+ UINT8 auth[PASSWORD_CRYPT_SIZE]; -+ UINTN auth_size = PASSWORD_CRYPT_SIZE; - UINT32 attributes; - EFI_STATUS ret = EFI_SUCCESS; - -@@ -1332,14 +1401,16 @@ static EFI_STATUS enter_mok_menu(EFI_HANDLE image_handle, - &shim_lock_guid, - &attributes, &auth_size, auth); - -- if ((efi_status == EFI_SUCCESS) && (auth_size == SHA256_DIGEST_SIZE)) -+ if ((efi_status == EFI_SUCCESS) && -+ (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)) -+ if ((efi_status == EFI_SUCCESS) && -+ (auth_size == SHA256_DIGEST_SIZE || auth_size == PASSWORD_CRYPT_SIZE)) - MokDelAuth = 1; - - if (MokNew || MokAuth) -diff --git a/PasswordCrypt.c b/PasswordCrypt.c -new file mode 100644 -index 0000000..bde23ed ---- /dev/null -+++ b/PasswordCrypt.c -@@ -0,0 +1,124 @@ -+#include -+#include -+#include -+#include -+#include "PasswordCrypt.h" -+ -+static EFI_STATUS sha256_crypt (const char *key, UINT32 key_len, -+ const char *salt, UINT32 salt_size, -+ const UINT32 rounds, UINT8 *hash) -+{ -+ SHA256_CTX ctx, alt_ctx; -+ UINT8 alt_result[SHA256_DIGEST_SIZE]; -+ UINT8 tmp_result[SHA256_DIGEST_SIZE]; -+ UINT8 *cp, *p_bytes, *s_bytes; -+ UINTN cnt; -+ -+ SHA256_Init(&ctx); -+ SHA256_Update(&ctx, key, key_len); -+ SHA256_Update(&ctx, salt, salt_size); -+ -+ SHA256_Init(&alt_ctx); -+ SHA256_Update(&alt_ctx, key, key_len); -+ SHA256_Update(&alt_ctx, salt, salt_size); -+ SHA256_Update(&alt_ctx, key, key_len); -+ SHA256_Final(alt_result, &alt_ctx); -+ -+ for (cnt = key_len; cnt > 32; cnt -= 32) -+ SHA256_Update(&ctx, alt_result, 32); -+ SHA256_Update(&ctx, alt_result, cnt); -+ -+ for (cnt = key_len; cnt > 0; cnt >>= 1) { -+ if ((cnt & 1) != 0) { -+ SHA256_Update(&ctx, alt_result, 32); -+ } else { -+ SHA256_Update(&ctx, key, key_len); -+ } -+ } -+ SHA256_Final(alt_result, &ctx); -+ -+ SHA256_Init(&alt_ctx); -+ for (cnt = 0; cnt < key_len; ++cnt) -+ SHA256_Update(&alt_ctx, key, key_len); -+ SHA256_Final(tmp_result, &alt_ctx); -+ -+ cp = p_bytes = AllocatePool(key_len); -+ for (cnt = key_len; cnt >= 32; cnt -= 32) { -+ CopyMem(cp, tmp_result, 32); -+ cp += 32; -+ } -+ CopyMem(cp, tmp_result, cnt); -+ -+ SHA256_Init(&alt_ctx); -+ for (cnt = 0; cnt < 16 + alt_result[0]; ++cnt) -+ SHA256_Update(&alt_ctx, salt, salt_size); -+ SHA256_Final(tmp_result, &alt_ctx); -+ -+ cp = s_bytes = AllocatePool(salt_size); -+ for (cnt = salt_size; cnt >= 32; cnt -= 32) { -+ CopyMem(cp, tmp_result, 32); -+ cp += 32; -+ } -+ CopyMem(cp, tmp_result, cnt); -+ -+ for (cnt = 0; cnt < rounds; ++cnt) { -+ SHA256_Init(&ctx); -+ -+ if ((cnt & 1) != 0) -+ SHA256_Update(&ctx, p_bytes, key_len); -+ else -+ SHA256_Update(&ctx, alt_result, 32); -+ -+ if (cnt % 3 != 0) -+ SHA256_Update(&ctx, s_bytes, salt_size); -+ -+ if (cnt % 7 != 0) -+ SHA256_Update(&ctx, p_bytes, key_len); -+ -+ if ((cnt & 1) != 0) -+ SHA256_Update(&ctx, alt_result, 32); -+ else -+ SHA256_Update(&ctx, p_bytes, key_len); -+ -+ SHA256_Final(alt_result, &ctx); -+ } -+ -+ CopyMem(hash, alt_result, SHA256_DIGEST_SIZE); -+ -+ FreePool(p_bytes); -+ FreePool(s_bytes); -+ -+ return EFI_SUCCESS; -+} -+ -+EFI_STATUS password_crypt (const char *password, UINT32 pw_length, -+ const PASSWORD_CRYPT *pw_crypt, UINT8 *hash) -+{ -+ EFI_STATUS status; -+ -+ if (!pw_crypt) -+ return EFI_INVALID_PARAMETER; -+ -+ switch (pw_crypt->method) { -+ case TRANDITIONAL_DES: -+ case EXTEND_BSDI_DES: -+ case MD5_BASED: -+ /* TODO unsupported */ -+ status = EFI_UNSUPPORTED; -+ break; -+ case SHA256_BASED: -+ status = sha256_crypt(password, pw_length, (char *)pw_crypt->salt, -+ pw_crypt->salt_size, pw_crypt->iter_count, -+ hash); -+ break; -+ case SHA512_BASED: -+ case BLOWFISH_BASED: -+ /* TODO unsupported */ -+ status = EFI_UNSUPPORTED; -+ break; -+ default: -+ return EFI_INVALID_PARAMETER; -+ } -+ -+ return status; -+} -diff --git a/PasswordCrypt.h b/PasswordCrypt.h -new file mode 100644 -index 0000000..c9e377a ---- /dev/null -+++ b/PasswordCrypt.h -@@ -0,0 +1,26 @@ -+#ifndef __PASSWORD_CRYPT_H__ -+#define __PASSWORD_CRYPT_H__ -+ -+enum HashMethod { -+ TRANDITIONAL_DES = 0, -+ EXTEND_BSDI_DES, -+ MD5_BASED, -+ SHA256_BASED, -+ SHA512_BASED, -+ BLOWFISH_BASED -+}; -+ -+typedef struct { -+ UINT16 method; -+ UINT64 iter_count; -+ UINT16 salt_size; -+ UINT8 salt[32]; -+ UINT8 hash[128]; -+} __attribute__ ((packed)) PASSWORD_CRYPT; -+ -+#define PASSWORD_CRYPT_SIZE sizeof(PASSWORD_CRYPT) -+ -+EFI_STATUS password_crypt (const char *password, UINT32 pw_length, -+ const PASSWORD_CRYPT *pw_hash, UINT8 *hash); -+ -+#endif /* __PASSWORD_CRYPT_H__ */ --- -1.8.1.4 - - -From 7c52801530ff684044e97e4070b91816d75a5089 Mon Sep 17 00:00:00 2001 -From: Gary Ching-Pang Lin -Date: Thu, 24 Jan 2013 18:24:49 +0800 -Subject: [PATCH 2/5] MokManager: support SHA512-based crypt() hash - ---- - Cryptlib/OpenSSL/Makefile | 2 +- - MokManager.c | 12 ++--- - PasswordCrypt.c | 114 ++++++++++++++++++++++++++++++++++++++++++++++ - PasswordCrypt.h | 1 + - 4 files changed, 120 insertions(+), 9 deletions(-) - -diff --git a/Cryptlib/OpenSSL/Makefile b/Cryptlib/OpenSSL/Makefile -index 1960b6b..f8ab841 100644 ---- a/Cryptlib/OpenSSL/Makefile -+++ b/Cryptlib/OpenSSL/Makefile -@@ -10,7 +10,7 @@ LIB_GCC = $(shell $(CC) -print-libgcc-file-name) - EFI_LIBS = -lefi -lgnuefi $(LIB_GCC) - - CFLAGS = -ggdb -O0 -I. -I.. -I../Include/ -Icrypto -fno-stack-protector -fno-strict-aliasing -fpic -fshort-wchar -nostdinc -mno-mmx -mno-sse -mno-red-zone -maccumulate-outgoing-args \ -- -Wall $(EFI_INCLUDES) -DOPENSSL_SYSNAME_UWIN -DOPENSSL_SYS_UEFI -DL_ENDIAN -DSIXTY_FOUR_BIT_LONG -D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE -DOPENSSL_NO_CAMELLIA -DOPENSSL_NO_SEED -DOPENSSL_NO_RC5 -DOPENSSL_NO_MDC2 -DOPENSSL_NO_SOCK -DOPENSSL_NO_CMS -DOPENSSL_NO_JPAKE -DOPENSSL_NO_CAPIENG -DOPENSSL_NO_ERR -DOPENSSL_NO_KRB5 -DOPENSSL_NO_DYNAMIC_ENGINE -DGETPID_IS_MEANINGLESS -DOPENSSL_NO_STDIO -DOPENSSL_NO_FP_API -DOPENSSL_NO_DGRAM -DOPENSSL_NO_SHA0 -DOPENSSL_NO_SHA512 -DOPENSSL_NO_LHASH -DOPENSSL_NO_HW -DOPENSSL_NO_OCSP -DOPENSSL_NO_LOCKING -DOPENSSL_NO_DEPRECATED -DOPENSSL_SMALL_FOOTPRINT -DPEDANTIC -+ -Wall $(EFI_INCLUDES) -DOPENSSL_SYSNAME_UWIN -DOPENSSL_SYS_UEFI -DL_ENDIAN -DSIXTY_FOUR_BIT_LONG -D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE -DOPENSSL_NO_CAMELLIA -DOPENSSL_NO_SEED -DOPENSSL_NO_RC5 -DOPENSSL_NO_MDC2 -DOPENSSL_NO_SOCK -DOPENSSL_NO_CMS -DOPENSSL_NO_JPAKE -DOPENSSL_NO_CAPIENG -DOPENSSL_NO_ERR -DOPENSSL_NO_KRB5 -DOPENSSL_NO_DYNAMIC_ENGINE -DGETPID_IS_MEANINGLESS -DOPENSSL_NO_STDIO -DOPENSSL_NO_FP_API -DOPENSSL_NO_DGRAM -DOPENSSL_NO_SHA0 -DOPENSSL_NO_LHASH -DOPENSSL_NO_HW -DOPENSSL_NO_OCSP -DOPENSSL_NO_LOCKING -DOPENSSL_NO_DEPRECATED -DOPENSSL_SMALL_FOOTPRINT -DPEDANTIC - ifeq ($(ARCH),x86_64) - CFLAGS += -DEFI_FUNCTION_WRAPPER -DGNU_EFI_USE_MS_ABI - endif -diff --git a/MokManager.c b/MokManager.c -index 6cf24e6..b05a52f 100644 ---- a/MokManager.c -+++ b/MokManager.c -@@ -623,7 +623,7 @@ static EFI_STATUS match_password (PASSWORD_CRYPT *pw_crypt, - UINT8 *auth, CHAR16 *prompt) - { - EFI_STATUS status; -- UINT8 hash[SHA256_DIGEST_SIZE]; -+ UINT8 hash[128]; - UINT8 *auth_hash; - UINT32 auth_size; - CHAR16 password[PASSWORD_MAX]; -@@ -632,14 +632,10 @@ static EFI_STATUS match_password (PASSWORD_CRYPT *pw_crypt, - int i; - - if (pw_crypt) { -- /* -- * Only support sha256 now -- */ -- if(pw_crypt->method != SHA256_BASED) -- return EFI_INVALID_PARAMETER; - auth_hash = pw_crypt->hash; -- /* FIXME assign auth_size according to pw_crypt->method */ -- auth_size = SHA256_DIGEST_SIZE; -+ auth_size = get_hash_size (pw_crypt->method); -+ if (auth_size == 0) -+ return EFI_INVALID_PARAMETER; - } else if (auth) { - auth_hash = auth; - auth_size = SHA256_DIGEST_SIZE; -diff --git a/PasswordCrypt.c b/PasswordCrypt.c -index bde23ed..a62512e 100644 ---- a/PasswordCrypt.c -+++ b/PasswordCrypt.c -@@ -2,8 +2,30 @@ - #include - #include - #include -+#include - #include "PasswordCrypt.h" - -+ -+UINT16 get_hash_size (const UINT16 method) -+{ -+ switch (method) { -+ case TRANDITIONAL_DES: -+ return 64 / 8; /* per "man crypt" */ -+ case EXTEND_BSDI_DES: -+ return 64 / 8; /* per "man crypt" */ -+ case MD5_BASED: -+ return MD5_DIGEST_LENGTH; -+ case SHA256_BASED: -+ return SHA256_DIGEST_LENGTH; -+ case SHA512_BASED: -+ return SHA512_DIGEST_LENGTH; -+ case BLOWFISH_BASED: -+ return 184 / 8; /* per "man crypt" */ -+ } -+ -+ return 0; -+} -+ - static EFI_STATUS sha256_crypt (const char *key, UINT32 key_len, - const char *salt, UINT32 salt_size, - const UINT32 rounds, UINT8 *hash) -@@ -91,6 +113,94 @@ static EFI_STATUS sha256_crypt (const char *key, UINT32 key_len, - return EFI_SUCCESS; - } - -+static EFI_STATUS sha512_crypt (const char *key, UINT32 key_len, -+ const char *salt, UINT32 salt_size, -+ const UINT32 rounds, UINT8 *hash) -+{ -+ SHA512_CTX ctx, alt_ctx; -+ UINT8 alt_result[SHA512_DIGEST_LENGTH]; -+ UINT8 tmp_result[SHA512_DIGEST_LENGTH]; -+ UINT8 *cp, *p_bytes, *s_bytes; -+ UINTN cnt; -+ -+ SHA512_Init(&ctx); -+ SHA512_Update(&ctx, key, key_len); -+ SHA512_Update(&ctx, salt, salt_size); -+ -+ SHA512_Init(&alt_ctx); -+ SHA512_Update(&alt_ctx, key, key_len); -+ SHA512_Update(&alt_ctx, salt, salt_size); -+ SHA512_Update(&alt_ctx, key, key_len); -+ -+ SHA512_Final(alt_result, &alt_ctx); -+ -+ for (cnt = key_len; cnt > 64; cnt -= 64) -+ SHA512_Update(&ctx, alt_result, 64); -+ SHA512_Update(&ctx, alt_result, cnt); -+ -+ for (cnt = key_len; cnt > 0; cnt >>= 1) { -+ if ((cnt & 1) != 0) { -+ SHA512_Update(&ctx, alt_result, 64); -+ } else { -+ SHA512_Update(&ctx, key, key_len); -+ } -+ } -+ SHA512_Final(alt_result, &ctx); -+ -+ SHA512_Init(&alt_ctx); -+ for (cnt = 0; cnt < key_len; ++cnt) -+ SHA512_Update(&alt_ctx, key, key_len); -+ SHA512_Final(tmp_result, &alt_ctx); -+ -+ cp = p_bytes = AllocatePool(key_len); -+ for (cnt = key_len; cnt >= 64; cnt -= 64) { -+ CopyMem(cp, tmp_result, 64); -+ cp += 64; -+ } -+ CopyMem(cp, tmp_result, cnt); -+ -+ SHA512_Init(&alt_ctx); -+ for (cnt = 0; cnt < 16 + alt_result[0]; ++cnt) -+ SHA512_Update(&alt_ctx, salt, salt_size); -+ SHA512_Final(tmp_result, &alt_ctx); -+ -+ cp = s_bytes = AllocatePool(salt_size); -+ for (cnt = salt_size; cnt >= 64; cnt -= 64) { -+ CopyMem(cp, tmp_result, 64); -+ cp += 64; -+ } -+ CopyMem(cp, tmp_result, cnt); -+ -+ for (cnt = 0; cnt < rounds; ++cnt) { -+ SHA512_Init(&ctx); -+ -+ if ((cnt & 1) != 0) -+ SHA512_Update(&ctx, p_bytes, key_len); -+ else -+ SHA512_Update(&ctx, alt_result, 64); -+ -+ if (cnt % 3 != 0) -+ SHA512_Update(&ctx, s_bytes, salt_size); -+ -+ if (cnt % 7 != 0) -+ SHA512_Update(&ctx, p_bytes, key_len); -+ -+ if ((cnt & 1) != 0) -+ SHA512_Update(&ctx, alt_result, 64); -+ else -+ SHA512_Update(&ctx, p_bytes, key_len); -+ -+ SHA512_Final(alt_result, &ctx); -+ } -+ -+ CopyMem(hash, alt_result, SHA512_DIGEST_LENGTH); -+ -+ FreePool(p_bytes); -+ FreePool(s_bytes); -+ -+ return EFI_SUCCESS; -+} -+ - EFI_STATUS password_crypt (const char *password, UINT32 pw_length, - const PASSWORD_CRYPT *pw_crypt, UINT8 *hash) - { -@@ -112,6 +222,10 @@ EFI_STATUS password_crypt (const char *password, UINT32 pw_length, - hash); - break; - case SHA512_BASED: -+ status = sha512_crypt(password, pw_length, (char *)pw_crypt->salt, -+ pw_crypt->salt_size, pw_crypt->iter_count, -+ hash); -+ break; - case BLOWFISH_BASED: - /* TODO unsupported */ - status = EFI_UNSUPPORTED; -diff --git a/PasswordCrypt.h b/PasswordCrypt.h -index c9e377a..144bf84 100644 ---- a/PasswordCrypt.h -+++ b/PasswordCrypt.h -@@ -22,5 +22,6 @@ typedef struct { - - 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__ */ --- -1.8.1.4 - - -From df4644c036ff9d02cbcc08b5902eccb58e8bc305 Mon Sep 17 00:00:00 2001 -From: Gary Ching-Pang Lin -Date: Fri, 17 May 2013 15:10:57 +0800 -Subject: [PATCH 3/5] MokManager: support blowfish-based crypt() hash - ---- - Makefile | 4 +- - PasswordCrypt.c | 26 +- - crypt_blowfish.c | 822 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ - crypt_blowfish.h | 22 ++ - 4 files changed, 869 insertions(+), 5 deletions(-) - create mode 100644 crypt_blowfish.c - create mode 100644 crypt_blowfish.h - -diff --git a/Makefile b/Makefile -index fa303e4..77f3e52 100644 ---- a/Makefile -+++ b/Makefile -@@ -36,8 +36,8 @@ TARGET = shim.efi MokManager.efi.signed fallback.efi.signed - OBJS = shim.o netboot.o cert.o dbx.o - KEYS = shim_cert.h ocsp.* ca.* shim.crt shim.csr shim.p12 shim.pem shim.key - SOURCES = shim.c shim.h netboot.c signature.h PeImage.h --MOK_OBJS = MokManager.o PasswordCrypt.o --MOK_SOURCES = MokManager.c shim.h PasswordCrypt.c PasswordCrypt.h -+MOK_OBJS = MokManager.o PasswordCrypt.o crypt_blowfish.o -+MOK_SOURCES = MokManager.c shim.h PasswordCrypt.c PasswordCrypt.h crypt_blowfish.c crypt_blowfish.h - FALLBACK_OBJS = fallback.o - FALLBACK_SRCS = fallback.c - -diff --git a/PasswordCrypt.c b/PasswordCrypt.c -index a62512e..38b980f 100644 ---- a/PasswordCrypt.c -+++ b/PasswordCrypt.c -@@ -4,7 +4,9 @@ - #include - #include - #include "PasswordCrypt.h" -+#include "crypt_blowfish.h" - -+#define BLOWFISH_HASH_SIZE 31 /* 184/6+1 */ - - UINT16 get_hash_size (const UINT16 method) - { -@@ -20,7 +22,7 @@ UINT16 get_hash_size (const UINT16 method) - case SHA512_BASED: - return SHA512_DIGEST_LENGTH; - case BLOWFISH_BASED: -- return 184 / 8; /* per "man crypt" */ -+ return BLOWFISH_HASH_SIZE; - } - - return 0; -@@ -201,6 +203,21 @@ static EFI_STATUS sha512_crypt (const char *key, UINT32 key_len, - return EFI_SUCCESS; - } - -+#define BF_RESULT_SIZE (7 + 22 + 31 + 1) -+ -+static EFI_STATUS blowfish_crypt (const char *key, const char *salt, UINT8 *hash) -+{ -+ char *retval, result[BF_RESULT_SIZE]; -+ -+ retval = crypt_blowfish_rn (key, salt, result, BF_RESULT_SIZE); -+ if (!retval) -+ return EFI_UNSUPPORTED; -+ -+ CopyMem(hash, result + 7 + 22, BF_RESULT_SIZE); -+ -+ return EFI_SUCCESS; -+} -+ - EFI_STATUS password_crypt (const char *password, UINT32 pw_length, - const PASSWORD_CRYPT *pw_crypt, UINT8 *hash) - { -@@ -227,8 +244,11 @@ EFI_STATUS password_crypt (const char *password, UINT32 pw_length, - hash); - break; - case BLOWFISH_BASED: -- /* TODO unsupported */ -- status = EFI_UNSUPPORTED; -+ if (pw_crypt->salt_size != (7 + 22 + 1)) { -+ status = EFI_INVALID_PARAMETER; -+ break; -+ } -+ status = blowfish_crypt(password, (char *)pw_crypt->salt, hash); - break; - default: - return EFI_INVALID_PARAMETER; -diff --git a/crypt_blowfish.c b/crypt_blowfish.c -new file mode 100644 -index 0000000..366a81a ---- /dev/null -+++ b/crypt_blowfish.c -@@ -0,0 +1,822 @@ -+/* -+ * The crypt_blowfish homepage is: -+ * -+ * http://www.openwall.com/crypt/ -+ * -+ * This code comes from John the Ripper password cracker, with reentrant -+ * and crypt(3) interfaces added, but optimizations specific to password -+ * cracking removed. -+ * -+ * Written by Solar Designer in 1998-2011. -+ * No copyright is claimed, and the software is hereby placed in the public -+ * domain. In case this attempt to disclaim copyright and place the software -+ * in the public domain is deemed null and void, then the software is -+ * Copyright (c) 1998-2011 Solar Designer and it is hereby released to the -+ * general public under the following terms: -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted. -+ * -+ * There's ABSOLUTELY NO WARRANTY, express or implied. -+ * -+ * It is my intent that you should be able to use this on your system, -+ * as part of a software package, or anywhere else to improve security, -+ * ensure compatibility, or for any other purpose. I would appreciate -+ * it if you give credit where it is due and keep your modifications in -+ * the public domain as well, but I don't require that in order to let -+ * you place this code and any modifications you make under a license -+ * of your choice. -+ * -+ * This implementation is mostly compatible with OpenBSD's bcrypt.c (prefix -+ * "$2a$") by Niels Provos , and uses some of his -+ * ideas. The password hashing algorithm was designed by David Mazieres -+ * . For more information on the level of compatibility, -+ * prefer refer to the comments in BF_set_key() below and to the included -+ * crypt(3) man page. -+ * -+ * There's a paper on the algorithm that explains its design decisions: -+ * -+ * http://www.usenix.org/events/usenix99/provos.html -+ * -+ * Some of the tricks in BF_ROUND might be inspired by Eric Young's -+ * Blowfish library (I can't be sure if I would think of something if I -+ * hadn't seen his code). -+ */ -+ -+#include -+#include -+ -+/* Just to make sure the prototypes match the actual definitions */ -+#include "crypt_blowfish.h" -+ -+typedef unsigned int BF_word; -+typedef signed int BF_word_signed; -+ -+/* Number of Blowfish rounds, this is also hardcoded into a few places */ -+#define BF_N 16 -+ -+typedef BF_word BF_key[BF_N + 2]; -+ -+typedef struct { -+ BF_word S[4][0x100]; -+ BF_key P; -+} BF_ctx; -+ -+/* -+ * Magic IV for 64 Blowfish encryptions that we do at the end. -+ * The string is "OrpheanBeholderScryDoubt" on big-endian. -+ */ -+static BF_word BF_magic_w[6] = { -+ 0x4F727068, 0x65616E42, 0x65686F6C, -+ 0x64657253, 0x63727944, 0x6F756274 -+}; -+ -+/* -+ * P-box and S-box tables initialized with digits of Pi. -+ */ -+static BF_ctx BF_init_state = { -+ { -+ { -+ 0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, -+ 0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99, -+ 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16, -+ 0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e, -+ 0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee, -+ 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013, -+ 0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef, -+ 0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e, -+ 0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60, -+ 0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440, -+ 0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce, -+ 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a, -+ 0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e, -+ 0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677, -+ 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193, -+ 0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032, -+ 0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88, -+ 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239, -+ 0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e, -+ 0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0, -+ 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3, -+ 0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98, -+ 0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88, -+ 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe, -+ 0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6, -+ 0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d, -+ 0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b, -+ 0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7, -+ 0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x04c006ba, -+ 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463, -+ 0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f, -+ 0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09, -+ 0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3, -+ 0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb, -+ 0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279, -+ 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8, -+ 0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab, -+ 0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82, -+ 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db, -+ 0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573, -+ 0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0, -+ 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b, -+ 0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790, -+ 0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8, -+ 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4, -+ 0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0, -+ 0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7, -+ 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c, -+ 0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad, -+ 0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1, -+ 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299, -+ 0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9, -+ 0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477, -+ 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf, -+ 0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49, -+ 0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af, -+ 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa, -+ 0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5, -+ 0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41, -+ 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915, -+ 0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400, -+ 0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915, -+ 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664, -+ 0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a -+ }, { -+ 0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623, -+ 0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266, -+ 0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1, -+ 0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e, -+ 0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6, -+ 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1, -+ 0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e, -+ 0x09686b3f, 0x3ebaefc9, 0x3c971814, 0x6b6a70a1, -+ 0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737, -+ 0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8, -+ 0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff, -+ 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd, -+ 0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701, -+ 0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7, -+ 0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41, -+ 0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331, -+ 0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf, -+ 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af, -+ 0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e, -+ 0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87, -+ 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c, -+ 0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2, -+ 0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16, -+ 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd, -+ 0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b, -+ 0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509, -+ 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e, -+ 0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3, -+ 0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f, -+ 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a, -+ 0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4, -+ 0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960, -+ 0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66, -+ 0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28, -+ 0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802, -+ 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84, -+ 0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510, -+ 0x13cca830, 0xeb61bd96, 0x0334fe1e, 0xaa0363cf, -+ 0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14, -+ 0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e, -+ 0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50, -+ 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7, -+ 0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8, -+ 0xf837889a, 0x97e32d77, 0x11ed935f, 0x16681281, -+ 0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99, -+ 0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696, -+ 0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128, -+ 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73, -+ 0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0, -+ 0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0, -+ 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105, -+ 0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250, -+ 0xcf62a1f2, 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3, -+ 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285, -+ 0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00, -+ 0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061, -+ 0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb, -+ 0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e, -+ 0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735, -+ 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc, -+ 0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9, -+ 0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340, -+ 0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20, -+ 0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7 -+ }, { -+ 0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934, -+ 0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068, -+ 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af, -+ 0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840, -+ 0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45, -+ 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504, -+ 0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a, -+ 0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb, -+ 0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee, -+ 0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6, -+ 0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42, -+ 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b, -+ 0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2, -+ 0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb, -+ 0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527, -+ 0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b, -+ 0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33, -+ 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c, -+ 0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3, -+ 0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc, -+ 0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17, -+ 0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564, -+ 0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b, -+ 0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115, -+ 0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922, -+ 0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728, -+ 0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0, -+ 0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e, -+ 0x0a476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37, -+ 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d, -+ 0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804, -+ 0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b, -+ 0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3, -+ 0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb, -+ 0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d, -+ 0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c, -+ 0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350, -+ 0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9, -+ 0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a, -+ 0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe, -+ 0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d, -+ 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc, -+ 0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f, -+ 0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61, -+ 0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2, -+ 0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9, -+ 0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2, -+ 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c, -+ 0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e, -+ 0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633, -+ 0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10, -+ 0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169, -+ 0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52, -+ 0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027, -+ 0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5, -+ 0xf0177a28, 0xc0f586e0, 0x006058aa, 0x30dc7d62, -+ 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634, -+ 0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76, -+ 0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24, -+ 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc, -+ 0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4, -+ 0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c, -+ 0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837, -+ 0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0 -+ }, { -+ 0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b, -+ 0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe, -+ 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b, -+ 0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4, -+ 0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8, -+ 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6, -+ 0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304, -+ 0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22, -+ 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4, -+ 0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6, -+ 0x2826a2f9, 0xa73a3ae1, 0x4ba99586, 0xef5562e9, -+ 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59, -+ 0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593, -+ 0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51, -+ 0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28, -+ 0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c, -+ 0xe029ac71, 0xe019a5e6, 0x47b0acfd, 0xed93fa9b, -+ 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28, -+ 0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c, -+ 0x15056dd4, 0x88f46dba, 0x03a16125, 0x0564f0bd, -+ 0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a, -+ 0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319, -+ 0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb, -+ 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f, -+ 0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991, -+ 0xea7a90c2, 0xfb3e7bce, 0x5121ce64, 0x774fbe32, -+ 0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680, -+ 0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166, -+ 0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae, -+ 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb, -+ 0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5, -+ 0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47, -+ 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370, -+ 0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d, -+ 0x4040cb08, 0x4eb4e2cc, 0x34d2466a, 0x0115af84, -+ 0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048, -+ 0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8, -+ 0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd, -+ 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9, -+ 0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7, -+ 0x1a908749, 0xd44fbd9a, 0xd0dadecb, 0xd50ada38, -+ 0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f, -+ 0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c, -+ 0xbf97222c, 0x15e6fc2a, 0x0f91fc71, 0x9b941525, -+ 0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1, -+ 0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442, -+ 0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964, -+ 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e, -+ 0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8, -+ 0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d, -+ 0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f, -+ 0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299, -+ 0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02, -+ 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc, -+ 0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614, -+ 0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a, -+ 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6, -+ 0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b, -+ 0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0, -+ 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060, -+ 0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e, -+ 0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9, -+ 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f, -+ 0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6 -+ } -+ }, { -+ 0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, -+ 0xa4093822, 0x299f31d0, 0x082efa98, 0xec4e6c89, -+ 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c, -+ 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917, -+ 0x9216d5d9, 0x8979fb1b -+ } -+}; -+ -+static unsigned char BF_itoa64[64 + 1] = -+ "./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; -+ -+static unsigned char BF_atoi64[0x60] = { -+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 0, 1, -+ 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 64, 64, 64, 64, 64, -+ 64, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, -+ 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 64, 64, 64, 64, 64, -+ 64, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, -+ 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 64, 64, 64, 64, 64 -+}; -+ -+#define BF_safe_atoi64(dst, src) \ -+{ \ -+ tmp = (unsigned char)(src); \ -+ if ((unsigned int)(tmp -= 0x20) >= 0x60) return -1; \ -+ tmp = BF_atoi64[tmp]; \ -+ if (tmp > 63) return -1; \ -+ (dst) = tmp; \ -+} -+ -+static int BF_decode(BF_word *dst, const char *src, int size) -+{ -+ unsigned char *dptr = (unsigned char *)dst; -+ unsigned char *end = dptr + size; -+ const unsigned char *sptr = (const unsigned char *)src; -+ unsigned int tmp, c1, c2, c3, c4; -+ -+ do { -+ BF_safe_atoi64(c1, *sptr++); -+ BF_safe_atoi64(c2, *sptr++); -+ *dptr++ = (c1 << 2) | ((c2 & 0x30) >> 4); -+ if (dptr >= end) break; -+ -+ BF_safe_atoi64(c3, *sptr++); -+ *dptr++ = ((c2 & 0x0F) << 4) | ((c3 & 0x3C) >> 2); -+ if (dptr >= end) break; -+ -+ BF_safe_atoi64(c4, *sptr++); -+ *dptr++ = ((c3 & 0x03) << 6) | c4; -+ } while (dptr < end); -+ -+ return 0; -+} -+ -+static void BF_encode(char *dst, const BF_word *src, int size) -+{ -+ const unsigned char *sptr = (const unsigned char *)src; -+ const unsigned char *end = sptr + size; -+ unsigned char *dptr = (unsigned char *)dst; -+ unsigned int c1, c2; -+ -+ do { -+ c1 = *sptr++; -+ *dptr++ = BF_itoa64[c1 >> 2]; -+ c1 = (c1 & 0x03) << 4; -+ if (sptr >= end) { -+ *dptr++ = BF_itoa64[c1]; -+ break; -+ } -+ -+ c2 = *sptr++; -+ c1 |= c2 >> 4; -+ *dptr++ = BF_itoa64[c1]; -+ c1 = (c2 & 0x0f) << 2; -+ if (sptr >= end) { -+ *dptr++ = BF_itoa64[c1]; -+ break; -+ } -+ -+ c2 = *sptr++; -+ c1 |= c2 >> 6; -+ *dptr++ = BF_itoa64[c1]; -+ *dptr++ = BF_itoa64[c2 & 0x3f]; -+ } while (sptr < end); -+} -+ -+static void BF_swap(BF_word *x, int count) -+{ -+ static int endianness_check = 1; -+ char *is_little_endian = (char *)&endianness_check; -+ BF_word tmp; -+ -+ if (*is_little_endian) -+ do { -+ tmp = *x; -+ tmp = (tmp << 16) | (tmp >> 16); -+ *x++ = ((tmp & 0x00FF00FF) << 8) | ((tmp >> 8) & 0x00FF00FF); -+ } while (--count); -+} -+ -+/* Architectures which can shift addresses left by 2 bits with no extra cost */ -+#define BF_ROUND(L, R, N) \ -+ tmp1 = L & 0xFF; \ -+ tmp2 = L >> 8; \ -+ tmp2 &= 0xFF; \ -+ tmp3 = L >> 16; \ -+ tmp3 &= 0xFF; \ -+ tmp4 = L >> 24; \ -+ tmp1 = data.ctx.S[3][tmp1]; \ -+ tmp2 = data.ctx.S[2][tmp2]; \ -+ tmp3 = data.ctx.S[1][tmp3]; \ -+ tmp3 += data.ctx.S[0][tmp4]; \ -+ tmp3 ^= tmp2; \ -+ R ^= data.ctx.P[N + 1]; \ -+ tmp3 += tmp1; \ -+ R ^= tmp3; -+ -+/* -+ * Encrypt one block, BF_N is hardcoded here. -+ */ -+#define BF_ENCRYPT \ -+ L ^= data.ctx.P[0]; \ -+ BF_ROUND(L, R, 0); \ -+ BF_ROUND(R, L, 1); \ -+ BF_ROUND(L, R, 2); \ -+ BF_ROUND(R, L, 3); \ -+ BF_ROUND(L, R, 4); \ -+ BF_ROUND(R, L, 5); \ -+ BF_ROUND(L, R, 6); \ -+ BF_ROUND(R, L, 7); \ -+ BF_ROUND(L, R, 8); \ -+ BF_ROUND(R, L, 9); \ -+ BF_ROUND(L, R, 10); \ -+ BF_ROUND(R, L, 11); \ -+ BF_ROUND(L, R, 12); \ -+ BF_ROUND(R, L, 13); \ -+ BF_ROUND(L, R, 14); \ -+ BF_ROUND(R, L, 15); \ -+ tmp4 = R; \ -+ R = L; \ -+ L = tmp4 ^ data.ctx.P[BF_N + 1]; -+ -+#define BF_body() \ -+ L = R = 0; \ -+ ptr = data.ctx.P; \ -+ do { \ -+ ptr += 2; \ -+ BF_ENCRYPT; \ -+ *(ptr - 2) = L; \ -+ *(ptr - 1) = R; \ -+ } while (ptr < &data.ctx.P[BF_N + 2]); \ -+\ -+ ptr = data.ctx.S[0]; \ -+ do { \ -+ ptr += 2; \ -+ BF_ENCRYPT; \ -+ *(ptr - 2) = L; \ -+ *(ptr - 1) = R; \ -+ } while (ptr < &data.ctx.S[3][0xFF]); -+ -+static void BF_set_key(const char *key, BF_key expanded, BF_key initial, -+ unsigned char flags) -+{ -+ const char *ptr = key; -+ unsigned int bug, i, j; -+ BF_word safety, sign, diff, tmp[2]; -+ -+/* -+ * There was a sign extension bug in older revisions of this function. While -+ * we would have liked to simply fix the bug and move on, we have to provide -+ * a backwards compatibility feature (essentially the bug) for some systems and -+ * a safety measure for some others. The latter is needed because for certain -+ * multiple inputs to the buggy algorithm there exist easily found inputs to -+ * the correct algorithm that produce the same hash. Thus, we optionally -+ * deviate from the correct algorithm just enough to avoid such collisions. -+ * While the bug itself affected the majority of passwords containing -+ * characters with the 8th bit set (although only a percentage of those in a -+ * collision-producing way), the anti-collision safety measure affects -+ * only a subset of passwords containing the '\xff' character (not even all of -+ * those passwords, just some of them). This character is not found in valid -+ * UTF-8 sequences and is rarely used in popular 8-bit character encodings. -+ * Thus, the safety measure is unlikely to cause much annoyance, and is a -+ * reasonable tradeoff to use when authenticating against existing hashes that -+ * are not reliably known to have been computed with the correct algorithm. -+ * -+ * We use an approach that tries to minimize side-channel leaks of password -+ * information - that is, we mostly use fixed-cost bitwise operations instead -+ * of branches or table lookups. (One conditional branch based on password -+ * length remains. It is not part of the bug aftermath, though, and is -+ * difficult and possibly unreasonable to avoid given the use of C strings by -+ * the caller, which results in similar timing leaks anyway.) -+ * -+ * For actual implementation, we set an array index in the variable "bug" -+ * (0 means no bug, 1 means sign extension bug emulation) and a flag in the -+ * variable "safety" (bit 16 is set when the safety measure is requested). -+ * Valid combinations of settings are: -+ * -+ * Prefix "$2a$": bug = 0, safety = 0x10000 -+ * Prefix "$2x$": bug = 1, safety = 0 -+ * Prefix "$2y$": bug = 0, safety = 0 -+ */ -+ bug = (unsigned int)flags & 1; -+ safety = ((BF_word)flags & 2) << 15; -+ -+ sign = diff = 0; -+ -+ for (i = 0; i < BF_N + 2; i++) { -+ tmp[0] = tmp[1] = 0; -+ for (j = 0; j < 4; j++) { -+ tmp[0] <<= 8; -+ tmp[0] |= (unsigned char)*ptr; /* correct */ -+ tmp[1] <<= 8; -+ tmp[1] |= (BF_word_signed)(signed char)*ptr; /* bug */ -+/* -+ * Sign extension in the first char has no effect - nothing to overwrite yet, -+ * and those extra 24 bits will be fully shifted out of the 32-bit word. For -+ * chars 2, 3, 4 in each four-char block, we set bit 7 of "sign" if sign -+ * extension in tmp[1] occurs. Once this flag is set, it remains set. -+ */ -+ if (j) -+ sign |= tmp[1] & 0x80; -+ if (!*ptr) -+ ptr = key; -+ else -+ ptr++; -+ } -+ diff |= tmp[0] ^ tmp[1]; /* Non-zero on any differences */ -+ -+ expanded[i] = tmp[bug]; -+ initial[i] = BF_init_state.P[i] ^ tmp[bug]; -+ } -+ -+/* -+ * At this point, "diff" is zero iff the correct and buggy algorithms produced -+ * exactly the same result. If so and if "sign" is non-zero, which indicates -+ * that there was a non-benign sign extension, this means that we have a -+ * collision between the correctly computed hash for this password and a set of -+ * passwords that could be supplied to the buggy algorithm. Our safety measure -+ * is meant to protect from such many-buggy to one-correct collisions, by -+ * deviating from the correct algorithm in such cases. Let's check for this. -+ */ -+ diff |= diff >> 16; /* still zero iff exact match */ -+ diff &= 0xffff; /* ditto */ -+ diff += 0xffff; /* bit 16 set iff "diff" was non-zero (on non-match) */ -+ sign <<= 9; /* move the non-benign sign extension flag to bit 16 */ -+ sign &= ~diff & safety; /* action needed? */ -+ -+/* -+ * If we have determined that we need to deviate from the correct algorithm, -+ * flip bit 16 in initial expanded key. (The choice of 16 is arbitrary, but -+ * let's stick to it now. It came out of the approach we used above, and it's -+ * not any worse than any other choice we could make.) -+ * -+ * It is crucial that we don't do the same to the expanded key used in the main -+ * Eksblowfish loop. By doing it to only one of these two, we deviate from a -+ * state that could be directly specified by a password to the buggy algorithm -+ * (and to the fully correct one as well, but that's a side-effect). -+ */ -+ initial[0] ^= sign; -+} -+ -+static char *BF_crypt(const char *key, const char *setting, -+ char *output, int size, -+ BF_word min) -+{ -+ static const unsigned char flags_by_subtype[26] = -+ {2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 4, 0}; -+ struct { -+ BF_ctx ctx; -+ BF_key expanded_key; -+ union { -+ BF_word salt[4]; -+ BF_word output[6]; -+ } binary; -+ } data; -+ BF_word L, R; -+ BF_word tmp1, tmp2, tmp3, tmp4; -+ BF_word *ptr; -+ BF_word count; -+ int i; -+ -+ if (size < 7 + 22 + 31 + 1) { -+ return NULL; -+ } -+ -+ if (setting[0] != '$' || -+ setting[1] != '2' || -+ setting[2] < 'a' || setting[2] > 'z' || -+ !flags_by_subtype[(unsigned int)(unsigned char)setting[2] - 'a'] || -+ setting[3] != '$' || -+ setting[4] < '0' || setting[4] > '3' || -+ setting[5] < '0' || setting[5] > '9' || -+ (setting[4] == '3' && setting[5] > '1') || -+ setting[6] != '$') { -+ return NULL; -+ } -+ -+ count = (BF_word)1 << ((setting[4] - '0') * 10 + (setting[5] - '0')); -+ if (count < min || BF_decode(data.binary.salt, &setting[7], 16)) { -+ return NULL; -+ } -+ BF_swap(data.binary.salt, 4); -+ -+ BF_set_key(key, data.expanded_key, data.ctx.P, -+ flags_by_subtype[(unsigned int)(unsigned char)setting[2] - 'a']); -+ -+ CopyMem(data.ctx.S, BF_init_state.S, sizeof(data.ctx.S)); -+ -+ L = R = 0; -+ for (i = 0; i < BF_N + 2; i += 2) { -+ L ^= data.binary.salt[i & 2]; -+ R ^= data.binary.salt[(i & 2) + 1]; -+ BF_ENCRYPT; -+ data.ctx.P[i] = L; -+ data.ctx.P[i + 1] = R; -+ } -+ -+ ptr = data.ctx.S[0]; -+ do { -+ ptr += 4; -+ L ^= data.binary.salt[(BF_N + 2) & 3]; -+ R ^= data.binary.salt[(BF_N + 3) & 3]; -+ BF_ENCRYPT; -+ *(ptr - 4) = L; -+ *(ptr - 3) = R; -+ -+ L ^= data.binary.salt[(BF_N + 4) & 3]; -+ R ^= data.binary.salt[(BF_N + 5) & 3]; -+ BF_ENCRYPT; -+ *(ptr - 2) = L; -+ *(ptr - 1) = R; -+ } while (ptr < &data.ctx.S[3][0xFF]); -+ -+ do { -+ int done; -+ -+ for (i = 0; i < BF_N + 2; i += 2) { -+ data.ctx.P[i] ^= data.expanded_key[i]; -+ data.ctx.P[i + 1] ^= data.expanded_key[i + 1]; -+ } -+ -+ done = 0; -+ do { -+ BF_body(); -+ if (done) -+ break; -+ done = 1; -+ -+ tmp1 = data.binary.salt[0]; -+ tmp2 = data.binary.salt[1]; -+ tmp3 = data.binary.salt[2]; -+ tmp4 = data.binary.salt[3]; -+ for (i = 0; i < BF_N; i += 4) { -+ data.ctx.P[i] ^= tmp1; -+ data.ctx.P[i + 1] ^= tmp2; -+ data.ctx.P[i + 2] ^= tmp3; -+ data.ctx.P[i + 3] ^= tmp4; -+ } -+ data.ctx.P[16] ^= tmp1; -+ data.ctx.P[17] ^= tmp2; -+ } while (1); -+ } while (--count); -+ -+ for (i = 0; i < 6; i += 2) { -+ L = BF_magic_w[i]; -+ R = BF_magic_w[i + 1]; -+ -+ count = 64; -+ do { -+ BF_ENCRYPT; -+ } while (--count); -+ -+ data.binary.output[i] = L; -+ data.binary.output[i + 1] = R; -+ } -+ -+ CopyMem(output, (void *)setting, 7 + 22 - 1); -+ output[7 + 22 - 1] = BF_itoa64[(int) -+ BF_atoi64[(int)setting[7 + 22 - 1] - 0x20] & 0x30]; -+ -+/* This has to be bug-compatible with the original implementation, so -+ * only encode 23 of the 24 bytes. :-) */ -+ BF_swap(data.binary.output, 6); -+ BF_encode(&output[7 + 22], data.binary.output, 23); -+ output[7 + 22 + 31] = '\0'; -+ -+ return output; -+} -+ -+int _crypt_output_magic(const char *setting, char *output, int size) -+{ -+ if (size < 3) -+ return -1; -+ -+ output[0] = '*'; -+ output[1] = '0'; -+ output[2] = '\0'; -+ -+ if (setting[0] == '*' && setting[1] == '0') -+ output[1] = '1'; -+ -+ return 0; -+} -+ -+/* -+ * Please preserve the runtime self-test. It serves two purposes at once: -+ * -+ * 1. We really can't afford the risk of producing incompatible hashes e.g. -+ * when there's something like gcc bug 26587 again, whereas an application or -+ * library integrating this code might not also integrate our external tests or -+ * it might not run them after every build. Even if it does, the miscompile -+ * might only occur on the production build, but not on a testing build (such -+ * as because of different optimization settings). It is painful to recover -+ * from incorrectly-computed hashes - merely fixing whatever broke is not -+ * enough. Thus, a proactive measure like this self-test is needed. -+ * -+ * 2. We don't want to leave sensitive data from our actual password hash -+ * computation on the stack or in registers. Previous revisions of the code -+ * would do explicit cleanups, but simply running the self-test after hash -+ * computation is more reliable. -+ * -+ * The performance cost of this quick self-test is around 0.6% at the "$2a$08" -+ * setting. -+ */ -+char *crypt_blowfish_rn(const char *key, const char *setting, -+ char *output, int size) -+{ -+ const char *test_key = "8b \xd0\xc1\xd2\xcf\xcc\xd8"; -+ const char *test_setting = "$2a$00$abcdefghijklmnopqrstuu"; -+ static const char * const test_hash[2] = -+ {"VUrPmXD6q/nVSSp7pNDhCR9071IfIRe\0\x55", /* $2x$ */ -+ "i1D709vfamulimlGcq0qq3UvuUasvEa\0\x55"}; /* $2a$, $2y$ */ -+ char *retval; -+ const char *p; -+ int ok; -+ struct { -+ char s[7 + 22 + 1]; -+ char o[7 + 22 + 31 + 1 + 1 + 1]; -+ } buf; -+ -+/* Hash the supplied password */ -+ _crypt_output_magic(setting, output, size); -+ retval = BF_crypt(key, setting, output, size, 16); -+ -+/* -+ * Do a quick self-test. It is important that we make both calls to BF_crypt() -+ * from the same scope such that they likely use the same stack locations, -+ * which makes the second call overwrite the first call's sensitive data on the -+ * stack and makes it more likely that any alignment related issues would be -+ * detected by the self-test. -+ */ -+ CopyMem(buf.s, (void *)test_setting, sizeof(buf.s)); -+ if (retval) -+ buf.s[2] = setting[2]; -+ SetMem(buf.o, sizeof(buf.o), 0x55); -+ buf.o[sizeof(buf.o) - 1] = 0; -+ p = BF_crypt(test_key, buf.s, buf.o, sizeof(buf.o) - (1 + 1), 1); -+ -+ ok = (p == buf.o && -+ !CompareMem((void *)p, (void *)buf.s, 7 + 22) && -+ !CompareMem((void *)(p + (7 + 22)), -+ (void *)test_hash[(unsigned int)(unsigned char)buf.s[2] & 1], -+ 31 + 1 + 1 + 1)); -+ -+ { -+ const char *k = "\xff\xa3" "34" "\xff\xff\xff\xa3" "345"; -+ BF_key ae, ai, ye, yi; -+ BF_set_key(k, ae, ai, 2); /* $2a$ */ -+ BF_set_key(k, ye, yi, 4); /* $2y$ */ -+ ai[0] ^= 0x10000; /* undo the safety (for comparison) */ -+ ok = ok && ai[0] == 0xdb9c59bc && ye[17] == 0x33343500 && -+ !CompareMem(ae, ye, sizeof(ae)) && -+ !CompareMem(ai, yi, sizeof(ai)); -+ } -+ -+ if (ok) -+ return retval; -+ -+/* Should not happen */ -+ _crypt_output_magic(setting, output, size); -+ return NULL; -+} -diff --git a/crypt_blowfish.h b/crypt_blowfish.h -new file mode 100644 -index 0000000..dc3bd56 ---- /dev/null -+++ b/crypt_blowfish.h -@@ -0,0 +1,22 @@ -+/* -+ * Written by Solar Designer in 2000-2011. -+ * No copyright is claimed, and the software is hereby placed in the public -+ * domain. In case this attempt to disclaim copyright and place the software -+ * in the public domain is deemed null and void, then the software is -+ * Copyright (c) 2000-2011 Solar Designer and it is hereby released to the -+ * general public under the following terms: -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted. -+ * -+ * There's ABSOLUTELY NO WARRANTY, express or implied. -+ * -+ * See crypt_blowfish.c for more information. -+ */ -+ -+#ifndef _CRYPT_BLOWFISH_H -+#define _CRYPT_BLOWFISH_H -+ -+char *crypt_blowfish_rn(const char *key, const char *setting, -+ char *output, int size); -+#endif --- -1.8.1.4 - - -From 05ad901e17bbc64f32ecffc64c6f3d253ecb099b Mon Sep 17 00:00:00 2001 -From: Gary Ching-Pang Lin -Date: Tue, 29 Jan 2013 12:09:34 +0800 -Subject: [PATCH 4/5] MokManager: support MD5-based crypt() hash - ---- - PasswordCrypt.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++- - 1 file changed, 67 insertions(+), 1 deletion(-) - -diff --git a/PasswordCrypt.c b/PasswordCrypt.c -index 38b980f..8483498 100644 ---- a/PasswordCrypt.c -+++ b/PasswordCrypt.c -@@ -28,6 +28,69 @@ UINT16 get_hash_size (const UINT16 method) - return 0; - } - -+static const char md5_salt_prefix[] = "$1$"; -+ -+static EFI_STATUS md5_crypt (const char *key, UINT32 key_len, -+ const char *salt, UINT32 salt_size, -+ UINT8 *hash) -+{ -+ MD5_CTX ctx, alt_ctx; -+ UINT8 alt_result[MD5_DIGEST_LENGTH]; -+ UINTN cnt; -+ -+ MD5_Init(&ctx); -+ MD5_Update(&ctx, key, key_len); -+ MD5_Update(&ctx, md5_salt_prefix, sizeof(md5_salt_prefix) - 1); -+ MD5_Update(&ctx, salt, salt_size); -+ -+ MD5_Init(&alt_ctx); -+ MD5_Update(&alt_ctx, key, key_len); -+ MD5_Update(&alt_ctx, salt, salt_size); -+ MD5_Update(&alt_ctx, key, key_len); -+ MD5_Final(alt_result, &alt_ctx); -+ -+ for (cnt = key_len; cnt > 16; cnt -= 16) -+ MD5_Update(&ctx, alt_result, 16); -+ MD5_Update(&ctx, alt_result, cnt); -+ -+ *alt_result = '\0'; -+ -+ for (cnt = key_len; cnt > 0; cnt >>= 1) { -+ if ((cnt & 1) != 0) { -+ MD5_Update(&ctx, alt_result, 1); -+ } else { -+ MD5_Update(&ctx, key, 1); -+ } -+ } -+ MD5_Final(alt_result, &ctx); -+ -+ for (cnt = 0; cnt < 1000; ++cnt) { -+ MD5_Init(&ctx); -+ -+ if ((cnt & 1) != 0) -+ MD5_Update(&ctx, key, key_len); -+ else -+ MD5_Update(&ctx, alt_result, 16); -+ -+ if (cnt % 3 != 0) -+ MD5_Update(&ctx, salt, salt_size); -+ -+ if (cnt % 7 != 0) -+ MD5_Update(&ctx, key, key_len); -+ -+ if ((cnt & 1) != 0) -+ MD5_Update(&ctx, alt_result, 16); -+ else -+ MD5_Update(&ctx, key, key_len); -+ -+ MD5_Final(alt_result, &ctx); -+ } -+ -+ CopyMem(hash, alt_result, MD5_DIGEST_LENGTH); -+ -+ return EFI_SUCCESS; -+} -+ - static EFI_STATUS sha256_crypt (const char *key, UINT32 key_len, - const char *salt, UINT32 salt_size, - const UINT32 rounds, UINT8 *hash) -@@ -229,10 +292,13 @@ EFI_STATUS password_crypt (const char *password, UINT32 pw_length, - switch (pw_crypt->method) { - case TRANDITIONAL_DES: - case EXTEND_BSDI_DES: -- case MD5_BASED: - /* TODO unsupported */ - status = EFI_UNSUPPORTED; - break; -+ case MD5_BASED: -+ 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, --- -1.8.1.4 - - -From 95d17e05d4bfdec193ae7c076542be496b2ae6e7 Mon Sep 17 00:00:00 2001 -From: Gary Ching-Pang Lin -Date: Tue, 29 Jan 2013 17:10:10 +0800 -Subject: [PATCH 5/5] MokManager: support Tradition DES hash - ---- - PasswordCrypt.c | 28 +++++++++++++++++++++++----- - PasswordCrypt.h | 2 +- - 2 files changed, 24 insertions(+), 6 deletions(-) - -diff --git a/PasswordCrypt.c b/PasswordCrypt.c -index 8483498..8d72a82 100644 ---- a/PasswordCrypt.c -+++ b/PasswordCrypt.c -@@ -3,18 +3,21 @@ - #include - #include - #include -+#include - #include "PasswordCrypt.h" - #include "crypt_blowfish.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 */ - #define BLOWFISH_HASH_SIZE 31 /* 184/6+1 */ - - UINT16 get_hash_size (const UINT16 method) - { - switch (method) { -- case TRANDITIONAL_DES: -- return 64 / 8; /* per "man crypt" */ -+ case TRADITIONAL_DES: -+ return TRAD_DES_HASH_SIZE; - case EXTEND_BSDI_DES: -- return 64 / 8; /* per "man crypt" */ -+ return BSDI_DES_HASH_SIZE; - case MD5_BASED: - return MD5_DIGEST_LENGTH; - case SHA256_BASED: -@@ -28,6 +31,20 @@ UINT16 get_hash_size (const UINT16 method) - return 0; - } - -+static EFI_STATUS trad_des_crypt (const char *key, const char *salt, UINT8 *hash) -+{ -+ char result[TRAD_DES_HASH_SIZE + 1]; -+ char *ret; -+ -+ ret = DES_fcrypt(key, salt, result); -+ if (ret) { -+ CopyMem(hash, result, TRAD_DES_HASH_SIZE); -+ return EFI_SUCCESS; -+ } -+ -+ return EFI_UNSUPPORTED; -+} -+ - static const char md5_salt_prefix[] = "$1$"; - - static EFI_STATUS md5_crypt (const char *key, UINT32 key_len, -@@ -290,9 +307,10 @@ EFI_STATUS password_crypt (const char *password, UINT32 pw_length, - return EFI_INVALID_PARAMETER; - - switch (pw_crypt->method) { -- case TRANDITIONAL_DES: -+ case TRADITIONAL_DES: -+ status = trad_des_crypt (password, (char *)pw_crypt->salt, hash); -+ break; - case EXTEND_BSDI_DES: -- /* TODO unsupported */ - status = EFI_UNSUPPORTED; - break; - case MD5_BASED: -diff --git a/PasswordCrypt.h b/PasswordCrypt.h -index 144bf84..b726f32 100644 ---- a/PasswordCrypt.h -+++ b/PasswordCrypt.h -@@ -2,7 +2,7 @@ - #define __PASSWORD_CRYPT_H__ - - enum HashMethod { -- TRANDITIONAL_DES = 0, -+ TRADITIONAL_DES = 0, - EXTEND_BSDI_DES, - MD5_BASED, - SHA256_BASED, --- -1.8.1.4 - diff --git a/shim-mokmanager-ui-revamp.patch b/shim-mokmanager-ui-revamp.patch deleted file mode 100644 index 80c4251..0000000 --- a/shim-mokmanager-ui-revamp.patch +++ /dev/null @@ -1,2082 +0,0 @@ -From a6436443a82b23de4c5dfe83f3c8389f8b554ad3 Mon Sep 17 00:00:00 2001 -From: Gary Ching-Pang Lin -Date: Thu, 30 May 2013 14:22:43 +0800 -Subject: [PATCH 01/11] MokManager: Remove the unnecessary string duplication - ---- - MokManager.c | 19 ++++++++----------- - 1 file changed, 8 insertions(+), 11 deletions(-) - -diff --git a/MokManager.c b/MokManager.c -index b05a52f..918d96b 100644 ---- a/MokManager.c -+++ b/MokManager.c -@@ -1433,45 +1433,45 @@ static EFI_STATUS enter_mok_menu(EFI_HANDLE image_handle, - return EFI_OUT_OF_RESOURCES; - } - -- menu_strings[i] = StrDuplicate(L"Continue boot"); -+ menu_strings[i] = L"Continue boot"; - menu_item[i] = MOK_CONTINUE_BOOT; - - i++; - - if (MokNew || MokAuth) { - if (!MokNew) { -- menu_strings[i] = StrDuplicate(L"Reset MOK"); -+ menu_strings[i] = L"Reset MOK"; - menu_item[i] = MOK_RESET_MOK; - } else { -- menu_strings[i] = StrDuplicate(L"Enroll MOK"); -+ menu_strings[i] = L"Enroll MOK"; - menu_item[i] = MOK_ENROLL_MOK; - } - i++; - } - - if (MokDel || MokDelAuth) { -- menu_strings[i] = StrDuplicate(L"Delete MOK"); -+ menu_strings[i] = L"Delete MOK"; - menu_item[i] = MOK_DELETE_MOK; - i++; - } - - if (MokSB) { -- menu_strings[i] = StrDuplicate(L"Change Secure Boot state"); -+ menu_strings[i] = L"Change Secure Boot state"; - menu_item[i] = MOK_CHANGE_SB; - i++; - } - - if (MokPW) { -- menu_strings[i] = StrDuplicate(L"Set MOK password"); -+ menu_strings[i] = L"Set MOK password"; - menu_item[i] = MOK_SET_PW; - i++; - } - -- menu_strings[i] = StrDuplicate(L"Enroll key from disk"); -+ menu_strings[i] = L"Enroll key from disk"; - menu_item[i] = MOK_KEY_ENROLL; - i++; - -- menu_strings[i] = StrDuplicate(L"Enroll hash from disk"); -+ menu_strings[i] = L"Enroll hash from disk"; - menu_item[i] = MOK_HASH_ENROLL; - i++; - -@@ -1514,9 +1514,6 @@ static EFI_STATUS enter_mok_menu(EFI_HANDLE image_handle, - out: - console_reset(); - -- for (i=0; menu_strings[i] != NULL; i++) -- FreePool(menu_strings[i]); -- - FreePool(menu_strings); - - if (menu_item) --- -1.8.1.4 - - -From ef8fdc597fd532cc4c91c3d2ee638ef339002618 Mon Sep 17 00:00:00 2001 -From: Gary Ching-Pang Lin -Date: Thu, 18 Apr 2013 17:13:12 +0800 -Subject: [PATCH 02/11] MokManager: draw the countdown screen - ---- - MokManager.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - 1 file changed, 60 insertions(+) - -diff --git a/MokManager.c b/MokManager.c -index 918d96b..6b8c79b 100644 ---- a/MokManager.c -+++ b/MokManager.c -@@ -1360,6 +1360,63 @@ static BOOLEAN verify_pw(void) - return TRUE; - } - -+static int draw_countdown() -+{ -+ SIMPLE_TEXT_OUTPUT_MODE SavedMode; -+ EFI_INPUT_KEY key; -+ EFI_STATUS status; -+ UINTN cols, rows; -+ CHAR16 *title[2]; -+ CHAR16 *message = L"Press any key to perform MOK management"; -+ int timeout = 10, wait = 10000000; -+ -+ CopyMem(&SavedMode, ST->ConOut->Mode, sizeof(SavedMode)); -+ uefi_call_wrapper(ST->ConOut->EnableCursor, 2, ST->ConOut, FALSE); -+ uefi_call_wrapper(ST->ConOut->SetAttribute, 2, ST->ConOut, -+ EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE); -+ -+ 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); -+ -+ PrintAt((cols - StrLen(message))/2, rows/2, message); -+ while (1) { -+ if (timeout > 1) -+ PrintAt(2, rows - 3, L"Booting in %d seconds ", timeout); -+ else if (timeout) -+ PrintAt(2, rows - 3, L"Booting in %d second ", timeout); -+ -+ status = WaitForSingleEvent(ST->ConIn->WaitForKey, wait); -+ -+ if (status != EFI_TIMEOUT) { -+ /* Clear the key in the queue */ -+ uefi_call_wrapper(ST->ConIn->ReadKeyStroke, 2, -+ ST->ConIn, &key); -+ break; -+ } -+ -+ timeout--; -+ if (!timeout) -+ break; -+ } -+ -+ FreePool(title[0]); -+ -+ /* Restore everything */ -+ 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); -+ -+ return timeout; -+} -+ - typedef enum { - MOK_CONTINUE_BOOT, - MOK_RESET_MOK, -@@ -1477,6 +1534,9 @@ static EFI_STATUS enter_mok_menu(EFI_HANDLE image_handle, - - menu_strings[i] = NULL; - -+ if (draw_countdown() == 0) -+ goto out; -+ - while (choice >= 0) { - choice = console_select((CHAR16 *[]){ L"Perform MOK management", NULL }, - menu_strings, 0); --- -1.8.1.4 - - -From 9ff682d251b3d30fae63c026aa0105c49db7db16 Mon Sep 17 00:00:00 2001 -From: Gary Ching-Pang Lin -Date: Wed, 26 Jun 2013 12:23:26 +0800 -Subject: [PATCH 03/11] MokManager: remove the duplicate get_keystroke() - ---- - MokManager.c | 14 +------------- - 1 file changed, 1 insertion(+), 13 deletions(-) - -diff --git a/MokManager.c b/MokManager.c -index 6b8c79b..6555a06 100644 ---- a/MokManager.c -+++ b/MokManager.c -@@ -58,18 +58,6 @@ static EFI_STATUS get_variable (CHAR16 *name, EFI_GUID guid, UINT32 *attributes, - return efi_status; - } - --static EFI_INPUT_KEY get_keystroke (void) --{ -- EFI_INPUT_KEY key; -- UINTN EventIndex; -- -- uefi_call_wrapper(BS->WaitForEvent, 3, 1, &ST->ConIn->WaitForKey, -- &EventIndex); -- uefi_call_wrapper(ST->ConIn->ReadKeyStroke, 2, ST->ConIn, &key); -- -- return key; --} -- - static EFI_STATUS get_sha1sum (void *Data, int DataSize, UINT8 *hash) - { - EFI_STATUS status; -@@ -538,7 +526,7 @@ static UINT8 get_line (UINT32 *length, CHAR16 *line, UINT32 line_max, UINT8 show - int count = 0; - - do { -- key = get_keystroke(); -+ key = console_get_keystroke(); - - if ((count >= line_max && - key.UnicodeChar != CHAR_BACKSPACE) || --- -1.8.1.4 - - -From 4c9f6b0b2100f5e878d8578db3ee232c20440735 Mon Sep 17 00:00:00 2001 -From: Gary Ching-Pang Lin -Date: Wed, 26 Jun 2013 15:21:35 +0800 -Subject: [PATCH 04/11] MokManager: enhance the password prompt - ---- - MokManager.c | 106 +++++++++++++++++++++++++++++++++++++++++++++-------------- - 1 file changed, 81 insertions(+), 25 deletions(-) - -diff --git a/MokManager.c b/MokManager.c -index 6555a06..4393aec 100644 ---- a/MokManager.c -+++ b/MokManager.c -@@ -606,6 +606,61 @@ done: - return status; - } - -+static void console_save_and_set_mode (SIMPLE_TEXT_OUTPUT_MODE *SavedMode) -+{ -+ if (!SavedMode) { -+ 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); -+} -+ -+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); -+} -+ -+static UINT32 get_password (CHAR16 *prompt, CHAR16 *password, UINT32 max) -+{ -+ SIMPLE_TEXT_OUTPUT_MODE SavedMode; -+ CHAR16 *str; -+ CHAR16 *message[2]; -+ UINTN length; -+ UINT32 pw_length; -+ -+ if (!prompt) -+ prompt = L"Password:"; -+ -+ console_save_and_set_mode(&SavedMode); -+ -+ str = PoolPrint(L"%s ", prompt); -+ if (!str) { -+ console_errorbox(L"Failed to allocate prompt"); -+ return 0; -+ } -+ -+ message[0] = str; -+ message[1] = NULL; -+ length = StrLen(message[0]); -+ console_print_box_at(message, -1, -length-4, -5, length+4, 3, 0, 1); -+ get_line(&pw_length, password, max, 0); -+ -+ console_restore_mode(&SavedMode); -+ -+ FreePool(str); -+ -+ return pw_length; -+} -+ - static EFI_STATUS match_password (PASSWORD_CRYPT *pw_crypt, - void *Data, UINTN DataSize, - UINT8 *auth, CHAR16 *prompt) -@@ -632,15 +687,10 @@ static EFI_STATUS match_password (PASSWORD_CRYPT *pw_crypt, - } - - while (fail_count < 3) { -- if (prompt) { -- Print(L"%s", prompt); -- } else { -- Print(L"Password: "); -- } -- get_line(&pw_length, password, PASSWORD_MAX, 0); -+ pw_length = get_password(prompt, password, PASSWORD_MAX); - - if (pw_length < PASSWORD_MIN || pw_length > PASSWORD_MAX) { -- Print(L"Invalid password length\n"); -+ console_errorbox(L"Invalid password length"); - fail_count++; - continue; - } -@@ -663,13 +713,13 @@ static EFI_STATUS match_password (PASSWORD_CRYPT *pw_crypt, - pw_length * sizeof(CHAR16), hash); - } - if (status != EFI_SUCCESS) { -- Print(L"Unable to generate password hash\n"); -+ console_errorbox(L"Unable to generate password hash"); - fail_count++; - continue; - } - - if (CompareMem(auth_hash, hash, auth_size) != 0) { -- Print(L"Password doesn't match\n"); -+ console_errorbox(L"Password doesn't match"); - fail_count++; - continue; - } -@@ -1307,13 +1357,17 @@ static void mok_key_enroll(void) - FreePool(data); - } - --static BOOLEAN verify_pw(void) -+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]; - UINTN size = PASSWORD_CRYPT_SIZE; - UINT32 attributes; -+ CHAR16 *message[2]; -+ -+ *protected = FALSE; - - efi_status = uefi_call_wrapper(RT->GetVariable, 5, L"MokPWStore", - &shim_lock_guid, &attributes, &size, -@@ -1333,18 +1387,28 @@ static BOOLEAN verify_pw(void) - - uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut); - -+ /* Draw the background */ -+ console_save_and_set_mode(&SavedMode); -+ 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, -- NULL, L"Enter MOK password: "); -+ NULL, L"Enter MOK password:"); - } else { - efi_status = match_password(NULL, NULL, 0, pwhash, -- L"Enter MOK password: "); -+ L"Enter MOK password:"); - } - if (efi_status != EFI_SUCCESS) { - console_notify(L"Password limit reached"); - return FALSE; - } - -+ *protected = TRUE; -+ - return TRUE; - } - -@@ -1358,10 +1422,7 @@ static int draw_countdown() - CHAR16 *message = L"Press any key to perform MOK management"; - int timeout = 10, wait = 10000000; - -- CopyMem(&SavedMode, ST->ConOut->Mode, sizeof(SavedMode)); -- uefi_call_wrapper(ST->ConOut->EnableCursor, 2, ST->ConOut, FALSE); -- uefi_call_wrapper(ST->ConOut->SetAttribute, 2, ST->ConOut, -- EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE); -+ console_save_and_set_mode (&SavedMode); - - title[0] = PoolPrint (L"%s UEFI key management", SHIM_VENDOR); - title[1] = NULL; -@@ -1394,13 +1455,7 @@ static int draw_countdown() - - FreePool(title[0]); - -- /* Restore everything */ -- 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); -+ console_restore_mode(&SavedMode); - - return timeout; - } -@@ -1433,9 +1488,10 @@ static EFI_STATUS enter_mok_menu(EFI_HANDLE image_handle, - UINT8 auth[PASSWORD_CRYPT_SIZE]; - UINTN auth_size = PASSWORD_CRYPT_SIZE; - UINT32 attributes; -+ BOOLEAN protected; - EFI_STATUS ret = EFI_SUCCESS; - -- if (verify_pw() == FALSE) -+ if (verify_pw(&protected) == FALSE) - return EFI_ACCESS_DENIED; - - efi_status = uefi_call_wrapper(RT->GetVariable, 5, L"MokAuth", -@@ -1522,7 +1578,7 @@ static EFI_STATUS enter_mok_menu(EFI_HANDLE image_handle, - - menu_strings[i] = NULL; - -- if (draw_countdown() == 0) -+ if (protected == FALSE && draw_countdown() == 0) - goto out; - - while (choice >= 0) { --- -1.8.1.4 - - -From 6e71cb7900b99482c7b51a6076f8392022ba15a6 Mon Sep 17 00:00:00 2001 -From: Gary Ching-Pang Lin -Date: Thu, 27 Jun 2013 11:59:09 +0800 -Subject: [PATCH 05/11] Enable openssl bio_printf() - -bio_printf() was replaced with a dummy function and this made -several openssl functions useless. This commit adds the print -functions back, so that we don't have to implement our own -ASN1 time print function. ---- - Cryptlib/OpenSSL/Makefile | 1 + - Cryptlib/OpenSSL/crypto/bio/b_print.c | 842 ++++++++++++++++++++++++++++++++++ - Cryptlib/SysCall/CrtWrapper.c | 10 - - 3 files changed, 843 insertions(+), 10 deletions(-) - create mode 100644 Cryptlib/OpenSSL/crypto/bio/b_print.c - -diff --git a/Cryptlib/OpenSSL/Makefile b/Cryptlib/OpenSSL/Makefile -index f8ab841..c93d5af 100644 ---- a/Cryptlib/OpenSSL/Makefile -+++ b/Cryptlib/OpenSSL/Makefile -@@ -215,6 +215,7 @@ OBJS = crypto/cryptlib.o \ - crypto/bio/bf_null.o \ - crypto/bio/bf_buff.o \ - crypto/bio/b_dump.o \ -+ crypto/bio/b_print.o \ - crypto/bio/bf_nbio.o \ - crypto/bio/bss_log.o \ - crypto/bio/bss_bio.o \ -diff --git a/Cryptlib/OpenSSL/crypto/bio/b_print.c b/Cryptlib/OpenSSL/crypto/bio/b_print.c -new file mode 100644 -index 0000000..3a87b0e ---- /dev/null -+++ b/Cryptlib/OpenSSL/crypto/bio/b_print.c -@@ -0,0 +1,842 @@ -+/* crypto/bio/b_print.c */ -+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) -+ * All rights reserved. -+ * -+ * This package is an SSL implementation written -+ * by Eric Young (eay@cryptsoft.com). -+ * The implementation was written so as to conform with Netscapes SSL. -+ * -+ * This library is free for commercial and non-commercial use as long as -+ * the following conditions are aheared to. The following conditions -+ * apply to all code found in this distribution, be it the RC4, RSA, -+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation -+ * included with this distribution is covered by the same copyright terms -+ * except that the holder is Tim Hudson (tjh@cryptsoft.com). -+ * -+ * Copyright remains Eric Young's, and as such any Copyright notices in -+ * the code are not to be removed. -+ * If this package is used in a product, Eric Young should be given attribution -+ * as the author of the parts of the library used. -+ * This can be in the form of a textual message at program startup or -+ * in documentation (online or textual) provided with the package. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the copyright -+ * notice, this list of conditions and the following disclaimer. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. All advertising materials mentioning features or use of this software -+ * must display the following acknowledgement: -+ * "This product includes cryptographic software written by -+ * Eric Young (eay@cryptsoft.com)" -+ * The word 'cryptographic' can be left out if the rouines from the library -+ * being used are not cryptographic related :-). -+ * 4. If you include any Windows specific code (or a derivative thereof) from -+ * the apps directory (application code) you must include an acknowledgement: -+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" -+ * -+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND -+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE -+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -+ * SUCH DAMAGE. -+ * -+ * The licence and distribution terms for any publically available version or -+ * derivative of this code cannot be changed. i.e. this code cannot simply be -+ * copied and put under another distribution licence -+ * [including the GNU Public Licence.] -+ */ -+ -+/* disable assert() unless BIO_DEBUG has been defined */ -+#ifndef BIO_DEBUG -+# ifndef NDEBUG -+# define NDEBUG -+# endif -+#endif -+ -+/* -+ * Stolen from tjh's ssl/ssl_trc.c stuff. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include "cryptlib.h" -+#ifndef NO_SYS_TYPES_H -+#include -+#endif -+#include /* To get BN_LLONG properly defined */ -+#include -+ -+#if defined(BN_LLONG) || defined(SIXTY_FOUR_BIT) -+# ifndef HAVE_LONG_LONG -+# define HAVE_LONG_LONG 1 -+# endif -+#endif -+ -+/***************************************************************************/ -+ -+/* -+ * Copyright Patrick Powell 1995 -+ * This code is based on code written by Patrick Powell -+ * It may be used for any purpose as long as this notice remains intact -+ * on all source code distributions. -+ */ -+ -+/* -+ * This code contains numerious changes and enhancements which were -+ * made by lots of contributors over the last years to Patrick Powell's -+ * original code: -+ * -+ * o Patrick Powell (1995) -+ * o Brandon Long (1996, for Mutt) -+ * o Thomas Roessler (1998, for Mutt) -+ * o Michael Elkins (1998, for Mutt) -+ * o Andrew Tridgell (1998, for Samba) -+ * o Luke Mewburn (1999, for LukemFTP) -+ * o Ralf S. Engelschall (1999, for Pth) -+ * o ... (for OpenSSL) -+ */ -+ -+#ifdef HAVE_LONG_DOUBLE -+#define LDOUBLE long double -+#else -+#define LDOUBLE double -+#endif -+ -+#if HAVE_LONG_LONG -+# if defined(OPENSSL_SYS_WIN32) && !defined(__GNUC__) -+# define LLONG __int64 -+# else -+# define LLONG long long -+# endif -+#else -+#define LLONG long -+#endif -+ -+static void fmtstr (char **, char **, size_t *, size_t *, -+ const char *, int, int, int); -+static void fmtint (char **, char **, size_t *, size_t *, -+ LLONG, int, int, int, int); -+static void fmtfp (char **, char **, size_t *, size_t *, -+ LDOUBLE, int, int, int); -+static void doapr_outch (char **, char **, size_t *, size_t *, int); -+static void _dopr(char **sbuffer, char **buffer, -+ size_t *maxlen, size_t *retlen, int *truncated, -+ const char *format, va_list args); -+ -+/* format read states */ -+#define DP_S_DEFAULT 0 -+#define DP_S_FLAGS 1 -+#define DP_S_MIN 2 -+#define DP_S_DOT 3 -+#define DP_S_MAX 4 -+#define DP_S_MOD 5 -+#define DP_S_CONV 6 -+#define DP_S_DONE 7 -+ -+/* format flags - Bits */ -+#define DP_F_MINUS (1 << 0) -+#define DP_F_PLUS (1 << 1) -+#define DP_F_SPACE (1 << 2) -+#define DP_F_NUM (1 << 3) -+#define DP_F_ZERO (1 << 4) -+#define DP_F_UP (1 << 5) -+#define DP_F_UNSIGNED (1 << 6) -+ -+/* conversion flags */ -+#define DP_C_SHORT 1 -+#define DP_C_LONG 2 -+#define DP_C_LDOUBLE 3 -+#define DP_C_LLONG 4 -+ -+/* some handy macros */ -+#define char_to_int(p) (p - '0') -+#define OSSL_MAX(p,q) ((p >= q) ? p : q) -+ -+static void -+_dopr( -+ char **sbuffer, -+ char **buffer, -+ size_t *maxlen, -+ size_t *retlen, -+ int *truncated, -+ const char *format, -+ va_list args) -+{ -+ char ch; -+ LLONG value; -+ LDOUBLE fvalue; -+ char *strvalue; -+ int min; -+ int max; -+ int state; -+ int flags; -+ int cflags; -+ size_t currlen; -+ -+ state = DP_S_DEFAULT; -+ flags = currlen = cflags = min = 0; -+ max = -1; -+ ch = *format++; -+ -+ while (state != DP_S_DONE) { -+ if (ch == '\0' || (buffer == NULL && currlen >= *maxlen)) -+ state = DP_S_DONE; -+ -+ switch (state) { -+ case DP_S_DEFAULT: -+ if (ch == '%') -+ state = DP_S_FLAGS; -+ else -+ doapr_outch(sbuffer,buffer, &currlen, maxlen, ch); -+ ch = *format++; -+ break; -+ case DP_S_FLAGS: -+ switch (ch) { -+ case '-': -+ flags |= DP_F_MINUS; -+ ch = *format++; -+ break; -+ case '+': -+ flags |= DP_F_PLUS; -+ ch = *format++; -+ break; -+ case ' ': -+ flags |= DP_F_SPACE; -+ ch = *format++; -+ break; -+ case '#': -+ flags |= DP_F_NUM; -+ ch = *format++; -+ break; -+ case '0': -+ flags |= DP_F_ZERO; -+ ch = *format++; -+ break; -+ default: -+ state = DP_S_MIN; -+ break; -+ } -+ break; -+ case DP_S_MIN: -+ if (isdigit((unsigned char)ch)) { -+ min = 10 * min + char_to_int(ch); -+ ch = *format++; -+ } else if (ch == '*') { -+ min = va_arg(args, int); -+ ch = *format++; -+ state = DP_S_DOT; -+ } else -+ state = DP_S_DOT; -+ break; -+ case DP_S_DOT: -+ if (ch == '.') { -+ state = DP_S_MAX; -+ ch = *format++; -+ } else -+ state = DP_S_MOD; -+ break; -+ case DP_S_MAX: -+ if (isdigit((unsigned char)ch)) { -+ if (max < 0) -+ max = 0; -+ max = 10 * max + char_to_int(ch); -+ ch = *format++; -+ } else if (ch == '*') { -+ max = va_arg(args, int); -+ ch = *format++; -+ state = DP_S_MOD; -+ } else -+ state = DP_S_MOD; -+ break; -+ case DP_S_MOD: -+ switch (ch) { -+ case 'h': -+ cflags = DP_C_SHORT; -+ ch = *format++; -+ break; -+ case 'l': -+ if (*format == 'l') { -+ cflags = DP_C_LLONG; -+ format++; -+ } else -+ cflags = DP_C_LONG; -+ ch = *format++; -+ break; -+ case 'q': -+ cflags = DP_C_LLONG; -+ ch = *format++; -+ break; -+ case 'L': -+ cflags = DP_C_LDOUBLE; -+ ch = *format++; -+ break; -+ default: -+ break; -+ } -+ state = DP_S_CONV; -+ break; -+ case DP_S_CONV: -+ switch (ch) { -+ case 'd': -+ case 'i': -+ switch (cflags) { -+ case DP_C_SHORT: -+ value = (short int)va_arg(args, int); -+ break; -+ case DP_C_LONG: -+ value = va_arg(args, long int); -+ break; -+ case DP_C_LLONG: -+ value = va_arg(args, LLONG); -+ break; -+ default: -+ value = va_arg(args, int); -+ break; -+ } -+ fmtint(sbuffer, buffer, &currlen, maxlen, -+ value, 10, min, max, flags); -+ break; -+ case 'X': -+ flags |= DP_F_UP; -+ /* FALLTHROUGH */ -+ case 'x': -+ case 'o': -+ case 'u': -+ flags |= DP_F_UNSIGNED; -+ switch (cflags) { -+ case DP_C_SHORT: -+ value = (unsigned short int)va_arg(args, unsigned int); -+ break; -+ case DP_C_LONG: -+ value = (LLONG) va_arg(args, -+ unsigned long int); -+ break; -+ case DP_C_LLONG: -+ value = va_arg(args, unsigned LLONG); -+ break; -+ default: -+ value = (LLONG) va_arg(args, -+ unsigned int); -+ break; -+ } -+ fmtint(sbuffer, buffer, &currlen, maxlen, value, -+ ch == 'o' ? 8 : (ch == 'u' ? 10 : 16), -+ min, max, flags); -+ break; -+ case 'f': -+ if (cflags == DP_C_LDOUBLE) -+ fvalue = va_arg(args, LDOUBLE); -+ else -+ fvalue = va_arg(args, double); -+ fmtfp(sbuffer, buffer, &currlen, maxlen, -+ fvalue, min, max, flags); -+ break; -+ case 'E': -+ flags |= DP_F_UP; -+ case 'e': -+ if (cflags == DP_C_LDOUBLE) -+ fvalue = va_arg(args, LDOUBLE); -+ else -+ fvalue = va_arg(args, double); -+ break; -+ case 'G': -+ flags |= DP_F_UP; -+ case 'g': -+ if (cflags == DP_C_LDOUBLE) -+ fvalue = va_arg(args, LDOUBLE); -+ else -+ fvalue = va_arg(args, double); -+ break; -+ case 'c': -+ doapr_outch(sbuffer, buffer, &currlen, maxlen, -+ va_arg(args, int)); -+ break; -+ case 's': -+ strvalue = va_arg(args, char *); -+ if (max < 0) { -+ if (buffer) -+ max = INT_MAX; -+ else -+ max = *maxlen; -+ } -+ fmtstr(sbuffer, buffer, &currlen, maxlen, strvalue, -+ flags, min, max); -+ break; -+ case 'p': -+ value = (long)va_arg(args, void *); -+ fmtint(sbuffer, buffer, &currlen, maxlen, -+ value, 16, min, max, flags|DP_F_NUM); -+ break; -+ case 'n': /* XXX */ -+ if (cflags == DP_C_SHORT) { -+ short int *num; -+ num = va_arg(args, short int *); -+ *num = currlen; -+ } else if (cflags == DP_C_LONG) { /* XXX */ -+ long int *num; -+ num = va_arg(args, long int *); -+ *num = (long int) currlen; -+ } else if (cflags == DP_C_LLONG) { /* XXX */ -+ LLONG *num; -+ num = va_arg(args, LLONG *); -+ *num = (LLONG) currlen; -+ } else { -+ int *num; -+ num = va_arg(args, int *); -+ *num = currlen; -+ } -+ break; -+ case '%': -+ doapr_outch(sbuffer, buffer, &currlen, maxlen, ch); -+ break; -+ case 'w': -+ /* not supported yet, treat as next char */ -+ ch = *format++; -+ break; -+ default: -+ /* unknown, skip */ -+ break; -+ } -+ ch = *format++; -+ state = DP_S_DEFAULT; -+ flags = cflags = min = 0; -+ max = -1; -+ break; -+ case DP_S_DONE: -+ break; -+ default: -+ break; -+ } -+ } -+ *truncated = (currlen > *maxlen - 1); -+ if (*truncated) -+ currlen = *maxlen - 1; -+ doapr_outch(sbuffer, buffer, &currlen, maxlen, '\0'); -+ *retlen = currlen - 1; -+ return; -+} -+ -+static void -+fmtstr( -+ char **sbuffer, -+ char **buffer, -+ size_t *currlen, -+ size_t *maxlen, -+ const char *value, -+ int flags, -+ int min, -+ int max) -+{ -+ int padlen, strln; -+ int cnt = 0; -+ -+ if (value == 0) -+ value = ""; -+ for (strln = 0; value[strln]; ++strln) -+ ; -+ padlen = min - strln; -+ if (padlen < 0) -+ padlen = 0; -+ if (flags & DP_F_MINUS) -+ padlen = -padlen; -+ -+ while ((padlen > 0) && (cnt < max)) { -+ doapr_outch(sbuffer, buffer, currlen, maxlen, ' '); -+ --padlen; -+ ++cnt; -+ } -+ while (*value && (cnt < max)) { -+ doapr_outch(sbuffer, buffer, currlen, maxlen, *value++); -+ ++cnt; -+ } -+ while ((padlen < 0) && (cnt < max)) { -+ doapr_outch(sbuffer, buffer, currlen, maxlen, ' '); -+ ++padlen; -+ ++cnt; -+ } -+} -+ -+static void -+fmtint( -+ char **sbuffer, -+ char **buffer, -+ size_t *currlen, -+ size_t *maxlen, -+ LLONG value, -+ int base, -+ int min, -+ int max, -+ int flags) -+{ -+ int signvalue = 0; -+ const char *prefix = ""; -+ unsigned LLONG uvalue; -+ char convert[DECIMAL_SIZE(value)+3]; -+ int place = 0; -+ int spadlen = 0; -+ int zpadlen = 0; -+ int caps = 0; -+ -+ if (max < 0) -+ max = 0; -+ uvalue = value; -+ if (!(flags & DP_F_UNSIGNED)) { -+ if (value < 0) { -+ signvalue = '-'; -+ uvalue = -value; -+ } else if (flags & DP_F_PLUS) -+ signvalue = '+'; -+ else if (flags & DP_F_SPACE) -+ signvalue = ' '; -+ } -+ if (flags & DP_F_NUM) { -+ if (base == 8) prefix = "0"; -+ if (base == 16) prefix = "0x"; -+ } -+ if (flags & DP_F_UP) -+ caps = 1; -+ do { -+ convert[place++] = -+ (caps ? "0123456789ABCDEF" : "0123456789abcdef") -+ [uvalue % (unsigned) base]; -+ uvalue = (uvalue / (unsigned) base); -+ } while (uvalue && (place < (int)sizeof(convert))); -+ if (place == sizeof(convert)) -+ place--; -+ convert[place] = 0; -+ -+ zpadlen = max - place; -+ spadlen = min - OSSL_MAX(max, place) - (signvalue ? 1 : 0) - strlen(prefix); -+ if (zpadlen < 0) -+ zpadlen = 0; -+ if (spadlen < 0) -+ spadlen = 0; -+ if (flags & DP_F_ZERO) { -+ zpadlen = OSSL_MAX(zpadlen, spadlen); -+ spadlen = 0; -+ } -+ if (flags & DP_F_MINUS) -+ spadlen = -spadlen; -+ -+ /* spaces */ -+ while (spadlen > 0) { -+ doapr_outch(sbuffer, buffer, currlen, maxlen, ' '); -+ --spadlen; -+ } -+ -+ /* sign */ -+ if (signvalue) -+ doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue); -+ -+ /* prefix */ -+ while (*prefix) { -+ doapr_outch(sbuffer, buffer, currlen, maxlen, *prefix); -+ prefix++; -+ } -+ -+ /* zeros */ -+ if (zpadlen > 0) { -+ while (zpadlen > 0) { -+ doapr_outch(sbuffer, buffer, currlen, maxlen, '0'); -+ --zpadlen; -+ } -+ } -+ /* digits */ -+ while (place > 0) -+ doapr_outch(sbuffer, buffer, currlen, maxlen, convert[--place]); -+ -+ /* left justified spaces */ -+ while (spadlen < 0) { -+ doapr_outch(sbuffer, buffer, currlen, maxlen, ' '); -+ ++spadlen; -+ } -+ return; -+} -+ -+static LDOUBLE -+abs_val(LDOUBLE value) -+{ -+ LDOUBLE result = value; -+ if (value < 0) -+ result = -value; -+ return result; -+} -+ -+static LDOUBLE -+pow_10(int in_exp) -+{ -+ LDOUBLE result = 1; -+ while (in_exp) { -+ result *= 10; -+ in_exp--; -+ } -+ return result; -+} -+ -+static long -+roundv(LDOUBLE value) -+{ -+ long intpart; -+ intpart = (long) value; -+ value = value - intpart; -+ if (value >= 0.5) -+ intpart++; -+ return intpart; -+} -+ -+static void -+fmtfp( -+ char **sbuffer, -+ char **buffer, -+ size_t *currlen, -+ size_t *maxlen, -+ LDOUBLE fvalue, -+ int min, -+ int max, -+ int flags) -+{ -+ int signvalue = 0; -+ LDOUBLE ufvalue; -+ char iconvert[20]; -+ char fconvert[20]; -+ int iplace = 0; -+ int fplace = 0; -+ int padlen = 0; -+ int zpadlen = 0; -+ int caps = 0; -+ long intpart; -+ long fracpart; -+ long max10; -+ -+ if (max < 0) -+ max = 6; -+ ufvalue = abs_val(fvalue); -+ if (fvalue < 0) -+ signvalue = '-'; -+ else if (flags & DP_F_PLUS) -+ signvalue = '+'; -+ else if (flags & DP_F_SPACE) -+ signvalue = ' '; -+ -+ intpart = (long)ufvalue; -+ -+ /* sorry, we only support 9 digits past the decimal because of our -+ conversion method */ -+ if (max > 9) -+ max = 9; -+ -+ /* we "cheat" by converting the fractional part to integer by -+ multiplying by a factor of 10 */ -+ max10 = roundv(pow_10(max)); -+ fracpart = roundv(pow_10(max) * (ufvalue - intpart)); -+ -+ if (fracpart >= max10) { -+ intpart++; -+ fracpart -= max10; -+ } -+ -+ /* convert integer part */ -+ do { -+ iconvert[iplace++] = -+ (caps ? "0123456789ABCDEF" -+ : "0123456789abcdef")[intpart % 10]; -+ intpart = (intpart / 10); -+ } while (intpart && (iplace < (int)sizeof(iconvert))); -+ if (iplace == sizeof iconvert) -+ iplace--; -+ iconvert[iplace] = 0; -+ -+ /* convert fractional part */ -+ do { -+ fconvert[fplace++] = -+ (caps ? "0123456789ABCDEF" -+ : "0123456789abcdef")[fracpart % 10]; -+ fracpart = (fracpart / 10); -+ } while (fplace < max); -+ if (fplace == sizeof fconvert) -+ fplace--; -+ fconvert[fplace] = 0; -+ -+ /* -1 for decimal point, another -1 if we are printing a sign */ -+ padlen = min - iplace - max - 1 - ((signvalue) ? 1 : 0); -+ zpadlen = max - fplace; -+ if (zpadlen < 0) -+ zpadlen = 0; -+ if (padlen < 0) -+ padlen = 0; -+ if (flags & DP_F_MINUS) -+ padlen = -padlen; -+ -+ if ((flags & DP_F_ZERO) && (padlen > 0)) { -+ if (signvalue) { -+ doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue); -+ --padlen; -+ signvalue = 0; -+ } -+ while (padlen > 0) { -+ doapr_outch(sbuffer, buffer, currlen, maxlen, '0'); -+ --padlen; -+ } -+ } -+ while (padlen > 0) { -+ doapr_outch(sbuffer, buffer, currlen, maxlen, ' '); -+ --padlen; -+ } -+ if (signvalue) -+ doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue); -+ -+ while (iplace > 0) -+ doapr_outch(sbuffer, buffer, currlen, maxlen, iconvert[--iplace]); -+ -+ /* -+ * Decimal point. This should probably use locale to find the correct -+ * char to print out. -+ */ -+ if (max > 0 || (flags & DP_F_NUM)) { -+ doapr_outch(sbuffer, buffer, currlen, maxlen, '.'); -+ -+ while (fplace > 0) -+ doapr_outch(sbuffer, buffer, currlen, maxlen, fconvert[--fplace]); -+ } -+ while (zpadlen > 0) { -+ doapr_outch(sbuffer, buffer, currlen, maxlen, '0'); -+ --zpadlen; -+ } -+ -+ while (padlen < 0) { -+ doapr_outch(sbuffer, buffer, currlen, maxlen, ' '); -+ ++padlen; -+ } -+} -+ -+static void -+doapr_outch( -+ char **sbuffer, -+ char **buffer, -+ size_t *currlen, -+ size_t *maxlen, -+ int c) -+{ -+ /* If we haven't at least one buffer, someone has doe a big booboo */ -+ assert(*sbuffer != NULL || buffer != NULL); -+ -+ if (buffer) { -+ while (*currlen >= *maxlen) { -+ if (*buffer == NULL) { -+ if (*maxlen == 0) -+ *maxlen = 1024; -+ *buffer = OPENSSL_malloc(*maxlen); -+ if (*currlen > 0) { -+ assert(*sbuffer != NULL); -+ memcpy(*buffer, *sbuffer, *currlen); -+ } -+ *sbuffer = NULL; -+ } else { -+ *maxlen += 1024; -+ *buffer = OPENSSL_realloc(*buffer, *maxlen); -+ } -+ } -+ /* What to do if *buffer is NULL? */ -+ assert(*sbuffer != NULL || *buffer != NULL); -+ } -+ -+ if (*currlen < *maxlen) { -+ if (*sbuffer) -+ (*sbuffer)[(*currlen)++] = (char)c; -+ else -+ (*buffer)[(*currlen)++] = (char)c; -+ } -+ -+ return; -+} -+ -+/***************************************************************************/ -+ -+int BIO_printf (BIO *bio, const char *format, ...) -+ { -+ va_list args; -+ int ret; -+ -+ va_start(args, format); -+ -+ ret = BIO_vprintf(bio, format, args); -+ -+ va_end(args); -+ return(ret); -+ } -+ -+int BIO_vprintf (BIO *bio, const char *format, va_list args) -+ { -+ int ret; -+ size_t retlen; -+ char hugebuf[1024*2]; /* Was previously 10k, which is unreasonable -+ in small-stack environments, like threads -+ or DOS programs. */ -+ char *hugebufp = hugebuf; -+ size_t hugebufsize = sizeof(hugebuf); -+ char *dynbuf = NULL; -+ int ignored; -+ -+ dynbuf = NULL; -+ CRYPTO_push_info("doapr()"); -+ _dopr(&hugebufp, &dynbuf, &hugebufsize, -+ &retlen, &ignored, format, args); -+ if (dynbuf) -+ { -+ ret=BIO_write(bio, dynbuf, (int)retlen); -+ OPENSSL_free(dynbuf); -+ } -+ else -+ { -+ ret=BIO_write(bio, hugebuf, (int)retlen); -+ } -+ CRYPTO_pop_info(); -+ return(ret); -+ } -+ -+/* As snprintf is not available everywhere, we provide our own implementation. -+ * This function has nothing to do with BIOs, but it's closely related -+ * to BIO_printf, and we need *some* name prefix ... -+ * (XXX the function should be renamed, but to what?) */ -+int BIO_snprintf(char *buf, size_t n, const char *format, ...) -+ { -+ va_list args; -+ int ret; -+ -+ va_start(args, format); -+ -+ ret = BIO_vsnprintf(buf, n, format, args); -+ -+ va_end(args); -+ return(ret); -+ } -+ -+int BIO_vsnprintf(char *buf, size_t n, const char *format, va_list args) -+ { -+ size_t retlen; -+ int truncated; -+ -+ _dopr(&buf, NULL, &n, &retlen, &truncated, format, args); -+ -+ if (truncated) -+ /* In case of truncation, return -1 like traditional snprintf. -+ * (Current drafts for ISO/IEC 9899 say snprintf should return -+ * the number of characters that would have been written, -+ * had the buffer been large enough.) */ -+ return -1; -+ else -+ return (retlen <= INT_MAX) ? (int)retlen : -1; -+ } -diff --git a/Cryptlib/SysCall/CrtWrapper.c b/Cryptlib/SysCall/CrtWrapper.c -index fb446b6..5a8322d 100644 ---- a/Cryptlib/SysCall/CrtWrapper.c -+++ b/Cryptlib/SysCall/CrtWrapper.c -@@ -293,16 +293,6 @@ size_t fwrite (const void *buffer, size_t size, size_t count, FILE *stream) - // -- Dummy OpenSSL Support Routines -- - // - --int BIO_printf (void *bio, const char *format, ...) --{ -- return 0; --} -- --int BIO_snprintf(char *buf, size_t n, const char *format, ...) --{ -- return 0; --} -- - void *UI_OpenSSL(void) - { - return NULL; --- -1.8.1.4 - - -From 0b5a0362d6bd3fd1a0721e05353046e387ef2a22 Mon Sep 17 00:00:00 2001 -From: Gary Ching-Pang Lin -Date: Thu, 27 Jun 2013 12:03:14 +0800 -Subject: [PATCH 06/11] Disable floating points in b_print - -The long double declaration will enable SSE and cause a compilation -error. Disabling everything related to floating points avoids the -error. ---- - Cryptlib/OpenSSL/crypto/bio/b_print.c | 8 ++++++++ - 1 file changed, 8 insertions(+) - -diff --git a/Cryptlib/OpenSSL/crypto/bio/b_print.c b/Cryptlib/OpenSSL/crypto/bio/b_print.c -index 3a87b0e..b8b630c 100644 ---- a/Cryptlib/OpenSSL/crypto/bio/b_print.c -+++ b/Cryptlib/OpenSSL/crypto/bio/b_print.c -@@ -129,8 +129,10 @@ static void fmtstr (char **, char **, size_t *, size_t *, - const char *, int, int, int); - static void fmtint (char **, char **, size_t *, size_t *, - LLONG, int, int, int, int); -+#ifndef OPENSSL_SYS_UEFI - static void fmtfp (char **, char **, size_t *, size_t *, - LDOUBLE, int, int, int); -+#endif - static void doapr_outch (char **, char **, size_t *, size_t *, int); - static void _dopr(char **sbuffer, char **buffer, - size_t *maxlen, size_t *retlen, int *truncated, -@@ -177,7 +179,9 @@ _dopr( - { - char ch; - LLONG value; -+#ifndef OPENSSL_SYS_UEFI - LDOUBLE fvalue; -+#endif - char *strvalue; - int min; - int max; -@@ -336,6 +340,7 @@ _dopr( - ch == 'o' ? 8 : (ch == 'u' ? 10 : 16), - min, max, flags); - break; -+#ifndef OPENSSL_SYS_UEFI - case 'f': - if (cflags == DP_C_LDOUBLE) - fvalue = va_arg(args, LDOUBLE); -@@ -360,6 +365,7 @@ _dopr( - else - fvalue = va_arg(args, double); - break; -+#endif - case 'c': - doapr_outch(sbuffer, buffer, &currlen, maxlen, - va_arg(args, int)); -@@ -566,6 +572,7 @@ fmtint( - return; - } - -+#ifndef OPENSSL_SYS_UEFI - static LDOUBLE - abs_val(LDOUBLE value) - { -@@ -721,6 +728,7 @@ fmtfp( - ++padlen; - } - } -+#endif - - static void - doapr_outch( --- -1.8.1.4 - - -From bb29385b30d6958fa99e43bfcf64815ca4bc4a53 Mon Sep 17 00:00:00 2001 -From: Gary Ching-Pang Lin -Date: Thu, 27 Jun 2013 12:28:08 +0800 -Subject: [PATCH 07/11] MokManager: rearrange the output of MOK info - ---- - MokManager.c | 239 ++++++++++++++++++++--------------------------------------- - 1 file changed, 81 insertions(+), 158 deletions(-) - -diff --git a/MokManager.c b/MokManager.c -index 4393aec..8b770ff 100644 ---- a/MokManager.c -+++ b/MokManager.c -@@ -180,136 +180,30 @@ static MokListNode *build_mok_list(UINT32 num, void *Data, UINTN DataSize) { - return list; - } - --static CHAR16* get_x509_name (X509_NAME *X509Name, CHAR16 *name) -+static CHAR16* get_x509_common_name (X509_NAME *X509Name) - { -- char *str; -- CHAR16 *ret = NULL; -+ char str[80]; - -- str = X509_NAME_oneline(X509Name, NULL, 0); -- if (str) { -- ret = PoolPrint(L"%s: %a", name, str); -- OPENSSL_free(str); -- } -- return ret; --} -- --static const char *mon[12]= { --"Jan","Feb","Mar","Apr","May","Jun", --"Jul","Aug","Sep","Oct","Nov","Dec" --}; -- --static void print_x509_GENERALIZEDTIME_time (ASN1_TIME *time, CHAR16 *time_string) --{ -- char *v; -- int gmt = 0; -- int i; -- int y = 0,M = 0,d = 0,h = 0,m = 0,s = 0; -- char *f = NULL; -- int f_len = 0; -- -- i=time->length; -- v=(char *)time->data; -- -- if (i < 12) -- goto error; -- -- if (v[i-1] == 'Z') -- gmt=1; -- -- for (i=0; i<12; i++) { -- if ((v[i] > '9') || (v[i] < '0')) -- goto error; -- } -- -- y = (v[0]-'0')*1000+(v[1]-'0')*100 + (v[2]-'0')*10+(v[3]-'0'); -- M = (v[4]-'0')*10+(v[5]-'0'); -- -- if ((M > 12) || (M < 1)) -- goto error; -- -- d = (v[6]-'0')*10+(v[7]-'0'); -- h = (v[8]-'0')*10+(v[9]-'0'); -- m = (v[10]-'0')*10+(v[11]-'0'); -- -- if (time->length >= 14 && -- (v[12] >= '0') && (v[12] <= '9') && -- (v[13] >= '0') && (v[13] <= '9')) { -- s = (v[12]-'0')*10+(v[13]-'0'); -- /* Check for fractions of seconds. */ -- if (time->length >= 15 && v[14] == '.') { -- int l = time->length; -- f = &v[14]; /* The decimal point. */ -- f_len = 1; -- while (14 + f_len < l && f[f_len] >= '0' && -- f[f_len] <= '9') -- ++f_len; -- } -- } -- -- SPrint(time_string, 0, L"%a %2d %02d:%02d:%02d%.*a %d%a", -- mon[M-1], d, h, m, s, f_len, f, y, (gmt)?" GMT":""); --error: -- return; --} -- --static void print_x509_UTCTIME_time (ASN1_TIME *time, CHAR16 *time_string) --{ -- char *v; -- int gmt=0; -- int i; -- int y = 0,M = 0,d = 0,h = 0,m = 0,s = 0; -- -- i=time->length; -- v=(char *)time->data; -+ ZeroMem(str, 80); -+ X509_NAME_get_text_by_NID (X509Name, NID_commonName, str, 80); - -- if (i < 10) -- goto error; -- -- if (v[i-1] == 'Z') -- gmt=1; -- -- for (i=0; i<10; i++) -- if ((v[i] > '9') || (v[i] < '0')) -- goto error; -- -- y = (v[0]-'0')*10+(v[1]-'0'); -- -- if (y < 50) -- y+=100; -- -- M = (v[2]-'0')*10+(v[3]-'0'); -- -- if ((M > 12) || (M < 1)) -- goto error; -- -- d = (v[4]-'0')*10+(v[5]-'0'); -- h = (v[6]-'0')*10+(v[7]-'0'); -- m = (v[8]-'0')*10+(v[9]-'0'); -- -- if (time->length >=12 && -- (v[10] >= '0') && (v[10] <= '9') && -- (v[11] >= '0') && (v[11] <= '9')) -- s = (v[10]-'0')*10+(v[11]-'0'); -- -- SPrint(time_string, 0, L"%a %2d %02d:%02d:%02d %d%a", -- mon[M-1], d, h, m, s, y+1900, (gmt)?" GMT":""); --error: -- return; -+ return PoolPrint(L"%a", str); - } - --static CHAR16* get_x509_time (ASN1_TIME *time, CHAR16 *name) -+static CHAR16* get_x509_time (ASN1_TIME *time) - { -- CHAR16 time_string[30]; -- -- if (time->type == V_ASN1_UTCTIME) { -- print_x509_UTCTIME_time(time, time_string); -- } else if (time->type == V_ASN1_GENERALIZEDTIME) { -- print_x509_GENERALIZEDTIME_time(time, time_string); -- } else { -- time_string[0] = '\0'; -- } -- -- return PoolPrint(L"%s: %s", name, time_string); -+ BIO *bio = BIO_new (BIO_s_mem()); -+ char str[30]; -+ int len; -+ -+ ASN1_TIME_print (bio, time); -+ len = BIO_read(bio, str, 29); -+ if (len < 0) -+ len = 0; -+ str[len] = '\0'; -+ BIO_free (bio); -+ -+ return PoolPrint(L"%a", str); - } - - static void show_x509_info (X509 *X509Cert, UINT8 *hash) -@@ -339,7 +233,6 @@ static void show_x509_info (X509 *X509Cert, UINT8 *hash) - int i, n; - bnser = ASN1_INTEGER_to_BN(serial, NULL); - n = BN_bn2bin(bnser, hexbuf); -- CatPrint(&serial_string, L"Serial Number:"); - for (i = 0; i < n; i++) { - CatPrint(&serial_string, L"%02x:", hexbuf[i]); - } -@@ -350,34 +243,32 @@ static void show_x509_info (X509 *X509Cert, UINT8 *hash) - - X509Name = X509_get_issuer_name(X509Cert); - if (X509Name) { -- issuer = get_x509_name(X509Name, L"Issuer"); -+ issuer = get_x509_common_name(X509Name); - if (issuer) - fields++; - } - - X509Name = X509_get_subject_name(X509Cert); - if (X509Name) { -- subject = get_x509_name(X509Name, L"Subject"); -+ subject = get_x509_common_name(X509Name); - if (subject) - fields++; - } - - time = X509_get_notBefore(X509Cert); - if (time) { -- from = get_x509_time(time, L"Validity from"); -- if (time) -+ from = get_x509_time(time); -+ if (from) - fields++; - } - - time = X509_get_notAfter(X509Cert); - if (time) { -- until = get_x509_time(time, L"Validity till"); -+ until = get_x509_time(time); - if (until) - fields++; - } - --#if 0 -- CatPrint(&hash_string1, L"SHA1 Fingerprint: "); - for (i=0; i<10; i++) - CatPrint(&hash_string1, L"%02x ", hash[i]); - for (i=10; i<20; i++) -@@ -388,42 +279,48 @@ static void show_x509_info (X509 *X509Cert, UINT8 *hash) - - if (hash_string2.str) - fields++; --#endif -+ - if (!fields) - return; - -- text = AllocateZeroPool(sizeof(CHAR16 *) * (fields + 1)); -+ i = 0; -+ text = AllocateZeroPool(sizeof(CHAR16 *) * (fields*3 + 1)); - if (serial_string.str) { -- text[i] = serial_string.str; -- i++; -+ text[i++] = StrDuplicate(L"[Serial Number]"); -+ text[i++] = serial_string.str; -+ text[i++] = StrDuplicate(L""); - } - if (issuer) { -- text[i] = issuer; -- i++; -+ text[i++] = StrDuplicate(L"[Issuer]"); -+ text[i++] = issuer; -+ text[i++] = StrDuplicate(L""); - } - if (subject) { -- text[i] = subject; -- i++; -+ text[i++] = StrDuplicate(L"[Subject]"); -+ text[i++] = subject; -+ text[i++] = StrDuplicate(L""); - } - if (from) { -- text[i] = from; -- i++; -+ text[i++] = StrDuplicate(L"[Valid Not Before]"); -+ text[i++] = from; -+ text[i++] = StrDuplicate(L""); - } - if (until) { -- text[i] = until; -- i++; -+ text[i++] = StrDuplicate(L"[Valid Not After]"); -+ text[i++] = until; -+ text[i++] = StrDuplicate(L""); - } - if (hash_string1.str) { -- text[i] = hash_string1.str; -- i++; -+ text[i++] = StrDuplicate(L"[Fingerprint]"); -+ text[i++] = hash_string1.str; - } - if (hash_string2.str) { -- text[i] = hash_string2.str; -- i++; -+ text[i++] = hash_string2.str; -+ text[i++] = StrDuplicate(L""); - } - text[i] = NULL; - -- console_alertbox(text); -+ console_print_box(text, -1); - - for (i=0; text[i] != NULL; i++) - FreePool(text[i]); -@@ -431,11 +328,41 @@ static void show_x509_info (X509 *X509Cert, UINT8 *hash) - FreePool(text); - } - -+static void show_efi_hash (UINT8 *hash) -+{ -+ CHAR16 *text[5]; -+ POOL_PRINT hash_string1; -+ POOL_PRINT hash_string2; -+ int i; -+ -+ ZeroMem(&hash_string1, sizeof(hash_string1)); -+ ZeroMem(&hash_string2, sizeof(hash_string2)); -+ -+ text[0] = L"SHA256 hash"; -+ text[1] = L""; -+ -+ for (i=0; i<16; i++) -+ CatPrint(&hash_string1, L"%02x ", hash[i]); -+ for (i=16; i<32; i++) -+ CatPrint(&hash_string2, L"%02x ", hash[i]); -+ -+ text[2] = hash_string1.str; -+ text[3] = hash_string2.str; -+ text[4] = NULL; -+ -+ console_print_box(text, -1); -+ -+ if (hash_string1.str) -+ FreePool(hash_string1.str); -+ -+ if (hash_string2.str) -+ FreePool(hash_string2.str); -+} -+ - static void show_mok_info (void *Mok, UINTN MokSize) - { - EFI_STATUS efi_status; - UINT8 hash[SHA1_DIGEST_SIZE]; -- unsigned int i; - X509 *X509Cert; - - if (!Mok || MokSize == 0) -@@ -458,13 +385,7 @@ static void show_mok_info (void *Mok, UINTN MokSize) - return; - } - } else { -- Print(L"SHA256 hash:\n "); -- for (i = 0; i < SHA256_DIGEST_SIZE; i++) { -- Print(L" %02x", ((UINT8 *)Mok)[i]); -- if (i % 10 == 9) -- Print(L"\n "); -- } -- Print(L"\n"); -+ show_efi_hash(Mok); - } - } - -@@ -506,7 +427,9 @@ static EFI_STATUS list_keys (void *KeyList, UINTN KeyListSize, CHAR16 *title) - key_num = console_select((CHAR16 *[]){ title, NULL }, - menu_strings, 0); - -- if (key_num < MokNum) -+ if (key_num < 0) -+ break; -+ else if (key_num < MokNum) - show_mok_info(keys[key_num].Mok, keys[key_num].MokSize); - } - --- -1.8.1.4 - - -From 139e31d514772f7aa74cf130ac1e4f2d548734ca Mon Sep 17 00:00:00 2001 -From: Gary Ching-Pang Lin -Date: Thu, 27 Jun 2013 15:04:07 +0800 -Subject: [PATCH 08/11] MokManager: enhance the password prompt for SB state - ---- - MokManager.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++++------- - 1 file changed, 55 insertions(+), 7 deletions(-) - -diff --git a/MokManager.c b/MokManager.c -index 8b770ff..b832e40 100644 ---- a/MokManager.c -+++ b/MokManager.c -@@ -942,13 +942,39 @@ static INTN mok_deletion_prompt (void *MokDel, UINTN MokDelSize) - return -1; - } - -+static CHAR16 get_password_charater (CHAR16 *prompt) -+{ -+ SIMPLE_TEXT_OUTPUT_MODE SavedMode; -+ CHAR16 *message[2]; -+ CHAR16 character; -+ UINTN length; -+ UINT32 pw_length; -+ -+ if (!prompt) -+ prompt = L"Password charater: "; -+ -+ console_save_and_set_mode(&SavedMode); -+ -+ message[0] = prompt; -+ message[1] = NULL; -+ length = StrLen(message[0]); -+ console_print_box_at(message, -1, -length-4, -5, length+4, 3, 0, 1); -+ get_line(&pw_length, &character, 1, 0); -+ -+ console_restore_mode(&SavedMode); -+ -+ return character; -+} -+ - static INTN mok_sb_prompt (void *MokSB, UINTN MokSBSize) { - EFI_GUID shim_lock_guid = SHIM_LOCK_GUID; - EFI_STATUS efi_status; -+ SIMPLE_TEXT_OUTPUT_MODE SavedMode; - MokSBvar *var = MokSB; -+ CHAR16 *message[4]; - CHAR16 pass1, pass2, pass3; -+ CHAR16 *str; - UINT8 fail_count = 0; -- UINT32 length; - UINT8 sbval = 1; - UINT8 pos1, pos2, pos3; - int ret; -@@ -960,6 +986,13 @@ static INTN mok_sb_prompt (void *MokSB, UINTN MokSBSize) { - - uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut); - -+ message[0] = L"Change Secure Boot state"; -+ message[1] = NULL; -+ -+ console_save_and_set_mode(&SavedMode); -+ console_print_box_at(message, -1, 0, 0, -1, -1, 1, 1); -+ console_restore_mode(&SavedMode); -+ - while (fail_count < 3) { - RandomBytes (&pos1, sizeof(pos1)); - pos1 = (pos1 % var->PWLen); -@@ -974,14 +1007,29 @@ static INTN mok_sb_prompt (void *MokSB, UINTN MokSBSize) { - pos3 = (pos3 % var->PWLen) ; - } while (pos3 == pos2 || pos3 == pos1); - -- Print(L"Enter password character %d: ", pos1 + 1); -- get_line(&length, &pass1, 1, 0); -+ str = PoolPrint(L"Enter password character %d: ", pos1 + 1); -+ if (!str) { -+ console_errorbox(L"Failed to allocate buffer"); -+ return -1; -+ } -+ pass1 = get_password_charater(str); -+ FreePool(str); - -- Print(L"Enter password character %d: ", pos2 + 1); -- get_line(&length, &pass2, 1, 0); -+ str = PoolPrint(L"Enter password character %d: ", pos2 + 1); -+ if (!str) { -+ console_errorbox(L"Failed to allocate buffer"); -+ return -1; -+ } -+ pass2 = get_password_charater(str); -+ FreePool(str); - -- Print(L"Enter password character %d: ", pos3 + 1); -- get_line(&length, &pass3, 1, 0); -+ str = PoolPrint(L"Enter password character %d: ", pos3 + 1); -+ if (!str) { -+ console_errorbox(L"Failed to allocate buffer"); -+ return -1; -+ } -+ pass3 = get_password_charater(str); -+ FreePool(str); - - if (pass1 != var->Password[pos1] || - pass2 != var->Password[pos2] || --- -1.8.1.4 - - -From f6102590b773cef0825eb707a793e70b54b882e9 Mon Sep 17 00:00:00 2001 -From: Gary Ching-Pang Lin -Date: Wed, 24 Jul 2013 14:39:39 +0800 -Subject: [PATCH 09/11] MokManager: reboot the system after clearing MOK - password - ---- - MokManager.c | 6 +++++- - 1 file changed, 5 insertions(+), 1 deletion(-) - -diff --git a/MokManager.c b/MokManager.c -index b832e40..bef4d8c 100644 ---- a/MokManager.c -+++ b/MokManager.c -@@ -1107,7 +1107,11 @@ static INTN mok_pw_prompt (void *MokPW, UINTN MokPWSize) { - - LibDeleteVariable(L"MokPWStore", &shim_lock_guid); - LibDeleteVariable(L"MokPW", &shim_lock_guid); -- return 0; -+ console_notify(L"The system must now be rebooted"); -+ uefi_call_wrapper(RT->ResetSystem, 4, EfiResetWarm, EFI_SUCCESS, 0, -+ NULL); -+ console_notify(L"Failed to reboot"); -+ return -1; - } - - if (MokPWSize == PASSWORD_CRYPT_SIZE) { --- -1.8.1.4 - - -From 05eeef80e4ae2bac8f0f27a8c1bc6c3869e030ce Mon Sep 17 00:00:00 2001 -From: Gary Ching-Pang Lin -Date: Fri, 26 Jul 2013 12:44:42 +0800 -Subject: [PATCH 10/11] MokManager: fetch more info from X509 name - ---- - MokManager.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++++------- - 1 file changed, 56 insertions(+), 7 deletions(-) - -diff --git a/MokManager.c b/MokManager.c -index bef4d8c..911c510 100644 ---- a/MokManager.c -+++ b/MokManager.c -@@ -14,6 +14,8 @@ - #define PASSWORD_MIN 1 - #define SB_PASSWORD_LEN 16 - -+#define NAME_LINE_MAX 70 -+ - #ifndef SHIM_VENDOR - #define SHIM_VENDOR L"Shim" - #endif -@@ -180,14 +182,61 @@ static MokListNode *build_mok_list(UINT32 num, void *Data, UINTN DataSize) { - return list; - } - --static CHAR16* get_x509_common_name (X509_NAME *X509Name) -+typedef struct { -+ int nid; -+ CHAR16 *name; -+} NidName; -+ -+static NidName nidname[] = { -+ {NID_commonName, L"CN"}, -+ {NID_organizationName, L"O"}, -+ {NID_countryName, L"C"}, -+ {NID_stateOrProvinceName, L"ST"}, -+ {NID_localityName, L"L"}, -+ {-1, NULL} -+}; -+ -+static CHAR16* get_x509_name (X509_NAME *X509Name) - { -- char str[80]; -+ CHAR16 name[NAME_LINE_MAX+1]; -+ CHAR16 part[NAME_LINE_MAX+1]; -+ char str[NAME_LINE_MAX]; -+ int i, len, rest, first; -+ -+ name[0] = '\0'; -+ rest = NAME_LINE_MAX; -+ 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); -+ if (len <= 0) -+ continue; - -- ZeroMem(str, 80); -- X509_NAME_get_text_by_NID (X509Name, NID_commonName, str, 80); -+ if (first) -+ add = len + (int)StrLen(nidname[i].name) + 1; -+ else -+ add = len + (int)StrLen(nidname[i].name) + 3; - -- return PoolPrint(L"%a", str); -+ if (add > rest) -+ continue; -+ -+ if (first) { -+ SPrint(part, NAME_LINE_MAX * sizeof(CHAR16), L"%s=%a", -+ nidname[i].name, str); -+ } else { -+ SPrint(part, NAME_LINE_MAX * sizeof(CHAR16), L", %s=%a", -+ nidname[i].name, str); -+ } -+ StrCat(name, part); -+ rest -= add; -+ first = 0; -+ } -+ -+ if (rest >= 0 && rest < NAME_LINE_MAX) -+ return PoolPrint(L"%s", name); -+ -+ return NULL; - } - - static CHAR16* get_x509_time (ASN1_TIME *time) -@@ -243,14 +292,14 @@ static void show_x509_info (X509 *X509Cert, UINT8 *hash) - - X509Name = X509_get_issuer_name(X509Cert); - if (X509Name) { -- issuer = get_x509_common_name(X509Name); -+ issuer = get_x509_name(X509Name); - if (issuer) - fields++; - } - - X509Name = X509_get_subject_name(X509Cert); - if (X509Name) { -- subject = get_x509_common_name(X509Name); -+ subject = get_x509_name(X509Name); - if (subject) - fields++; - } --- -1.8.1.4 - - -From 6d6df739005169333734ee04fc379a28d213ab8c Mon Sep 17 00:00:00 2001 -From: Gary Ching-Pang Lin -Date: Fri, 26 Jul 2013 15:44:49 +0800 -Subject: [PATCH 11/11] MokManager: check the suffix of the key file - ---- - MokManager.c | 39 ++++++++++++++++++++++++++++++++++++++- - 1 file changed, 38 insertions(+), 1 deletion(-) - -diff --git a/MokManager.c b/MokManager.c -index 911c510..604129f 100644 ---- a/MokManager.c -+++ b/MokManager.c -@@ -1199,7 +1199,7 @@ static INTN mok_pw_prompt (void *MokPW, UINTN MokPWSize) { - return -1; - } - --static UINTN verify_certificate(void *cert, UINTN size) -+static BOOLEAN verify_certificate(void *cert, UINTN size) - { - X509 *X509Cert; - if (!cert || size == 0) -@@ -1341,6 +1341,34 @@ static void mok_hash_enroll(void) - FreePool(data); - } - -+static CHAR16 *der_suffix[] = { -+ L".cer", -+ L".der", -+ L".crt", -+ NULL -+}; -+ -+static BOOLEAN check_der_suffix (CHAR16 *file_name) -+{ -+ CHAR16 suffix[5]; -+ int i; -+ -+ if (!file_name || StrLen(file_name) <= 4) -+ return FALSE; -+ -+ suffix[0] = '\0'; -+ StrCat(suffix, file_name + StrLen(file_name) - 4); -+ -+ StrLwr (suffix); -+ for (i = 0; der_suffix[i] != NULL; i++) { -+ if (StrCmp(suffix, der_suffix[i]) == 0) { -+ return TRUE; -+ } -+ } -+ -+ return FALSE; -+} -+ - static void mok_key_enroll(void) - { - EFI_STATUS efi_status; -@@ -1362,6 +1390,15 @@ static void mok_key_enroll(void) - if (!file_name) - return; - -+ if (!check_der_suffix(file_name)) { -+ console_alertbox((CHAR16 *[]){ -+ L"Unsupported Format", -+ L"", -+ L"Only DER encoded certificate (*.cer/der/crt) is supported", -+ NULL}); -+ return; -+ } -+ - efi_status = simple_file_open(im, file_name, &file, EFI_FILE_MODE_READ); - - if (efi_status != EFI_SUCCESS) { --- -1.8.1.4 - diff --git a/shim-mokx-support.patch b/shim-mokx-support.patch new file mode 100644 index 0000000..f19a7f4 --- /dev/null +++ b/shim-mokx-support.patch @@ -0,0 +1,1162 @@ +From 8614cf8c164049e77d702eb234d608d5342e975b Mon Sep 17 00:00:00 2001 +From: Gary Ching-Pang Lin +Date: Thu, 24 Oct 2013 17:02:08 +0800 +Subject: [PATCH 1/9] Support MOK blacklist + +The new blacklist, MokListX, stores the keys and hashes that are +banned. +--- + MokManager.c | 241 +++++++++++++++++++++++++++++++++++++++++++++++++---------- + shim.c | 3 +- + 2 files changed, 202 insertions(+), 42 deletions(-) + +diff --git a/MokManager.c b/MokManager.c +index f5ed379..b9b42b6 100644 +--- a/MokManager.c ++++ b/MokManager.c +@@ -701,23 +701,37 @@ static EFI_STATUS match_password (PASSWORD_CRYPT *pw_crypt, + return EFI_SUCCESS; + } + +-static EFI_STATUS store_keys (void *MokNew, UINTN MokNewSize, int authenticate) ++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; + UINT8 auth[PASSWORD_CRYPT_SIZE]; + UINTN auth_size = PASSWORD_CRYPT_SIZE; + UINT32 attributes; + ++ if (MokX) { ++ db_name = L"MokListX"; ++ auth_name = L"MokXAuth"; ++ } else { ++ db_name = L"MokList"; ++ auth_name = L"MokAuth"; ++ } ++ + if (authenticate) { +- efi_status = uefi_call_wrapper(RT->GetVariable, 5, L"MokAuth", ++ 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)) { +- console_error(L"Failed to get MokAuth", efi_status); ++ if (MokX) ++ console_error(L"Failed to get MokXAuth", efi_status); ++ else ++ console_error(L"Failed to get MokAuth", efi_status); + return efi_status; + } + +@@ -734,14 +748,14 @@ static EFI_STATUS store_keys (void *MokNew, UINTN MokNewSize, int authenticate) + + if (!MokNewSize) { + /* Delete MOK */ +- efi_status = uefi_call_wrapper(RT->SetVariable, 5, L"MokList", ++ efi_status = uefi_call_wrapper(RT->SetVariable, 5, db_name, + &shim_lock_guid, + EFI_VARIABLE_NON_VOLATILE + | EFI_VARIABLE_BOOTSERVICE_ACCESS, + 0, NULL); + } else { + /* Write new MOK */ +- efi_status = uefi_call_wrapper(RT->SetVariable, 5, L"MokList", ++ efi_status = uefi_call_wrapper(RT->SetVariable, 5, db_name, + &shim_lock_guid, + EFI_VARIABLE_NON_VOLATILE + | EFI_VARIABLE_BOOTSERVICE_ACCESS +@@ -757,17 +771,25 @@ static EFI_STATUS store_keys (void *MokNew, UINTN MokNewSize, int authenticate) + return EFI_SUCCESS; + } + +-static UINTN mok_enrollment_prompt (void *MokNew, UINTN MokNewSize, int auth) { ++static UINTN mok_enrollment_prompt (void *MokNew, UINTN MokNewSize, int auth, ++ BOOLEAN MokX) ++{ + EFI_GUID shim_lock_guid = SHIM_LOCK_GUID; + EFI_STATUS efi_status; ++ CHAR16 *title; + +- if (list_keys(MokNew, MokNewSize, L"[Enroll MOK]") != EFI_SUCCESS) ++ if (MokX) ++ title = L"[Enroll MOKX]"; ++ else ++ title = L"[Enroll MOK]"; ++ ++ if (list_keys(MokNew, MokNewSize, title) != EFI_SUCCESS) + return 0; + + if (console_yes_no((CHAR16 *[]){L"Enroll the key(s)?", NULL}) == 0) + return 0; + +- efi_status = store_keys(MokNew, MokNewSize, auth); ++ efi_status = store_keys(MokNew, MokNewSize, auth, MokX); + + if (efi_status != EFI_SUCCESS) { + console_notify(L"Failed to enroll keys\n"); +@@ -775,8 +797,13 @@ static UINTN mok_enrollment_prompt (void *MokNew, UINTN MokNewSize, int auth) { + } + + if (auth) { +- LibDeleteVariable(L"MokNew", &shim_lock_guid); +- LibDeleteVariable(L"MokAuth", &shim_lock_guid); ++ if (MokX) { ++ 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); ++ } + + console_notify(L"The system must now be rebooted"); + uefi_call_wrapper(RT->ResetSystem, 4, EfiResetWarm, +@@ -788,25 +815,35 @@ static UINTN mok_enrollment_prompt (void *MokNew, UINTN MokNewSize, int auth) { + return 0; + } + +-static INTN mok_reset_prompt () ++static INTN mok_reset_prompt (BOOLEAN MokX) + { + EFI_GUID shim_lock_guid = SHIM_LOCK_GUID; + EFI_STATUS efi_status; ++ CHAR16 *prompt; + + uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut); + +- if (console_yes_no((CHAR16 *[]){L"Erase all stored keys?", NULL }) == 0) ++ if (MokX) ++ prompt = L"Erase all stored keys in MokListX?"; ++ else ++ prompt = L"Erase all stored keys in MokList?"; ++ if (console_yes_no((CHAR16 *[]){prompt, NULL }) == 0) + return 0; + +- efi_status = store_keys(NULL, 0, TRUE); ++ efi_status = store_keys(NULL, 0, TRUE, MokX); + + if (efi_status != EFI_SUCCESS) { + console_notify(L"Failed to erase keys\n"); + return -1; + } + +- LibDeleteVariable(L"MokNew", &shim_lock_guid); +- LibDeleteVariable(L"MokAuth", &shim_lock_guid); ++ if (MokX) { ++ 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); ++ } + + console_notify(L"The system must now be rebooted"); + uefi_call_wrapper(RT->ResetSystem, 4, EfiResetWarm, +@@ -815,7 +852,8 @@ static INTN mok_reset_prompt () + return -1; + } + +-static EFI_STATUS write_back_mok_list (MokListNode *list, INTN key_num) ++static EFI_STATUS write_back_mok_list (MokListNode *list, INTN key_num, ++ BOOLEAN MokX) + { + EFI_GUID shim_lock_guid = SHIM_LOCK_GUID; + EFI_STATUS efi_status; +@@ -824,6 +862,12 @@ static EFI_STATUS write_back_mok_list (MokListNode *list, INTN key_num) + void *Data = NULL, *ptr; + INTN DataSize = 0; + int i; ++ CHAR16 *db_name; ++ ++ if (MokX) ++ db_name = L"MokListX"; ++ else ++ db_name = L"MokList"; + + for (i = 0; i < key_num; i++) { + if (list[i].Mok == NULL) +@@ -861,7 +905,7 @@ static EFI_STATUS write_back_mok_list (MokListNode *list, INTN key_num) + sizeof(EFI_GUID) + list[i].MokSize; + } + +- efi_status = uefi_call_wrapper(RT->SetVariable, 5, L"MokList", ++ efi_status = uefi_call_wrapper(RT->SetVariable, 5, db_name, + &shim_lock_guid, + EFI_VARIABLE_NON_VOLATILE + | EFI_VARIABLE_BOOTSERVICE_ACCESS, +@@ -877,10 +921,14 @@ static EFI_STATUS write_back_mok_list (MokListNode *list, INTN key_num) + return EFI_SUCCESS; + } + +-static EFI_STATUS delete_keys (void *MokDel, UINTN MokDelSize) ++static EFI_STATUS delete_keys (void *MokDel, UINTN MokDelSize, BOOLEAN MokX) + { + EFI_GUID shim_lock_guid = SHIM_LOCK_GUID; + EFI_STATUS efi_status; ++ CHAR16 *db_name; ++ CHAR16 *auth_name; ++ CHAR16 *err_str1; ++ CHAR16 *err_str2; + UINT8 auth[PASSWORD_CRYPT_SIZE]; + UINTN auth_size = PASSWORD_CRYPT_SIZE; + UINT32 attributes; +@@ -890,13 +938,24 @@ static EFI_STATUS delete_keys (void *MokDel, UINTN MokDelSize) + INTN mok_num, del_num; + int i, j; + +- efi_status = uefi_call_wrapper(RT->GetVariable, 5, L"MokDelAuth", ++ if (MokX) { ++ db_name = L"MokListX"; ++ auth_name = L"MokXDelAuth"; ++ } else { ++ db_name = L"MokList"; ++ 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)) { +- console_error(L"Failed to get MokDelAuth", efi_status); ++ if (MokX) ++ console_error(L"Failed to get MokXDelAuth", efi_status); ++ else ++ console_error(L"Failed to get MokDelAuth", efi_status); + return efi_status; + } + +@@ -909,15 +968,18 @@ static EFI_STATUS delete_keys (void *MokDel, UINTN MokDelSize) + if (efi_status != EFI_SUCCESS) + return EFI_ACCESS_DENIED; + +- efi_status = get_variable_attr (L"MokList", &MokListData, &MokListDataSize, ++ efi_status = get_variable_attr (db_name, &MokListData, &MokListDataSize, + shim_lock_guid, &attributes); + if (attributes & EFI_VARIABLE_RUNTIME_ACCESS) { +- console_alertbox((CHAR16 *[]){L"MokList is compromised!", +- L"Erase all keys in MokList!", +- NULL}); +- if (LibDeleteVariable(L"MokList", &shim_lock_guid) != EFI_SUCCESS) { +- console_notify(L"Failed to erase MokList"); ++ if (MokX) { ++ err_str1 = L"MokListX is compromised!"; ++ err_str2 = L"Erase all keys in MokListX!"; ++ } else { ++ err_str1 = L"MokList is compromised!"; ++ err_str2 = L"Erase all keys in MokList!"; + } ++ console_alertbox((CHAR16 *[]){err_str1, err_str2, NULL}); ++ LibDeleteVariable(db_name, &shim_lock_guid); + return EFI_ACCESS_DENIED; + } + +@@ -945,7 +1007,7 @@ static EFI_STATUS delete_keys (void *MokDel, UINTN MokDelSize) + } + } + +- efi_status = write_back_mok_list(mok, mok_num); ++ efi_status = write_back_mok_list(mok, mok_num, MokX); + + if (MokListData) + FreePool(MokListData); +@@ -957,27 +1019,38 @@ static EFI_STATUS delete_keys (void *MokDel, UINTN MokDelSize) + return efi_status; + } + +-static INTN mok_deletion_prompt (void *MokDel, UINTN MokDelSize) ++static INTN mok_deletion_prompt (void *MokDel, UINTN MokDelSize, BOOLEAN MokX) + { + EFI_GUID shim_lock_guid = SHIM_LOCK_GUID; + EFI_STATUS efi_status; ++ CHAR16 *title; ++ ++ if (MokX) ++ title = L"[Delete MOKX]"; ++ else ++ title = L"[Delete MOK]"; + +- if (list_keys(MokDel, MokDelSize, L"[Delete MOK]") != EFI_SUCCESS) { ++ if (list_keys(MokDel, MokDelSize, title) != EFI_SUCCESS) { + return 0; + } + + if (console_yes_no((CHAR16 *[]){L"Delete the key(s)?", NULL}) == 0) + return 0; + +- efi_status = delete_keys(MokDel, MokDelSize); ++ efi_status = delete_keys(MokDel, MokDelSize, MokX); + + if (efi_status != EFI_SUCCESS) { + console_notify(L"Failed to delete keys"); + return -1; + } + +- LibDeleteVariable(L"MokDel", &shim_lock_guid); +- LibDeleteVariable(L"MokDelAuth", &shim_lock_guid); ++ if (MokX) { ++ 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); ++ } + + console_notify(L"The system must now be rebooted"); + uefi_call_wrapper(RT->ResetSystem, 4, EfiResetWarm, +@@ -1396,7 +1469,7 @@ static EFI_STATUS enroll_file (void *data, UINTN datasize, BOOLEAN hash) + goto out; + } + +- mok_enrollment_prompt(mokbuffer, mokbuffersize, FALSE); ++ mok_enrollment_prompt(mokbuffer, mokbuffersize, FALSE, FALSE); + out: + if (mokbuffer) + FreePool(mokbuffer); +@@ -1631,8 +1704,11 @@ static int draw_countdown() + typedef enum { + MOK_CONTINUE_BOOT, + MOK_RESET_MOK, ++ MOK_RESET_MOKX, + MOK_ENROLL_MOK, ++ MOK_ENROLL_MOKX, + MOK_DELETE_MOK, ++ MOK_DELETE_MOKX, + MOK_CHANGE_SB, + MOK_SET_PW, + MOK_CHANGE_DB, +@@ -1645,13 +1721,17 @@ static EFI_STATUS enter_mok_menu(EFI_HANDLE image_handle, + void *MokDel, UINTN MokDelSize, + void *MokSB, UINTN MokSBSize, + void *MokPW, UINTN MokPWSize, +- void *MokDB, UINTN MokDBSize) ++ void *MokDB, UINTN MokDBSize, ++ void *MokXNew, UINTN MokXNewSize, ++ void *MokXDel, UINTN MokXDelSize) + { + CHAR16 **menu_strings; + mok_menu_item *menu_item; + int choice = 0; + UINT32 MokAuth = 0; + UINT32 MokDelAuth = 0; ++ UINT32 MokXAuth = 0; ++ UINT32 MokXDelAuth = 0; + UINTN menucount = 3, i = 0; + EFI_STATUS efi_status; + EFI_GUID shim_lock_guid = SHIM_LOCK_GUID; +@@ -1680,12 +1760,34 @@ static EFI_STATUS enter_mok_menu(EFI_HANDLE image_handle, + (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)) ++ 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)) ++ MokXDelAuth = 1; ++ + if (MokNew || MokAuth) + menucount++; + + if (MokDel || MokDelAuth) + menucount++; + ++ if (MokXNew || MokXAuth) ++ menucount++; ++ ++ if (MokXDel || MokXDelAuth) ++ menucount++; ++ + if (MokSB) + menucount++; + +@@ -1723,12 +1825,29 @@ static EFI_STATUS enter_mok_menu(EFI_HANDLE image_handle, + i++; + } + +- if (MokDel || MokDelAuth) { ++ if (MokDel || MokDelAuth) { + menu_strings[i] = L"Delete MOK"; + menu_item[i] = MOK_DELETE_MOK; + i++; + } + ++ if (MokXNew || MokXAuth) { ++ if (!MokXNew) { ++ menu_strings[i] = L"Reset MOKX"; ++ menu_item[i] = MOK_RESET_MOKX; ++ } else { ++ menu_strings[i] = L"Enroll MOKX"; ++ menu_item[i] = MOK_ENROLL_MOKX; ++ } ++ i++; ++ } ++ ++ if (MokXDel || MokXDelAuth) { ++ menu_strings[i] = L"Delete MOKX"; ++ menu_item[i] = MOK_DELETE_MOKX; ++ i++; ++ } ++ + if (MokSB) { + menu_strings[i] = L"Change Secure Boot state"; + menu_item[i] = MOK_CHANGE_SB; +@@ -1771,13 +1890,22 @@ static EFI_STATUS enter_mok_menu(EFI_HANDLE image_handle, + case MOK_CONTINUE_BOOT: + goto out; + case MOK_RESET_MOK: +- mok_reset_prompt(); ++ mok_reset_prompt(FALSE); + break; + case MOK_ENROLL_MOK: +- mok_enrollment_prompt(MokNew, MokNewSize, TRUE); ++ mok_enrollment_prompt(MokNew, MokNewSize, TRUE, FALSE); + break; + case MOK_DELETE_MOK: +- mok_deletion_prompt(MokDel, MokDelSize); ++ mok_deletion_prompt(MokDel, MokDelSize, FALSE); ++ break; ++ case MOK_RESET_MOKX: ++ mok_reset_prompt(TRUE); ++ break; ++ case MOK_ENROLL_MOKX: ++ mok_enrollment_prompt(MokXNew, MokXNewSize, TRUE, TRUE); ++ break; ++ case MOK_DELETE_MOKX: ++ mok_deletion_prompt(MokXDel, MokXDelSize, TRUE); + break; + case MOK_CHANGE_SB: + mok_sb_prompt(MokSB, MokSBSize); +@@ -1811,13 +1939,15 @@ 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, +- MokDBSize = 0; ++ UINTN MokNewSize = 0, MokDelSize = 0, MokSBSize = 0, MokPWSize = 0; ++ UINTN MokDBSize = 0, MokXNewSize = 0, MokXDelSize = 0; + void *MokNew = NULL; + void *MokDel = NULL; + void *MokSB = NULL; + void *MokPW = NULL; + void *MokDB = NULL; ++ void *MokXNew = NULL; ++ void *MokXDel = NULL; + EFI_STATUS status; + + status = get_variable(L"MokNew", (UINT8 **)&MokNew, &MokNewSize, +@@ -1870,8 +2000,29 @@ static EFI_STATUS check_mok_request(EFI_HANDLE image_handle) + console_error(L"Could not retrieve MokDB", 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) { ++ console_notify(L"Failed to delete MokXNew"); ++ } ++ } else if (EFI_ERROR(status) && status != EFI_NOT_FOUND) { ++ console_error(L"Could not retrieve MokXNew", 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) { ++ console_notify(L"Failed to delete MokXDel"); ++ } ++ } else if (EFI_ERROR(status) && status != EFI_NOT_FOUND) { ++ console_error(L"Could not retrieve MokXDel", status); ++ } ++ + enter_mok_menu(image_handle, MokNew, MokNewSize, MokDel, MokDelSize, +- MokSB, MokSBSize, MokPW, MokPWSize, MokDB, MokDBSize); ++ MokSB, MokSBSize, MokPW, MokPWSize, MokDB, MokDBSize, ++ MokXNew, MokXNewSize, MokXDel, MokXDelSize); + + if (MokNew) + FreePool (MokNew); +@@ -1888,8 +2039,16 @@ static EFI_STATUS check_mok_request(EFI_HANDLE image_handle) + if (MokDB) + FreePool (MokDB); + ++ if (MokXNew) ++ FreePool (MokXNew); ++ ++ if (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); + + return EFI_SUCCESS; + } +diff --git a/shim.c b/shim.c +index 9ae1936..c133bb2 100644 +--- a/shim.c ++++ b/shim.c +@@ -1510,7 +1510,8 @@ EFI_STATUS check_mok_request(EFI_HANDLE image_handle) + + 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"MokDel") || check_var(L"MokDB") || ++ check_var(L"MokXNew") || check_var(L"MokXDel")) { + efi_status = start_image(image_handle, MOK_MANAGER); + + if (efi_status != EFI_SUCCESS) { +-- +1.8.1.4 + + +From f36f4093bb72344242949b16b83905cefb93d3cd Mon Sep 17 00:00:00 2001 +From: Gary Ching-Pang Lin +Date: Thu, 24 Oct 2013 17:32:31 +0800 +Subject: [PATCH 2/9] MokManager: show the hash list properly + +--- + MokManager.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++++-------- + 1 file changed, 71 insertions(+), 11 deletions(-) + +diff --git a/MokManager.c b/MokManager.c +index b9b42b6..5575a94 100644 +--- a/MokManager.c ++++ b/MokManager.c +@@ -165,9 +165,16 @@ static MokListNode *build_mok_list(UINT32 num, void *Data, UINTN DataSize) { + Cert = (EFI_SIGNATURE_DATA *) (((UINT8 *) CertList) + + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize); + +- list[count].MokSize = CertList->SignatureSize - sizeof(EFI_GUID); +- list[count].Mok = (void *)Cert->SignatureData; + list[count].Type = CertList->SignatureType; ++ if (CompareGuid (&CertList->SignatureType, &CertType) == 0) { ++ list[count].MokSize = CertList->SignatureSize - ++ sizeof(EFI_GUID); ++ list[count].Mok = (void *)Cert->SignatureData; ++ } else { ++ list[count].MokSize = CertList->SignatureListSize - ++ sizeof(EFI_SIGNATURE_LIST); ++ list[count].Mok = (void *)Cert; ++ } + + count++; + dbsize -= CertList->SignatureListSize; +@@ -373,7 +380,7 @@ static void show_x509_info (X509 *X509Cert, UINT8 *hash) + FreePool(text); + } + +-static void show_efi_hash (UINT8 *hash) ++static void show_sha256_digest (UINT8 *hash) + { + CHAR16 *text[5]; + POOL_PRINT hash_string1; +@@ -404,16 +411,68 @@ static void show_efi_hash (UINT8 *hash) + FreePool(hash_string2.str); + } + +-static void show_mok_info (void *Mok, UINTN MokSize) ++static void show_efi_hash (void *Mok, UINTN MokSize) ++{ ++ UINTN sig_size; ++ UINTN hash_num; ++ UINT8 *hash; ++ CHAR16 **menu_strings; ++ int key_num = 0; ++ int i; ++ ++ sig_size = SHA256_DIGEST_SIZE + sizeof(EFI_GUID); ++ if ((MokSize % sig_size) != 0) { ++ console_errorbox(L"Corrupted Hash List"); ++ return; ++ } ++ hash_num = MokSize / sig_size; ++ ++ if (hash_num == 1) { ++ hash = (UINT8 *)Mok + sizeof(EFI_GUID); ++ show_sha256_digest(hash); ++ return; ++ } ++ ++ menu_strings = AllocateZeroPool(sizeof(CHAR16 *) * (hash_num + 2)); ++ if (!menu_strings) { ++ console_errorbox(L"Out of Resources"); ++ return; ++ } ++ for (i=0; i= hash_num) ++ break; ++ ++ hash = (UINT8 *)Mok + sig_size*key_num + sizeof(EFI_GUID); ++ show_sha256_digest(hash); ++ } ++ ++ 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) + { + EFI_STATUS efi_status; + UINT8 hash[SHA1_DIGEST_SIZE]; + X509 *X509Cert; ++ EFI_GUID CertType = X509_GUID; ++ EFI_GUID HashType = EFI_CERT_SHA256_GUID; + + if (!Mok || MokSize == 0) + return; + +- if (MokSize != SHA256_DIGEST_SIZE) { ++ if (CompareGuid (&Type, &CertType) == 0) { + efi_status = get_sha1sum(Mok, MokSize, hash); + + if (efi_status != EFI_SUCCESS) { +@@ -429,8 +488,8 @@ static void show_mok_info (void *Mok, UINTN MokSize) + console_notify(L"Not a valid X509 certificate"); + return; + } +- } else { +- show_efi_hash(Mok); ++ } else if (CompareGuid (&Type, &HashType) == 0) { ++ show_efi_hash(Mok, MokSize); + } + } + +@@ -438,7 +497,7 @@ static EFI_STATUS list_keys (void *KeyList, UINTN KeyListSize, CHAR16 *title) + { + UINT32 MokNum = 0; + MokListNode *keys = NULL; +- INTN key_num = 0; ++ int key_num = 0; + CHAR16 **menu_strings; + int i; + +@@ -472,10 +531,11 @@ static EFI_STATUS list_keys (void *KeyList, UINTN KeyListSize, CHAR16 *title) + key_num = console_select((CHAR16 *[]){ title, NULL }, + menu_strings, 0); + +- if (key_num < 0) ++ if (key_num < 0 || key_num >= MokNum) + break; +- else if (key_num < MokNum) +- show_mok_info(keys[key_num].Mok, keys[key_num].MokSize); ++ ++ show_mok_info(keys[key_num].Type, keys[key_num].Mok, ++ keys[key_num].MokSize); + } + + for (i=0; menu_strings[i] != NULL; i++) +-- +1.8.1.4 + + +From f1073a9bc757008d44b5b86cb5002a3654faf2d2 Mon Sep 17 00:00:00 2001 +From: Gary Ching-Pang Lin +Date: Fri, 25 Oct 2013 16:54:25 +0800 +Subject: [PATCH 3/9] MokManager: delete the hash properly + +--- + MokManager.c | 124 ++++++++++++++++++++++++++++++++++++++++++++++++++++++----- + 1 file changed, 114 insertions(+), 10 deletions(-) + +diff --git a/MokManager.c b/MokManager.c +index 5575a94..23bdeef 100644 +--- a/MokManager.c ++++ b/MokManager.c +@@ -981,9 +981,116 @@ 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) ++{ ++ EFI_GUID CertType = X509_GUID; ++ int i; ++ ++ for (i = 0; i < mok_num; i++) { ++ if (CompareGuid(&(mok[i].Type), &CertType) != 0) ++ continue; ++ ++ if (mok[i].MokSize == key_size && ++ CompareMem(key, mok[i].Mok, key_size) == 0) { ++ /* Remove the key */ ++ mok[i].Mok = NULL; ++ mok[i].MokSize = 0; ++ } ++ } ++} ++ ++static int match_hash (UINT8 *hash, UINT32 hash_size, ++ void *hash_list, UINT32 list_num) ++{ ++ UINT8 *ptr; ++ int i; ++ ++ ptr = hash_list + sizeof(EFI_GUID); ++ for (i = 0; i < list_num; i++) { ++ if (CompareMem(hash, ptr, hash_size) == 0) ++ return i; ++ ptr += hash_size + sizeof(EFI_GUID); ++ } ++ ++ return -1; ++} ++ ++static void mem_move (void *dest, void *src, UINTN size) ++{ ++ UINT8 *d, *s; ++ int i; ++ ++ d = (UINT8 *)dest; ++ s = (UINT8 *)src; ++ for (i = 0; i < size; i++) ++ d[i] = s[i]; ++} ++ ++static void delete_hash_in_list (UINT8 *hash, UINT32 hash_size, ++ MokListNode *mok, INTN mok_num) ++{ ++ EFI_GUID HashType = EFI_CERT_SHA256_GUID; ++ UINT32 sig_size; ++ int i, del_ind; ++ void *start, *end; ++ UINT32 remain; ++ ++ sig_size = hash_size + sizeof(EFI_GUID); ++ ++ for (i = 0; i < mok_num; i++) { ++ if ((CompareGuid(&(mok[i].Type), &HashType) != 0) || ++ (mok[i].MokSize < sig_size)) ++ continue; ++ ++ del_ind = match_hash(hash, hash_size, mok[i].Mok, ++ mok[i].MokSize); ++ if (del_ind < 0) ++ continue; ++ /* Remove the hash */ ++ if (sig_size == mok[i].MokSize) { ++ mok[i].Mok = NULL; ++ mok[i].MokSize = 0; ++ } else { ++ start = mok[i].Mok + del_ind * sig_size; ++ end = start + sig_size; ++ remain = mok[i].MokSize - (del_ind + 1)*sig_size; ++ ++ mem_move(start, end, remain); ++ mok[i].MokSize -= sig_size; ++ } ++ } ++} ++ ++static void delete_hash_list (void *hash_list, UINT32 list_size, ++ MokListNode *mok, INTN mok_num) ++{ ++ UINT32 hash_size; ++ UINT32 hash_num; ++ UINT32 sig_size; ++ UINT8 *hash; ++ int i; ++ ++ hash_size = SHA256_DIGEST_SIZE; ++ sig_size = hash_size + sizeof(EFI_GUID); ++ if (list_size < sig_size) ++ return; ++ ++ hash_num = list_size / sig_size; ++ ++ hash = hash_list + sizeof(EFI_GUID); ++ ++ for (i = 0; i < hash_num; i++) { ++ delete_hash_in_list (hash, hash_size, mok, mok_num); ++ hash += sig_size; ++ } ++} ++ + 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_GUID HashType = EFI_CERT_SHA256_GUID; + EFI_STATUS efi_status; + CHAR16 *db_name; + CHAR16 *auth_name; +@@ -996,7 +1103,7 @@ static EFI_STATUS delete_keys (void *MokDel, UINTN MokDelSize, BOOLEAN MokX) + UINTN MokListDataSize = 0; + MokListNode *mok, *del_key; + INTN mok_num, del_num; +- int i, j; ++ int i; + + if (MokX) { + db_name = L"MokListX"; +@@ -1055,15 +1162,12 @@ static EFI_STATUS delete_keys (void *MokDel, UINTN MokDelSize, BOOLEAN MokX) + + /* Search and destroy */ + for (i = 0; i < del_num; i++) { +- UINT32 key_size = del_key[i].MokSize; +- void *key = del_key[i].Mok; +- for (j = 0; j < mok_num; j++) { +- if (mok[j].MokSize == key_size && +- CompareMem(key, mok[j].Mok, key_size) == 0) { +- /* Remove the key */ +- mok[j].Mok = NULL; +- mok[j].MokSize = 0; +- } ++ if (CompareGuid(&(del_key[i].Type), &CertType) == 0) { ++ delete_cert(del_key[i].Mok, del_key[i].MokSize, ++ mok, mok_num); ++ } else if (CompareGuid(&(del_key[i].Type), &HashType) == 0) { ++ delete_hash_list(del_key[i].Mok, del_key[i].MokSize, ++ mok, mok_num); + } + } + +-- +1.8.1.4 + + +From b5cb83a92620b0b41857f3e3a292d1577eb3a3a5 Mon Sep 17 00:00:00 2001 +From: Gary Ching-Pang Lin +Date: Fri, 25 Oct 2013 17:05:10 +0800 +Subject: [PATCH 4/9] MokManager: Match all hashes in the list + +--- + MokManager.c | 24 ++++++++++++++---------- + 1 file changed, 14 insertions(+), 10 deletions(-) + +diff --git a/MokManager.c b/MokManager.c +index 23bdeef..5b40e19 100644 +--- a/MokManager.c ++++ b/MokManager.c +@@ -1000,14 +1000,14 @@ static void delete_cert (void *key, UINT32 key_size, + } + } + +-static int match_hash (UINT8 *hash, UINT32 hash_size, ++static int match_hash (UINT8 *hash, UINT32 hash_size, int start, + void *hash_list, UINT32 list_num) + { + UINT8 *ptr; + int i; + + ptr = hash_list + sizeof(EFI_GUID); +- for (i = 0; i < list_num; i++) { ++ for (i = start; i < list_num; i++) { + if (CompareMem(hash, ptr, hash_size) == 0) + return i; + ptr += hash_size + sizeof(EFI_GUID); +@@ -1043,21 +1043,25 @@ static void delete_hash_in_list (UINT8 *hash, UINT32 hash_size, + (mok[i].MokSize < sig_size)) + continue; + +- del_ind = match_hash(hash, hash_size, mok[i].Mok, ++ del_ind = match_hash(hash, hash_size, 0, mok[i].Mok, + mok[i].MokSize); +- if (del_ind < 0) +- continue; +- /* Remove the hash */ +- if (sig_size == mok[i].MokSize) { +- mok[i].Mok = NULL; +- mok[i].MokSize = 0; +- } else { ++ while (del_ind >= 0) { ++ /* Remove the hash */ ++ if (sig_size == mok[i].MokSize) { ++ mok[i].Mok = NULL; ++ mok[i].MokSize = 0; ++ break; ++ } ++ + start = mok[i].Mok + del_ind * sig_size; + end = start + sig_size; + remain = mok[i].MokSize - (del_ind + 1)*sig_size; + + mem_move(start, end, remain); + mok[i].MokSize -= sig_size; ++ ++ del_ind = match_hash(hash, hash_size, del_ind, ++ mok[i].Mok, mok[i].MokSize); + } + } + } +-- +1.8.1.4 + + +From 70a4e12d2e6ba37541d0b78ec3c8ed5e8da9a941 Mon Sep 17 00:00:00 2001 +From: Gary Ching-Pang Lin +Date: Fri, 25 Oct 2013 18:30:48 +0800 +Subject: [PATCH 5/9] MokManager: Write the hash list properly + +also return to the previous entry in the list +--- + MokManager.c | 30 +++++++++++++++++++----------- + 1 file changed, 19 insertions(+), 11 deletions(-) + +diff --git a/MokManager.c b/MokManager.c +index 5b40e19..e79a8e0 100644 +--- a/MokManager.c ++++ b/MokManager.c +@@ -441,12 +441,12 @@ static void show_efi_hash (void *Mok, UINTN MokSize) + for (i=0; i= hash_num) + break; +@@ -529,7 +529,7 @@ static EFI_STATUS list_keys (void *KeyList, UINTN KeyListSize, CHAR16 *title) + + while (key_num < MokNum) { + key_num = console_select((CHAR16 *[]){ title, NULL }, +- menu_strings, 0); ++ menu_strings, key_num); + + if (key_num < 0 || key_num >= MokNum) + break; +@@ -916,6 +916,7 @@ 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; +@@ -952,17 +953,24 @@ static EFI_STATUS write_back_mok_list (MokListNode *list, INTN key_num, + sizeof(EFI_SIGNATURE_LIST)); + + CertList->SignatureType = list[i].Type; +- CertList->SignatureListSize = list[i].MokSize + +- sizeof(EFI_SIGNATURE_LIST) + +- sizeof(EFI_SIGNATURE_DATA) - 1; + CertList->SignatureHeaderSize = 0; +- CertList->SignatureSize = list[i].MokSize + sizeof(EFI_GUID); + +- CertData->SignatureOwner = shim_lock_guid; +- CopyMem(CertData->SignatureData, list[i].Mok, list[i].MokSize); ++ if (CompareGuid(&(list[i].Type), &CertType) == 0) { ++ CertList->SignatureListSize = list[i].MokSize + ++ sizeof(EFI_SIGNATURE_LIST) + ++ sizeof(EFI_GUID); ++ CertList->SignatureSize = list[i].MokSize + sizeof(EFI_GUID); + +- ptr = (uint8_t *)ptr + sizeof(EFI_SIGNATURE_LIST) + +- sizeof(EFI_GUID) + 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 = SHA256_DIGEST_SIZE + sizeof(EFI_GUID); ++ ++ CopyMem(CertData, list[i].Mok, list[i].MokSize); ++ } ++ ptr = (uint8_t *)ptr + CertList->SignatureListSize; + } + + efi_status = uefi_call_wrapper(RT->SetVariable, 5, db_name, +-- +1.8.1.4 + + +From 225e5fca2f7cf63e365b77243d6e43b1eb9860c8 Mon Sep 17 00:00:00 2001 +From: Gary Ching-Pang Lin +Date: Mon, 28 Oct 2013 15:08:40 +0800 +Subject: [PATCH 6/9] Copy the MOK blacklist to a RT variable + +--- + shim.c | 29 +++++++++++++++++++++++++++++ + 1 file changed, 29 insertions(+) + +diff --git a/shim.c b/shim.c +index c133bb2..a0383a8 100644 +--- a/shim.c ++++ b/shim.c +@@ -1480,6 +1480,33 @@ EFI_STATUS mirror_mok_list() + } + + /* ++ * 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; ++} ++ ++/* + * Check if a variable exists + */ + static BOOLEAN check_var(CHAR16 *varname) +@@ -1795,6 +1822,8 @@ EFI_STATUS efi_main (EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *passed_systab) + */ + efi_status = mirror_mok_list(); + ++ efi_status = mirror_mok_list_x(); ++ + /* + * Create the runtime MokIgnoreDB variable so the kernel can make + * use of it +-- +1.8.1.4 + + +From f9db55b719281ce491780ecd4ec269c5286a7251 Mon Sep 17 00:00:00 2001 +From: Gary Ching-Pang Lin +Date: Mon, 28 Oct 2013 16:36:34 +0800 +Subject: [PATCH 7/9] No newline for console_notify + +--- + shim.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/shim.c b/shim.c +index a0383a8..a2e0862 100644 +--- a/shim.c ++++ b/shim.c +@@ -470,7 +470,7 @@ static BOOLEAN secure_mode (void) + + if (sb != 1) { + if (verbose) +- console_notify(L"Secure boot not enabled\n"); ++ console_notify(L"Secure boot not enabled"); + return FALSE; + } + +@@ -483,7 +483,7 @@ static BOOLEAN secure_mode (void) + + if (setupmode == 1) { + if (verbose) +- console_notify(L"Platform is in setup mode\n"); ++ console_notify(L"Platform is in setup mode"); + return FALSE; + } + +-- +1.8.1.4 + + +From 0bf2da5c7d9442f3249fc977b3fbffab924a374c Mon Sep 17 00:00:00 2001 +From: Gary Ching-Pang Lin +Date: Mon, 4 Nov 2013 14:45:33 +0800 +Subject: [PATCH 8/9] Verify the EFI images with MOK blacklist + +Signed-off-by: Gary Ching-Pang Lin +--- + shim.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/shim.c b/shim.c +index a2e0862..5f5e9a6 100644 +--- a/shim.c ++++ b/shim.c +@@ -365,6 +365,7 @@ 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, +@@ -388,6 +389,14 @@ static EFI_STATUS check_blacklist (WIN_CERTIFICATE_EFI_PKCS *cert, + if (cert && check_db_cert(L"dbx", secure_var, cert, sha256hash) == + DATA_FOUND) + return EFI_ACCESS_DENIED; ++ if (check_db_hash(L"MokListX", shim_var, sha256hash, SHA256_DIGEST_SIZE, ++ EFI_CERT_SHA256_GUID) == DATA_FOUND) { ++ return EFI_ACCESS_DENIED; ++ } ++ if (cert && check_db_cert(L"MokListX", shim_var, cert, sha256hash) == ++ DATA_FOUND) { ++ return EFI_ACCESS_DENIED; ++ } + + return EFI_SUCCESS; + } +-- +1.8.1.4 + + +From 20ced27d1785bceaf814c07ca0d5686506a119ad Mon Sep 17 00:00:00 2001 +From: Gary Ching-Pang Lin +Date: Mon, 4 Nov 2013 17:51:55 +0800 +Subject: [PATCH 9/9] Exclude ca.crt while signing EFI images + +If ca.crt was added into the certificate database, ca.crt would be the first +certificate in the signature. Because shim couldn't verify ca.crt with the +embedded shim.cer, it failed to load MokManager.efi.signed and +fallback.efi.signed. + +Signed-off-by: Gary Ching-Pang Lin +--- + Makefile | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/Makefile b/Makefile +index e65d28d..5e3fa9e 100644 +--- a/Makefile ++++ b/Makefile +@@ -72,7 +72,6 @@ version.c : version.c.in + + certdb/secmod.db: shim.crt + -mkdir certdb +- certutil -A -n 'my CA' -d certdb/ -t CT,CT,CT -i ca.crt + pk12util -d certdb/ -i shim.p12 -W "" -K "" + certutil -d certdb/ -A -i shim.crt -n shim -t u + +-- +1.8.1.4 + diff --git a/shim-netboot-fixes.patch b/shim-netboot-fixes.patch deleted file mode 100644 index ebf05ea..0000000 --- a/shim-netboot-fixes.patch +++ /dev/null @@ -1,370 +0,0 @@ -From 6bd858269e91b3966c569f5d18a6fd3932b65112 Mon Sep 17 00:00:00 2001 -From: Steve Langasek -Date: Fri, 20 Sep 2013 11:29:23 -0500 -Subject: [PATCH 1/7] Pass the right arguments to - EFI_PXE_BASE_CODE_TFTP_READ_FILE - -A wrong pointer was being passed to EFI_PXE_BASE_CODE_TFTP_READ_FILE, -preventing us from getting the file size back from the tftp call, ensuring -that we don't have enough information to properly secureboot-validate the -retrieved image. ---- - netboot.c | 4 ++-- - shim.c | 2 +- - 2 files changed, 3 insertions(+), 3 deletions(-) - -diff --git a/netboot.c b/netboot.c -index d569048..f7a6a1a 100644 ---- a/netboot.c -+++ b/netboot.c -@@ -328,7 +328,7 @@ EFI_STATUS parseNetbootinfo(EFI_HANDLE image_handle) - return rc; - } - --EFI_STATUS FetchNetbootimage(EFI_HANDLE image_handle, VOID **buffer, UINTN *bufsiz) -+EFI_STATUS FetchNetbootimage(EFI_HANDLE image_handle, VOID **buffer, UINT64 *bufsiz) - { - EFI_STATUS rc; - EFI_PXE_BASE_CODE_TFTP_OPCODE read = EFI_PXE_BASE_CODE_TFTP_READ_FILE; -@@ -346,7 +346,7 @@ EFI_STATUS FetchNetbootimage(EFI_HANDLE image_handle, VOID **buffer, UINTN *bufs - - try_again: - rc = uefi_call_wrapper(pxe->Mtftp, 10, pxe, read, *buffer, overwrite, -- &bufsiz, &blksz, &tftp_addr, full_path, NULL, nobuffer); -+ bufsiz, &blksz, &tftp_addr, full_path, NULL, nobuffer); - - if (rc == EFI_BUFFER_TOO_SMALL) { - /* try again, doubling buf size */ -diff --git a/shim.c b/shim.c -index 47e3812..c1bb85f 100644 ---- a/shim.c -+++ b/shim.c -@@ -1193,7 +1193,7 @@ EFI_STATUS start_image(EFI_HANDLE image_handle, CHAR16 *ImagePath) - EFI_DEVICE_PATH *path; - CHAR16 *PathName = NULL; - void *sourcebuffer = NULL; -- UINTN sourcesize = 0; -+ UINT64 sourcesize = 0; - void *data = NULL; - int datasize; - --- -1.8.1.4 - - -From b1fa932c45038fbe280420b88f0103610fff48aa Mon Sep 17 00:00:00 2001 -From: Steve Langasek -Date: Fri, 20 Sep 2013 13:03:57 -0500 -Subject: [PATCH 2/7] Fix nul termination errors in filenames passed to tftp - -Fix various errors in the tftp string handling, to ensure we always have -properly nul-terminated strings. ---- - netboot.c | 39 ++++++++++++++++----------------------- - 1 file changed, 16 insertions(+), 23 deletions(-) - -diff --git a/netboot.c b/netboot.c -index f7a6a1a..b31e71c 100644 ---- a/netboot.c -+++ b/netboot.c -@@ -54,7 +54,7 @@ static inline unsigned short int __swap16(unsigned short int x) - - static EFI_PXE_BASE_CODE *pxe; - static EFI_IP_ADDRESS tftp_addr; --static char *full_path; -+static UINT8 *full_path; - - - typedef struct { -@@ -112,7 +112,7 @@ try_again: - for (i=0; i < (bs / sizeof(EFI_HANDLE)); i++) { - status = uefi_call_wrapper(BS->OpenProtocol, 6, hbuf[i], - &pxe_base_code_protocol, -- &pxe, image_handle, NULL, -+ (void **)&pxe, image_handle, NULL, - EFI_OPEN_PROTOCOL_GET_PROTOCOL); - - if (status != EFI_SUCCESS) { -@@ -228,15 +228,15 @@ static UINT8 *str2ip6(char *str) - - static BOOLEAN extract_tftp_info(char *url) - { -- char *start, *end; -+ CHAR8 *start, *end; - char ip6str[128]; -- char *template = DEFAULT_LOADER; -+ CHAR8 *template = (CHAR8 *)DEFAULT_LOADER; - - if (strncmp((UINT8 *)url, (UINT8 *)"tftp://", 7)) { - Print(L"URLS MUST START WITH tftp://\n"); - return FALSE; - } -- start = url + 7; -+ start = (CHAR8 *)url + 7; - if (*start != '[') { - Print(L"TFTP SERVER MUST BE ENCLOSED IN [..]\n"); - return FALSE; -@@ -251,21 +251,19 @@ static BOOLEAN extract_tftp_info(char *url) - Print(L"TFTP SERVER MUST BE ENCLOSED IN [..]\n"); - return FALSE; - } -- *end = '\0'; - memset(ip6str, 0, 128); -- memcpy(ip6str, start, strlen((UINT8 *)start)); -- *end = ']'; -+ memcpy(ip6str, start, end + 1 - start); - end++; - memcpy(&tftp_addr.v6, str2ip6(ip6str), 16); -- full_path = AllocatePool(strlen((UINT8 *)end)+strlen((UINT8 *)template)+1); -+ full_path = AllocateZeroPool(strlen(end)+strlen(template)+1); - if (!full_path) - return FALSE; -- memset(full_path, 0, strlen((UINT8 *)end)+strlen((UINT8 *)template)); -- memcpy(full_path, end, strlen((UINT8 *)end)); -- end = strrchr(full_path, '/'); -+ memcpy(full_path, end, strlen(end)); -+ end = (CHAR8 *)strrchr((char *)full_path, '/'); - if (!end) -- end = full_path; -- memcpy(end, template, strlen((UINT8 *)template)); -+ end = (CHAR8 *)full_path; -+ memcpy(end, template, strlen(template)); -+ end[strlen(template)] = '\0'; - - return TRUE; - } -@@ -286,20 +284,15 @@ static EFI_STATUS parseDhcp6() - - static EFI_STATUS parseDhcp4() - { -- char *template = DEFAULT_LOADER; -- char *tmp; -- int len = strlen((CHAR8 *)template); -+ CHAR8 *template = (CHAR8 *)DEFAULT_LOADER; -+ full_path = AllocateZeroPool(strlen(template)+1); - -- tmp = AllocatePool(len+1); -- -- if (!tmp) -+ if (!full_path) - return EFI_OUT_OF_RESOURCES; - -- - memcpy(&tftp_addr.v4, pxe->Mode->DhcpAck.Dhcpv4.BootpSiAddr, 4); - -- memcpy(tmp, template, len+1); -- full_path = tmp; -+ memcpy(full_path, template, strlen(template)); - - /* Note we don't capture the filename option here because we know its shim.efi - * We instead assume the filename at the end of the path is going to be grubx64.efi --- -1.8.1.4 - - -From a68d8233dcc76094813e5c235a80fb6c7ec6ad7c Mon Sep 17 00:00:00 2001 -From: Steve Langasek -Date: Fri, 20 Sep 2013 17:06:33 -0500 -Subject: [PATCH 3/7] Fix an off-by-one error - -We don't need to add one because our end pointer is already off the end of -the string we want to copy. ---- - netboot.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/netboot.c b/netboot.c -index b31e71c..15dbdf7 100644 ---- a/netboot.c -+++ b/netboot.c -@@ -252,7 +252,7 @@ static BOOLEAN extract_tftp_info(char *url) - return FALSE; - } - memset(ip6str, 0, 128); -- memcpy(ip6str, start, end + 1 - start); -+ memcpy(ip6str, start, end - start); - end++; - memcpy(&tftp_addr.v6, str2ip6(ip6str), 16); - full_path = AllocateZeroPool(strlen(end)+strlen(template)+1); --- -1.8.1.4 - - -From bbaa1df5dcc6570dc29544dbcc00353f925a1128 Mon Sep 17 00:00:00 2001 -From: Steve Langasek -Date: Sun, 22 Sep 2013 22:21:49 -0700 -Subject: [PATCH 4/7] Misc allocation cleanups - ---- - netboot.c | 10 ++++++---- - 1 file changed, 6 insertions(+), 4 deletions(-) - -diff --git a/netboot.c b/netboot.c -index 15dbdf7..c81e28e 100644 ---- a/netboot.c -+++ b/netboot.c -@@ -160,10 +160,9 @@ static char *get_v6_bootfile_url(EFI_PXE_BASE_CODE_DHCPV6_PACKET *pkt) - if (ntohs(option->OpCode) == 59) { - /* This is the bootfile url option */ - urllen = ntohs(option->Length); -- url = AllocatePool(urllen+2); -+ url = AllocateZeroPool(urllen+1); - if (!url) - return NULL; -- memset(url, 0, urllen+2); - memcpy(url, option->Data, urllen); - return url; - } -@@ -275,10 +274,13 @@ static EFI_STATUS parseDhcp6() - - - bootfile_url = get_v6_bootfile_url(packet); -- if (extract_tftp_info(bootfile_url) == FALSE) -- return EFI_NOT_FOUND; - if (!bootfile_url) - return EFI_NOT_FOUND; -+ if (extract_tftp_info(bootfile_url) == FALSE) { -+ FreePool(bootfile_url); -+ return EFI_NOT_FOUND; -+ } -+ FreePool(bootfile_url); - return EFI_SUCCESS; - } - --- -1.8.1.4 - - -From 4b1e7425479a111553f1055757429249bc389d28 Mon Sep 17 00:00:00 2001 -From: Steve Langasek -Date: Sun, 22 Sep 2013 22:25:47 -0700 -Subject: [PATCH 5/7] More consistent types, fewer casts - ---- - netboot.c | 11 +++++------ - 1 file changed, 5 insertions(+), 6 deletions(-) - -diff --git a/netboot.c b/netboot.c -index c81e28e..dab1f5c 100644 ---- a/netboot.c -+++ b/netboot.c -@@ -142,11 +142,11 @@ try_again: - return rc; - } - --static char *get_v6_bootfile_url(EFI_PXE_BASE_CODE_DHCPV6_PACKET *pkt) -+static CHAR8 *get_v6_bootfile_url(EFI_PXE_BASE_CODE_DHCPV6_PACKET *pkt) - { - void *optr; - EFI_DHCP6_PACKET_OPTION *option; -- char *url; -+ CHAR8 *url; - UINT32 urllen; - - optr = pkt->DhcpOptions; -@@ -225,7 +225,7 @@ static UINT8 *str2ip6(char *str) - return (UINT8 *)ip; - } - --static BOOLEAN extract_tftp_info(char *url) -+static BOOLEAN extract_tftp_info(CHAR8 *url) - { - CHAR8 *start, *end; - char ip6str[128]; -@@ -235,7 +235,7 @@ static BOOLEAN extract_tftp_info(char *url) - Print(L"URLS MUST START WITH tftp://\n"); - return FALSE; - } -- start = (CHAR8 *)url + 7; -+ start = url + 7; - if (*start != '[') { - Print(L"TFTP SERVER MUST BE ENCLOSED IN [..]\n"); - return FALSE; -@@ -270,8 +270,7 @@ static BOOLEAN extract_tftp_info(char *url) - static EFI_STATUS parseDhcp6() - { - EFI_PXE_BASE_CODE_DHCPV6_PACKET *packet = (EFI_PXE_BASE_CODE_DHCPV6_PACKET *)&pxe->Mode->DhcpAck.Raw; -- char *bootfile_url; -- -+ CHAR8 *bootfile_url; - - bootfile_url = get_v6_bootfile_url(packet); - if (!bootfile_url) --- -1.8.1.4 - - -From 12cd90c232301efe7d262a33c471a6af1282ae03 Mon Sep 17 00:00:00 2001 -From: Steve Langasek -Date: Sun, 22 Sep 2013 22:45:26 -0700 -Subject: [PATCH 6/7] Correct limits on the length of ipv6 addresses - -The maximum length of a string representation of an ipv6 address is 39 -characters (8 groups of 4 hex chars, with 7 colons in between). So don't -allocate more room than this - and more importantly, don't blindly accept -strings from the server that are longer than our buffer... ---- - netboot.c | 8 ++++++-- - 1 file changed, 6 insertions(+), 2 deletions(-) - -diff --git a/netboot.c b/netboot.c -index dab1f5c..61777a2 100644 ---- a/netboot.c -+++ b/netboot.c -@@ -228,7 +228,7 @@ static UINT8 *str2ip6(char *str) - static BOOLEAN extract_tftp_info(CHAR8 *url) - { - CHAR8 *start, *end; -- char ip6str[128]; -+ char ip6str[40]; - CHAR8 *template = (CHAR8 *)DEFAULT_LOADER; - - if (strncmp((UINT8 *)url, (UINT8 *)"tftp://", 7)) { -@@ -245,12 +245,16 @@ static BOOLEAN extract_tftp_info(CHAR8 *url) - end = start; - while ((*end != '\0') && (*end != ']')) { - end++; -+ if (end - start > 39) { -+ Print(L"TFTP URL includes malformed IPv6 address\n"); -+ return FALSE; -+ } - } - if (end == '\0') { - Print(L"TFTP SERVER MUST BE ENCLOSED IN [..]\n"); - return FALSE; - } -- memset(ip6str, 0, 128); -+ memset(ip6str, 0, 40); - memcpy(ip6str, start, end - start); - end++; - memcpy(&tftp_addr.v6, str2ip6(ip6str), 16); --- -1.8.1.4 - - -From 0c3bd9d9ea5261cfdf5c1d6feb2f42d17ba4ca8a Mon Sep 17 00:00:00 2001 -From: Steve Langasek -Date: Sun, 22 Sep 2013 23:11:26 -0700 -Subject: [PATCH 7/7] Fix a memory leak - ---- - netboot.c | 4 +++- - 1 file changed, 3 insertions(+), 1 deletion(-) - -diff --git a/netboot.c b/netboot.c -index 61777a2..927445d 100644 ---- a/netboot.c -+++ b/netboot.c -@@ -356,6 +356,8 @@ try_again: - goto try_again; - } - -+ if (rc != EFI_SUCCESS && *buffer) { -+ FreePool(*buffer); -+ } - return rc; -- - } --- -1.8.1.4 - diff --git a/shim-suse-build.patch b/shim-suse-build.patch deleted file mode 100644 index c1a758e..0000000 --- a/shim-suse-build.patch +++ /dev/null @@ -1,15 +0,0 @@ ---- - Makefile | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/Makefile -+++ b/Makefile -@@ -6,7 +6,7 @@ LIB_PATH = /usr/lib64 - - EFI_INCLUDE = /usr/include/efi - EFI_INCLUDES = -nostdinc -ICryptlib -ICryptlib/Include -I$(EFI_INCLUDE) -I$(EFI_INCLUDE)/$(ARCH) -I$(EFI_INCLUDE)/protocol --EFI_PATH = /usr/lib64/gnuefi -+EFI_PATH = /usr/lib64 - - 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) diff --git a/shim.changes b/shim.changes index f71f152..aa96f21 100644 --- a/shim.changes +++ b/shim.changes @@ -1,3 +1,30 @@ +------------------------------------------------------------------- +Thu Dec 5 02:05:13 UTC 2013 - glin@suse.com + +- Update to 0.7 +- Add upstream patches: + + shim-fix-verify-mok.patch + + shim-improve-error-messages.patch + + shim-correct-user_insecure-usage.patch + + shim-fix-dhcpv4-path-generation.patch +- Add shim-mokx-support.patch to support the MOK blacklist + (Fate#316531) +- Drop upstreamed patches + + shim-fix-pointer-casting.patch + + shim-merge-lf-loader-code.patch + + shim-fix-simple-file-selector.patch + + shim-mokmanager-support-crypt-hash-method.patch + + shim-bnc804631-fix-broken-bootpath.patch + + shim-bnc798043-no-doulbe-separators.patch + + shim-bnc807760-change-pxe-2nd-loader-name.patch + + shim-bnc808106-correct-certcount.patch + + shim-mokmanager-ui-revamp.patch + + shim-netboot-fixes.patch + + shim-mokmanager-disable-gfx-console.patch +- Drop shim-suse-build.patch: it's not necessary anymore +- Drop shim-bnc841426-silence-shim-protocols.patch: shim is not + verbose by default + ------------------------------------------------------------------- Thu Oct 31 09:11:18 UTC 2013 - fcrozat@suse.com diff --git a/shim.spec b/shim.spec index c8d8f20..da13aa3 100644 --- a/shim.spec +++ b/shim.spec @@ -19,7 +19,7 @@ # needssslcertforbuild Name: shim -Version: 0.4 +Version: 0.7 Release: 0 Summary: UEFI shim loader License: BSD-2-Clause @@ -38,32 +38,16 @@ Source7: show_hash.sh Source8: show_signatures.sh Source9: openSUSE-UEFI-CA-Certificate-4096.crt Source10: timestamp.pl -# PATCH-FIX-SUSE shim-suse-build.patch glin@suse.com -- Adjust Makefile for the build service -Patch0: shim-suse-build.patch -# PATCH-FIX-UPSTREAM shim-fix-pointer-casting.patch glin@suse.com -- Fix a casting issue and the size of an empty vendor_cert or dbx_cert. -Patch1: shim-fix-pointer-casting.patch -# PATCH-FIX-UPSTREAM shim-merge-lf-loader-code.patch glin@suse.com -- Merge the Linux Foundation loader UI code -Patch2: shim-merge-lf-loader-code.patch -# PATCH-FIX-UPSTREAM shim-fix-simple-file-selector.patch glin@suse.com -- Fix the buffer allocation in the simple file selector -Patch3: shim-fix-simple-file-selector.patch -# PATCH-FIX-UPSTREAM shim-mokmanager-support-crypt-hash-method.patch glin@suse.com -- Support the password hashes from /etc/shadow -Patch4: shim-mokmanager-support-crypt-hash-method.patch -# PATCH-FIX-UPSTREAM shim-bnc804631-fix-broken-bootpath.patch bnc#804631 glin@suse.com -- Fix the broken bootpath generated in generate_path() -Patch5: shim-bnc804631-fix-broken-bootpath.patch -# PATCH-FIX-UPSTREAM shim-bnc798043-no-doulbe-separators.patch bnc#798043 glin@suse.com -- Remove all double-separators from the bootpath -Patch6: shim-bnc798043-no-doulbe-separators.patch -# PATCH-FIX-UPSTREAM shim-bnc807760-change-pxe-2nd-loader-name.patch bnc#807760 glin@suse.com -- Change the PXE 2nd stage loader to match the filename we are using -Patch7: shim-bnc807760-change-pxe-2nd-loader-name.patch -# PATCH-FIX-UPSTREAM shim-bnc808106-correct-certcount.patch bnc#808106 glin@suse.com -- Correct the certifcate count of the signature list -Patch8: shim-bnc808106-correct-certcount.patch -# PATCH-FIX-UPSTREAM shim-mokmanager-ui-revamp.patch glin@suse.com -- Revamp the MokManager UI -Patch9: shim-mokmanager-ui-revamp.patch -# PATCH-FIX-UPSTREAM shim-netboot-fixes.patch glin@suse.com -- Upstream netboot fixes -Patch10: shim-netboot-fixes.patch -# PATCH-FIX-UPSTREAM shim-mokmanager-disable-gfx-console.patch glin@suse.com -- Disable graphics console to avoid system hang on some machines -Patch11: shim-mokmanager-disable-gfx-console.patch -# PATCH-FIX-UPSTREAM shim-bnc841426-silence-shim-protocols.patch bnc#841426 glin@suse.com -- Silence the shim protocols to avoid system hang -Patch12: shim-bnc841426-silence-shim-protocols.patch +# PATCH-FIX-UPSTREAM shim-fix-verify-mok.patch glin@suse.com -- Fix the error handling in verify_mok() +Patch1: shim-fix-verify-mok.patch +# PATCH-FIX-UPSTREAM shim-improve-error-messages.patch glin@suse.com -- Improve the error messages +Patch2: shim-improve-error-messages.patch +# PATCH-FIX-UPSTREAM shim-correct-user_insecure-usage.patch glin@suse.com -- Correct the usage of the user insecure mode variable +Patch3: shim-correct-user_insecure-usage.patch +# PATCH-FIX-UPSTREAM shim-fix-dhcpv4-path-generation.patch glin@suse.com -- Fix path generation for DHCPv4 bootloader +Patch4: shim-fix-dhcpv4-path-generation.patch +# PATCH-FIX-UPSTREAM shim-mokx-support.patch glin@suse.com -- Support MOK blacklist +Patch5: shim-mokx-support.patch BuildRequires: gnu-efi >= 3.0t BuildRequires: mozilla-nss-tools BuildRequires: openssl >= 0.9.8 @@ -86,26 +70,16 @@ Authors: %prep %setup -q -%patch0 -p1 %patch1 -p1 %patch2 -p1 %patch3 -p1 %patch4 -p1 %patch5 -p1 -%patch6 -p1 -%patch7 -p1 -%patch8 -p1 -%patch9 -p1 -%patch10 -p1 -%patch11 -p1 -%patch12 -p1 %build -chmod +x "make-certs" - # first, build MokManager and fallback as they don't depend on a # specific certificate -make MokManager.efi fallback.efi 2>/dev/null +make EFI_PATH=/usr/lib64 MokManager.efi fallback.efi 2>/dev/null # now build variants of shim that embed different certificates default='' @@ -154,7 +128,7 @@ for suffix in "${suffixes[@]}"; do rm -f shim.cer fi # make sure cast warnings don't trigger post build check - make VENDOR_CERT_FILE=shim-$suffix.der shim.efi 2>/dev/null + make EFI_PATH=/usr/lib64 VENDOR_CERT_FILE=shim-$suffix.der shim.efi 2>/dev/null # make VENDOR_CERT_FILE=cert.der VENDOR_DBX_FILE=dbx chmod 755 %{SOURCE6} %{SOURCE7} %{SOURCE10} # alternative: verify signature