shim/shim-mokmanager-ui-revamp.patch

10788 lines
352 KiB
Diff
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

From 0709a7fd4ab06b445ed7343c2e9f544e0040ab21 Mon Sep 17 00:00:00 2001
From: Gary Ching-Pang Lin <glin@suse.com>
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.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ 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.
+
+ <signature of Ty Coon>, 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.<BR>
+Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
+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 <wincert.h>
+
+#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 "!<arch>\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 <wincert.h>
+//***********************************************************************
+// 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 <efierr.h>
+
+#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 <efi.h>
+
+#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 <variables_iterators.h>
+#include <sha256.h>
+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 <PeImage.h>
+
+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 <efiauthenticated.h>
+
+#include <sha256.h> /* for SHA256_DIGEST_SIZE */
+#include <variables_iterators.h>
+
+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 <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * 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 <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * 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 <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * 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 <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * 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 <stdarg.h>
+
+#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 <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * 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 <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * 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 <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * 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 <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * 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 <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * 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 <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * 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 <stdlib.h>
+
+#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 <http://www.fsf.org/copyleft/gpl.txt>.
+#
+# 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 <sys/types.h>\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, "<oid.txt")
+ or die "could not open 'oid.txt': $!";
+
+$counter = 0;
+$max_name = 0;
+$max_order = 0;
+
+while ($line = <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 <stdlib.h>\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 <fcntl.h>
+
+#include <x509.h>
+
+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 <efi.h>
+#include <efilib.h>
+
+#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 <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <errno.h>
+#include <ctype.h>
+#include <string.h>
+#include <limits.h>
+#include <dirent.h>
+#include <time.h>
+
+#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 <James.Bottomley@HansenPartnership.com>
+ *
+ * see COPYING file
+ *
+ * read some platform configuration tables
+ */
+#include <efi.h>
+#include <efilib.h>
+
+#include <guid.h>
+#include <configtable.h>
+
+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 <James.Bottomley@HansenPartnership.com>
+ *
+ * see COPYING file
+ */
+#include <efi/efi.h>
+#include <efi/efilib.h>
+
+#include <console.h>
+#include <errors.h>
+
+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 <James.Bottomley@HansenPartnership.com>
+ *
+ * see COPYING file
+ *
+ * --
+ *
+ * generate_path is a cut and paste from
+ *
+ * git://github.com/mjg59/shim.git
+ *
+ * Code Copyright 2012 Red Hat, Inc <mjg@redhat.com>
+ *
+ * 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 <efi.h>
+#include <efilib.h>
+
+#include <guid.h>
+#include <execute.h>
+
+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 <James.Bottomley@HansenPartnership.com>
+ *
+ * see COPYING file
+ */
+
+#include <guid.h>
+#include <stdio.h>
+
+#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 <mjg@redhat.com>
+ *
+ * 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.<BR>
+ * Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
+ * 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 <efi.h>
+#include <efilib.h>
+
+#include <pecoff.h>
+#include <guid.h>
+#include <simple_file.h>
+#include <variables.h>
+#include <sha256.h>
+#include <errors.h>
+
+#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 <James.Bottomley@HansenPartnership.com>
+ *
+ * see COPYING file
+ *
+ * Install and remove a platform security2 override policy
+ */
+
+#include <efi.h>
+#include <efilib.h>
+
+#include <guid.h>
+#include <sha256.h>
+#include <variables.h>
+#include <simple_file.h>
+#include <errors.h>
+
+#include <security_policy.h>
+
+/*
+ * 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 <efi/efi.h>
+#include <efi/efilib.h>
+
+#include <sha256.h>
+#include <pecoff.h>
+#include <simple_file.h>
+
+#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 <James.Bottomley@HansenPartnership.com>
+ *
+ * see COPYING file
+ *
+ * misc shell helper functions
+ */
+#include <efi.h>
+#include <efilib.h>
+
+#include <shell.h>
+
+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 <James.Bottomley@HansenPartnership.com>
+ *
+ * see COPYING file
+ */
+
+#include <efi.h>
+#include <efilib.h>
+
+#include <console.h>
+#include <simple_file.h>
+#include <efiauthenticated.h>
+#include <execute.h> /* 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 <James.Bottomley@HansenPartnership.com>
+ *
+ * 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.<BR>
+ * 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 <efi.h>
+#include <efilib.h>
+
+#include <efiauthenticated.h>
+
+#include <variables.h>
+#include <guid.h>
+#include <console.h>
+#include <sha256.h>
+#include <errors.h>
+
+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 <glin@suse.com>
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 <efilib.h>
#include <Library/BaseCryptLib.h>
#include <openssl/x509.h>
+#include <console.h>
+#include <simple_file.h>
#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; i<count; i++) {
- EFI_HANDLE fs = filesystem_handles[i-1];
- EFI_FILE_IO_INTERFACE *fs_interface;
- EFI_DEVICE_PATH *path;
- EFI_FILE *root;
- EFI_STATUS status;
- CHAR16 *VolumeLabel = NULL;
- EFI_FILE_SYSTEM_INFO *buffer = NULL;
- UINTN buffersize = 0;
- EFI_GUID file_info_guid = EFI_FILE_INFO_ID;
-
- status = uefi_call_wrapper(BS->HandleProtocol, 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 <glin@suse.com>
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 <variables_iterators.h>
-#include <sha256.h>
-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 <glin@suse.com>
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.
+
+ <one line to give the library's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ 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.
+
+ <signature of Ty Coon>, 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 <glin@suse.com>
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<count; i++)
+ FreePool(entries[i]);
+}
+
void
simple_file_selector(EFI_HANDLE *im, CHAR16 **title, CHAR16 *name,
CHAR16 *filter, CHAR16 **result)
@@ -436,8 +453,6 @@ simple_file_selector(EFI_HANDLE *im, CHAR16 **title, CHAR16 *name,
/* 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] == '/') {
@@ -445,6 +460,9 @@ simple_file_selector(EFI_HANDLE *im, CHAR16 **title, CHAR16 *name,
/* stay where we are */
if (StrCmp(selected, L"./") == 0) {
+ free_entries(entries, count);
+ FreePool(entries);
+ entries = NULL;
FreePool(dmp);
goto redo;
} else if (StrCmp(selected, L"../") == 0) {
@@ -463,6 +481,9 @@ simple_file_selector(EFI_HANDLE *im, CHAR16 **title, CHAR16 *name,
if (StrCmp(name, L"\\") != 0
&& StrCmp(&name[i], L"..") != 0) {
name[i] = '\0';
+ free_entries(entries, count);
+ FreePool(entries);
+ entries = NULL;
FreePool(dmp);
goto redo;
}
@@ -478,6 +499,9 @@ simple_file_selector(EFI_HANDLE *im, CHAR16 **title, CHAR16 *name,
/* remove trailing / */
newname[StrLen(newname) - 1] = '\0';
+ free_entries(entries, count);
+ FreePool(entries);
+ entries = NULL;
FreePool(dmp);
FreePool(name);
name = newname;
@@ -494,8 +518,10 @@ simple_file_selector(EFI_HANDLE *im, CHAR16 **title, CHAR16 *name,
out_free:
FreePool(dmp);
- if (entries)
+ if (entries) {
+ free_entries(entries, count);
FreePool(entries);
+ }
out_free_name:
FreePool(name);
}
--
1.8.1.4
From ff426e1d703de40eb7b6cd6ddfb00600c44613df Mon Sep 17 00:00:00 2001
From: Gary Ching-Pang Lin <glin@suse.com>
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; i<count; i++) {
- if (items[i].text)
- FreePool(items[i].text);
- }
-
- FreePool(items);
-}
-
-static void update_time (UINTN position, UINTN timeout)
+static int draw_countdown()
{
- uefi_call_wrapper(ST->ConOut->SetCursorPosition, 3, ST->ConOut, 0,
- position);
-
- uefi_call_wrapper(ST->ConOut->SetAttribute, 2, ST->ConOut,
- EFI_BLACK | EFI_BACKGROUND_BLACK);
-
- Print(L" ", timeout);
-
- uefi_call_wrapper(ST->ConOut->SetCursorPosition, 3, ST->ConOut, 0,
- position);
+ 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 <glin@suse.com>
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 <glin@suse.com>
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 <glin@suse.com>
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 <glin@suse.com>
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 <glin@suse.com>
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 <glin@suse.com>
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