]> code.delx.au - refind/commitdiff
Files for new MOK/shim code based on Bottomley's PreLoader.
authorsrs5694 <srs5694@users.sourceforge.net>
Fri, 28 Dec 2012 15:59:56 +0000 (10:59 -0500)
committersrs5694 <srs5694@users.sourceforge.net>
Fri, 28 Dec 2012 15:59:56 +0000 (10:59 -0500)
15 files changed:
mok/COPYING [new file with mode: 0644]
mok/Make.tiano [new file with mode: 0644]
mok/Makefile [new file with mode: 0644]
mok/console.h [new file with mode: 0644]
mok/efiauthenticated.h [new file with mode: 0644]
mok/execute.h [new file with mode: 0644]
mok/guid.c [new file with mode: 0644]
mok/guid.h [new file with mode: 0644]
mok/mok.c [new file with mode: 0644]
mok/mok.h [moved from refind/mok.h with 68% similarity]
mok/security_policy.c [new file with mode: 0644]
mok/security_policy.h [new file with mode: 0644]
mok/simple_file.c [new file with mode: 0644]
mok/simple_file.h [new file with mode: 0644]
refind/mok.c [deleted file]

diff --git a/mok/COPYING b/mok/COPYING
new file mode 100644 (file)
index 0000000..804e589
--- /dev/null
@@ -0,0 +1,354 @@
+Below file was part of the efitools package by James Bottomley, from which
+most of the source files in this directory were taken. The mok.c and mok.h
+files, however, are based on Matthew J. Garrett's shim program; see the
+copyright notices in those files for details....
+
+------------------------------------------------------------------------
+
+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.
+
+                   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.
+\f
+                   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.)
+\f
+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.
+\f
+  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.
+\f
+  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
+\f
+           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/mok/Make.tiano b/mok/Make.tiano
new file mode 100644 (file)
index 0000000..40f889a
--- /dev/null
@@ -0,0 +1,17 @@
+#
+# mok/Make.tiano
+# Build control file for Secure Boot components of rEFInd, using TianoCore EDK2
+#
+
+include ../Make.tiano
+
+SOURCE_NAMES     = guid mok security_policy simple_file
+OBJS             = $(SOURCE_NAMES:=.obj)
+
+all: $(AR_TARGET)
+
+$(AR_TARGET): $(OBJS)
+       $(AR) -cr $(AR_TARGET).lib $(OBJS)
+
+clean:
+       make clean
diff --git a/mok/Makefile b/mok/Makefile
new file mode 100644 (file)
index 0000000..83851c1
--- /dev/null
@@ -0,0 +1,19 @@
+#
+# mok/Makefile
+# Build control file for the libeg library
+#
+
+SRCDIR = .
+
+VPATH = $(SRCDIR)
+
+LOCAL_CPPFLAGS  = -I$(SRCDIR) -I$(SRCDIR)/../include
+
+OBJS            = guid.o mok.o security_policy.o simple_file.o
+TARGET          = libmok.a
+
+all: $(TARGET)
+
+include $(SRCDIR)/../Make.common
+
+# EOF
diff --git a/mok/console.h b/mok/console.h
new file mode 100644 (file)
index 0000000..2024bd7
--- /dev/null
@@ -0,0 +1,16 @@
+EFI_INPUT_KEY
+console_get_keystroke(void);
+void
+console_print_box_at(CHAR16 *str_arr[], int highlight, int start_col, int start_row, int size_cols, int size_rows, int offset, int lines);
+void
+console_print_box(CHAR16 *str_arr[], int highlight);
+int
+console_yes_no(CHAR16 *str_arr[]);
+int
+console_select(CHAR16 *title[], CHAR16* selectors[], int start);
+void
+console_errorbox(CHAR16 *err);
+void
+console_error(CHAR16 *err, EFI_STATUS);
+void
+console_alertbox(CHAR16 **title);
diff --git a/mok/efiauthenticated.h b/mok/efiauthenticated.h
new file mode 100644 (file)
index 0000000..811be70
--- /dev/null
@@ -0,0 +1,231 @@
+#ifndef _INC_EFIAUTHENTICATED_H
+#define _INC_EFIAUTHENTICATED_H
+//#include "wincert.h"
+#include "../include/PeImage.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 } }
+
+#ifdef __MAKEWITH_GNUEFI
+
+///
+/// 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))
+
+#endif
+
+///
+/// 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
+
+#ifdef __MAKEWITH_GNUEFI
+
+///   
+/// 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;
+
+#endif
+
+///
+/// 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/mok/execute.h b/mok/execute.h
new file mode 100644 (file)
index 0000000..9aecbff
--- /dev/null
@@ -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/mok/guid.c b/mok/guid.c
new file mode 100644 (file)
index 0000000..b0e430f
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2012 <James.Bottomley@HansenPartnership.com>
+ *
+ * see COPYING file
+ */
+
+#include "global.h"
+#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;
+// }
+// 
+// void str_to_guid(const char *str, EFI_GUID *guid)
+// {
+//   sscanf(str, "%8x-%4hx-%4hx-%2hhx%2hhx-%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx",
+//           &guid->Data1, &guid->Data2, &guid->Data3,
+//           guid->Data4, guid->Data4 + 1, guid->Data4 + 2,
+//           guid->Data4 + 3, guid->Data4 + 4, guid->Data4 + 5,
+//           guid->Data4 + 6, guid->Data4 + 7);
+// }
+// #endif
+
+/* all the necessary guids */
+EFI_GUID GV_GUID = EFI_GLOBAL_VARIABLE;
+EFI_GUID SIG_DB = { 0xd719b2cb, 0x3d3a, 0x4596, {0xa3, 0xbc, 0xda, 0xd0,  0xe, 0x67, 0x65, 0x6f }};
+
+EFI_GUID X509_GUID =   { 0xa5c059a1, 0x94e4, 0x4aa7, {0x87, 0xb5, 0xab, 0x15, 0x5c, 0x2b, 0xf0, 0x72} };
+EFI_GUID RSA2048_GUID = { 0x3c5766e8, 0x269c, 0x4e34, {0xaa, 0x14, 0xed, 0x77, 0x6e, 0x85, 0xb3, 0xb6} };
+EFI_GUID PKCS7_GUID = { 0x4aafd29d, 0x68df, 0x49ee, {0x8a, 0xa9, 0x34, 0x7d, 0x37, 0x56, 0x65, 0xa7} };
+EFI_GUID IMAGE_PROTOCOL = LOADED_IMAGE_PROTOCOL;
+EFI_GUID SIMPLE_FS_PROTOCOL = SIMPLE_FILE_SYSTEM_PROTOCOL;
+EFI_GUID EFI_CERT_SHA256_GUID  = { 0xc1c41626, 0x504c, 0x4092, { 0xac, 0xa9, 0x41, 0xf9, 0x36, 0x93, 0x43, 0x28 } };
+EFI_GUID MOK_OWNER = { 0x605dab50, 0xe046, 0x4300, {0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23} };
+EFI_GUID SECURITY_PROTOCOL_GUID = { 0xA46423E3, 0x4617, 0x49f1, {0xB9, 0xFF, 0xD1, 0xBF, 0xA9, 0x11, 0x58, 0x39 } };
+EFI_GUID SECURITY2_PROTOCOL_GUID = { 0x94ab2f58, 0x1438, 0x4ef1, {0x91, 0x52, 0x18, 0x94, 0x1a, 0x3a, 0x0e, 0x68 } };
diff --git a/mok/guid.h b/mok/guid.h
new file mode 100644 (file)
index 0000000..3d8925f
--- /dev/null
@@ -0,0 +1,18 @@
+//#include <efi.h>
+
+// #ifndef BUILD_EFI
+// const char *guid_to_str(EFI_GUID *guid);
+// void str_to_guid(const char *str, EFI_GUID *guid);
+// #endif
+
+extern EFI_GUID GV_GUID;
+extern EFI_GUID SIG_DB;
+extern EFI_GUID X509_GUID;
+extern EFI_GUID RSA2048_GUID;
+extern EFI_GUID PKCS7_GUID;
+extern EFI_GUID IMAGE_PROTOCOL;
+extern EFI_GUID SIMPLE_FS_PROTOCOL;
+extern EFI_GUID EFI_CERT_SHA256_GUID;
+extern EFI_GUID MOK_OWNER;
+extern EFI_GUID SECURITY_PROTOCOL_GUID;
+extern EFI_GUID SECURITY2_PROTOCOL_GUID;
diff --git a/mok/mok.c b/mok/mok.c
new file mode 100644 (file)
index 0000000..bedd031
--- /dev/null
+++ b/mok/mok.c
@@ -0,0 +1,127 @@
+/* mok/mok.c
+ *
+ * Based mostly on shim.c by Matthew J. Garrett/Red Hat (see below
+ * copyright notice).
+ *
+ * Code to perform Secure Boot verification of boot loader programs
+ * using the Shim program and its Machine Owner Keys (MOKs), to
+ * supplement standard Secure Boot checks performed by the firmware.
+ *
+ */
+
+/*
+ * shim - trivial UEFI first-stage bootloader
+ *
+ * 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.
+ *
+ * Significant portions of this code are derived from Tianocore
+ * (http://tianocore.sf.net) and are Copyright 2009-2012 Intel
+ * Corporation.
+ */
+
+#include "global.h"
+#include "mok.h"
+#include "../include/refit_call_wrapper.h"
+
+static EFI_STATUS get_variable (CHAR16 *name, EFI_GUID guid, UINT32 *attributes, UINTN *size, VOID **buffer)
+{
+   EFI_STATUS efi_status;
+   char allocate = !(*size);
+
+   efi_status = uefi_call_wrapper(RT->GetVariable, 5, name, &guid, attributes, size, buffer);
+
+   if (efi_status != EFI_BUFFER_TOO_SMALL || !allocate) {
+      return efi_status;
+   }
+
+   *buffer = AllocatePool(*size);
+
+   if (!*buffer) {
+      Print(L"Unable to allocate variable buffer\n");
+      return EFI_OUT_OF_RESOURCES;
+   }
+
+   efi_status = uefi_call_wrapper(RT->GetVariable, 5, name, &guid, attributes, size, *buffer);
+
+   return efi_status;
+} // get_variable()
+
+/*
+ * Check whether we're in Secure Boot and user mode
+ */
+BOOLEAN secure_mode (VOID)
+{
+   EFI_STATUS status;
+   EFI_GUID global_var = EFI_GLOBAL_VARIABLE;
+   UINTN charsize = sizeof(char);
+   UINT8 sb, setupmode;
+   UINT32 attributes;
+
+   status = get_variable(L"SecureBoot", global_var, &attributes, &charsize, (VOID *)&sb);
+
+   /* FIXME - more paranoia here? */
+   if (status != EFI_SUCCESS || sb != 1) {
+      return FALSE;
+   }
+
+   status = get_variable(L"SetupMode", global_var, &attributes, &charsize, (VOID *)&setupmode);
+
+   if (status == EFI_SUCCESS && setupmode == 1) {
+      return FALSE;
+   }
+
+   return TRUE;
+} // secure_mode()
+
+// Returns TRUE if the shim program is available to verify binaries,
+// FALSE if not
+BOOLEAN ShimLoaded(void) {
+   SHIM_LOCK   *shim_lock;
+   EFI_GUID    ShimLockGuid = SHIM_LOCK_GUID;
+
+   return (refit_call3_wrapper(BS->LocateProtocol, &ShimLockGuid, NULL, (VOID**) &shim_lock) == EFI_SUCCESS);
+} // ShimLoaded()
+
+// The following is based on the grub_linuxefi_secure_validate() function in Fedora's
+// version of GRUB 2.
+// Returns TRUE if the specified data is validated by Shim's MOK, FALSE otherwise
+BOOLEAN ShimValidate (VOID *data, UINT32 size)
+{
+   SHIM_LOCK   *shim_lock;
+   EFI_GUID    ShimLockGuid = SHIM_LOCK_GUID;
+
+   if (refit_call3_wrapper(BS->LocateProtocol, &ShimLockGuid, NULL, (VOID**) &shim_lock) == EFI_SUCCESS) {
+      if (!shim_lock)
+         return FALSE;
+
+      if (shim_lock->shim_verify(data, size) == EFI_SUCCESS)
+         return TRUE;
+   }
+
+   return FALSE;
+} // BOOLEAN ShimValidate()
similarity index 68%
rename from refind/mok.h
rename to mok/mok.h
index d9545d52e99bb9e09540d47f9645ff3585f5b400..7648209d5c2ec787a4a1b6b381381f870df9b31c 100644 (file)
+++ b/mok/mok.h
@@ -18,15 +18,12 @@ typedef struct _SHIM_LOCK
 typedef struct _SHIM_LOCK
 {
    EFI_STATUS (*shim_verify) (VOID *buffer, UINT32 size);
-   EFI_STATUS (*generate_hash) (char *data, int datasize,
-                                GNUEFI_PE_COFF_LOADER_IMAGE_CONTEXT *context, UINT8 *sha256hash,
-                                UINT8 *sha1hash);
-   EFI_STATUS (*read_header) (void *data, unsigned int datasize,
-                              GNUEFI_PE_COFF_LOADER_IMAGE_CONTEXT *context);
+   EFI_STATUS (*generate_hash) (char *data, int datasize, GNUEFI_PE_COFF_LOADER_IMAGE_CONTEXT *context,
+                                UINT8 *sha256hash, UINT8 *sha1hash);
+   EFI_STATUS (*read_header) (void *data, unsigned int datasize, GNUEFI_PE_COFF_LOADER_IMAGE_CONTEXT *context);
 } SHIM_LOCK;
 #endif
 
 BOOLEAN ShimLoaded(void);
+BOOLEAN ShimValidate (VOID *data, UINT32 size);
 BOOLEAN secure_mode (VOID);
-EFI_STATUS start_image(EFI_HANDLE image_handle, CHAR16 *ImagePath, VOID *data, UINTN datasize,
-                       CHAR16 *Options, REFIT_VOLUME *DeviceVolume, IN EFI_DEVICE_PATH *DevicePath);
diff --git a/mok/security_policy.c b/mok/security_policy.c
new file mode 100644 (file)
index 0000000..086ef6a
--- /dev/null
@@ -0,0 +1,349 @@
+/*
+ * Copyright 2012 <James.Bottomley@HansenPartnership.com>
+ *
+ * see COPYING file
+ *
+ * Install and remove a platform security2 override policy
+ */
+
+// #include <efi.h>
+// #include <efilib.h>
+#include <global.h>
+
+#include "guid.h"
+//#include "sha256.h"
+//#include "variables.h"
+#include "simple_file.h"
+//#include "errors.h"
+#include "../include/refit_call_wrapper.h"
+#include "mok.h"
+
+#include <security_policy.h>
+
+/*
+ * See the UEFI Platform Initialization manual (Vol2: DXE) for this
+ */
+struct _EFI_SECURITY2_PROTOCOL;
+struct _EFI_SECURITY_PROTOCOL;
+struct _EFI_DEVICE_PATH_PROTOCOL;
+typedef struct _EFI_SECURITY2_PROTOCOL EFI_SECURITY2_PROTOCOL;
+typedef struct _EFI_SECURITY_PROTOCOL EFI_SECURITY_PROTOCOL;
+#ifdef __MAKEWITH_GNUEFI
+typedef struct _EFI_DEVICE_PATH_PROTOCOL EFI_DEVICE_PATH_PROTOCOL;
+#endif
+
+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_SECURITY_FILE_AUTHENTICATION_STATE esfas = NULL;
+static EFI_SECURITY2_FILE_AUTHENTICATION es2fa = NULL;
+
+#ifdef __MAKEWITH_GNUEFI
+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));
+#endif
+
+#ifdef __MAKEWITH_GNUEFI
+static __attribute__((used)) EFI_STATUS
+#else
+static __attribute__((ms_abi)) EFI_STATUS
+#endif
+security2_policy_authentication (
+   const EFI_SECURITY2_PROTOCOL *This,
+   const EFI_DEVICE_PATH_PROTOCOL *DevicePath,
+   VOID *FileBuffer,
+   UINTN FileSize,
+   BOOLEAN  BootPolicy
+             )
+{
+   EFI_STATUS status;
+
+   /* 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;
+
+   if (ShimValidate(FileBuffer, FileSize)) {
+      status = EFI_SUCCESS;
+   } else {
+      status = EFI_ACCESS_DENIED;
+   }
+
+//   status = security_policy_check_mok(FileBuffer, FileSize);
+
+   return status;
+}
+
+#ifdef __MAKEWITH_GNUEFI
+static __attribute__((used)) EFI_STATUS
+#else
+static __attribute__((ms_abi)) EFI_STATUS
+#endif
+security_policy_authentication (
+   const EFI_SECURITY_PROTOCOL *This,
+   UINT32 AuthenticationStatus,
+   const EFI_DEVICE_PATH_PROTOCOL *DevicePathConst
+   )
+{
+   EFI_STATUS 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 = refit_call3_wrapper(esfas, This, AuthenticationStatus, DevicePathConst);
+
+   /* if OK avoid checking MOK: It's a bit expensive to
+    * read the whole file in again (esfas already did this) */
+   if (status == EFI_SUCCESS)
+      goto out;
+
+   status = refit_call3_wrapper(BS->LocateDevicePath, &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;
+
+   if (ShimValidate(FileBuffer, FileSize)) {
+      status = EFI_SUCCESS;
+   } else {
+      status = EFI_ACCESS_DENIED;
+   }
+   FreePool(FileBuffer);
+
+ out:
+   FreePool(OrigDevPath);
+   return status;
+}
+
+#ifdef __MAKEWITH_GNUEFI
+/* 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"
+);
+#endif
+
+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, (VOID**) &security2_protocol);
+
+   status = uefi_call_wrapper(BS->LocateProtocol, 3, &SECURITY_PROTOCOL_GUID, NULL, (VOID**) &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;
+#ifdef __MAKEWITH_GNUEFI
+      security2_protocol->FileAuthentication = thunk_security2_policy_authentication;
+#else
+      security2_protocol->FileAuthentication = security2_policy_authentication;
+#endif
+   }
+
+   esfas = security_protocol->FileAuthenticationState;
+#ifdef __MAKEWITH_GNUEFI
+   security_protocol->FileAuthenticationState = thunk_security_policy_authentication;
+#else
+   security_protocol->FileAuthenticationState = security_policy_authentication;
+#endif
+   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,
+                  (VOID**) &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,
+                  (VOID**) &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/mok/security_policy.h b/mok/security_policy.h
new file mode 100644 (file)
index 0000000..a1c1002
--- /dev/null
@@ -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/mok/simple_file.c b/mok/simple_file.c
new file mode 100644 (file)
index 0000000..85aa9e6
--- /dev/null
@@ -0,0 +1,114 @@
+/*
+ * Copyright 2012 <James.Bottomley@HansenPartnership.com>
+ *
+ * see COPYING file
+ */
+
+#include <global.h>
+#include "../include/refit_call_wrapper.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;
+
+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, (VOID**) &drive);
+
+   if (efi_status != EFI_SUCCESS) {
+      Print(L"Unable to find simple file protocol\n");
+      goto error;
+   }
+
+   efi_status = uefi_call_wrapper(drive->OpenVolume, 2, drive, &root);
+
+   if (efi_status != EFI_SUCCESS) {
+      Print(L"Failed to open drive volume\n");
+      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, (VOID**) &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_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;
+}
+
+void
+simple_file_close(EFI_FILE *file)
+{
+   uefi_call_wrapper(file->Close, 1, file);
+}
diff --git a/mok/simple_file.h b/mok/simple_file.h
new file mode 100644 (file)
index 0000000..e0cbf16
--- /dev/null
@@ -0,0 +1,9 @@
+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);
+void
+simple_file_close(EFI_FILE *file);
+
diff --git a/refind/mok.c b/refind/mok.c
deleted file mode 100644 (file)
index 091028a..0000000
+++ /dev/null
@@ -1,526 +0,0 @@
-/* refind/mok.c
- *
- * Based mostly on shim.c by Matthew J. Garrett/Red Hat (see below
- * copyright notice).
- *
- * Code to perform Secure Boot verification of boot loader programs
- * using the Shim program and its Machine Owner Keys (MOKs), to
- * supplement standard Secure Boot checks performed by the firmware.
- *
- */
-
-/*
- * shim - trivial UEFI first-stage bootloader
- *
- * 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.
- *
- * Significant portions of this code are derived from Tianocore
- * (http://tianocore.sf.net) and are Copyright 2009-2012 Intel
- * Corporation.
- */
-
-#include "global.h"
-#include "mok.h"
-#include "lib.h"
-#include "config.h"
-#include "screen.h"
-#include "../include/refit_call_wrapper.h"
-#include "../include/PeImage.h"
-
-#define SECOND_STAGE L"\\refind.efi"
-#define MOK_MANAGER L"\\MokManager.efi"
-
-static EFI_STATUS (EFIAPI *entry_point) (EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *system_table);
-
-// /*
-//  * The vendor certificate used for validating the second stage loader
-//  */
-// extern UINT8 vendor_cert[];
-// extern UINT32 vendor_cert_size;
-// extern UINT32 vendor_dbx_size;
-
-#define EFI_IMAGE_SECURITY_DATABASE_GUID { 0xd719b2cb, 0x3d3a, 0x4596, { 0xa3, 0xbc, 0xda, 0xd0, 0x0e, 0x67, 0x65, 0x6f }}
-
-//static UINT8 insecure_mode;
-
-typedef enum {
-   DATA_FOUND,
-   DATA_NOT_FOUND,
-   VAR_NOT_FOUND
-} CHECK_STATUS;
-
-typedef struct {
-   UINT32 MokSize;
-   UINT8 *Mok;
-} MokListNode;
-
-
-static EFI_STATUS get_variable (CHAR16 *name, EFI_GUID guid, UINT32 *attributes, UINTN *size, VOID **buffer)
-{
-   EFI_STATUS efi_status;
-   char allocate = !(*size);
-
-   efi_status = uefi_call_wrapper(RT->GetVariable, 5, name, &guid, attributes, size, buffer);
-
-   if (efi_status != EFI_BUFFER_TOO_SMALL || !allocate) {
-      return efi_status;
-   }
-
-   *buffer = AllocatePool(*size);
-
-   if (!*buffer) {
-      Print(L"Unable to allocate variable buffer\n");
-      return EFI_OUT_OF_RESOURCES;
-   }
-
-   efi_status = uefi_call_wrapper(RT->GetVariable, 5, name, &guid, attributes, size, *buffer);
-
-   return efi_status;
-} // get_variable()
-
-/*
- * Check whether we're in Secure Boot and user mode
- */
-BOOLEAN secure_mode (VOID)
-{
-   EFI_STATUS status;
-   EFI_GUID global_var = EFI_GLOBAL_VARIABLE;
-   UINTN charsize = sizeof(char);
-   UINT8 sb, setupmode;
-   UINT32 attributes;
-
-   status = get_variable(L"SecureBoot", global_var, &attributes, &charsize, (VOID *)&sb);
-
-   /* FIXME - more paranoia here? */
-   if (status != EFI_SUCCESS || sb != 1) {
-      return FALSE;
-   }
-
-   status = get_variable(L"SetupMode", global_var, &attributes, &charsize, (VOID *)&setupmode);
-
-   if (status == EFI_SUCCESS && setupmode == 1) {
-      return FALSE;
-   }
-
-   return TRUE;
-} // secure_mode()
-
-// Returns TRUE if the shim program is available to verify binaries,
-// FALSE if not
-BOOLEAN ShimLoaded(void) {
-   SHIM_LOCK   *shim_lock;
-   EFI_GUID    ShimLockGuid = SHIM_LOCK_GUID;
-
-   return (BS->LocateProtocol(&ShimLockGuid, NULL, (VOID**) &shim_lock) == EFI_SUCCESS);
-} // ShimLoaded()
-
-/*
- * Currently, shim/MOK only works on x86-64 (X64) systems, and some of this code
- * generates warnings on x86 (IA32) builds, so don't bother compiling it at all
- * on such systems.
- *
- */
-
-#if defined(EFIX64)
-
-/*
- * Perform basic bounds checking of the intra-image pointers
- */
-static void *ImageAddress (void *image, int size, unsigned int address)
-{
-   if (address > size)
-      return NULL;
-
-   return image + address;
-}
-
-/*
- * Perform the actual relocation
- */
-static EFI_STATUS relocate_coff (GNUEFI_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;
-
-   context->PEHdr->Pe32Plus.OptionalHeader.ImageBase = (UINT64)data;
-
-   // Linux kernels with EFI stub support don't have relocation information, so
-   // we can skip all this stuff....
-   if (((context->RelocDir->VirtualAddress == 0) && (context->RelocDir->Size == 0)) ||
-       ((context->PEHdr->Pe32.FileHeader.Characteristics & EFI_IMAGE_FILE_RELOCS_STRIPPED) != 0)) {
-      return EFI_SUCCESS;
-   }
-
-   if (context->NumberOfRvaAndSizes <= EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {
-      Print(L"Image has no relocation entry\n");
-      return EFI_UNSUPPORTED;
-   }
-
-   RelocBase = ImageAddress(data, size, context->RelocDir->VirtualAddress);
-   RelocBaseEnd = ImageAddress(data, size, context->RelocDir->VirtualAddress + context->RelocDir->Size - 1);
-
-   if (!RelocBase || !RelocBaseEnd) {
-      Print(L"Reloc table overflows binary\n");
-      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 = ImageAddress(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;
-} /* relocate_coff() */
-
-/*
- * Read the binary header and grab appropriate information from it
- */
-static EFI_STATUS read_header(void *data, unsigned int datasize,
-               GNUEFI_PE_COFF_LOADER_IMAGE_CONTEXT *context)
-{
-   EFI_IMAGE_DOS_HEADER *DosHdr = data;
-   EFI_IMAGE_OPTIONAL_HEADER_UNION *PEHdr = data;
-
-   if (datasize < sizeof(EFI_IMAGE_DOS_HEADER)) {
-      Print(L"Invalid image\n");
-      return EFI_UNSUPPORTED;
-   }
-
-   if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE)
-      PEHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)((char *)data + DosHdr->e_lfanew);
-
-   if ((((UINT8 *)PEHdr - (UINT8 *)data) + sizeof(EFI_IMAGE_OPTIONAL_HEADER_UNION)) > datasize) {
-      Print(L"Invalid image\n");
-      return EFI_UNSUPPORTED;
-   }
-
-   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->ImageSize < context->SizeOfHeaders) {
-      Print(L"Invalid image\n");
-      return EFI_UNSUPPORTED;
-   }
-
-   if (((UINT8 *)context->SecDir - (UINT8 *)data) > (datasize - sizeof(EFI_IMAGE_DATA_DIRECTORY))) {
-      Print(L"Invalid image\n");
-      return EFI_UNSUPPORTED;
-   }
-
-   if (context->SecDir->VirtualAddress >= datasize) {
-      Print(L"Malformed security header\n");
-      return EFI_INVALID_PARAMETER;
-   }
-   return EFI_SUCCESS;
-}
-
-// The following is based on the grub_linuxefi_secure_validate() function in Fedora's
-// version of GRUB 2.
-// Returns TRUE if the specified data is validated by Shim's MOK, FALSE otherwise
-static BOOLEAN ShimValidate (VOID *data, UINT32 size)
-{
-   SHIM_LOCK   *shim_lock;
-   EFI_GUID    ShimLockGuid = SHIM_LOCK_GUID;
-
-   if (BS->LocateProtocol(&ShimLockGuid, NULL, (VOID**) &shim_lock) == EFI_SUCCESS) {
-      if (!shim_lock)
-         return FALSE;
-
-      if (shim_lock->shim_verify(data, size) == EFI_SUCCESS)
-         return TRUE;
-   } // if
-
-   return FALSE;
-} // BOOLEAN ShimValidate()
-
-/*
- * Once the image has been loaded it needs to be validated and relocated
- */
-static EFI_STATUS handle_image (void *data, unsigned int datasize, EFI_LOADED_IMAGE *li,
-                                CHAR16 *Options, REFIT_VOLUME *DeviceVolume, IN CHAR16 *FileName)
-{
-   EFI_STATUS efi_status;
-   char *buffer;
-   int i, size;
-   EFI_IMAGE_SECTION_HEADER *Section;
-   char *base, *end;
-   GNUEFI_PE_COFF_LOADER_IMAGE_CONTEXT context;
-   EFI_DEVICE_PATH *DevicePath;
-
-   /*
-    * The binary header contains relevant context and section pointers
-    */
-   efi_status = read_header(data, datasize, &context);
-   if (efi_status != EFI_SUCCESS) {
-      Print(L"Failed to read header\n");
-      return efi_status;
-   }
-
-   /*
-    * Validate the image; if this fails, return EFI_ACCESS_DENIED
-    */
-   if (!ShimValidate(data, datasize)) {
-      return EFI_ACCESS_DENIED;
-   }
-
-   buffer = AllocatePool(context.ImageSize);
-
-   if (!buffer) {
-      Print(L"Failed to allocate image buffer\n");
-      return EFI_OUT_OF_RESOURCES;
-   }
-
-   CopyMem(buffer, data, context.SizeOfHeaders);
-
-   /*
-    * Copy the executable's sections to their desired offsets
-    */
-   Section = context.FirstSection;
-   for (i = 0; i < context.NumberOfSections; i++) {
-      size = Section->Misc.VirtualSize;
-
-      if (size > Section->SizeOfRawData)
-         size = Section->SizeOfRawData;
-
-      base = ImageAddress (buffer, context.ImageSize, Section->VirtualAddress);
-      end = ImageAddress (buffer, context.ImageSize, Section->VirtualAddress + size - 1);
-
-      if (!base || !end) {
-         Print(L"Invalid section size\n");
-         return EFI_UNSUPPORTED;
-      }
-
-      if (Section->SizeOfRawData > 0)
-         CopyMem(base, data + Section->PointerToRawData, size);
-
-      if (size < Section->Misc.VirtualSize)
-         ZeroMem (base + size, Section->Misc.VirtualSize - size);
-
-      Section += 1;
-   }
-
-   /*
-    * Run the relocation fixups
-    */
-   efi_status = relocate_coff(&context, buffer);
-
-   if (efi_status != EFI_SUCCESS) {
-      Print(L"Relocation failed\n");
-      FreePool(buffer);
-      return efi_status;
-   }
-
-   entry_point = ImageAddress(buffer, context.ImageSize, context.EntryPoint);
-   /*
-    * grub needs to know its location and size in memory, its location on
-    * disk, and its load options, so fix up the loaded image protocol values
-    */
-   DevicePath = FileDevicePath(NULL, FileName);
-//   DevicePath = FileDevicePath(DeviceVolume->DeviceHandle, FileName);
-   li->DeviceHandle = DeviceVolume->DeviceHandle;
-   li->FilePath = DevicePath;
-   li->LoadOptionsSize = ((UINT32)StrLen(Options) + 1) * sizeof(CHAR16);
-   li->LoadOptions = (VOID *)Options;
-   li->ImageBase = buffer;
-   li->ImageSize = context.ImageSize;
-
-   if (!entry_point) {
-      Print(L"Invalid entry point\n");
-      FreePool(buffer);
-      return EFI_UNSUPPORTED;
-   }
-
-   return EFI_SUCCESS;
-}
-
-#endif /* defined(EFIX64) */
-
-/*
- * Load and run an EFI executable.
- * Note that most of this function compiles only on x86-64 (X64) systems, since
- * shim/MOK works only on those systems. I'm leaving just enough to get the
- * function to return EFI_ACCESS_DENIED on x86 (IA32) systems, which should
- * let the calling function work in case it somehow ends up calling this
- * function inappropriately.
- */
-EFI_STATUS start_image(EFI_HANDLE image_handle, CHAR16 *ImagePath, VOID *data, UINTN datasize,
-                       CHAR16 *Options, REFIT_VOLUME *DeviceVolume, IN EFI_DEVICE_PATH *DevicePath)
-{
-   EFI_STATUS efi_status = EFI_ACCESS_DENIED;
-#if defined(EFIX64)
-   EFI_GUID loaded_image_protocol = LOADED_IMAGE_PROTOCOL;
-   EFI_LOADED_IMAGE *li, li_bak;
-   CHAR16 *PathName = NULL;
-
-   if (data == NULL)
-      return EFI_LOAD_ERROR;
-
-   /*
-    * We need to refer to the loaded image protocol on the running
-    * binary in order to find our path
-    */
-   efi_status = uefi_call_wrapper(BS->HandleProtocol, 3, image_handle, &loaded_image_protocol, (void **)&li);
-
-   if (efi_status != EFI_SUCCESS) {
-      Print(L"Unable to init protocol\n");
-      return efi_status;
-   }
-
-   /*
-    * We need to modify the loaded image protocol entry before running
-    * the new binary, so back it up
-    */
-   CopyMem(&li_bak, li, sizeof(li_bak));
-
-   /*
-    * Verify and, if appropriate, relocate and execute the executable
-    */
-   efi_status = handle_image(data, datasize, li, Options, DeviceVolume, ImagePath);
-
-   if (efi_status != EFI_SUCCESS) {
-      Print(L"Failed to load image\n");
-      CopyMem(li, &li_bak, sizeof(li_bak));
-      goto done;
-   }
-
-   /*
-    * The binary is trusted and relocated. Run it
-    */
-   efi_status = refit_call2_wrapper(entry_point, image_handle, ST);
-
-//   efi_status = refit_call1_wrapper(BS->UnloadImage, li);
-
-   /*
-    * Restore our original loaded image values
-    */
-   CopyMem(li, &li_bak, sizeof(li_bak));
-done:
-   if (PathName)
-      FreePool(PathName);
-
-   if (data)
-      FreePool(data);
-
-#endif
-   return efi_status;
-} // EFI_STATUS start_image()