diff --git a/shim-mokmanager-ui-revamp.patch b/shim-mokmanager-ui-revamp.patch new file mode 100644 index 0000000..9e11372 --- /dev/null +++ b/shim-mokmanager-ui-revamp.patch @@ -0,0 +1,10787 @@ +From 0709a7fd4ab06b445ed7343c2e9f544e0040ab21 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 + +--- + 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 + +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,) + +-SUBDIRS = Cryptlib ++SUBDIRS = Cryptlib efitools + + 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 -Iefitools/include -I$(EFI_INCLUDE) -I$(EFI_INCLUDE)/$(ARCH) -I$(EFI_INCLUDE)/protocol + EFI_PATH = /usr/lib64 + + LIB_GCC = $(shell $(CC) -print-libgcc-file-name) +@@ -67,7 +69,7 @@ shim.so: $(OBJS) Cryptlib/libcryptlib.a Cryptlib/OpenSSL/libopenssl.a + + MokManager.o: $(MOK_SOURCES) + +-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) + + Cryptlib/libcryptlib.a: +@@ -76,6 +78,12 @@ Cryptlib/libcryptlib.a: + Cryptlib/OpenSSL/libopenssl.a: + $(MAKE) -C Cryptlib/OpenSSL + ++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 + +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; ++} +-- +1.8.1.4 + + +From 35556acbc747eac5e22d45324503ffcd002ca9dd 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 + +--- + MokManager.c | 378 +++++++++-------------------------------------------------- + 1 file changed, 57 insertions(+), 321 deletions(-) + +diff --git a/MokManager.c b/MokManager.c +index e27c2c1..c076b12 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) + 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"; ++ 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); +-} ++ 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); ++ 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; ++ 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; ++ timeout--; ++ if (!timeout) + break; +- } + } ++ ++ FreePool(title[0]); ++ ++ /* Restore everything */ ++ uefi_call_wrapper(ST->ConOut->EnableCursor, 2, ST->ConOut, ++ SavedMode.CursorVisible); ++ uefi_call_wrapper(ST->ConOut->SetCursorPosition, 3, ST->ConOut, ++ SavedMode.CursorColumn, SavedMode.CursorRow); ++ uefi_call_wrapper(ST->ConOut->SetAttribute, 2, ST->ConOut, ++ SavedMode.Attribute); ++ ++ return timeout; + } + + 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; ++ ++ if (draw_countdown() == 0) ++ goto done; ++ ++ 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; + } + +-- +1.8.1.4 + + +From 74cbc9f5a4d6f93de93d93dd0a79796ec560f672 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() + +--- + MokManager.c | 16 ++-------------- + 1 file changed, 2 insertions(+), 14 deletions(-) + +diff --git a/MokManager.c b/MokManager.c +index c1a726d..8c52121 100644 +--- a/MokManager.c ++++ b/MokManager.c +@@ -67,18 +67,6 @@ static EFI_STATUS get_variable (CHAR16 *name, EFI_GUID guid, UINT32 *attributes, + return efi_status; + } + +-static EFI_INPUT_KEY get_keystroke (void) +-{ +- EFI_INPUT_KEY key; +- UINTN EventIndex; +- +- uefi_call_wrapper(BS->WaitForEvent, 3, 1, &ST->ConIn->WaitForKey, +- &EventIndex); +- uefi_call_wrapper(ST->ConIn->ReadKeyStroke, 2, ST->ConIn, &key); +- +- return key; +-} +- + static EFI_STATUS get_sha1sum (void *Data, int DataSize, UINT8 *hash) + { + EFI_STATUS status; +@@ -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 + int count = 0; + + do { +- key = get_keystroke(); ++ key = console_get_keystroke(); + + if ((count >= line_max && + key.UnicodeChar != CHAR_BACKSPACE) || +-- +1.8.1.4 + + +From d9073c96d9bb51cca75cd10b32ad79fef9ce3217 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 + +--- + MokManager.c | 439 ++++++++++++++++++++++++++++++++++------------------------- + 1 file changed, 254 insertions(+), 185 deletions(-) + +diff --git a/MokManager.c b/MokManager.c +index 8c52121..27887c4 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: + return status; + } + ++static void console_save_and_set_mode (SIMPLE_TEXT_OUTPUT_MODE *SavedMode) ++{ ++ if (!SavedMode) { ++ Print(L"Invalid parameter: SavedMode\n"); ++ return; ++ } ++ ++ CopyMem(SavedMode, ST->ConOut->Mode, sizeof(SIMPLE_TEXT_OUTPUT_MODE)); ++ uefi_call_wrapper(ST->ConOut->EnableCursor, 2, ST->ConOut, FALSE); ++ uefi_call_wrapper(ST->ConOut->SetAttribute, 2, ST->ConOut, ++ EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE); ++} ++ ++static void console_restore_mode (SIMPLE_TEXT_OUTPUT_MODE *SavedMode) ++{ ++ uefi_call_wrapper(ST->ConOut->EnableCursor, 2, ST->ConOut, ++ SavedMode->CursorVisible); ++ uefi_call_wrapper(ST->ConOut->SetCursorPosition, 3, ST->ConOut, ++ SavedMode->CursorColumn, SavedMode->CursorRow); ++ uefi_call_wrapper(ST->ConOut->SetAttribute, 2, ST->ConOut, ++ SavedMode->Attribute); ++} ++ ++static UINT32 get_password (CHAR16 *prompt, CHAR16 *password, UINT32 max) ++{ ++ SIMPLE_TEXT_OUTPUT_MODE SavedMode; ++ CHAR16 *str; ++ CHAR16 *message[2]; ++ UINTN length; ++ UINT32 pw_length; ++ ++ if (!prompt) ++ prompt = L"Password:"; ++ ++ console_save_and_set_mode(&SavedMode); ++ ++ str = PoolPrint(L"%s ", prompt); ++ if (!str) { ++ console_errorbox(L"Failed to allocate prompt"); ++ return 0; ++ } ++ ++ message[0] = str; ++ message[1] = NULL; ++ length = StrLen(message[0]); ++ console_print_box_at(message, -1, -length-4, -5, length+4, 3, 0, 1); ++ get_line(&pw_length, password, max, 0); ++ ++ console_restore_mode(&SavedMode); ++ ++ FreePool(str); ++ ++ return pw_length; ++} ++ + static EFI_STATUS match_password (PASSWORD_CRYPT *pw_crypt, + void *Data, UINTN DataSize, + UINT8 *auth, CHAR16 *prompt) +@@ -611,15 +671,10 @@ static EFI_STATUS match_password (PASSWORD_CRYPT *pw_crypt, + } + + while (fail_count < 3) { +- if (prompt) { +- Print(L"%s", prompt); +- } else { +- Print(L"Password: "); +- } +- get_line(&pw_length, password, PASSWORD_MAX, 0); ++ pw_length = get_password(prompt, password, PASSWORD_MAX); + + if (pw_length < PASSWORD_MIN || pw_length > PASSWORD_MAX) { +- Print(L"Invalid password length\n"); ++ console_errorbox(L"Invalid password length"); + fail_count++; + continue; + } +@@ -642,13 +697,13 @@ static EFI_STATUS match_password (PASSWORD_CRYPT *pw_crypt, + pw_length * sizeof(CHAR16), hash); + } + if (status != EFI_SUCCESS) { +- Print(L"Unable to generate password hash\n"); ++ console_errorbox(L"Unable to generate password hash"); + fail_count++; + continue; + } + + if (CompareMem(auth_hash, hash, auth_size) != 0) { +- Print(L"Password doesn't match\n"); ++ console_errorbox(L"Password doesn't match"); + fail_count++; + continue; + } +@@ -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; + } + +-static BOOLEAN verify_pw(void) ++static BOOLEAN verify_pw(UINT8 *protected) + { ++ SIMPLE_TEXT_OUTPUT_MODE SavedMode; + EFI_GUID shim_lock_guid = SHIM_LOCK_GUID; + EFI_STATUS efi_status; + UINT8 pwhash[PASSWORD_CRYPT_SIZE]; + UINTN size = PASSWORD_CRYPT_SIZE; + UINT32 attributes; ++ CHAR16 *message[2]; ++ ++ *protected = 0; + + efi_status = uefi_call_wrapper(RT->GetVariable, 5, L"MokPWStore", + &shim_lock_guid, &attributes, &size, +@@ -1493,18 +1485,27 @@ static BOOLEAN verify_pw(void) + + uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut); + ++ console_save_and_set_mode(&SavedMode); ++ message[0] = PoolPrint (L"%s UEFI key management", SHIM_VENDOR); ++ message[1] = NULL; ++ console_print_box_at(message, -1, 0, 0, -1, -1, 1, 1); ++ FreePool(message[0]); ++ console_restore_mode(&SavedMode); ++ + if (size == PASSWORD_CRYPT_SIZE) { + efi_status = match_password((PASSWORD_CRYPT *)pwhash, NULL, 0, +- NULL, L"Enter MOK password: "); ++ NULL, L"Enter MOK password:"); + } else { + efi_status = match_password(NULL, NULL, 0, pwhash, +- L"Enter MOK password: "); ++ L"Enter MOK password:"); + } + if (efi_status != EFI_SUCCESS) { +- Print(L"Password limit reached\n"); ++ console_errorbox(L"Password limit reached"); + return FALSE; + } + ++ *protected = 1; ++ + return TRUE; + } + +@@ -1525,8 +1526,9 @@ 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; + +- 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, + } + + 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; + +- if (draw_countdown() == 0) ++ if (protected == 0 && draw_countdown() == 0) + goto done; + + while (1) { +-- +1.8.1.4 + + +From 7ab54bd23e9bc412fa581e166c8f214df44604c5 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 + +--- + MokManager.c | 129 ++++++++++++++++++++++++++++++++++++++--------------------- + 1 file changed, 84 insertions(+), 45 deletions(-) + +diff --git a/MokManager.c b/MokManager.c +index 9c37a44..5b0c70c 100644 +--- a/MokManager.c ++++ b/MokManager.c +@@ -1067,25 +1067,57 @@ static INTN mok_deletion_prompt (void *MokDel, void *data2, void *data3) + return -1; + } + ++static CHAR16 get_password_charater (CHAR16 *prompt) ++{ ++ SIMPLE_TEXT_OUTPUT_MODE SavedMode; ++ CHAR16 *message[2]; ++ CHAR16 character; ++ UINTN length; ++ UINT32 pw_length; ++ ++ if (!prompt) ++ prompt = L"Password charater: "; ++ ++ console_save_and_set_mode(&SavedMode); ++ ++ message[0] = prompt; ++ message[1] = NULL; ++ length = StrLen(message[0]); ++ console_print_box_at(message, -1, -length-4, -5, length+4, 3, 0, 1); ++ get_line(&pw_length, &character, 1, 0); ++ ++ console_restore_mode(&SavedMode); ++ ++ return character; ++} ++ + static INTN mok_sb_prompt (void *MokSB, void *data2, void *data3) { ++ SIMPLE_TEXT_OUTPUT_MODE SavedMode; + EFI_GUID shim_lock_guid = SHIM_LOCK_GUID; +- EFI_STATUS efi_status; ++ EFI_STATUS status; + UINTN MokSBSize = (UINTN)data2; + 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; + } + + uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut); + ++ message[0] = L"Change Secure Boot state"; ++ message[1] = NULL; ++ ++ console_save_and_set_mode(&SavedMode); ++ console_print_box_at(message, -1, 0, 0, -1, -1, 1, 1); ++ console_restore_mode(&SavedMode); ++ + while (fail_count < 3) { + RandomBytes (&pos1, sizeof(pos1)); + pos1 = (pos1 % var->PWLen); +@@ -1100,19 +1132,34 @@ static INTN mok_sb_prompt (void *MokSB, void *data2, void *data3) { + pos3 = (pos3 % var->PWLen) ; + } while (pos3 == pos2 || pos3 == pos1); + +- Print(L"Enter password character %d: ", pos1 + 1); +- get_line(&length, &pass1, 1, 0); ++ str = PoolPrint(L"Enter password character %d: ", pos1 + 1); ++ if (!str) { ++ console_errorbox(L"Failed to allocate buffer"); ++ return -1; ++ } ++ pass1 = get_password_charater(str); ++ FreePool(str); + +- Print(L"Enter password character %d: ", pos2 + 1); +- get_line(&length, &pass2, 1, 0); ++ str = PoolPrint(L"Enter password character %d: ", pos2 + 1); ++ if (!str) { ++ console_errorbox(L"Failed to allocate buffer"); ++ return -1; ++ } ++ pass2 = get_password_charater(str); ++ FreePool(str); + +- Print(L"Enter password character %d: ", pos3 + 1); +- get_line(&length, &pass3, 1, 0); ++ str = PoolPrint(L"Enter password character %d: ", pos3 + 1); ++ if (!str) { ++ console_errorbox(L"Failed to allocate buffer"); ++ return -1; ++ } ++ pass3 = get_password_charater(str); ++ FreePool(str); + + if (pass1 != var->Password[pos1] || + pass2 != var->Password[pos2] || + 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.changes b/shim.changes index 893408c..9a31f74 100644 --- a/shim.changes +++ b/shim.changes @@ -1,3 +1,8 @@ +------------------------------------------------------------------- +Wed May 8 06:40:12 UTC 2013 - glin@suse.com + +- Add shim-mokmanager-ui-revamp.patch to update the MokManager UI + ------------------------------------------------------------------- Wed Apr 3 03:54:22 UTC 2013 - glin@suse.com diff --git a/shim.spec b/shim.spec index ab5445d..05236a2 100644 --- a/shim.spec +++ b/shim.spec @@ -61,6 +61,8 @@ Patch12: shim-bnc798043-no-doulbe-separators.patch Patch13: 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 +# 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 BuildRequires: mozilla-nss-tools BuildRequires: openssl >= 0.9.8 @@ -97,6 +99,7 @@ Authors: %patch12 -p1 %patch13 -p1 %patch14 -p1 +%patch15 -p1 %build chmod +x "make-certs"