From 16ab868efcfc0239475e6f39689e6233c781c713576b1e05833c71b57b3c788f Mon Sep 17 00:00:00 2001 From: Gary Ching-Pang Lin Date: Tue, 23 Jul 2013 04:44:22 +0000 Subject: [PATCH] Accepting request 184039 from home:gary_lin:branches:devel:openSUSE:Factory - Update to 0.4 - Rebase patches + shim-suse-build.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 - Add patches + shim-merge-lf-loader-code.patch: merge the Linux Foundation loader UI code + shim-fix-pointer-casting.patch: fix a casting issue and the size of an empty vendor cert + shim-fix-simple-file-selector.patch: fix the buffer allocation in the simple file selector - Remove upstreamed patches + shim-support-mok-delete.patch + shim-reboot-after-changes.patch + shim-clear-queued-key.patch + shim-local-key-sign-mokmanager.patch + shim-get-2nd-stage-loader.patch + shim-fix-loadoptions.patch - Remove unused patch: shim-mokmanager-new-pw-hash.patch and shim-keep-unsigned-mokmanager.patch - Install the vendor certificate to /etc/uefi/certs OBS-URL: https://build.opensuse.org/request/show/184039 OBS-URL: https://build.opensuse.org/package/show/devel:openSUSE:Factory/shim?expand=0&rev=28 --- shim-0.2.tar.bz2 | 3 - shim-0.4.tar.bz2 | 3 + shim-bnc798043-no-doulbe-separators.patch | 12 +- shim-bnc804631-fix-broken-bootpath.patch | 12 +- ...bnc807760-change-pxe-2nd-loader-name.patch | 6 +- shim-bnc808106-correct-certcount.patch | 12 +- shim-clear-queued-key.patch | 30 - shim-fix-loadoptions.patch | 84 - shim-fix-pointer-casting.patch | 61 + shim-fix-simple-file-selector.patch | 149 + shim-get-2nd-stage-loader.patch | 123 - shim-keep-unsigned-mokmanager.patch | 13 - shim-local-key-sign-mokmanager.patch | 722 - shim-merge-lf-loader-code.patch | 5260 +++++++ shim-mokmanager-new-pw-hash.patch | 587 - ...mokmanager-support-crypt-hash-method.patch | 472 +- shim-mokmanager-ui-revamp.patch | 11931 ++-------------- shim-reboot-after-changes.patch | 94 - shim-support-mok-delete.patch | 763 - shim-suse-build.patch | 12 +- shim.changes | 30 + shim.spec | 64 +- 22 files changed, 7305 insertions(+), 13138 deletions(-) delete mode 100644 shim-0.2.tar.bz2 create mode 100644 shim-0.4.tar.bz2 delete mode 100644 shim-clear-queued-key.patch delete mode 100644 shim-fix-loadoptions.patch create mode 100644 shim-fix-pointer-casting.patch create mode 100644 shim-fix-simple-file-selector.patch delete mode 100644 shim-get-2nd-stage-loader.patch delete mode 100644 shim-keep-unsigned-mokmanager.patch delete mode 100644 shim-local-key-sign-mokmanager.patch create mode 100644 shim-merge-lf-loader-code.patch delete mode 100644 shim-mokmanager-new-pw-hash.patch delete mode 100644 shim-reboot-after-changes.patch delete mode 100644 shim-support-mok-delete.patch diff --git a/shim-0.2.tar.bz2 b/shim-0.2.tar.bz2 deleted file mode 100644 index 47d444c..0000000 --- a/shim-0.2.tar.bz2 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:866b1d73d022baa4874dede94bfd2525954b986db9497e6a8f6f2c7e5fea5852 -size 940450 diff --git a/shim-0.4.tar.bz2 b/shim-0.4.tar.bz2 new file mode 100644 index 0000000..d724527 --- /dev/null +++ b/shim-0.4.tar.bz2 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:442c5ea22e50aeea816fc83e4a328e48d9429eefb706fa55de3d7c8b05aea0e7 +size 966676 diff --git a/shim-bnc798043-no-doulbe-separators.patch b/shim-bnc798043-no-doulbe-separators.patch index 27a0140..f9ff606 100644 --- a/shim-bnc798043-no-doulbe-separators.patch +++ b/shim-bnc798043-no-doulbe-separators.patch @@ -1,17 +1,17 @@ -From 5c736550e8f7645f39df6948785ab5cae2201418 Mon Sep 17 00:00:00 2001 +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 ++++++++++++++++++++------- + shim.c | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/shim.c b/shim.c -index 690d064..c36b641 100644 +index 0622c72..806f065 100644 --- a/shim.c +++ b/shim.c -@@ -907,7 +907,7 @@ static EFI_STATUS generate_path(EFI_LOADED_IMAGE *li, CHAR16 *ImagePath, +@@ -969,7 +969,7 @@ static EFI_STATUS generate_path(EFI_LOADED_IMAGE *li, CHAR16 *ImagePath, { EFI_DEVICE_PATH *devpath; EFI_HANDLE device; @@ -20,7 +20,7 @@ index 690d064..c36b641 100644 unsigned int pathlen = 0; EFI_STATUS efi_status = EFI_SUCCESS; CHAR16 *bootpath; -@@ -927,14 +927,27 @@ static EFI_STATUS generate_path(EFI_LOADED_IMAGE *li, CHAR16 *ImagePath, +@@ -989,14 +989,27 @@ static EFI_STATUS generate_path(EFI_LOADED_IMAGE *li, CHAR16 *ImagePath, if (bootpath[i] == '/') bootpath[i] = '\\'; } @@ -55,5 +55,5 @@ index 690d064..c36b641 100644 while (*ImagePath == '\\') ImagePath++; -- -1.7.10.4 +1.8.1.4 diff --git a/shim-bnc804631-fix-broken-bootpath.patch b/shim-bnc804631-fix-broken-bootpath.patch index 32d63c9..a4700c8 100644 --- a/shim-bnc804631-fix-broken-bootpath.patch +++ b/shim-bnc804631-fix-broken-bootpath.patch @@ -1,4 +1,4 @@ -From 6b70850baa958b196ec332cf0224ffa9d5a81f5f Mon Sep 17 00:00:00 2001 +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 @@ -12,14 +12,14 @@ Subject: [PATCH] Fix the broken bootpath Based on the patch from Michal Marek --- - shim.c | 22 +++++++++++++++++----- + shim.c | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/shim.c b/shim.c -index 37a5898..690d064 100644 +index 94b9710..0622c72 100644 --- a/shim.c +++ b/shim.c -@@ -919,15 +919,25 @@ static EFI_STATUS generate_path(EFI_LOADED_IMAGE *li, CHAR16 *ImagePath, +@@ -981,15 +981,25 @@ static EFI_STATUS generate_path(EFI_LOADED_IMAGE *li, CHAR16 *ImagePath, pathlen = StrLen(bootpath); @@ -50,7 +50,7 @@ index 37a5898..690d064 100644 *PathName = AllocatePool(StrSize(bootpath) + StrSize(ImagePath)); -@@ -944,6 +954,8 @@ static EFI_STATUS generate_path(EFI_LOADED_IMAGE *li, CHAR16 *ImagePath, +@@ -1007,6 +1017,8 @@ static EFI_STATUS generate_path(EFI_LOADED_IMAGE *li, CHAR16 *ImagePath, *grubpath = FileDevicePath(device, *PathName); error: @@ -60,5 +60,5 @@ index 37a5898..690d064 100644 } -- -1.7.10.4 +1.8.1.4 diff --git a/shim-bnc807760-change-pxe-2nd-loader-name.patch b/shim-bnc807760-change-pxe-2nd-loader-name.patch index b5ca9fb..1b015a3 100644 --- a/shim-bnc807760-change-pxe-2nd-loader-name.patch +++ b/shim-bnc807760-change-pxe-2nd-loader-name.patch @@ -1,11 +1,11 @@ -From 8222b5f6dd8ff34368173b86ae6108cb792802a7 Mon Sep 17 00:00:00 2001 +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 +++++++----- + netboot.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/netboot.c b/netboot.c @@ -54,5 +54,5 @@ index 90fb9cb..ae723c7 100644 /* Note we don't capture the filename option here because we know its shim.efi -- -1.7.10.4 +1.8.1.4 diff --git a/shim-bnc808106-correct-certcount.patch b/shim-bnc808106-correct-certcount.patch index c8d5d47..c6ba95f 100644 --- a/shim-bnc808106-correct-certcount.patch +++ b/shim-bnc808106-correct-certcount.patch @@ -1,17 +1,17 @@ -From 822b44b8d978449a43fb2cd7bcd1381d961d0b25 Mon Sep 17 00:00:00 2001 +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 ++-- + shim.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/shim.c b/shim.c -index c36b641..1daa84b 100644 +index 806f065..7219d53 100644 --- a/shim.c +++ b/shim.c -@@ -228,7 +228,7 @@ static CHECK_STATUS check_db_cert_in_ram(EFI_SIGNATURE_LIST *CertList, +@@ -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) { @@ -20,7 +20,7 @@ index c36b641..1daa84b 100644 Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize); for (Index = 0; Index < CertCount; Index++) { IsFound = AuthenticodeVerify (data->CertData, -@@ -293,7 +293,7 @@ static CHECK_STATUS check_db_hash_in_ram(EFI_SIGNATURE_LIST *CertList, +@@ -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)) { @@ -30,5 +30,5 @@ index c36b641..1daa84b 100644 if (CompareGuid(&CertList->SignatureType, &CertType) == 0) { for (Index = 0; Index < CertCount; Index++) { -- -1.7.10.4 +1.8.1.4 diff --git a/shim-clear-queued-key.patch b/shim-clear-queued-key.patch deleted file mode 100644 index 544b3f6..0000000 --- a/shim-clear-queued-key.patch +++ /dev/null @@ -1,30 +0,0 @@ -From daa6a7519caa23ef69b9a879bc70789a0669b3e3 Mon Sep 17 00:00:00 2001 -From: Gary Ching-Pang Lin -Date: Wed, 26 Dec 2012 11:44:46 +0800 -Subject: [PATCH] Make sure the menu shows when the callback fails - -Since Pause() doesn't clear the key from the input queue, the next -ReadKeyStroke reads the queued key instead of the new one. If the -user presses "Enter", MokManager exits directly without showing -the menu again. ---- - MokManager.c | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/MokManager.c b/MokManager.c -index bfcbfd6..97588cb 100644 ---- a/MokManager.c -+++ b/MokManager.c -@@ -1241,6 +1241,9 @@ static void run_menu (CHAR16 *header, UINTN lines, struct menu_item *items, - 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; --- -1.7.10.4 - diff --git a/shim-fix-loadoptions.patch b/shim-fix-loadoptions.patch deleted file mode 100644 index 74923e4..0000000 --- a/shim-fix-loadoptions.patch +++ /dev/null @@ -1,84 +0,0 @@ -commit f23f6b726bd12b28befd5a064c47a8a249d80a59 -Author: Gary Ching-Pang Lin -Date: Mon Jan 14 16:53:19 2013 +0800 - - Adopt the UEFI shell style LoadOptions - - The previous commit, 14d4b8e, caused shim failed to parse the name - of the 2nd stage loader in UEFI shell. Amend parsing of the name the - 2nd stage loader to be compatible with UEFI shell. - - To create an boot entry for elilo.efi: - - # efibootmgr -c -L "shim elilo" -l "efi\\shim.efi" -u "shim.efi elilo.efi" - -diff --git a/shim.c b/shim.c -index dcf1c51..37a5898 100644 ---- a/shim.c -+++ b/shim.c -@@ -1330,6 +1330,8 @@ EFI_STATUS set_second_stage (EFI_HANDLE image_handle) - EFI_LOADED_IMAGE *li; - CHAR16 *start = NULL, *c; - int i, remaining_size = 0; -+ CHAR16 *loader_str = NULL; -+ int loader_len = 0; - - second_stage = DEFAULT_LOADER; - load_options = NULL; -@@ -1351,6 +1353,11 @@ EFI_STATUS set_second_stage (EFI_HANDLE image_handle) - return EFI_BAD_BUFFER_SIZE; - } - -+ /* -+ * UEFI shell copies the whole line of the command into LoadOptions. -+ * We ignore the string before the first L' ', i.e. the name of this -+ * program. -+ */ - for (i = 0; i < li->LoadOptionsSize; i += 2) { - c = (CHAR16 *)(li->LoadOptions + i); - if (*c == L' ') { -@@ -1360,9 +1367,30 @@ EFI_STATUS set_second_stage (EFI_HANDLE image_handle) - break; - } - } -+ if (!start || remaining_size <= 0) -+ return EFI_SUCCESS; - -- second_stage = (CHAR16 *)li->LoadOptions; -- if (start && remaining_size > 0) { -+ for (i = 0; start[i] != '\0'; i++) { -+ if (start[i] == L' ' || start[i] == L'\0') -+ break; -+ loader_len++; -+ } -+ -+ /* -+ * Setup the name of the alternative loader and the LoadOptions for -+ * the loader -+ */ -+ if (loader_len > 0) { -+ loader_str = AllocatePool((loader_len + 1) * sizeof(CHAR16)); -+ if (!loader_str) { -+ Print(L"Failed to allocate loader string\n"); -+ return EFI_OUT_OF_RESOURCES; -+ } -+ for (i = 0; i < loader_len; i++) -+ loader_str[i] = start[i]; -+ loader_str[loader_len] = L'\0'; -+ -+ second_stage = loader_str; - load_options = start; - load_options_size = remaining_size; - } -@@ -1439,5 +1467,11 @@ EFI_STATUS efi_main (EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *passed_systab) - uefi_call_wrapper(BS->UninstallProtocolInterface, 3, handle, - &shim_lock_guid, &shim_lock_interface); - -+ /* -+ * Free the space allocated for the alternative 2nd stage loader -+ */ -+ if (load_options_size > 0) -+ FreePool(second_stage); -+ - return efi_status; - } diff --git a/shim-fix-pointer-casting.patch b/shim-fix-pointer-casting.patch new file mode 100644 index 0000000..af3edd9 --- /dev/null +++ b/shim-fix-pointer-casting.patch @@ -0,0 +1,61 @@ +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 new file mode 100644 index 0000000..8e7c9c0 --- /dev/null +++ b/shim-fix-simple-file-selector.patch @@ -0,0 +1,149 @@ +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-get-2nd-stage-loader.patch b/shim-get-2nd-stage-loader.patch deleted file mode 100644 index 42e225b..0000000 --- a/shim-get-2nd-stage-loader.patch +++ /dev/null @@ -1,123 +0,0 @@ -commit 940425a8bce6bf1b556dc48189884b4a82d8d420 -Author: Gary Ching-Pang Lin -Date: Thu Dec 6 17:47:26 2012 +0800 - - Get the second stage loader from the Load Options - - This commit replaces the 2nd stage loader path with the first - argument in the Load Options and moves the rest arguments (if any) - to the Load Options for the 2nd stage loader. - - For example, to make shim to load elilo.efi, just create a new - boot entry with efibootmgr: - - # efibootmgr -c -L "shim elilo" -l "efi\\shim.efi" -u "elilo.efi" - -diff --git a/shim.c b/shim.c -index c3aae9e..44301dd 100644 ---- a/shim.c -+++ b/shim.c -@@ -42,12 +42,16 @@ - #include "netboot.h" - #include "shim_cert.h" - --#define SECOND_STAGE L"\\grub.efi" -+#define DEFAULT_LOADER L"\\grub.efi" - #define MOK_MANAGER L"\\MokManager.efi" - - static EFI_SYSTEM_TABLE *systab; - static EFI_STATUS (EFIAPI *entry_point) (EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *system_table); - -+static CHAR16 *second_stage; -+static void *load_options; -+static UINT32 load_options_size; -+ - /* - * The vendor certificate used for validating the second stage loader - */ -@@ -881,6 +885,10 @@ static EFI_STATUS handle_image (void *data, unsigned int datasize, - li->ImageBase = buffer; - li->ImageSize = context.ImageSize; - -+ /* Pass the load options to the second stage loader */ -+ li->LoadOptions = load_options; -+ li->LoadOptionsSize = load_options_size; -+ - if (!entry_point) { - Print(L"Invalid entry point\n"); - FreePool(buffer); -@@ -1192,7 +1200,7 @@ EFI_STATUS init_grub(EFI_HANDLE image_handle) - { - EFI_STATUS efi_status; - -- efi_status = start_image(image_handle, SECOND_STAGE); -+ efi_status = start_image(image_handle, second_stage); - - if (efi_status != EFI_SUCCESS) - efi_status = start_image(image_handle, MOK_MANAGER); -@@ -1312,6 +1320,55 @@ static EFI_STATUS check_mok_sb (void) - return status; - } - -+/* -+ * Check the load options to specify the second stage loader -+ */ -+EFI_STATUS set_second_stage (EFI_HANDLE image_handle) -+{ -+ EFI_STATUS status; -+ EFI_LOADED_IMAGE *li; -+ CHAR16 *start = NULL, *c; -+ int i, remaining_size = 0; -+ -+ second_stage = DEFAULT_LOADER; -+ load_options = NULL; -+ load_options_size = 0; -+ -+ status = uefi_call_wrapper(BS->HandleProtocol, 3, image_handle, -+ &LoadedImageProtocol, (void **) &li); -+ if (status != EFI_SUCCESS) { -+ Print (L"Failed to get load options\n"); -+ return status; -+ } -+ -+ /* Expect a CHAR16 string with at least one CHAR16 */ -+ if (li->LoadOptionsSize < 4 || li->LoadOptionsSize % 2 != 0) { -+ return EFI_BAD_BUFFER_SIZE; -+ } -+ c = (CHAR16 *)(li->LoadOptions + (li->LoadOptionsSize - 2)); -+ if (*c != L'\0') { -+ return EFI_BAD_BUFFER_SIZE; -+ } -+ -+ for (i = 0; i < li->LoadOptionsSize; i += 2) { -+ c = (CHAR16 *)(li->LoadOptions + i); -+ if (*c == L' ') { -+ *c = L'\0'; -+ start = c + 1; -+ remaining_size = li->LoadOptionsSize - i - 2; -+ break; -+ } -+ } -+ -+ second_stage = (CHAR16 *)li->LoadOptions; -+ if (start && remaining_size > 0) { -+ load_options = start; -+ load_options_size = remaining_size; -+ } -+ -+ return EFI_SUCCESS; -+} -+ - EFI_STATUS efi_main (EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *passed_systab) - { - EFI_GUID shim_lock_guid = SHIM_LOCK_GUID; -@@ -1334,6 +1391,9 @@ EFI_STATUS efi_main (EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *passed_systab) - */ - InitializeLib(image_handle, systab); - -+ /* Set the second stage loader */ -+ set_second_stage (image_handle); -+ - /* - * Check whether the user has configured the system to run in - * insecure mode diff --git a/shim-keep-unsigned-mokmanager.patch b/shim-keep-unsigned-mokmanager.patch deleted file mode 100644 index d30091b..0000000 --- a/shim-keep-unsigned-mokmanager.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/Makefile b/Makefile -index 9217ba1..cd1c688 100644 ---- a/Makefile -+++ b/Makefile -@@ -28,7 +28,7 @@ LDFLAGS = -nostdlib -znocombreloc -T $(EFI_LDS) -shared -Bsymbolic -L$(EFI_PATH - - VERSION = 0.2 - --TARGET = shim.efi MokManager.efi.signed -+TARGET = shim.efi MokManager.efi.signed MokManager.efi - 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 diff --git a/shim-local-key-sign-mokmanager.patch b/shim-local-key-sign-mokmanager.patch deleted file mode 100644 index feea2c8..0000000 --- a/shim-local-key-sign-mokmanager.patch +++ /dev/null @@ -1,722 +0,0 @@ -From 6d50f87a06ff70d2075863f4c145235c081263d6 Mon Sep 17 00:00:00 2001 -From: Matthew Garrett -Date: Sat, 24 Nov 2012 00:07:11 -0500 -Subject: [PATCH 1/2] Sign MokManager with a locally-generated key - -shim needs to verify that MokManager hasn't been modified, but we want to -be able to support configurations where shim is shipped without a vendor -certificate. This patch adds support for generating a certificate at build -time, incorporating the public half into shim and signing MokManager with -the private half. It uses pesign and nss, but still requires openssl for -key generation. Anyone using sbsign will need to figure this out for -themselves. ---- - Makefile | 28 ++- - make-certs | 554 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - shim.c | 24 ++- - 3 files changed, 597 insertions(+), 9 deletions(-) - create mode 100755 make-certs - -diff --git a/Makefile b/Makefile -index b266018..412eba5 100644 ---- a/Makefile -+++ b/Makefile -@@ -28,15 +28,33 @@ LDFLAGS = -nostdlib -znocombreloc -T $(EFI_LDS) -shared -Bsymbolic -L$(EFI_PATH - - VERSION = 0.2 - --TARGET = shim.efi MokManager.efi -+TARGET = shim.efi MokManager.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 - - all: $(TARGET) - --shim.o: $(SOURCES) -+shim.crt: -+ ./make-certs shim shim@xn--u4h.net all codesign 1.3.6.1.4.1.311.10.3.1 $@ -+ hexdump -v -e '1/1 "0x%02x, "' $< >> $@ -+ echo "};" >> $@ -+ -+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 -+ -+shim.o: $(SOURCES) shim_cert.h - - cert.o : cert.S - $(CC) $(CFLAGS) -c -o $@ $< -@@ -70,10 +88,14 @@ Cryptlib/OpenSSL/libopenssl.a: - -j .debug_line -j .debug_str -j .debug_ranges \ - --target=efi-app-$(ARCH) $^ $@.debug - -+%.efi.signed: %.efi certdb/secmod.db -+ pesign -n certdb -i $< -c "shim" -s -o $@ -f -+ - clean: - $(MAKE) -C Cryptlib clean - $(MAKE) -C Cryptlib/OpenSSL clean -- rm -f $(TARGET) $(OBJS) -+ rm -rf $(TARGET) $(OBJS) $(MOK_OBJS) $(KEYS) certdb -+ rm -f *.debug *.so - - GITTAG = $(VERSION) - -diff --git a/make-certs b/make-certs -new file mode 100755 -index 0000000..3e9293b ---- /dev/null -+++ b/make-certs -@@ -0,0 +1,554 @@ -+#!/bin/bash -e -+# -+# Generate a root CA cert for signing, and then a subject cert. -+# Usage: make-certs.sh hostname [user[@domain]] [more ...] -+# For testing only, probably still has some bugs in it. -+# -+ -+DOMAIN=xn--u4h.net -+DAYS=365 -+KEYTYPE=RSA -+KEYSIZE=2048 -+DIGEST=SHA256 -+CRLHOURS=24 -+CRLDAYS= -+ -+# Cleanup temporary files at exit. -+touch openssl.cnf -+newcertdir=`mktemp -d` -+cleanup() { -+ test -f openssl.cnf && rm -f openssl.cnf -+ test -f ca.txt && rm -f ca.txt -+ test -f ocsp.txt && rm -f ocsp.txt -+ test -n "$newcertdir" && rm -fr "$newcertdir" -+} -+trap cleanup EXIT -+ -+# The first argument is either a common name value or a flag indicating that -+# we're doing something other than issuing a cert. -+commonname="$1" -+refresh_crl=false -+revoke_cert=false -+ocsp_serve=false -+if test "x$commonname" = "x-refresh-crl" ; then -+ refresh_crl=true -+ commonname="$1" -+fi -+if test "x$commonname" = "x-refresh_crl" ; then -+ refresh_crl=true -+ commonname="$1" -+fi -+if test "x$commonname" = "x-revoke" ; then -+ revoke_cert=true -+ shift -+ commonname="$1" -+fi -+if test "x$commonname" = "x-ocsp" ; then -+ ocsp_serve=true -+ commonname="$1" -+fi -+if test "x$commonname" = x ; then -+ echo Usage: `basename $0` 'commonname' user'[@domain]' '[more [...]]' -+ echo Usage: `basename $0` -revoke 'commonname' -+ echo Usage: `basename $0` -ocsp -+ echo Usage: `basename $0` -refresh-crl -+ echo More: -+ echo -e \\tKey usage: "[sign|signing|encrypt|encryption|all]" -+ echo -e \\tAuthority Access Info OCSP responder: "ocsp:URI" -+ echo -e \\tCRL distribution point: "crl:URI" -+ echo -e \\tSubject Alternative Name: -+ echo -e \\t\\tHostname: "*" -+ echo -e \\t\\tIP address: w.x.y.z -+ echo -e \\t\\tEmail address: "*@*.com/edu/net/org/local" -+ echo -e \\t\\tKerberos principal name: "*@*.COM/EDU/NET/ORG/LOCAL" -+ echo -e \\tExtended key usage: -+ echo -e \\t\\t1.... -+ echo -e \\t\\t2.... -+ echo -e \\t\\tid-kp-server-auth \| tls-server -+ echo -e \\t\\tid-kp-client-auth \| tls-client -+ echo -e \\t\\tid-kp-email-protection \| email -+ echo -e \\t\\tid-ms-kp-sc-logon \| id-ms-sc-logon -+ echo -e \\t\\tid-pkinit-kp-client-auth \| id-pkinit-client -+ echo -e \\t\\tid-pkinit-kp-kdc \| id-pkinit-kdc -+ echo -e \\t\\tca \| CA -+ exit 1 -+fi -+ -+# Choose a user name part for email attributes. -+GIVENUSER=$2 -+test x"$GIVENUSER" = x && GIVENUSER=$USER -+echo "$GIVENUSER" | grep -q @ || GIVENUSER="$GIVENUSER"@$DOMAIN -+DOMAIN=`echo "$GIVENUSER" | cut -f2- -d@` -+ -+shift || true -+shift || true -+ -+# Done already? -+done=: -+ -+keygen() { -+ case "$KEYTYPE" in -+ DSA) -+ openssl dsaparam -out "$1".param $KEYSIZE -+ openssl gendsa "$1".param -+ ;; -+ RSA|*) -+ #openssl genrsa $KEYSIZE -passout pass:qweqwe -+ openssl genrsa $KEYSIZE -+ #openssl genrsa $KEYSIZE -nodes -+ ;; -+ esac -+} -+ -+# Set some defaults. -+CA=FALSE -+if test -s ca.crldp.uri.txt ; then -+ crlval="`cat ca.crldp.uri.txt`" -+ crl="URI:$crlval" -+fi -+if test -s ca.ocsp.uri.txt ; then -+ aiaval="`cat ca.ocsp.uri.txt`" -+ aia="OCSP;URI:$aiaval" -+fi -+if test -s ca.domain.txt ; then -+ domval="`cat ca.domain.txt`" -+ if test -n "$domval" ; then -+ DOMAIN="$domval" -+ fi -+fi -+ -+# Parse the arguments which indicate what sort of information we want. -+while test $# -gt 0 ; do -+ type= -+ value="$1" -+ case "$value" in -+ RSA|rsa) -+ KEYTYPE=RSA -+ ;; -+ DSA|dsa) -+ KEYTYPE=DSA -+ ;; -+ OCSP:*|ocsp:*) -+ aiaval=`echo "$value" | cut -f2- -d:` -+ aia="OCSP;URI:$aiaval" -+ ;; -+ CRL:*|crl:*) -+ crlval=`echo "$value" | cut -f2- -d:` -+ crl="URI:$crlval" -+ ;; -+ signing|sign) -+ keyusage="${keyusage:+${keyusage},}nonRepudiation,digitalSignature" -+ ;; -+ encryption|encrypt) -+ keyusage="${keyusage:+${keyusage},}keyEncipherment,dataEncipherment" -+ ;; -+ all) -+ keyusage="digitalSignature,nonRepudiation,keyEncipherment,dataEncipherment,keyAgreement,keyCertSign,cRLSign,encipherOnly,decipherOnly" -+ ;; -+ ca|CA) -+ CA=TRUE -+ keyusage="${keyusage:+${keyusage},}nonRepudiation,digitalSignature,keyEncipherment,dataEncipherment,keyAgreement,keyCertSign,cRLSign" -+ ;; -+ 1.*|2.*|id-*|tls-*|email|mail|codesign) -+ ekuval=`echo "$value" | tr '[A-Z]' '[a-z]' | sed 's,\-,,g'` -+ case "$ekuval" in -+ idkpserverauth|tlsserver) ekuval=1.3.6.1.5.5.7.3.1;; -+ idkpclientauth|tlsclient) ekuval=1.3.6.1.5.5.7.3.2;; -+ idkpemailprotection|email|mail) ekuval=1.3.6.1.5.5.7.3.4;; -+ idkpcodesign|codesign) ekuval=1.3.6.1.5.5.7.3.3;; -+ idmskpsclogon|idmssclogon) ekuval=1.3.6.1.4.1.311.20.2.2;; -+ idpkinitkpclientauth|idpkinitclient) ekuval=1.3.6.1.5.2.3.4;; -+ idpkinitkpkdc|idpkinitkdc) ekuval=1.3.6.1.5.2.3.5;; -+ esac -+ if test -z "$eku" ; then -+ eku="$ekuval" -+ else -+ eku="$eku,$ekuval" -+ fi -+ ;; -+ *@*.COM|*@*.EDU|*@*.NET|*@*.ORG|*@*.LOCAL) -+ luser=`echo "$value" | tr '[A-Z]' '[a-z]'` -+ if test "$luser" = "$value" ; then -+ luser= -+ fi -+ type="otherName:1.3.6.1.5.2.2;SEQUENCE:$value,${luser:+otherName:1.3.6.1.4.1.311.20.2.3;UTF8:${luser},}otherName:1.3.6.1.4.1.311.20.2.3;UTF8" -+ unset luser -+ principals="$principals $value" -+ ;; -+ *@*.com|*@*.edu|*@*.net|*@*.org|*@*.local) type=email;; -+ [0-9]*.[0-9]*.[0-9]*.[0-9]*) type=IP;; -+ *) type=DNS;; -+ esac -+ if test -n "$type" ; then -+ newvalue="${type}:$value" -+ if test -z "$altnames" ; then -+ altnames="${newvalue}" -+ else -+ altnames="${altnames},${newvalue}" -+ fi -+ fi -+ shift -+done -+ -+# Build the configuration file, including bits on how to construct the CA -+# certificate, an OCSP responder certificate, and the issued certificate. -+cat > openssl.cnf <<- EOF -+[ca] -+default_ca = issuer -+ -+[issuer] -+private_key = `pwd`/ca.key -+certificate = `pwd`/ca.crt -+database = `pwd`/ca.db -+serial = `pwd`/ca.srl -+default_md = $DIGEST -+new_certs_dir = $newcertdir -+policy = no_policy -+ -+[no_policy] -+ -+[req_oids] -+domainComponent = 0.9.2342.19200300.100.1.25 -+ -+[req_ca] -+prompt = no -+oid_section = req_oids -+distinguished_name = req_ca_name -+default_md = $DIGEST -+subjectKeyIdentifier=hash -+ -+[req_ca_name] -+C=US -+#stateOrProvinceName=SomeState -+localityName=SomeCity -+O=SomeOrg -+EOF -+#echo $DOMAIN | awk 'BEGIN {FS="."}{for(i=NF;i>0;i--){print NF-i ".domainComponent="$i;}}' >> openssl.cnf -+cat >> openssl.cnf <<- EOF -+#commonName = Test Certifying CA -+ -+[v3_ca] -+subjectKeyIdentifier=hash -+authorityKeyIdentifier=keyid:always -+#authorityKeyIdentifier=keyid:always,issuer:always -+keyUsage=nonRepudiation,digitalSignature,keyEncipherment,dataEncipherment,keyAgreement,keyCertSign,cRLSign -+basicConstraints=critical,CA:TRUE -+nsComment="Testing CA Certificate" -+EOF -+if test -n "$aia" ; then -+ echo "authorityInfoAccess = ${aia}" >> openssl.cnf -+ echo -n "$aiaval" > ca.ocsp.uri.txt -+fi -+if test -n "$crl" ; then -+ echo "crlDistributionPoints = ${crl}" >> openssl.cnf -+ echo -n "$crlval" > ca.crldp.uri.txt -+fi -+echo "$DOMAIN" > ca.domain.txt -+cat >> openssl.cnf <<- EOF -+ -+[req_ocsp] -+prompt = no -+oid_section = req_oids -+distinguished_name = req_ocsp_name -+default_md = $DIGEST -+ -+[req_ocsp_name] -+C=US -+#stateOrProvinceName=SomeState -+localityName=SomeOrg -+O=SomeOrg -+EOF -+#echo $DOMAIN | awk 'BEGIN {FS="."}{for(i=NF;i>0;i--){print NF-i ".domainComponent="$i;}}' >> openssl.cnf -+cat >> openssl.cnf <<- EOF -+#commonName = OCSP Signer for Test Certifying CA -+ -+[v3_ocsp] -+subjectKeyIdentifier=hash -+#authorityKeyIdentifier=keyid:always,issuer:always -+authorityKeyIdentifier=keyid:always -+keyUsage=digitalSignature,nonRepudiation,keyEncipherment,dataEncipherment,keyAgreement,keyCertSign,cRLSign -+extendedKeyUsage=1.3.6.1.5.5.7.3.9 -+#basicConstraints=CA:FALSE -+basicConstraints=CA:TRUE -+nsComment="Testing OCSP Certificate" -+1.3.6.1.5.5.7.48.1.5=ASN1:NULL -+EOF -+if test -n "$aia" ; then -+ echo "authorityInfoAccess = ${aia}" >> openssl.cnf -+fi -+if test -n "$crl" ; then -+ echo "crlDistributionPoints = ${crl}" >> openssl.cnf -+fi -+cat >> openssl.cnf <<- EOF -+ -+[req_issued] -+prompt = no -+oid_section = req_oids -+distinguished_name = req_issued_name -+default_md = $DIGEST -+ -+[req_issued_name] -+C=US -+#stateOrProvinceName=SomeState -+localityName=SomeCity -+O=SomeOrg -+EOF -+#echo $DOMAIN | awk 'BEGIN {FS="."}{for(i=NF;i>0;i--){print NF-i ".domainComponent="$i;}}' >> openssl.cnf -+#mail = $GIVENUSER -+cat >> openssl.cnf <<- EOF -+commonName = $commonname -+ -+[v3_issued] -+#certificatePolicies=2.5.29.32.0${eku:+,${eku}} -+subjectKeyIdentifier=hash -+authorityKeyIdentifier=keyid:always -+#authorityKeyIdentifier=keyid:always,issuer:always -+EOF -+if test -n "$aia" ; then -+ echo "authorityInfoAccess = ${aia}" >> openssl.cnf -+fi -+if test -n "$crl" ; then -+ echo "crlDistributionPoints = ${crl}" >> openssl.cnf -+fi -+if test -n "$keyusage" ; then -+ echo "keyUsage = critical,${keyusage}" >> openssl.cnf -+fi -+if test -n "$altnames" ; then -+ echo "subjectAltName = ${altnames}" >> openssl.cnf -+fi -+if test -n "$eku" ; then -+ echo "extendedKeyUsage = ${eku}" >> openssl.cnf -+ : -+fi -+if test "x$CA" = xTRUE ; then -+ echo "basicConstraints=critical,CA:TRUE" >> openssl.cnf -+ echo 'nsComment="Testing CA Certificate for '"$commonname"'"' >> openssl.cnf -+else -+ echo "basicConstraints=CA:FALSE" >> openssl.cnf -+ echo 'nsComment="Testing Certificate for '"$commonname"'"' >> openssl.cnf -+fi -+for value in $principals; do -+ user=`echo "$value" | cut -f1 -d@` -+ realm=`echo "$value" | cut -f2- -d@` -+ echo "" >> openssl.cnf -+ echo "[$value]" >> openssl.cnf -+ echo "realm=EXPLICIT:0,GeneralString:$realm" >> openssl.cnf -+ echo "kerberosname=EXPLICIT:1,SEQUENCE:krb5$user" >> openssl.cnf -+ -+ echo "" >> openssl.cnf -+ echo "[krb5$user]" >> openssl.cnf -+ echo "nametype=EXPLICIT:0,INTEGER:1" >> openssl.cnf -+ echo "namelist=EXPLICIT:1,SEQUENCE:krb5basic$user" >> openssl.cnf -+ -+ echo "[krb5basic$user]" >> openssl.cnf -+ count=0 -+ for part in `echo "$user" | sed 's,/, ,g'` ; do -+ echo "$count.part=GeneralString:$part" >> openssl.cnf -+ count=`expr "$count" + 1` -+ done -+done -+ -+# Create the data files for a new CA. -+if ! test -s ca.srl ; then -+ (dd if=/dev/urandom bs=8 count=1 2> /dev/null) | od -t x1c | head -n 1 | awk '{$1="00";OFS="";print}' > ca.srl -+else -+ echo "You already have a ca.srl file; not replacing." -+fi -+if ! test -s ca.db ; then -+ touch ca.db -+else -+ echo "You already have a ca.db file; not replacing." -+fi -+if ! test -s ca.db.attr ; then -+ touch ca.db.attr -+else -+ echo "You already have a ca.db.attr file; not replacing." -+fi -+ -+# If we need a CA key, generate one. -+if ! test -s ca.key ; then -+ umask=`umask -p` -+ umask 077 -+ keygen ca > ca.key 2> /dev/null -+ $umask -+else -+ echo "You already have a ca.key file; not replacing." -+ done=echo -+fi -+ -+# If we need a CA certificate, generate one. -+if ! test -s ca.crt ; then -+ sed -i -e 's,^\[req_ca\]$,\[req\],g' `pwd`/openssl.cnf -+ openssl req -config `pwd`/openssl.cnf -new -key ca.key > ca.csr 2> /dev/null -passin pass:shim -+ sed -i -e 's,^\[req\]$,\[req_ca\],g' `pwd`/openssl.cnf -+ openssl x509 -extfile `pwd`/openssl.cnf -CAserial ca.srl -signkey ca.key -extensions v3_ca -req -in ca.csr -days $DAYS -out ca.crt ; : 2> /dev/null -+ openssl x509 -noout -text -in ca.crt > ca.txt -+ cat ca.crt >> ca.txt -+ cat ca.txt > ca.crt -+ rm ca.txt -+ cat ca.crt > ca.chain.crt -+else -+ echo "You already have a ca.crt file; not replacing." -+ done=echo -+fi -+ -+# If we need an OCSP key, generate one. -+if ! test -s ocsp.key ; then -+ umask=`umask -p` -+ umask 077 -+ keygen ocsp > ocsp.key 2> /dev/null -+ $umask -+else -+ echo "You already have an ocsp.key file; not replacing." -+ done=echo -+fi -+ -+# Generate the OCSP signing cert. Set the X.509v3 basic constraints and EKU. -+if ! test -s ocsp.crt ; then -+ sed -i -e 's,^\[req_ocsp\]$,\[req\],g' `pwd`/openssl.cnf -+ openssl req -config `pwd`/openssl.cnf -new -key ocsp.key > ocsp.csr 2> /dev/null -+ sed -i -e 's,^\[req\]$,\[req_ocsp\],g' `pwd`/openssl.cnf -+ openssl ca -batch -config `pwd`/openssl.cnf -extensions v3_ocsp -preserveDN -in ocsp.csr -days $DAYS -out ocsp.crt 2> /dev/null -+ openssl x509 -noout -text -in ocsp.crt > ocsp.txt -+ cat ocsp.crt >> ocsp.txt -+ cat ocsp.txt > ocsp.crt -+ rm ocsp.txt -+else -+ echo "You already have an ocsp.crt file; not replacing." -+ done=echo -+fi -+ -+# If we were told to revoke the certificate with the specified common name, -+# do so. -+if $revoke_cert ; then -+ openssl ca -config `pwd`/openssl.cnf -revoke "$commonname".crt -+fi -+ -+# Always refresh the CRL. -+openssl ca -config `pwd`/openssl.cnf -gencrl ${CRLHOURS:+-crlhours ${CRLHOURS}} ${CRLDAYS:+-crldays ${CRLDAYS}} -out ca.crl.pem -+openssl crl -in ca.crl.pem -outform der -out ca.crl -+openssl crl -in ca.crl -inform der -noout -text > ca.crl.pem -+openssl crl -in ca.crl -inform der >> ca.crl.pem -+ -+# If we were told to start up the mini OCSP server, do so. -+if $ocsp_serve ; then -+ openssl ocsp -text -index `pwd`/ca.db -CA `pwd`/ca.crt -rsigner `pwd`/ocsp.crt -rkey `pwd`/ocsp.key -rother `pwd`/ocsp.crt -port "`cut -f3 -d/ ca.ocsp.uri.txt | sed -r 's,(^[^:]*),0.0.0.0,g'`" -+ exit 0 -+fi -+ -+# If we're just here to do a revocation or refresh the CRL, we're done. -+if $revoke_cert || $refresh_crl ; then -+ exit 0 -+fi -+ -+# Create a new serial number and whatnot if this is a new sub-CA. -+if test "x$CA" = xTRUE ; then -+ if ! test -d "$commonname" ; then -+ mkdir "$commonname" -+ fi -+ if ! test -s "$commonname/ca.srl" ; then -+ (dd if=/dev/urandom bs=8 count=1 2> /dev/null) | od -t x1c | head -n 1 | awk '{$1="00";OFS="";print}' > "$commonname/ca.srl" -+ else -+ echo "You already have a $commonname/ca.srl file; not replacing." -+ fi -+ if test -n "$aia" ; then -+ echo -n "$aiaval" > "$commonname/ca.ocsp.uri.txt" -+ fi -+ if test -n "$crl" ; then -+ echo -n "$crlval" > "$commonname/ca.crldp.uri.txt" -+ fi -+ echo "$DOMAIN" > "$commonname/ca.domain.txt" -+ touch "$commonname/ca.db" "$commonname/ca.db.attr" -+ cert="$commonname/ca.crt" -+ csr="$commonname/ca.csr" -+ key="$commonname/ca.key" -+ pem="$commonname/ca.pem" -+ pfx="$commonname/ca.p12" -+ ln -s ../`basename $0` "$commonname"/ -+else -+ cert="$commonname.crt" -+ csr="$commonname.csr" -+ key="$commonname.key" -+ pem="$commonname.pem" -+ pfx="$commonname.p12" -+fi -+ -+# Generate the subject's certificate. Set the X.509v3 basic constraints. -+if ! test -s "$cert" ; then -+ # Generate another key, unless we have a key or CSR. -+ if ! test -s "$key" && ! test -s "$csr" ; then -+ umask=`umask -p` -+ umask 077 -+ keygen "$commonname" > "$key" 2> /dev/null -+ $umask -+ else -+ echo "You already have a $key or $csr file; not replacing." -+ done=echo -+ fi -+ -+ if ! test -s "$csr" ; then -+ sed -i -e 's,^\[req_issued\]$,\[req\],g' `pwd`/openssl.cnf -+ openssl req -config `pwd`/openssl.cnf -new -key "$key" > "$csr" 2> /dev/null -+ sed -i -e 's,^\[req\]$,\[req_issued\],g' `pwd`/openssl.cnf -+ fi -+ openssl ca -batch -config `pwd`/openssl.cnf -extensions v3_issued -preserveDN -in "$csr" -days $DAYS -out "$cert" 2> /dev/null -+ openssl x509 -noout -text -in "$cert" > "$cert.txt" -+ cat "$cert" >> "$cert.txt" -+ cat "$cert.txt" > "$cert" -+ rm -f "$cert.txt" -+else -+ echo "You already have a $cert file; not replacing." -+ done=echo -+fi -+ -+if test -s ca.chain.crt ; then -+ chain=ca.chain.crt -+else -+ chain=ca.crt -+fi -+if test "x$CA" = xTRUE ; then -+ cat "$chain" "$cert" > "$commonname/ca.chain.crt" -+fi -+ -+# Create ca.pem and the subject's name.pem for the benefit of applications -+# which expect both the private key and the certificate in one file. -+umask=`umask -p` -+umask 077 -+if ! test -s ca.pem ; then -+ cat ca.key ca.crt > ca.pem -+else -+ echo "You already have a ca.pem file; not replacing." -+ done=echo -+fi -+if ! test -s "$pem" ; then -+ cat "$key" "$cert" > "$pem" -+else -+ echo "You already have a $pem file; not replacing." -+ done=echo -+fi -+if ! test -s "$pfx" ; then -+ #openssl pkcs12 -export -inkey "$key" -in "$cert" -name "$commonname" -out "$pfx" -nodes -passout pass:qweqwe -+ openssl pkcs12 -export -inkey "$key" -in "$cert" -name "$commonname" -out "$pfx" -nodes -passout pass: -+else -+ echo "You already have a $pfx file; not replacing." -+ done=echo -+fi -+$umask -+$done -+ -+echo CA certificate: -+openssl x509 -noout -issuer -in ca.crt | sed s,=\ ,\ ,g -+openssl x509 -noout -subject -in ca.crt | sed s,=\ ,\ ,g -+echo -+echo End entity certificate: -+openssl x509 -noout -issuer -in "$cert" | sed s,=\ ,\ ,g -+openssl x509 -noout -subject -in "$cert" | sed s,=\ ,\ ,g -+openssl x509 -noout -serial -in "$cert" | sed s,=,\ ,g -+echo -+echo PKCS12 bag: -+openssl pkcs12 -in "$pfx" -nodes -nokeys -nocerts -info -passin pass: -+#openssl pkcs12 -in "$pfx" -nodes -nokeys -nocerts -info -passin pass:qweqwe -+echo -+echo Verifying: -+echo + openssl verify -CAfile "$chain" "$cert" -+openssl verify -CAfile "$chain" "$cert" -diff --git a/shim.c b/shim.c -index 8130ed8..4d490b9 100644 ---- a/shim.c -+++ b/shim.c -@@ -40,6 +40,7 @@ - #include "shim.h" - #include "signature.h" - #include "netboot.h" -+#include "shim_cert.h" - - #define SECOND_STAGE L"\\grub.efi" - #define MOK_MANAGER L"\\MokManager.efi" -@@ -415,6 +416,8 @@ static BOOLEAN secure_mode (void) - UINT8 sb, setupmode; - UINT32 attributes; - -+ return TRUE; -+ - if (insecure_mode) - return FALSE; - -@@ -696,6 +699,19 @@ static EFI_STATUS verify_buffer (char *data, int datasize, - } - - /* -+ * Check against the shim build key -+ */ -+ if (AuthenticodeVerify(cert->CertData, -+ context->SecDir->Size - sizeof(cert->Hdr), -+ shim_cert, sizeof(shim_cert), sha256hash, -+ SHA256_DIGEST_SIZE)) { -+ status = EFI_SUCCESS; -+ Print(L"Binary is verified by the vendor certificate\n"); -+ return status; -+ } -+ -+ -+ /* - * And finally, check against shim's built-in key - */ - if (AuthenticodeVerify(cert->CertData, -@@ -1180,12 +1196,8 @@ EFI_STATUS init_grub(EFI_HANDLE image_handle) - - efi_status = start_image(image_handle, SECOND_STAGE); - -- if (efi_status != EFI_SUCCESS) { -- if (efi_status == EFI_ACCESS_DENIED) -- efi_status = start_image(image_handle, MOK_MANAGER); -- else -- Print(L"Failed to start grub\n"); -- } -+ if (efi_status != EFI_SUCCESS) -+ efi_status = start_image(image_handle, MOK_MANAGER); - done: - - return efi_status; --- -1.7.10.4 - - -From 9c0c64ebde4ec504fc4e4d92ea18b889b1ccd498 Mon Sep 17 00:00:00 2001 -From: Matthew Garrett -Date: Tue, 27 Nov 2012 23:52:27 -0500 -Subject: [PATCH 2/2] Remove debug code - -secure_mode() was altered to always return true for debug purposes, and this -accidentally got committed to mainline. Fix that. ---- - shim.c | 2 -- - 1 file changed, 2 deletions(-) - -diff --git a/shim.c b/shim.c -index 4d490b9..c3aae9e 100644 ---- a/shim.c -+++ b/shim.c -@@ -416,8 +416,6 @@ static BOOLEAN secure_mode (void) - UINT8 sb, setupmode; - UINT32 attributes; - -- return TRUE; -- - if (insecure_mode) - return FALSE; - --- -1.7.10.4 - diff --git a/shim-merge-lf-loader-code.patch b/shim-merge-lf-loader-code.patch new file mode 100644 index 0000000..6692f39 --- /dev/null +++ b/shim-merge-lf-loader-code.patch @@ -0,0 +1,5260 @@ +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-new-pw-hash.patch b/shim-mokmanager-new-pw-hash.patch deleted file mode 100644 index 2ccb194..0000000 --- a/shim-mokmanager-new-pw-hash.patch +++ /dev/null @@ -1,587 +0,0 @@ -From 6e816e3e0f8b2013c1bccd67ec27db10ccaabc67 Mon Sep 17 00:00:00 2001 -From: Gary Ching-Pang Lin -Date: Tue, 15 Jan 2013 18:01:41 +0800 -Subject: [PATCH 1/2] Support new password hash - -Old password hash: sha256sum(key_list + password) -New password hash: salt + sha256sum(salt + password) ---- - MokManager.c | 91 ++++++++++++++++++++++++++++++++++++++++++---------------- - 1 file changed, 67 insertions(+), 24 deletions(-) - -diff --git a/MokManager.c b/MokManager.c -index 97588cb..be2a764 100644 ---- a/MokManager.c -+++ b/MokManager.c -@@ -19,6 +19,9 @@ - #define CERT_STRING L"Select an X509 certificate to enroll:\n\n" - #define HASH_STRING L"Select a file to trust:\n\n" - -+#define SALT_LEN 16 -+#define AUTH_LEN (SALT_LEN + SHA256_DIGEST_SIZE) -+ - struct menu_item { - CHAR16 *text; - INTN (* callback)(void *data, void *data2, void *data3); -@@ -648,23 +651,30 @@ 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 data[AUTH_LEN], *auth, *salt; -+ UINTN auth_size = AUTH_LEN; - 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); -+ &attributes, &auth_size, data); - - -- if (efi_status != EFI_SUCCESS || auth_size != SHA256_DIGEST_SIZE) { -+ if (efi_status != EFI_SUCCESS || -+ (auth_size != SHA256_DIGEST_SIZE && auth_size != AUTH_LEN)) { - Print(L"Failed to get MokAuth %d\n", efi_status); - return efi_status; - } - -- efi_status = match_password(MokNew, MokNewSize, auth, NULL); -+ if (auth_size == AUTH_LEN) { -+ salt = data; -+ auth = data + SALT_LEN; -+ efi_status = match_password(salt, SALT_LEN, auth, NULL); -+ } else { -+ auth = data; -+ efi_status = match_password(MokNew, MokNewSize, auth, NULL); -+ } - if (efi_status != EFI_SUCCESS) - return EFI_ACCESS_DENIED; - } -@@ -842,8 +852,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 data[AUTH_LEN], *auth, *salt;; -+ UINTN auth_size = AUTH_LEN; - UINT32 attributes; - void *MokListData = NULL; - UINTN MokListDataSize = 0; -@@ -853,14 +863,22 @@ static EFI_STATUS delete_keys (void *MokDel, UINTN MokDelSize) - - efi_status = uefi_call_wrapper(RT->GetVariable, 5, L"MokDelAuth", - &shim_lock_guid, -- &attributes, &auth_size, auth); -+ &attributes, &auth_size, data); - -- if (efi_status != EFI_SUCCESS || auth_size != SHA256_DIGEST_SIZE) { -+ if (efi_status != EFI_SUCCESS || -+ (auth_size != SHA256_DIGEST_SIZE && auth_size != AUTH_LEN)) { - Print(L"Failed to get MokDelAuth %d\n", efi_status); - return efi_status; - } - -- efi_status = match_password(MokDel, MokDelSize, auth, NULL); -+ if (auth_size == AUTH_LEN) { -+ salt = data; -+ auth = data + SALT_LEN; -+ efi_status = match_password(salt, SALT_LEN, auth, NULL); -+ } else { -+ auth = data; -+ efi_status = match_password(MokDel, MokDelSize, auth, NULL); -+ } - if (efi_status != EFI_SUCCESS) - return EFI_ACCESS_DENIED; - -@@ -1052,20 +1070,29 @@ static INTN mok_pw_prompt (void *MokPW, void *data2, void *data3) { - EFI_GUID shim_lock_guid = SHIM_LOCK_GUID; - EFI_STATUS efi_status; - UINTN MokPWSize = (UINTN)data2; -- UINT8 hash[SHA256_DIGEST_SIZE]; -+ UINT8 hash[AUTH_LEN], *auth, *salt; -+ UINT8 clear = 0; - UINT32 length; - CHAR16 line[1]; - -- if (MokPWSize != SHA256_DIGEST_SIZE) { -+ if (MokPWSize != SHA256_DIGEST_SIZE && MokPWSize != AUTH_LEN) { - Print(L"Invalid MokPW variable contents\n"); - return -1; - } - - uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut); - -- SetMem(hash, SHA256_DIGEST_SIZE, 0); -+ SetMem(hash, AUTH_LEN, 0); -+ -+ if (MokPWSize == AUTH_LEN) { -+ if (CompareMem(MokPW, hash, AUTH_LEN) == 0) -+ clear = 1; -+ } else { -+ if (CompareMem(MokPW, hash, SHA256_DIGEST_SIZE) == 0) -+ clear = 1; -+ } - -- if (CompareMem(MokPW, hash, SHA256_DIGEST_SIZE) == 0) { -+ if (clear) { - Print(L"Clear MOK password? (y/n): "); - - do { -@@ -1080,7 +1107,14 @@ static INTN mok_pw_prompt (void *MokPW, void *data2, void *data3) { - return 0; - } - -- efi_status = match_password(NULL, 0, MokPW, L"Confirm MOK passphrase: "); -+ if (MokPWSize == AUTH_LEN) { -+ salt = MokPW; -+ auth = MokPW + SALT_LEN; -+ efi_status = match_password(salt, SALT_LEN, auth, L"Confirm MOK passphrase: "); -+ } else { -+ efi_status = match_password(NULL, 0, MokPW, L"Confirm MOK passphrase: "); -+ } -+ - if (efi_status != EFI_SUCCESS) { - Print(L"Password limit reached\n"); - return -1; -@@ -1691,8 +1725,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[AUTH_LEN], *auth, *salt; -+ UINTN size = AUTH_LEN; - UINT32 attributes; - - efi_status = uefi_call_wrapper(RT->GetVariable, 5, L"MokPWStore", -@@ -1704,7 +1738,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 != AUTH_LEN)) - return TRUE; - - if (attributes & EFI_VARIABLE_RUNTIME_ACCESS) -@@ -1712,7 +1747,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 == AUTH_LEN) { -+ salt = pwhash; -+ auth = pwhash + SALT_LEN; -+ efi_status = match_password(salt, SALT_LEN, auth, L"Enter MOK password: "); -+ } else { -+ efi_status = match_password(NULL, 0, pwhash, L"Enter MOK password: "); -+ } - if (efi_status != EFI_SUCCESS) { - Print(L"Password limit reached\n"); - return FALSE; -@@ -1733,8 +1774,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[AUTH_LEN]; -+ UINTN auth_size = AUTH_LEN; - UINT32 attributes; - - if (verify_pw() == FALSE) -@@ -1744,14 +1785,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 == AUTH_LEN)) - 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 == AUTH_LEN)) - MokDelAuth = 1; - - if (MokNew || MokAuth) --- -1.7.10.4 - - -From cf448e938a54ee3006f0fca214b83e0a40499ea5 Mon Sep 17 00:00:00 2001 -From: Gary Ching-Pang Lin -Date: Fri, 18 Jan 2013 15:51:02 +0800 -Subject: [PATCH 2/2] Extend the password hash format - -Several new fields were added to support hash from /etc/shadow. -Affected variables: MokAuth, MokDelAuth, MokPW, MokPWStore - -[Hash Method][Interation Count][Salt Size][Salt][hash] - -Besides, the password is converted to a 8-bit char array before -hashing with salt. ---- - MokManager.c | 145 +++++++++++++++++++++++++++++++++----------------------- - PasswordHash.h | 23 +++++++++ - 2 files changed, 110 insertions(+), 58 deletions(-) - create mode 100644 PasswordHash.h - -diff --git a/MokManager.c b/MokManager.c -index be2a764..9c8f32f 100644 ---- a/MokManager.c -+++ b/MokManager.c -@@ -5,6 +5,7 @@ - #include "shim.h" - #include "signature.h" - #include "PeImage.h" -+#include "PasswordHash.h" - - #define PASSWORD_MAX 16 - #define PASSWORD_MIN 8 -@@ -19,9 +20,6 @@ - #define CERT_STRING L"Select an X509 certificate to enroll:\n\n" - #define HASH_STRING L"Select a file to trust:\n\n" - --#define SALT_LEN 16 --#define AUTH_LEN (SALT_LEN + SHA256_DIGEST_SIZE) -- - struct menu_item { - CHAR16 *text; - INTN (* callback)(void *data, void *data2, void *data3); -@@ -553,8 +551,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; -@@ -574,15 +572,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))) { - Print(L"Unable to generate hash\n"); - status = EFI_OUT_OF_RESOURCES; - goto done; - } - } - -- if (!(Sha256Update(ctx, password, pw_length * sizeof(CHAR16)))) { -+ if (!(Sha256Update(ctx, password, pw_length))) { - Print(L"Unable to generate hash\n"); - status = EFI_OUT_OF_RESOURCES; - goto done; -@@ -599,15 +597,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_HASH *pw_hash, -+ void *Data, UINTN DataSize, -+ UINT8 *auth, CHAR16 *prompt) - { - EFI_STATUS efi_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_hash) { -+ /* -+ * Only support sha256 now and ignore iter_count -+ */ -+ if(pw_hash->method != SHA256_BASED) -+ return EFI_INVALID_PARAMETER; -+ auth_hash = pw_hash->hash; -+ /* FIXME assign auth_size according to pw_hash->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) { -@@ -623,16 +640,31 @@ 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_hash) { -+ char pw_ascii[PASSWORD_MAX]; -+ for (i = 0; i < pw_length; i++) -+ pw_ascii[i] = (char)password[i]; -+ -+ /* FIXME calculate a proper salt_size */ -+ efi_status = compute_pw_hash(pw_hash->salt, (pw_hash->salt_size)/8, -+ (UINT8 *)pw_ascii, pw_length, hash); -+ } else { -+ /* -+ * For backward compatibility -+ */ -+ efi_status = compute_pw_hash(Data, DataSize, (UINT8 *)password, -+ pw_length * sizeof(CHAR16), hash); -+ } - if (efi_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; -@@ -651,29 +683,28 @@ static EFI_STATUS store_keys (void *MokNew, UINTN MokNewSize, int authenticate) - { - EFI_GUID shim_lock_guid = SHIM_LOCK_GUID; - EFI_STATUS efi_status; -- UINT8 data[AUTH_LEN], *auth, *salt; -- UINTN auth_size = AUTH_LEN; -+ UINT8 auth[PASSWORD_HASH_SIZE]; -+ UINTN auth_size = PASSWORD_HASH_SIZE; - UINT32 attributes; - - if (authenticate) { - efi_status = uefi_call_wrapper(RT->GetVariable, 5, L"MokAuth", - &shim_lock_guid, -- &attributes, &auth_size, data); -- -+ &attributes, &auth_size, auth); - - if (efi_status != EFI_SUCCESS || -- (auth_size != SHA256_DIGEST_SIZE && auth_size != AUTH_LEN)) { -+ (auth_size != SHA256_DIGEST_SIZE && -+ auth_size != PASSWORD_HASH_SIZE)) { - Print(L"Failed to get MokAuth %d\n", efi_status); - return efi_status; - } - -- if (auth_size == AUTH_LEN) { -- salt = data; -- auth = data + SALT_LEN; -- efi_status = match_password(salt, SALT_LEN, auth, NULL); -+ if (auth_size == PASSWORD_HASH_SIZE) { -+ efi_status = match_password((PASSWORD_HASH *)auth, -+ NULL, 0, NULL, NULL); - } else { -- auth = data; -- efi_status = match_password(MokNew, MokNewSize, auth, NULL); -+ efi_status = match_password(NULL, MokNew, MokNewSize, -+ auth, NULL); - } - if (efi_status != EFI_SUCCESS) - return EFI_ACCESS_DENIED; -@@ -852,8 +883,8 @@ static EFI_STATUS delete_keys (void *MokDel, UINTN MokDelSize) - { - EFI_GUID shim_lock_guid = SHIM_LOCK_GUID; - EFI_STATUS efi_status; -- UINT8 data[AUTH_LEN], *auth, *salt;; -- UINTN auth_size = AUTH_LEN; -+ UINT8 auth[PASSWORD_HASH_SIZE]; -+ UINTN auth_size = PASSWORD_HASH_SIZE; - UINT32 attributes; - void *MokListData = NULL; - UINTN MokListDataSize = 0; -@@ -863,21 +894,19 @@ static EFI_STATUS delete_keys (void *MokDel, UINTN MokDelSize) - - efi_status = uefi_call_wrapper(RT->GetVariable, 5, L"MokDelAuth", - &shim_lock_guid, -- &attributes, &auth_size, data); -+ &attributes, &auth_size, auth); - - if (efi_status != EFI_SUCCESS || -- (auth_size != SHA256_DIGEST_SIZE && auth_size != AUTH_LEN)) { -+ (auth_size != SHA256_DIGEST_SIZE && auth_size != PASSWORD_HASH_SIZE)) { - Print(L"Failed to get MokDelAuth %d\n", efi_status); - return efi_status; - } - -- if (auth_size == AUTH_LEN) { -- salt = data; -- auth = data + SALT_LEN; -- efi_status = match_password(salt, SALT_LEN, auth, NULL); -+ if (auth_size == PASSWORD_HASH_SIZE) { -+ efi_status = match_password((PASSWORD_HASH *)auth, NULL, 0, -+ NULL, NULL); - } else { -- auth = data; -- efi_status = match_password(MokDel, MokDelSize, auth, NULL); -+ efi_status = match_password(NULL, MokDel, MokDelSize, auth, NULL); - } - if (efi_status != EFI_SUCCESS) - return EFI_ACCESS_DENIED; -@@ -1070,22 +1099,22 @@ static INTN mok_pw_prompt (void *MokPW, void *data2, void *data3) { - EFI_GUID shim_lock_guid = SHIM_LOCK_GUID; - EFI_STATUS efi_status; - UINTN MokPWSize = (UINTN)data2; -- UINT8 hash[AUTH_LEN], *auth, *salt; -+ UINT8 hash[PASSWORD_HASH_SIZE]; - UINT8 clear = 0; - UINT32 length; - CHAR16 line[1]; - -- if (MokPWSize != SHA256_DIGEST_SIZE && MokPWSize != AUTH_LEN) { -+ if (MokPWSize != SHA256_DIGEST_SIZE && MokPWSize != PASSWORD_HASH_SIZE) { - Print(L"Invalid MokPW variable contents\n"); - return -1; - } - - uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut); - -- SetMem(hash, AUTH_LEN, 0); -+ SetMem(hash, PASSWORD_HASH_SIZE, 0); - -- if (MokPWSize == AUTH_LEN) { -- if (CompareMem(MokPW, hash, AUTH_LEN) == 0) -+ if (MokPWSize == PASSWORD_HASH_SIZE) { -+ if (CompareMem(MokPW, hash, PASSWORD_HASH_SIZE) == 0) - clear = 1; - } else { - if (CompareMem(MokPW, hash, SHA256_DIGEST_SIZE) == 0) -@@ -1107,12 +1136,12 @@ static INTN mok_pw_prompt (void *MokPW, void *data2, void *data3) { - return 0; - } - -- if (MokPWSize == AUTH_LEN) { -- salt = MokPW; -- auth = MokPW + SALT_LEN; -- efi_status = match_password(salt, SALT_LEN, auth, L"Confirm MOK passphrase: "); -+ if (MokPWSize == PASSWORD_HASH_SIZE) { -+ efi_status = match_password((PASSWORD_HASH *)MokPW, NULL, 0, -+ NULL, L"Confirm MOK passphrase: "); - } else { -- efi_status = match_password(NULL, 0, MokPW, L"Confirm MOK passphrase: "); -+ efi_status = match_password(NULL, NULL, 0, MokPW, -+ L"Confirm MOK passphrase: "); - } - - if (efi_status != EFI_SUCCESS) { -@@ -1725,8 +1754,8 @@ static BOOLEAN verify_pw(void) - { - EFI_GUID shim_lock_guid = SHIM_LOCK_GUID; - EFI_STATUS efi_status; -- UINT8 pwhash[AUTH_LEN], *auth, *salt; -- UINTN size = AUTH_LEN; -+ UINT8 pwhash[PASSWORD_HASH_SIZE]; -+ UINTN size = PASSWORD_HASH_SIZE; - UINT32 attributes; - - efi_status = uefi_call_wrapper(RT->GetVariable, 5, L"MokPWStore", -@@ -1739,7 +1768,7 @@ static BOOLEAN verify_pw(void) - * purely because of a failure to read the variable - */ - if (efi_status != EFI_SUCCESS || -- (size != SHA256_DIGEST_SIZE && size != AUTH_LEN)) -+ (size != SHA256_DIGEST_SIZE && size != PASSWORD_HASH_SIZE)) - return TRUE; - - if (attributes & EFI_VARIABLE_RUNTIME_ACCESS) -@@ -1747,12 +1776,12 @@ static BOOLEAN verify_pw(void) - - uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut); - -- if (size == AUTH_LEN) { -- salt = pwhash; -- auth = pwhash + SALT_LEN; -- efi_status = match_password(salt, SALT_LEN, auth, L"Enter MOK password: "); -+ if (size == PASSWORD_HASH_SIZE) { -+ efi_status = match_password((PASSWORD_HASH *)pwhash, NULL, 0, -+ NULL, L"Enter MOK password: "); - } else { -- efi_status = match_password(NULL, 0, pwhash, L"Enter MOK password: "); -+ efi_status = match_password(NULL, NULL, 0, pwhash, -+ L"Enter MOK password: "); - } - if (efi_status != EFI_SUCCESS) { - Print(L"Password limit reached\n"); -@@ -1774,8 +1803,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[AUTH_LEN]; -- UINTN auth_size = AUTH_LEN; -+ UINT8 auth[PASSWORD_HASH_SIZE]; -+ UINTN auth_size = PASSWORD_HASH_SIZE; - UINT32 attributes; - - if (verify_pw() == FALSE) -@@ -1786,7 +1815,7 @@ static EFI_STATUS enter_mok_menu(EFI_HANDLE image_handle, - &attributes, &auth_size, auth); - - if ((efi_status == EFI_SUCCESS) && -- (auth_size == SHA256_DIGEST_SIZE || auth_size == AUTH_LEN)) -+ (auth_size == SHA256_DIGEST_SIZE || auth_size == PASSWORD_HASH_SIZE)) - MokAuth = 1; - - efi_status = uefi_call_wrapper(RT->GetVariable, 5, L"MokDelAuth", -@@ -1794,7 +1823,7 @@ static EFI_STATUS enter_mok_menu(EFI_HANDLE image_handle, - &attributes, &auth_size, auth); - - if ((efi_status == EFI_SUCCESS) && -- (auth_size == SHA256_DIGEST_SIZE || auth_size == AUTH_LEN)) -+ (auth_size == SHA256_DIGEST_SIZE || auth_size == PASSWORD_HASH_SIZE)) - MokDelAuth = 1; - - if (MokNew || MokAuth) -diff --git a/PasswordHash.h b/PasswordHash.h -new file mode 100644 -index 0000000..70ee441 ---- /dev/null -+++ b/PasswordHash.h -@@ -0,0 +1,23 @@ -+#ifndef __PASSWORD_HASH_H__ -+#define __PASSWORD_HASH_H__ -+ -+#define PASSWORD_HASH_SIZE 88 -+ -+enum HashMethod { -+ Tranditional_DES = 0, -+ Extend_BSDI_DES, -+ MD5_BASED, -+ SHA256_BASED, -+ SHA512_BASED, -+ BLOWFISH_BASED -+}; -+ -+typedef struct { -+ UINT16 method; -+ UINT32 iter_count; -+ UINT16 salt_size; -+ UINT8 salt[16]; -+ UINT8 hash[64]; -+} __attribute__ ((packed)) PASSWORD_HASH; -+ -+#endif /* __PASSWORD_HASH_H__ */ --- -1.7.10.4 - diff --git a/shim-mokmanager-support-crypt-hash-method.patch b/shim-mokmanager-support-crypt-hash-method.patch index e09287e..374637a 100644 --- a/shim-mokmanager-support-crypt-hash-method.patch +++ b/shim-mokmanager-support-crypt-hash-method.patch @@ -1,31 +1,28 @@ -From d046361f872467ed4a8481968ffb089596f6ae30 Mon Sep 17 00:00:00 2001 +From 1c373e8acff0bd08cfd6a596d2df732fd5324627 Mon Sep 17 00:00:00 2001 From: Gary Ching-Pang Lin -Date: Wed, 23 Jan 2013 18:33:01 +0800 -Subject: [PATCH 1/6] Adopt the crypt_r() hash style +Date: Tue, 15 Jan 2013 18:01:41 +0800 +Subject: [PATCH 1/5] MokManager: support crypt() password hash -1. This commit implements the sha256-based hash method used in crypt_r() - in glibc. +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. -2. The password length now is allowed to be 1 to 256 characters. - -3. The size of password hash structure is changed and the extra space - is reserved for the future use. +This commit implements the sha256-based crypt() hash function. --- - Makefile | 6 +-- - MokManager.c | 88 +++++++++++++++++++-------------------- - PasswordCrypt.c | 124 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ - PasswordCrypt.h | 26 ++++++++++++ - PasswordHash.h | 23 ----------- - 5 files changed, 196 insertions(+), 71 deletions(-) + 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 - delete mode 100644 PasswordHash.h diff --git a/Makefile b/Makefile -index 412eba5..321c3f5 100644 +index 50b5898..fa303e4 100644 --- a/Makefile +++ b/Makefile -@@ -32,8 +32,8 @@ TARGET = shim.efi MokManager.efi.signed +@@ -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 @@ -33,29 +30,31 @@ index 412eba5..321c3f5 100644 -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 - all: $(TARGET) - -@@ -65,7 +65,7 @@ dbx.o : dbx.S - shim.so: $(OBJS) Cryptlib/libcryptlib.a Cryptlib/OpenSSL/libopenssl.a +@@ -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 - $(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 diff --git a/MokManager.c b/MokManager.c -index 9c8f32f..6b0e6f3 100644 +index 60e799a..6cf24e6 100644 --- a/MokManager.c +++ b/MokManager.c -@@ -5,11 +5,11 @@ +@@ -5,13 +5,14 @@ #include "shim.h" #include "signature.h" #include "PeImage.h" --#include "PasswordHash.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 @@ -65,7 +64,7 @@ index 9c8f32f..6b0e6f3 100644 #ifndef SHIM_VENDOR #define SHIM_VENDOR L"Shim" -@@ -38,7 +38,7 @@ typedef struct { +@@ -28,7 +29,7 @@ typedef struct { typedef struct { UINT32 MokSBState; UINT32 PWLen; @@ -74,219 +73,288 @@ index 9c8f32f..6b0e6f3 100644 } __attribute__ ((packed)) MokSBvar; static EFI_STATUS get_variable (CHAR16 *name, EFI_GUID guid, UINT32 *attributes, -@@ -597,11 +597,11 @@ done: +@@ -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 (PASSWORD_HASH *pw_hash, +-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) ++ 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; -@@ -610,14 +610,14 @@ static EFI_STATUS match_password (PASSWORD_HASH *pw_hash, ++ UINT8 *auth_hash; ++ UINT32 auth_size; + CHAR16 password[PASSWORD_MAX]; + UINT32 pw_length; UINT8 fail_count = 0; - int i; - -- if (pw_hash) { ++ int i; ++ + if (pw_crypt) { - /* -- * Only support sha256 now and ignore iter_count ++ /* + * Only support sha256 now - */ -- if(pw_hash->method != SHA256_BASED) ++ */ + if(pw_crypt->method != SHA256_BASED) - return EFI_INVALID_PARAMETER; -- auth_hash = pw_hash->hash; -- /* FIXME assign auth_size according to pw_hash->method */ ++ 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; -@@ -643,22 +643,20 @@ static EFI_STATUS match_password (PASSWORD_HASH *pw_hash, - /* - * Compute password hash - */ -- if (pw_hash) { -+ if (pw_crypt) { - char pw_ascii[PASSWORD_MAX]; - for (i = 0; i < pw_length; i++) - pw_ascii[i] = (char)password[i]; ++ auth_size = SHA256_DIGEST_SIZE; ++ } else if (auth) { ++ auth_hash = auth; ++ auth_size = SHA256_DIGEST_SIZE; ++ } else { ++ return EFI_INVALID_PARAMETER; ++ } -- /* FIXME calculate a proper salt_size */ -- efi_status = compute_pw_hash(pw_hash->salt, (pw_hash->salt_size)/8, -- (UINT8 *)pw_ascii, pw_length, hash); + 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 - */ -- efi_status = compute_pw_hash(Data, DataSize, (UINT8 *)password, -- pw_length * sizeof(CHAR16), hash); ++ } else { ++ /* ++ * For backward compatibility ++ */ + status = compute_pw_hash(Data, DataSize, (UINT8 *)password, + pw_length * sizeof(CHAR16), hash); - } -- if (efi_status != EFI_SUCCESS) { ++ } + if (status != EFI_SUCCESS) { Print(L"Unable to generate password hash\n"); fail_count++; continue; -@@ -683,8 +681,8 @@ static EFI_STATUS store_keys (void *MokNew, UINTN MokNewSize, int authenticate) + } + +- 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[PASSWORD_HASH_SIZE]; -- UINTN auth_size = PASSWORD_HASH_SIZE; +- UINT8 auth[SHA256_DIGEST_SIZE]; +- UINTN auth_size; + UINT8 auth[PASSWORD_CRYPT_SIZE]; + UINTN auth_size = PASSWORD_CRYPT_SIZE; UINT32 attributes; if (authenticate) { -@@ -694,13 +692,13 @@ static EFI_STATUS store_keys (void *MokNew, UINTN MokNewSize, int 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 && -- auth_size != PASSWORD_HASH_SIZE)) { +- +- 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)) { - Print(L"Failed to get MokAuth %d\n", efi_status); + console_error(L"Failed to get MokAuth", efi_status); return efi_status; } -- if (auth_size == PASSWORD_HASH_SIZE) { -- efi_status = match_password((PASSWORD_HASH *)auth, +- 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, -@@ -883,8 +881,8 @@ static EFI_STATUS delete_keys (void *MokDel, UINTN MokDelSize) ++ 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[PASSWORD_HASH_SIZE]; -- UINTN auth_size = PASSWORD_HASH_SIZE; +- 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; -@@ -897,13 +895,13 @@ static EFI_STATUS delete_keys (void *MokDel, UINTN MokDelSize) +@@ -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 && auth_size != PASSWORD_HASH_SIZE)) { +- 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)) { - Print(L"Failed to get MokDelAuth %d\n", efi_status); + console_error(L"Failed to get MokDelAuth", efi_status); return efi_status; } -- if (auth_size == PASSWORD_HASH_SIZE) { -- efi_status = match_password((PASSWORD_HASH *)auth, NULL, 0, +- 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); -@@ -1099,22 +1097,22 @@ static INTN mok_pw_prompt (void *MokPW, void *data2, void *data3) { ++ 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; - UINTN MokPWSize = (UINTN)data2; -- UINT8 hash[PASSWORD_HASH_SIZE]; +- UINT8 hash[SHA256_DIGEST_SIZE]; + UINT8 hash[PASSWORD_CRYPT_SIZE]; - UINT8 clear = 0; - UINT32 length; - CHAR16 line[1]; ++ UINT8 clear = 0; -- if (MokPWSize != SHA256_DIGEST_SIZE && MokPWSize != PASSWORD_HASH_SIZE) { +- if (MokPWSize != SHA256_DIGEST_SIZE) { + if (MokPWSize != SHA256_DIGEST_SIZE && MokPWSize != PASSWORD_CRYPT_SIZE) { - Print(L"Invalid MokPW variable contents\n"); + console_notify(L"Invalid MokPW variable contents"); return -1; } uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut); -- SetMem(hash, PASSWORD_HASH_SIZE, 0); +- SetMem(hash, SHA256_DIGEST_SIZE, 0); + SetMem(hash, PASSWORD_CRYPT_SIZE, 0); - -- if (MokPWSize == PASSWORD_HASH_SIZE) { -- if (CompareMem(MokPW, hash, PASSWORD_HASH_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) -@@ -1136,8 +1134,8 @@ static INTN mok_pw_prompt (void *MokPW, void *data2, void *data3) { ++ 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; } -- if (MokPWSize == PASSWORD_HASH_SIZE) { -- efi_status = match_password((PASSWORD_HASH *)MokPW, NULL, 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, -@@ -1754,8 +1752,8 @@ static BOOLEAN verify_pw(void) ++ 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[PASSWORD_HASH_SIZE]; -- UINTN size = PASSWORD_HASH_SIZE; +- 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", -@@ -1768,7 +1766,7 @@ static BOOLEAN verify_pw(void) +@@ -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 || -- (size != SHA256_DIGEST_SIZE && size != PASSWORD_HASH_SIZE)) +- 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) -@@ -1776,8 +1774,8 @@ static BOOLEAN verify_pw(void) +@@ -1286,7 +1349,13 @@ static BOOLEAN verify_pw(void) uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut); -- if (size == PASSWORD_HASH_SIZE) { -- efi_status = match_password((PASSWORD_HASH *)pwhash, NULL, 0, +- 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, -@@ -1803,8 +1801,8 @@ static EFI_STATUS enter_mok_menu(EFI_HANDLE image_handle, ++ 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[PASSWORD_HASH_SIZE]; -- UINTN auth_size = PASSWORD_HASH_SIZE; +- 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; - if (verify_pw() == FALSE) -@@ -1815,7 +1813,7 @@ static EFI_STATUS enter_mok_menu(EFI_HANDLE image_handle, +@@ -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 || auth_size == PASSWORD_HASH_SIZE)) +- 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", -@@ -1823,7 +1821,7 @@ 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 || auth_size == PASSWORD_HASH_SIZE)) +- 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; @@ -453,69 +521,40 @@ index 0000000..c9e377a + const PASSWORD_CRYPT *pw_hash, UINT8 *hash); + +#endif /* __PASSWORD_CRYPT_H__ */ -diff --git a/PasswordHash.h b/PasswordHash.h -deleted file mode 100644 -index 70ee441..0000000 ---- a/PasswordHash.h -+++ /dev/null -@@ -1,23 +0,0 @@ --#ifndef __PASSWORD_HASH_H__ --#define __PASSWORD_HASH_H__ -- --#define PASSWORD_HASH_SIZE 88 -- --enum HashMethod { -- Tranditional_DES = 0, -- Extend_BSDI_DES, -- MD5_BASED, -- SHA256_BASED, -- SHA512_BASED, -- BLOWFISH_BASED --}; -- --typedef struct { -- UINT16 method; -- UINT32 iter_count; -- UINT16 salt_size; -- UINT8 salt[16]; -- UINT8 hash[64]; --} __attribute__ ((packed)) PASSWORD_HASH; -- --#endif /* __PASSWORD_HASH_H__ */ -- -1.7.10.4 +1.8.1.4 -From 1e3f6fa2e149980d337365d55728da74ed76fe1f Mon Sep 17 00:00:00 2001 +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/6] Support SHA512-based crypt() hash +Subject: [PATCH 2/5] MokManager: support SHA512-based crypt() hash --- - Cryptlib/OpenSSL/Makefile | 2 +- - MokManager.c | 12 ++--- - PasswordCrypt.c | 114 +++++++++++++++++++++++++++++++++++++++++++++ - PasswordCrypt.h | 1 + + 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 7fde382..c44c008 100644 +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 \ -- -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 -mno-red-zone -+ -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 -mno-red-zone + 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 + CFLAGS += -DEFI_FUNCTION_WRAPPER -DGNU_EFI_USE_MS_ABI endif diff --git a/MokManager.c b/MokManager.c -index 6b0e6f3..65465ec 100644 +index 6cf24e6..b05a52f 100644 --- a/MokManager.c +++ b/MokManager.c -@@ -602,7 +602,7 @@ static EFI_STATUS match_password (PASSWORD_CRYPT *pw_crypt, +@@ -623,7 +623,7 @@ static EFI_STATUS match_password (PASSWORD_CRYPT *pw_crypt, UINT8 *auth, CHAR16 *prompt) { EFI_STATUS status; @@ -524,7 +563,7 @@ index 6b0e6f3..65465ec 100644 UINT8 *auth_hash; UINT32 auth_size; CHAR16 password[PASSWORD_MAX]; -@@ -611,14 +611,10 @@ static EFI_STATUS match_password (PASSWORD_CRYPT *pw_crypt, +@@ -632,14 +632,10 @@ static EFI_STATUS match_password (PASSWORD_CRYPT *pw_crypt, int i; if (pw_crypt) { @@ -695,28 +734,28 @@ index c9e377a..144bf84 100644 #endif /* __PASSWORD_CRYPT_H__ */ -- -1.7.10.4 +1.8.1.4 -From 4df0fbdeda91a42bad688c88f3cebb313ce99484 Mon Sep 17 00:00:00 2001 +From df4644c036ff9d02cbcc08b5902eccb58e8bc305 Mon Sep 17 00:00:00 2001 From: Gary Ching-Pang Lin -Date: Fri, 25 Jan 2013 18:27:31 +0800 -Subject: [PATCH 3/6] Support blowfish-based crypt() hash +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 ++ + 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 321c3f5..b4916f1 100644 +index fa303e4..77f3e52 100644 --- a/Makefile +++ b/Makefile -@@ -32,8 +32,8 @@ TARGET = shim.efi MokManager.efi.signed +@@ -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 @@ -724,8 +763,8 @@ index 321c3f5..b4916f1 100644 -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 - - all: $(TARGET) + FALLBACK_OBJS = fallback.o + FALLBACK_SRCS = fallback.c diff --git a/PasswordCrypt.c b/PasswordCrypt.c index a62512e..38b980f 100644 @@ -1643,16 +1682,16 @@ index 0000000..dc3bd56 + char *output, int size); +#endif -- -1.7.10.4 +1.8.1.4 -From eeda23de3deaa6e13c51e1f831a72a2007029cfb Mon Sep 17 00:00:00 2001 +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/6] Support MD5-based crypt() hash +Subject: [PATCH 4/5] MokManager: support MD5-based crypt() hash --- - PasswordCrypt.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- + PasswordCrypt.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 67 insertions(+), 1 deletion(-) diff --git a/PasswordCrypt.c b/PasswordCrypt.c @@ -1745,17 +1784,17 @@ index 38b980f..8483498 100644 status = sha256_crypt(password, pw_length, (char *)pw_crypt->salt, pw_crypt->salt_size, pw_crypt->iter_count, -- -1.7.10.4 +1.8.1.4 -From cd8e7b8a25023523f30ed065b892aa2bb1b619d6 Mon Sep 17 00:00:00 2001 +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/6] Support Tradition DES hash +Subject: [PATCH 5/5] MokManager: support Tradition DES hash --- - PasswordCrypt.c | 28 +++++++++++++++++++++++----- - PasswordCrypt.h | 2 +- + PasswordCrypt.c | 28 +++++++++++++++++++++++----- + PasswordCrypt.h | 2 +- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/PasswordCrypt.c b/PasswordCrypt.c @@ -1835,34 +1874,5 @@ index 144bf84..b726f32 100644 MD5_BASED, SHA256_BASED, -- -1.7.10.4 - - -From 982d008347669cd6d5699764f23820b9c50d622f Mon Sep 17 00:00:00 2001 -From: Gary Ching-Pang Lin -Date: Tue, 29 Jan 2013 17:41:21 +0800 -Subject: [PATCH 6/6] Append a null character to the ASCII password string - ---- - MokManager.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/MokManager.c b/MokManager.c -index 65465ec..e27c2c1 100644 ---- a/MokManager.c -+++ b/MokManager.c -@@ -640,9 +640,10 @@ static EFI_STATUS match_password (PASSWORD_CRYPT *pw_crypt, - * Compute password hash - */ - if (pw_crypt) { -- char pw_ascii[PASSWORD_MAX]; -+ char pw_ascii[PASSWORD_MAX + 1]; - for (i = 0; i < pw_length; i++) - pw_ascii[i] = (char)password[i]; -+ pw_ascii[pw_length] = '\0'; - - status = password_crypt(pw_ascii, pw_length, pw_crypt, hash); - } else { --- -1.7.10.4 +1.8.1.4 diff --git a/shim-mokmanager-ui-revamp.patch b/shim-mokmanager-ui-revamp.patch index 9e11372..4fbb106 100644 --- a/shim-mokmanager-ui-revamp.patch +++ b/shim-mokmanager-ui-revamp.patch @@ -1,9389 +1,144 @@ -From 0709a7fd4ab06b445ed7343c2e9f544e0040ab21 Mon Sep 17 00:00:00 2001 +From a6436443a82b23de4c5dfe83f3c8389f8b554ad3 Mon Sep 17 00:00:00 2001 From: Gary Ching-Pang Lin -Date: Tue, 16 Apr 2013 16:51:31 +0800 -Subject: [PATCH 01/12] Merge efitools lib +Date: Thu, 30 May 2013 14:22:43 +0800 +Subject: [PATCH 1/8] MokManager: Remove the unnecessary string duplication --- - Makefile | 15 +- - efitools/COPYING | 350 +++++++++++++++ - efitools/Make.rules | 24 + - efitools/Makefile | 15 + - efitools/include/PeImage.h | 787 +++++++++++++++++++++++++++++++++ - efitools/include/configtable.h | 68 +++ - efitools/include/console.h | 21 + - efitools/include/efiauthenticated.h | 222 ++++++++++ - efitools/include/errors.h | 9 + - efitools/include/execute.h | 5 + - efitools/include/guid.h | 19 + - efitools/include/kernel_efivars.h | 26 ++ - efitools/include/pecoff.h | 23 + - efitools/include/security_policy.h | 6 + - efitools/include/sha256.h | 33 ++ - efitools/include/shell.h | 2 + - efitools/include/simple_file.h | 21 + - efitools/include/variables.h | 45 ++ - efitools/include/variables_iterators.h | 16 + - efitools/include/version.h | 8 + - efitools/include/wincert.h | 33 ++ - efitools/include/x509.h | 23 + - efitools/lib/Makefile | 12 + - efitools/lib/asn1/.gitignore | 1 + - efitools/lib/asn1/Makefile | 11 + - efitools/lib/asn1/asn1.c | 197 +++++++++ - efitools/lib/asn1/asn1.h | 115 +++++ - efitools/lib/asn1/asn1_parser.c | 286 ++++++++++++ - efitools/lib/asn1/asn1_parser.h | 117 +++++ - efitools/lib/asn1/chunk.c | 83 ++++ - efitools/lib/asn1/chunk.h | 164 +++++++ - efitools/lib/asn1/enumerator.c | 37 ++ - efitools/lib/asn1/enumerator.h | 55 +++ - efitools/lib/asn1/identification.c | 226 ++++++++++ - efitools/lib/asn1/identification.h | 285 ++++++++++++ - efitools/lib/asn1/oid.c | 390 ++++++++++++++++ - efitools/lib/asn1/oid.h | 224 ++++++++++ - efitools/lib/asn1/oid.pl | 134 ++++++ - efitools/lib/asn1/oid.txt | 377 ++++++++++++++++ - efitools/lib/asn1/test.c | 29 ++ - efitools/lib/asn1/typedefs.h | 117 +++++ - efitools/lib/asn1/x509.c | 58 +++ - efitools/lib/configtable.c | 144 ++++++ - efitools/lib/console.c | 413 +++++++++++++++++ - efitools/lib/execute.c | 127 ++++++ - efitools/lib/guid.c | 57 +++ - efitools/lib/pecoff.c | 391 ++++++++++++++++ - efitools/lib/security_policy.c | 399 +++++++++++++++++ - efitools/lib/sha256.c | 394 +++++++++++++++++ - efitools/lib/shell.c | 57 +++ - efitools/lib/simple_file.c | 501 +++++++++++++++++++++ - efitools/lib/variables.c | 340 ++++++++++++++ - 52 files changed, 7509 insertions(+), 3 deletions(-) - create mode 100644 efitools/COPYING - create mode 100644 efitools/Make.rules - create mode 100644 efitools/Makefile - create mode 100644 efitools/include/PeImage.h - create mode 100644 efitools/include/configtable.h - create mode 100644 efitools/include/console.h - create mode 100644 efitools/include/efiauthenticated.h - create mode 100644 efitools/include/errors.h - create mode 100644 efitools/include/execute.h - create mode 100644 efitools/include/guid.h - create mode 100644 efitools/include/kernel_efivars.h - create mode 100644 efitools/include/pecoff.h - create mode 100644 efitools/include/security_policy.h - create mode 100644 efitools/include/sha256.h - create mode 100644 efitools/include/shell.h - create mode 100644 efitools/include/simple_file.h - create mode 100644 efitools/include/variables.h - create mode 100644 efitools/include/variables_iterators.h - create mode 100644 efitools/include/version.h - create mode 100644 efitools/include/wincert.h - create mode 100644 efitools/include/x509.h - create mode 100644 efitools/lib/Makefile - create mode 100644 efitools/lib/asn1/.gitignore - create mode 100644 efitools/lib/asn1/Makefile - create mode 100644 efitools/lib/asn1/asn1.c - create mode 100644 efitools/lib/asn1/asn1.h - create mode 100644 efitools/lib/asn1/asn1_parser.c - create mode 100644 efitools/lib/asn1/asn1_parser.h - create mode 100644 efitools/lib/asn1/chunk.c - create mode 100644 efitools/lib/asn1/chunk.h - create mode 100644 efitools/lib/asn1/enumerator.c - create mode 100644 efitools/lib/asn1/enumerator.h - create mode 100644 efitools/lib/asn1/identification.c - create mode 100644 efitools/lib/asn1/identification.h - create mode 100644 efitools/lib/asn1/oid.c - create mode 100644 efitools/lib/asn1/oid.h - create mode 100644 efitools/lib/asn1/oid.pl - create mode 100644 efitools/lib/asn1/oid.txt - create mode 100644 efitools/lib/asn1/test.c - create mode 100644 efitools/lib/asn1/typedefs.h - create mode 100644 efitools/lib/asn1/x509.c - create mode 100644 efitools/lib/configtable.c - create mode 100644 efitools/lib/console.c - create mode 100644 efitools/lib/execute.c - create mode 100644 efitools/lib/guid.c - create mode 100644 efitools/lib/pecoff.c - create mode 100644 efitools/lib/security_policy.c - create mode 100644 efitools/lib/sha256.c - create mode 100644 efitools/lib/shell.c - create mode 100644 efitools/lib/simple_file.c - create mode 100644 efitools/lib/variables.c + MokManager.c | 19 ++++++++----------- + 1 file changed, 8 insertions(+), 11 deletions(-) -diff --git a/Makefile b/Makefile -index 9217ba1..8ca8c51 100644 ---- a/Makefile -+++ b/Makefile -@@ -1,11 +1,13 @@ -+export TOPDIR := $(shell pwd)/ -+ - ARCH = $(shell uname -m | sed s,i[3456789]86,ia32,) +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; + } --SUBDIRS = Cryptlib -+SUBDIRS = Cryptlib efitools +- menu_strings[i] = StrDuplicate(L"Continue boot"); ++ menu_strings[i] = L"Continue boot"; + menu_item[i] = MOK_CONTINUE_BOOT; - LIB_PATH = /usr/lib64 + i++; - EFI_INCLUDE = /usr/include/efi --EFI_INCLUDES = -nostdinc -ICryptlib -ICryptlib/Include -I$(EFI_INCLUDE) -I$(EFI_INCLUDE)/$(ARCH) -I$(EFI_INCLUDE)/protocol -+EFI_INCLUDES = -nostdinc -ICryptlib -ICryptlib/Include -Iefitools/include -I$(EFI_INCLUDE) -I$(EFI_INCLUDE)/$(ARCH) -I$(EFI_INCLUDE)/protocol - EFI_PATH = /usr/lib64 + 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++; + } - LIB_GCC = $(shell $(CC) -print-libgcc-file-name) -@@ -67,7 +69,7 @@ shim.so: $(OBJS) Cryptlib/libcryptlib.a Cryptlib/OpenSSL/libopenssl.a + if (MokDel || MokDelAuth) { +- menu_strings[i] = StrDuplicate(L"Delete MOK"); ++ menu_strings[i] = L"Delete MOK"; + menu_item[i] = MOK_DELETE_MOK; + i++; + } - MokManager.o: $(MOK_SOURCES) + 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++; + } --MokManager.so: $(MOK_OBJS) Cryptlib/libcryptlib.a Cryptlib/OpenSSL/libopenssl.a -+MokManager.so: $(MOK_OBJS) Cryptlib/libcryptlib.a Cryptlib/OpenSSL/libopenssl.a efitools/lib/lib-efi.a - $(LD) -o $@ $(LDFLAGS) $^ $(EFI_LIBS) + if (MokPW) { +- menu_strings[i] = StrDuplicate(L"Set MOK password"); ++ menu_strings[i] = L"Set MOK password"; + menu_item[i] = MOK_SET_PW; + i++; + } - Cryptlib/libcryptlib.a: -@@ -76,6 +78,12 @@ Cryptlib/libcryptlib.a: - Cryptlib/OpenSSL/libopenssl.a: - $(MAKE) -C Cryptlib/OpenSSL +- menu_strings[i] = StrDuplicate(L"Enroll key from disk"); ++ menu_strings[i] = L"Enroll key from disk"; + menu_item[i] = MOK_KEY_ENROLL; + i++; -+efitools/lib/lib-efi.a: -+ $(MAKE) -C efitools/lib -+ -+efitools/lib/asn1/libasn1-efi.a: -+ $(MAKE) -C efitools/lib/asn1 -+ - %.efi: %.so - objcopy -j .text -j .sdata -j .data \ - -j .dynamic -j .dynsym -j .rel \ -@@ -94,6 +102,7 @@ Cryptlib/OpenSSL/libopenssl.a: - clean: - $(MAKE) -C Cryptlib clean - $(MAKE) -C Cryptlib/OpenSSL clean -+ $(MAKE) -C efitools clean - rm -rf $(TARGET) $(OBJS) $(MOK_OBJS) $(KEYS) certdb - rm -f *.debug *.so +- menu_strings[i] = StrDuplicate(L"Enroll hash from disk"); ++ menu_strings[i] = L"Enroll hash from disk"; + menu_item[i] = MOK_HASH_ENROLL; + i++; -diff --git a/efitools/COPYING b/efitools/COPYING -new file mode 100644 -index 0000000..7737e63 ---- /dev/null -+++ b/efitools/COPYING -@@ -0,0 +1,350 @@ -+efitools - useful tools for manipulating UEFI secure boot platforms -+ -+(c) 2012 James Bottomley -+ -+All of these programs are made available under version 2 of the GNU General -+Public Licence. The library routines in lib/ are made available under the GNU -+Lesser General Public Licence version 2.1. Additionally for linking the -+programme files with openSSL, there is an additional permission that -+compiling, linking, and/or using OpenSSL is allowed. -+ -+ GNU GENERAL PUBLIC LICENSE -+ Version 2, June 1991 -+ -+ Copyright (C) 1989, 1991 Free Software Foundation, Inc. -+ 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -+ Everyone is permitted to copy and distribute verbatim copies -+ of this license document, but changing it is not allowed. -+ -+ Preamble -+ -+ The licenses for most software are designed to take away your -+freedom to share and change it. By contrast, the GNU General Public -+License is intended to guarantee your freedom to share and change free -+software--to make sure the software is free for all its users. This -+General Public License applies to most of the Free Software -+Foundation's software and to any other program whose authors commit to -+using it. (Some other Free Software Foundation software is covered by -+the GNU Library General Public License instead.) You can apply it to -+your programs, too. -+ -+ When we speak of free software, we are referring to freedom, not -+price. Our General Public Licenses are designed to make sure that you -+have the freedom to distribute copies of free software (and charge for -+this service if you wish), that you receive source code or can get it -+if you want it, that you can change the software or use pieces of it -+in new free programs; and that you know you can do these things. -+ -+ To protect your rights, we need to make restrictions that forbid -+anyone to deny you these rights or to ask you to surrender the rights. -+These restrictions translate to certain responsibilities for you if you -+distribute copies of the software, or if you modify it. -+ -+ For example, if you distribute copies of such a program, whether -+gratis or for a fee, you must give the recipients all the rights that -+you have. You must make sure that they, too, receive or can get the -+source code. And you must show them these terms so they know their -+rights. -+ -+ We protect your rights with two steps: (1) copyright the software, and -+(2) offer you this license which gives you legal permission to copy, -+distribute and/or modify the software. -+ -+ Also, for each author's protection and ours, we want to make certain -+that everyone understands that there is no warranty for this free -+software. If the software is modified by someone else and passed on, we -+want its recipients to know that what they have is not the original, so -+that any problems introduced by others will not reflect on the original -+authors' reputations. -+ -+ Finally, any free program is threatened constantly by software -+patents. We wish to avoid the danger that redistributors of a free -+program will individually obtain patent licenses, in effect making the -+program proprietary. To prevent this, we have made it clear that any -+patent must be licensed for everyone's free use or not licensed at all. -+ -+ The precise terms and conditions for copying, distribution and -+modification follow. -+ -+ GNU GENERAL PUBLIC LICENSE -+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION -+ -+ 0. This License applies to any program or other work which contains -+a notice placed by the copyright holder saying it may be distributed -+under the terms of this General Public License. The "Program", below, -+refers to any such program or work, and a "work based on the Program" -+means either the Program or any derivative work under copyright law: -+that is to say, a work containing the Program or a portion of it, -+either verbatim or with modifications and/or translated into another -+language. (Hereinafter, translation is included without limitation in -+the term "modification".) Each licensee is addressed as "you". -+ -+Activities other than copying, distribution and modification are not -+covered by this License; they are outside its scope. The act of -+running the Program is not restricted, and the output from the Program -+is covered only if its contents constitute a work based on the -+Program (independent of having been made by running the Program). -+Whether that is true depends on what the Program does. -+ -+ 1. You may copy and distribute verbatim copies of the Program's -+source code as you receive it, in any medium, provided that you -+conspicuously and appropriately publish on each copy an appropriate -+copyright notice and disclaimer of warranty; keep intact all the -+notices that refer to this License and to the absence of any warranty; -+and give any other recipients of the Program a copy of this License -+along with the Program. -+ -+You may charge a fee for the physical act of transferring a copy, and -+you may at your option offer warranty protection in exchange for a fee. -+ -+ 2. You may modify your copy or copies of the Program or any portion -+of it, thus forming a work based on the Program, and copy and -+distribute such modifications or work under the terms of Section 1 -+above, provided that you also meet all of these conditions: -+ -+ a) You must cause the modified files to carry prominent notices -+ stating that you changed the files and the date of any change. -+ -+ b) You must cause any work that you distribute or publish, that in -+ whole or in part contains or is derived from the Program or any -+ part thereof, to be licensed as a whole at no charge to all third -+ parties under the terms of this License. -+ -+ c) If the modified program normally reads commands interactively -+ when run, you must cause it, when started running for such -+ interactive use in the most ordinary way, to print or display an -+ announcement including an appropriate copyright notice and a -+ notice that there is no warranty (or else, saying that you provide -+ a warranty) and that users may redistribute the program under -+ these conditions, and telling the user how to view a copy of this -+ License. (Exception: if the Program itself is interactive but -+ does not normally print such an announcement, your work based on -+ the Program is not required to print an announcement.) -+ -+These requirements apply to the modified work as a whole. If -+identifiable sections of that work are not derived from the Program, -+and can be reasonably considered independent and separate works in -+themselves, then this License, and its terms, do not apply to those -+sections when you distribute them as separate works. But when you -+distribute the same sections as part of a whole which is a work based -+on the Program, the distribution of the whole must be on the terms of -+this License, whose permissions for other licensees extend to the -+entire whole, and thus to each and every part regardless of who wrote it. -+ -+Thus, it is not the intent of this section to claim rights or contest -+your rights to work written entirely by you; rather, the intent is to -+exercise the right to control the distribution of derivative or -+collective works based on the Program. -+ -+In addition, mere aggregation of another work not based on the Program -+with the Program (or with a work based on the Program) on a volume of -+a storage or distribution medium does not bring the other work under -+the scope of this License. -+ -+ 3. You may copy and distribute the Program (or a work based on it, -+under Section 2) in object code or executable form under the terms of -+Sections 1 and 2 above provided that you also do one of the following: -+ -+ a) Accompany it with the complete corresponding machine-readable -+ source code, which must be distributed under the terms of Sections -+ 1 and 2 above on a medium customarily used for software interchange; or, -+ -+ b) Accompany it with a written offer, valid for at least three -+ years, to give any third party, for a charge no more than your -+ cost of physically performing source distribution, a complete -+ machine-readable copy of the corresponding source code, to be -+ distributed under the terms of Sections 1 and 2 above on a medium -+ customarily used for software interchange; or, -+ -+ c) Accompany it with the information you received as to the offer -+ to distribute corresponding source code. (This alternative is -+ allowed only for noncommercial distribution and only if you -+ received the program in object code or executable form with such -+ an offer, in accord with Subsection b above.) -+ -+The source code for a work means the preferred form of the work for -+making modifications to it. For an executable work, complete source -+code means all the source code for all modules it contains, plus any -+associated interface definition files, plus the scripts used to -+control compilation and installation of the executable. However, as a -+special exception, the source code distributed need not include -+anything that is normally distributed (in either source or binary -+form) with the major components (compiler, kernel, and so on) of the -+operating system on which the executable runs, unless that component -+itself accompanies the executable. -+ -+If distribution of executable or object code is made by offering -+access to copy from a designated place, then offering equivalent -+access to copy the source code from the same place counts as -+distribution of the source code, even though third parties are not -+compelled to copy the source along with the object code. -+ -+ 4. You may not copy, modify, sublicense, or distribute the Program -+except as expressly provided under this License. Any attempt -+otherwise to copy, modify, sublicense or distribute the Program is -+void, and will automatically terminate your rights under this License. -+However, parties who have received copies, or rights, from you under -+this License will not have their licenses terminated so long as such -+parties remain in full compliance. -+ -+ 5. You are not required to accept this License, since you have not -+signed it. However, nothing else grants you permission to modify or -+distribute the Program or its derivative works. These actions are -+prohibited by law if you do not accept this License. Therefore, by -+modifying or distributing the Program (or any work based on the -+Program), you indicate your acceptance of this License to do so, and -+all its terms and conditions for copying, distributing or modifying -+the Program or works based on it. -+ -+ 6. Each time you redistribute the Program (or any work based on the -+Program), the recipient automatically receives a license from the -+original licensor to copy, distribute or modify the Program subject to -+these terms and conditions. You may not impose any further -+restrictions on the recipients' exercise of the rights granted herein. -+You are not responsible for enforcing compliance by third parties to -+this License. -+ -+ 7. If, as a consequence of a court judgment or allegation of patent -+infringement or for any other reason (not limited to patent issues), -+conditions are imposed on you (whether by court order, agreement or -+otherwise) that contradict the conditions of this License, they do not -+excuse you from the conditions of this License. If you cannot -+distribute so as to satisfy simultaneously your obligations under this -+License and any other pertinent obligations, then as a consequence you -+may not distribute the Program at all. For example, if a patent -+license would not permit royalty-free redistribution of the Program by -+all those who receive copies directly or indirectly through you, then -+the only way you could satisfy both it and this License would be to -+refrain entirely from distribution of the Program. -+ -+If any portion of this section is held invalid or unenforceable under -+any particular circumstance, the balance of the section is intended to -+apply and the section as a whole is intended to apply in other -+circumstances. -+ -+It is not the purpose of this section to induce you to infringe any -+patents or other property right claims or to contest validity of any -+such claims; this section has the sole purpose of protecting the -+integrity of the free software distribution system, which is -+implemented by public license practices. Many people have made -+generous contributions to the wide range of software distributed -+through that system in reliance on consistent application of that -+system; it is up to the author/donor to decide if he or she is willing -+to distribute software through any other system and a licensee cannot -+impose that choice. -+ -+This section is intended to make thoroughly clear what is believed to -+be a consequence of the rest of this License. -+ -+ 8. If the distribution and/or use of the Program is restricted in -+certain countries either by patents or by copyrighted interfaces, the -+original copyright holder who places the Program under this License -+may add an explicit geographical distribution limitation excluding -+those countries, so that distribution is permitted only in or among -+countries not thus excluded. In such case, this License incorporates -+the limitation as if written in the body of this License. -+ -+ 9. The Free Software Foundation may publish revised and/or new versions -+of the General Public License from time to time. Such new versions will -+be similar in spirit to the present version, but may differ in detail to -+address new problems or concerns. -+ -+Each version is given a distinguishing version number. If the Program -+specifies a version number of this License which applies to it and "any -+later version", you have the option of following the terms and conditions -+either of that version or of any later version published by the Free -+Software Foundation. If the Program does not specify a version number of -+this License, you may choose any version ever published by the Free Software -+Foundation. -+ -+ 10. If you wish to incorporate parts of the Program into other free -+programs whose distribution conditions are different, write to the author -+to ask for permission. For software which is copyrighted by the Free -+Software Foundation, write to the Free Software Foundation; we sometimes -+make exceptions for this. Our decision will be guided by the two goals -+of preserving the free status of all derivatives of our free software and -+of promoting the sharing and reuse of software generally. -+ -+ NO WARRANTY -+ -+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -+REPAIR OR CORRECTION. -+ -+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -+POSSIBILITY OF SUCH DAMAGES. -+ -+ END OF TERMS AND CONDITIONS -+ -+ How to Apply These Terms to Your New Programs -+ -+ If you develop a new program, and you want it to be of the greatest -+possible use to the public, the best way to achieve this is to make it -+free software which everyone can redistribute and change under these terms. -+ -+ To do so, attach the following notices to the program. It is safest -+to attach them to the start of each source file to most effectively -+convey the exclusion of warranty; and each file should have at least -+the "copyright" line and a pointer to where the full notice is found. -+ -+ -+ Copyright (C) -+ -+ This program is free software; you can redistribute it and/or modify -+ it under the terms of the GNU General Public License as published by -+ the Free Software Foundation; either version 2 of the License, or -+ (at your option) any later version. -+ -+ This program is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ GNU General Public License for more details. -+ -+ You should have received a copy of the GNU General Public License -+ along with this program; if not, write to the Free Software -+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -+ -+ -+Also add information on how to contact you by electronic and paper mail. -+ -+If the program is interactive, make it output a short notice like this -+when it starts in an interactive mode: -+ -+ Gnomovision version 69, Copyright (C) year name of author -+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. -+ This is free software, and you are welcome to redistribute it -+ under certain conditions; type `show c' for details. -+ -+The hypothetical commands `show w' and `show c' should show the appropriate -+parts of the General Public License. Of course, the commands you use may -+be called something other than `show w' and `show c'; they could even be -+mouse-clicks or menu items--whatever suits your program. -+ -+You should also get your employer (if you work as a programmer) or your -+school, if any, to sign a "copyright disclaimer" for the program, if -+necessary. Here is a sample; alter the names: -+ -+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program -+ `Gnomovision' (which makes passes at compilers) written by James Hacker. -+ -+ , 1 April 1989 -+ Ty Coon, President of Vice -+ -+This General Public License does not permit incorporating your program into -+proprietary programs. If your program is a subroutine library, you may -+consider it more useful to permit linking proprietary applications with the -+library. If this is what you want to do, use the GNU Library General -+Public License instead of this License. -diff --git a/efitools/Make.rules b/efitools/Make.rules -new file mode 100644 -index 0000000..6ba937e ---- /dev/null -+++ b/efitools/Make.rules -@@ -0,0 +1,24 @@ -+ARCH = $(shell uname -m) -+INCDIR = -I$(TOPDIR)efitools/include/ -I/usr/include/efi -I/usr/include/efi/$(ARCH) -I/usr/include/efi/protocol -+CPPFLAGS = -DCONFIG_$(ARCH) -+CFLAGS = -O2 -fpic -Wall -fshort-wchar -fno-strict-aliasing -fno-merge-constants -mno-red-zone -fno-stack-protector -g -+LDFLAGS = -nostdlib -+LDFLAGS += -T $(LDSCRIPT) -shared -Bsymbolic $(CRTOBJS) -L $(CRTPATH) -+FORMAT = efi-app-$(ARCH) -+OBJCOPY = objcopy -+ -+ifeq ($(ARCH),x86_64) -+ CFLAGS += -DEFI_FUNCTION_WRAPPER -+endif -+ -+%.o: %.c -+ $(CC) $(INCDIR) $(CFLAGS) $(CPPFLAGS) -c $< -o $@ -+ -+%.efi.o: %.c -+ $(CC) $(INCDIR) $(CFLAGS) $(CPPFLAGS) -fno-toplevel-reorder -DBUILD_EFI -c $< -o $@ -+ -+%.efi.s: %.c -+ $(CC) -S $(INCDIR) $(CFLAGS) $(CPPFLAGS) -fno-toplevel-reorder -DBUILD_EFI -c $< -o $@ -+ -+%.a: -+ ar rcv $@ $^ -diff --git a/efitools/Makefile b/efitools/Makefile -new file mode 100644 -index 0000000..45d6f3a ---- /dev/null -+++ b/efitools/Makefile -@@ -0,0 +1,15 @@ -+include Make.rules -+ -+EFITOOL_LIBS=lib/lib-efi.a lib/asn1/libasn1-efi.a -+ -+all: $(EFITOOL_LIBS) -+ -+lib/lib-efi.a: -+ $(MAKE) -C lib $(notdir $@) -+ -+lib/asn1/libasn1-efi.a: -+ $(MAKE) -C lib/asn1 $(notdir $@) -+ -+clean: -+ $(MAKE) -C lib clean -+ $(MAKE) -C lib/asn1 clean -diff --git a/efitools/include/PeImage.h b/efitools/include/PeImage.h -new file mode 100644 -index 0000000..ec13404 ---- /dev/null -+++ b/efitools/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/efitools/include/configtable.h b/efitools/include/configtable.h -new file mode 100644 -index 0000000..fa2b505 ---- /dev/null -+++ b/efitools/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/efitools/include/console.h b/efitools/include/console.h -new file mode 100644 -index 0000000..5ab5d6b ---- /dev/null -+++ b/efitools/include/console.h -@@ -0,0 +1,21 @@ -+EFI_INPUT_KEY -+console_get_keystroke(void); -+int -+console_check_for_keystroke(CHAR16 key); -+void -+console_print_box_at(CHAR16 *str_arr[], int highlight, int start_col, int start_row, int size_cols, int size_rows, int offset, int lines); -+void -+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_reset(void); -+#define NOSEL 0x7fffffff -diff --git a/efitools/include/efiauthenticated.h b/efitools/include/efiauthenticated.h -new file mode 100644 -index 0000000..f7d6bcb ---- /dev/null -+++ b/efitools/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/efitools/include/errors.h b/efitools/include/errors.h -new file mode 100644 -index 0000000..0da4bb5 ---- /dev/null -+++ b/efitools/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/efitools/include/execute.h b/efitools/include/execute.h -new file mode 100644 -index 0000000..9aecbff ---- /dev/null -+++ b/efitools/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/efitools/include/guid.h b/efitools/include/guid.h -new file mode 100644 -index 0000000..17aa6af ---- /dev/null -+++ b/efitools/include/guid.h -@@ -0,0 +1,19 @@ -+#include -+ -+#ifndef BUILD_EFI -+const char *guid_to_str(EFI_GUID *guid); -+int str_to_guid(const char *str, EFI_GUID *guid); -+int compare_guid(EFI_GUID *g1, EFI_GUID *g2); -+#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/efitools/include/kernel_efivars.h b/efitools/include/kernel_efivars.h -new file mode 100644 -index 0000000..1f5dfa0 ---- /dev/null -+++ b/efitools/include/kernel_efivars.h -@@ -0,0 +1,26 @@ -+#include -+#include -+void -+kernel_variable_init(void); -+int -+get_variable(const char *var, EFI_GUID *guid, uint32_t *attributes, -+ uint32_t *size, void *buf); -+int -+get_variable_alloc(const char *var, EFI_GUID *guid, uint32_t *attributes, -+ uint32_t *size, uint8_t **buf); -+int -+variable_is_setupmode(void); -+int -+variable_is_secureboot(void); -+int -+set_variable(const char *var, EFI_GUID *guid, uint32_t attributes, -+ uint32_t size, void *buf); -+int -+set_variable_esl(const char *var, EFI_GUID *guid, uint32_t attributes, -+ uint32_t size, void *buf); -+int -+set_variable_hash(const char *var, EFI_GUID *owner, uint32_t attributes, -+ uint8_t hash[SHA256_DIGEST_SIZE]); -+uint8_t * -+hash_to_esl(EFI_GUID *owner, int *len, -+ uint8_t hash[SHA256_DIGEST_SIZE]); -diff --git a/efitools/include/pecoff.h b/efitools/include/pecoff.h -new file mode 100644 -index 0000000..4265906 ---- /dev/null -+++ b/efitools/include/pecoff.h -@@ -0,0 +1,23 @@ -+#include -+ -+EFI_STATUS -+pecoff_read_header(PE_COFF_LOADER_IMAGE_CONTEXT *context, void *data); -+EFI_STATUS -+pecoff_relocate(PE_COFF_LOADER_IMAGE_CONTEXT *context, void **data); -+EFI_STATUS -+pecoff_image_layout(PE_COFF_LOADER_IMAGE_CONTEXT *context, void **data); -+EFI_STATUS -+pecoff_execute_checked(EFI_HANDLE image, EFI_SYSTEM_TABLE *systab, -+ CHAR16 *name); -+EFI_STATUS -+pecoff_execute_image(EFI_FILE *file, CHAR16 *name, EFI_HANDLE image, -+ EFI_SYSTEM_TABLE *systab); -+ -+static inline void* -+pecoff_image_address(void *image, int size, unsigned int address) -+{ -+ if (address > size) -+ return NULL; -+ -+ return image + address; -+} -diff --git a/efitools/include/security_policy.h b/efitools/include/security_policy.h -new file mode 100644 -index 0000000..a1c1002 ---- /dev/null -+++ b/efitools/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/efitools/include/sha256.h b/efitools/include/sha256.h -new file mode 100644 -index 0000000..07c531d ---- /dev/null -+++ b/efitools/include/sha256.h -@@ -0,0 +1,33 @@ -+#ifndef _SHA256_H -+#define _SHA256_H -+ -+#ifndef uint8 -+#define uint8 unsigned char -+#endif -+ -+#ifndef uint32 -+#define uint32 unsigned long int -+#endif -+ -+#define SHA256_DIGEST_SIZE 32 -+ -+typedef struct -+{ -+ uint32 total[2]; -+ uint32 state[8]; -+ uint8 buffer[64]; -+} -+sha256_context; -+ -+void sha256_starts( sha256_context *ctx ); -+void sha256_update( sha256_context *ctx, uint8 *input, uint32 length ); -+void sha256_finish( sha256_context *ctx, uint8 digest[32] ); -+EFI_STATUS -+sha256_get_pecoff_digest_mem(void *buffer, UINTN DataSize, -+ UINT8 hash[SHA256_DIGEST_SIZE]); -+void -+sha256_StrCat_hash(CHAR16 *str, UINT8 hash[SHA256_DIGEST_SIZE]); -+EFI_STATUS -+sha256_get_pecoff_digest(EFI_HANDLE device, CHAR16 *name, uint8 digest[SHA256_DIGEST_SIZE]); -+#endif /* sha256.h */ -+ -diff --git a/efitools/include/shell.h b/efitools/include/shell.h -new file mode 100644 -index 0000000..9cb5d47 ---- /dev/null -+++ b/efitools/include/shell.h -@@ -0,0 +1,2 @@ -+EFI_STATUS -+argsplit(EFI_HANDLE image, int *argc, CHAR16*** ARGV); -diff --git a/efitools/include/simple_file.h b/efitools/include/simple_file.h -new file mode 100644 -index 0000000..fe4fd97 ---- /dev/null -+++ b/efitools/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/efitools/include/variables.h b/efitools/include/variables.h -new file mode 100644 -index 0000000..f14a320 ---- /dev/null -+++ b/efitools/include/variables.h -@@ -0,0 +1,45 @@ -+#include -+ -+#include /* for SHA256_DIGEST_SIZE */ -+#include -+ -+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/efitools/include/variables_iterators.h b/efitools/include/variables_iterators.h -new file mode 100644 -index 0000000..fc2df0c ---- /dev/null -+++ b/efitools/include/variables_iterators.h -@@ -0,0 +1,16 @@ -+ -+#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)) -+ -diff --git a/efitools/include/version.h b/efitools/include/version.h -new file mode 100644 -index 0000000..897bbc4 ---- /dev/null -+++ b/efitools/include/version.h -@@ -0,0 +1,8 @@ -+#define VERSION "1.4.1" -+ -+static void -+version(const char *progname) -+{ -+ printf("%s " VERSION "\n", progname); -+} -+ -diff --git a/efitools/include/wincert.h b/efitools/include/wincert.h -new file mode 100644 -index 0000000..68d1974 ---- /dev/null -+++ b/efitools/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/efitools/include/x509.h b/efitools/include/x509.h -new file mode 100644 -index 0000000..f072702 ---- /dev/null -+++ b/efitools/include/x509.h -@@ -0,0 +1,23 @@ -+#ifndef STR -+#define STR CHAR16 -+#endif -+ -+#define X509_OBJ_TBS_CERTIFICATE 1 -+#define X509_OBJ_VERSION 3 -+#define X509_OBJ_SERIAL_NUMBER 4 -+#define X509_OBJ_SIG_ALG 5 -+#define X509_OBJ_ISSUER 6 -+#define X509_OBJ_NOT_BEFORE 8 -+#define X509_OBJ_NOT_AFTER 9 -+#define X509_OBJ_SUBJECT 10 -+#define X509_OBJ_SUBJECT_PUBLIC_KEY_INFO 11 -+#define X509_OBJ_OPTIONAL_EXTENSIONS 16 -+#define X509_OBJ_EXTN_ID 19 -+#define X509_OBJ_CRITICAL 20 -+#define X509_OBJ_EXTN_VALUE 21 -+#define X509_OBJ_ALGORITHM 24 -+#define X509_OBJ_SIGNATURE 25 -+ -+int -+x509_to_str(void *cert, int cert_size, int tag, -+ STR *buf, int len); -diff --git a/efitools/lib/Makefile b/efitools/lib/Makefile -new file mode 100644 -index 0000000..6cfe503 ---- /dev/null -+++ b/efitools/lib/Makefile -@@ -0,0 +1,12 @@ -+FILES = simple_file.o pecoff.o guid.o sha256.o console.o \ -+ security_policy.o execute.o configtable.o shell.o -+EFILIBFILES = $(patsubst %.o,%.efi.o,$(FILES)) variables.o -+ -+include ../Make.rules -+ -+lib-efi.a: $(EFILIBFILES) -+ -+clean: -+ rm -f lib-efi.a -+ rm -f $(EFILIBFILES) -+ -diff --git a/efitools/lib/asn1/.gitignore b/efitools/lib/asn1/.gitignore -new file mode 100644 -index 0000000..9daeafb ---- /dev/null -+++ b/efitools/lib/asn1/.gitignore -@@ -0,0 +1 @@ -+test -diff --git a/efitools/lib/asn1/Makefile b/efitools/lib/asn1/Makefile -new file mode 100644 -index 0000000..b683b50 ---- /dev/null -+++ b/efitools/lib/asn1/Makefile -@@ -0,0 +1,11 @@ -+LIBFILES = asn1.o asn1_parser.o enumerator.o chunk.o oid.o identification.o \ -+ x509.o -+EFILIBFILES = $(patsubst %.o,%.efi.o,$(LIBFILES)) -+ -+include ../../Make.rules -+ -+libasn1-efi.a: $(EFILIBFILES) -+ -+clean: -+ rm -f libasn1-efi.a -+ rm -f $(EFILIBFILES) -diff --git a/efitools/lib/asn1/asn1.c b/efitools/lib/asn1/asn1.c -new file mode 100644 -index 0000000..e28f467 ---- /dev/null -+++ b/efitools/lib/asn1/asn1.c -@@ -0,0 +1,197 @@ -+/* -+ * Copyright (C) 2006 Martin Will -+ * Copyright (C) 2000-2008 Andreas Steffen -+ * -+ * Hochschule fuer Technik Rapperswil -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -+ * for more details. -+ */ -+ -+#include "typedefs.h" -+#include "enumerator.h" -+#include "chunk.h" -+#include "oid.h" -+#include "asn1.h" -+#include "asn1_parser.h" -+ -+/* -+ * Defined in header. -+ */ -+int asn1_known_oid(chunk_t object) -+{ -+ int oid = 0; -+ -+ while (object.len) -+ { -+ if (oid_names[oid].octet == *object.ptr) -+ { -+ if (--object.len == 0 || oid_names[oid].down == 0) -+ { -+ return oid; /* found terminal symbol */ -+ } -+ else -+ { -+ object.ptr++; oid++; /* advance to next hex octet */ -+ } -+ } -+ else -+ { -+ if (oid_names[oid].next) -+ { -+ oid = oid_names[oid].next; -+ } -+ else -+ { -+ return OID_UNKNOWN; -+ } -+ } -+ } -+ return -1; -+} -+ -+/* -+ * Defined in header. -+ */ -+chunk_t asn1_build_known_oid(int n) -+{ -+ chunk_t oid; -+ int i; -+ -+ if (n < 0 || n >= OID_MAX) -+ { -+ return chunk_empty; -+ } -+ -+ i = oid_names[n].level + 1; -+ oid = chunk_alloc(2 + i); -+ oid.ptr[0] = ASN1_OID; -+ oid.ptr[1] = i; -+ -+ do -+ { -+ if (oid_names[n].level >= i) -+ { -+ n--; -+ continue; -+ } -+ oid.ptr[--i + 2] = oid_names[n--].octet; -+ } -+ while (i > 0); -+ -+ return oid; -+} -+ -+/* -+ * Defined in header. -+ */ -+size_t asn1_length(chunk_t *blob) -+{ -+ u_char n; -+ size_t len; -+ -+ if (blob->len < 2) -+ { -+ DBG1("insufficient number of octets to parse ASN.1 length"); -+ return ASN1_INVALID_LENGTH; -+ } -+ -+ /* read length field, skip tag and length */ -+ n = blob->ptr[1]; -+ blob->ptr += 2; -+ blob->len -= 2; -+ -+ if ((n & 0x80) == 0) -+ { /* single length octet */ -+ if (n > blob->len) -+ { -+ DBG1("length is larger than remaining blob size"); -+ return ASN1_INVALID_LENGTH; -+ } -+ return n; -+ } -+ -+ /* composite length, determine number of length octets */ -+ n &= 0x7f; -+ -+ if (n == 0 || n > blob->len) -+ { -+ DBG1("number of length octets invalid"); -+ return ASN1_INVALID_LENGTH; -+ } -+ -+ if (n > sizeof(len)) -+ { -+ DBG1("number of length octets is larger than limit of" -+ " %d octets", (int)sizeof(len)); -+ return ASN1_INVALID_LENGTH; -+ } -+ -+ len = 0; -+ -+ while (n-- > 0) -+ { -+ len = 256*len + *blob->ptr++; -+ blob->len--; -+ } -+ if (len > blob->len) -+ { -+ DBG1("length is larger than remaining blob size"); -+ return ASN1_INVALID_LENGTH; -+ } -+ return len; -+} -+ -+/* -+ * See header. -+ */ -+int asn1_unwrap(chunk_t *blob, chunk_t *inner) -+{ -+ chunk_t res; -+ u_char len; -+ int type; -+ -+ if (blob->len < 2) -+ { -+ return ASN1_INVALID; -+ } -+ type = blob->ptr[0]; -+ len = blob->ptr[1]; -+ *blob = chunk_skip(*blob, 2); -+ -+ if ((len & 0x80) == 0) -+ { /* single length octet */ -+ res.len = len; -+ } -+ else -+ { /* composite length, determine number of length octets */ -+ len &= 0x7f; -+ if (len == 0 || len > sizeof(res.len)) -+ { -+ return ASN1_INVALID; -+ } -+ res.len = 0; -+ while (len-- > 0) -+ { -+ res.len = 256 * res.len + blob->ptr[0]; -+ *blob = chunk_skip(*blob, 1); -+ } -+ } -+ if (res.len > blob->len) -+ { -+ return ASN1_INVALID; -+ } -+ res.ptr = blob->ptr; -+ *blob = chunk_skip(*blob, res.len); -+ /* updating inner not before we are finished allows a caller to pass -+ * blob = inner */ -+ *inner = res; -+ return type; -+} -diff --git a/efitools/lib/asn1/asn1.h b/efitools/lib/asn1/asn1.h -new file mode 100644 -index 0000000..97ae9bd ---- /dev/null -+++ b/efitools/lib/asn1/asn1.h -@@ -0,0 +1,115 @@ -+/* -+ * Copyright (C) 2006 Martin Will -+ * Copyright (C) 2000-2008 Andreas Steffen -+ * -+ * Hochschule fuer Technik Rapperswil -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -+ * for more details. -+ */ -+ -+/** -+ * @defgroup asn1i asn1 -+ * @{ @ingroup asn1 -+ */ -+ -+#ifndef ASN1_H_ -+#define ASN1_H_ -+ -+/** -+ * Definition of some primitive ASN1 types -+ */ -+typedef enum { -+ ASN1_EOC = 0x00, -+ ASN1_BOOLEAN = 0x01, -+ ASN1_INTEGER = 0x02, -+ ASN1_BIT_STRING = 0x03, -+ ASN1_OCTET_STRING = 0x04, -+ ASN1_NULL = 0x05, -+ ASN1_OID = 0x06, -+ ASN1_ENUMERATED = 0x0A, -+ ASN1_UTF8STRING = 0x0C, -+ ASN1_NUMERICSTRING = 0x12, -+ ASN1_PRINTABLESTRING = 0x13, -+ ASN1_T61STRING = 0x14, -+ ASN1_VIDEOTEXSTRING = 0x15, -+ ASN1_IA5STRING = 0x16, -+ ASN1_UTCTIME = 0x17, -+ ASN1_GENERALIZEDTIME = 0x18, -+ ASN1_GRAPHICSTRING = 0x19, -+ ASN1_VISIBLESTRING = 0x1A, -+ ASN1_GENERALSTRING = 0x1B, -+ ASN1_UNIVERSALSTRING = 0x1C, -+ ASN1_BMPSTRING = 0x1E, -+ -+ ASN1_CONSTRUCTED = 0x20, -+ -+ ASN1_SEQUENCE = 0x30, -+ ASN1_SET = 0x31, -+ -+ ASN1_CONTEXT_S_0 = 0x80, -+ ASN1_CONTEXT_S_1 = 0x81, -+ ASN1_CONTEXT_S_2 = 0x82, -+ ASN1_CONTEXT_S_3 = 0x83, -+ ASN1_CONTEXT_S_4 = 0x84, -+ ASN1_CONTEXT_S_5 = 0x85, -+ ASN1_CONTEXT_S_6 = 0x86, -+ ASN1_CONTEXT_S_7 = 0x87, -+ ASN1_CONTEXT_S_8 = 0x88, -+ -+ ASN1_CONTEXT_C_0 = 0xA0, -+ ASN1_CONTEXT_C_1 = 0xA1, -+ ASN1_CONTEXT_C_2 = 0xA2, -+ ASN1_CONTEXT_C_3 = 0xA3, -+ ASN1_CONTEXT_C_4 = 0xA4, -+ ASN1_CONTEXT_C_5 = 0xA5, -+ -+ ASN1_INVALID = 0x100, -+} asn1_t; -+ -+#define ASN1_INVALID_LENGTH 0xffffffff -+ -+/** Some ASN.1 analysis functions */ -+ -+/** -+ * Converts an ASN.1 OID into a known OID index -+ * -+ * @param object body of an OID -+ * @return index into the oid_names[] table or OID_UNKNOWN -+ */ -+int asn1_known_oid(chunk_t object); -+ -+/** -+ * Converts a known OID index to an ASN.1 OID -+ * -+ * @param n index into the oid_names[] table -+ * @return allocated OID chunk, chunk_empty if index out of range -+ */ -+chunk_t asn1_build_known_oid(int n); -+ -+/** -+ * Returns the length of an ASN.1 object -+ * The blob pointer is advanced past the tag length fields -+ * -+ * @param blob pointer to an ASN.1 coded blob -+ * @return length of ASN.1 object -+ */ -+size_t asn1_length(chunk_t *blob); -+ -+/** -+ * Unwrap the inner content of an ASN.1 type/length wrapped object. -+ * -+ * @param blob blob to parse header from, moved behind parsed content -+ * @param content inner content -+ * @return parsed type, ASN1_INVALID if length parsing failed -+ */ -+int asn1_unwrap(chunk_t *blob, chunk_t *content); -+ -+#endif /** ASN1_H_ @}*/ -diff --git a/efitools/lib/asn1/asn1_parser.c b/efitools/lib/asn1/asn1_parser.c -new file mode 100644 -index 0000000..ca3626a ---- /dev/null -+++ b/efitools/lib/asn1/asn1_parser.c -@@ -0,0 +1,286 @@ -+/* -+ * Copyright (C) 2006 Martin Will -+ * Copyright (C) 2000-2008 Andreas Steffen -+ * -+ * Hochschule fuer Technik Rapperswil -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -+ * for more details. -+ */ -+ -+#include "typedefs.h" -+#include "chunk.h" -+#include "asn1.h" -+#include "asn1_parser.h" -+ -+#define ASN1_MAX_LEVEL 10 -+ -+typedef struct private_asn1_parser_t private_asn1_parser_t; -+ -+/** -+ * Private data of an asn1_cxt_t object. -+ */ -+struct private_asn1_parser_t { -+ /** -+ * Public interface. -+ */ -+ asn1_parser_t public; -+ -+ /** -+ * Syntax definition of ASN.1 object -+ */ -+ asn1Object_t const *objects; -+ -+ /** -+ * Current syntax definition line -+ */ -+ int line; -+ -+ /** -+ * Current stat of the parsing operation -+ */ -+ bool success; -+ -+ /** -+ * Declare object data as private - use debug level 4 to log it -+ */ -+ bool private; -+ -+ /** -+ * Top-most type is implicit - ignore it -+ */ -+ bool implicit; -+ -+ /** -+ * Top-most parsing level - defaults to 0 -+ */ -+ u_int level0; -+ -+ /** -+ * Jump back address for loops for each level -+ */ -+ int loopAddr[ASN1_MAX_LEVEL + 1]; -+ -+ /** -+ * Current parsing pointer for each level -+ */ -+ chunk_t blobs[ASN1_MAX_LEVEL + 2]; -+}; -+ -+METHOD(asn1_parser_t, iterate, bool, -+ private_asn1_parser_t *this, int *objectID, chunk_t *object) -+{ -+ chunk_t *blob, *blob1; -+ u_char *start_ptr; -+ u_int level; -+ asn1Object_t obj; -+ -+ *object = chunk_empty; -+ -+ /* Advance to the next object syntax definition line */ -+ obj = this->objects[++(this->line)]; -+ -+ /* Terminate if the end of the object syntax definition has been reached */ -+ if (obj.flags & ASN1_EXIT) -+ { -+ return FALSE; -+ } -+ -+ if (obj.flags & ASN1_END) /* end of loop or option found */ -+ { -+ if (this->loopAddr[obj.level] && this->blobs[obj.level+1].len > 0) -+ { -+ this->line = this->loopAddr[obj.level]; /* another iteration */ -+ obj = this->objects[this->line]; -+ } -+ else -+ { -+ this->loopAddr[obj.level] = 0; /* exit loop or option*/ -+ goto end; -+ } -+ } -+ -+ level = this->level0 + obj.level; -+ blob = this->blobs + obj.level; -+ blob1 = blob + 1; -+ start_ptr = blob->ptr; -+ -+ /* handle ASN.1 defaults values */ -+ if ((obj.flags & ASN1_DEF) && (blob->len == 0 || *start_ptr != obj.type) ) -+ { -+ /* field is missing */ -+ DBG1("L%d - %a:", level, obj.name); -+ if (obj.type & ASN1_CONSTRUCTED) -+ { -+ this->line++ ; /* skip context-specific tag */ -+ } -+ goto end; -+ } -+ -+ /* handle ASN.1 options */ -+ -+ if ((obj.flags & ASN1_OPT) -+ && (blob->len == 0 || *start_ptr != obj.type)) -+ { -+ /* advance to end of missing option field */ -+ do -+ { -+ this->line++; -+ } -+ while (!((this->objects[this->line].flags & ASN1_END) && -+ (this->objects[this->line].level == obj.level))); -+ goto end; -+ } -+ -+ /* an ASN.1 object must possess at least a tag and length field */ -+ -+ if (blob->len < 2) -+ { -+ DBG1("L%d - %a: ASN.1 object smaller than 2 octets", -+ level, obj.name); -+ this->success = FALSE; -+ goto end; -+ } -+ -+ blob1->len = asn1_length(blob); -+ -+ if (blob1->len == ASN1_INVALID_LENGTH) -+ { -+ DBG1("L%d - %a: length of ASN.1 object invalid or too large", -+ level, obj.name); -+ this->success = FALSE; -+ } -+ -+ blob1->ptr = blob->ptr; -+ blob->ptr += blob1->len; -+ blob->len -= blob1->len; -+ -+ /* return raw ASN.1 object without prior type checking */ -+ -+ if (obj.flags & ASN1_RAW) -+ { -+ DBG1("L%d - %a:", level, obj.name); -+ object->ptr = start_ptr; -+ object->len = (size_t)(blob->ptr - start_ptr); -+ goto end; -+ } -+ -+ if (*start_ptr != obj.type && !(this->implicit && this->line == 0)) -+ { -+ DBG1("L%d - %a: ASN1 tag 0x%02x expected, but is 0x%02x", -+ level, obj.name, obj.type, *start_ptr); -+ DBG1("%b", start_ptr, (u_int)(blob->ptr - start_ptr)); -+ this->success = FALSE; -+ goto end; -+ } -+ -+ DBG1("L%d - %a:", level, obj.name); -+ -+ /* In case of "SEQUENCE OF" or "SET OF" start a loop */ -+ if (obj.flags & ASN1_LOOP) -+ { -+ if (blob1->len > 0) -+ { -+ /* at least one item, start the loop */ -+ this->loopAddr[obj.level] = this->line + 1; -+ } -+ else -+ { -+ /* no items, advance directly to end of loop */ -+ do -+ { -+ this->line++; -+ } -+ while (!((this->objects[this->line].flags & ASN1_END) && -+ (this->objects[this->line].level == obj.level))); -+ goto end; -+ } -+ } -+ -+ if (obj.flags & ASN1_OBJ) -+ { -+ object->ptr = start_ptr; -+ object->len = (size_t)(blob->ptr - start_ptr); -+ if (this->private) -+ { -+ DBG1("%B", object); -+ } -+ else -+ { -+ DBG1("%B", object); -+ } -+ } -+ else if (obj.flags & ASN1_BODY) -+ { -+ *object = *blob1; -+ } -+ -+end: -+ *objectID = this->line; -+ return this->success; -+} -+ -+METHOD(asn1_parser_t, get_level, u_int, -+private_asn1_parser_t *this) -+{ -+ return this->level0 + this->objects[this->line].level; -+} -+ -+METHOD(asn1_parser_t, set_top_level, void, -+ private_asn1_parser_t *this, u_int level0) -+{ -+ this->level0 = level0; -+} -+ -+METHOD(asn1_parser_t, set_flags, void, -+ private_asn1_parser_t *this, bool implicit, bool private) -+{ -+ this->implicit = implicit; -+ this->private = private; -+} -+ -+METHOD(asn1_parser_t, success, bool, -+ private_asn1_parser_t *this) -+{ -+ return this->success; -+} -+ -+METHOD(asn1_parser_t, destroy, void, -+ private_asn1_parser_t *this) -+{ -+ free(this); -+} -+ -+/** -+ * Defined in header. -+ */ -+asn1_parser_t* asn1_parser_create(asn1Object_t const *objects, chunk_t blob) -+{ -+ private_asn1_parser_t *this; -+ -+ this = malloc(sizeof(*this)); -+ -+ *this = (private_asn1_parser_t) { -+ .public = { -+ .iterate = _iterate, -+ .get_level = _get_level, -+ .set_top_level = _set_top_level, -+ .set_flags = _set_flags, -+ .success = _success, -+ .destroy = _destroy, -+ }, -+ .objects = objects, -+ .blobs[0] = blob, -+ .line = -1, -+ .success = TRUE, -+ }; -+ -+ return &this->public; -+} -diff --git a/efitools/lib/asn1/asn1_parser.h b/efitools/lib/asn1/asn1_parser.h -new file mode 100644 -index 0000000..4b5320f ---- /dev/null -+++ b/efitools/lib/asn1/asn1_parser.h -@@ -0,0 +1,117 @@ -+/* -+ * Copyright (C) 2006 Martin Will -+ * Copyright (C) 2000-2008 Andreas Steffen -+ * -+ * Hochschule fuer Technik Rapperswil -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -+ * for more details. -+ */ -+ -+/** -+ * @defgroup asn1_parser asn1_parser -+ * @{ @ingroup asn1 -+ */ -+ -+#ifndef ASN1_PARSER_H_ -+#define ASN1_PARSER_H_ -+ -+#include -+ -+#include "asn1.h" -+ -+/** -+ * Definition of ASN.1 flags -+ */ -+#define ASN1_NONE 0x00 -+#define ASN1_DEF 0x01 -+#define ASN1_OPT 0x02 -+#define ASN1_LOOP 0x04 -+#define ASN1_END 0x08 -+#define ASN1_OBJ 0x10 -+#define ASN1_BODY 0x20 -+#define ASN1_RAW 0x40 -+#define ASN1_EXIT 0x80 -+ -+typedef struct asn1Object_t asn1Object_t; -+ -+/** -+ * Syntax definition of an ASN.1 object -+ */ -+struct asn1Object_t{ -+ u_int level; -+ const u_char *name; -+ asn1_t type; -+ u_char flags; -+}; -+ -+typedef struct asn1_parser_t asn1_parser_t; -+ -+/** -+ * Public interface of an ASN.1 parser -+ */ -+struct asn1_parser_t { -+ -+ /** -+ * Parse the next ASN.1 object in the hierarchy and return it -+ * -+ * @param objectID current line in the object syntax definition -+ * @param object current object -+ * @return - FALSE if end of object syntax definition was reached -+ * or a parsing error occurred -+ * - TRUE otherwise -+ */ -+ bool (*iterate)(asn1_parser_t *this, int *objectID, chunk_t *object); -+ -+ /** -+ * Get the current parsing level -+ * -+ * @return current level -+ */ -+ u_int (*get_level)(asn1_parser_t *this); -+ -+ /** -+ * Set the top-most level -+ * -+ * @param level top-most level -+ */ -+ void (*set_top_level)(asn1_parser_t *this, u_int level0); -+ -+ /** -+ * Set implicit and private flags -+ * -+ * @param implicit top-most type of object is implicit -+ * @param private object data is private (use debug level 4) -+ */ -+ void (*set_flags)(asn1_parser_t *this, bool implicit, bool private); -+ -+ /** -+ * Show final parsing status -+ * -+ * @return TRUE if parsing was successful, FALSE otherwise -+ */ -+ bool (*success)(asn1_parser_t *this); -+ -+ /** -+ * Destroy the ASN.1 parser -+ */ -+ void (*destroy)(asn1_parser_t *this); -+}; -+ -+/** -+ * Create an ASN.1 parser -+ * -+ * @param objects syntax definition of the ASN.1 object to be parsed -+ * @param blob ASN.1 coded binary blob -+ * @return ASN.1 context -+ */ -+asn1_parser_t* asn1_parser_create(asn1Object_t const *objects, chunk_t blob); -+ -+#endif /** ASN1_PARSER_H_ @}*/ -diff --git a/efitools/lib/asn1/chunk.c b/efitools/lib/asn1/chunk.c -new file mode 100644 -index 0000000..38baf07 ---- /dev/null -+++ b/efitools/lib/asn1/chunk.c -@@ -0,0 +1,83 @@ -+/* -+ * Copyright (C) 2008-2009 Tobias Brunner -+ * Copyright (C) 2005-2006 Martin Willi -+ * Copyright (C) 2005 Jan Hutter -+ * Hochschule fuer Technik Rapperswil -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -+ * for more details. -+ */ -+ -+#include "typedefs.h" -+#include "chunk.h" -+ -+/** -+ * Empty chunk. -+ */ -+chunk_t chunk_empty = { NULL, 0 }; -+ -+ /** -+ * Described in header. -+ */ -+chunk_t chunk_create_clone(u_char *ptr, chunk_t chunk) -+{ -+ chunk_t clone = chunk_empty; -+ -+ if (chunk.ptr && chunk.len > 0) -+ { -+ clone.ptr = ptr; -+ clone.len = chunk.len; -+ memcpy(clone.ptr, chunk.ptr, chunk.len); -+ } -+ -+ return clone; -+} -+ -+/** -+ * Described in header. -+ */ -+int chunk_compare(chunk_t a, chunk_t b) -+{ -+ int compare_len = a.len - b.len; -+ int len = (compare_len < 0)? a.len : b.len; -+ -+ if (compare_len != 0 || len == 0) -+ { -+ return compare_len; -+ } -+ return memcmp(a.ptr, b.ptr, len); -+}; -+ -+ -+/** -+ * Remove non-printable characters from a chunk. -+ */ -+bool chunk_printable(chunk_t chunk, chunk_t *sane, char replace) -+{ -+ bool printable = TRUE; -+ int i; -+ -+ if (sane) -+ { -+ *sane = chunk_clone(chunk); -+ } -+ for (i = 0; i < chunk.len; i++) -+ { -+ if (!isprint(chunk.ptr[i])) -+ { -+ if (sane) -+ { -+ sane->ptr[i] = replace; -+ } -+ printable = FALSE; -+ } -+ } -+ return printable; -+} -diff --git a/efitools/lib/asn1/chunk.h b/efitools/lib/asn1/chunk.h -new file mode 100644 -index 0000000..c375e79 ---- /dev/null -+++ b/efitools/lib/asn1/chunk.h -@@ -0,0 +1,164 @@ -+/* -+ * Copyright (C) 2008-2009 Tobias Brunner -+ * Copyright (C) 2005-2008 Martin Willi -+ * Copyright (C) 2005 Jan Hutter -+ * Hochschule fuer Technik Rapperswil -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -+ * for more details. -+ */ -+ -+/** -+ * @defgroup chunk chunk -+ * @{ @ingroup libstrongswan -+ */ -+ -+#ifndef CHUNK_H_ -+#define CHUNK_H_ -+ -+typedef struct chunk_t chunk_t; -+ -+/** -+ * General purpose pointer/length abstraction. -+ */ -+struct chunk_t { -+ /** Pointer to start of data */ -+ u_char *ptr; -+ /** Length of data in bytes */ -+ size_t len; -+}; -+ -+/** -+ * A { NULL, 0 }-chunk handy for initialization. -+ */ -+extern chunk_t chunk_empty; -+ -+/** -+ * Create a new chunk pointing to "ptr" with length "len" -+ */ -+static inline chunk_t chunk_create(u_char *ptr, size_t len) -+{ -+ chunk_t chunk = {ptr, len}; -+ return chunk; -+} -+ -+/** -+ * Free contents of a chunk -+ */ -+static inline void chunk_free(chunk_t *chunk) -+{ -+ free(chunk->ptr); -+ *chunk = chunk_empty; -+} -+ -+/** -+ * Overwrite the contents of a chunk and free it -+ */ -+static inline void chunk_clear(chunk_t *chunk) -+{ -+ if (chunk->ptr) -+ { -+ memset(chunk->ptr, 0, chunk->len); -+ chunk_free(chunk); -+ } -+} -+ -+/** -+ * Initialize a chunk using a char array -+ */ -+#define chunk_from_chars(...) ((chunk_t){(char[]){__VA_ARGS__}, sizeof((char[]){__VA_ARGS__})}) -+ -+/** -+ * Initialize a chunk to point to a thing -+ */ -+#define chunk_from_thing(thing) chunk_create((char*)&(thing), sizeof(thing)) -+ -+/** -+ * Allocate a chunk on the heap -+ */ -+#define chunk_alloc(bytes) ({size_t x = (bytes); chunk_create(x ? malloc(x) : NULL, x);}) -+ -+/** -+ * Allocate a chunk on the stack -+ */ -+#define chunk_alloca(bytes) ({size_t x = (bytes); chunk_create(x ? alloca(x) : NULL, x);}) -+ -+/** -+ * Clone a chunk on heap -+ */ -+#define chunk_clone(chunk) ({chunk_t x = (chunk); chunk_create_clone(x.len ? malloc(x.len) : NULL, x);}) -+ -+/** -+ * Skip n bytes in chunk (forward pointer, shorten length) -+ */ -+static inline chunk_t chunk_skip(chunk_t chunk, size_t bytes) -+{ -+ if (chunk.len > bytes) -+ { -+ chunk.ptr += bytes; -+ chunk.len -= bytes; -+ return chunk; -+ } -+ return chunk_empty; -+} -+ -+/** -+ * Skip a leading zero-valued byte -+ */ -+static inline chunk_t chunk_skip_zero(chunk_t chunk) -+{ -+ if (chunk.len > 1 && *chunk.ptr == 0x00) -+ { -+ chunk.ptr++; -+ chunk.len--; -+ } -+ return chunk; -+} -+ -+ -+/** -+ * Compare two chunks, returns zero if a equals b -+ * or negative/positive if a is small/greater than b -+ */ -+int chunk_compare(chunk_t a, chunk_t b); -+ -+/** -+ * Compare two chunks for equality, -+ * NULL chunks are never equal. -+ */ -+static inline bool chunk_equals(chunk_t a, chunk_t b) -+{ -+ return a.ptr != NULL && b.ptr != NULL && -+ a.len == b.len && memeq(a.ptr, b.ptr, a.len); -+} -+ -+/** -+ * Compare two chunks (given as pointers) for equality (useful as callback), -+ * NULL chunks are never equal. -+ */ -+static inline bool chunk_equals_ptr(chunk_t *a, chunk_t *b) -+{ -+ return a != NULL && b != NULL && chunk_equals(*a, *b); -+} -+ -+/** -+ * Check if a chunk has printable characters only. -+ * -+ * If sane is given, chunk is cloned into sane and all non printable characters -+ * get replaced by "replace". -+ * -+ * @param chunk chunk to check for printability -+ * @param sane pointer where sane version is allocated, or NULL -+ * @param replace character to use for replaceing unprintable characters -+ * @return TRUE if all characters in chunk are printable -+ */ -+bool chunk_printable(chunk_t chunk, chunk_t *sane, char replace); -+ -+#endif -diff --git a/efitools/lib/asn1/enumerator.c b/efitools/lib/asn1/enumerator.c -new file mode 100644 -index 0000000..ac716db ---- /dev/null -+++ b/efitools/lib/asn1/enumerator.c -@@ -0,0 +1,37 @@ -+/* -+ * Copyright (C) 2008 Tobias Brunner -+ * Copyright (C) 2007 Martin Willi -+ * Hochschule fuer Technik Rapperswil -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -+ * for more details. -+ */ -+ -+#include "typedefs.h" -+#include "enumerator.h" -+ -+/** -+ * Implementation of enumerator_create_empty().enumerate -+ */ -+static bool enumerate_empty(enumerator_t *enumerator, ...) -+{ -+ return FALSE; -+} -+ -+/** -+ * See header -+ */ -+enumerator_t* enumerator_create_empty(void) -+{ -+ enumerator_t *this = malloc_thing(enumerator_t); -+ this->enumerate = enumerate_empty; -+ this->destroy = (void*)free; -+ return this; -+} -diff --git a/efitools/lib/asn1/enumerator.h b/efitools/lib/asn1/enumerator.h -new file mode 100644 -index 0000000..a09edec ---- /dev/null -+++ b/efitools/lib/asn1/enumerator.h -@@ -0,0 +1,55 @@ -+/* -+ * Copyright (C) 2007 Martin Willi -+ * Hochschule fuer Technik Rapperswil -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -+ * for more details. -+ */ -+ -+/** -+ * @defgroup enumerator enumerator -+ * @{ @ingroup utils -+ */ -+ -+#ifndef ENUMERATOR_H_ -+#define ENUMERATOR_H_ -+ -+typedef struct enumerator_t enumerator_t; -+ -+/** -+ * Enumerator interface, allows enumeration over collections. -+ */ -+struct enumerator_t { -+ -+ /** -+ * Enumerate collection. -+ * -+ * The enumerate function takes a variable argument list containing -+ * pointers where the enumerated values get written. -+ * -+ * @param ... variable list of enumerated items, implementation dependent -+ * @return TRUE if pointers returned -+ */ -+ bool (*enumerate)(enumerator_t *this, ...); -+ -+ /** -+ * Destroy a enumerator instance. -+ */ -+ void (*destroy)(enumerator_t *this); -+}; -+ -+/** -+ * Create an enumerator which enumerates over nothing -+ * -+ * @return an enumerator over no values -+ */ -+enumerator_t* enumerator_create_empty(); -+ -+#endif /** ENUMERATOR_H_ @}*/ -diff --git a/efitools/lib/asn1/identification.c b/efitools/lib/asn1/identification.c -new file mode 100644 -index 0000000..73cc96b ---- /dev/null -+++ b/efitools/lib/asn1/identification.c -@@ -0,0 +1,226 @@ -+/* -+ * Copyright (C) 2009-2012 Tobias Brunner -+ * Copyright (C) 2005-2009 Martin Willi -+ * Copyright (C) 2005 Jan Hutter -+ * Hochschule fuer Technik Rapperswil -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -+ * for more details. -+ */ -+ -+#include "typedefs.h" -+#include "identification.h" -+ -+#include "oid.h" -+#include "asn1.h" -+ -+/** -+ * coding of X.501 distinguished name -+ */ -+typedef struct { -+ const u_char *name; -+ int oid; -+ u_char type; -+} x501rdn_t; -+ -+static const x501rdn_t x501rdns[] = { -+ {"ND", OID_NAME_DISTINGUISHER, ASN1_PRINTABLESTRING}, -+ {"UID", OID_PILOT_USERID, ASN1_PRINTABLESTRING}, -+ {"DC", OID_PILOT_DOMAIN_COMPONENT, ASN1_PRINTABLESTRING}, -+ {"CN", OID_COMMON_NAME, ASN1_PRINTABLESTRING}, -+ {"S", OID_SURNAME, ASN1_PRINTABLESTRING}, -+ {"SN", OID_SERIAL_NUMBER, ASN1_PRINTABLESTRING}, -+ {"serialNumber", OID_SERIAL_NUMBER, ASN1_PRINTABLESTRING}, -+ {"C", OID_COUNTRY, ASN1_PRINTABLESTRING}, -+ {"L", OID_LOCALITY, ASN1_PRINTABLESTRING}, -+ {"ST", OID_STATE_OR_PROVINCE, ASN1_PRINTABLESTRING}, -+ {"O", OID_ORGANIZATION, ASN1_PRINTABLESTRING}, -+ {"OU", OID_ORGANIZATION_UNIT, ASN1_PRINTABLESTRING}, -+ {"T", OID_TITLE, ASN1_PRINTABLESTRING}, -+ {"D", OID_DESCRIPTION, ASN1_PRINTABLESTRING}, -+ {"N", OID_NAME, ASN1_PRINTABLESTRING}, -+ {"G", OID_GIVEN_NAME, ASN1_PRINTABLESTRING}, -+ {"I", OID_INITIALS, ASN1_PRINTABLESTRING}, -+ {"dnQualifier", OID_DN_QUALIFIER, ASN1_PRINTABLESTRING}, -+ {"ID", OID_UNIQUE_IDENTIFIER, ASN1_PRINTABLESTRING}, -+ {"EN", OID_EMPLOYEE_NUMBER, ASN1_PRINTABLESTRING}, -+ {"employeeNumber", OID_EMPLOYEE_NUMBER, ASN1_PRINTABLESTRING}, -+ {"E", OID_EMAIL_ADDRESS, ASN1_IA5STRING}, -+ {"Email", OID_EMAIL_ADDRESS, ASN1_IA5STRING}, -+ {"emailAddress", OID_EMAIL_ADDRESS, ASN1_IA5STRING}, -+ {"UN", OID_UNSTRUCTURED_NAME, ASN1_IA5STRING}, -+ {"unstructuredName", OID_UNSTRUCTURED_NAME, ASN1_IA5STRING}, -+ {"UA", OID_UNSTRUCTURED_ADDRESS, ASN1_PRINTABLESTRING}, -+ {"unstructuredAddress", OID_UNSTRUCTURED_ADDRESS, ASN1_PRINTABLESTRING}, -+ {"TCGID", OID_TCGID, ASN1_PRINTABLESTRING} -+}; -+ -+/** -+ * maximum number of RDNs in atodn() -+ */ -+#define RDN_MAX 20 -+ -+ -+typedef struct private_identification_t private_identification_t; -+ -+/** -+ * Private data of an identification_t object. -+ */ -+struct private_identification_t { -+ /** -+ * Public interface. -+ */ -+ identification_t public; -+ -+ /** -+ * Encoded representation of this ID. -+ */ -+ chunk_t encoded; -+ -+ /** -+ * Type of this ID. -+ */ -+ id_type_t type; -+}; -+ -+/** -+ * Enumerator over RDNs -+ */ -+typedef struct { -+ /* implements enumerator interface */ -+ enumerator_t public; -+ /* next set to parse, if any */ -+ chunk_t sets; -+ /* next sequence in set, if any */ -+ chunk_t seqs; -+} rdn_enumerator_t; -+ -+METHOD(enumerator_t, rdn_enumerate, bool, -+ rdn_enumerator_t *this, chunk_t *oid, u_char *type, chunk_t *data) -+{ -+ chunk_t rdn; -+ -+ /* a DN contains one or more SET, each containing one or more SEQUENCES, -+ * each containing a OID/value RDN */ -+ if (!this->seqs.len) -+ { -+ /* no SEQUENCEs in current SET, parse next SET */ -+ if (asn1_unwrap(&this->sets, &this->seqs) != ASN1_SET) -+ { -+ return FALSE; -+ } -+ } -+ if (asn1_unwrap(&this->seqs, &rdn) == ASN1_SEQUENCE && -+ asn1_unwrap(&rdn, oid) == ASN1_OID) -+ { -+ int t = asn1_unwrap(&rdn, data); -+ -+ if (t != ASN1_INVALID) -+ { -+ *type = t; -+ return TRUE; -+ } -+ } -+ return FALSE; -+} -+ -+/** -+ * Create an enumerator over all RDNs (oid, string type, data) of a DN -+ */ -+static enumerator_t* create_rdn_enumerator(chunk_t dn) -+{ -+ rdn_enumerator_t *e; -+ -+ INIT(e, -+ .public = { -+ .enumerate = (void*)_rdn_enumerate, -+ .destroy = (void*)free, -+ }, -+ ); -+ -+ /* a DN is a SEQUENCE, get the first SET of it */ -+ if (asn1_unwrap(&dn, &e->sets) == ASN1_SEQUENCE) -+ { -+ e->seqs = chunk_empty; -+ return &e->public; -+ } -+ free(e); -+ return enumerator_create_empty(); -+} -+ -+/** -+ * Print a DN with all its RDN in a buffer to present it to the user -+ */ -+void dntoa(chunk_t dn, STR *buf, size_t len) -+{ -+ enumerator_t *e; -+ chunk_t oid_data, data, printable; -+ u_char type; -+ int oid, written; -+ bool finished = FALSE, empty = TRUE; -+ -+ e = create_rdn_enumerator(dn); -+ while (e->enumerate(e, &oid_data, &type, &data)) -+ { -+ empty = FALSE; -+ -+ oid = asn1_known_oid(oid_data); -+ -+ if (oid == OID_UNKNOWN) -+ { -+ written = snprintf(buf, len, "UNKNOWN-OID="); -+ } -+ else -+ { -+ written = snprintf(buf, len,"%" STRA "=", oid_names[oid].name); -+ } -+ if (written < 0 || written >= len) -+ { -+ break; -+ } -+ buf += written; -+ len -= written; -+ -+ chunk_printable(data, &printable, '?'); -+ written = snprintf(buf, len, "%.*" STRA, (int)printable.len, printable.ptr); -+ chunk_free(&printable); -+ if (written < 0 || written >= len) -+ { -+ break; -+ } -+ buf += written; -+ len -= written; -+ -+ if (data.ptr + data.len != dn.ptr + dn.len) -+ { -+ written = snprintf(buf, len, ", "); -+ if (written < 0 || written >= len) -+ { -+ break; -+ } -+ buf += written; -+ len -= written; -+ } -+ else -+ { -+ finished = TRUE; -+ break; -+ } -+ } -+ if (empty) -+ { -+ snprintf(buf, len, ""); -+ } -+ else if (!finished) -+ { -+ snprintf(buf, len, "(invalid ID_DER_ASN1_DN)"); -+ } -+ e->destroy(e); -+} -diff --git a/efitools/lib/asn1/identification.h b/efitools/lib/asn1/identification.h -new file mode 100644 -index 0000000..8231a63 ---- /dev/null -+++ b/efitools/lib/asn1/identification.h -@@ -0,0 +1,285 @@ -+/* -+ * Copyright (C) 2009 Tobias Brunner -+ * Copyright (C) 2005-2009 Martin Willi -+ * Copyright (C) 2005 Jan Hutter -+ * Hochschule fuer Technik Rapperswil -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the -+ * Free Software Foundation; either version 2 of the License, or (at your -+ * option) any later version. See . -+ * -+ * This program is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -+ * for more details. -+ */ -+ -+/** -+ * @defgroup identification identification -+ * @{ @ingroup utils -+ */ -+ -+ -+#ifndef IDENTIFICATION_H_ -+#define IDENTIFICATION_H_ -+ -+typedef enum id_type_t id_type_t; -+typedef struct identification_t identification_t; -+typedef enum id_match_t id_match_t; -+typedef enum id_part_t id_part_t; -+ -+#include "chunk.h" -+#include "enumerator.h" -+ -+/** -+ * Matches returned from identification_t.match -+ */ -+enum id_match_t { -+ /* no match */ -+ ID_MATCH_NONE = 0, -+ /* match to %any ID */ -+ ID_MATCH_ANY = 1, -+ /* match with maximum allowed wildcards */ -+ ID_MATCH_MAX_WILDCARDS = 2, -+ /* match with only one wildcard */ -+ ID_MATCH_ONE_WILDCARD = 19, -+ /* perfect match, won't get better */ -+ ID_MATCH_PERFECT = 20, -+}; -+ -+/** -+ * ID Types in a ID payload. -+ */ -+enum id_type_t { -+ -+ /** -+ * private type which matches any other id. -+ */ -+ ID_ANY = 0, -+ -+ /** -+ * ID data is a single four (4) octet IPv4 address. -+ */ -+ ID_IPV4_ADDR = 1, -+ -+ /** -+ * ID data is a fully-qualified domain name string. -+ * An example of a ID_FQDN is "example.com". -+ * The string MUST not contain any terminators (e.g., NULL, CR, etc.). -+ */ -+ ID_FQDN = 2, -+ -+ /** -+ * ID data is a fully-qualified RFC822 email address string. -+ * An example of an ID_RFC822_ADDR is "jsmith@example.com". -+ * The string MUST NOT contain any terminators. -+ */ -+ ID_USER_FQDN = 3, /* IKEv1 only */ -+ ID_RFC822_ADDR = 3, /* IKEv2 only */ -+ -+ /** -+ * ID data is an IPv4 subnet (IKEv1 only) -+ */ -+ ID_IPV4_ADDR_SUBNET = 4, -+ -+ /** -+ * ID data is a single sixteen (16) octet IPv6 address. -+ */ -+ ID_IPV6_ADDR = 5, -+ -+ /** -+ * ID data is an IPv6 subnet (IKEv1 only) -+ */ -+ ID_IPV6_ADDR_SUBNET = 6, -+ -+ /** -+ * ID data is an IPv4 address range (IKEv1 only) -+ */ -+ ID_IPV4_ADDR_RANGE = 7, -+ -+ /** -+ * ID data is an IPv6 address range (IKEv1 only) -+ */ -+ ID_IPV6_ADDR_RANGE = 8, -+ -+ /** -+ * ID data is the binary DER encoding of an ASN.1 X.501 Distinguished Name -+ */ -+ ID_DER_ASN1_DN = 9, -+ -+ /** -+ * ID data is the binary DER encoding of an ASN.1 X.509 GeneralName -+ */ -+ ID_DER_ASN1_GN = 10, -+ -+ /** -+ * ID data is an opaque octet stream which may be used to pass vendor- -+ * specific information necessary to do certain proprietary -+ * types of identification. -+ */ -+ ID_KEY_ID = 11, -+ -+ /** -+ * private type which represents a GeneralName of type URI -+ */ -+ ID_DER_ASN1_GN_URI = 201, -+ -+ /** -+ * Private ID used by the pluto daemon for opportunistic encryption -+ */ -+ ID_MYID = 203, -+}; -+ -+/** -+ * Type of an ID sub part. -+ */ -+enum id_part_t { -+ /** Username part of an RFC822_ADDR */ -+ ID_PART_USERNAME, -+ /** Domain part of an RFC822_ADDR */ -+ ID_PART_DOMAIN, -+ -+ /** Top-Level domain of a FQDN */ -+ ID_PART_TLD, -+ /** Second-Level domain of a FQDN */ -+ ID_PART_SLD, -+ /** Another Level domain of a FQDN */ -+ ID_PART_ALD, -+ -+ /** Country RDN of a DN */ -+ ID_PART_RDN_C, -+ /** CommonName RDN of a DN */ -+ ID_PART_RDN_CN, -+ /** Description RDN of a DN */ -+ ID_PART_RDN_D, -+ /** Email RDN of a DN */ -+ ID_PART_RDN_E, -+ /** EmployeeNumber RDN of a DN */ -+ ID_PART_RDN_EN, -+ /** GivenName RDN of a DN */ -+ ID_PART_RDN_G, -+ /** Initials RDN of a DN */ -+ ID_PART_RDN_I, -+ /** DN Qualifier RDN of a DN */ -+ ID_PART_RDN_DNQ, -+ /** UniqueIdentifier RDN of a DN */ -+ ID_PART_RDN_ID, -+ /** Locality RDN of a DN */ -+ ID_PART_RDN_L, -+ /** Name RDN of a DN */ -+ ID_PART_RDN_N, -+ /** Organization RDN of a DN */ -+ ID_PART_RDN_O, -+ /** OrganizationUnit RDN of a DN */ -+ ID_PART_RDN_OU, -+ /** Surname RDN of a DN */ -+ ID_PART_RDN_S, -+ /** SerialNumber RDN of a DN */ -+ ID_PART_RDN_SN, -+ /** StateOrProvince RDN of a DN */ -+ ID_PART_RDN_ST, -+ /** Title RDN of a DN */ -+ ID_PART_RDN_T, -+}; -+ -+/** -+ * Generic identification, such as used in ID payload. -+ * -+ * @todo Support for ID_DER_ASN1_GN is minimal right now. Comparison -+ * between them and ID_IPV4_ADDR/RFC822_ADDR would be nice. -+ */ -+struct identification_t { -+ -+ /** -+ * Get the encoding of this id, to send over -+ * the network. -+ * -+ * Result points to internal data, do not free. -+ * -+ * @return a chunk containing the encoded bytes -+ */ -+ chunk_t (*get_encoding) (identification_t *this); -+ -+ /** -+ * Get the type of this identification. -+ * -+ * @return id_type_t -+ */ -+ id_type_t (*get_type) (identification_t *this); -+ -+ /** -+ * Check if two identification_t objects are equal. -+ * -+ * @param other other identification_t object -+ * @return TRUE if the IDs are equal -+ */ -+ bool (*equals) (identification_t *this, identification_t *other); -+ -+ /** -+ * Check if an ID matches a wildcard ID. -+ * -+ * An identification_t may contain wildcards, such as -+ * *.strongswan.org. This call checks if a given ID -+ * (e.g. tester.strongswan.org) belongs to a such wildcard -+ * ID. Returns > 0 if -+ * - IDs are identical -+ * - other is of type ID_ANY -+ * - other contains a wildcard and matches this -+ * -+ * The larger the return value is, the better is the match. Zero means -+ * no match at all, 1 means a bad match, and 2 a slightly better match. -+ * -+ * @param other the ID containing one or more wildcards -+ * @param wildcards returns the number of wildcards, may be NULL -+ * @return match value as described above -+ */ -+ id_match_t (*matches) (identification_t *this, identification_t *other); -+ -+ /** -+ * Check if an ID is a wildcard ID. -+ * -+ * If the ID represents multiple IDs (with wildcards, or -+ * as the type ID_ANY), TRUE is returned. If it is unique, -+ * FALSE is returned. -+ * -+ * @return TRUE if ID contains wildcards -+ */ -+ bool (*contains_wildcards) (identification_t *this); -+ -+ /** -+ * Create an enumerator over subparts of an identity. -+ * -+ * Some identities are built from several parts, e.g. an E-Mail consists -+ * of a username and a domain part, or a DistinguishedName contains several -+ * RDNs. -+ * For identity without subtypes (support), an empty enumerator is -+ * returned. -+ * -+ * @return an enumerator over (id_part_t type, chunk_t data) -+ */ -+ enumerator_t* (*create_part_enumerator)(identification_t *this); -+ -+ /** -+ * Clone a identification_t instance. -+ * -+ * @return clone of this -+ */ -+ identification_t *(*clone) (identification_t *this); -+ -+ /** -+ * Destroys a identification_t object. -+ */ -+ void (*destroy) (identification_t *this); -+}; -+ -+/** -+ * creates an ascii representation of a DN -+ * -+ * @param dn chunk pointing to DN -+ * @param buf buffer to have string written to it -+ * @param len length of buf -+ */ -+void dntoa(chunk_t dn, STR *buf, size_t len); -+ -+#endif /** IDENTIFICATION_H_ @}*/ -diff --git a/efitools/lib/asn1/oid.c b/efitools/lib/asn1/oid.c -new file mode 100644 -index 0000000..b212996 ---- /dev/null -+++ b/efitools/lib/asn1/oid.c -@@ -0,0 +1,390 @@ -+/* List of some useful object identifiers (OIDs) -+ * Copyright (C) 2003-2008 Andreas Steffen, Hochschule fuer Technik Rapperswil -+ * -+ * This file has been automatically generated by the script oid.pl -+ * Do not edit manually! -+ */ -+ -+#include -+ -+#include "oid.h" -+ -+const oid_t oid_names[] = { -+ {0x02, 7, 1, 0, "ITU-T Administration" }, /* 0 */ -+ { 0x82, 0, 1, 1, "" }, /* 1 */ -+ { 0x06, 0, 1, 2, "Germany ITU-T member" }, /* 2 */ -+ { 0x01, 0, 1, 3, "Deutsche Telekom AG" }, /* 3 */ -+ { 0x0A, 0, 1, 4, "" }, /* 4 */ -+ { 0x07, 0, 1, 5, "" }, /* 5 */ -+ { 0x14, 0, 0, 6, "ND" }, /* 6 */ -+ {0x09, 18, 1, 0, "data" }, /* 7 */ -+ { 0x92, 0, 1, 1, "" }, /* 8 */ -+ { 0x26, 0, 1, 2, "" }, /* 9 */ -+ { 0x89, 0, 1, 3, "" }, /* 10 */ -+ { 0x93, 0, 1, 4, "" }, /* 11 */ -+ { 0xF2, 0, 1, 5, "" }, /* 12 */ -+ { 0x2C, 0, 1, 6, "" }, /* 13 */ -+ { 0x64, 0, 1, 7, "pilot" }, /* 14 */ -+ { 0x01, 0, 1, 8, "pilotAttributeType" }, /* 15 */ -+ { 0x01, 17, 0, 9, "UID" }, /* 16 */ -+ { 0x19, 0, 0, 9, "DC" }, /* 17 */ -+ {0x55, 65, 1, 0, "X.500" }, /* 18 */ -+ { 0x04, 37, 1, 1, "X.509" }, /* 19 */ -+ { 0x03, 21, 0, 2, "CN" }, /* 20 */ -+ { 0x04, 22, 0, 2, "S" }, /* 21 */ -+ { 0x05, 23, 0, 2, "SN" }, /* 22 */ -+ { 0x06, 24, 0, 2, "C" }, /* 23 */ -+ { 0x07, 25, 0, 2, "L" }, /* 24 */ -+ { 0x08, 26, 0, 2, "ST" }, /* 25 */ -+ { 0x0A, 27, 0, 2, "O" }, /* 26 */ -+ { 0x0B, 28, 0, 2, "OU" }, /* 27 */ -+ { 0x0C, 29, 0, 2, "T" }, /* 28 */ -+ { 0x0D, 30, 0, 2, "D" }, /* 29 */ -+ { 0x24, 31, 0, 2, "userCertificate" }, /* 30 */ -+ { 0x29, 32, 0, 2, "N" }, /* 31 */ -+ { 0x2A, 33, 0, 2, "G" }, /* 32 */ -+ { 0x2B, 34, 0, 2, "I" }, /* 33 */ -+ { 0x2D, 35, 0, 2, "ID" }, /* 34 */ -+ { 0x2E, 36, 0, 2, "dnQualifier" }, /* 35 */ -+ { 0x48, 0, 0, 2, "role" }, /* 36 */ -+ { 0x1D, 0, 1, 1, "id-ce" }, /* 37 */ -+ { 0x09, 39, 0, 2, "subjectDirectoryAttrs" }, /* 38 */ -+ { 0x0E, 40, 0, 2, "subjectKeyIdentifier" }, /* 39 */ -+ { 0x0F, 41, 0, 2, "keyUsage" }, /* 40 */ -+ { 0x10, 42, 0, 2, "privateKeyUsagePeriod" }, /* 41 */ -+ { 0x11, 43, 0, 2, "subjectAltName" }, /* 42 */ -+ { 0x12, 44, 0, 2, "issuerAltName" }, /* 43 */ -+ { 0x13, 45, 0, 2, "basicConstraints" }, /* 44 */ -+ { 0x14, 46, 0, 2, "crlNumber" }, /* 45 */ -+ { 0x15, 47, 0, 2, "reasonCode" }, /* 46 */ -+ { 0x17, 48, 0, 2, "holdInstructionCode" }, /* 47 */ -+ { 0x18, 49, 0, 2, "invalidityDate" }, /* 48 */ -+ { 0x1B, 50, 0, 2, "deltaCrlIndicator" }, /* 49 */ -+ { 0x1C, 51, 0, 2, "issuingDistributionPoint" }, /* 50 */ -+ { 0x1D, 52, 0, 2, "certificateIssuer" }, /* 51 */ -+ { 0x1E, 53, 0, 2, "nameConstraints" }, /* 52 */ -+ { 0x1F, 54, 0, 2, "crlDistributionPoints" }, /* 53 */ -+ { 0x20, 56, 1, 2, "certificatePolicies" }, /* 54 */ -+ { 0x00, 0, 0, 3, "anyPolicy" }, /* 55 */ -+ { 0x21, 57, 0, 2, "policyMappings" }, /* 56 */ -+ { 0x23, 58, 0, 2, "authorityKeyIdentifier" }, /* 57 */ -+ { 0x24, 59, 0, 2, "policyConstraints" }, /* 58 */ -+ { 0x25, 61, 1, 2, "extendedKeyUsage" }, /* 59 */ -+ { 0x00, 0, 0, 3, "anyExtendedKeyUsage" }, /* 60 */ -+ { 0x2E, 62, 0, 2, "freshestCRL" }, /* 61 */ -+ { 0x36, 63, 0, 2, "inhibitAnyPolicy" }, /* 62 */ -+ { 0x37, 64, 0, 2, "targetInformation" }, /* 63 */ -+ { 0x38, 0, 0, 2, "noRevAvail" }, /* 64 */ -+ {0x2A, 169, 1, 0, "" }, /* 65 */ -+ { 0x83, 78, 1, 1, "" }, /* 66 */ -+ { 0x08, 0, 1, 2, "jp" }, /* 67 */ -+ { 0x8C, 0, 1, 3, "" }, /* 68 */ -+ { 0x9A, 0, 1, 4, "" }, /* 69 */ -+ { 0x4B, 0, 1, 5, "" }, /* 70 */ -+ { 0x3D, 0, 1, 6, "" }, /* 71 */ -+ { 0x01, 0, 1, 7, "security" }, /* 72 */ -+ { 0x01, 0, 1, 8, "algorithm" }, /* 73 */ -+ { 0x01, 0, 1, 9, "symm-encryption-alg" }, /* 74 */ -+ { 0x02, 76, 0, 10, "camellia128-cbc" }, /* 75 */ -+ { 0x03, 77, 0, 10, "camellia192-cbc" }, /* 76 */ -+ { 0x04, 0, 0, 10, "camellia256-cbc" }, /* 77 */ -+ { 0x86, 0, 1, 1, "" }, /* 78 */ -+ { 0x48, 0, 1, 2, "us" }, /* 79 */ -+ { 0x86, 128, 1, 3, "" }, /* 80 */ -+ { 0xF6, 86, 1, 4, "" }, /* 81 */ -+ { 0x7D, 0, 1, 5, "NortelNetworks" }, /* 82 */ -+ { 0x07, 0, 1, 6, "Entrust" }, /* 83 */ -+ { 0x41, 0, 1, 7, "nsn-ce" }, /* 84 */ -+ { 0x00, 0, 0, 8, "entrustVersInfo" }, /* 85 */ -+ { 0xF7, 0, 1, 4, "" }, /* 86 */ -+ { 0x0D, 0, 1, 5, "RSADSI" }, /* 87 */ -+ { 0x01, 123, 1, 6, "PKCS" }, /* 88 */ -+ { 0x01, 100, 1, 7, "PKCS-1" }, /* 89 */ -+ { 0x01, 91, 0, 8, "rsaEncryption" }, /* 90 */ -+ { 0x02, 92, 0, 8, "md2WithRSAEncryption" }, /* 91 */ -+ { 0x04, 93, 0, 8, "md5WithRSAEncryption" }, /* 92 */ -+ { 0x05, 94, 0, 8, "sha-1WithRSAEncryption" }, /* 93 */ -+ { 0x07, 95, 0, 8, "id-RSAES-OAEP" }, /* 94 */ -+ { 0x09, 96, 0, 8, "id-pSpecified" }, /* 95 */ -+ { 0x0B, 97, 0, 8, "sha256WithRSAEncryption" }, /* 96 */ -+ { 0x0C, 98, 0, 8, "sha384WithRSAEncryption" }, /* 97 */ -+ { 0x0D, 99, 0, 8, "sha512WithRSAEncryption" }, /* 98 */ -+ { 0x0E, 0, 0, 8, "sha224WithRSAEncryption" }, /* 99 */ -+ { 0x05, 105, 1, 7, "PKCS-5" }, /* 100 */ -+ { 0x03, 102, 0, 8, "pbeWithMD5AndDES-CBC" }, /* 101 */ -+ { 0x0A, 103, 0, 8, "pbeWithSHA1AndDES-CBC" }, /* 102 */ -+ { 0x0C, 104, 0, 8, "id-PBKDF2" }, /* 103 */ -+ { 0x0D, 0, 0, 8, "id-PBES2" }, /* 104 */ -+ { 0x07, 112, 1, 7, "PKCS-7" }, /* 105 */ -+ { 0x01, 107, 0, 8, "data" }, /* 106 */ -+ { 0x02, 108, 0, 8, "signedData" }, /* 107 */ -+ { 0x03, 109, 0, 8, "envelopedData" }, /* 108 */ -+ { 0x04, 110, 0, 8, "signedAndEnvelopedData" }, /* 109 */ -+ { 0x05, 111, 0, 8, "digestedData" }, /* 110 */ -+ { 0x06, 0, 0, 8, "encryptedData" }, /* 111 */ -+ { 0x09, 0, 1, 7, "PKCS-9" }, /* 112 */ -+ { 0x01, 114, 0, 8, "E" }, /* 113 */ -+ { 0x02, 115, 0, 8, "unstructuredName" }, /* 114 */ -+ { 0x03, 116, 0, 8, "contentType" }, /* 115 */ -+ { 0x04, 117, 0, 8, "messageDigest" }, /* 116 */ -+ { 0x05, 118, 0, 8, "signingTime" }, /* 117 */ -+ { 0x06, 119, 0, 8, "counterSignature" }, /* 118 */ -+ { 0x07, 120, 0, 8, "challengePassword" }, /* 119 */ -+ { 0x08, 121, 0, 8, "unstructuredAddress" }, /* 120 */ -+ { 0x0E, 122, 0, 8, "extensionRequest" }, /* 121 */ -+ { 0x0F, 0, 0, 8, "S/MIME Capabilities" }, /* 122 */ -+ { 0x02, 126, 1, 6, "digestAlgorithm" }, /* 123 */ -+ { 0x02, 125, 0, 7, "md2" }, /* 124 */ -+ { 0x05, 0, 0, 7, "md5" }, /* 125 */ -+ { 0x03, 0, 1, 6, "encryptionAlgorithm" }, /* 126 */ -+ { 0x07, 0, 0, 7, "3des-ede-cbc" }, /* 127 */ -+ { 0xCE, 0, 1, 3, "" }, /* 128 */ -+ { 0x3D, 0, 1, 4, "ansi-X9-62" }, /* 129 */ -+ { 0x02, 132, 1, 5, "id-publicKeyType" }, /* 130 */ -+ { 0x01, 0, 0, 6, "id-ecPublicKey" }, /* 131 */ -+ { 0x03, 162, 1, 5, "ellipticCurve" }, /* 132 */ -+ { 0x00, 154, 1, 6, "c-TwoCurve" }, /* 133 */ -+ { 0x01, 135, 0, 7, "c2pnb163v1" }, /* 134 */ -+ { 0x02, 136, 0, 7, "c2pnb163v2" }, /* 135 */ -+ { 0x03, 137, 0, 7, "c2pnb163v3" }, /* 136 */ -+ { 0x04, 138, 0, 7, "c2pnb176w1" }, /* 137 */ -+ { 0x05, 139, 0, 7, "c2tnb191v1" }, /* 138 */ -+ { 0x06, 140, 0, 7, "c2tnb191v2" }, /* 139 */ -+ { 0x07, 141, 0, 7, "c2tnb191v3" }, /* 140 */ -+ { 0x08, 142, 0, 7, "c2onb191v4" }, /* 141 */ -+ { 0x09, 143, 0, 7, "c2onb191v5" }, /* 142 */ -+ { 0x0A, 144, 0, 7, "c2pnb208w1" }, /* 143 */ -+ { 0x0B, 145, 0, 7, "c2tnb239v1" }, /* 144 */ -+ { 0x0C, 146, 0, 7, "c2tnb239v2" }, /* 145 */ -+ { 0x0D, 147, 0, 7, "c2tnb239v3" }, /* 146 */ -+ { 0x0E, 148, 0, 7, "c2onb239v4" }, /* 147 */ -+ { 0x0F, 149, 0, 7, "c2onb239v5" }, /* 148 */ -+ { 0x10, 150, 0, 7, "c2pnb272w1" }, /* 149 */ -+ { 0x11, 151, 0, 7, "c2pnb304w1" }, /* 150 */ -+ { 0x12, 152, 0, 7, "c2tnb359v1" }, /* 151 */ -+ { 0x13, 153, 0, 7, "c2pnb368w1" }, /* 152 */ -+ { 0x14, 0, 0, 7, "c2tnb431r1" }, /* 153 */ -+ { 0x01, 0, 1, 6, "primeCurve" }, /* 154 */ -+ { 0x01, 156, 0, 7, "prime192v1" }, /* 155 */ -+ { 0x02, 157, 0, 7, "prime192v2" }, /* 156 */ -+ { 0x03, 158, 0, 7, "prime192v3" }, /* 157 */ -+ { 0x04, 159, 0, 7, "prime239v1" }, /* 158 */ -+ { 0x05, 160, 0, 7, "prime239v2" }, /* 159 */ -+ { 0x06, 161, 0, 7, "prime239v3" }, /* 160 */ -+ { 0x07, 0, 0, 7, "prime256v1" }, /* 161 */ -+ { 0x04, 0, 1, 5, "id-ecSigType" }, /* 162 */ -+ { 0x01, 164, 0, 6, "ecdsa-with-SHA1" }, /* 163 */ -+ { 0x03, 0, 1, 6, "ecdsa-with-Specified" }, /* 164 */ -+ { 0x01, 166, 0, 7, "ecdsa-with-SHA224" }, /* 165 */ -+ { 0x02, 167, 0, 7, "ecdsa-with-SHA256" }, /* 166 */ -+ { 0x03, 168, 0, 7, "ecdsa-with-SHA384" }, /* 167 */ -+ { 0x04, 0, 0, 7, "ecdsa-with-SHA512" }, /* 168 */ -+ {0x2B, 323, 1, 0, "" }, /* 169 */ -+ { 0x06, 237, 1, 1, "dod" }, /* 170 */ -+ { 0x01, 0, 1, 2, "internet" }, /* 171 */ -+ { 0x04, 194, 1, 3, "private" }, /* 172 */ -+ { 0x01, 0, 1, 4, "enterprise" }, /* 173 */ -+ { 0x82, 187, 1, 5, "" }, /* 174 */ -+ { 0x37, 184, 1, 6, "Microsoft" }, /* 175 */ -+ { 0x0A, 180, 1, 7, "" }, /* 176 */ -+ { 0x03, 0, 1, 8, "" }, /* 177 */ -+ { 0x03, 179, 0, 9, "msSGC" }, /* 178 */ -+ { 0x04, 0, 0, 9, "msEncryptingFileSystem" }, /* 179 */ -+ { 0x14, 0, 1, 7, "msEnrollmentInfrastructure"}, /* 180 */ -+ { 0x02, 0, 1, 8, "msCertificateTypeExtension"}, /* 181 */ -+ { 0x02, 183, 0, 9, "msSmartcardLogon" }, /* 182 */ -+ { 0x03, 0, 0, 9, "msUPN" }, /* 183 */ -+ { 0xA0, 0, 1, 6, "" }, /* 184 */ -+ { 0x2A, 0, 1, 7, "ITA" }, /* 185 */ -+ { 0x01, 0, 0, 8, "strongSwan" }, /* 186 */ -+ { 0x89, 0, 1, 5, "" }, /* 187 */ -+ { 0x31, 0, 1, 6, "" }, /* 188 */ -+ { 0x01, 0, 1, 7, "" }, /* 189 */ -+ { 0x01, 0, 1, 8, "" }, /* 190 */ -+ { 0x02, 0, 1, 9, "" }, /* 191 */ -+ { 0x02, 0, 1, 10, "" }, /* 192 */ -+ { 0x4B, 0, 0, 11, "TCGID" }, /* 193 */ -+ { 0x05, 0, 1, 3, "security" }, /* 194 */ -+ { 0x05, 0, 1, 4, "mechanisms" }, /* 195 */ -+ { 0x07, 234, 1, 5, "id-pkix" }, /* 196 */ -+ { 0x01, 201, 1, 6, "id-pe" }, /* 197 */ -+ { 0x01, 199, 0, 7, "authorityInfoAccess" }, /* 198 */ -+ { 0x03, 200, 0, 7, "qcStatements" }, /* 199 */ -+ { 0x07, 0, 0, 7, "ipAddrBlocks" }, /* 200 */ -+ { 0x02, 204, 1, 6, "id-qt" }, /* 201 */ -+ { 0x01, 203, 0, 7, "cps" }, /* 202 */ -+ { 0x02, 0, 0, 7, "unotice" }, /* 203 */ -+ { 0x03, 214, 1, 6, "id-kp" }, /* 204 */ -+ { 0x01, 206, 0, 7, "serverAuth" }, /* 205 */ -+ { 0x02, 207, 0, 7, "clientAuth" }, /* 206 */ -+ { 0x03, 208, 0, 7, "codeSigning" }, /* 207 */ -+ { 0x04, 209, 0, 7, "emailProtection" }, /* 208 */ -+ { 0x05, 210, 0, 7, "ipsecEndSystem" }, /* 209 */ -+ { 0x06, 211, 0, 7, "ipsecTunnel" }, /* 210 */ -+ { 0x07, 212, 0, 7, "ipsecUser" }, /* 211 */ -+ { 0x08, 213, 0, 7, "timeStamping" }, /* 212 */ -+ { 0x09, 0, 0, 7, "ocspSigning" }, /* 213 */ -+ { 0x08, 216, 1, 6, "id-otherNames" }, /* 214 */ -+ { 0x05, 0, 0, 7, "xmppAddr" }, /* 215 */ -+ { 0x0A, 221, 1, 6, "id-aca" }, /* 216 */ -+ { 0x01, 218, 0, 7, "authenticationInfo" }, /* 217 */ -+ { 0x02, 219, 0, 7, "accessIdentity" }, /* 218 */ -+ { 0x03, 220, 0, 7, "chargingIdentity" }, /* 219 */ -+ { 0x04, 0, 0, 7, "group" }, /* 220 */ -+ { 0x0B, 222, 0, 6, "subjectInfoAccess" }, /* 221 */ -+ { 0x30, 0, 1, 6, "id-ad" }, /* 222 */ -+ { 0x01, 231, 1, 7, "ocsp" }, /* 223 */ -+ { 0x01, 225, 0, 8, "basic" }, /* 224 */ -+ { 0x02, 226, 0, 8, "nonce" }, /* 225 */ -+ { 0x03, 227, 0, 8, "crl" }, /* 226 */ -+ { 0x04, 228, 0, 8, "response" }, /* 227 */ -+ { 0x05, 229, 0, 8, "noCheck" }, /* 228 */ -+ { 0x06, 230, 0, 8, "archiveCutoff" }, /* 229 */ -+ { 0x07, 0, 0, 8, "serviceLocator" }, /* 230 */ -+ { 0x02, 232, 0, 7, "caIssuers" }, /* 231 */ -+ { 0x03, 233, 0, 7, "timeStamping" }, /* 232 */ -+ { 0x05, 0, 0, 7, "caRepository" }, /* 233 */ -+ { 0x08, 0, 1, 5, "ipsec" }, /* 234 */ -+ { 0x02, 0, 1, 6, "certificate" }, /* 235 */ -+ { 0x02, 0, 0, 7, "iKEIntermediate" }, /* 236 */ -+ { 0x0E, 243, 1, 1, "oiw" }, /* 237 */ -+ { 0x03, 0, 1, 2, "secsig" }, /* 238 */ -+ { 0x02, 0, 1, 3, "algorithms" }, /* 239 */ -+ { 0x07, 241, 0, 4, "des-cbc" }, /* 240 */ -+ { 0x1A, 242, 0, 4, "sha-1" }, /* 241 */ -+ { 0x1D, 0, 0, 4, "sha-1WithRSASignature" }, /* 242 */ -+ { 0x24, 289, 1, 1, "TeleTrusT" }, /* 243 */ -+ { 0x03, 0, 1, 2, "algorithm" }, /* 244 */ -+ { 0x03, 0, 1, 3, "signatureAlgorithm" }, /* 245 */ -+ { 0x01, 250, 1, 4, "rsaSignature" }, /* 246 */ -+ { 0x02, 248, 0, 5, "rsaSigWithripemd160" }, /* 247 */ -+ { 0x03, 249, 0, 5, "rsaSigWithripemd128" }, /* 248 */ -+ { 0x04, 0, 0, 5, "rsaSigWithripemd256" }, /* 249 */ -+ { 0x02, 0, 1, 4, "ecSign" }, /* 250 */ -+ { 0x01, 252, 0, 5, "ecSignWithsha1" }, /* 251 */ -+ { 0x02, 253, 0, 5, "ecSignWithripemd160" }, /* 252 */ -+ { 0x03, 254, 0, 5, "ecSignWithmd2" }, /* 253 */ -+ { 0x04, 255, 0, 5, "ecSignWithmd5" }, /* 254 */ -+ { 0x05, 272, 1, 5, "ttt-ecg" }, /* 255 */ -+ { 0x01, 260, 1, 6, "fieldType" }, /* 256 */ -+ { 0x01, 0, 1, 7, "characteristictwoField" }, /* 257 */ -+ { 0x01, 0, 1, 8, "basisType" }, /* 258 */ -+ { 0x01, 0, 0, 9, "ipBasis" }, /* 259 */ -+ { 0x02, 262, 1, 6, "keyType" }, /* 260 */ -+ { 0x01, 0, 0, 7, "ecgPublicKey" }, /* 261 */ -+ { 0x03, 263, 0, 6, "curve" }, /* 262 */ -+ { 0x04, 270, 1, 6, "signatures" }, /* 263 */ -+ { 0x01, 265, 0, 7, "ecgdsa-with-RIPEMD160" }, /* 264 */ -+ { 0x02, 266, 0, 7, "ecgdsa-with-SHA1" }, /* 265 */ -+ { 0x03, 267, 0, 7, "ecgdsa-with-SHA224" }, /* 266 */ -+ { 0x04, 268, 0, 7, "ecgdsa-with-SHA256" }, /* 267 */ -+ { 0x05, 269, 0, 7, "ecgdsa-with-SHA384" }, /* 268 */ -+ { 0x06, 0, 0, 7, "ecgdsa-with-SHA512" }, /* 269 */ -+ { 0x05, 0, 1, 6, "module" }, /* 270 */ -+ { 0x01, 0, 0, 7, "1" }, /* 271 */ -+ { 0x08, 0, 1, 5, "ecStdCurvesAndGeneration" }, /* 272 */ -+ { 0x01, 0, 1, 6, "ellipticCurve" }, /* 273 */ -+ { 0x01, 0, 1, 7, "versionOne" }, /* 274 */ -+ { 0x01, 276, 0, 8, "brainpoolP160r1" }, /* 275 */ -+ { 0x02, 277, 0, 8, "brainpoolP160t1" }, /* 276 */ -+ { 0x03, 278, 0, 8, "brainpoolP192r1" }, /* 277 */ -+ { 0x04, 279, 0, 8, "brainpoolP192t1" }, /* 278 */ -+ { 0x05, 280, 0, 8, "brainpoolP224r1" }, /* 279 */ -+ { 0x06, 281, 0, 8, "brainpoolP224t1" }, /* 280 */ -+ { 0x07, 282, 0, 8, "brainpoolP256r1" }, /* 281 */ -+ { 0x08, 283, 0, 8, "brainpoolP256t1" }, /* 282 */ -+ { 0x09, 284, 0, 8, "brainpoolP320r1" }, /* 283 */ -+ { 0x0A, 285, 0, 8, "brainpoolP320t1" }, /* 284 */ -+ { 0x0B, 286, 0, 8, "brainpoolP384r1" }, /* 285 */ -+ { 0x0C, 287, 0, 8, "brainpoolP384t1" }, /* 286 */ -+ { 0x0D, 288, 0, 8, "brainpoolP512r1" }, /* 287 */ -+ { 0x0E, 0, 0, 8, "brainpoolP512t1" }, /* 288 */ -+ { 0x81, 0, 1, 1, "" }, /* 289 */ -+ { 0x04, 0, 1, 2, "Certicom" }, /* 290 */ -+ { 0x00, 0, 1, 3, "curve" }, /* 291 */ -+ { 0x01, 293, 0, 4, "sect163k1" }, /* 292 */ -+ { 0x02, 294, 0, 4, "sect163r1" }, /* 293 */ -+ { 0x03, 295, 0, 4, "sect239k1" }, /* 294 */ -+ { 0x04, 296, 0, 4, "sect113r1" }, /* 295 */ -+ { 0x05, 297, 0, 4, "sect113r2" }, /* 296 */ -+ { 0x06, 298, 0, 4, "secp112r1" }, /* 297 */ -+ { 0x07, 299, 0, 4, "secp112r2" }, /* 298 */ -+ { 0x08, 300, 0, 4, "secp160r1" }, /* 299 */ -+ { 0x09, 301, 0, 4, "secp160k1" }, /* 300 */ -+ { 0x0A, 302, 0, 4, "secp256k1" }, /* 301 */ -+ { 0x0F, 303, 0, 4, "sect163r2" }, /* 302 */ -+ { 0x10, 304, 0, 4, "sect283k1" }, /* 303 */ -+ { 0x11, 305, 0, 4, "sect283r1" }, /* 304 */ -+ { 0x16, 306, 0, 4, "sect131r1" }, /* 305 */ -+ { 0x17, 307, 0, 4, "sect131r2" }, /* 306 */ -+ { 0x18, 308, 0, 4, "sect193r1" }, /* 307 */ -+ { 0x19, 309, 0, 4, "sect193r2" }, /* 308 */ -+ { 0x1A, 310, 0, 4, "sect233k1" }, /* 309 */ -+ { 0x1B, 311, 0, 4, "sect233r1" }, /* 310 */ -+ { 0x1C, 312, 0, 4, "secp128r1" }, /* 311 */ -+ { 0x1D, 313, 0, 4, "secp128r2" }, /* 312 */ -+ { 0x1E, 314, 0, 4, "secp160r2" }, /* 313 */ -+ { 0x1F, 315, 0, 4, "secp192k1" }, /* 314 */ -+ { 0x20, 316, 0, 4, "secp224k1" }, /* 315 */ -+ { 0x21, 317, 0, 4, "secp224r1" }, /* 316 */ -+ { 0x22, 318, 0, 4, "secp384r1" }, /* 317 */ -+ { 0x23, 319, 0, 4, "secp521r1" }, /* 318 */ -+ { 0x24, 320, 0, 4, "sect409k1" }, /* 319 */ -+ { 0x25, 321, 0, 4, "sect409r1" }, /* 320 */ -+ { 0x26, 322, 0, 4, "sect571k1" }, /* 321 */ -+ { 0x27, 0, 0, 4, "sect571r1" }, /* 322 */ -+ {0x60, 369, 1, 0, "" }, /* 323 */ -+ { 0x86, 0, 1, 1, "" }, /* 324 */ -+ { 0x48, 0, 1, 2, "" }, /* 325 */ -+ { 0x01, 0, 1, 3, "organization" }, /* 326 */ -+ { 0x65, 345, 1, 4, "gov" }, /* 327 */ -+ { 0x03, 0, 1, 5, "csor" }, /* 328 */ -+ { 0x04, 0, 1, 6, "nistalgorithm" }, /* 329 */ -+ { 0x01, 340, 1, 7, "aes" }, /* 330 */ -+ { 0x02, 332, 0, 8, "id-aes128-CBC" }, /* 331 */ -+ { 0x06, 333, 0, 8, "id-aes128-GCM" }, /* 332 */ -+ { 0x07, 334, 0, 8, "id-aes128-CCM" }, /* 333 */ -+ { 0x16, 335, 0, 8, "id-aes192-CBC" }, /* 334 */ -+ { 0x1A, 336, 0, 8, "id-aes192-GCM" }, /* 335 */ -+ { 0x1B, 337, 0, 8, "id-aes192-CCM" }, /* 336 */ -+ { 0x2A, 338, 0, 8, "id-aes256-CBC" }, /* 337 */ -+ { 0x2E, 339, 0, 8, "id-aes256-GCM" }, /* 338 */ -+ { 0x2F, 0, 0, 8, "id-aes256-CCM" }, /* 339 */ -+ { 0x02, 0, 1, 7, "hashalgs" }, /* 340 */ -+ { 0x01, 342, 0, 8, "id-SHA-256" }, /* 341 */ -+ { 0x02, 343, 0, 8, "id-SHA-384" }, /* 342 */ -+ { 0x03, 344, 0, 8, "id-SHA-512" }, /* 343 */ -+ { 0x04, 0, 0, 8, "id-SHA-224" }, /* 344 */ -+ { 0x86, 0, 1, 4, "" }, /* 345 */ -+ { 0xf8, 0, 1, 5, "" }, /* 346 */ -+ { 0x42, 359, 1, 6, "netscape" }, /* 347 */ -+ { 0x01, 354, 1, 7, "" }, /* 348 */ -+ { 0x01, 350, 0, 8, "nsCertType" }, /* 349 */ -+ { 0x03, 351, 0, 8, "nsRevocationUrl" }, /* 350 */ -+ { 0x04, 352, 0, 8, "nsCaRevocationUrl" }, /* 351 */ -+ { 0x08, 353, 0, 8, "nsCaPolicyUrl" }, /* 352 */ -+ { 0x0d, 0, 0, 8, "nsComment" }, /* 353 */ -+ { 0x03, 357, 1, 7, "directory" }, /* 354 */ -+ { 0x01, 0, 1, 8, "" }, /* 355 */ -+ { 0x03, 0, 0, 9, "employeeNumber" }, /* 356 */ -+ { 0x04, 0, 1, 7, "policy" }, /* 357 */ -+ { 0x01, 0, 0, 8, "nsSGC" }, /* 358 */ -+ { 0x45, 0, 1, 6, "verisign" }, /* 359 */ -+ { 0x01, 0, 1, 7, "pki" }, /* 360 */ -+ { 0x09, 0, 1, 8, "attributes" }, /* 361 */ -+ { 0x02, 363, 0, 9, "messageType" }, /* 362 */ -+ { 0x03, 364, 0, 9, "pkiStatus" }, /* 363 */ -+ { 0x04, 365, 0, 9, "failInfo" }, /* 364 */ -+ { 0x05, 366, 0, 9, "senderNonce" }, /* 365 */ -+ { 0x06, 367, 0, 9, "recipientNonce" }, /* 366 */ -+ { 0x07, 368, 0, 9, "transID" }, /* 367 */ -+ { 0x08, 0, 0, 9, "extensionReq" }, /* 368 */ -+ {0x67, 0, 1, 0, "" }, /* 369 */ -+ { 0x81, 0, 1, 1, "" }, /* 370 */ -+ { 0x05, 0, 1, 2, "" }, /* 371 */ -+ { 0x02, 0, 1, 3, "tcg-attribute" }, /* 372 */ -+ { 0x01, 374, 0, 4, "tcg-at-tpmManufacturer" }, /* 373 */ -+ { 0x02, 375, 0, 4, "tcg-at-tpmModel" }, /* 374 */ -+ { 0x03, 376, 0, 4, "tcg-at-tpmVersion" }, /* 375 */ -+ { 0x0F, 0, 0, 4, "tcg-at-tpmIdLabel" } /* 376 */ -+}; -diff --git a/efitools/lib/asn1/oid.h b/efitools/lib/asn1/oid.h -new file mode 100644 -index 0000000..05aa606 ---- /dev/null -+++ b/efitools/lib/asn1/oid.h -@@ -0,0 +1,224 @@ -+/* Object identifiers (OIDs) used by strongSwan -+ * Copyright (C) 2003-2008 Andreas Steffen, Hochschule fuer Technik Rapperswil -+ * -+ * This file has been automatically generated by the script oid.pl -+ * Do not edit manually! -+ */ -+ -+#ifndef OID_H_ -+#define OID_H_ -+ -+typedef struct { -+ u_char octet; -+ u_int next; -+ u_int down; -+ u_int level; -+ const u_char *name; -+} oid_t; -+ -+extern const oid_t oid_names[]; -+ -+#define OID_UNKNOWN -1 -+#define OID_NAME_DISTINGUISHER 6 -+#define OID_PILOT_USERID 16 -+#define OID_PILOT_DOMAIN_COMPONENT 17 -+#define OID_COMMON_NAME 20 -+#define OID_SURNAME 21 -+#define OID_SERIAL_NUMBER 22 -+#define OID_COUNTRY 23 -+#define OID_LOCALITY 24 -+#define OID_STATE_OR_PROVINCE 25 -+#define OID_ORGANIZATION 26 -+#define OID_ORGANIZATION_UNIT 27 -+#define OID_TITLE 28 -+#define OID_DESCRIPTION 29 -+#define OID_USER_CERTIFICATE 30 -+#define OID_NAME 31 -+#define OID_GIVEN_NAME 32 -+#define OID_INITIALS 33 -+#define OID_UNIQUE_IDENTIFIER 34 -+#define OID_DN_QUALIFIER 35 -+#define OID_ROLE 36 -+#define OID_SUBJECT_KEY_ID 39 -+#define OID_KEY_USAGE 40 -+#define OID_SUBJECT_ALT_NAME 42 -+#define OID_BASIC_CONSTRAINTS 44 -+#define OID_CRL_NUMBER 45 -+#define OID_CRL_REASON_CODE 46 -+#define OID_DELTA_CRL_INDICATOR 49 -+#define OID_NAME_CONSTRAINTS 52 -+#define OID_CRL_DISTRIBUTION_POINTS 53 -+#define OID_CERTIFICATE_POLICIES 54 -+#define OID_ANY_POLICY 55 -+#define OID_POLICY_MAPPINGS 56 -+#define OID_AUTHORITY_KEY_ID 57 -+#define OID_POLICY_CONSTRAINTS 58 -+#define OID_EXTENDED_KEY_USAGE 59 -+#define OID_FRESHEST_CRL 61 -+#define OID_INHIBIT_ANY_POLICY 62 -+#define OID_TARGET_INFORMATION 63 -+#define OID_NO_REV_AVAIL 64 -+#define OID_CAMELLIA128_CBC 75 -+#define OID_CAMELLIA192_CBC 76 -+#define OID_CAMELLIA256_CBC 77 -+#define OID_RSA_ENCRYPTION 90 -+#define OID_MD2_WITH_RSA 91 -+#define OID_MD5_WITH_RSA 92 -+#define OID_SHA1_WITH_RSA 93 -+#define OID_RSAES_OAEP 94 -+#define OID_SHA256_WITH_RSA 96 -+#define OID_SHA384_WITH_RSA 97 -+#define OID_SHA512_WITH_RSA 98 -+#define OID_SHA224_WITH_RSA 99 -+#define OID_PBE_MD5_DES_CBC 101 -+#define OID_PBE_SHA1_DES_CBC 102 -+#define OID_PBKDF2 103 -+#define OID_PBES2 104 -+#define OID_PKCS7_DATA 106 -+#define OID_PKCS7_SIGNED_DATA 107 -+#define OID_PKCS7_ENVELOPED_DATA 108 -+#define OID_PKCS7_SIGNED_ENVELOPED_DATA 109 -+#define OID_PKCS7_DIGESTED_DATA 110 -+#define OID_PKCS7_ENCRYPTED_DATA 111 -+#define OID_EMAIL_ADDRESS 113 -+#define OID_UNSTRUCTURED_NAME 114 -+#define OID_PKCS9_CONTENT_TYPE 115 -+#define OID_PKCS9_MESSAGE_DIGEST 116 -+#define OID_PKCS9_SIGNING_TIME 117 -+#define OID_CHALLENGE_PASSWORD 119 -+#define OID_UNSTRUCTURED_ADDRESS 120 -+#define OID_EXTENSION_REQUEST 121 -+#define OID_MD2 124 -+#define OID_MD5 125 -+#define OID_3DES_EDE_CBC 127 -+#define OID_EC_PUBLICKEY 131 -+#define OID_C2PNB163V1 134 -+#define OID_C2PNB163V2 135 -+#define OID_C2PNB163V3 136 -+#define OID_C2PNB176W1 137 -+#define OID_C2PNB191V1 138 -+#define OID_C2PNB191V2 139 -+#define OID_C2PNB191V3 140 -+#define OID_C2PNB191V4 141 -+#define OID_C2PNB191V5 142 -+#define OID_C2PNB208W1 143 -+#define OID_C2PNB239V1 144 -+#define OID_C2PNB239V2 145 -+#define OID_C2PNB239V3 146 -+#define OID_C2PNB239V4 147 -+#define OID_C2PNB239V5 148 -+#define OID_C2PNB272W1 149 -+#define OID_C2PNB304W1 150 -+#define OID_C2PNB359V1 151 -+#define OID_C2PNB368W1 152 -+#define OID_C2PNB431R1 153 -+#define OID_PRIME192V1 155 -+#define OID_PRIME192V2 156 -+#define OID_PRIME192V3 157 -+#define OID_PRIME239V1 158 -+#define OID_PRIME239V2 159 -+#define OID_PRIME239V3 160 -+#define OID_PRIME256V1 161 -+#define OID_ECDSA_WITH_SHA1 163 -+#define OID_ECDSA_WITH_SHA224 165 -+#define OID_ECDSA_WITH_SHA256 166 -+#define OID_ECDSA_WITH_SHA384 167 -+#define OID_ECDSA_WITH_SHA512 168 -+#define OID_USER_PRINCIPAL_NAME 183 -+#define OID_STRONGSWAN 186 -+#define OID_TCGID 193 -+#define OID_AUTHORITY_INFO_ACCESS 198 -+#define OID_IP_ADDR_BLOCKS 200 -+#define OID_POLICY_QUALIFIER_CPS 202 -+#define OID_POLICY_QUALIFIER_UNOTICE 203 -+#define OID_SERVER_AUTH 205 -+#define OID_CLIENT_AUTH 206 -+#define OID_OCSP_SIGNING 213 -+#define OID_XMPP_ADDR 215 -+#define OID_AUTHENTICATION_INFO 217 -+#define OID_ACCESS_IDENTITY 218 -+#define OID_CHARGING_IDENTITY 219 -+#define OID_GROUP 220 -+#define OID_OCSP 223 -+#define OID_BASIC 224 -+#define OID_NONCE 225 -+#define OID_CRL 226 -+#define OID_RESPONSE 227 -+#define OID_NO_CHECK 228 -+#define OID_ARCHIVE_CUTOFF 229 -+#define OID_SERVICE_LOCATOR 230 -+#define OID_CA_ISSUERS 231 -+#define OID_IKE_INTERMEDIATE 236 -+#define OID_DES_CBC 240 -+#define OID_SHA1 241 -+#define OID_SHA1_WITH_RSA_OIW 242 -+#define OID_ECGDSA_PUBKEY 261 -+#define OID_ECGDSA_SIG_WITH_RIPEMD160 264 -+#define OID_ECGDSA_SIG_WITH_SHA1 265 -+#define OID_ECGDSA_SIG_WITH_SHA224 266 -+#define OID_ECGDSA_SIG_WITH_SHA256 267 -+#define OID_ECGDSA_SIG_WITH_SHA384 268 -+#define OID_ECGDSA_SIG_WITH_SHA512 269 -+#define OID_SECT163K1 292 -+#define OID_SECT163R1 293 -+#define OID_SECT239K1 294 -+#define OID_SECT113R1 295 -+#define OID_SECT113R2 296 -+#define OID_SECT112R1 297 -+#define OID_SECT112R2 298 -+#define OID_SECT160R1 299 -+#define OID_SECT160K1 300 -+#define OID_SECT256K1 301 -+#define OID_SECT163R2 302 -+#define OID_SECT283K1 303 -+#define OID_SECT283R1 304 -+#define OID_SECT131R1 305 -+#define OID_SECT131R2 306 -+#define OID_SECT193R1 307 -+#define OID_SECT193R2 308 -+#define OID_SECT233K1 309 -+#define OID_SECT233R1 310 -+#define OID_SECT128R1 311 -+#define OID_SECT128R2 312 -+#define OID_SECT160R2 313 -+#define OID_SECT192K1 314 -+#define OID_SECT224K1 315 -+#define OID_SECT224R1 316 -+#define OID_SECT384R1 317 -+#define OID_SECT521R1 318 -+#define OID_SECT409K1 319 -+#define OID_SECT409R1 320 -+#define OID_SECT571K1 321 -+#define OID_SECT571R1 322 -+#define OID_AES128_CBC 331 -+#define OID_AES128_GCM 332 -+#define OID_AES128_CCM 333 -+#define OID_AES192_CBC 334 -+#define OID_AES192_GCM 335 -+#define OID_AES192_CCM 336 -+#define OID_AES256_CBC 337 -+#define OID_AES256_GCM 338 -+#define OID_AES256_CCM 339 -+#define OID_SHA256 341 -+#define OID_SHA384 342 -+#define OID_SHA512 343 -+#define OID_SHA224 344 -+#define OID_NS_REVOCATION_URL 350 -+#define OID_NS_CA_REVOCATION_URL 351 -+#define OID_NS_CA_POLICY_URL 352 -+#define OID_NS_COMMENT 353 -+#define OID_EMPLOYEE_NUMBER 356 -+#define OID_PKI_MESSAGE_TYPE 362 -+#define OID_PKI_STATUS 363 -+#define OID_PKI_FAIL_INFO 364 -+#define OID_PKI_SENDER_NONCE 365 -+#define OID_PKI_RECIPIENT_NONCE 366 -+#define OID_PKI_TRANS_ID 367 -+#define OID_TPM_MANUFACTURER 373 -+#define OID_TPM_MODEL 374 -+#define OID_TPM_VERSION 375 -+#define OID_TPM_ID_LABEL 376 -+ -+#define OID_MAX 377 -+ -+#endif /* OID_H_ */ -diff --git a/efitools/lib/asn1/oid.pl b/efitools/lib/asn1/oid.pl -new file mode 100644 -index 0000000..ed26feb ---- /dev/null -+++ b/efitools/lib/asn1/oid.pl -@@ -0,0 +1,134 @@ -+#!/usr/bin/perl -+# Generates oid.h and oid.c out of oid.txt -+# -+# Copyright (C) 2003-2008 Andreas Steffen -+# Hochschule fuer Technik Rapperswil -+# -+# This program is free software; you can redistribute it and/or modify it -+# under the terms of the GNU General Public License as published by the -+# Free Software Foundation; either version 2 of the License, or (at your -+# option) any later version. See . -+# -+# This program is distributed in the hope that it will be useful, but -+# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -+# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -+# for more details. -+# -+ -+$copyright="Copyright (C) 2003-2008 Andreas Steffen, Hochschule fuer Technik Rapperswil"; -+$automatic="This file has been automatically generated by the script oid.pl"; -+$warning="Do not edit manually!"; -+ -+print "oid.pl generating oid.h and oid.c\n"; -+ -+# Generate oid.h -+ -+open(OID_H, ">oid.h") -+ or die "could not open 'oid.h': $!"; -+ -+print OID_H "/* Object identifiers (OIDs) used by strongSwan\n", -+ " * ", $copyright, "\n", -+ " * \n", -+ " * ", $automatic, "\n", -+ " * ", $warning, "\n", -+ " */\n\n", -+ "#include \n\n", -+ "#ifndef OID_H_\n", -+ "#define OID_H_\n\n", -+ "typedef struct {\n", -+ " u_char octet;\n", -+ " u_int next;\n", -+ " u_int down;\n", -+ " u_int level;\n", -+ " const u_char *name;\n", -+ "} oid_t;\n", -+ "\n", -+ "extern const oid_t oid_names[];\n", -+ "\n", -+ "#define OID_UNKNOWN -1\n"; -+ -+# parse oid.txt -+ -+open(SRC, ") -+{ -+ $line =~ m/( *?)(0x\w{2})\s+(".*?")[ \t]*?([\w_]*?)\Z/; -+ -+ @order[$counter] = length($1); -+ @octet[$counter] = $2; -+ @name[$counter] = $3; -+ -+ if (length($1) > $max_order) -+ { -+ $max_order = length($1); -+ } -+ if (length($3) > $max_name) -+ { -+ $max_name = length($3); -+ } -+ if (length($4) > 0) -+ { -+ printf OID_H "#define %s%s%d\n", $4, "\t" x ((39-length($4))/4), $counter; -+ } -+ $counter++; -+} -+ -+printf OID_H "\n#define OID_MAX%s%d\n", "\t" x 8, $counter; -+ -+print OID_H "\n#endif /* OID_H_ */\n"; -+ -+close SRC; -+close OID_H; -+ -+# Generate oid.c -+ -+open(OID_C, ">oid.c") -+ or die "could not open 'oid.c': $!"; -+ -+print OID_C "/* List of some useful object identifiers (OIDs)\n", -+ " * ", $copyright, "\n", -+ " * \n", -+ " * ", $automatic, "\n", -+ " * ", $warning, "\n", -+ " */\n", -+ "\n", -+ "#include \n", -+ "\n", -+ "#include \"oid.h\"\n", -+ "\n", -+ "const oid_t oid_names[] = {\n"; -+ -+for ($c = 0; $c < $counter; $c++) -+{ -+ $next = 0; -+ -+ for ($d = $c+1; $d < $counter && @order[$d] >= @order[$c]; $d++) -+ { -+ if (@order[$d] == @order[$c]) -+ { -+ @next[$c] = $d; -+ last; -+ } -+ } -+ -+ printf OID_C " {%s%s,%s%3d, %d, %2d, %s%s}%s /* %3d */\n" -+ ,' ' x @order[$c] -+ , @octet[$c] -+ , ' ' x (1 + $max_order - @order[$c]) -+ , @next[$c] -+ , @order[$c+1] > @order[$c] -+ , @order[$c] / 2 -+ , @name[$c] -+ , ' ' x ($max_name - length(@name[$c])) -+ , $c != $counter-1 ? "," : " " -+ , $c; -+} -+ -+print OID_C "};\n" ; -+close OID_C; -diff --git a/efitools/lib/asn1/oid.txt b/efitools/lib/asn1/oid.txt -new file mode 100644 -index 0000000..51a29eb ---- /dev/null -+++ b/efitools/lib/asn1/oid.txt -@@ -0,0 +1,377 @@ -+0x02 "ITU-T Administration" -+ 0x82 "" -+ 0x06 "Germany ITU-T member" -+ 0x01 "Deutsche Telekom AG" -+ 0x0A "" -+ 0x07 "" -+ 0x14 "ND" OID_NAME_DISTINGUISHER -+0x09 "data" -+ 0x92 "" -+ 0x26 "" -+ 0x89 "" -+ 0x93 "" -+ 0xF2 "" -+ 0x2C "" -+ 0x64 "pilot" -+ 0x01 "pilotAttributeType" -+ 0x01 "UID" OID_PILOT_USERID -+ 0x19 "DC" OID_PILOT_DOMAIN_COMPONENT -+0x55 "X.500" -+ 0x04 "X.509" -+ 0x03 "CN" OID_COMMON_NAME -+ 0x04 "S" OID_SURNAME -+ 0x05 "SN" OID_SERIAL_NUMBER -+ 0x06 "C" OID_COUNTRY -+ 0x07 "L" OID_LOCALITY -+ 0x08 "ST" OID_STATE_OR_PROVINCE -+ 0x0A "O" OID_ORGANIZATION -+ 0x0B "OU" OID_ORGANIZATION_UNIT -+ 0x0C "T" OID_TITLE -+ 0x0D "D" OID_DESCRIPTION -+ 0x24 "userCertificate" OID_USER_CERTIFICATE -+ 0x29 "N" OID_NAME -+ 0x2A "G" OID_GIVEN_NAME -+ 0x2B "I" OID_INITIALS -+ 0x2D "ID" OID_UNIQUE_IDENTIFIER -+ 0x2E "dnQualifier" OID_DN_QUALIFIER -+ 0x48 "role" OID_ROLE -+ 0x1D "id-ce" -+ 0x09 "subjectDirectoryAttrs" -+ 0x0E "subjectKeyIdentifier" OID_SUBJECT_KEY_ID -+ 0x0F "keyUsage" OID_KEY_USAGE -+ 0x10 "privateKeyUsagePeriod" -+ 0x11 "subjectAltName" OID_SUBJECT_ALT_NAME -+ 0x12 "issuerAltName" -+ 0x13 "basicConstraints" OID_BASIC_CONSTRAINTS -+ 0x14 "crlNumber" OID_CRL_NUMBER -+ 0x15 "reasonCode" OID_CRL_REASON_CODE -+ 0x17 "holdInstructionCode" -+ 0x18 "invalidityDate" -+ 0x1B "deltaCrlIndicator" OID_DELTA_CRL_INDICATOR -+ 0x1C "issuingDistributionPoint" -+ 0x1D "certificateIssuer" -+ 0x1E "nameConstraints" OID_NAME_CONSTRAINTS -+ 0x1F "crlDistributionPoints" OID_CRL_DISTRIBUTION_POINTS -+ 0x20 "certificatePolicies" OID_CERTIFICATE_POLICIES -+ 0x00 "anyPolicy" OID_ANY_POLICY -+ 0x21 "policyMappings" OID_POLICY_MAPPINGS -+ 0x23 "authorityKeyIdentifier" OID_AUTHORITY_KEY_ID -+ 0x24 "policyConstraints" OID_POLICY_CONSTRAINTS -+ 0x25 "extendedKeyUsage" OID_EXTENDED_KEY_USAGE -+ 0x00 "anyExtendedKeyUsage" -+ 0x2E "freshestCRL" OID_FRESHEST_CRL -+ 0x36 "inhibitAnyPolicy" OID_INHIBIT_ANY_POLICY -+ 0x37 "targetInformation" OID_TARGET_INFORMATION -+ 0x38 "noRevAvail" OID_NO_REV_AVAIL -+0x2A "" -+ 0x83 "" -+ 0x08 "jp" -+ 0x8C "" -+ 0x9A "" -+ 0x4B "" -+ 0x3D "" -+ 0x01 "security" -+ 0x01 "algorithm" -+ 0x01 "symm-encryption-alg" -+ 0x02 "camellia128-cbc" OID_CAMELLIA128_CBC -+ 0x03 "camellia192-cbc" OID_CAMELLIA192_CBC -+ 0x04 "camellia256-cbc" OID_CAMELLIA256_CBC -+ 0x86 "" -+ 0x48 "us" -+ 0x86 "" -+ 0xF6 "" -+ 0x7D "NortelNetworks" -+ 0x07 "Entrust" -+ 0x41 "nsn-ce" -+ 0x00 "entrustVersInfo" -+ 0xF7 "" -+ 0x0D "RSADSI" -+ 0x01 "PKCS" -+ 0x01 "PKCS-1" -+ 0x01 "rsaEncryption" OID_RSA_ENCRYPTION -+ 0x02 "md2WithRSAEncryption" OID_MD2_WITH_RSA -+ 0x04 "md5WithRSAEncryption" OID_MD5_WITH_RSA -+ 0x05 "sha-1WithRSAEncryption" OID_SHA1_WITH_RSA -+ 0x07 "id-RSAES-OAEP" OID_RSAES_OAEP -+ 0x09 "id-pSpecified" -+ 0x0B "sha256WithRSAEncryption" OID_SHA256_WITH_RSA -+ 0x0C "sha384WithRSAEncryption" OID_SHA384_WITH_RSA -+ 0x0D "sha512WithRSAEncryption" OID_SHA512_WITH_RSA -+ 0x0E "sha224WithRSAEncryption" OID_SHA224_WITH_RSA -+ 0x05 "PKCS-5" -+ 0x03 "pbeWithMD5AndDES-CBC" OID_PBE_MD5_DES_CBC -+ 0x0A "pbeWithSHA1AndDES-CBC" OID_PBE_SHA1_DES_CBC -+ 0x0C "id-PBKDF2" OID_PBKDF2 -+ 0x0D "id-PBES2" OID_PBES2 -+ 0x07 "PKCS-7" -+ 0x01 "data" OID_PKCS7_DATA -+ 0x02 "signedData" OID_PKCS7_SIGNED_DATA -+ 0x03 "envelopedData" OID_PKCS7_ENVELOPED_DATA -+ 0x04 "signedAndEnvelopedData" OID_PKCS7_SIGNED_ENVELOPED_DATA -+ 0x05 "digestedData" OID_PKCS7_DIGESTED_DATA -+ 0x06 "encryptedData" OID_PKCS7_ENCRYPTED_DATA -+ 0x09 "PKCS-9" -+ 0x01 "E" OID_EMAIL_ADDRESS -+ 0x02 "unstructuredName" OID_UNSTRUCTURED_NAME -+ 0x03 "contentType" OID_PKCS9_CONTENT_TYPE -+ 0x04 "messageDigest" OID_PKCS9_MESSAGE_DIGEST -+ 0x05 "signingTime" OID_PKCS9_SIGNING_TIME -+ 0x06 "counterSignature" -+ 0x07 "challengePassword" OID_CHALLENGE_PASSWORD -+ 0x08 "unstructuredAddress" OID_UNSTRUCTURED_ADDRESS -+ 0x0E "extensionRequest" OID_EXTENSION_REQUEST -+ 0x0F "S/MIME Capabilities" -+ 0x02 "digestAlgorithm" -+ 0x02 "md2" OID_MD2 -+ 0x05 "md5" OID_MD5 -+ 0x03 "encryptionAlgorithm" -+ 0x07 "3des-ede-cbc" OID_3DES_EDE_CBC -+ 0xCE "" -+ 0x3D "ansi-X9-62" -+ 0x02 "id-publicKeyType" -+ 0x01 "id-ecPublicKey" OID_EC_PUBLICKEY -+ 0x03 "ellipticCurve" -+ 0x00 "c-TwoCurve" -+ 0x01 "c2pnb163v1" OID_C2PNB163V1 -+ 0x02 "c2pnb163v2" OID_C2PNB163V2 -+ 0x03 "c2pnb163v3" OID_C2PNB163V3 -+ 0x04 "c2pnb176w1" OID_C2PNB176W1 -+ 0x05 "c2tnb191v1" OID_C2PNB191V1 -+ 0x06 "c2tnb191v2" OID_C2PNB191V2 -+ 0x07 "c2tnb191v3" OID_C2PNB191V3 -+ 0x08 "c2onb191v4" OID_C2PNB191V4 -+ 0x09 "c2onb191v5" OID_C2PNB191V5 -+ 0x0A "c2pnb208w1" OID_C2PNB208W1 -+ 0x0B "c2tnb239v1" OID_C2PNB239V1 -+ 0x0C "c2tnb239v2" OID_C2PNB239V2 -+ 0x0D "c2tnb239v3" OID_C2PNB239V3 -+ 0x0E "c2onb239v4" OID_C2PNB239V4 -+ 0x0F "c2onb239v5" OID_C2PNB239V5 -+ 0x10 "c2pnb272w1" OID_C2PNB272W1 -+ 0x11 "c2pnb304w1" OID_C2PNB304W1 -+ 0x12 "c2tnb359v1" OID_C2PNB359V1 -+ 0x13 "c2pnb368w1" OID_C2PNB368W1 -+ 0x14 "c2tnb431r1" OID_C2PNB431R1 -+ 0x01 "primeCurve" -+ 0x01 "prime192v1" OID_PRIME192V1 -+ 0x02 "prime192v2" OID_PRIME192V2 -+ 0x03 "prime192v3" OID_PRIME192V3 -+ 0x04 "prime239v1" OID_PRIME239V1 -+ 0x05 "prime239v2" OID_PRIME239V2 -+ 0x06 "prime239v3" OID_PRIME239V3 -+ 0x07 "prime256v1" OID_PRIME256V1 -+ 0x04 "id-ecSigType" -+ 0x01 "ecdsa-with-SHA1" OID_ECDSA_WITH_SHA1 -+ 0x03 "ecdsa-with-Specified" -+ 0x01 "ecdsa-with-SHA224" OID_ECDSA_WITH_SHA224 -+ 0x02 "ecdsa-with-SHA256" OID_ECDSA_WITH_SHA256 -+ 0x03 "ecdsa-with-SHA384" OID_ECDSA_WITH_SHA384 -+ 0x04 "ecdsa-with-SHA512" OID_ECDSA_WITH_SHA512 -+0x2B "" -+ 0x06 "dod" -+ 0x01 "internet" -+ 0x04 "private" -+ 0x01 "enterprise" -+ 0x82 "" -+ 0x37 "Microsoft" -+ 0x0A "" -+ 0x03 "" -+ 0x03 "msSGC" -+ 0x04 "msEncryptingFileSystem" -+ 0x14 "msEnrollmentInfrastructure" -+ 0x02 "msCertificateTypeExtension" -+ 0x02 "msSmartcardLogon" -+ 0x03 "msUPN" OID_USER_PRINCIPAL_NAME -+ 0xA0 "" -+ 0x2A "ITA" -+ 0x01 "strongSwan" OID_STRONGSWAN -+ 0x89 "" -+ 0x31 "" -+ 0x01 "" -+ 0x01 "" -+ 0x02 "" -+ 0x02 "" -+ 0x4B "TCGID" OID_TCGID -+ 0x05 "security" -+ 0x05 "mechanisms" -+ 0x07 "id-pkix" -+ 0x01 "id-pe" -+ 0x01 "authorityInfoAccess" OID_AUTHORITY_INFO_ACCESS -+ 0x03 "qcStatements" -+ 0x07 "ipAddrBlocks" OID_IP_ADDR_BLOCKS -+ 0x02 "id-qt" -+ 0x01 "cps" OID_POLICY_QUALIFIER_CPS -+ 0x02 "unotice" OID_POLICY_QUALIFIER_UNOTICE -+ 0x03 "id-kp" -+ 0x01 "serverAuth" OID_SERVER_AUTH -+ 0x02 "clientAuth" OID_CLIENT_AUTH -+ 0x03 "codeSigning" -+ 0x04 "emailProtection" -+ 0x05 "ipsecEndSystem" -+ 0x06 "ipsecTunnel" -+ 0x07 "ipsecUser" -+ 0x08 "timeStamping" -+ 0x09 "ocspSigning" OID_OCSP_SIGNING -+ 0x08 "id-otherNames" -+ 0x05 "xmppAddr" OID_XMPP_ADDR -+ 0x0A "id-aca" -+ 0x01 "authenticationInfo" OID_AUTHENTICATION_INFO -+ 0x02 "accessIdentity" OID_ACCESS_IDENTITY -+ 0x03 "chargingIdentity" OID_CHARGING_IDENTITY -+ 0x04 "group" OID_GROUP -+ 0x0B "subjectInfoAccess" -+ 0x30 "id-ad" -+ 0x01 "ocsp" OID_OCSP -+ 0x01 "basic" OID_BASIC -+ 0x02 "nonce" OID_NONCE -+ 0x03 "crl" OID_CRL -+ 0x04 "response" OID_RESPONSE -+ 0x05 "noCheck" OID_NO_CHECK -+ 0x06 "archiveCutoff" OID_ARCHIVE_CUTOFF -+ 0x07 "serviceLocator" OID_SERVICE_LOCATOR -+ 0x02 "caIssuers" OID_CA_ISSUERS -+ 0x03 "timeStamping" -+ 0x05 "caRepository" -+ 0x08 "ipsec" -+ 0x02 "certificate" -+ 0x02 "iKEIntermediate" OID_IKE_INTERMEDIATE -+ 0x0E "oiw" -+ 0x03 "secsig" -+ 0x02 "algorithms" -+ 0x07 "des-cbc" OID_DES_CBC -+ 0x1A "sha-1" OID_SHA1 -+ 0x1D "sha-1WithRSASignature" OID_SHA1_WITH_RSA_OIW -+ 0x24 "TeleTrusT" -+ 0x03 "algorithm" -+ 0x03 "signatureAlgorithm" -+ 0x01 "rsaSignature" -+ 0x02 "rsaSigWithripemd160" -+ 0x03 "rsaSigWithripemd128" -+ 0x04 "rsaSigWithripemd256" -+ 0x02 "ecSign" -+ 0x01 "ecSignWithsha1" -+ 0x02 "ecSignWithripemd160" -+ 0x03 "ecSignWithmd2" -+ 0x04 "ecSignWithmd5" -+ 0x05 "ttt-ecg" -+ 0x01 "fieldType" -+ 0x01 "characteristictwoField" -+ 0x01 "basisType" -+ 0x01 "ipBasis" -+ 0x02 "keyType" -+ 0x01 "ecgPublicKey" OID_ECGDSA_PUBKEY -+ 0x03 "curve" -+ 0x04 "signatures" -+ 0x01 "ecgdsa-with-RIPEMD160" OID_ECGDSA_SIG_WITH_RIPEMD160 -+ 0x02 "ecgdsa-with-SHA1" OID_ECGDSA_SIG_WITH_SHA1 -+ 0x03 "ecgdsa-with-SHA224" OID_ECGDSA_SIG_WITH_SHA224 -+ 0x04 "ecgdsa-with-SHA256" OID_ECGDSA_SIG_WITH_SHA256 -+ 0x05 "ecgdsa-with-SHA384" OID_ECGDSA_SIG_WITH_SHA384 -+ 0x06 "ecgdsa-with-SHA512" OID_ECGDSA_SIG_WITH_SHA512 -+ 0x05 "module" -+ 0x01 "1" -+ 0x08 "ecStdCurvesAndGeneration" -+ 0x01 "ellipticCurve" -+ 0x01 "versionOne" -+ 0x01 "brainpoolP160r1" -+ 0x02 "brainpoolP160t1" -+ 0x03 "brainpoolP192r1" -+ 0x04 "brainpoolP192t1" -+ 0x05 "brainpoolP224r1" -+ 0x06 "brainpoolP224t1" -+ 0x07 "brainpoolP256r1" -+ 0x08 "brainpoolP256t1" -+ 0x09 "brainpoolP320r1" -+ 0x0A "brainpoolP320t1" -+ 0x0B "brainpoolP384r1" -+ 0x0C "brainpoolP384t1" -+ 0x0D "brainpoolP512r1" -+ 0x0E "brainpoolP512t1" -+ 0x81 "" -+ 0x04 "Certicom" -+ 0x00 "curve" -+ 0x01 "sect163k1" OID_SECT163K1 -+ 0x02 "sect163r1" OID_SECT163R1 -+ 0x03 "sect239k1" OID_SECT239K1 -+ 0x04 "sect113r1" OID_SECT113R1 -+ 0x05 "sect113r2" OID_SECT113R2 -+ 0x06 "secp112r1" OID_SECT112R1 -+ 0x07 "secp112r2" OID_SECT112R2 -+ 0x08 "secp160r1" OID_SECT160R1 -+ 0x09 "secp160k1" OID_SECT160K1 -+ 0x0A "secp256k1" OID_SECT256K1 -+ 0x0F "sect163r2" OID_SECT163R2 -+ 0x10 "sect283k1" OID_SECT283K1 -+ 0x11 "sect283r1" OID_SECT283R1 -+ 0x16 "sect131r1" OID_SECT131R1 -+ 0x17 "sect131r2" OID_SECT131R2 -+ 0x18 "sect193r1" OID_SECT193R1 -+ 0x19 "sect193r2" OID_SECT193R2 -+ 0x1A "sect233k1" OID_SECT233K1 -+ 0x1B "sect233r1" OID_SECT233R1 -+ 0x1C "secp128r1" OID_SECT128R1 -+ 0x1D "secp128r2" OID_SECT128R2 -+ 0x1E "secp160r2" OID_SECT160R2 -+ 0x1F "secp192k1" OID_SECT192K1 -+ 0x20 "secp224k1" OID_SECT224K1 -+ 0x21 "secp224r1" OID_SECT224R1 -+ 0x22 "secp384r1" OID_SECT384R1 -+ 0x23 "secp521r1" OID_SECT521R1 -+ 0x24 "sect409k1" OID_SECT409K1 -+ 0x25 "sect409r1" OID_SECT409R1 -+ 0x26 "sect571k1" OID_SECT571K1 -+ 0x27 "sect571r1" OID_SECT571R1 -+0x60 "" -+ 0x86 "" -+ 0x48 "" -+ 0x01 "organization" -+ 0x65 "gov" -+ 0x03 "csor" -+ 0x04 "nistalgorithm" -+ 0x01 "aes" -+ 0x02 "id-aes128-CBC" OID_AES128_CBC -+ 0x06 "id-aes128-GCM" OID_AES128_GCM -+ 0x07 "id-aes128-CCM" OID_AES128_CCM -+ 0x16 "id-aes192-CBC" OID_AES192_CBC -+ 0x1A "id-aes192-GCM" OID_AES192_GCM -+ 0x1B "id-aes192-CCM" OID_AES192_CCM -+ 0x2A "id-aes256-CBC" OID_AES256_CBC -+ 0x2E "id-aes256-GCM" OID_AES256_GCM -+ 0x2F "id-aes256-CCM" OID_AES256_CCM -+ 0x02 "hashalgs" -+ 0x01 "id-SHA-256" OID_SHA256 -+ 0x02 "id-SHA-384" OID_SHA384 -+ 0x03 "id-SHA-512" OID_SHA512 -+ 0x04 "id-SHA-224" OID_SHA224 -+ 0x86 "" -+ 0xf8 "" -+ 0x42 "netscape" -+ 0x01 "" -+ 0x01 "nsCertType" -+ 0x03 "nsRevocationUrl" OID_NS_REVOCATION_URL -+ 0x04 "nsCaRevocationUrl" OID_NS_CA_REVOCATION_URL -+ 0x08 "nsCaPolicyUrl" OID_NS_CA_POLICY_URL -+ 0x0d "nsComment" OID_NS_COMMENT -+ 0x03 "directory" -+ 0x01 "" -+ 0x03 "employeeNumber" OID_EMPLOYEE_NUMBER -+ 0x04 "policy" -+ 0x01 "nsSGC" -+ 0x45 "verisign" -+ 0x01 "pki" -+ 0x09 "attributes" -+ 0x02 "messageType" OID_PKI_MESSAGE_TYPE -+ 0x03 "pkiStatus" OID_PKI_STATUS -+ 0x04 "failInfo" OID_PKI_FAIL_INFO -+ 0x05 "senderNonce" OID_PKI_SENDER_NONCE -+ 0x06 "recipientNonce" OID_PKI_RECIPIENT_NONCE -+ 0x07 "transID" OID_PKI_TRANS_ID -+ 0x08 "extensionReq" -+0x67 "" -+ 0x81 "" -+ 0x05 "" -+ 0x02 "tcg-attribute" -+ 0x01 "tcg-at-tpmManufacturer" OID_TPM_MANUFACTURER -+ 0x02 "tcg-at-tpmModel" OID_TPM_MODEL -+ 0x03 "tcg-at-tpmVersion" OID_TPM_VERSION -+ 0x0F "tcg-at-tpmIdLabel" OID_TPM_ID_LABEL -diff --git a/efitools/lib/asn1/test.c b/efitools/lib/asn1/test.c -new file mode 100644 -index 0000000..9e8c05f ---- /dev/null -+++ b/efitools/lib/asn1/test.c -@@ -0,0 +1,29 @@ -+#include "typedefs.h" -+ -+#include -+ -+#include -+ -+int main(int argc, char *argv[]) -+{ -+ void *buf; -+ int fd; -+ struct stat st; -+ char out[512]; -+ -+ fd = open(argv[1], O_RDONLY); -+ if (fd<0) { -+ fprintf(stderr, "Failed to open file %s\n", argv[1]); -+ perror(""); -+ exit(1); -+ } -+ fstat(fd, &st); -+ buf = malloc(st.st_size); -+ read(fd, buf, st.st_size); -+ x509_to_str(buf, st.st_size, X509_OBJ_SUBJECT, out, sizeof(out)); -+ printf("Subject: %s\n", out); -+ x509_to_str(buf, st.st_size, X509_OBJ_ISSUER, out, sizeof(out)); -+ printf("Issuer: %s\n", out); -+ -+ exit(0); -+} -diff --git a/efitools/lib/asn1/typedefs.h b/efitools/lib/asn1/typedefs.h -new file mode 100644 -index 0000000..756a629 ---- /dev/null -+++ b/efitools/lib/asn1/typedefs.h -@@ -0,0 +1,117 @@ -+#ifdef BUILD_EFI -+#include -+#include -+ -+#define malloc(x) AllocatePool(x) -+#define free FreePool -+#define strcmp(x,y) StrCmp(x,y) -+#define memset(m,c,l) ZeroMem(m,l) -+#define memcmp(x,y,z) strncmpa(x,y,z) -+#define isprint(x) (1) -+#define snprintf(s, l, f...) SPrint(s, l, L ## f) -+ -+/* STR is the native string and STRA is how to printf and ASCII string */ -+#define STR CHAR16 -+#define STRA "a" -+#define size_t UINTN -+ -+static inline void -+MEMCPY(void *dest, void *src, size_t n) -+{ -+ UINTN i; -+ char *d = dest, *s = src; -+ -+ for (i = 0; i < n; i++) -+ d[i] = s[i]; -+} -+ -+#define memcpy MEMCPY -+ -+typedef unsigned char u_char; -+ -+#else -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define STR char -+#define STRA "s" -+ -+#define FALSE 0 -+#define TRUE 1 -+ -+#endif -+ -+typedef unsigned char bool; -+typedef unsigned int u_int; -+ -+#define DBG1(s...) -+#define DBG2(s...) -+ -+/** -+ * Method declaration/definition macro, providing private and public interface. -+ * -+ * Defines a method name with this as first parameter and a return value ret, -+ * and an alias for this method with a _ prefix, having the this argument -+ * safely casted to the public interface iface. -+ * _name is provided a function pointer, but will get optimized out by GCC. -+ */ -+#define METHOD(iface, name, ret, this, ...) \ -+ static ret name(union {iface *_public; this;} \ -+ __attribute__((transparent_union)), ##__VA_ARGS__); \ -+ static typeof(name) *_##name = (typeof(name)*)name; \ -+ static ret name(this, ##__VA_ARGS__) -+ -+/** -+ * Object allocation/initialization macro, using designated initializer. -+ */ -+#define INIT(this, ...) { (this) = malloc(sizeof(*(this))); \ -+ *(this) = (typeof(*(this))){ __VA_ARGS__ }; } -+ -+/** -+ * Macro to allocate a sized type. -+ */ -+#define malloc_thing(thing) ((thing*)malloc(sizeof(thing))) -+/** -+ * Get the number of elements in an array -+ */ -+#define countof(array) (sizeof(array)/sizeof(array[0])) -+ -+/** -+ * Helper function that compares two strings for equality -+ */ -+static inline bool streq(STR *x, STR *y) -+{ -+ return strcmp(x, y) == 0; -+} -+ -+/** -+ * Macro compares two binary blobs for equality -+ */ -+#define memeq(x,y,len) (memcmp(x, y, len) == 0) -+ -+/** -+ * Call destructor of an object, if object != NULL -+ */ -+#define DESTROY_IF(obj) if (obj) (obj)->destroy(obj) -+/** -+ * Macro gives back smaller of two values. -+ */ -+#define min(x,y) ({ \ -+ typeof(x) _x = (x); \ -+ typeof(y) _y = (y); \ -+ _x < _y ? _x : _y; }) -+ -+ -+#define TIME_32_BIT_SIGNED_MAX 0x7fffffff -+#define BUF_LEN 512 -diff --git a/efitools/lib/asn1/x509.c b/efitools/lib/asn1/x509.c -new file mode 100644 -index 0000000..bb313c2 ---- /dev/null -+++ b/efitools/lib/asn1/x509.c -@@ -0,0 +1,58 @@ -+#include "typedefs.h" -+#include "identification.h" -+#include "asn1_parser.h" -+ -+/** -+ * ASN.1 definition of an X.509v3 x509_cert -+ */ -+const asn1Object_t x509_certObjects[] = { -+ { 0, "x509", ASN1_SEQUENCE, ASN1_OBJ }, /* 0 */ -+ { 1, "tbsCertificate", ASN1_SEQUENCE, ASN1_OBJ }, /* 1 */ -+ { 2, "DEFAULT v1", ASN1_CONTEXT_C_0, ASN1_DEF }, /* 2 */ -+ { 3, "version", ASN1_INTEGER, ASN1_BODY }, /* 3 */ -+ { 2, "serialNumber", ASN1_INTEGER, ASN1_BODY }, /* 4 */ -+ { 2, "signature", ASN1_EOC, ASN1_RAW }, /* 5 */ -+ { 2, "issuer", ASN1_SEQUENCE, ASN1_OBJ }, /* 6 */ -+ { 2, "validity", ASN1_SEQUENCE, ASN1_NONE }, /* 7 */ -+ { 3, "notBefore", ASN1_EOC, ASN1_RAW }, /* 8 */ -+ { 3, "notAfter", ASN1_EOC, ASN1_RAW }, /* 9 */ -+ { 2, "subject", ASN1_SEQUENCE, ASN1_OBJ }, /* 10 */ -+ { 2, "subjectPublicKeyInfo",ASN1_SEQUENCE, ASN1_RAW }, /* 11 */ -+ { 2, "issuerUniqueID", ASN1_CONTEXT_C_1, ASN1_OPT }, /* 12 */ -+ { 2, "end opt", ASN1_EOC, ASN1_END }, /* 13 */ -+ { 2, "subjectUniqueID", ASN1_CONTEXT_C_2, ASN1_OPT }, /* 14 */ -+ { 2, "end opt", ASN1_EOC, ASN1_END }, /* 15 */ -+ { 2, "optional extensions", ASN1_CONTEXT_C_3, ASN1_OPT }, /* 16 */ -+ { 3, "extensions", ASN1_SEQUENCE, ASN1_LOOP }, /* 17 */ -+ { 4, "extension", ASN1_SEQUENCE, ASN1_NONE }, /* 18 */ -+ { 5, "extnID", ASN1_OID, ASN1_BODY }, /* 19 */ -+ { 5, "critical", ASN1_BOOLEAN, ASN1_DEF|ASN1_BODY }, /* 20 */ -+ { 5, "extnValue", ASN1_OCTET_STRING, ASN1_BODY }, /* 21 */ -+ { 3, "end loop", ASN1_EOC, ASN1_END }, /* 22 */ -+ { 2, "end opt", ASN1_EOC, ASN1_END }, /* 23 */ -+ { 1, "signatureAlgorithm", ASN1_EOC, ASN1_RAW }, /* 24 */ -+ { 1, "signatureValue", ASN1_BIT_STRING, ASN1_BODY }, /* 25 */ -+ { 0, "exit", ASN1_EOC, ASN1_EXIT } -+}; -+ -+int -+x509_to_str(void *cert, int cert_size, int tag, -+ STR *buf, int len) -+{ -+ asn1_parser_t *parser; -+ chunk_t object, blob; -+ int objectID; -+ -+ blob = chunk_create(cert, cert_size); -+ -+ parser = asn1_parser_create(x509_certObjects, blob); -+ parser->set_top_level(parser, 0); -+ -+ snprintf(buf, sizeof(buf), "MISPARSE"); -+ -+ while (parser->iterate(parser, &objectID, &object)) { -+ if (objectID == tag) -+ dntoa(object, buf, len); -+ } -+ return 0; -+} -diff --git a/efitools/lib/configtable.c b/efitools/lib/configtable.c -new file mode 100644 -index 0000000..735ce8f ---- /dev/null -+++ b/efitools/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/efitools/lib/console.c b/efitools/lib/console.c -new file mode 100644 -index 0000000..8e209e1 ---- /dev/null -+++ b/efitools/lib/console.c -@@ -0,0 +1,413 @@ -+/* -+ * 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; -+} -+ -+int -+console_check_for_keystroke(CHAR16 key) -+{ -+ EFI_INPUT_KEY k; -+ EFI_STATUS status; -+ /* check for both upper and lower cases */ -+ CHAR16 key_u = key & ~0x20, key_l = key | 0x20; -+ -+ /* the assumption is the user has been holding the key down so empty -+ * the key buffer at this point because auto repeat may have filled -+ * it */ -+ -+ for(;;) { -+ status = uefi_call_wrapper(ST->ConIn->ReadKeyStroke, 2, ST->ConIn, &k); -+ -+ if (status != EFI_SUCCESS) -+ break; -+ -+ if (key_u == k.UnicodeChar || key_l == k.UnicodeChar) -+ return 1; -+ } -+ return 0; -+} -+ -+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); -+} -+ -+#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/efitools/lib/execute.c b/efitools/lib/execute.c -new file mode 100644 -index 0000000..8d726eb ---- /dev/null -+++ b/efitools/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/efitools/lib/guid.c b/efitools/lib/guid.c -new file mode 100644 -index 0000000..e6471a5 ---- /dev/null -+++ b/efitools/lib/guid.c -@@ -0,0 +1,57 @@ -+/* -+ * 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; -+} -+ -+int str_to_guid(const char *str, EFI_GUID *guid) -+{ -+ int args; -+ args = 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); -+ -+ return args != 11; -+} -+ -+int -+compare_guid(EFI_GUID *g1, EFI_GUID *g2) -+{ -+ return memcmp(g1, g2, sizeof(*g1)); -+} -+#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/efitools/lib/pecoff.c b/efitools/lib/pecoff.c -new file mode 100644 -index 0000000..9cd091c ---- /dev/null -+++ b/efitools/lib/pecoff.c -@@ -0,0 +1,391 @@ -+/* -+ * Code Copyright 2012 Red Hat, Inc -+ * -+ * Functions cut and pasted from -+ * -+ * git://github.com/mjg59/shim.git -+ * -+ * 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. -+ * -+ * --- -+ * -+ * This file is a functional simplification of Original code from TianoCore -+ * (http://tianocore.sf.net) -+ * -+ * MdePkg/Library/BasePeCoffLib/BasePeCoff.c -+ * -+ * Copyright (c) 2006 - 2012, 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. -+ */ -+ -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#ifndef BUILD_EFI -+#define Print(...) do { } while(0) -+#define AllocatePool(x) malloc(x) -+#define CopyMem(d, s, l) memcpy(d, s, l) -+#define ZeroMem(s, l) memset(s, 0, l) -+#endif -+ -+EFI_STATUS -+pecoff_read_header(PE_COFF_LOADER_IMAGE_CONTEXT *context, void *data) -+{ -+ EFI_IMAGE_DOS_HEADER *DosHdr = data; -+ EFI_IMAGE_OPTIONAL_HEADER_UNION *PEHdr = data; -+ -+ if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) -+ PEHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)((char *)data + DosHdr->e_lfanew); -+ -+ if (PEHdr->Te.Signature != EFI_IMAGE_NT_SIGNATURE) { -+ Print(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"); -+ return EFI_UNSUPPORTED; -+ } -+ -+ if (PEHdr->Pe32.OptionalHeader.Magic != EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) { -+ Print(L"Only 64-bit images supported\n"); -+ return EFI_UNSUPPORTED; -+ } -+ -+ context->PEHdr = PEHdr; -+ context->ImageAddress = PEHdr->Pe32Plus.OptionalHeader.ImageBase; -+ context->ImageSize = (UINT64)PEHdr->Pe32Plus.OptionalHeader.SizeOfImage; -+ context->SizeOfHeaders = PEHdr->Pe32Plus.OptionalHeader.SizeOfHeaders; -+ context->EntryPoint = PEHdr->Pe32Plus.OptionalHeader.AddressOfEntryPoint; -+ context->RelocDir = &PEHdr->Pe32Plus.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC]; -+ context->NumberOfRvaAndSizes = PEHdr->Pe32Plus.OptionalHeader.NumberOfRvaAndSizes; -+ context->NumberOfSections = PEHdr->Pe32.FileHeader.NumberOfSections; -+ context->FirstSection = (EFI_IMAGE_SECTION_HEADER *)((char *)PEHdr + PEHdr->Pe32.FileHeader.SizeOfOptionalHeader + sizeof(UINT32) + sizeof(EFI_IMAGE_FILE_HEADER)); -+ context->SecDir = (EFI_IMAGE_DATA_DIRECTORY *) &PEHdr->Pe32Plus.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]; -+ -+ if (context->SecDir->VirtualAddress >= context->ImageSize) { -+ Print(L"Malformed security header\n"); -+ return EFI_INVALID_PARAMETER; -+ } -+ -+ return EFI_SUCCESS; -+} -+ -+EFI_STATUS -+pecoff_image_layout(PE_COFF_LOADER_IMAGE_CONTEXT *context, void **data) -+{ -+ void *buffer = AllocatePool(context->ImageSize); -+ EFI_IMAGE_SECTION_HEADER *s; -+ int i, size; -+ char *base, *end; -+ -+ CopyMem(buffer, *data, context->SizeOfHeaders); -+ -+ for (i = 0; i < context->NumberOfSections; i++) { -+ s = &context->FirstSection[i]; -+ size = s->Misc.VirtualSize; -+ -+ if (size > s->SizeOfRawData) -+ size = s->SizeOfRawData; -+ base = pecoff_image_address(buffer, context->ImageSize, s->VirtualAddress); -+ end = pecoff_image_address(buffer, context->ImageSize, s->VirtualAddress + size - 1); -+ -+ if (!base || !end) { -+ Print(L"Invalid section size\n"); -+ return EFI_UNSUPPORTED; -+ } -+ -+ if (s->SizeOfRawData > 0) -+ CopyMem(base, *data + s->PointerToRawData, size); -+ -+ if (size < s->Misc.VirtualSize) -+ ZeroMem (base + size, s->Misc.VirtualSize - size); -+ -+ } -+ //FreePool(*data); -+ *data = buffer; -+ -+ return EFI_SUCCESS; -+} -+ -+EFI_STATUS -+pecoff_relocate(PE_COFF_LOADER_IMAGE_CONTEXT *context, void **data) -+{ -+ EFI_IMAGE_BASE_RELOCATION *RelocBase, *RelocBaseEnd; -+ UINT64 Adjust; -+ UINT16 *Reloc, *RelocEnd; -+ char *Fixup, *FixupBase, *FixupData = NULL; -+ UINT16 *Fixup16; -+ UINT32 *Fixup32; -+ UINT64 *Fixup64; -+ int size = context->ImageSize; -+ void *ImageEnd = (char *)data + size; -+ EFI_STATUS efi_status; -+ -+ efi_status = pecoff_image_layout(context, data); -+ if (efi_status != EFI_SUCCESS) { -+ Print(L"pecoff_image_layout: failed to layout image\n"); -+ return efi_status; -+ } -+ -+ context->PEHdr->Pe32Plus.OptionalHeader.ImageBase = (UINT64)*data; -+ -+ if (context->NumberOfRvaAndSizes <= EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) { -+ Print(L"Image has no relocation entry\n"); -+ return EFI_UNSUPPORTED; -+ } -+ -+ RelocBase = pecoff_image_address(*data, size, context->RelocDir->VirtualAddress); -+ RelocBaseEnd = pecoff_image_address(*data, size, context->RelocDir->VirtualAddress + context->RelocDir->Size - 1); -+ -+ if (!RelocBase || !RelocBaseEnd) { -+ Print(L"Reloc table overflows binary %d %d\n", -+ context->RelocDir->VirtualAddress, -+ context->RelocDir->VirtualAddress + context->RelocDir->Size - 1); -+ return EFI_UNSUPPORTED; -+ } -+ -+ Adjust = (UINT64)*data - context->ImageAddress; -+ -+ while (RelocBase < RelocBaseEnd) { -+ Reloc = (UINT16 *) ((char *) RelocBase + sizeof (EFI_IMAGE_BASE_RELOCATION)); -+ RelocEnd = (UINT16 *) ((char *) RelocBase + RelocBase->SizeOfBlock); -+ -+ if ((void *)RelocEnd < *data || (void *)RelocEnd > ImageEnd) { -+ Print(L"Reloc entry overflows binary\n"); -+ return EFI_UNSUPPORTED; -+ } -+ -+ FixupBase = pecoff_image_address(*data, size, RelocBase->VirtualAddress); -+ if (!FixupBase) { -+ Print(L"Invalid fixupbase\n"); -+ return EFI_UNSUPPORTED; -+ } -+ -+ while (Reloc < RelocEnd) { -+ Fixup = FixupBase + (*Reloc & 0xFFF); -+ switch ((*Reloc) >> 12) { -+ case EFI_IMAGE_REL_BASED_ABSOLUTE: -+ break; -+ -+ case EFI_IMAGE_REL_BASED_HIGH: -+ Fixup16 = (UINT16 *) Fixup; -+ *Fixup16 = (UINT16) (*Fixup16 + ((UINT16) ((UINT32) Adjust >> 16))); -+ if (FixupData != NULL) { -+ *(UINT16 *) FixupData = *Fixup16; -+ FixupData = FixupData + sizeof (UINT16); -+ } -+ break; -+ -+ case EFI_IMAGE_REL_BASED_LOW: -+ Fixup16 = (UINT16 *) Fixup; -+ *Fixup16 = (UINT16) (*Fixup16 + (UINT16) Adjust); -+ if (FixupData != NULL) { -+ *(UINT16 *) FixupData = *Fixup16; -+ FixupData = FixupData + sizeof (UINT16); -+ } -+ break; -+ -+ case EFI_IMAGE_REL_BASED_HIGHLOW: -+ Fixup32 = (UINT32 *) Fixup; -+ *Fixup32 = *Fixup32 + (UINT32) Adjust; -+ if (FixupData != NULL) { -+ FixupData = ALIGN_POINTER (FixupData, sizeof (UINT32)); -+ *(UINT32 *)FixupData = *Fixup32; -+ FixupData = FixupData + sizeof (UINT32); -+ } -+ break; -+ -+ case EFI_IMAGE_REL_BASED_DIR64: -+ Fixup64 = (UINT64 *) Fixup; -+ *Fixup64 = *Fixup64 + (UINT64) Adjust; -+ if (FixupData != NULL) { -+ FixupData = ALIGN_POINTER (FixupData, sizeof(UINT64)); -+ *(UINT64 *)(FixupData) = *Fixup64; -+ FixupData = FixupData + sizeof(UINT64); -+ } -+ break; -+ -+ default: -+ Print(L"Unknown relocation\n"); -+ return EFI_UNSUPPORTED; -+ } -+ Reloc += 1; -+ } -+ RelocBase = (EFI_IMAGE_BASE_RELOCATION *) RelocEnd; -+ } -+ -+ return EFI_SUCCESS; -+} -+ -+#ifdef BUILD_EFI -+EFI_STATUS -+pecoff_check_mok(EFI_HANDLE image, CHAR16 *name) -+{ -+ EFI_STATUS status; -+ UINT8 hash[SHA256_DIGEST_SIZE]; -+ UINT8 *data; -+ UINTN len; -+ UINT32 attr; -+ -+ /* first check is MokSBState. If we're in insecure mode, boot -+ * anyway regardless of dbx contents */ -+ status = get_variable_attr(L"MokSBState", &data, &len, -+ MOK_OWNER, &attr); -+ if (status == EFI_SUCCESS) { -+ UINT8 MokSBState = data[0]; -+ -+ FreePool(data); -+ if ((attr & EFI_VARIABLE_RUNTIME_ACCESS) == 0 -+ && MokSBState) -+ return EFI_SUCCESS; -+ } -+ -+ status = sha256_get_pecoff_digest(image, name, 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 */ -+ goto check_tmplist; -+ -+ status = get_variable_attr(L"MokList", &data, &len, MOK_OWNER, &attr); -+ if (status != EFI_SUCCESS) -+ goto check_tmplist; -+ FreePool(data); -+ -+ 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: -+ status = get_variable_attr(L"tmpHashList", &data, &len, MOK_OWNER, -+ &attr); -+ if (status == EFI_SUCCESS && attr == EFI_VARIABLE_BOOTSERVICE_ACCESS -+ && find_in_variable_esl(L"tmpHashList", MOK_OWNER, hash, -+ SHA256_DIGEST_SIZE) == EFI_SUCCESS) -+ return EFI_SUCCESS; -+ -+ return EFI_SECURITY_VIOLATION; -+} -+ -+EFI_STATUS -+pecoff_execute_checked(EFI_HANDLE image, EFI_SYSTEM_TABLE *systab, CHAR16 *name) -+{ -+ EFI_STATUS status; -+ EFI_LOADED_IMAGE *li; -+ EFI_DEVICE_PATH *loadpath = NULL; -+ CHAR16 *PathName = NULL; -+ EFI_HANDLE h; -+ EFI_FILE *file; -+ -+ status = uefi_call_wrapper(BS->HandleProtocol, 3, image, -+ &IMAGE_PROTOCOL, &li); -+ if (status != EFI_SUCCESS) -+ return status; -+ status = generate_path(name, li, &loadpath, &PathName); -+ if (status != EFI_SUCCESS) -+ return status; -+ status = uefi_call_wrapper(BS->LoadImage, 6, FALSE, image, -+ loadpath, NULL, 0, &h); -+ if (status == EFI_SECURITY_VIOLATION || status == EFI_ACCESS_DENIED) -+ status = pecoff_check_mok(image, name); -+ if (status != EFI_SUCCESS) -+ /* this will fail if signature validation fails */ -+ return status; -+ uefi_call_wrapper(BS->UnloadImage, 1, h); -+ -+ status = simple_file_open(image, name, &file, EFI_FILE_MODE_READ); -+ if (status != EFI_SUCCESS) -+ return status; -+ -+ pecoff_execute_image(file, name, image, systab); -+ simple_file_close(file); -+ -+ return status; -+} -+ -+EFI_STATUS -+pecoff_execute_image(EFI_FILE *file, CHAR16 *name, EFI_HANDLE image, -+ EFI_SYSTEM_TABLE *systab) -+{ -+ UINTN DataSize; -+ void *buffer; -+ EFI_STATUS efi_status; -+ PE_COFF_LOADER_IMAGE_CONTEXT context; -+ EFI_STATUS (EFIAPI *entry_point) (EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *system_table); -+ -+ efi_status = simple_file_read_all(file, &DataSize, &buffer); -+ if (efi_status != EFI_SUCCESS) { -+ Print(L"Failed to read %s\n", name); -+ return efi_status; -+ } -+ -+ Print(L"Read %d bytes from %s\n", DataSize, name); -+ efi_status = pecoff_read_header(&context, buffer); -+ if (efi_status != EFI_SUCCESS) { -+ Print(L"Failed to read header\n"); -+ goto out; -+ } -+ -+ efi_status = pecoff_relocate(&context, &buffer); -+ if (efi_status != EFI_SUCCESS) { -+ Print(L"Failed to relocate image\n"); -+ goto out; -+ } -+ -+ entry_point = pecoff_image_address(buffer, context.ImageSize, context.EntryPoint); -+ if (!entry_point) { -+ Print(L"Invalid entry point\n"); -+ efi_status = EFI_UNSUPPORTED; -+ goto out; -+ } -+ -+ efi_status = uefi_call_wrapper(entry_point, 2, image, systab); -+ -+ out: -+ FreePool(buffer); -+ -+ return efi_status; -+} -+#endif -diff --git a/efitools/lib/security_policy.c b/efitools/lib/security_policy.c -new file mode 100644 -index 0000000..b688763 ---- /dev/null -+++ b/efitools/lib/security_policy.c -@@ -0,0 +1,399 @@ -+/* -+ * 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; -+ /* check for security policy in write protected memory */ -+ if (security2_protocol->FileAuthentication -+ != thunk_security2_policy_authentication) -+ return EFI_ACCESS_DENIED; -+ } -+ -+ esfas = security_protocol->FileAuthenticationState; -+ security_protocol->FileAuthenticationState = -+ thunk_security_policy_authentication; -+ /* check for security policy in write protected memory */ -+ if (security_protocol->FileAuthenticationState -+ != thunk_security_policy_authentication) -+ return EFI_ACCESS_DENIED; -+ -+ 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/efitools/lib/sha256.c b/efitools/lib/sha256.c -new file mode 100644 -index 0000000..a34cab0 ---- /dev/null -+++ b/efitools/lib/sha256.c -@@ -0,0 +1,394 @@ -+/* -+ * FIPS-180-2 compliant SHA-256 implementation -+ * -+ * Copyright (C) 2001-2003 Christophe Devine -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ */ -+ -+#include -+#include -+ -+#include -+#include -+#include -+ -+#ifndef BUILD_EFI -+#define Print(...) do { } while(0) -+#define AllocatePool(x) malloc(x) -+#define CopyMem(d, s, l) memcpy(d, s, l) -+#define ZeroMem(s, l) memset(s, 0, l) -+#define FreePool(s) free(s) -+#endif -+ -+#define GET_UINT32(n,b,i) \ -+{ \ -+ (n) = ( (uint32) (b)[(i) ] << 24 ) \ -+ | ( (uint32) (b)[(i) + 1] << 16 ) \ -+ | ( (uint32) (b)[(i) + 2] << 8 ) \ -+ | ( (uint32) (b)[(i) + 3] ); \ -+} -+ -+#define PUT_UINT32(n,b,i) \ -+{ \ -+ (b)[(i) ] = (uint8) ( (n) >> 24 ); \ -+ (b)[(i) + 1] = (uint8) ( (n) >> 16 ); \ -+ (b)[(i) + 2] = (uint8) ( (n) >> 8 ); \ -+ (b)[(i) + 3] = (uint8) ( (n) ); \ -+} -+ -+void sha256_starts( sha256_context *ctx ) -+{ -+ ctx->total[0] = 0; -+ ctx->total[1] = 0; -+ -+ ctx->state[0] = 0x6A09E667; -+ ctx->state[1] = 0xBB67AE85; -+ ctx->state[2] = 0x3C6EF372; -+ ctx->state[3] = 0xA54FF53A; -+ ctx->state[4] = 0x510E527F; -+ ctx->state[5] = 0x9B05688C; -+ ctx->state[6] = 0x1F83D9AB; -+ ctx->state[7] = 0x5BE0CD19; -+} -+ -+void sha256_process( sha256_context *ctx, uint8 data[64] ) -+{ -+ uint32 temp1, temp2, W[64]; -+ uint32 A, B, C, D, E, F, G, H; -+ -+ GET_UINT32( W[0], data, 0 ); -+ GET_UINT32( W[1], data, 4 ); -+ GET_UINT32( W[2], data, 8 ); -+ GET_UINT32( W[3], data, 12 ); -+ GET_UINT32( W[4], data, 16 ); -+ GET_UINT32( W[5], data, 20 ); -+ GET_UINT32( W[6], data, 24 ); -+ GET_UINT32( W[7], data, 28 ); -+ GET_UINT32( W[8], data, 32 ); -+ GET_UINT32( W[9], data, 36 ); -+ GET_UINT32( W[10], data, 40 ); -+ GET_UINT32( W[11], data, 44 ); -+ GET_UINT32( W[12], data, 48 ); -+ GET_UINT32( W[13], data, 52 ); -+ GET_UINT32( W[14], data, 56 ); -+ GET_UINT32( W[15], data, 60 ); -+ -+#define SHR(x,n) ((x & 0xFFFFFFFF) >> n) -+#define ROTR(x,n) (SHR(x,n) | (x << (32 - n))) -+ -+#define S0(x) (ROTR(x, 7) ^ ROTR(x,18) ^ SHR(x, 3)) -+#define S1(x) (ROTR(x,17) ^ ROTR(x,19) ^ SHR(x,10)) -+ -+#define S2(x) (ROTR(x, 2) ^ ROTR(x,13) ^ ROTR(x,22)) -+#define S3(x) (ROTR(x, 6) ^ ROTR(x,11) ^ ROTR(x,25)) -+ -+#define F0(x,y,z) ((x & y) | (z & (x | y))) -+#define F1(x,y,z) (z ^ (x & (y ^ z))) -+ -+#define R(t) \ -+( \ -+ W[t] = S1(W[t - 2]) + W[t - 7] + \ -+ S0(W[t - 15]) + W[t - 16] \ -+) -+ -+#define P(a,b,c,d,e,f,g,h,x,K) \ -+{ \ -+ temp1 = h + S3(e) + F1(e,f,g) + K + x; \ -+ temp2 = S2(a) + F0(a,b,c); \ -+ d += temp1; h = temp1 + temp2; \ -+} -+ -+ A = ctx->state[0]; -+ B = ctx->state[1]; -+ C = ctx->state[2]; -+ D = ctx->state[3]; -+ E = ctx->state[4]; -+ F = ctx->state[5]; -+ G = ctx->state[6]; -+ H = ctx->state[7]; -+ -+ P( A, B, C, D, E, F, G, H, W[ 0], 0x428A2F98 ); -+ P( H, A, B, C, D, E, F, G, W[ 1], 0x71374491 ); -+ P( G, H, A, B, C, D, E, F, W[ 2], 0xB5C0FBCF ); -+ P( F, G, H, A, B, C, D, E, W[ 3], 0xE9B5DBA5 ); -+ P( E, F, G, H, A, B, C, D, W[ 4], 0x3956C25B ); -+ P( D, E, F, G, H, A, B, C, W[ 5], 0x59F111F1 ); -+ P( C, D, E, F, G, H, A, B, W[ 6], 0x923F82A4 ); -+ P( B, C, D, E, F, G, H, A, W[ 7], 0xAB1C5ED5 ); -+ P( A, B, C, D, E, F, G, H, W[ 8], 0xD807AA98 ); -+ P( H, A, B, C, D, E, F, G, W[ 9], 0x12835B01 ); -+ P( G, H, A, B, C, D, E, F, W[10], 0x243185BE ); -+ P( F, G, H, A, B, C, D, E, W[11], 0x550C7DC3 ); -+ P( E, F, G, H, A, B, C, D, W[12], 0x72BE5D74 ); -+ P( D, E, F, G, H, A, B, C, W[13], 0x80DEB1FE ); -+ P( C, D, E, F, G, H, A, B, W[14], 0x9BDC06A7 ); -+ P( B, C, D, E, F, G, H, A, W[15], 0xC19BF174 ); -+ P( A, B, C, D, E, F, G, H, R(16), 0xE49B69C1 ); -+ P( H, A, B, C, D, E, F, G, R(17), 0xEFBE4786 ); -+ P( G, H, A, B, C, D, E, F, R(18), 0x0FC19DC6 ); -+ P( F, G, H, A, B, C, D, E, R(19), 0x240CA1CC ); -+ P( E, F, G, H, A, B, C, D, R(20), 0x2DE92C6F ); -+ P( D, E, F, G, H, A, B, C, R(21), 0x4A7484AA ); -+ P( C, D, E, F, G, H, A, B, R(22), 0x5CB0A9DC ); -+ P( B, C, D, E, F, G, H, A, R(23), 0x76F988DA ); -+ P( A, B, C, D, E, F, G, H, R(24), 0x983E5152 ); -+ P( H, A, B, C, D, E, F, G, R(25), 0xA831C66D ); -+ P( G, H, A, B, C, D, E, F, R(26), 0xB00327C8 ); -+ P( F, G, H, A, B, C, D, E, R(27), 0xBF597FC7 ); -+ P( E, F, G, H, A, B, C, D, R(28), 0xC6E00BF3 ); -+ P( D, E, F, G, H, A, B, C, R(29), 0xD5A79147 ); -+ P( C, D, E, F, G, H, A, B, R(30), 0x06CA6351 ); -+ P( B, C, D, E, F, G, H, A, R(31), 0x14292967 ); -+ P( A, B, C, D, E, F, G, H, R(32), 0x27B70A85 ); -+ P( H, A, B, C, D, E, F, G, R(33), 0x2E1B2138 ); -+ P( G, H, A, B, C, D, E, F, R(34), 0x4D2C6DFC ); -+ P( F, G, H, A, B, C, D, E, R(35), 0x53380D13 ); -+ P( E, F, G, H, A, B, C, D, R(36), 0x650A7354 ); -+ P( D, E, F, G, H, A, B, C, R(37), 0x766A0ABB ); -+ P( C, D, E, F, G, H, A, B, R(38), 0x81C2C92E ); -+ P( B, C, D, E, F, G, H, A, R(39), 0x92722C85 ); -+ P( A, B, C, D, E, F, G, H, R(40), 0xA2BFE8A1 ); -+ P( H, A, B, C, D, E, F, G, R(41), 0xA81A664B ); -+ P( G, H, A, B, C, D, E, F, R(42), 0xC24B8B70 ); -+ P( F, G, H, A, B, C, D, E, R(43), 0xC76C51A3 ); -+ P( E, F, G, H, A, B, C, D, R(44), 0xD192E819 ); -+ P( D, E, F, G, H, A, B, C, R(45), 0xD6990624 ); -+ P( C, D, E, F, G, H, A, B, R(46), 0xF40E3585 ); -+ P( B, C, D, E, F, G, H, A, R(47), 0x106AA070 ); -+ P( A, B, C, D, E, F, G, H, R(48), 0x19A4C116 ); -+ P( H, A, B, C, D, E, F, G, R(49), 0x1E376C08 ); -+ P( G, H, A, B, C, D, E, F, R(50), 0x2748774C ); -+ P( F, G, H, A, B, C, D, E, R(51), 0x34B0BCB5 ); -+ P( E, F, G, H, A, B, C, D, R(52), 0x391C0CB3 ); -+ P( D, E, F, G, H, A, B, C, R(53), 0x4ED8AA4A ); -+ P( C, D, E, F, G, H, A, B, R(54), 0x5B9CCA4F ); -+ P( B, C, D, E, F, G, H, A, R(55), 0x682E6FF3 ); -+ P( A, B, C, D, E, F, G, H, R(56), 0x748F82EE ); -+ P( H, A, B, C, D, E, F, G, R(57), 0x78A5636F ); -+ P( G, H, A, B, C, D, E, F, R(58), 0x84C87814 ); -+ P( F, G, H, A, B, C, D, E, R(59), 0x8CC70208 ); -+ P( E, F, G, H, A, B, C, D, R(60), 0x90BEFFFA ); -+ P( D, E, F, G, H, A, B, C, R(61), 0xA4506CEB ); -+ P( C, D, E, F, G, H, A, B, R(62), 0xBEF9A3F7 ); -+ P( B, C, D, E, F, G, H, A, R(63), 0xC67178F2 ); -+ -+ ctx->state[0] += A; -+ ctx->state[1] += B; -+ ctx->state[2] += C; -+ ctx->state[3] += D; -+ ctx->state[4] += E; -+ ctx->state[5] += F; -+ ctx->state[6] += G; -+ ctx->state[7] += H; -+} -+ -+void sha256_update( sha256_context *ctx, uint8 *input, uint32 length ) -+{ -+ uint32 left, fill; -+ -+ if( ! length ) return; -+ -+ left = ctx->total[0] & 0x3F; -+ fill = 64 - left; -+ -+ ctx->total[0] += length; -+ ctx->total[0] &= 0xFFFFFFFF; -+ -+ if( ctx->total[0] < length ) -+ ctx->total[1]++; -+ -+ if( left && length >= fill ) -+ { -+ CopyMem( (void *) (ctx->buffer + left), -+ (void *) input, fill ); -+ sha256_process( ctx, ctx->buffer ); -+ length -= fill; -+ input += fill; -+ left = 0; -+ } -+ -+ while( length >= 64 ) -+ { -+ sha256_process( ctx, input ); -+ length -= 64; -+ input += 64; -+ } -+ -+ if( length ) -+ { -+ CopyMem( (void *) (ctx->buffer + left), -+ (void *) input, length ); -+ } -+} -+ -+static uint8 sha256_padding[64] = -+{ -+ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -+}; -+ -+void sha256_finish( sha256_context *ctx, uint8 digest[SHA256_DIGEST_SIZE] ) -+{ -+ uint32 last, padn; -+ uint32 high, low; -+ uint8 msglen[8]; -+ -+ high = ( ctx->total[0] >> 29 ) -+ | ( ctx->total[1] << 3 ); -+ low = ( ctx->total[0] << 3 ); -+ -+ PUT_UINT32( high, msglen, 0 ); -+ PUT_UINT32( low, msglen, 4 ); -+ -+ last = ctx->total[0] & 0x3F; -+ padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); -+ -+ sha256_update( ctx, sha256_padding, padn ); -+ sha256_update( ctx, msglen, 8 ); -+ -+ PUT_UINT32( ctx->state[0], digest, 0 ); -+ PUT_UINT32( ctx->state[1], digest, 4 ); -+ PUT_UINT32( ctx->state[2], digest, 8 ); -+ PUT_UINT32( ctx->state[3], digest, 12 ); -+ PUT_UINT32( ctx->state[4], digest, 16 ); -+ PUT_UINT32( ctx->state[5], digest, 20 ); -+ PUT_UINT32( ctx->state[6], digest, 24 ); -+ PUT_UINT32( ctx->state[7], digest, 28 ); -+} -+ -+EFI_STATUS -+sha256_get_pecoff_digest_mem(void *buffer, UINTN DataSize, -+ UINT8 hash[SHA256_DIGEST_SIZE]) -+{ -+ PE_COFF_LOADER_IMAGE_CONTEXT context; -+ sha256_context ctx; -+ void *hashbase; -+ unsigned int hashsize; -+ EFI_IMAGE_SECTION_HEADER *section; -+ EFI_IMAGE_SECTION_HEADER **sections; -+ int i, sum_of_bytes; -+ EFI_STATUS efi_status; -+ -+ efi_status = pecoff_read_header(&context, buffer); -+ if (efi_status != EFI_SUCCESS) { -+ Print(L"Failed to read header\n"); -+ return efi_status; -+ } -+ -+ sections = AllocatePool(context.PEHdr->Pe32.FileHeader.NumberOfSections * sizeof(*sections)); -+ if (!sections) -+ return EFI_OUT_OF_RESOURCES; -+ -+ sha256_starts(&ctx); -+ -+ /* hash start to checksum */ -+ hashbase = buffer; -+ hashsize = (void *)&context.PEHdr->Pe32.OptionalHeader.CheckSum - buffer; -+ -+ sha256_update(&ctx, hashbase, hashsize); -+ -+ /* hash post-checksum to start of certificate table */ -+ hashbase = (void *)&context.PEHdr->Pe32.OptionalHeader.CheckSum + sizeof (int); -+ hashsize = (void *)context.SecDir - hashbase; -+ -+ sha256_update(&ctx, hashbase, hashsize); -+ -+ /* Hash end of certificate table to end of image header */ -+ hashbase = &context.PEHdr->Pe32Plus.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1]; -+ hashsize = context.PEHdr->Pe32Plus.OptionalHeader.SizeOfHeaders - -+ (int) ((void *) (&context.PEHdr->Pe32Plus.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1]) - buffer); -+ -+ sha256_update(&ctx, hashbase, hashsize); -+ sum_of_bytes = context.PEHdr->Pe32Plus.OptionalHeader.SizeOfHeaders; -+ section = (EFI_IMAGE_SECTION_HEADER *) ((char *)context.PEHdr + sizeof (UINT32) + sizeof (EFI_IMAGE_FILE_HEADER) + context.PEHdr->Pe32.FileHeader.SizeOfOptionalHeader); -+ -+ /* Sort the section headers by their data pointers */ -+ for (i = 0; i < context.PEHdr->Pe32.FileHeader.NumberOfSections; i++) { -+ int p = i; -+ while (p > 0 && section->PointerToRawData < sections[p - 1]->PointerToRawData) { -+ sections[p] = sections[p-1]; -+ p--; -+ } -+ sections[p] = section++; -+ } -+ /* hash the sorted sections */ -+ for (i = 0; i < context.PEHdr->Pe32.FileHeader.NumberOfSections; i++) { -+ section = sections[i]; -+ hashbase = pecoff_image_address(buffer, DataSize, section->PointerToRawData); -+ hashsize = (unsigned int) section->SizeOfRawData; -+ if (hashsize == 0) -+ continue; -+ sha256_update(&ctx, hashbase, hashsize); -+ sum_of_bytes += hashsize; -+ } -+ -+ if (DataSize > sum_of_bytes) { -+ /* stuff at end to hash */ -+ hashbase = buffer + sum_of_bytes; -+ hashsize = (unsigned int)(DataSize - context.PEHdr->Pe32Plus.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size - sum_of_bytes); -+ sha256_update(&ctx, hashbase, hashsize); -+ } -+ sha256_finish(&ctx, hash); -+ -+ FreePool(sections); -+ -+ return EFI_SUCCESS; -+} -+ -+#ifdef BUILD_EFI -+void -+sha256_StrCat_hash(CHAR16 *str, UINT8 hash[SHA256_DIGEST_SIZE]) -+{ -+ int i; -+ -+ for (i = 0; i < SHA256_DIGEST_SIZE; i++) { -+ CHAR16 buf[10]; -+ -+ SPrint(buf, sizeof(buf), L"%02x", hash[i]); -+ StrCat(str, buf); -+ } -+} -+ -+EFI_STATUS -+sha256_get_pecoff_digest(EFI_HANDLE device, CHAR16 *name, uint8 hash[SHA256_DIGEST_SIZE]) -+{ -+ EFI_STATUS efi_status; -+ EFI_FILE *file; -+ UINTN DataSize; -+ void *buffer; -+ -+ efi_status = simple_file_open(device, name, &file, EFI_FILE_MODE_READ); -+ if (efi_status != EFI_SUCCESS) { -+ Print(L"Failed to open %s\n", name); -+ return efi_status; -+ } -+ -+ efi_status = simple_file_read_all(file, &DataSize, &buffer); -+ if (efi_status != EFI_SUCCESS) { -+ Print(L"Failed to read %s\n", name); -+ goto out_close_file; -+ } -+ -+ efi_status = sha256_get_pecoff_digest_mem(buffer, DataSize, hash); -+ -+ FreePool(buffer); -+ out_close_file: -+ simple_file_close(file); -+ return efi_status; -+} -+#endif -diff --git a/efitools/lib/shell.c b/efitools/lib/shell.c -new file mode 100644 -index 0000000..51de4e0 ---- /dev/null -+++ b/efitools/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/efitools/lib/simple_file.c b/efitools/lib/simple_file.c -new file mode 100644 -index 0000000..0e5ecd2 ---- /dev/null -+++ b/efitools/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/efitools/lib/variables.c b/efitools/lib/variables.c -new file mode 100644 -index 0000000..37bb1c1 ---- /dev/null -+++ b/efitools/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, sizeof(sig), 0); -+ 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; -+} +@@ -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 35556acbc747eac5e22d45324503ffcd002ca9dd Mon Sep 17 00:00:00 2001 +From ef8fdc597fd532cc4c91c3d2ee638ef339002618 Mon Sep 17 00:00:00 2001 From: Gary Ching-Pang Lin -Date: Wed, 17 Apr 2013 11:20:12 +0800 -Subject: [PATCH 02/12] Adopt the file selector from efitools +Date: Thu, 18 Apr 2013 17:13:12 +0800 +Subject: [PATCH 2/8] MokManager: draw the countdown screen --- - MokManager.c | 378 +++++++++-------------------------------------------------- - 1 file changed, 57 insertions(+), 321 deletions(-) + MokManager.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 60 insertions(+) diff --git a/MokManager.c b/MokManager.c -index e27c2c1..c076b12 100644 +index 918d96b..6b8c79b 100644 --- a/MokManager.c +++ b/MokManager.c -@@ -2,6 +2,8 @@ - #include - #include - #include -+#include -+#include - #include "shim.h" - #include "signature.h" - #include "PeImage.h" -@@ -17,8 +19,8 @@ - - #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" -+#define CERT_STRING L"Select an X509 certificate to enroll:" -+#define HASH_STRING L"Select a file to trust:" - - struct menu_item { - CHAR16 *text; -@@ -1318,8 +1320,6 @@ static UINTN verify_certificate(void *cert, UINTN size) - - if (!(X509ConstructCertificate(cert, size, (UINT8 **) &X509Cert)) || - X509Cert == NULL) { -- Print(L"Invalid X509 certificate\n"); -- Pause(); - return FALSE; - } - -@@ -1327,25 +1327,35 @@ static UINTN verify_certificate(void *cert, UINTN size) +@@ -1360,6 +1360,63 @@ static BOOLEAN verify_pw(void) return TRUE; } --static INTN file_callback (void *data, void *data2, void *data3) { -- EFI_FILE_INFO *buffer = NULL; -- UINTN buffersize = 0, mokbuffersize; -- EFI_STATUS status; -+static INTN find_file (void *data, void *data2, void *data3) -+{ -+ EFI_HANDLE handle = NULL; - EFI_FILE *file; -- CHAR16 *filename = data; -- EFI_FILE *parent = data2; -+ EFI_STATUS status; -+ CHAR16 *title[2]; -+ CHAR16 *filename; - BOOLEAN hash = !!data3; -+ EFI_FILE_INFO *buffer = NULL; - EFI_GUID file_info_guid = EFI_FILE_INFO_ID; - EFI_GUID shim_lock_guid = SHIM_LOCK_GUID; - EFI_SIGNATURE_LIST *CertList; - EFI_SIGNATURE_DATA *CertData; -+ UINTN buffersize = 0, mokbuffersize; - void *mokbuffer = NULL; - -- status = uefi_call_wrapper(parent->Open, 5, parent, &file, filename, -- EFI_FILE_MODE_READ, 0); -+ title[0] = hash ? HASH_STRING : CERT_STRING; -+ title[1] = NULL; - -- if (status != EFI_SUCCESS) -- return 1; -+ simple_file_selector(&handle, title, NULL, NULL, &filename); -+ if (filename == NULL) { -+ return 0; -+ } -+ -+ status = simple_file_open(handle, filename, &file, EFI_FILE_MODE_READ); -+ if (status != EFI_SUCCESS) { -+ console_error (L"Failed to open file", status); -+ return 0; -+ } - - status = uefi_call_wrapper(file->GetInfo, 4, file, &file_info_guid, - &buffersize, buffer); -@@ -1357,8 +1367,10 @@ static INTN file_callback (void *data, void *data2, void *data3) { - buffer); - } - -- if (!buffer) -+ if (!buffer) { -+ console_error (L"Failed to allocate buffer", EFI_OUT_OF_RESOURCES); - return 0; -+ } - - buffersize = buffer->FileSize; - -@@ -1372,35 +1384,46 @@ static INTN file_callback (void *data, void *data2, void *data3) { - - status = LibLocateProtocol(&shim_guid, (VOID **)&shim_lock); - -- if (status != EFI_SUCCESS) -+ if (status != EFI_SUCCESS) { -+ console_error (L"Failed to locate shim protocol", status); - goto out; -+ } - - mokbuffersize = sizeof(EFI_SIGNATURE_LIST) + sizeof(EFI_GUID) + - SHA256_DIGEST_SIZE; - - mokbuffer = AllocatePool(mokbuffersize); - -- if (!mokbuffer) -+ if (!mokbuffer) { -+ console_error (L"Failed to allocate mokbuffer", -+ EFI_OUT_OF_RESOURCES); - goto out; -+ } - - binary = AllocatePool(buffersize); - - status = uefi_call_wrapper(file->Read, 3, file, &buffersize, - binary); - -- if (status != EFI_SUCCESS) -+ if (status != EFI_SUCCESS) { -+ console_error (L"Failed to read file", status); - goto out; -+ } - - status = shim_lock->Context(binary, buffersize, &context); - -- if (status != EFI_SUCCESS) -+ if (status != EFI_SUCCESS) { -+ console_error (L"Failed to get EFI context", status); - goto out; -+ } - - status = shim_lock->Hash(binary, buffersize, &context, sha256, - sha1); - -- if (status != EFI_SUCCESS) -+ if (status != EFI_SUCCESS) { -+ console_error (L"Failed to compute hash", status); - goto out; -+ } - - CertList = mokbuffer; - CertList->SignatureType = EfiHashSha256Guid; -@@ -1413,8 +1436,11 @@ static INTN file_callback (void *data, void *data2, void *data3) { - sizeof(EFI_GUID); - mokbuffer = AllocatePool(mokbuffersize); - -- if (!mokbuffer) -+ if (!mokbuffer) { -+ console_error (L"Failed to allocate mokbuffer", -+ EFI_OUT_OF_RESOURCES); - goto out; -+ } - - CertList = mokbuffer; - CertList->SignatureType = EfiCertX509Guid; -@@ -1422,8 +1448,10 @@ static INTN file_callback (void *data, void *data2, void *data3) { - status = uefi_call_wrapper(file->Read, 3, file, &buffersize, - mokbuffer + sizeof(EFI_SIGNATURE_LIST) + 16); - -- if (status != EFI_SUCCESS) -+ if (status != EFI_SUCCESS) { -+ console_error (L"Failed to read file", status); - goto out; -+ } - CertData = (EFI_SIGNATURE_DATA *)(((UINT8 *)mokbuffer) + - sizeof(EFI_SIGNATURE_LIST)); - } -@@ -1433,8 +1461,11 @@ 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, buffersize)) { -+ console_error (L"Not a valid certificate", -+ EFI_INVALID_PARAMETER); - goto out; -+ } - } - - mok_enrollment_prompt(mokbuffer, mokbuffersize, FALSE); -@@ -1445,302 +1476,7 @@ out: - if (mokbuffer) - FreePool(mokbuffer); - -- return 0; --} -- --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; -- -- 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 = 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; -- } -- -- i++; -- FreePool(buffer); -- buffersize = 0; -- buffer = NULL; -- } -- -- if (hash) -- run_menu(HASH_STRING, 2, dircontent, dircount, 0); -- else -- run_menu(CERT_STRING, 2, dircontent, dircount, 0); -- -- 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; -- } -- -- 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; -- } -- -- if (hash) -- run_menu(HASH_STRING, 2, dircontent, dircount, 0); -- else -- run_menu(CERT_STRING, 2, dircontent, dircount, 0); -- -- return 0; --} -- --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); -- -- if (status == EFI_BUFFER_TOO_SMALL) { -- buffer = AllocatePool(buffersize); -- status = uefi_call_wrapper(root->GetInfo, 4, root, -- &file_info_guid, -- &buffersize, buffer); -- } -- -- 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 (buffersize) -- FreePool(buffer); -- -- filesystems[i].data = root; -- filesystems[i].data2 = NULL; -- filesystems[i].data3 = data3; -- filesystems[i].callback = filesystem_callback; -- filesystems[i].colour = EFI_YELLOW; -- } -- -- uefi_call_wrapper(BS->FreePool, 1, filesystem_handles); -- -- if (hash) -- run_menu(HASH_STRING, 2, filesystems, count, 0); -- else -- run_menu(CERT_STRING, 2, filesystems, count, 0); -+ simple_file_close(file); - - return 0; - } -@@ -1888,14 +1624,14 @@ static EFI_STATUS enter_mok_menu(EFI_HANDLE image_handle, - - 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].callback = find_file; - menu_item[i].data3 = (void *)FALSE; - - 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].callback = find_file; - menu_item[i].data3 = (void *)TRUE; - - i++; --- -1.8.1.4 - - -From 87a2148636e2616bb586ee95ad942f5a3eac8905 Mon Sep 17 00:00:00 2001 -From: Gary Ching-Pang Lin -Date: Wed, 17 Apr 2013 18:00:13 +0800 -Subject: [PATCH 03/12] Drop kernel_efivars.h - -It's not for EFI programs ---- - efitools/include/kernel_efivars.h | 26 -------------------------- - 1 file changed, 26 deletions(-) - delete mode 100644 efitools/include/kernel_efivars.h - -diff --git a/efitools/include/kernel_efivars.h b/efitools/include/kernel_efivars.h -deleted file mode 100644 -index 1f5dfa0..0000000 ---- a/efitools/include/kernel_efivars.h -+++ /dev/null -@@ -1,26 +0,0 @@ --#include --#include --void --kernel_variable_init(void); --int --get_variable(const char *var, EFI_GUID *guid, uint32_t *attributes, -- uint32_t *size, void *buf); --int --get_variable_alloc(const char *var, EFI_GUID *guid, uint32_t *attributes, -- uint32_t *size, uint8_t **buf); --int --variable_is_setupmode(void); --int --variable_is_secureboot(void); --int --set_variable(const char *var, EFI_GUID *guid, uint32_t attributes, -- uint32_t size, void *buf); --int --set_variable_esl(const char *var, EFI_GUID *guid, uint32_t attributes, -- uint32_t size, void *buf); --int --set_variable_hash(const char *var, EFI_GUID *owner, uint32_t attributes, -- uint8_t hash[SHA256_DIGEST_SIZE]); --uint8_t * --hash_to_esl(EFI_GUID *owner, int *len, -- uint8_t hash[SHA256_DIGEST_SIZE]); --- -1.8.1.4 - - -From cb9bf99ef9ffef2b7921dd7d743ec1eb357095fc Mon Sep 17 00:00:00 2001 -From: Gary Ching-Pang Lin -Date: Wed, 8 May 2013 11:07:55 +0800 -Subject: [PATCH 04/12] Update efitools COPYING - ---- - efitools/COPYING | 513 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- - 1 file changed, 512 insertions(+), 1 deletion(-) - -diff --git a/efitools/COPYING b/efitools/COPYING -index 7737e63..454bd72 100644 ---- a/efitools/COPYING -+++ b/efitools/COPYING -@@ -6,7 +6,13 @@ All of these programs are made available under version 2 of the GNU General - Public Licence. The library routines in lib/ are made available under the GNU - Lesser General Public Licence version 2.1. Additionally for linking the - programme files with openSSL, there is an additional permission that --compiling, linking, and/or using OpenSSL is allowed. -+compiling, linking, and/or using OpenSSL is allowed. Contributing Authors -+agree that their code is submitted under the licence appropriate for its -+location within the source tree (GPL except for LGPL in lib/) and agree that -+any future patches, provided they are accepted into the project, may change -+the licence of their code from GPL to LGPL by moving pieces of it into lib/ or -+LGPL to GPL by moving pieces of it out of lib/ -+ - - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 -@@ -348,3 +354,508 @@ proprietary programs. If your program is a subroutine library, you may - consider it more useful to permit linking proprietary applications with the - library. If this is what you want to do, use the GNU Library General - Public License instead of this License. -+ -+--------------------------------------- -+ -+ GNU LESSER GENERAL PUBLIC LICENSE -+ Version 2.1, February 1999 -+ -+ Copyright (C) 1991, 1999 Free Software Foundation, Inc. -+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -+ Everyone is permitted to copy and distribute verbatim copies -+ of this license document, but changing it is not allowed. -+ -+[This is the first released version of the Lesser GPL. It also counts -+ as the successor of the GNU Library Public License, version 2, hence -+ the version number 2.1.] -+ -+ Preamble -+ -+ The licenses for most software are designed to take away your -+freedom to share and change it. By contrast, the GNU General Public -+Licenses are intended to guarantee your freedom to share and change -+free software--to make sure the software is free for all its users. -+ -+ This license, the Lesser General Public License, applies to some -+specially designated software packages--typically libraries--of the -+Free Software Foundation and other authors who decide to use it. You -+can use it too, but we suggest you first think carefully about whether -+this license or the ordinary General Public License is the better -+strategy to use in any particular case, based on the explanations below. -+ -+ When we speak of free software, we are referring to freedom of use, -+not price. Our General Public Licenses are designed to make sure that -+you have the freedom to distribute copies of free software (and charge -+for this service if you wish); that you receive source code or can get -+it if you want it; that you can change the software and use pieces of -+it in new free programs; and that you are informed that you can do -+these things. -+ -+ To protect your rights, we need to make restrictions that forbid -+distributors to deny you these rights or to ask you to surrender these -+rights. These restrictions translate to certain responsibilities for -+you if you distribute copies of the library or if you modify it. -+ -+ For example, if you distribute copies of the library, whether gratis -+or for a fee, you must give the recipients all the rights that we gave -+you. You must make sure that they, too, receive or can get the source -+code. If you link other code with the library, you must provide -+complete object files to the recipients, so that they can relink them -+with the library after making changes to the library and recompiling -+it. And you must show them these terms so they know their rights. -+ -+ We protect your rights with a two-step method: (1) we copyright the -+library, and (2) we offer you this license, which gives you legal -+permission to copy, distribute and/or modify the library. -+ -+ To protect each distributor, we want to make it very clear that -+there is no warranty for the free library. Also, if the library is -+modified by someone else and passed on, the recipients should know -+that what they have is not the original version, so that the original -+author's reputation will not be affected by problems that might be -+introduced by others. -+ -+ Finally, software patents pose a constant threat to the existence of -+any free program. We wish to make sure that a company cannot -+effectively restrict the users of a free program by obtaining a -+restrictive license from a patent holder. Therefore, we insist that -+any patent license obtained for a version of the library must be -+consistent with the full freedom of use specified in this license. -+ -+ Most GNU software, including some libraries, is covered by the -+ordinary GNU General Public License. This license, the GNU Lesser -+General Public License, applies to certain designated libraries, and -+is quite different from the ordinary General Public License. We use -+this license for certain libraries in order to permit linking those -+libraries into non-free programs. -+ -+ When a program is linked with a library, whether statically or using -+a shared library, the combination of the two is legally speaking a -+combined work, a derivative of the original library. The ordinary -+General Public License therefore permits such linking only if the -+entire combination fits its criteria of freedom. The Lesser General -+Public License permits more lax criteria for linking other code with -+the library. -+ -+ We call this license the "Lesser" General Public License because it -+does Less to protect the user's freedom than the ordinary General -+Public License. It also provides other free software developers Less -+of an advantage over competing non-free programs. These disadvantages -+are the reason we use the ordinary General Public License for many -+libraries. However, the Lesser license provides advantages in certain -+special circumstances. -+ -+ For example, on rare occasions, there may be a special need to -+encourage the widest possible use of a certain library, so that it becomes -+a de-facto standard. To achieve this, non-free programs must be -+allowed to use the library. A more frequent case is that a free -+library does the same job as widely used non-free libraries. In this -+case, there is little to gain by limiting the free library to free -+software only, so we use the Lesser General Public License. -+ -+ In other cases, permission to use a particular library in non-free -+programs enables a greater number of people to use a large body of -+free software. For example, permission to use the GNU C Library in -+non-free programs enables many more people to use the whole GNU -+operating system, as well as its variant, the GNU/Linux operating -+system. -+ -+ Although the Lesser General Public License is Less protective of the -+users' freedom, it does ensure that the user of a program that is -+linked with the Library has the freedom and the wherewithal to run -+that program using a modified version of the Library. -+ -+ The precise terms and conditions for copying, distribution and -+modification follow. Pay close attention to the difference between a -+"work based on the library" and a "work that uses the library". The -+former contains code derived from the library, whereas the latter must -+be combined with the library in order to run. -+ -+ GNU LESSER GENERAL PUBLIC LICENSE -+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION -+ -+ 0. This License Agreement applies to any software library or other -+program which contains a notice placed by the copyright holder or -+other authorized party saying it may be distributed under the terms of -+this Lesser General Public License (also called "this License"). -+Each licensee is addressed as "you". -+ -+ A "library" means a collection of software functions and/or data -+prepared so as to be conveniently linked with application programs -+(which use some of those functions and data) to form executables. -+ -+ The "Library", below, refers to any such software library or work -+which has been distributed under these terms. A "work based on the -+Library" means either the Library or any derivative work under -+copyright law: that is to say, a work containing the Library or a -+portion of it, either verbatim or with modifications and/or translated -+straightforwardly into another language. (Hereinafter, translation is -+included without limitation in the term "modification".) -+ -+ "Source code" for a work means the preferred form of the work for -+making modifications to it. For a library, complete source code means -+all the source code for all modules it contains, plus any associated -+interface definition files, plus the scripts used to control compilation -+and installation of the library. -+ -+ Activities other than copying, distribution and modification are not -+covered by this License; they are outside its scope. The act of -+running a program using the Library is not restricted, and output from -+such a program is covered only if its contents constitute a work based -+on the Library (independent of the use of the Library in a tool for -+writing it). Whether that is true depends on what the Library does -+and what the program that uses the Library does. -+ -+ 1. You may copy and distribute verbatim copies of the Library's -+complete source code as you receive it, in any medium, provided that -+you conspicuously and appropriately publish on each copy an -+appropriate copyright notice and disclaimer of warranty; keep intact -+all the notices that refer to this License and to the absence of any -+warranty; and distribute a copy of this License along with the -+Library. -+ -+ You may charge a fee for the physical act of transferring a copy, -+and you may at your option offer warranty protection in exchange for a -+fee. -+ -+ 2. You may modify your copy or copies of the Library or any portion -+of it, thus forming a work based on the Library, and copy and -+distribute such modifications or work under the terms of Section 1 -+above, provided that you also meet all of these conditions: -+ -+ a) The modified work must itself be a software library. -+ -+ b) You must cause the files modified to carry prominent notices -+ stating that you changed the files and the date of any change. -+ -+ c) You must cause the whole of the work to be licensed at no -+ charge to all third parties under the terms of this License. -+ -+ d) If a facility in the modified Library refers to a function or a -+ table of data to be supplied by an application program that uses -+ the facility, other than as an argument passed when the facility -+ is invoked, then you must make a good faith effort to ensure that, -+ in the event an application does not supply such function or -+ table, the facility still operates, and performs whatever part of -+ its purpose remains meaningful. -+ -+ (For example, a function in a library to compute square roots has -+ a purpose that is entirely well-defined independent of the -+ application. Therefore, Subsection 2d requires that any -+ application-supplied function or table used by this function must -+ be optional: if the application does not supply it, the square -+ root function must still compute square roots.) -+ -+These requirements apply to the modified work as a whole. If -+identifiable sections of that work are not derived from the Library, -+and can be reasonably considered independent and separate works in -+themselves, then this License, and its terms, do not apply to those -+sections when you distribute them as separate works. But when you -+distribute the same sections as part of a whole which is a work based -+on the Library, the distribution of the whole must be on the terms of -+this License, whose permissions for other licensees extend to the -+entire whole, and thus to each and every part regardless of who wrote -+it. -+ -+Thus, it is not the intent of this section to claim rights or contest -+your rights to work written entirely by you; rather, the intent is to -+exercise the right to control the distribution of derivative or -+collective works based on the Library. -+ -+In addition, mere aggregation of another work not based on the Library -+with the Library (or with a work based on the Library) on a volume of -+a storage or distribution medium does not bring the other work under -+the scope of this License. -+ -+ 3. You may opt to apply the terms of the ordinary GNU General Public -+License instead of this License to a given copy of the Library. To do -+this, you must alter all the notices that refer to this License, so -+that they refer to the ordinary GNU General Public License, version 2, -+instead of to this License. (If a newer version than version 2 of the -+ordinary GNU General Public License has appeared, then you can specify -+that version instead if you wish.) Do not make any other change in -+these notices. -+ -+ Once this change is made in a given copy, it is irreversible for -+that copy, so the ordinary GNU General Public License applies to all -+subsequent copies and derivative works made from that copy. -+ -+ This option is useful when you wish to copy part of the code of -+the Library into a program that is not a library. -+ -+ 4. You may copy and distribute the Library (or a portion or -+derivative of it, under Section 2) in object code or executable form -+under the terms of Sections 1 and 2 above provided that you accompany -+it with the complete corresponding machine-readable source code, which -+must be distributed under the terms of Sections 1 and 2 above on a -+medium customarily used for software interchange. -+ -+ If distribution of object code is made by offering access to copy -+from a designated place, then offering equivalent access to copy the -+source code from the same place satisfies the requirement to -+distribute the source code, even though third parties are not -+compelled to copy the source along with the object code. -+ -+ 5. A program that contains no derivative of any portion of the -+Library, but is designed to work with the Library by being compiled or -+linked with it, is called a "work that uses the Library". Such a -+work, in isolation, is not a derivative work of the Library, and -+therefore falls outside the scope of this License. -+ -+ However, linking a "work that uses the Library" with the Library -+creates an executable that is a derivative of the Library (because it -+contains portions of the Library), rather than a "work that uses the -+library". The executable is therefore covered by this License. -+Section 6 states terms for distribution of such executables. -+ -+ When a "work that uses the Library" uses material from a header file -+that is part of the Library, the object code for the work may be a -+derivative work of the Library even though the source code is not. -+Whether this is true is especially significant if the work can be -+linked without the Library, or if the work is itself a library. The -+threshold for this to be true is not precisely defined by law. -+ -+ If such an object file uses only numerical parameters, data -+structure layouts and accessors, and small macros and small inline -+functions (ten lines or less in length), then the use of the object -+file is unrestricted, regardless of whether it is legally a derivative -+work. (Executables containing this object code plus portions of the -+Library will still fall under Section 6.) -+ -+ Otherwise, if the work is a derivative of the Library, you may -+distribute the object code for the work under the terms of Section 6. -+Any executables containing that work also fall under Section 6, -+whether or not they are linked directly with the Library itself. -+ -+ 6. As an exception to the Sections above, you may also combine or -+link a "work that uses the Library" with the Library to produce a -+work containing portions of the Library, and distribute that work -+under terms of your choice, provided that the terms permit -+modification of the work for the customer's own use and reverse -+engineering for debugging such modifications. -+ -+ You must give prominent notice with each copy of the work that the -+Library is used in it and that the Library and its use are covered by -+this License. You must supply a copy of this License. If the work -+during execution displays copyright notices, you must include the -+copyright notice for the Library among them, as well as a reference -+directing the user to the copy of this License. Also, you must do one -+of these things: -+ -+ a) Accompany the work with the complete corresponding -+ machine-readable source code for the Library including whatever -+ changes were used in the work (which must be distributed under -+ Sections 1 and 2 above); and, if the work is an executable linked -+ with the Library, with the complete machine-readable "work that -+ uses the Library", as object code and/or source code, so that the -+ user can modify the Library and then relink to produce a modified -+ executable containing the modified Library. (It is understood -+ that the user who changes the contents of definitions files in the -+ Library will not necessarily be able to recompile the application -+ to use the modified definitions.) -+ -+ b) Use a suitable shared library mechanism for linking with the -+ Library. A suitable mechanism is one that (1) uses at run time a -+ copy of the library already present on the user's computer system, -+ rather than copying library functions into the executable, and (2) -+ will operate properly with a modified version of the library, if -+ the user installs one, as long as the modified version is -+ interface-compatible with the version that the work was made with. -+ -+ c) Accompany the work with a written offer, valid for at -+ least three years, to give the same user the materials -+ specified in Subsection 6a, above, for a charge no more -+ than the cost of performing this distribution. -+ -+ d) If distribution of the work is made by offering access to copy -+ from a designated place, offer equivalent access to copy the above -+ specified materials from the same place. -+ -+ e) Verify that the user has already received a copy of these -+ materials or that you have already sent this user a copy. -+ -+ For an executable, the required form of the "work that uses the -+Library" must include any data and utility programs needed for -+reproducing the executable from it. However, as a special exception, -+the materials to be distributed need not include anything that is -+normally distributed (in either source or binary form) with the major -+components (compiler, kernel, and so on) of the operating system on -+which the executable runs, unless that component itself accompanies -+the executable. -+ -+ It may happen that this requirement contradicts the license -+restrictions of other proprietary libraries that do not normally -+accompany the operating system. Such a contradiction means you cannot -+use both them and the Library together in an executable that you -+distribute. -+ -+ 7. You may place library facilities that are a work based on the -+Library side-by-side in a single library together with other library -+facilities not covered by this License, and distribute such a combined -+library, provided that the separate distribution of the work based on -+the Library and of the other library facilities is otherwise -+permitted, and provided that you do these two things: -+ -+ a) Accompany the combined library with a copy of the same work -+ based on the Library, uncombined with any other library -+ facilities. This must be distributed under the terms of the -+ Sections above. -+ -+ b) Give prominent notice with the combined library of the fact -+ that part of it is a work based on the Library, and explaining -+ where to find the accompanying uncombined form of the same work. -+ -+ 8. You may not copy, modify, sublicense, link with, or distribute -+the Library except as expressly provided under this License. Any -+attempt otherwise to copy, modify, sublicense, link with, or -+distribute the Library is void, and will automatically terminate your -+rights under this License. However, parties who have received copies, -+or rights, from you under this License will not have their licenses -+terminated so long as such parties remain in full compliance. -+ -+ 9. You are not required to accept this License, since you have not -+signed it. However, nothing else grants you permission to modify or -+distribute the Library or its derivative works. These actions are -+prohibited by law if you do not accept this License. Therefore, by -+modifying or distributing the Library (or any work based on the -+Library), you indicate your acceptance of this License to do so, and -+all its terms and conditions for copying, distributing or modifying -+the Library or works based on it. -+ -+ 10. Each time you redistribute the Library (or any work based on the -+Library), the recipient automatically receives a license from the -+original licensor to copy, distribute, link with or modify the Library -+subject to these terms and conditions. You may not impose any further -+restrictions on the recipients' exercise of the rights granted herein. -+You are not responsible for enforcing compliance by third parties with -+this License. -+ -+ 11. If, as a consequence of a court judgment or allegation of patent -+infringement or for any other reason (not limited to patent issues), -+conditions are imposed on you (whether by court order, agreement or -+otherwise) that contradict the conditions of this License, they do not -+excuse you from the conditions of this License. If you cannot -+distribute so as to satisfy simultaneously your obligations under this -+License and any other pertinent obligations, then as a consequence you -+may not distribute the Library at all. For example, if a patent -+license would not permit royalty-free redistribution of the Library by -+all those who receive copies directly or indirectly through you, then -+the only way you could satisfy both it and this License would be to -+refrain entirely from distribution of the Library. -+ -+If any portion of this section is held invalid or unenforceable under any -+particular circumstance, the balance of the section is intended to apply, -+and the section as a whole is intended to apply in other circumstances. -+ -+It is not the purpose of this section to induce you to infringe any -+patents or other property right claims or to contest validity of any -+such claims; this section has the sole purpose of protecting the -+integrity of the free software distribution system which is -+implemented by public license practices. Many people have made -+generous contributions to the wide range of software distributed -+through that system in reliance on consistent application of that -+system; it is up to the author/donor to decide if he or she is willing -+to distribute software through any other system and a licensee cannot -+impose that choice. -+ -+This section is intended to make thoroughly clear what is believed to -+be a consequence of the rest of this License. -+ -+ 12. If the distribution and/or use of the Library is restricted in -+certain countries either by patents or by copyrighted interfaces, the -+original copyright holder who places the Library under this License may add -+an explicit geographical distribution limitation excluding those countries, -+so that distribution is permitted only in or among countries not thus -+excluded. In such case, this License incorporates the limitation as if -+written in the body of this License. -+ -+ 13. The Free Software Foundation may publish revised and/or new -+versions of the Lesser General Public License from time to time. -+Such new versions will be similar in spirit to the present version, -+but may differ in detail to address new problems or concerns. -+ -+Each version is given a distinguishing version number. If the Library -+specifies a version number of this License which applies to it and -+"any later version", you have the option of following the terms and -+conditions either of that version or of any later version published by -+the Free Software Foundation. If the Library does not specify a -+license version number, you may choose any version ever published by -+the Free Software Foundation. -+ -+ 14. If you wish to incorporate parts of the Library into other free -+programs whose distribution conditions are incompatible with these, -+write to the author to ask for permission. For software which is -+copyrighted by the Free Software Foundation, write to the Free -+Software Foundation; we sometimes make exceptions for this. Our -+decision will be guided by the two goals of preserving the free status -+of all derivatives of our free software and of promoting the sharing -+and reuse of software generally. -+ -+ NO WARRANTY -+ -+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO -+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. -+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR -+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY -+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE -+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE -+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME -+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. -+ -+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN -+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY -+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU -+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR -+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE -+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING -+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A -+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF -+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH -+DAMAGES. -+ -+ END OF TERMS AND CONDITIONS -+ -+ How to Apply These Terms to Your New Libraries -+ -+ If you develop a new library, and you want it to be of the greatest -+possible use to the public, we recommend making it free software that -+everyone can redistribute and change. You can do so by permitting -+redistribution under these terms (or, alternatively, under the terms of the -+ordinary General Public License). -+ -+ To apply these terms, attach the following notices to the library. It is -+safest to attach them to the start of each source file to most effectively -+convey the exclusion of warranty; and each file should have at least the -+"copyright" line and a pointer to where the full notice is found. -+ -+ -+ Copyright (C) -+ -+ This library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ This library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with this library; if not, write to the Free Software -+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -+ -+Also add information on how to contact you by electronic and paper mail. -+ -+You should also get your employer (if you work as a programmer) or your -+school, if any, to sign a "copyright disclaimer" for the library, if -+necessary. Here is a sample; alter the names: -+ -+ Yoyodyne, Inc., hereby disclaims all copyright interest in the -+ library `Frob' (a library for tweaking knobs) written by James Random Hacker. -+ -+ , 1 April 1990 -+ Ty Coon, President of Vice -+ -+That's all there is to it! --- -1.8.1.4 - - -From f23279283a3540dc3921e808a75603e9818acda5 Mon Sep 17 00:00:00 2001 -From: Gary Ching-Pang Lin -Date: Fri, 3 May 2013 16:15:04 +0800 -Subject: [PATCH 05/12] 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. ---- - efitools/lib/simple_file.c | 42 ++++++++++++++++++++++++++++++++++-------- - 1 file changed, 34 insertions(+), 8 deletions(-) - -diff --git a/efitools/lib/simple_file.c b/efitools/lib/simple_file.c -index 0e5ecd2..e288272 100644 ---- a/efitools/lib/simple_file.c -+++ b/efitools/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, 18 Apr 2013 17:13:12 +0800 -Subject: [PATCH 06/12] Improve the MokManager menu - ---- - MokManager.c | 207 ++++++++++++++++++++--------------------------------------- - 1 file changed, 71 insertions(+), 136 deletions(-) - -diff --git a/MokManager.c b/MokManager.c -index c076b12..c1a726d 100644 ---- a/MokManager.c -+++ b/MokManager.c -@@ -23,12 +23,10 @@ - #define HASH_STRING L"Select a file to trust:" - - struct menu_item { -- CHAR16 *text; - INTN (* callback)(void *data, void *data2, void *data3); - void *data; - void *data2; - void *data3; -- UINTN colour; - }; - - typedef struct { -@@ -1177,139 +1175,61 @@ static INTN mok_pw_prompt (void *MokPW, void *data2, void *data3) { - 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; -- -- for (i=0; iConOut->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); ++{ + 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 enter management menu"; ++ 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_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); --} ++ uefi_call_wrapper(ST->ConOut->SetAttribute, 2, ST->ConOut, + EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE); - --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; ++ + title[0] = PoolPrint (L"%s UEFI key management", SHIM_VENDOR); + title[1] = NULL; - -- if (timeout) -- wait = 10000000; ++ + console_print_box_at(title, -1, 0, 0, -1, -1, 1, 1); - -- offset = draw_menu (header, lines, items, count); ++ + 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) { -- update_time(count + offset + 1, timeout); ++ 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); - -- 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; ++ ++ 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; - } - -- switch(key.UnicodeChar) { -- case CHAR_LINEFEED: -- case CHAR_CARRIAGE_RETURN: -- if (items[pos].callback == NULL) { -- free_menu(items, count); -- return; -- } -- -- 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; ++ } ++ + timeout--; + if (!timeout) - break; -- } - } ++ break; ++ } + + FreePool(title[0]); + @@ -9396,142 +151,39 @@ index c076b12..c1a726d 100644 + SavedMode.Attribute); + + return timeout; - } - - static UINTN verify_certificate(void *cert, UINTN size) -@@ -1529,6 +1449,8 @@ static EFI_STATUS enter_mok_menu(EFI_HANDLE image_handle, - void *MokPW, UINTN MokPWSize) - { - struct menu_item *menu_item; -+ CHAR16 *title[2], **item_text; -+ int opt; - UINT32 MokAuth = 0; - UINT32 MokDelAuth = 0; - UINTN menucount = 3, i = 0; -@@ -1570,24 +1492,22 @@ static EFI_STATUS enter_mok_menu(EFI_HANDLE image_handle, - menucount++; - - menu_item = AllocateZeroPool(sizeof(struct menu_item) * menucount); -+ item_text = AllocateZeroPool(sizeof(CHAR16 *) * (menucount + 1)); - - if (!menu_item) - return EFI_OUT_OF_RESOURCES; - -- menu_item[i].text = StrDuplicate(L"Continue boot"); -- menu_item[i].colour = EFI_WHITE; -+ item_text[i] = L"Continue boot"; - menu_item[i].callback = NULL; - - i++; - - if (MokNew || MokAuth) { - if (!MokNew) { -- menu_item[i].text = StrDuplicate(L"Reset MOK"); -- menu_item[i].colour = EFI_WHITE; -+ item_text[i] = L"Reset MOK"; - menu_item[i].callback = mok_reset_prompt; - } else { -- menu_item[i].text = StrDuplicate(L"Enroll MOK"); -- menu_item[i].colour = EFI_WHITE; -+ item_text[i] = L"Enroll MOK"; - menu_item[i].data = MokNew; - menu_item[i].data2 = (void *)MokNewSize; - menu_item[i].callback = mok_enrollment_prompt_callback; -@@ -1596,8 +1516,7 @@ static EFI_STATUS enter_mok_menu(EFI_HANDLE image_handle, - } - - if (MokDel || MokDelAuth) { -- menu_item[i].text = StrDuplicate(L"Delete MOK"); -- menu_item[i].colour = EFI_WHITE; -+ item_text[i] = L"Delete MOK"; - menu_item[i].data = MokDel; - menu_item[i].data2 = (void *)MokDelSize; - menu_item[i].callback = mok_deletion_prompt; -@@ -1605,8 +1524,7 @@ static EFI_STATUS enter_mok_menu(EFI_HANDLE image_handle, - } - - if (MokSB) { -- menu_item[i].text = StrDuplicate(L"Change Secure Boot state"); -- menu_item[i].colour = EFI_WHITE; -+ item_text[i] = L"Change Secure Boot state"; - menu_item[i].callback = mok_sb_prompt; - menu_item[i].data = MokSB; - menu_item[i].data2 = (void *)MokSBSize; -@@ -1614,32 +1532,49 @@ static EFI_STATUS enter_mok_menu(EFI_HANDLE image_handle, - } - - if (MokPW) { -- menu_item[i].text = StrDuplicate(L"Set MOK password"); -- menu_item[i].colour = EFI_WHITE; -+ item_text[i] = L"Set MOK password"; - menu_item[i].callback = mok_pw_prompt; - menu_item[i].data = MokPW; - menu_item[i].data2 = (void *)MokPWSize; - i++; - } - -- menu_item[i].text = StrDuplicate(L"Enroll key from disk"); -- menu_item[i].colour = EFI_WHITE; -+ item_text[i] = L"Enroll key from disk"; - menu_item[i].callback = find_file; - menu_item[i].data3 = (void *)FALSE; - - i++; - -- menu_item[i].text = StrDuplicate(L"Enroll hash from disk"); -- menu_item[i].colour = EFI_WHITE; -+ item_text[i] = L"Enroll hash from disk"; - menu_item[i].callback = find_file; - menu_item[i].data3 = (void *)TRUE; - - i++; - -- run_menu(NULL, 0, menu_item, menucount, 10); -+ title[0] = PoolPrint (L"%s UEFI key management", SHIM_VENDOR); -+ title[1] = NULL; ++} + + 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 done; ++ goto out; + -+ while (1) { -+ opt = console_select(title, item_text, 0); -+ if (opt == -1 || opt == 0) -+ break; - -+ if (menu_item[opt].callback) { -+ menu_item[opt].callback(menu_item[opt].data, -+ menu_item[opt].data2, -+ menu_item[opt].data3); -+ } -+ } -+ -+done: - uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut); - -+ FreePool(item_text); -+ FreePool(title[0]); -+ - return 0; - } - + while (choice >= 0) { + choice = console_select((CHAR16 *[]){ L"Perform MOK management", NULL }, + menu_strings, 0); -- 1.8.1.4 -From 74cbc9f5a4d6f93de93d93dd0a79796ec560f672 Mon Sep 17 00:00:00 2001 +From 9ff682d251b3d30fae63c026aa0105c49db7db16 Mon Sep 17 00:00:00 2001 From: Gary Ching-Pang Lin -Date: Thu, 18 Apr 2013 17:52:46 +0800 -Subject: [PATCH 07/12] Remove the duplicate get_keystroke() +Date: Wed, 26 Jun 2013 12:23:26 +0800 +Subject: [PATCH 3/8] MokManager: remove the duplicate get_keystroke() --- - MokManager.c | 16 ++-------------- - 1 file changed, 2 insertions(+), 14 deletions(-) + MokManager.c | 14 +------------- + 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/MokManager.c b/MokManager.c -index c1a726d..8c52121 100644 +index 6b8c79b..6555a06 100644 --- a/MokManager.c +++ b/MokManager.c -@@ -67,18 +67,6 @@ static EFI_STATUS get_variable (CHAR16 *name, EFI_GUID guid, UINT32 *attributes, +@@ -58,18 +58,6 @@ static EFI_STATUS get_variable (CHAR16 *name, EFI_GUID guid, UINT32 *attributes, return efi_status; } @@ -9550,16 +202,7 @@ index c1a726d..8c52121 100644 static EFI_STATUS get_sha1sum (void *Data, int DataSize, UINT8 *hash) { EFI_STATUS status; -@@ -426,7 +414,7 @@ static INTN get_number () - int count = 0; - - do { -- input_key = get_keystroke(); -+ input_key = console_get_keystroke(); - - if ((input_key.UnicodeChar < '0' || - input_key.UnicodeChar > '9' || -@@ -517,7 +505,7 @@ static UINT8 get_line (UINT32 *length, CHAR16 *line, UINT32 line_max, UINT8 show +@@ -538,7 +526,7 @@ static UINT8 get_line (UINT32 *length, CHAR16 *line, UINT32 line_max, UINT8 show int count = 0; do { @@ -9572,413 +215,20 @@ index c1a726d..8c52121 100644 1.8.1.4 -From d9073c96d9bb51cca75cd10b32ad79fef9ce3217 Mon Sep 17 00:00:00 2001 +From 4c9f6b0b2100f5e878d8578db3ee232c20440735 Mon Sep 17 00:00:00 2001 From: Gary Ching-Pang Lin -Date: Fri, 3 May 2013 17:06:56 +0800 -Subject: [PATCH 08/12] Revamp the key enrollment UI +Date: Wed, 26 Jun 2013 15:21:35 +0800 +Subject: [PATCH 4/8] MokManager: enhance the password prompt --- - MokManager.c | 439 ++++++++++++++++++++++++++++++++++------------------------- - 1 file changed, 254 insertions(+), 185 deletions(-) + MokManager.c | 106 +++++++++++++++++++++++++++++++++++++++++++++-------------- + 1 file changed, 81 insertions(+), 25 deletions(-) diff --git a/MokManager.c b/MokManager.c -index 8c52121..27887c4 100644 +index 6555a06..4393aec 100644 --- a/MokManager.c +++ b/MokManager.c -@@ -189,17 +189,6 @@ static MokListNode *build_mok_list(UINT32 num, void *Data, UINTN DataSize) { - return list; - } - --static void print_x509_name (X509_NAME *X509Name, CHAR16 *name) --{ -- char *str; -- -- str = X509_NAME_oneline(X509Name, NULL, 0); -- if (str) { -- Print(L" %s:\n %a\n", name, str); -- OPENSSL_free(str); -- } --} -- - static const char *mon[12]= { - "Jan","Feb","Mar","Apr","May","Jun", - "Jul","Aug","Sep","Oct","Nov","Dec" -@@ -304,157 +293,165 @@ error: - return; - } - --static void print_x509_time (ASN1_TIME *time, CHAR16 *name) -+static void put_x509_time (ASN1_TIME *time, CHAR16 *output) - { -- CHAR16 time_string[30]; -- - if (time->type == V_ASN1_UTCTIME) { -- print_x509_UTCTIME_time(time, time_string); -+ print_x509_UTCTIME_time(time, output); - } else if (time->type == V_ASN1_GENERALIZEDTIME) { -- print_x509_GENERALIZEDTIME_time(time, time_string); -+ print_x509_GENERALIZEDTIME_time(time, output); - } else { -- time_string[0] = '\0'; -+ output[0] = '\0'; - } -- -- Print(L" %s:\n %s\n", name, time_string); - } - --static void show_x509_info (X509 *X509Cert) -+static int get_common_name (X509_NAME *X509Name, CHAR16 *output, int max) - { -- ASN1_INTEGER *serial; -- BIGNUM *bnser; -- unsigned char hexbuf[30]; -- X509_NAME *X509Name; -- ASN1_TIME *time; -+ CHAR8 *full, *ptr, *cn = NULL; -+ int i, full_len; - -- 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]); -- } -- Print(L"%02x\n", hexbuf[n-1]); -- } -+ if (!output) -+ return -1; - -- X509Name = X509_get_issuer_name(X509Cert); -- if (X509Name) { -- print_x509_name(X509Name, L"Issuer"); -+ if (!X509Name) { -+ output[0] = '\0'; -+ return 0; - } - -- X509Name = X509_get_subject_name(X509Cert); -- if (X509Name) { -- print_x509_name(X509Name, L"Subject"); -+ full = (CHAR8 *)X509_NAME_oneline(X509Name, NULL, 0); -+ full_len = strlena(full); -+ -+ for (ptr = full, i = 0; i < (full_len -4) ; ptr++, i++) { -+ if (strncmpa(ptr, (CHAR8 *)"/CN=", 4) == 0) { -+ cn = ptr+4; -+ break; -+ } - } - -- time = X509_get_notBefore(X509Cert); -- if (time) { -- print_x509_time(time, L"Validity from"); -+ if (!cn) { -+ output[0] = '\0'; -+ return 0; - } - -- time = X509_get_notAfter(X509Cert); -- if (time) { -- print_x509_time(time, L"Validity till"); -+ for (ptr = cn, i = 0; i < max; ptr++, i++) { -+ if (*ptr == '\0' || *ptr == '/') -+ break; -+ output[i] = (CHAR16)*ptr; - } -+ output[i] = '\0'; -+ -+ return 0; - } - - static void show_mok_info (void *Mok, UINTN MokSize) - { - EFI_STATUS efi_status; - UINT8 hash[SHA1_DIGEST_SIZE]; -- unsigned int i; -+ CHAR16 *title[19]; -+ INTN start; - X509 *X509Cert; -+ X509_NAME *X509Name; -+ CHAR16 issuer[80], subject[80]; -+ ASN1_TIME *time; -+ CHAR16 str_from[30], str_till[30]; -+ CHAR16 hash_line[2][40]; - - if (!Mok || MokSize == 0) - 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); -+ title[0] = L"X509 certificate"; -+ title[1] = L""; - -- if (efi_status != EFI_SUCCESS) { -- Print(L"Failed to compute MOK fingerprint\n"); -- 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) { -+ title[2] = L"Not a valid X509 certificate"; -+ title[3] = NULL; -+ goto done; - } -- } 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 "); -+ start = 2; -+ -+ title[start] = L"[Issuer]"; -+ X509Name = X509_get_issuer_name(X509Cert); -+ get_common_name(X509Name, issuer, 80); -+ title[start + 1] = issuer; -+ title[start + 2] = L""; -+ -+ title[start + 3] = L"[Subject]"; -+ X509Name = X509_get_subject_name(X509Cert); -+ get_common_name(X509Name, subject, 80); -+ title[start + 4] = subject; -+ title[start + 5] = L""; -+ -+ title[start + 6] = L"[Valid Not Before]"; -+ time = X509_get_notBefore(X509Cert); -+ if (time) { -+ put_x509_time(time, str_from); -+ title[start + 7] = str_from; -+ } else { -+ title[start + 7] = L""; - } -- Print(L"\n"); -- } -+ title[start + 8] = L""; - -- Print(L"\n"); --} -- --static INTN get_number () --{ -- EFI_INPUT_KEY input_key; -- CHAR16 input[10]; -- int count = 0; -- -- do { -- input_key = console_get_keystroke(); -- -- if ((input_key.UnicodeChar < '0' || -- input_key.UnicodeChar > '9' || -- count >= 10) && -- input_key.UnicodeChar != CHAR_BACKSPACE) { -- continue; -+ title[start + 9] = L"[Valid Not After]"; -+ time = X509_get_notAfter(X509Cert); -+ if (time) { -+ put_x509_time(time, str_till); -+ title[start + 10] = str_till; -+ } else { -+ title[start + 10] = L""; - } -+ title[start + 11] = L""; - -- if (count == 0 && input_key.UnicodeChar == CHAR_BACKSPACE) -- continue; -+ X509_free(X509Cert); - -- Print(L"%c", input_key.UnicodeChar); -- -- if (input_key.UnicodeChar == CHAR_BACKSPACE) { -- input[--count] = '\0'; -- continue; -+ title[start + 12] = L"[Fingerprint (SHA1)]"; -+ efi_status = get_sha1sum(Mok, MokSize, hash); -+ if (efi_status != EFI_SUCCESS) { -+ title[start + 13] = L"Failed to compute MOK fingerprint"; -+ title[start + 14] = L""; -+ } else { -+ SPrint(hash_line[0], 0, L"%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x", -+ hash[0], hash[1], hash[2], hash[3], hash[4], -+ hash[5], hash[6], hash[7], hash[8], hash[9]); -+ SPrint(hash_line[1], 0, L"%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x", -+ hash[10], hash[11], hash[12], hash[13], hash[14], -+ hash[15], hash[16], hash[17], hash[18], hash[19]); -+ title[start + 13] = hash_line[0]; -+ title[start + 14] = hash_line[1]; - } - -- input[count++] = input_key.UnicodeChar; -- } while (input_key.UnicodeChar != CHAR_CARRIAGE_RETURN); -+ title[start + 15] = NULL; -+ } else { -+ title[0] = L"SHA256 hash"; -+ title[1] = title[2] = L""; - -- if (count == 0) -- return -1; - -- input[count] = '\0'; -+ SPrint(hash_line[0], 0, L"%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x", -+ hash[0], hash[1], hash[2], hash[3], hash[4], -+ hash[5], hash[6], hash[7], hash[8], hash[9]); -+ SPrint(hash_line[1], 0, L"%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x", -+ hash[10], hash[11], hash[12], hash[13], hash[14], -+ hash[15], hash[16], hash[17], hash[18], hash[19]); -+ title[3] = hash_line[0]; -+ title[4] = hash_line[1]; -+ title[5] = NULL; -+ } - -- return (INTN)Atoi(input); -+done: -+ console_print_box(title, -1); - } - - static UINT8 list_keys (void *KeyList, UINTN KeyListSize, CHAR16 *title) - { - UINT32 MokNum = 0; - MokListNode *keys = NULL; -- INTN key_num = 0; -- UINT8 initial = 1; -+ CHAR16 *selector_title[2]; -+ CHAR16 **opt_text; -+ INTN i, opt = 0; - - if (KeyListSize < (sizeof(EFI_SIGNATURE_LIST) + - sizeof(EFI_SIGNATURE_DATA))) { -- Print(L"No keys\n"); -- Pause(); -+ console_errorbox(L"No Key in the list."); - return 0; - } - -@@ -462,38 +459,46 @@ 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_errorbox(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); -- } -+ if (MokNum == 1) { -+ show_mok_info(keys[0].Mok, keys[0].MokSize); -+ FreePool(keys); -+ return 1; -+ } - -- Print(L"Key Number: "); -+ selector_title[0] = title; -+ selector_title[1] = NULL; - -- key_num = get_number(); -+ opt_text = AllocateZeroPool(sizeof(CHAR16 *) * (MokNum + 2)); -+ if (!opt_text) { -+ console_errorbox(L"Failed to allocate buffer"); -+ return 0; -+ } - -- Print(L"\n\n"); -+ opt_text[0] = L"Back"; -+ for (i = 0; i < MokNum; i++) { -+ opt_text[i+1] = PoolPrint(L"Mok-%02d", i+1); -+ if (!opt_text[i+1]) { -+ console_errorbox(L"Failed to allocate buffer"); -+ return 0; -+ } -+ } - -- if (key_num == -1) -- continue; -+ while(1) { -+ opt = console_select(selector_title, opt_text, opt); - -- initial = 0; -- } while (key_num != 0); -+ if (opt == 0 || opt == -1) -+ break; -+ else -+ show_mok_info(keys[opt-1].Mok, keys[opt-1].MokSize); -+ } - -+ for (i = 0; i < MokNum; i++) -+ FreePool(opt_text[i+1]); -+ FreePool(opt_text); - FreePool(keys); - - return 1; -@@ -550,32 +555,32 @@ static EFI_STATUS compute_pw_hash (void *Data, UINTN DataSize, UINT8 *password, - ctx = AllocatePool(ctxsize); - - if (!ctx) { -- Print(L"Unable to allocate memory for hash context\n"); -+ console_errorbox(L"Unable to allocate memory for hash context"); - return EFI_OUT_OF_RESOURCES; - } - - if (!Sha256Init(ctx)) { -- Print(L"Unable to initialise hash\n"); -+ console_errorbox(L"Unable to initialise hash"); - status = EFI_OUT_OF_RESOURCES; - goto done; - } - - if (Data && DataSize) { - if (!(Sha256Update(ctx, Data, DataSize))) { -- Print(L"Unable to generate hash\n"); -+ console_errorbox(L"Unable to generate hash"); - status = EFI_OUT_OF_RESOURCES; - goto done; - } - } - - if (!(Sha256Update(ctx, password, pw_length))) { -- Print(L"Unable to generate hash\n"); -+ console_errorbox(L"Unable to generate hash"); - status = EFI_OUT_OF_RESOURCES; - goto done; - } - - if (!(Sha256Final(ctx, hash))) { -- Print(L"Unable to finalise hash\n"); -+ console_errorbox(L"Unable to finalise hash"); - status = EFI_OUT_OF_RESOURCES; - goto done; - } -@@ -585,6 +590,61 @@ done: +@@ -606,6 +606,61 @@ done: return status; } @@ -10040,7 +290,7 @@ index 8c52121..27887c4 100644 static EFI_STATUS match_password (PASSWORD_CRYPT *pw_crypt, void *Data, UINTN DataSize, UINT8 *auth, CHAR16 *prompt) -@@ -611,15 +671,10 @@ static EFI_STATUS match_password (PASSWORD_CRYPT *pw_crypt, +@@ -632,15 +687,10 @@ static EFI_STATUS match_password (PASSWORD_CRYPT *pw_crypt, } while (fail_count < 3) { @@ -10058,7 +308,7 @@ index 8c52121..27887c4 100644 fail_count++; continue; } -@@ -642,13 +697,13 @@ static EFI_STATUS match_password (PASSWORD_CRYPT *pw_crypt, +@@ -663,13 +713,13 @@ static EFI_STATUS match_password (PASSWORD_CRYPT *pw_crypt, pw_length * sizeof(CHAR16), hash); } if (status != EFI_SUCCESS) { @@ -10074,464 +324,30 @@ index 8c52121..27887c4 100644 fail_count++; continue; } -@@ -678,7 +733,7 @@ static EFI_STATUS store_keys (void *MokNew, UINTN MokNewSize, int authenticate) - if (efi_status != EFI_SUCCESS || - (auth_size != SHA256_DIGEST_SIZE && - auth_size != PASSWORD_CRYPT_SIZE)) { -- Print(L"Failed to get MokAuth %d\n", efi_status); -+ console_error(L"Failed to get MokAuth", efi_status); - return efi_status; - } - -@@ -711,33 +766,58 @@ static EFI_STATUS store_keys (void *MokNew, UINTN MokNewSize, int authenticate) - } - - 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; - } - - return EFI_SUCCESS; - } - --static UINTN mok_enrollment_prompt (void *MokNew, UINTN MokNewSize, int auth) { -+static void restart_system() -+{ -+ console_print_box((CHAR16 *[]){L"Press a key to reboot system", NULL}, -1); -+ -+ uefi_call_wrapper(RT->ResetSystem, 4, EfiResetWarm, EFI_SUCCESS, -+ 0, NULL); -+ -+ console_errorbox(L"Failed to reboot"); -+} -+ -+static UINTN mok_enrollment_prompt (void *MokNew, UINTN MokNewSize, int auth) -+{ - EFI_GUID shim_lock_guid = SHIM_LOCK_GUID; -- CHAR16 line[1]; -- UINT32 length; -- EFI_STATUS efi_status; -+ EFI_STATUS status; -+ CHAR16 *title[2]; -+ CHAR16 *opt_text[4]; -+ CHAR16 *enroll_text[4]; -+ INTN opt = 0; - -- do { -- if (!list_keys(MokNew, MokNewSize, L"[Enroll MOK]")) { -- return 0; -- } -+ title[0] = L"Enroll MOK"; -+ title[1] = NULL; - -- Print(L"Enroll the key(s)? (y/n): "); -+ opt_text[0] = L"Enroll"; -+ opt_text[1] = L"Show details"; -+ opt_text[2] = L"Cancel"; -+ opt_text[3] = NULL; - -- get_line (&length, line, 1, 1); -+ enroll_text[0] = L"Enroll MOK"; -+ enroll_text[1] = L""; -+ enroll_text[2] = L"Do you want to enroll the key(s)?"; -+ enroll_text[3] = NULL; - -- if (line[0] == 'Y' || line[0] == 'y') { -- efi_status = store_keys(MokNew, MokNewSize, auth); -+ while (1) { -+ opt = console_select(title, opt_text, opt); - -- if (efi_status != EFI_SUCCESS) { -- Print(L"Failed to enroll keys\n"); -+ if (opt == -1 || opt == 2) -+ break; -+ -+ if (opt == 0) { -+ if (console_yes_no(enroll_text) == 0) -+ break; -+ -+ status = store_keys(MokNew, MokNewSize, auth); -+ if (status != EFI_SUCCESS) { -+ console_errorbox(L"Failed to enroll keys"); - return -1; - } - -@@ -745,18 +825,16 @@ static UINTN mok_enrollment_prompt (void *MokNew, UINTN MokNewSize, int auth) { - 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"); -+ restart_system(); - return -1; - } -- -- return 0; -+ break; -+ } else if (opt == 1) { -+ list_keys(MokNew, MokNewSize, L"Keys to be enrolled"); - } -- } while (line[0] != 'N' && line[0] != 'n'); -- return -1; -+ } -+ -+ return 0; - } - - static INTN mok_enrollment_prompt_callback (void *MokNew, void *data2, -@@ -1173,10 +1251,7 @@ static int draw_countdown() - CHAR16 *message = L"Press any key to enter management menu"; - 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; -@@ -1209,13 +1284,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; - } --- -1.8.1.4 - - -From 5364b826a40dfb76e58c20d7ff8e2fd4e98f40d6 Mon Sep 17 00:00:00 2001 -From: Gary Ching-Pang Lin -Date: Fri, 3 May 2013 17:58:38 +0800 -Subject: [PATCH 09/12] Revamp the key deletion UI - ---- - MokManager.c | 60 ++++++++++++++++++++++++++++++++++++++---------------------- - 1 file changed, 38 insertions(+), 22 deletions(-) - -diff --git a/MokManager.c b/MokManager.c -index 27887c4..6883cb1 100644 ---- a/MokManager.c -+++ b/MokManager.c -@@ -959,7 +959,7 @@ static EFI_STATUS delete_keys (void *MokDel, UINTN MokDelSize) - - if (efi_status != EFI_SUCCESS || - (auth_size != SHA256_DIGEST_SIZE && auth_size != PASSWORD_CRYPT_SIZE)) { -- Print(L"Failed to get MokDelAuth %d\n", efi_status); -+ console_error(L"Failed to get MokDelAuth", efi_status); - return efi_status; - } - -@@ -976,9 +976,13 @@ 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"ERROR", -+ L"", -+ 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_errorbox(L"Failed to erase MokList"); - } - return EFI_ACCESS_DENIED; - } -@@ -1023,38 +1027,50 @@ static INTN mok_deletion_prompt (void *MokDel, void *data2, void *data3) - { - EFI_GUID shim_lock_guid = SHIM_LOCK_GUID; - UINTN MokDelSize = (UINTN)data2; -- CHAR16 line[1]; -- UINT32 length; -- EFI_STATUS efi_status; -+ EFI_STATUS status; -+ CHAR16 *title[2]; -+ CHAR16 *opt_text[4]; -+ CHAR16 *delete_text[4]; -+ INTN opt = 0; - -- do { -- if (!list_keys(MokDel, MokDelSize, L"[Delete MOK]")) { -- return 0; -- } -+ title[0] = L"Delete MOK"; -+ title[1] = NULL; - -- Print(L"Delete the key(s)? (y/n): "); -+ opt_text[0] = L"Delete"; -+ opt_text[1] = L"Show details"; -+ opt_text[2] = L"Cancel"; -+ opt_text[3] = NULL; - -- get_line (&length, line, 1, 1); -+ delete_text[0] = L"Delete MOK"; -+ delete_text[1] = L""; -+ delete_text[2] = L"Do you want to delete the key(s)?"; -+ delete_text[3] = NULL; - -- if (line[0] == 'Y' || line[0] == 'y') { -- efi_status = delete_keys(MokDel, MokDelSize); -+ while (1) { -+ opt = console_select(title, opt_text, opt); - -- if (efi_status != EFI_SUCCESS) { -- Print(L"Failed to delete keys\n"); -+ if (opt == -1 || opt == 2) -+ break; -+ -+ if (opt == 0) { -+ if (console_yes_no(delete_text) == 0) -+ break; -+ -+ status = delete_keys(MokDel, MokDelSize); -+ if (status != EFI_SUCCESS) { -+ console_errorbox(L"Failed to delete keys"); - return -1; - } - - 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"); -+ restart_system(); - return -1; -+ } else if (opt == 1) { -+ list_keys(MokDel, MokDelSize, L"Keys to be deleted"); - } -- } while (line[0] != 'N' && line[0] != 'n'); -+ } - return -1; - } - --- -1.8.1.4 - - -From bcd5b4fb1489888af4310c63f6429120700b78ad Mon Sep 17 00:00:00 2001 -From: Gary Ching-Pang Lin -Date: Fri, 3 May 2013 18:05:22 +0800 -Subject: [PATCH 10/12] Revamp the key reset UI - ---- - MokManager.c | 39 ++++++++++++++++----------------------- - 1 file changed, 16 insertions(+), 23 deletions(-) - -diff --git a/MokManager.c b/MokManager.c -index 6883cb1..59e2b2d 100644 ---- a/MokManager.c -+++ b/MokManager.c -@@ -847,35 +847,28 @@ static INTN mok_enrollment_prompt_callback (void *MokNew, void *data2, - static INTN mok_reset_prompt (void *MokNew, void *data2, void *data3) - { - 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); -+ EFI_STATUS status; -+ CHAR16 *erase_text[4]; - -- if (line[0] == 'Y' || line[0] == 'y') { -- efi_status = store_keys(NULL, 0, TRUE); -+ erase_text[0] = L"Reset MOK"; -+ erase_text[1] = L""; -+ erase_text[2] = L"Do you want to erase all keys?"; -+ erase_text[3] = NULL; - -- if (efi_status != EFI_SUCCESS) { -- Print(L"Failed to erase keys\n"); -- return -1; -- } -- -- LibDeleteVariable(L"MokNew", &shim_lock_guid); -- LibDeleteVariable(L"MokAuth", &shim_lock_guid); -+ if (console_yes_no(erase_text) == 0) -+ return 0; - -- 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"); -+ status = store_keys(NULL, 0, TRUE); -+ if (status != EFI_SUCCESS) { -+ console_errorbox(L"Failed to erase keys"); - return -1; - } - -- return 0; -+ LibDeleteVariable(L"MokNew", &shim_lock_guid); -+ LibDeleteVariable(L"MokAuth", &shim_lock_guid); -+ -+ restart_system(); -+ return -1; - } - - static EFI_STATUS write_back_mok_list (MokListNode *list, INTN key_num) --- -1.8.1.4 - - -From f4a5f4fb0c3b57f3801d9d7d28a3ea3d3a58ff5e Mon Sep 17 00:00:00 2001 -From: Gary Ching-Pang Lin -Date: Mon, 6 May 2013 15:53:49 +0800 -Subject: [PATCH 11/12] Revamp the lockdown password UI - ---- - MokManager.c | 90 +++++++++++++++++++++++++++++++----------------------------- - 1 file changed, 46 insertions(+), 44 deletions(-) - -diff --git a/MokManager.c b/MokManager.c -index 59e2b2d..9c37a44 100644 ---- a/MokManager.c -+++ b/MokManager.c -@@ -1171,14 +1171,15 @@ static INTN mok_pw_prompt (void *MokPW, void *data2, void *data3) { - UINTN MokPWSize = (UINTN)data2; - UINT8 hash[PASSWORD_CRYPT_SIZE]; - UINT8 clear = 0; -- UINT32 length; -- CHAR16 line[1]; -+ CHAR16 *pw_text[2]; - - if (MokPWSize != SHA256_DIGEST_SIZE && MokPWSize != PASSWORD_CRYPT_SIZE) { - Print(L"Invalid MokPW variable contents\n"); - return -1; - } - -+ pw_text[1] = NULL; -+ - uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut); - - SetMem(hash, PASSWORD_CRYPT_SIZE, 0); -@@ -1192,60 +1193,47 @@ static INTN mok_pw_prompt (void *MokPW, void *data2, void *data3) { - } - - if (clear) { -- Print(L"Clear MOK password? (y/n): "); -- -- do { -- get_line (&length, line, 1, 1); -+ pw_text[0] = L"Clear MOK lockdown password?"; - -- 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(pw_text) == 1) { -+ LibDeleteVariable(L"MokPWStore", &shim_lock_guid); -+ LibDeleteVariable(L"MokPW", &shim_lock_guid); -+ } - - return 0; - } - - if (MokPWSize == PASSWORD_CRYPT_SIZE) { - efi_status = match_password((PASSWORD_CRYPT *)MokPW, NULL, 0, -- NULL, L"Confirm MOK passphrase: "); -+ NULL, L"Confirm MOK password:"); - } else { - efi_status = match_password(NULL, NULL, 0, MokPW, -- L"Confirm MOK passphrase: "); -+ L"Confirm MOK password:"); - } - - if (efi_status != EFI_SUCCESS) { -- Print(L"Password limit reached\n"); -+ console_errorbox(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, -+ pw_text[0] = L"Set MOK lockdown password?"; -+ if (console_yes_no(pw_text) == 1) { -+ 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"); -+ MokPWSize, MokPW); -+ if (efi_status != EFI_SUCCESS) { -+ console_errorbox(L"Failed to set MOK lockdown password"); - return -1; - } -- } while (line[0] != 'N' && line[0] != 'n'); -+ -+ LibDeleteVariable(L"MokPW", &shim_lock_guid); -+ -+ restart_system(); -+ return -1; -+ } - - return 0; - } -@@ -1467,13 +1455,17 @@ out: - return 0; +@@ -1307,13 +1357,17 @@ static void mok_key_enroll(void) + FreePool(data); } -static BOOLEAN verify_pw(void) -+static BOOLEAN verify_pw(UINT8 *protected) ++static BOOLEAN verify_pw(BOOLEAN *protected) { -+ SIMPLE_TEXT_OUTPUT_MODE SavedMode; 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 = 0; ++ *protected = FALSE; efi_status = uefi_call_wrapper(RT->GetVariable, 5, L"MokPWStore", &shim_lock_guid, &attributes, &size, -@@ -1493,18 +1485,27 @@ static BOOLEAN verify_pw(void) +@@ -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; @@ -10549,63 +365,1410 @@ index 59e2b2d..9c37a44 100644 + L"Enter MOK password:"); } if (efi_status != EFI_SUCCESS) { -- Print(L"Password limit reached\n"); -+ console_errorbox(L"Password limit reached"); + console_notify(L"Password limit reached"); return FALSE; } -+ *protected = 1; ++ *protected = TRUE; + return TRUE; } -@@ -1525,8 +1526,9 @@ static EFI_STATUS enter_mok_menu(EFI_HANDLE image_handle, +@@ -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; -+ UINT8 protected; ++ 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", -@@ -1598,7 +1600,7 @@ static EFI_STATUS enter_mok_menu(EFI_HANDLE image_handle, - } +@@ -1522,7 +1578,7 @@ static EFI_STATUS enter_mok_menu(EFI_HANDLE image_handle, - if (MokPW) { -- item_text[i] = L"Set MOK password"; -+ item_text[i] = L"Set MOK lockdown password"; - menu_item[i].callback = mok_pw_prompt; - menu_item[i].data = MokPW; - menu_item[i].data2 = (void *)MokPWSize; -@@ -1620,7 +1622,7 @@ static EFI_STATUS enter_mok_menu(EFI_HANDLE image_handle, - title[0] = PoolPrint (L"%s UEFI key management", SHIM_VENDOR); - title[1] = NULL; + menu_strings[i] = NULL; - if (draw_countdown() == 0) -+ if (protected == 0 && draw_countdown() == 0) - goto done; ++ if (protected == FALSE && draw_countdown() == 0) + goto out; - while (1) { + while (choice >= 0) { -- 1.8.1.4 -From 7ab54bd23e9bc412fa581e166c8f214df44604c5 Mon Sep 17 00:00:00 2001 +From 6e71cb7900b99482c7b51a6076f8392022ba15a6 Mon Sep 17 00:00:00 2001 From: Gary Ching-Pang Lin -Date: Mon, 6 May 2013 17:19:47 +0800 -Subject: [PATCH 12/12] Revamp the Secure Boot state setting UI +Date: Thu, 27 Jun 2013 11:59:09 +0800 +Subject: [PATCH 5/8] 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 6/8] 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 7/8] MokManager: rearrange the output of MOK info --- - MokManager.c | 129 ++++++++++++++++++++++++++++++++++++++--------------------- - 1 file changed, 84 insertions(+), 45 deletions(-) + MokManager.c | 239 ++++++++++++++++++++--------------------------------------- + 1 file changed, 81 insertions(+), 158 deletions(-) diff --git a/MokManager.c b/MokManager.c -index 9c37a44..5b0c70c 100644 +index 4393aec..8b770ff 100644 --- a/MokManager.c +++ b/MokManager.c -@@ -1067,25 +1067,57 @@ static INTN mok_deletion_prompt (void *MokDel, void *data2, void *data3) +@@ -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 8/8] 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; } @@ -10633,27 +1796,20 @@ index 9c37a44..5b0c70c 100644 + return character; +} + - static INTN mok_sb_prompt (void *MokSB, void *data2, void *data3) { -+ SIMPLE_TEXT_OUTPUT_MODE SavedMode; + static INTN mok_sb_prompt (void *MokSB, UINTN MokSBSize) { EFI_GUID shim_lock_guid = SHIM_LOCK_GUID; -- EFI_STATUS efi_status; -+ EFI_STATUS status; - UINTN MokSBSize = (UINTN)data2; + 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; -- CHAR16 line[1]; UINT8 sbval = 1; UINT8 pos1, pos2, pos3; - - if (MokSBSize != sizeof(MokSBvar)) { -- Print(L"Invalid MokSB variable contents\n"); -+ console_errorbox(L"Invalid MokSB variable contents"); - return -1; - } + int ret; +@@ -960,6 +986,13 @@ static INTN mok_sb_prompt (void *MokSB, UINTN MokSBSize) { uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut); @@ -10667,7 +1823,7 @@ index 9c37a44..5b0c70c 100644 while (fail_count < 3) { RandomBytes (&pos1, sizeof(pos1)); pos1 = (pos1 % var->PWLen); -@@ -1100,19 +1132,34 @@ static INTN mok_sb_prompt (void *MokSB, void *data2, void *data3) { +@@ -974,14 +1007,29 @@ static INTN mok_sb_prompt (void *MokSB, UINTN MokSBSize) { pos3 = (pos3 % var->PWLen) ; } while (pos3 == pos2 || pos3 == pos1); @@ -10703,85 +1859,6 @@ index 9c37a44..5b0c70c 100644 if (pass1 != var->Password[pos1] || pass2 != var->Password[pos2] || - pass3 != var->Password[pos3]) { -- Print(L"Invalid character\n"); -+ console_errorbox(L"Invalid character"); - fail_count++; - } else { - break; -@@ -1120,46 +1167,38 @@ static INTN mok_sb_prompt (void *MokSB, void *data2, void *data3) { - } - - if (fail_count >= 3) { -- Print(L"Password limit reached\n"); -+ console_errorbox(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): "); -- } -- -- do { -- get_line (&length, line, 1, 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, -- 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); -+ message[1] = L""; -+ if (var->MokSBState == 0) -+ message[2] = L"Disable Secure Boot?"; -+ else -+ message[2] = L"Enable Secure Boot?"; -+ message[3] = NULL; -+ -+ if (console_yes_no(message) == 1) { -+ if (var->MokSBState == 0) { -+ status = uefi_call_wrapper(RT->SetVariable, -+ 5, L"MokSBState", -+ &shim_lock_guid, -+ EFI_VARIABLE_NON_VOLATILE | -+ EFI_VARIABLE_BOOTSERVICE_ACCESS, -+ 1, &sbval); -+ if (status != EFI_SUCCESS) { -+ console_errorbox(L"Failed to set Secure Boot state"); -+ return -1; - } -+ } else { -+ LibDeleteVariable(L"MokSBState", &shim_lock_guid); -+ } - -- LibDeleteVariable(L"MokSB", &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"); -- return -1; -- } -- } while (line[0] != 'N' && line[0] != 'n'); -+ restart_system(); -+ return -1; -+ } - - return -1; - } -- 1.8.1.4 diff --git a/shim-reboot-after-changes.patch b/shim-reboot-after-changes.patch deleted file mode 100644 index 9256720..0000000 --- a/shim-reboot-after-changes.patch +++ /dev/null @@ -1,94 +0,0 @@ -From 10f0f58b03b3bcc56797744f25be15b226b51a50 Mon Sep 17 00:00:00 2001 -From: Gary Ching-Pang Lin -Date: Mon, 10 Dec 2012 17:54:05 +0800 -Subject: [PATCH 1/2] Clear the screen before erasing keys - ---- - MokManager.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/MokManager.c b/MokManager.c -index 5802d27..c6f84d8 100644 ---- a/MokManager.c -+++ b/MokManager.c -@@ -675,6 +675,7 @@ static INTN mok_deletion_prompt (void *MokNew, void *data2, void *data3) { - 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); --- -1.7.10.4 - - -From 510dafda53cd56210d7ff634b1c630d3645150f0 Mon Sep 17 00:00:00 2001 -From: Gary Ching-Pang Lin -Date: Mon, 10 Dec 2012 18:24:45 +0800 -Subject: [PATCH 2/2] Reboot the system after enrolling/erasing keys - ---- - MokManager.c | 25 +++++++++++++++++++++++++ - 1 file changed, 25 insertions(+) - -diff --git a/MokManager.c b/MokManager.c -index c6f84d8..7d6650e 100644 ---- a/MokManager.c -+++ b/MokManager.c -@@ -637,6 +637,7 @@ static EFI_STATUS store_keys (void *MokNew, UINTN MokNewSize, int authenticate) - } - - static UINTN mok_enrollment_prompt (void *MokNew, UINTN MokNewSize, int auth) { -+ EFI_GUID shim_lock_guid = SHIM_LOCK_GUID; - CHAR16 line[1]; - UINT32 length; - EFI_STATUS efi_status; -@@ -657,6 +658,19 @@ static UINTN mok_enrollment_prompt (void *MokNew, UINTN MokNewSize, int auth) { - Print(L"Failed to enroll keys\n"); - return -1; - } -+ -+ if (auth) { -+ 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"); -+ return -1; -+ } -+ - return 0; - } - } while (line[0] != 'N' && line[0] != 'n'); -@@ -671,6 +685,7 @@ static INTN mok_enrollment_prompt_callback (void *MokNew, void *data2, - } - - static INTN mok_deletion_prompt (void *MokNew, void *data2, void *data3) { -+ EFI_GUID shim_lock_guid = SHIM_LOCK_GUID; - CHAR16 line[1]; - UINT32 length; - EFI_STATUS efi_status; -@@ -687,6 +702,16 @@ static INTN mok_deletion_prompt (void *MokNew, void *data2, void *data3) { - Print(L"Failed to erase keys\n"); - return -1; - } -+ -+ 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"); -+ return -1; - } - - return 0; --- -1.7.10.4 - diff --git a/shim-support-mok-delete.patch b/shim-support-mok-delete.patch deleted file mode 100644 index 5b08f06..0000000 --- a/shim-support-mok-delete.patch +++ /dev/null @@ -1,763 +0,0 @@ -From 5abe73ab8177f0d831ff04ca67a8ed92ef09ca8b Mon Sep 17 00:00:00 2001 -From: Gary Ching-Pang Lin -Date: Thu, 20 Dec 2012 17:02:35 +0800 -Subject: [PATCH 1/3] Add a general function for password matching - ---- - MokManager.c | 148 ++++++++++++++++++++++------------------------------------ - 1 file changed, 57 insertions(+), 91 deletions(-) - -diff --git a/MokManager.c b/MokManager.c -index 7d6650e..ffe37ff 100644 ---- a/MokManager.c -+++ b/MokManager.c -@@ -558,17 +558,61 @@ done: - return status; - } - -+static EFI_STATUS match_password (void *Data, UINTN DataSize, -+ UINT8 auth[SHA256_DIGEST_SIZE], -+ CHAR16 *prompt) -+{ -+ EFI_STATUS efi_status; -+ UINT8 hash[SHA256_DIGEST_SIZE]; -+ CHAR16 password[PASSWORD_MAX]; -+ UINT32 pw_length; -+ UINT8 fail_count = 0; -+ -+ while (fail_count < 3) { -+ if (prompt) { -+ Print(L"%s", prompt); -+ } else { -+ Print(L"Password: "); -+ } -+ get_line(&pw_length, password, PASSWORD_MAX, 0); -+ -+ if (pw_length < PASSWORD_MIN || pw_length > PASSWORD_MAX) { -+ Print(L"Invalid password length\n"); -+ fail_count++; -+ continue; -+ } -+ -+ efi_status = compute_pw_hash(Data, DataSize, password, -+ pw_length, hash); -+ -+ if (efi_status != EFI_SUCCESS) { -+ Print(L"Unable to generate password hash\n"); -+ fail_count++; -+ continue; -+ } -+ -+ if (CompareMem(auth, hash, SHA256_DIGEST_SIZE) != 0) { -+ Print(L"Password doesn't match\n"); -+ fail_count++; -+ continue; -+ } -+ -+ break; -+ } -+ -+ if (fail_count >= 3) -+ return EFI_ACCESS_DENIED; -+ -+ return EFI_SUCCESS; -+} -+ - static EFI_STATUS store_keys (void *MokNew, UINTN MokNewSize, int authenticate) - { - EFI_GUID shim_lock_guid = SHIM_LOCK_GUID; - EFI_STATUS efi_status; -- UINT8 hash[SHA256_DIGEST_SIZE]; - UINT8 auth[SHA256_DIGEST_SIZE]; - UINTN auth_size; - UINT32 attributes; -- CHAR16 password[PASSWORD_MAX]; -- UINT32 pw_length; -- UINT8 fail_count = 0; - - if (authenticate) { - auth_size = SHA256_DIGEST_SIZE; -@@ -582,32 +626,8 @@ static EFI_STATUS store_keys (void *MokNew, UINTN MokNewSize, int authenticate) - return efi_status; - } - -- while (fail_count < 3) { -- Print(L"Password(%d-%d characters): ", -- PASSWORD_MIN, PASSWORD_MAX); -- get_line(&pw_length, password, PASSWORD_MAX, 0); -- -- if (pw_length < 8) { -- Print(L"At least %d characters for the password\n", -- PASSWORD_MIN); -- } -- -- efi_status = compute_pw_hash(MokNew, MokNewSize, password, -- pw_length, hash); -- -- if (efi_status != EFI_SUCCESS) { -- return efi_status; -- } -- -- if (CompareMem(auth, hash, SHA256_DIGEST_SIZE) != 0) { -- Print(L"Password doesn't match\n"); -- fail_count++; -- } else { -- break; -- } -- } -- -- if (fail_count >= 3) -+ efi_status = match_password(MokNew, MokNewSize, auth, NULL); -+ if (efi_status != EFI_SUCCESS) - return EFI_ACCESS_DENIED; - } - -@@ -819,9 +839,7 @@ static INTN mok_pw_prompt (void *MokPW, void *data2, void *data3) { - EFI_GUID shim_lock_guid = SHIM_LOCK_GUID; - EFI_STATUS efi_status; - UINTN MokPWSize = (UINTN)data2; -- UINT8 fail_count = 0; - UINT8 hash[SHA256_DIGEST_SIZE]; -- CHAR16 password[PASSWORD_MAX]; - UINT32 length; - CHAR16 line[1]; - -@@ -849,34 +867,8 @@ static INTN mok_pw_prompt (void *MokPW, void *data2, void *data3) { - return 0; - } - -- while (fail_count < 3) { -- Print(L"Confirm MOK passphrase: "); -- get_line(&length, password, PASSWORD_MAX, 0); -- -- if ((length < PASSWORD_MIN) || (length > PASSWORD_MAX)) { -- Print(L"Invalid password length\n"); -- fail_count++; -- continue; -- } -- -- efi_status = compute_pw_hash(NULL, 0, password, length, hash); -- -- if (efi_status != EFI_SUCCESS) { -- Print(L"Unable to generate password hash\n"); -- fail_count++; -- continue; -- } -- -- if (CompareMem(MokPW, hash, SHA256_DIGEST_SIZE) != 0) { -- Print(L"Password doesn't match\n"); -- fail_count++; -- continue; -- } -- -- break; -- } -- -- if (fail_count >= 3) { -+ efi_status = match_password(NULL, 0, MokPW, L"Confirm MOK passphrase: "); -+ if (efi_status != EFI_SUCCESS) { - Print(L"Password limit reached\n"); - return -1; - } -@@ -1483,12 +1475,8 @@ static BOOLEAN verify_pw(void) - { - EFI_GUID shim_lock_guid = SHIM_LOCK_GUID; - EFI_STATUS efi_status; -- CHAR16 password[PASSWORD_MAX]; -- UINT8 fail_count = 0; -- UINT8 hash[SHA256_DIGEST_SIZE]; - UINT8 pwhash[SHA256_DIGEST_SIZE]; - UINTN size = SHA256_DIGEST_SIZE; -- UINT32 length; - UINT32 attributes; - - efi_status = uefi_call_wrapper(RT->GetVariable, 5, L"MokPWStore", -@@ -1508,35 +1496,13 @@ static BOOLEAN verify_pw(void) - - uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut); - -- while (fail_count < 3) { -- Print(L"Enter MOK password: "); -- get_line(&length, password, PASSWORD_MAX, 0); -- -- if (length < PASSWORD_MIN || length > PASSWORD_MAX) { -- Print(L"Invalid password length\n"); -- fail_count++; -- continue; -- } -- -- efi_status = compute_pw_hash(NULL, 0, password, length, hash); -- -- if (efi_status != EFI_SUCCESS) { -- Print(L"Unable to generate password hash\n"); -- fail_count++; -- continue; -- } -- -- if (CompareMem(pwhash, hash, SHA256_DIGEST_SIZE) != 0) { -- Print(L"Password doesn't match\n"); -- fail_count++; -- continue; -- } -- -- return TRUE; -+ efi_status = match_password(NULL, 0, pwhash, L"Enter MOK password: "); -+ if (efi_status != EFI_SUCCESS) { -+ Print(L"Password limit reached\n"); -+ return FALSE; - } - -- Print(L"Password limit reached\n"); -- return FALSE; -+ return TRUE; - } - - static EFI_STATUS enter_mok_menu(EFI_HANDLE image_handle, void *MokNew, --- -1.7.10.4 - - -From 0c6a8a7501f2eb4e751c33090c6763044d131b96 Mon Sep 17 00:00:00 2001 -From: Gary Ching-Pang Lin -Date: Fri, 21 Dec 2012 15:02:09 +0800 -Subject: [PATCH 2/3] MOK doesn't include the signature owner - ---- - MokManager.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/MokManager.c b/MokManager.c -index ffe37ff..ddf12de 100644 ---- a/MokManager.c -+++ b/MokManager.c -@@ -124,7 +124,7 @@ 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; -+ list[count].MokSize = CertList->SignatureSize - sizeof(EFI_GUID); - list[count].Mok = (void *)Cert->SignatureData; - - count++; -@@ -317,7 +317,7 @@ static void show_mok_info (void *Mok, UINTN MokSize) - if (!Mok || MokSize == 0) - return; - -- if (MokSize != 48) { -+ if (MokSize != SHA256_DIGEST_SIZE) { - if (X509ConstructCertificate(Mok, MokSize, - (UINT8 **) &X509Cert) && X509Cert != NULL) { - show_x509_info(X509Cert); --- -1.7.10.4 - - -From 990dcdb6a6cea2a22ef237b68630aa30784184c4 Mon Sep 17 00:00:00 2001 -From: Gary Ching-Pang Lin -Date: Fri, 21 Dec 2012 17:59:31 +0800 -Subject: [PATCH 3/3] Add support for deleting specific keys - ---- - MokManager.c | 336 ++++++++++++++++++++++++++++++++++++++++++++++++++-------- - shim.c | 3 +- - 2 files changed, 293 insertions(+), 46 deletions(-) - -diff --git a/MokManager.c b/MokManager.c -index ddf12de..bfcbfd6 100644 ---- a/MokManager.c -+++ b/MokManager.c -@@ -31,6 +31,7 @@ struct menu_item { - typedef struct { - UINT32 MokSize; - UINT8 *Mok; -+ EFI_GUID Type; - } __attribute__ ((packed)) MokListNode; - - typedef struct { -@@ -39,6 +40,32 @@ typedef struct { - CHAR16 Password[PASSWORD_MAX]; - } __attribute__ ((packed)) MokSBvar; - -+static EFI_STATUS get_variable (CHAR16 *name, EFI_GUID guid, UINT32 *attributes, -+ UINTN *size, void **buffer) -+{ -+ EFI_STATUS efi_status; -+ char allocate = !(*size); -+ -+ efi_status = uefi_call_wrapper(RT->GetVariable, 5, name, &guid, -+ attributes, size, buffer); -+ -+ if (efi_status != EFI_BUFFER_TOO_SMALL || !allocate) { -+ return efi_status; -+ } -+ -+ *buffer = AllocatePool(*size); -+ -+ if (!*buffer) { -+ Print(L"Unable to allocate variable buffer\n"); -+ return EFI_OUT_OF_RESOURCES; -+ } -+ -+ efi_status = uefi_call_wrapper(RT->GetVariable, 5, name, &guid, -+ attributes, size, *buffer); -+ -+ return efi_status; -+} -+ - static EFI_INPUT_KEY get_keystroke (void) - { - EFI_INPUT_KEY key; -@@ -88,6 +115,42 @@ done: - return status; - } - -+static UINT32 count_keys(void *Data, UINTN DataSize) -+{ -+ EFI_SIGNATURE_LIST *CertList = Data; -+ EFI_GUID CertType = EfiCertX509Guid; -+ EFI_GUID HashType = EfiHashSha256Guid; -+ UINTN dbsize = DataSize; -+ UINT32 MokNum = 0; -+ -+ 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"); -+ dbsize -= CertList->SignatureListSize; -+ CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + -+ CertList->SignatureListSize); -+ continue; -+ } -+ -+ if ((CompareGuid (&CertList->SignatureType, &CertType) != 0) && -+ (CertList->SignatureSize != 48)) { -+ Print(L"Doesn't look like a valid hash\n"); -+ dbsize -= CertList->SignatureListSize; -+ CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + -+ CertList->SignatureListSize); -+ continue; -+ } -+ -+ MokNum++; -+ dbsize -= CertList->SignatureListSize; -+ CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + -+ CertList->SignatureListSize); -+ } -+ -+ return MokNum; -+} -+ - static MokListNode *build_mok_list(UINT32 num, void *Data, UINTN DataSize) { - MokListNode *list; - EFI_SIGNATURE_LIST *CertList = Data; -@@ -126,6 +189,7 @@ static MokListNode *build_mok_list(UINT32 num, void *Data, UINTN DataSize) { - - list[count].MokSize = CertList->SignatureSize - sizeof(EFI_GUID); - list[count].Mok = (void *)Cert->SignatureData; -+ list[count].Type = CertList->SignatureType; - - count++; - dbsize -= CertList->SignatureListSize; -@@ -391,61 +455,35 @@ static INTN get_number () - return (INTN)Atoi(input); - } - --static UINT8 list_keys (void *MokNew, UINTN MokNewSize) -+static UINT8 list_keys (void *KeyList, UINTN KeyListSize, CHAR16 *title) - { - UINT32 MokNum = 0; - MokListNode *keys = NULL; - INTN key_num = 0; - UINT8 initial = 1; -- EFI_SIGNATURE_LIST *CertList = MokNew; -- EFI_GUID CertType = EfiCertX509Guid; -- EFI_GUID HashType = EfiHashSha256Guid; -- UINTN dbsize = MokNewSize; - -- if (MokNewSize < (sizeof(EFI_SIGNATURE_LIST) + -- sizeof(EFI_SIGNATURE_DATA))) { -+ if (KeyListSize < (sizeof(EFI_SIGNATURE_LIST) + -+ sizeof(EFI_SIGNATURE_DATA))) { - Print(L"No keys\n"); - Pause(); - return 0; - } - -- 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"); -- dbsize -= CertList->SignatureListSize; -- CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + -- CertList->SignatureListSize); -- continue; -- } -- -- if ((CompareGuid (&CertList->SignatureType, &CertType) != 0) && -- (CertList->SignatureSize != 48)) { -- Print(L"Doesn't look like a valid hash\n"); -- dbsize -= CertList->SignatureListSize; -- CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + -- CertList->SignatureListSize); -- continue; -- } -- -- MokNum++; -- dbsize -= CertList->SignatureListSize; -- CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + -- CertList->SignatureListSize); -- } -- -- keys = build_mok_list(MokNum, MokNew, MokNewSize); -+ MokNum = count_keys(KeyList, KeyListSize); -+ keys = build_mok_list(MokNum, KeyList, KeyListSize); - - if (!keys) { -- Print(L"Failed to construct key list in MokNew\n"); -+ Print(L"Failed to construct key list\n"); - 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 new key list\n\n", MokNum); -+ Print(L"%d key(s) in the key list\n\n", MokNum); - - if (key_num > MokNum) { - Print(L"[Key %d]\n", key_num); -@@ -663,7 +701,7 @@ static UINTN mok_enrollment_prompt (void *MokNew, UINTN MokNewSize, int auth) { - EFI_STATUS efi_status; - - do { -- if (!list_keys(MokNew, MokNewSize)) { -+ if (!list_keys(MokNew, MokNewSize, L"[Enroll MOK]")) { - return 0; - } - -@@ -704,7 +742,8 @@ static INTN mok_enrollment_prompt_callback (void *MokNew, void *data2, - return mok_enrollment_prompt(MokNew, (UINTN)data2, TRUE); - } - --static INTN mok_deletion_prompt (void *MokNew, void *data2, void *data3) { -+static INTN mok_reset_prompt (void *MokNew, void *data2, void *data3) -+{ - EFI_GUID shim_lock_guid = SHIM_LOCK_GUID; - CHAR16 line[1]; - UINT32 length; -@@ -737,6 +776,180 @@ static INTN mok_deletion_prompt (void *MokNew, void *data2, void *data3) { - return 0; - } - -+static EFI_STATUS write_back_mok_list (MokListNode *list, INTN key_num) -+{ -+ EFI_GUID shim_lock_guid = SHIM_LOCK_GUID; -+ EFI_STATUS efi_status; -+ EFI_SIGNATURE_LIST *CertList; -+ EFI_SIGNATURE_DATA *CertData; -+ void *Data = NULL, *ptr; -+ INTN DataSize = 0; -+ int i; -+ -+ for (i = 0; i < key_num; i++) { -+ if (list[i].Mok == NULL) -+ continue; -+ -+ DataSize += sizeof(EFI_SIGNATURE_LIST) + sizeof(EFI_GUID); -+ DataSize += list[i].MokSize; -+ } -+ -+ Data = AllocatePool(DataSize); -+ if (Data == NULL && DataSize != 0) -+ return EFI_OUT_OF_RESOURCES; -+ -+ ptr = Data; -+ -+ for (i = 0; i < key_num; i++) { -+ if (list[i].Mok == NULL) -+ continue; -+ -+ CertList = (EFI_SIGNATURE_LIST *)ptr; -+ CertData = (EFI_SIGNATURE_DATA *)(((uint8_t *)ptr) + -+ 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); -+ -+ ptr = (uint8_t *)ptr + sizeof(EFI_SIGNATURE_LIST) + -+ sizeof(EFI_GUID) + list[i].MokSize; -+ } -+ -+ efi_status = uefi_call_wrapper(RT->SetVariable, 5, L"MokList", -+ &shim_lock_guid, -+ EFI_VARIABLE_NON_VOLATILE -+ | EFI_VARIABLE_BOOTSERVICE_ACCESS, -+ DataSize, Data); -+ if (Data) -+ FreePool(Data); -+ -+ if (efi_status != EFI_SUCCESS) { -+ Print(L"Failed to set variable %d\n", efi_status); -+ return efi_status; -+ } -+ -+ return EFI_SUCCESS; -+} -+ -+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; -+ UINT32 attributes; -+ void *MokListData = NULL; -+ UINTN MokListDataSize = 0; -+ MokListNode *mok, *del_key; -+ INTN mok_num, del_num; -+ int i, j; -+ -+ 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) { -+ Print(L"Failed to get MokDelAuth %d\n", efi_status); -+ return efi_status; -+ } -+ -+ efi_status = match_password(MokDel, MokDelSize, auth, NULL); -+ if (efi_status != EFI_SUCCESS) -+ return EFI_ACCESS_DENIED; -+ -+ efi_status = get_variable(L"MokList", shim_lock_guid, &attributes, -+ &MokListDataSize, &MokListData); -+ -+ if (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; -+ } -+ -+ /* Nothing to do */ -+ if (!MokListData || MokListDataSize == 0) -+ return EFI_SUCCESS; -+ -+ /* Construct lists */ -+ mok_num = count_keys(MokListData, MokListDataSize); -+ mok = build_mok_list(mok_num, MokListData, MokListDataSize); -+ del_num = count_keys(MokDel, MokDelSize); -+ del_key = build_mok_list(del_num, MokDel, MokDelSize); -+ -+ /* 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; -+ } -+ } -+ } -+ -+ efi_status = write_back_mok_list(mok, mok_num); -+ -+ if (MokListData) -+ FreePool(MokListData); -+ if (mok) -+ FreePool(mok); -+ if (del_key) -+ FreePool(del_key); -+ -+ return efi_status; -+} -+ -+static INTN mok_deletion_prompt (void *MokDel, void *data2, void *data3) -+{ -+ 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): "); -+ -+ get_line (&length, line, 1, 1); -+ -+ if (line[0] == 'Y' || line[0] == 'y') { -+ efi_status = delete_keys(MokDel, MokDelSize); -+ -+ if (efi_status != EFI_SUCCESS) { -+ Print(L"Failed to delete keys\n"); -+ return -1; -+ } -+ -+ 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'); -+ return -1; -+} -+ - static INTN mok_sb_prompt (void *MokSB, void *data2, void *data3) { - EFI_GUID shim_lock_guid = SHIM_LOCK_GUID; - EFI_STATUS efi_status; -@@ -1505,12 +1718,15 @@ static BOOLEAN verify_pw(void) - return TRUE; - } - --static EFI_STATUS enter_mok_menu(EFI_HANDLE image_handle, void *MokNew, -- UINTN MokNewSize, void *MokSB, -- UINTN MokSBSize, void *MokPW, UINTN MokPWSize) -+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; - UINT32 MokAuth = 0; -+ UINT32 MokDelAuth = 0; - UINTN menucount = 3, i = 0; - EFI_STATUS efi_status; - EFI_GUID shim_lock_guid = SHIM_LOCK_GUID; -@@ -1528,9 +1744,19 @@ static EFI_STATUS enter_mok_menu(EFI_HANDLE image_handle, void *MokNew, - if ((efi_status == EFI_SUCCESS) && (auth_size == SHA256_DIGEST_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)) -+ MokDelAuth = 1; -+ - if (MokNew || MokAuth) - menucount++; - -+ if (MokDel || MokDelAuth) -+ menucount++; -+ - if (MokSB) - menucount++; - -@@ -1550,9 +1776,9 @@ static EFI_STATUS enter_mok_menu(EFI_HANDLE image_handle, void *MokNew, - - if (MokNew || MokAuth) { - if (!MokNew) { -- menu_item[i].text = StrDuplicate(L"Delete MOK"); -+ menu_item[i].text = StrDuplicate(L"Reset MOK"); - menu_item[i].colour = EFI_WHITE; -- menu_item[i].callback = mok_deletion_prompt; -+ menu_item[i].callback = mok_reset_prompt; - } else { - menu_item[i].text = StrDuplicate(L"Enroll MOK"); - menu_item[i].colour = EFI_WHITE; -@@ -1563,6 +1789,15 @@ static EFI_STATUS enter_mok_menu(EFI_HANDLE image_handle, void *MokNew, - 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; -+ i++; -+ } -+ - if (MokSB) { - menu_item[i].text = StrDuplicate(L"Change Secure Boot state"); - menu_item[i].colour = EFI_WHITE; -@@ -1605,19 +1840,22 @@ static EFI_STATUS enter_mok_menu(EFI_HANDLE image_handle, void *MokNew, - static EFI_STATUS check_mok_request(EFI_HANDLE image_handle) - { - EFI_GUID shim_lock_guid = SHIM_LOCK_GUID; -- UINTN MokNewSize = 0, MokSBSize = 0, MokPWSize = 0; -+ UINTN MokNewSize = 0, MokDelSize = 0, MokSBSize = 0, MokPWSize = 0; - void *MokNew = NULL; -+ void *MokDel = NULL; - void *MokSB = NULL; - void *MokPW = NULL; - - MokNew = LibGetVariableAndSize(L"MokNew", &shim_lock_guid, &MokNewSize); - -+ MokDel = LibGetVariableAndSize(L"MokDel", &shim_lock_guid, &MokDelSize); -+ - MokSB = LibGetVariableAndSize(L"MokSB", &shim_lock_guid, &MokSBSize); - - MokPW = LibGetVariableAndSize(L"MokPW", &shim_lock_guid, &MokPWSize); - -- enter_mok_menu(image_handle, MokNew, MokNewSize, MokSB, MokSBSize, -- MokPW, MokPWSize); -+ enter_mok_menu(image_handle, MokNew, MokNewSize, MokDel, MokDelSize, -+ MokSB, MokSBSize, MokPW, MokPWSize); - - if (MokNew) { - if (LibDeleteVariable(L"MokNew", &shim_lock_guid) != EFI_SUCCESS) { -@@ -1626,6 +1864,13 @@ static EFI_STATUS check_mok_request(EFI_HANDLE image_handle) - FreePool (MokNew); - } - -+ if (MokDel) { -+ if (LibDeleteVariable(L"MokDel", &shim_lock_guid) != EFI_SUCCESS) { -+ Print(L"Failed to delete MokDel\n"); -+ } -+ FreePool (MokDel); -+ } -+ - if (MokSB) { - if (LibDeleteVariable(L"MokSB", &shim_lock_guid) != EFI_SUCCESS) { - Print(L"Failed to delete MokSB\n"); -@@ -1641,6 +1886,7 @@ static EFI_STATUS check_mok_request(EFI_HANDLE image_handle) - } - - LibDeleteVariable(L"MokAuth", &shim_lock_guid); -+ LibDeleteVariable(L"MokDelAuth", &shim_lock_guid); - - return EFI_SUCCESS; - } -diff --git a/shim.c b/shim.c -index 44301dd..dcf1c51 100644 ---- a/shim.c -+++ b/shim.c -@@ -1271,7 +1271,8 @@ EFI_STATUS check_mok_request(EFI_HANDLE image_handle) - EFI_STATUS efi_status; - - if (check_var(L"MokNew") || check_var(L"MokSB") || -- check_var(L"MokPW") || check_var(L"MokAuth")) { -+ check_var(L"MokPW") || check_var(L"MokAuth") || -+ check_var(L"MokDel")) { - efi_status = start_image(image_handle, MOK_MANAGER); - - if (efi_status != EFI_SUCCESS) { --- -1.7.10.4 - diff --git a/shim-suse-build.patch b/shim-suse-build.patch index b29b70b..c1a758e 100644 --- a/shim-suse-build.patch +++ b/shim-suse-build.patch @@ -1,11 +1,13 @@ -Index: shim-0.2/Makefile -=================================================================== ---- shim-0.2.orig/Makefile -+++ shim-0.2/Makefile +--- + 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_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 diff --git a/shim.changes b/shim.changes index 9a31f74..3695a84 100644 --- a/shim.changes +++ b/shim.changes @@ -1,3 +1,33 @@ +------------------------------------------------------------------- +Tue Jul 23 03:55:05 UTC 2013 - glin@suse.com + +- Update to 0.4 +- Rebase patches + + shim-suse-build.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 +- Add patches + + shim-merge-lf-loader-code.patch: merge the Linux Foundation + loader UI code + + shim-fix-pointer-casting.patch: fix a casting issue and the + size of an empty vendor cert + + shim-fix-simple-file-selector.patch: fix the buffer allocation + in the simple file selector +- Remove upstreamed patches + + shim-support-mok-delete.patch + + shim-reboot-after-changes.patch + + shim-clear-queued-key.patch + + shim-local-key-sign-mokmanager.patch + + shim-get-2nd-stage-loader.patch + + shim-fix-loadoptions.patch +- Remove unused patch: shim-mokmanager-new-pw-hash.patch and + shim-keep-unsigned-mokmanager.patch +- Install the vendor certificate to /etc/uefi/certs + ------------------------------------------------------------------- Wed May 8 06:40:12 UTC 2013 - glin@suse.com diff --git a/shim.spec b/shim.spec index 05236a2..307050f 100644 --- a/shim.spec +++ b/shim.spec @@ -19,7 +19,7 @@ # needssslcertforbuild Name: shim -Version: 0.2 +Version: 0.4 Release: 0 Summary: UEFI shim loader License: BSD-2-Clause @@ -35,35 +35,25 @@ Source3: shim-install Source4: SLES-UEFI-CA-Certificate.crt # 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-local-key-sign-mokmanager.patch glin@suse.com -- Sign MokManager.efi with the local generated certificate -Patch1: shim-local-key-sign-mokmanager.patch -# PATCH-FEATURE-UPSTREAM shim-get-2nd-stage-loader.patch glin@suse.com -- Get the second stage loader path from the load options -Patch2: shim-get-2nd-stage-loader.patch -# PATCH-FIX-UPSTREAM shim-reboot-after-changes.patch glin@suse.com -- Reboot the system after enrolling or erasing keys -Patch3: shim-reboot-after-changes.patch -# PATCH-FIX-UPSTREAM shim-clear-queued-key.patch glin@suse.com -- Clear the queued key to show the menu properly -Patch5: shim-clear-queued-key.patch -# PATCH-FIX-UPSTREAM shim-fix-loadoptions.patch bnc#798043 glin@suse.com -- Adopt the UEFI shell style LoadOptions -Patch6: shim-fix-loadoptions.patch -# PATCH-FIX-UPSTREAM shim-support-mok-delete.patch glin@suse.com -- Support for deleting specific keys -Patch7: shim-support-mok-delete.patch -# PATCH-FIX-UPSTREAM shim-mokmanager-new-pw-hash.patch glin@suse.com -- Support the new password hash -Patch8: shim-mokmanager-new-pw-hash.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 -Patch9: shim-mokmanager-support-crypt-hash-method.patch -# PATCH-FIX-OPENSUSE shim-keep-unsigned-mokmanager.patch glin@suse.com -- Keep MokManager.efi and sign it with the openSUSE key later -Patch10: shim-keep-unsigned-mokmanager.patch +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() -Patch11: shim-bnc804631-fix-broken-bootpath.patch +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 -Patch12: shim-bnc798043-no-doulbe-separators.patch +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 -Patch13: shim-bnc807760-change-pxe-2nd-loader-name.patch +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 -Patch14: shim-bnc808106-correct-certcount.patch +Patch8: shim-bnc808106-correct-certcount.patch # PATCH-FIX-UPSTREAM shim-mokmanager-ui-revamp.patch glin@suse.com -- Revamp the MokManager UI -Patch15: shim-mokmanager-ui-revamp.patch -BuildRequires: gnu-efi >= 3.0q +Patch9: shim-mokmanager-ui-revamp.patch +BuildRequires: gnu-efi >= 3.0t BuildRequires: mozilla-nss-tools BuildRequires: openssl >= 0.9.8 BuildRequires: pesign @@ -89,17 +79,12 @@ Authors: %patch1 -p1 %patch2 -p1 %patch3 -p1 +%patch4 -p1 %patch5 -p1 %patch6 -p1 %patch7 -p1 %patch8 -p1 %patch9 -p1 -%patch10 -p1 -%patch11 -p1 -%patch12 -p1 -%patch13 -p1 -%patch14 -p1 -%patch15 -p1 %build chmod +x "make-certs" @@ -134,20 +119,25 @@ openssl x509 -in $cert -outform DER -out shim-$suffix.der touch shim.crt touch shim.cer # make sure cast warnings don't trigger post build check -make VENDOR_CERT_FILE=shim-$suffix.der shim.efi MokManager.efi 2>/dev/null +make VENDOR_CERT_FILE=shim-$suffix.der shim.efi MokManager.efi fallback.efi 2>/dev/null # make VENDOR_CERT_FILE=cert.der VENDOR_DBX_FILE=dbx mv shim.efi shim-$suffix.efi %install -export BRP_PESIGN_FILES='%{_libdir}/efi/shim*.efi %{_libdir}/efi/MokManager.efi' +export BRP_PESIGN_FILES='%{_libdir}/efi/shim*.efi %{_libdir}/efi/MokManager.efi %{_libdir}/efi/fallback.efi' install -d %{buildroot}/%{_libdir}/efi -install -m 444 shim-*.efi %{buildroot}/%{_libdir}/efi +install -m 644 shim-*.efi %{buildroot}/%{_libdir}/efi install -m 444 shim-*.der %{buildroot}/%{_libdir}/efi # FIXME: install signed shim here -install -m 444 %{SOURCE1} %{buildroot}/%{_libdir}/efi/shim.efi -install -m 444 MokManager.efi %{buildroot}/%{_libdir}/efi/MokManager.efi +install -m 644 %{SOURCE1} %{buildroot}/%{_libdir}/efi/shim.efi +install -m 644 MokManager.efi %{buildroot}/%{_libdir}/efi/MokManager.efi +install -m 644 fallback.efi %{buildroot}/%{_libdir}/efi/fallback.efi install -d %{buildroot}/%{_sbindir} install -m 755 %{SOURCE3} %{buildroot}/%{_sbindir}/ +# install SUSE certificate +CERT_NAME=$(openssl x509 -sha1 -fingerprint -inform DER -in shim-*.der | grep "SHA1 Fingerprint" | cut -c 18- | cut -d ":" -f 1,2,3,4 | sed 's/://g') +install -d %{buildroot}/%{_sysconfdir}/uefi/certs/ +install -m 444 shim-*.der %{buildroot}/%{_sysconfdir}/uefi/certs/$CERT_NAME.crt %clean %{?buildroot:%__rm -rf "%{buildroot}"} @@ -163,6 +153,10 @@ install -m 755 %{SOURCE3} %{buildroot}/%{_sbindir}/ %{_libdir}/efi/shim-*.efi %{_libdir}/efi/shim-*.der %{_libdir}/efi/MokManager.efi +%{_libdir}/efi/fallback.efi %{_sbindir}/shim-install +%dir %{_sysconfdir}/uefi/ +%dir %{_sysconfdir}/uefi/certs/ +%{_sysconfdir}/uefi/certs/*.crt %changelog