pax_global_header00006660000000000000000000000064134152201710014506gustar00rootroot0000000000000052 comment=392836a46ce3c92b55dc88a1aebbcfdfc5dcddce efitools-1.9.2/000077500000000000000000000000001341522017100133435ustar00rootroot00000000000000efitools-1.9.2/.gitignore000066400000000000000000000004321341522017100153320ustar00rootroot00000000000000*.o *.so *.a *.efi *.key *.crt *.csr *.cer *.auth *.esl *.1 PK.h KEK.h DB.h hashlist.h *.hash *~ *.orig *.pvk *.p12 *.der *.pk7 *.cab hash-to-efi-sig-list cert-to-efi-sig-list cert-to-efi-hash-list sig-list-to-certs sign-efi-sig-list efi-keytool efi-readvar efi-updatevar flash-var efitools-1.9.2/COPYING000066400000000000000000001305331341522017100144030ustar00rootroot00000000000000efitools - 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. 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 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. --------------------------------------- GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! efitools-1.9.2/HashTool.c000066400000000000000000000136111341522017100152320ustar00rootroot00000000000000/* * Copyright 2012 * * see COPYING file * * Simple key manager for both MOK and SecureBoot variables */ #include #include #include #include #include #include #include #include #include static CHAR16* keytoolbin = L"KeyTool.efi"; static int transition_to_setup = 0, reboot_to_uefi_menu = 0; static EFI_HANDLE im; #if 0 /* some UEFI machines have a buggy implementation * see if we can tip the system into Setup Mode */ static EFI_STATUS change_setup_mode(int user_mode) { static UINT8 *data = NULL; static UINTN len = 0; EFI_STATUS status; if (user_mode) { if (!data) /* can only do this if we previously reset to setup */ return EFI_INVALID_PARAMETER; status = SetSecureVariable(L"PK", data, len, GV_GUID, 0, 0); if (status == EFI_SUCCESS) { data = NULL; len = 0; } return status; } else { status = get_variable(L"PK", &data, &len, GV_GUID); if (status != EFI_SUCCESS) return status; /* try to update it to nothing */ return SetSecureVariable(L"PK", data, 0, GV_GUID, 0, 0); } } #endif static void enroll_hash(void) { EFI_STATUS efi_status; CHAR16 *file_name = NULL, *title[6], buf0[256], buf1[256], buf2[256], *var; EFI_GUID *owner; UINT8 hash[SHA256_DIGEST_SIZE]; int i, setupmode = variable_is_setupmode(); simple_file_selector(&im, (CHAR16 *[]){ L"Select Binary", L"", L"The Selected Binary will have its hash Enrolled", L"This means it will Subsequently Boot with no prompting", L"Remember to make sure it is a genuine binary before Enroling its hash", NULL }, L"\\", L"", &file_name); if (!file_name) /* user pressed ESC */ return; efi_status = sha256_get_pecoff_digest(im, file_name, hash); if (efi_status != EFI_SUCCESS) { console_error(L"Hash failed (is efi binary valid?)", efi_status); return; } StrCpy(buf0, L"Enroll this hash into "); if (setupmode) StrCat(buf0, L"UEFI signature database?"); else StrCat(buf0, L"MOK database?"); title[0] = buf0; title[1] = L""; StrCpy(buf1, L"File: "); StrCat(buf1, file_name); title[2] = buf1; StrCpy(buf2, L"Hash: "); sha256_StrCat_hash(buf2, hash); title[3] = buf2; title[4] = NULL; i = console_yes_no(title); if (i == 0) return; /* We're in setup mode and the User asked us to add the signature * of this binary to the authorized signatures database */ if (setupmode) { var = L"db"; owner = &SIG_DB; } else { var = L"MokList"; owner = &MOK_OWNER; } efi_status = variable_enroll_hash(var, *owner, hash); if (efi_status != EFI_SUCCESS && efi_status != EFI_ALREADY_STARTED) { console_error(L"Failed to add signature to db", efi_status); return; } } void transition_to_uefi_menu(void) { int option; UINT64 indications = GetOSIndications(); if ((indications & EFI_OS_INDICATIONS_BOOT_TO_FW_UI) == 0) { console_errorbox(L"Platform Does not Support rebooting to firmware menu"); return; } option = console_yes_no( (CHAR16 *[]){ L"About to reboot to UEFI Setup Menu", L"", L"For more details about your system's setup menu", L"Including how to reset the system to setup mode, see", L"", L"http://www.linuxfoundation.org/uefi", NULL }); /* user said no */ if (option == 0) return; SETOSIndicationsAndReboot(EFI_OS_INDICATIONS_BOOT_TO_FW_UI); return; } EFI_STATUS efi_main (EFI_HANDLE image, EFI_SYSTEM_TABLE *systab) { UINT64 indications; int option = 0; im = image; InitializeLib(image, systab); indications = GetOSIndications(); if (indications & EFI_OS_INDICATIONS_BOOT_TO_FW_UI) reboot_to_uefi_menu = 1; #if 0 /* * Microsoft objects to this code. What it does is test to see * if the platform key is removable and offer a menu item to * transition to setup mode */ if (!variable_is_setupmode()) { if (change_setup_mode(0) == EFI_SUCCESS) { transition_to_setup = 1; change_setup_mode(1); } } #endif for (;;) { CHAR16 line2[80], line3[80], **title, *options[6]; int c = 0, setup_mode = NOSEL, uefi_reboot = NOSEL, reboot = NOSEL, exit_moktool = NOSEL, SetupMode, setup_mode_arg = 0, keytool = NOSEL; EFI_FILE *file; if (simple_file_open(image, keytoolbin, &file, EFI_FILE_MODE_READ) == EFI_SUCCESS) { keytool = 1; simple_file_close(file); } SetupMode = variable_is_setupmode(); StrCpy(line2, L"Platform is in "); StrCat(line2, SetupMode ? L"Setup Mode" : L"User Mode"); StrCpy(line3, L"Secure Boot is "); StrCat(line3, variable_is_secureboot() ? L"on" : L"off"); title = (CHAR16 *[]){L"Hash Tool main menu", L"", line2, line3, NULL }; options[c++] = L"Enroll Hash"; if (keytool != NOSEL) { keytool = c; options[c++] = L"Start UEFI Key Tool"; } if (transition_to_setup) { setup_mode = c; if (SetupMode) { setup_mode_arg = 1; options[c++] = L"Enter User Mode"; } else { setup_mode_arg = 0; options[c++] = L"Enter Setup Mode"; } } if (reboot_to_uefi_menu) { uefi_reboot = c; options[c++] = L"Reboot to UEFI Menu"; } reboot = c; options[c++] = L"Reboot System"; exit_moktool = c; options[c++] = L"Exit"; options[c++] = NULL; option = console_select(title, options, option); if (option == 0) { enroll_hash(); } else if (option == keytool) { EFI_STATUS status; status = execute(image, keytoolbin); if (status != EFI_SUCCESS) console_error(L"Failed to execute KeyTool", status); #if 0 } else if (option == setup_mode) { change_setup_mode(setup_mode_arg); #endif } else if (option == uefi_reboot) { transition_to_uefi_menu(); } else if (option == reboot) { int selection; selection = console_yes_no((CHAR16 *[]) { L"Are you sure you want to reboot?", NULL }); if (selection == 1) RT->ResetSystem(EfiResetWarm, EFI_SUCCESS, 0, NULL); } else if (option == exit_moktool) { break; } } return EFI_SUCCESS; } efitools-1.9.2/HelloWorld.c000066400000000000000000000005551341522017100155670ustar00rootroot00000000000000#include #include #include EFI_STATUS efi_main (EFI_HANDLE image, EFI_SYSTEM_TABLE *systab) { InitializeLib(image, systab); console_alertbox((CHAR16 *[]) { L"HelloWorld", L"", L"This file is used to prove you have managed", L"To execute an unsigned binary in secure boot mode", NULL, }); return EFI_SUCCESS; } efitools-1.9.2/KeyTool.c000066400000000000000000000461041341522017100151020ustar00rootroot00000000000000/* * Copyright 2012 * * see COPYING file * * Tool for manipulating system keys in setup mode */ #include #include #include #include #include #include #include #include static EFI_HANDLE im; static UINT8 SetupMode, SecureBoot, display_dbt; #define ARRAY_SIZE(a) (sizeof (a) / sizeof ((a)[0])) enum { KEY_PK = 0, KEY_KEK, KEY_DB, KEY_DBX, KEY_DBT, KEY_MOK, MAX_KEYS }; static struct { CHAR16 *name; CHAR16 *text; EFI_GUID *guid; int authenticated:1; int hash:1; } keyinfo[] = { [KEY_PK] = { .name = L"PK", .text = L"The Platform Key (PK)", .guid = &GV_GUID, .authenticated = 1, .hash = 0, }, [KEY_KEK] = { .name = L"KEK", .text = L"The Key Exchange Key Database (KEK)", .guid = &GV_GUID, .authenticated = 1, .hash = 0, }, [KEY_DB] = { .name = L"db", .text = L"The Allowed Signatures Database (db)", .guid = &SIG_DB, .authenticated = 1, .hash = 1, }, [KEY_DBX] = { .name = L"dbx", .text = L"The Forbidden Signatures Database (dbx)", .guid = &SIG_DB, .authenticated = 1, .hash = 1, }, [KEY_DBT] = { .name = L"dbt", .text = L"The Timestamp Signatures Database (dbt)", .guid = &SIG_DB, .authenticated = 1, .hash = 0, }, [KEY_MOK] = { .name = L"MokList", .text = L"The Machine Owner Key List (MokList)", .guid = &MOK_OWNER, .authenticated = 0, .hash = 1, } }; static const int keyinfo_size = ARRAY_SIZE(keyinfo); struct { EFI_GUID *guid; CHAR16 *name; } signatures[] = { { .guid = &X509_GUID, .name = L"X509", }, { .guid = &RSA2048_GUID, .name = L"RSA2048", }, { .guid = &EFI_CERT_SHA256_GUID, .name = L"SHA256 signature", }, { .guid = &EFI_CERT_X509_SHA256_GUID, .name = L"X509 SHA256 signature", }, { .guid = &EFI_CERT_X509_SHA384_GUID, .name = L"X509 SHA384 signature", }, { .guid = &EFI_CERT_X509_SHA384_GUID, .name = L"X509 SHA256 signature", }, }; static const int signatures_size = ARRAY_SIZE(signatures); static void select_and_apply(CHAR16 **title, CHAR16 *ext, int key, UINTN options) { CHAR16 *file_name; EFI_STATUS status; EFI_FILE *file; EFI_HANDLE h = NULL; int use_setsecurevariable = 0; simple_file_selector(&h, title, L"\\", ext, &file_name); if (file_name == NULL) return; status = simple_file_open(h, file_name, &file, EFI_FILE_MODE_READ); if (status != EFI_SUCCESS) return; UINTN size; void *esl; simple_file_read_all(file, &size, &esl); simple_file_close(file); /* PK is different: need to update with an authenticated bundle * including a signature with the new PK */ if (StrCmp(&file_name[StrLen(file_name) - 4], L".esl") == 0) { if (keyinfo[key].authenticated) use_setsecurevariable = 1; else use_setsecurevariable = 0; } else if (StrCmp(&file_name[StrLen(file_name) - 5], L".auth") == 0) { use_setsecurevariable = 0; options |= EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS; ; if (!keyinfo[key].authenticated) { console_errorbox(L"Can't set MOK variables with a .auth file"); return; } } else { if (keyinfo[key].authenticated) use_setsecurevariable = 1; else use_setsecurevariable = 0; void *newesl; int newsize; status = variable_create_esl(esl, size, &X509_GUID, NULL, &newesl, &newsize); if (status != EFI_SUCCESS) { console_error(L"Failed to create proper ESL", status); return; } FreePool(esl); esl = newesl; size = newsize; } if (use_setsecurevariable) { status = SetSecureVariable(keyinfo[key].name, esl, size, *keyinfo[key].guid, options, 0); } else { status = RT->SetVariable(keyinfo[key].name, keyinfo[key].guid, EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | options, size, esl); } if (status != EFI_SUCCESS) { console_error(L"Failed to update variable", status); return; } } static int StringSplit(CHAR16 *str, int maxlen, CHAR16 c, CHAR16 **out) { int len = StrLen(str); int count = 0; if (len < maxlen) { out[0] = str; return 1; } while (len > 0) { int i, found = 0; for (i = 0; i < maxlen; i++) { if (str[i] == c) found = i; if (str[i] == '\0') { found = i; break; } } out[count++] = str; str[found] = '\0'; str = str + found + 1; len -= found + 1; } return count; } static void delete_key(int key, void *Data, int DataSize, EFI_SIGNATURE_LIST *CertList, EFI_SIGNATURE_DATA *Cert) { EFI_STATUS status; int certs = (CertList->SignatureListSize - sizeof(EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize; if (certs == 1) { /* delete entire sig list + data */ DataSize -= CertList->SignatureListSize; if (DataSize > 0) CopyMem(CertList, (void *) CertList + CertList->SignatureListSize, DataSize - ((void *) CertList - Data)); } else { int remain = DataSize - ((void *)Cert - Data) - CertList->SignatureSize; /* only delete single sig */ DataSize -= CertList->SignatureSize; CertList->SignatureListSize -= CertList->SignatureSize; if (remain > 0) CopyMem(Cert, (void *)Cert + CertList->SignatureSize, remain); } if (keyinfo[key].authenticated) status = SetSecureVariable(keyinfo[key].name, Data, DataSize, *keyinfo[key].guid, 0, 0); else status = RT->SetVariable(keyinfo[key].name, keyinfo[key].guid, EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS, DataSize, Data); if (status != EFI_SUCCESS) console_error(L"Failed to delete key", status); } static void show_key(int key, int offset, void *Data, int DataSize) { EFI_SIGNATURE_LIST *CertList; EFI_SIGNATURE_DATA *Cert = NULL; int cert_count = 0, i, Size, option = 0; CHAR16 *title[20], *options[4]; CHAR16 str[256], str1[256], str2[256]; title[0] = keyinfo[key].text; certlist_for_each_certentry(CertList, Data, Size, DataSize) { certentry_for_each_cert(Cert, CertList) if (cert_count++ == offset) goto finished; } finished: SPrint(str, sizeof(str), L"Sig[%d] - owner: %g", offset, &Cert->SignatureOwner); int c = 0; title[c++] = str; title[c] = L"Unknown"; for (i = 0; i < signatures_size; i++) { if (CompareGuid(signatures[i].guid, &CertList->SignatureType) == 0) { SPrint(str1, sizeof(str1), L"Type: %s", signatures[i].name); title[c] = str1; break; } } CHAR16 buf[1024], buf1[1024], *tmpbuf[10], *tmpbuf1[10]; if (CompareGuid(&CertList->SignatureType, &EFI_CERT_SHA256_GUID) == 0) { StrCpy(str2, L"Hash: "); sha256_StrCat_hash(str2, Cert->SignatureData); title[++c] = str2; } else if (CompareGuid(&CertList->SignatureType, &X509_GUID) == 0) { x509_to_str(Cert->SignatureData, CertList->SignatureSize, X509_OBJ_SUBJECT, buf, sizeof(buf)); title[++c] = L""; title[++c] = L"Subject:"; int sp = StringSplit(buf, 70, ',', tmpbuf); for (i = 0; i < sp; i++) title[++c] = tmpbuf[i]; x509_to_str(Cert->SignatureData, CertList->SignatureSize, X509_OBJ_ISSUER, buf1, sizeof(buf1)); sp = StringSplit(buf1, 70, ',', tmpbuf1); title[++c] = L"Issuer:"; for (i = 0; i < sp; i++) title[++c] = tmpbuf1[i]; } else if (CompareGuid(&CertList->SignatureType, &EFI_CERT_X509_SHA256_GUID) == 0) { EFI_CERT_X509_SHA256 *tmp = (void *)Cert->SignatureData; StrCpy(str2, L"Hash: "); sha256_StrCat_hash(str2, Cert->SignatureData); title[++c] = str2; EFI_TIME timestamp = tmp->TimeOfRevocation; SPrint(buf, sizeof(buf), L"Revocation Timestamp: %d-%d-%d %02d:%02d:%02d\n", timestamp.Year, timestamp.Month, timestamp.Day, timestamp.Hour, timestamp.Minute, timestamp.Second); title[++c] = buf; } title[++c] = NULL; int o = 0; int option_delete = NOSEL, option_delete_w_auth = NOSEL, option_save = NOSEL; if (variable_is_setupmode() || key == KEY_MOK) { option_delete = o; options[o++] = L"Delete"; } option_save = o; options[o++] = L"Save to File"; if (key == KEY_PK) { option_delete_w_auth = o; options[o++] = L"Delete with .auth File"; } options[o++] = NULL; option = console_select(title, options, option); if (option == -1) return; if (option == option_delete) { delete_key(key, Data, DataSize, CertList, Cert); } else if (option == option_save) { CHAR16 *filename; EFI_FILE *file; EFI_STATUS status; EFI_HANDLE vol; CHAR16 *volname; simple_volume_selector((CHAR16 *[]) { L"Save Key", L"", L"Select a disk Volume to save the key file to", L"The Key file will be saved in the top level directory", L"", L"Note: For USB volumes, some UEFI implementations aren't", L"very good at hotplug, so you may have to boot with the USB", L"Key already plugged in to see the volume", NULL }, &volname, &vol); /* no selection or ESC pressed */ if (!volname) return; FreePool(volname); filename = AllocatePool(1024); SPrint(filename, 0, L"%s-%d.esl", keyinfo[key].name, offset); status = simple_file_open(vol, filename, &file, EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE); if (status == EFI_SUCCESS) { status = simple_file_write_all(file, CertList->SignatureListSize, CertList); simple_file_close(file); } if (status != EFI_SUCCESS) { CHAR16 str[80]; SPrint(str, sizeof(str), L"Failed to write %s", filename); console_error(str, status); } else { CHAR16 str1[80], str2[80], str3[80]; SPrint(str1, sizeof(str1), L"Key %s[%d]", keyinfo[key].name, offset); SPrint(str2, sizeof(str2), L"With GUID: %g", &Cert->SignatureOwner); SPrint(str3, sizeof(str3), L"saved to %s", filename); console_alertbox((CHAR16 *[]) { L"Successfully Saved", L"", str1, str2, str3, NULL }); } FreePool(filename); } else if (option == option_delete_w_auth) { title[0] = L"Select authority bundle to remove PK"; title[1] = NULL; select_and_apply(title, L".auth", key, 0); } } static void add_new_key(int key, UINTN options) { CHAR16 *title[3]; /* PK update must be signed: so require .auth file */ CHAR16 *ext = (key != KEY_PK && variable_is_setupmode()) ? L".esl|.auth|.cer" : L".auth"; title[0] = L"Select File containing additional key for"; title[1] = keyinfo[key].text; title[2] = NULL; select_and_apply(title, ext, key, options); } static void enroll_hash(int key) { EFI_STATUS efi_status; CHAR16 *file_name = NULL, *title[6], buf0[256], buf1[256], buf2[256]; UINT8 hash[SHA256_DIGEST_SIZE]; int i; EFI_HANDLE h = NULL; simple_file_selector(&h, (CHAR16 *[]){ L"Select Binary", L"", L"The Selected Binary will have its hash Enrolled", L"This means it will Subsequently Boot with no prompting", L"Remember to make sure it is a genuine binary before Enrolling its hash", NULL }, L"\\", NULL, &file_name); if (!file_name) /* user pressed ESC */ return; efi_status = sha256_get_pecoff_digest(h, file_name, hash); if (efi_status != EFI_SUCCESS) { console_error(L"Hash failed (is efi binary valid?)", efi_status); return; } StrCpy(buf0, L"Enroll hash into "); StrCat(buf0, keyinfo[key].text); title[0] = buf0; title[1] = L""; StrCpy(buf1, L"File: "); StrCat(buf1, file_name); title[2] = buf1; StrCpy(buf2, L"Hash: "); sha256_StrCat_hash(buf2, hash); title[3] = buf2; title[4] = NULL; i = console_yes_no(title); if (i == 0) return; efi_status = variable_enroll_hash(keyinfo[key].name, *keyinfo[key].guid, hash); if (efi_status != EFI_SUCCESS && efi_status != EFI_ALREADY_STARTED) { console_error(L"Failed to add signature to db", efi_status); return; } } static void save_key_internal(int key, EFI_HANDLE vol, CHAR16 *error) { EFI_STATUS status; EFI_FILE *file; UINT8 *data; UINTN len; CHAR16 file_name[512]; StrCpy(error, keyinfo[key].name); status = get_variable(keyinfo[key].name, &data, &len, *keyinfo[key].guid); if (status != EFI_SUCCESS) { if (status == EFI_NOT_FOUND) StrCat(error, L": Variable has no entries"); else SPrint(error, 1024, L"%s: Failed to get variable (Error: %d)", error, status); return; } StrCpy(file_name, L"\\"); StrCat(file_name, keyinfo[key].name); StrCat(file_name, L".esl"); status = simple_file_open(vol, file_name, &file, EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE); if (status != EFI_SUCCESS) { SPrint(error, 1024, L"%s: Failed to open file %s (Error: %d)", error, file_name, status); return; } status = simple_file_write_all(file, len, data); simple_file_close(file); if (status != EFI_SUCCESS) { SPrint(error, 1024, L"%s: Failed to write to %s (Error: %d)", error, file_name, status); return; } StrCat(error, L": Successfully written to "); StrCat(error, file_name); } static void save_key(int key) { EFI_HANDLE vol; CHAR16 *volname; simple_volume_selector((CHAR16 *[]) { L"Save Key", L"", L"Select a disk Volume to save the key file to", L"The key file will be saved in the top level directory", L"", L"Note: For USB volumes, some UEFI implementations aren't", L"very good at hotplug, so you may have to boot with the USB", L"USB device already plugged in to see the volume", NULL }, &volname, &vol); /* no selection or ESC pressed */ if (!volname) return; FreePool(volname); CHAR16 buf[1024], *title[2]; save_key_internal(key, vol, buf); title[0] = buf; title[1] = NULL; console_alertbox(title); } static void manipulate_key(int key) { CHAR16 *title[5]; EFI_STATUS efi_status; int setup_mode = variable_is_setupmode(), i; title[0] = L"Manipulating Contents of"; title[1] = keyinfo[key].text; title[2] = NULL; UINT8 *Data; UINTN DataSize = 0, Size; efi_status = RT->GetVariable(keyinfo[key].name, keyinfo[key].guid, NULL, &DataSize, NULL); if (efi_status != EFI_BUFFER_TOO_SMALL && efi_status != EFI_NOT_FOUND) { console_error(L"Failed to get DataSize", efi_status); return; } Data = AllocatePool(DataSize); if (!Data) { CHAR16 str[80]; SPrint(str, sizeof(str), L"Failed to allocate %d", DataSize); console_errorbox(str); return; } efi_status = RT->GetVariable(keyinfo[key].name, keyinfo[key].guid, NULL, &DataSize, Data); if (efi_status == EFI_NOT_FOUND) { int t = 2; title[t++] = L"Variable is Empty"; if (key == KEY_PK) title[t++] = L"WARNING: Setting PK will take the platform out of Setup Mode"; title[t++] = NULL; } else if (efi_status != EFI_SUCCESS) { console_error(L"Failed to get variable", efi_status); return; } EFI_SIGNATURE_LIST *CertList; int cert_count = 0, add = NOSEL, replace = NOSEL, hash = NOSEL, save = NOSEL; certlist_for_each_certentry(CertList, Data, Size, DataSize) { cert_count += (CertList->SignatureListSize - sizeof(EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize; } CHAR16 **guids = (CHAR16 **)AllocatePool((cert_count + 5)*sizeof(void *)); cert_count = 0; int g; certlist_for_each_certentry(CertList, Data, Size, DataSize) { EFI_SIGNATURE_DATA *Cert; certentry_for_each_cert(Cert, CertList) { guids[cert_count] = AllocatePool(64*sizeof(CHAR16)); SPrint(guids[cert_count++], 64*sizeof(CHAR16), L"%g", &Cert->SignatureOwner); } } g = cert_count; if (key != 0) { add = g; guids[g++] = L"Add New Key"; } replace = g; guids[g++] = L"Replace Key(s)"; if (keyinfo[key].hash && (!keyinfo[key].authenticated || setup_mode)) { hash = g; guids[g++] = L"Enroll hash of binary"; } if (cert_count != 0) { save = g; guids[g++] = L"Save key"; } guids[g] = NULL; int select = console_select(title, guids, 0); for (i = 0; i < cert_count; i++) FreePool(guids[i]); FreePool(guids); if (select == replace) add_new_key(key, 0); else if (select == add) add_new_key(key, EFI_VARIABLE_APPEND_WRITE); else if (select == hash) enroll_hash(key); else if (select == save) save_key(key); else if (select >= 0) show_key(key, select, Data, DataSize); FreePool(Data); } static void select_key(void) { int i, j; int keymap[keyinfo_size + 1]; CHAR16 *keys[keyinfo_size + 1]; for (i = 0, j = 0; i < keyinfo_size; i++) { if (i == KEY_DBT && !display_dbt) continue; keys[j] = keyinfo[i].text; keymap[j++] = i; } keys[j] = NULL; i = 0; for (;;) { i = console_select( (CHAR16 *[]){ L"Select Key to Manipulate", NULL }, keys, i); if (i == -1) break; manipulate_key(keymap[i]); } } static void save_keys(void) { EFI_HANDLE vol; CHAR16 *volname; simple_volume_selector((CHAR16 *[]) { L"Save Keys", L"", L"Select a disk Volume to save all the key files to", L"Key files will be saved in the top level directory", L"", L"Note: For USB volumes, some UEFI implementations aren't", L"very good at hotplug, so you may have to boot with the USB", L"USB device already plugged in to see the volume", NULL }, &volname, &vol); /* no selection or ESC pressed */ if (!volname) return; FreePool(volname); CHAR16 *title[10], buf[8000]; int i, t_c = 0, b_c = 0; title[t_c++] = L"Results of Saving Keys"; title[t_c++] = L""; for (i = 0; i < MAX_KEYS; i++) { if (i == KEY_DBT && !display_dbt) continue; save_key_internal(i, vol, &buf[b_c]); title[t_c++] = &buf[b_c]; b_c += StrLen(&buf[b_c]) + 1; } title[t_c] = NULL; console_alertbox(title); } static void execute_binary() { CHAR16 *bin_name; EFI_HANDLE h = NULL; EFI_HANDLE ih; EFI_DEVICE_PATH *devpath; EFI_STATUS status; simple_file_selector(&h, (CHAR16 *[]) { L"Select Binary to Execute", L"", NULL }, L"\\", NULL, &bin_name); if (!bin_name) { /* user pressed ESC */ return; } /* the execute() call is designed to construct handles from * local resources on the image. We have a handle and a full * path name, so we follow proper process here */ devpath = FileDevicePath(h, bin_name); status = BS->LoadImage(FALSE, im, devpath, NULL, 0, &ih); if (status != EFI_SUCCESS) { console_error(L"Image failed to load", status); return; } status = BS->StartImage(ih, NULL, NULL); BS->UnloadImage(ih); if (status != EFI_SUCCESS) console_error(L"Execution returned error", status); } EFI_STATUS efi_main (EFI_HANDLE image, EFI_SYSTEM_TABLE *systab) { EFI_STATUS efi_status; UINTN DataSize = sizeof(SetupMode); int option = 0; im = image; InitializeLib(image, systab); if (GetOSIndications() & EFI_OS_INDICATIONS_TIMESTAMP_REVOCATION) display_dbt = 1; efi_status = RT->GetVariable(L"SetupMode", &GV_GUID, NULL, &DataSize, &SetupMode); if (efi_status != EFI_SUCCESS) { Print(L"No SetupMode variable ... is platform secure boot enabled?\n"); return EFI_SUCCESS; } for (;;) { CHAR16 line2[80], line3[80], **title; SetupMode = variable_is_setupmode(); SecureBoot = variable_is_secureboot(); line2[0] = line3[0] = L'\0'; StrCat(line2, L"Platform is in "); StrCat(line2, SetupMode ? L"Setup Mode" : L"User Mode"); StrCat(line3, L"Secure Boot is "); StrCat(line3, SecureBoot ? L"on" : L"off"); title = (CHAR16 *[]){L"KeyTool main menu", L"", line2, line3, NULL }; option = console_select(title, (CHAR16 *[]){ L"Save Keys", L"Edit Keys", L"Execute Binary", L"Exit", NULL }, option); switch (option) { case 0: save_keys(); break; case 1: select_key(); break; case 2: execute_binary(); break; case 3: /* exit from programme */ return EFI_SUCCESS; default: break; } } return EFI_SUCCESS; } efitools-1.9.2/Loader.c000066400000000000000000000105441341522017100147210ustar00rootroot00000000000000/* * Copyright 2012 * * see COPYING file * * Simple elf loader based on Intel TianoCore */ #include #include #include #include #include #include #include #include #include #include CHAR16 *loader = L"\\linux-loader.efi"; /* get the user's permission to boot the image */ int ask_to_boot(void) { return console_yes_no( (CHAR16 *[]) { L"WARNING: This Binary is unsigned (and should be a Linux boot loader)", L"", L"Are you sure you wish to run an unsigned binary", L"in a secure environment?", L"", L"To avoid this question in future place the platform into setup mode", L"See http://www.linuxfoundation.org/uefi", L"And reboot.", NULL, }); } /* Get the user's permission to install the image signature */ static int ask_install_keys(void) { /* first check to see if the key is already present */ return console_yes_no( (CHAR16 *[]){ L"You are in Setup Mode", L"", L"Do you wish me to install the signature", L"of the binary into the allowed signatures database?", L"", L"If you say \"yes\" here, the platform will no longer ask permission", L"to run the binary on every boot", NULL }); } EFI_STATUS efi_main (EFI_HANDLE image, EFI_SYSTEM_TABLE *systab) { EFI_STATUS efi_status; UINT8 SecureBoot = 0, SetupMode = 0; UINTN DataSize = sizeof(SecureBoot); EFI_FILE *file; EFI_LOADED_IMAGE *li; EFI_DEVICE_PATH *loadpath = NULL; CHAR16 *PathName = NULL; EFI_HANDLE loader_handle; InitializeLib(image, systab); efi_status = RT->GetVariable(L"SecureBoot", &GV_GUID, NULL, &DataSize, &SecureBoot); if (efi_status != EFI_SUCCESS) { Print(L"Not a Secure Boot Platform %d\n", efi_status); } else if (!SecureBoot) { Print(L"Secure Boot Disabled\n"); DataSize = sizeof(SetupMode); } RT->GetVariable(L"SetupMode", &GV_GUID, NULL, &DataSize, &SetupMode); efi_status = BS->HandleProtocol(image, &IMAGE_PROTOCOL, (VOID **)&li); if (efi_status != EFI_SUCCESS) { Print(L"Failed to init loaded image protocol: %d\n", efi_status); return efi_status; } efi_status = generate_path(loader, li, &loadpath, &PathName); if (efi_status != EFI_SUCCESS) { Print(L"Unable to generate load path for %s: %d\n", loader, efi_status); return efi_status; } if (!SetupMode) { efi_status = BS->LoadImage(FALSE, image, loadpath, NULL, 0, &loader_handle); if (efi_status == EFI_SUCCESS) { /* Image validates - start it */ Print(L"Starting file via StartImage\n"); BS->StartImage(loader_handle, NULL, NULL); BS->UnloadImage(loader_handle); return EFI_SUCCESS; } else { Print(L"Failed to load the image: %d\n", efi_status); } } if (SecureBoot) { if (ask_to_boot() == 0) { /* user told us not to boot this */ Print(L"Refusing to boot %s\n", loader); return EFI_ACCESS_DENIED; } Print(L"Booting %s with Present User Authorisation\n", loader); } efi_status = simple_file_open(image, loader, &file, EFI_FILE_MODE_READ); if (efi_status != EFI_SUCCESS) { Print(L"Failed to open %s\n", loader); return efi_status; } /* We're in setup mode and the User asked us to add the signature * of this binary to the authorized signatures database */ if (SetupMode) { UINT8 hash[SHA256_DIGEST_SIZE]; int i; sha256_get_pecoff_digest(image, loader, hash); Print(L"HASH IS "); for (i=0; iSignatureType = EFI_CERT_SHA256_GUID; l->SignatureListSize = sizeof(sig); l->SignatureSize = 16 +32; /* UEFI defined */ CopyMem(&d->SignatureData, hash, sizeof(hash)); efi_status = SetSecureVariable(L"db", sig, sizeof(sig), SIG_DB, EFI_VARIABLE_APPEND_WRITE, 0); if (efi_status != EFI_SUCCESS) { Print(L"Failed to add signature to db: %s\n", efi_status); return efi_status; } } dont_ask: ; } efi_status = pecoff_execute_image(file, loader, image, systab); simple_file_close(file); return efi_status; } efitools-1.9.2/LockDown.c000066400000000000000000000057221341522017100152350ustar00rootroot00000000000000/* * Copyright 2012 * * see COPYING file */ #include #include #include #include #include "PK.h" #include "KEK.h" #include "DB.h" EFI_STATUS efi_main (EFI_HANDLE image, EFI_SYSTEM_TABLE *systab) { EFI_STATUS efi_status; UINT8 SecureBoot, SetupMode; UINTN DataSize = sizeof(SetupMode); InitializeLib(image, systab); efi_status = RT->GetVariable(L"SetupMode", &GV_GUID, NULL, &DataSize, &SetupMode); if (efi_status != EFI_SUCCESS) { Print(L"No SetupMode variable ... is platform secure boot enabled?\n"); return EFI_SUCCESS; } if (!SetupMode) { Print(L"Platform is not in Setup Mode, cannot install Keys\n"); return EFI_SUCCESS; } Print(L"Platform is in Setup Mode\n"); efi_status = RT->SetVariable(L"KEK", &GV_GUID, EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS, KEK_auth_len, KEK_auth); if (efi_status != EFI_SUCCESS) { Print(L"Failed to enroll KEK: %d\n", efi_status); return efi_status; } Print(L"Created KEK Cert\n"); efi_status = RT->SetVariable(L"db", &SIG_DB, EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS, DB_auth_len, DB_auth); if (efi_status != EFI_SUCCESS) { Print(L"Failed to enroll db: %d\n", efi_status); return efi_status; } Print(L"Created db Cert\n"); #if 0 /* testing revocation ... this will revoke the certificate * we just enrolled in db */ efi_status = SetSecureVariable(L"dbx", DB_cer, DB_cer_len, SIG_DB, 0); if (efi_status != EFI_SUCCESS) { Print(L"Failed to enroll dbx: %d\n", efi_status); return efi_status; } #endif /* PK must be updated with a signed copy of itself */ efi_status = RT->SetVariable(L"PK", &GV_GUID, EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS, PK_auth_len, PK_auth); if (efi_status != EFI_SUCCESS) { Print(L"Failed to enroll PK: %d\n", efi_status); return efi_status; } Print(L"Created PK Cert\n"); /* enrolling the PK should put us in SetupMode; check this */ efi_status = RT->GetVariable(L"SetupMode", &GV_GUID, NULL, &DataSize, &SetupMode); if (efi_status != EFI_SUCCESS) { Print(L"Failed to get SetupMode variable: %d\n", efi_status); return efi_status; } Print(L"Platform is in %s Mode\n", SetupMode ? L"Setup" : L"User"); /* finally, check that SecureBoot is enabled */ efi_status = RT->GetVariable(L"SecureBoot", &GV_GUID, NULL, &DataSize, &SecureBoot); if (efi_status != EFI_SUCCESS) { Print(L"Failed to get SecureBoot variable: %d\n", efi_status); return efi_status; } Print(L"Platform %s set to boot securely\n", SecureBoot ? L"is" : L"is not"); return EFI_SUCCESS; } efitools-1.9.2/Make.rules000066400000000000000000000104521341522017100152760ustar00rootroot00000000000000EFISIGNED = $(patsubst %.efi,%-signed.efi,$(EFIFILES)) MANPAGES = $(patsubst doc/%.1.in,doc/%.1,$(wildcard doc/*.1.in)) HELP2MAN = help2man ARCH = $(shell uname -m | sed 's/i.86/ia32/;s/arm.*/arm/') ifeq ($(ARCH),ia32) ARCH3264 = -m32 else ifeq ($(ARCH),x86_64) ARCH3264 = else ifeq ($(ARCH),aarch64) ARCH3264 = else ifeq ($(ARCH),arm) ARCH3264 = else $(error unknown architecture $(ARCH)) endif INCDIR = -I$(TOPDIR)include/ -I/usr/include/efi -I/usr/include/efi/$(ARCH) -I/usr/include/efi/protocol CPPFLAGS = -DCONFIG_$(ARCH) CFLAGS = -O2 -g $(ARCH3264) -fpic -Wall -fshort-wchar -fno-strict-aliasing -fno-merge-constants -fno-stack-protector -ffreestanding -fno-stack-check LDFLAGS = -nostdlib CRTOBJ = crt0-efi-$(ARCH).o CRTPATHS = /lib /lib64 /lib/efi /lib64/efi /usr/lib /usr/lib64 /usr/lib/efi /usr/lib64/efi /usr/lib/gnuefi /usr/lib64/gnuefi CRTPATH = $(shell for f in $(CRTPATHS); do if [ -e $$f/$(CRTOBJ) ]; then echo $$f; break; fi; done) CRTOBJS = $(CRTPATH)/$(CRTOBJ) # there's a bug in the gnu tools ... the .reloc section has to be # aligned otherwise the file alignment gets screwed up LDSCRIPT = elf_$(ARCH)_efi.lds LDFLAGS += -shared -Bsymbolic $(CRTOBJS) -L $(CRTPATH) -L /usr/lib -L /usr/lib64 -T $(LDSCRIPT) LOADLIBES = -lefi -lgnuefi $(shell $(CC) $(ARCH3264) -print-libgcc-file-name) FORMAT = --target=efi-app-$(ARCH) OBJCOPY = objcopy MYGUID = 11111111-2222-3333-4444-123456789abc INSTALL = install BINDIR = $(DESTDIR)/usr/bin MANDIR = $(DESTDIR)/usr/share/man/man1 EFIDIR = $(DESTDIR)/usr/share/efitools/efi DOCDIR = $(DESTDIR)/usr/share/efitools # globally use EFI calling conventions (requires gcc >= 4.7) CFLAGS += -DGNU_EFI_USE_MS_ABI ifeq ($(ARCH),x86_64) CFLAGS += -DEFI_FUNCTION_WRAPPER -mno-red-zone endif ifeq ($(ARCH),ia32) CFLAGS += -mno-red-zone endif ifeq ($(ARCH),arm) LDFLAGS += --defsym=EFI_SUBSYSTEM=0x0a FORMAT = -O binary endif ifeq ($(ARCH),aarch64) LDFLAGS += --defsym=EFI_SUBSYSTEM=0x0a FORMAT = -O binary endif %.efi: %.so $(OBJCOPY) -j .text -j .sdata -j .data -j .dynamic -j .dynsym \ -j .rel -j .rela -j .rel.* -j .rela.* -j .rel* -j .rela* \ -j .reloc $(FORMAT) $*.so $@ %.so: %.o $(LD) $(LDFLAGS) $^ -o $@ $(LOADLIBES) # check we have no undefined symbols nm -D $@ | grep ' U ' && exit 1 || exit 0 %.h: %.auth ./xxdi.pl $< > $@ %.hash: %.efi hash-to-efi-sig-list ./hash-to-efi-sig-list $< $@ %-blacklist.esl: %.crt cert-to-efi-hash-list ./cert-to-efi-sig-list $< $@ %-hash-blacklist.esl: %.crt cert-to-efi-hash-list ./cert-to-efi-hash-list $< $@ %.esl: %.crt cert-to-efi-sig-list ./cert-to-efi-sig-list -g $(MYGUID) $< $@ getcert = $(shell if [ "$(1)" = "PK" -o "$(1)" = "KEK" ]; then echo "-c PK.crt -k PK.key"; else echo "-c KEK.crt -k KEK.key"; fi) getvar = $(shell if [ "$(1)" = "PK" -o "$(1)" = "KEK" ]; then echo $(1); else echo db; fi) %.auth: %.esl PK.crt KEK.crt sign-efi-sig-list ./sign-efi-sig-list $(call getcert,$*) $(call getvar,$*) $< $@ %-update.auth: %.esl PK.crt KEK.crt sign-efi-sig-list ./sign-efi-sig-list -a $(call getcert,$*) $(call getvar,$*) $< $@ %-pkupdate.auth: %.esl PK.crt sign-efi-sig-list ./sign-efi-sig-list -a -c PK.crt -k PK.key $(call getvar,$*) $< $@ %-blacklist.auth: %-blacklist.esl KEK.crt sign-efi-sig-list ./sign-efi-sig-list -a -c KEK.crt -k KEK.key dbx $< $@ %-pkblacklist.auth: %-blacklist.esl PK.crt sign-efi-sig-list ./sign-efi-sig-list -a -c PK.crt -k PK.key dbx $< $@ %.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 $@ %.crt: openssl req -new -x509 -newkey rsa:2048 -subj "/CN=$*/" -keyout $*.key -out $@ -days 3650 -nodes -sha256 %.cer: %.crt openssl x509 -in $< -out $@ -outform DER %-subkey.csr: openssl req -new -newkey rsa:2048 -keyout $*-subkey.key -subj "/CN=Subkey $* of KEK/" -out $@ -nodes %-subkey.crt: %-subkey.csr KEK.crt openssl x509 -req -in $< -CA DB.crt -CAkey DB.key -set_serial 1 -out $@ -days 365 %-signed.efi: %.efi DB.crt sbsign --key DB.key --cert DB.crt --output $@ $< ## # No need for KEK signing ## #%-kek-signed.efi: %.efi KEK.crt # sbsign --key KEK.key --cert KEK.crt --output $@ $< %.a: ar rcv $@ $^ doc/%.1: doc/%.1.in % $(HELP2MAN) --no-info -i $< -o $@ ./$* efitools-1.9.2/Makefile000066400000000000000000000063411341522017100150070ustar00rootroot00000000000000EFIFILES = HelloWorld.efi LockDown.efi Loader.efi ReadVars.efi UpdateVars.efi \ KeyTool.efi HashTool.efi SetNull.efi ShimReplace.efi BINARIES = cert-to-efi-sig-list sig-list-to-certs sign-efi-sig-list \ hash-to-efi-sig-list efi-readvar efi-updatevar cert-to-efi-hash-list \ flash-var ifeq ($(ARCH),x86_64) EFIFILES += PreLoader.efi endif MSGUID = 77FA9ABD-0359-4D32-BD60-28F4E78F784B KEYS = PK KEK DB EXTRAKEYS = DB1 DB2 EXTERNALKEYS = ms-uefi ms-kek ALLKEYS = $(KEYS) $(EXTRAKEYS) $(EXTERNALKEYS) KEYAUTH = $(ALLKEYS:=.auth) KEYUPDATEAUTH = $(ALLKEYS:=-update.auth) $(ALLKEYS:=-pkupdate.auth) KEYBLACKLISTAUTH = $(ALLKEYS:=-blacklist.auth) KEYHASHBLACKLISTAUTH = $(ALLKEYS:=-hash-blacklist.auth) export TOPDIR := $(shell pwd)/ include Make.rules EFISIGNED = $(patsubst %.efi,%-signed.efi,$(EFIFILES)) all: $(EFISIGNED) $(BINARIES) $(MANPAGES) noPK.auth $(KEYAUTH) \ $(KEYUPDATEAUTH) $(KEYBLACKLISTAUTH) $(KEYHASHBLACKLISTAUTH) install: all $(INSTALL) -m 755 -d $(MANDIR) $(INSTALL) -m 644 $(MANPAGES) $(MANDIR) $(INSTALL) -m 755 -d $(EFIDIR) $(INSTALL) -m 755 $(EFIFILES) $(EFIDIR) $(INSTALL) -m 755 -d $(BINDIR) $(INSTALL) -m 755 $(BINARIES) $(BINDIR) $(INSTALL) -m 755 mkusb.sh $(BINDIR)/efitool-mkusb $(INSTALL) -m 755 -d $(DOCDIR) $(INSTALL) -m 644 README COPYING $(DOCDIR) lib/lib.a lib/lib-efi.a: FORCE $(MAKE) -C lib $(notdir $@) lib/asn1/libasn1.a lib/asn1/libasn1-efi.a: FORCE $(MAKE) -C lib/asn1 $(notdir $@) .SUFFIXES: .crt .KEEP: PK.crt KEK.crt DB.crt PK.key KEK.key DB.key PK.esl DB.esl KEK.esl \ $(EFIFILES) LockDown.o: PK.h KEK.h DB.h PreLoader.o: hashlist.h PK.h: PK.auth KEK.h: KEK.auth DB.h: DB.auth noPK.esl: > noPK.esl noPK.auth: noPK.esl PK.crt sign-efi-sig-list ./sign-efi-sig-list -t "$(shell date --date='1 second' +'%Y-%m-%d %H:%M:%S')" -c PK.crt -k PK.key PK $< $@ ms-%.esl: ms-%.crt cert-to-efi-sig-list ./cert-to-efi-sig-list -g $(MSGUID) $< $@ hashlist.h: HashTool.hash cat $^ > /tmp/tmp.hash ./xxdi.pl /tmp/tmp.hash > $@ rm -f /tmp/tmp.hash Loader.so: lib/lib-efi.a ReadVars.so: lib/lib-efi.a lib/asn1/libasn1-efi.a UpdateVars.so: lib/lib-efi.a LockDown.so: lib/lib-efi.a KeyTool.so: lib/lib-efi.a lib/asn1/libasn1-efi.a HashTool.so: lib/lib-efi.a PreLoader.so: lib/lib-efi.a HelloWorld.so: lib/lib-efi.a ShimReplace.so: lib/lib-efi.a cert-to-efi-sig-list: cert-to-efi-sig-list.o lib/lib.a $(CC) $(ARCH3264) -o $@ $< lib/lib.a -lcrypto sig-list-to-certs: sig-list-to-certs.o lib/lib.a $(CC) $(ARCH3264) -o $@ $< lib/lib.a -lcrypto sign-efi-sig-list: sign-efi-sig-list.o lib/lib.a $(CC) $(ARCH3264) -o $@ $< lib/lib.a -lcrypto hash-to-efi-sig-list: hash-to-efi-sig-list.o lib/lib.a $(CC) $(ARCH3264) -o $@ $< lib/lib.a cert-to-efi-hash-list: cert-to-efi-hash-list.o lib/lib.a $(CC) $(ARCH3264) -o $@ $< lib/lib.a -lcrypto efi-keytool: efi-keytool.o lib/lib.a $(CC) $(ARCH3264) -o $@ $< lib/lib.a efi-readvar: efi-readvar.o lib/lib.a $(CC) $(ARCH3264) -o $@ $< lib/lib.a -lcrypto efi-updatevar: efi-updatevar.o lib/lib.a $(CC) $(ARCH3264) -o $@ $< lib/lib.a -lcrypto flash-var: flash-var.o lib/lib.a $(CC) $(ARCH3264) -o $@ $< lib/lib.a clean: rm -f PK.* KEK.* DB.* $(EFIFILES) $(EFISIGNED) $(BINARIES) *.o *.so rm -f noPK.* rm -f doc/*.1 $(MAKE) -C lib clean $(MAKE) -C lib/asn1 clean FORCE: efitools-1.9.2/PreLoader.c000066400000000000000000000055111341522017100153660ustar00rootroot00000000000000/* * Copyright 2012 * * see COPYING file * */ #include #include #include #include #include #include #include #include "hashlist.h" CHAR16 *loader = L"loader.efi"; CHAR16 *hashtool = L"HashTool.efi"; EFI_STATUS efi_main (EFI_HANDLE image, EFI_SYSTEM_TABLE *systab) { EFI_STATUS status; UINT8 SecureBoot; UINTN DataSize = sizeof(SecureBoot); InitializeLib(image, systab); console_reset(); status = RT->GetVariable(L"SecureBoot", &GV_GUID, NULL, &DataSize, &SecureBoot); if (status != EFI_SUCCESS) { Print(L"Not a Secure Boot Platform %d\n", status); goto override; } if (!SecureBoot) { Print(L"Secure Boot Disabled\n"); goto override; } status = security_policy_install(security_policy_mok_override, security_policy_mok_allow, security_policy_mok_deny); if (status != EFI_SUCCESS) { console_error(L"Failed to install override security policy", status); /* Don't die, just try to execute without security policy */ goto override; } /* install statically compiled in hashes */ security_protocol_set_hashes(_tmp_tmp_hash, _tmp_tmp_hash_len); /* Check for H key being pressed */ if (console_check_for_keystroke('H')) goto start_hashtool; status = execute(image, loader); if (status == EFI_SUCCESS) goto out; if (status != EFI_SECURITY_VIOLATION && status != EFI_ACCESS_DENIED) { CHAR16 buf[256]; StrCpy(buf, L"Failed to start "); StrCat(buf, loader); console_error(buf, status); goto out; } console_alertbox((CHAR16 *[]) { L"Failed to start loader", L"", L"It should be called loader.efi (in the current directory)", L"Please enrol its hash and try again", L"", L"I will now execute HashTool for you to do this", NULL }); for (;;) { start_hashtool: status = execute(image, hashtool); if (status != EFI_SUCCESS) { CHAR16 buf[256]; StrCpy(buf, L"Failed to start backup programme "); StrCat(buf, hashtool); console_error(buf, status); goto out; } /* try to start the loader again */ status = execute(image, loader); if (status == EFI_ACCESS_DENIED || status == EFI_SECURITY_VIOLATION) { int selection = console_select((CHAR16 *[]) { L"loader is still giving a security error", NULL }, (CHAR16 *[]) { L"Start HashTool", L"Exit", NULL }, 0); if (selection == 0) continue; } break; } out: status = security_policy_uninstall(); if (status != EFI_SUCCESS) console_error(L"Failed to uninstall security policy. Platform needs rebooting", status); return status; override: status = execute(image, loader); if (status != EFI_SUCCESS) { CHAR16 buf[256]; StrCpy(buf, L"Failed to start "); StrCat(buf, loader); console_error(buf, status); } return status; } efitools-1.9.2/README000066400000000000000000000070001341522017100142200ustar00rootroot00000000000000How to use these files simply typing make will build you everything including sample certificates for PK, KEK and db. The prerequisites are the standard development environment, gnu-efi version 3.0q or later, help2man and sbsigntools. There will be one file called LockDown.efi. If run on your efi platform in Setup Mode, this binary will *replace* all the values in the PK, KEK and db variables with the ones you just generated and place the platform back into User Mode (booting securely). If you don't want to replace all the variables, take a dump of your current variables, see sig-list-to-cert(1), and add them to the EFI signature list files before creating LockDown.efi Say you want to concatenate an existing platform-db.esl file, do this: make DB.esl cat platform.esl DB.esl > newDB.esl mv newDB.esl DB.esl and then make LockDown.efi in the usual way. All of the EFI programs are also generated in signed form (signed by both db and KEK). Loader.efi ========== This EFI binary is created to boot an unsigned EFI file on the platform. Since this explicitly breaks the security of the platform, it will first check to see if the boot binary is naturally executable and execute it if it is (either it's properly signed or the platform isn't in Secure Boot mode). If the binary gives an EFI_ACCESS_DENIED error meaning it isn't properly signed, Loader.efi will request present user authorisation before proceeding to boot. The idea is that Loader.efi may serve as a chain for elilo.efi or another boot loader on distributed linux live and install CDs and even as the boot loader for the distribution on the hard disk assuming the user does not wish to take control of the platform and replace the keys. To build a secure bootable CD, simply use Loader.efi as the usual /efi/boot/bootX64.efi and place the usual loader in the same directory as the file boot.efi. In order to add further convenience, if the user places the platform in setup mode and re-runs the loader, it will ask permission to add the signature the unsigned boot loader, boot.efi, to the authorised signatures database, meaning Loader.efi will now no longer ask for present user authorisation every time the system is started. Creating, using and installing your own keys ============================================ To create PEM files with the certificate and the key for PK for example, do openssl req -new -x509 -newkey rsa:2048 -subj "/CN=PK/" -keyout PK.key -out PK.crt -days 3650 -nodes -sha256 Which will create a self signed X509 certificate for PK in PK.crt (using unprotected key PK.key with the subject common name PK (that's what the CN=PK is doing). You need to create at least three sets of certificates: one for PK, one for KEK and one for db. Now you need to take all the efi binaries in /usr/share/efitools/efi and sign them with your own db key using sbsign --key db.key --cert db.crt --output HelloWorld-signed.efi HelloWorld.efi To install your new keys on the platform, first create your authorised update bundles: cert-to-sig-list PK.crt PK.esl sign-efi-sig-list -k PK.key -c PK.crt PK PK.esl PK.auth And repeat for KEK and db. In setup mode, it only matters that the PK update PK.auth is signed by the new platform key. None of the other variables will have their signatures checked. Now on your platform update the variables, remembering to do PK last because an update to PK usually puts the platform into secure mode UpdateVars db db.auth UpdateVars KEK KEK.auth UpdateVars PK PK.auth And you should now be running in secure mode with your own keys. efitools-1.9.2/ReadVars.c000066400000000000000000000121301341522017100152130ustar00rootroot00000000000000/* * Copyright 2012 * * see COPYING file * * Read and dump all the secure variables */ #include #include #include #include #include #include #include #include #include "efiauthenticated.h" void parse_db(UINT8 *data, UINTN len, EFI_HANDLE image, CHAR16 *name, int save_file) { EFI_SIGNATURE_LIST *CertList = (EFI_SIGNATURE_LIST *)data; EFI_SIGNATURE_DATA *Cert; UINTN count = 0, DataSize = len; EFI_FILE *file; CHAR16 *buf = AllocatePool(StrSize(name) + 4 + 2 + 4 + 8 +100); CHAR16 *ext; EFI_STATUS status; int size; certlist_for_each_certentry(CertList, data, size, DataSize) { int Index = 0; count++; if (CompareGuid(&CertList->SignatureType, &X509_GUID) == 0) { ext = L"X509"; } else if (CompareGuid(&CertList->SignatureType, &RSA2048_GUID) == 0) { ext = L"RSA2048"; } else if (CompareGuid(&CertList->SignatureType, &PKCS7_GUID) == 0) { ext = L"PKCS7"; } else if (CompareGuid(&CertList->SignatureType, &EFI_CERT_SHA256_GUID) == 0) { ext = L"SHA256"; } else { ext = L"Unknown"; } Print(L"%s: List %d, type %s\n", name, count, ext); certentry_for_each_cert(Cert, CertList) { Print(L" Signature %d, size %d, owner %g\n", Index++, CertList->SignatureSize, &Cert->SignatureOwner); if (StrCmp(ext, L"X509") == 0) { CHAR16 buf1[4096]; x509_to_str(Cert->SignatureData, CertList->SignatureSize, X509_OBJ_SUBJECT, buf1, sizeof(buf1)); Print(L" Subject: %s\n", buf1); x509_to_str(Cert->SignatureData, CertList->SignatureSize, X509_OBJ_ISSUER, buf1, sizeof(buf1)); Print(L" Issuer: %s\n", buf1); } else if (StrCmp(ext, L"SHA256") == 0) { CHAR16 buf1[256]; StrCpy(buf1, L"Hash: "); sha256_StrCat_hash(buf1, Cert->SignatureData); Print(L" %s\n", buf1); } if (save_file) { SPrint(buf, 0, L"%s-%d-%d-%s-%g", name, count, Index, ext, &Cert->SignatureOwner); Print(L"Writing to file %s\n", buf); status = simple_file_open(image, buf, &file, EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE); if (status != EFI_SUCCESS) { Print(L"Failed to open file %s: %d\n", buf, status); continue; } status = simple_file_write_all(file, CertList->SignatureSize-sizeof(EFI_GUID), Cert->SignatureData); simple_file_close(file); if (status != EFI_SUCCESS) { Print(L"Failed to write signature to file %s: %d\n", buf, status); continue; } } } } FreePool(buf); } EFI_STATUS efi_main (EFI_HANDLE image, EFI_SYSTEM_TABLE *systab) { EFI_STATUS status; CHAR16 **variables; EFI_GUID *owners; CHAR16 **ARGV, *progname; UINT8 *data; UINTN len; int i, argc, save_keys = 0, no_print = 0; InitializeLib(image, systab); if (GetOSIndications() & EFI_OS_INDICATIONS_TIMESTAMP_REVOCATION) { variables = (CHAR16 *[]){ L"PK", L"KEK", L"db", L"dbx", L"dbt", L"MokList" , NULL}; owners = (EFI_GUID []){ GV_GUID, GV_GUID, SIG_DB, SIG_DB, SIG_DB, MOK_OWNER }; } else { variables = (CHAR16 *[]){ L"PK", L"KEK", L"db", L"dbx", L"MokList" , NULL}; owners = (EFI_GUID []){ GV_GUID, GV_GUID, SIG_DB, SIG_DB, MOK_OWNER }; } status = argsplit(image, &argc, &ARGV); if (status != EFI_SUCCESS) { Print(L"Failed to parse arguments: %d\n", status); return status; } progname = ARGV[0]; while (argc > 1 && ARGV[1][0] == L'-') { if (StrCmp(ARGV[1], L"-s") == 0) { save_keys = 1; ARGV += 1; argc -= 1; } else if (StrCmp(ARGV[1], L"-n") == 0) { no_print = 1; ARGV += 1; argc -= 1; } else { /* unrecognised option */ break; } } if ((argc != 2 && argc != 1) || (argc != 1 && no_print)) { Print(L"Usage: %s: [-s|-n] [var]\n", progname); return EFI_INVALID_PARAMETER; } if (argc == 1) { for (i = 0; variables[i] != NULL; i++) { status = get_variable(variables[i], &data, &len, owners[i]); if (status == EFI_NOT_FOUND) { Print(L"Variable %s has no entries\n", variables[i]); } else if (status != EFI_SUCCESS) { Print(L"Failed to get %s: %d\n", variables[i], status); } else { Print(L"Variable %s length %d\n", variables[i], len); parse_db(data, len, image, variables[i], save_keys); FreePool(data); } } } else { CHAR16 *var = ARGV[1]; for(i = 0; variables[i] != NULL; i++) { if (StrCmp(var, variables[i]) == 0) { break; } } if (variables[i]== NULL) { Print(L"Invalid Variable %s\nVariable must be one of: ", var); for (i = 0; variables[i] != NULL; i++) Print(L"%s ", variables[i]); Print(L"\n"); return EFI_INVALID_PARAMETER; } status = get_variable(variables[i], &data, &len, owners[i]); if (status == EFI_NOT_FOUND) { Print(L"Variable %s has no entries\n", variables[i]); } else if (status != EFI_SUCCESS) { Print(L"Failed to get %s: %d\n", variables[i], status); } else { Print(L"Variable %s length %d\n", variables[i], len); parse_db(data, len, image, variables[i], save_keys); FreePool(data); parse_db(data, len, image, variables[i], save_keys); } } return EFI_SUCCESS; } efitools-1.9.2/SetNull.c000066400000000000000000000002211341522017100150700ustar00rootroot00000000000000#include EFI_STATUS efi_main (EFI_HANDLE image, EFI_SYSTEM_TABLE *systab) { int *test = NULL; *test = 0x123; return EFI_SUCCESS; } efitools-1.9.2/ShimReplace.c000066400000000000000000000027231341522017100157070ustar00rootroot00000000000000/* * Copyright 2016 * * see COPYING file * * Replacement for shim.efi which is signed by your own key * and installs the shim protocol verifier for grub to use * so the secure boot chain is unbroken */ #include #include #include #include #include #include #include #include static const CHAR16 *loader = L"\\grub.efi"; static const CHAR16 *fallback = L"\\fallback.efi"; EFI_STATUS efi_main (EFI_HANDLE image, EFI_SYSTEM_TABLE *systab) { EFI_STATUS efi_status; EFI_PKCS7_VERIFY_PROTOCOL *p7vp; CHAR16 *error; void *ptr; InitializeLib(image, systab); efi_status = pkcs7verify_get_protocol(image, &p7vp, &error); if (efi_status != EFI_SUCCESS) { console_error(error, efi_status); return efi_status; } efi_status = shim_protocol_install(); if (efi_status != EFI_SUCCESS) console_error(L"Failed to install shim protocol", efi_status); efi_status = BS->LocateProtocol(&MOK_OWNER, NULL, &ptr); if (efi_status != EFI_SUCCESS) console_error(L"Failed to locate shim protocol", efi_status); efi_status = execute(image, loader); if (efi_status == EFI_SUCCESS) return efi_status; console_error(L"Failed to start primary loader", efi_status); efi_status = execute(image, fallback); if (efi_status != EFI_SUCCESS) console_error(L"Failed to start fallback loader", efi_status); return efi_status; } efitools-1.9.2/UpdateVars.c000066400000000000000000000072221341522017100155700ustar00rootroot00000000000000/* * Copyright 2012 * * see COPYING file * * Update a secure varible when in secure mode * * For instance append a signature to the KEK, db or dbx datbases */ #include #include #include #include #include #include #include "efiauthenticated.h" EFI_STATUS efi_main (EFI_HANDLE image, EFI_SYSTEM_TABLE *systab) { EFI_STATUS status; int argc, i, esl_mode = 0, hash_mode = 0; CHAR16 **ARGV, *var, *name, *progname, *owner_guid; EFI_FILE *file; void *buf; UINTN size, options = 0; EFI_GUID *owner; CHAR16 **variables; EFI_GUID **owners; InitializeLib(image, systab); if (GetOSIndications() & EFI_OS_INDICATIONS_TIMESTAMP_REVOCATION) { variables = (CHAR16 *[]){ L"PK", L"KEK", L"db", L"dbx", L"dbt", L"MokList" , NULL}; owners = (EFI_GUID *[]){ &GV_GUID, &GV_GUID, &SIG_DB, &SIG_DB, &SIG_DB, &MOK_OWNER }; } else { variables = (CHAR16 *[]){ L"PK", L"KEK", L"db", L"dbx", L"MokList" , NULL}; owners = (EFI_GUID *[]){ &GV_GUID, &GV_GUID, &SIG_DB, &SIG_DB, &MOK_OWNER }; } status = argsplit(image, &argc, &ARGV); if (status != EFI_SUCCESS) { Print(L"Failed to parse arguments: %d\n", status); return status; } progname = ARGV[0]; while (argc > 1 && ARGV[1][0] == L'-') { if (StrCmp(ARGV[1], L"-a") == 0) { options |= EFI_VARIABLE_APPEND_WRITE; ARGV += 1; argc -= 1; } else if (StrCmp(ARGV[1], L"-g") == 0) { owner_guid = ARGV[2]; ARGV += 2; argc -= 2; } else if (StrCmp(ARGV[1], L"-e") == 0) { esl_mode = 1; ARGV += 1; argc -= 1; } else if (StrCmp(ARGV[1], L"-b") == 0) { esl_mode = 1; hash_mode = 1; ARGV += 1; argc -= 1; } else { /* unrecognised option */ break; } } if (argc != 3 ) { Print(L"Usage: %s: [-g guid] [-a] [-e] [-b] var file\n", progname); return EFI_INVALID_PARAMETER; } var = ARGV[1]; name = ARGV[2]; for(i = 0; variables[i] != NULL; i++) { if (StrCmp(var, variables[i]) == 0) { owner = owners[i]; break; } } if (variables[i] == NULL) { Print(L"Invalid Variable %s\nVariable must be one of: ", var); for (i = 0; variables[i] != NULL; i++) Print(L"%s ", variables[i]); Print(L"\n"); return EFI_INVALID_PARAMETER; } if (owner == &MOK_OWNER) { if (!esl_mode) { Print(L"MoK variables can only be updated in ESL mode\n"); return EFI_INVALID_PARAMETER; } /* hack: esl goes directly into MoK variables, so we now * pretend we have a direct .auth update */ esl_mode = 0; } else { /* non MoK variables have runtime access and time based * authentication, MoK ones don't */ options |= EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS; } status = simple_file_open(image, name, &file, EFI_FILE_MODE_READ); if (status != EFI_SUCCESS) { Print(L"Failed to open file %s\n", name); return status; } status = simple_file_read_all(file, &size, &buf); if (status != EFI_SUCCESS) { Print(L"Failed to read file %s\n", name); return status; } simple_file_close(file); if (hash_mode) { UINT8 hash[SHA256_DIGEST_SIZE]; status = sha256_get_pecoff_digest_mem(buf, size, hash); if (status != EFI_SUCCESS) { Print(L"Failed to get hash of %s\n", name); return status; } status = variable_enroll_hash(var, *owner, hash); } else if (esl_mode) { status = SetSecureVariable(var, buf, size, *owner, options, 0); } else { status = RT->SetVariable(var, owner, EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | options, size, buf); } if (status != EFI_SUCCESS) { Print(L"Failed to update variable %s: %d\n", var, status); return status; } return EFI_SUCCESS; } efitools-1.9.2/cert-to-efi-hash-list.c000066400000000000000000000133561341522017100175270ustar00rootroot00000000000000/* * Copyright 2012 * * see COPYING file */ #include #define _XOPEN_SOURCE #include #ifdef CONFIG_arm /* FIXME: * arm efi leaves a visibilit pragma pushed that won't work for * non efi programs, so eliminate it */ #pragma GCC visibility pop #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static void usage(const char *progname) { printf("Usage: %s [-g ][-t ][-s ] \n", progname); } static void help(const char * progname) { usage(progname); printf("Take an input X509 certificate (in PEM format) and convert it to an EFI\n" "signature hash list file containing only that single certificate\n\n" "Options:\n" "\t-g Use as the owner of the signature. If this is not\n" "\t supplied, an all zero guid will be used\n" "\t-s Use SHA hash algorithm (256, 384, 512)\n" "\t-t Time of Revocation for hash signature\n" " Set to 0 if not specified meaning revoke\n" " for all time.\n" ); } int main(int argc, char *argv[]) { char *certfile, *efifile; const char *progname = argv[0]; EFI_GUID owner = { 0 }; int sha = 256; EFI_TIME timestamp; char *timestampstr = NULL; memset(×tamp, 0, sizeof(timestamp)); while (argc > 1) { if (strcmp("--version", argv[1]) == 0) { version(progname); exit(0); } else if (strcmp("--help", argv[1]) == 0) { help(progname); exit(0); } else if (strcmp("-g", argv[1]) == 0) { str_to_guid(argv[2], &owner); argv += 2; argc -= 2; } else if (strcmp("-s", argv[1]) == 0) { sha = atoi(argv[2]); argv += 2; argc -= 2; } else if (strcmp("-t", argv[1]) == 0) { timestampstr = argv[2]; argv += 2; argc -= 2; } else { break; } } if (argc != 3) { usage(progname); exit(1); } if (sha != 256 && sha != 384 && sha != 512) { fprintf(stderr, "Supported algorithms are sha256, sha384 or sha512\n"); exit(1); } if (timestampstr) { struct tm tms; strptime(timestampstr, "%Y-%m-%d %H:%M:%S", &tms); /* timestamp.Year is from 0 not 1900 as tm year is */ tms.tm_year += 1900; timestamp.Year = tms.tm_year; timestamp.Month = tms.tm_mon + 1; timestamp.Day = tms.tm_mday; timestamp.Hour = tms.tm_hour; timestamp.Minute = tms.tm_min; timestamp.Second = tms.tm_sec; } certfile = argv[1]; efifile = argv[2]; printf("TimeOfRevocation is %d-%d-%d %02d:%02d:%02d\n", timestamp.Year, timestamp.Month, timestamp.Day, timestamp.Hour, timestamp.Minute, timestamp.Second); ERR_load_crypto_strings(); OpenSSL_add_all_digests(); OpenSSL_add_all_ciphers(); /* here we may get highly unlikely failures or we'll get a * complaint about FIPS signatures (usually becuase the FIPS * module isn't present). In either case ignore the errors * (malloc will cause other failures out lower down */ ERR_clear_error(); BIO *cert_bio = BIO_new_file(certfile, "r"); X509 *cert = PEM_read_bio_X509(cert_bio, NULL, NULL, NULL); unsigned char *cert_buf = NULL; #if OPENSSL_VERSION_NUMBER < 0x10100000L int cert_len = i2d_X509_CINF(cert->cert_info, &cert_buf); #else int cert_len = i2d_re_X509_tbs(cert, &cert_buf); #endif ERR_print_errors_fp(stdout); int len, digest_len, time_offset; EFI_GUID guid; const EVP_MD *md; if (sha == 256) { len = sizeof(EFI_CERT_X509_SHA256); digest_len = sizeof(EFI_SHA256_HASH); guid = EFI_CERT_X509_SHA256_GUID; md = EVP_get_digestbyname("SHA256"); time_offset = OFFSET_OF(EFI_CERT_X509_SHA256, TimeOfRevocation); } else if (sha == 384) { len = sizeof(EFI_CERT_X509_SHA384); digest_len = sizeof(EFI_SHA384_HASH); guid = EFI_CERT_X509_SHA384_GUID; md = EVP_get_digestbyname("SHA384"); time_offset = OFFSET_OF(EFI_CERT_X509_SHA384, TimeOfRevocation); } else if (sha == 512) { len = sizeof(EFI_CERT_X509_SHA512); digest_len = sizeof(EFI_SHA512_HASH); guid = EFI_CERT_X509_SHA512_GUID; md = EVP_get_digestbyname("SHA512"); time_offset = OFFSET_OF(EFI_CERT_X509_SHA512, TimeOfRevocation); } else { fprintf(stderr, "assertion failure sha%d\n", sha); exit(1); } len += sizeof(EFI_SIGNATURE_LIST) + OFFSET_OF(EFI_SIGNATURE_DATA, SignatureData); unsigned char *buf = malloc(len); EFI_SIGNATURE_LIST *SigList = (EFI_SIGNATURE_LIST *)buf; SigList->SignatureListSize = len; SigList->SignatureSize = (UINT32)(len - sizeof(EFI_SIGNATURE_LIST)); SigList->SignatureHeaderSize = 0; SigList->SignatureType = guid; EFI_SIGNATURE_DATA *SigData = (void *)buf + sizeof(EFI_SIGNATURE_LIST); SigData->SignatureOwner = owner; /* point buf at hash buffer */ unsigned char *digest = (void *)SigData + OFFSET_OF(EFI_SIGNATURE_DATA, SignatureData); EFI_TIME *TimeOfRevocation = (void *)digest + time_offset; *TimeOfRevocation = timestamp; EVP_MD_CTX *ctx; unsigned int md_len; ctx = EVP_MD_CTX_create(); EVP_DigestInit_ex(ctx, md, NULL); EVP_DigestUpdate(ctx, cert_buf, cert_len); EVP_DigestFinal_ex(ctx, digest, &md_len); EVP_MD_CTX_destroy(ctx); if (digest_len != md_len) { fprintf(stderr, "Digest assertion failure sha%d %d != %d\n", sha, digest_len, md_len); exit(1); } FILE *f = fopen(efifile, "w"); if (!f) { fprintf(stderr, "failed to open efi file %s: ", efifile); perror(""); exit(1); } if (fwrite(buf, 1, len, f) != len) { perror("Did not write enough bytes to efi file"); exit(1); } return 0; } efitools-1.9.2/cert-to-efi-sig-list.c000066400000000000000000000057271341522017100173710ustar00rootroot00000000000000/* * Copyright 2012 * * see COPYING file */ #include #define __STDC_VERSION__ 199901L #include #ifdef CONFIG_arm /* FIXME: * arm efi leaves a visibilit pragma pushed that won't work for * non efi programs, so eliminate it */ #pragma GCC visibility pop #endif #include #include #include #include #include #include #include #include static void usage(const char *progname) { printf("Usage: %s [-g ] \n", progname); } static void help(const char * progname) { usage(progname); printf("Take an input X509 certificate (in PEM format) and convert it to an EFI\n" "signature list file containing only that single certificate\n\n" "Options:\n" "\t-g Use as the owner of the signature. If this is not\n" "\t supplied, an all zero guid will be used\n" ); } int main(int argc, char *argv[]) { char *certfile, *efifile; const char *progname = argv[0]; EFI_GUID owner = { 0 }; while (argc > 1) { if (strcmp("--version", argv[1]) == 0) { version(progname); exit(0); } else if (strcmp("--help", argv[1]) == 0) { help(progname); exit(0); } else if (strcmp("-g", argv[1]) == 0) { str_to_guid(argv[2], &owner); argv += 2; argc -= 2; } else { break; } } if (argc != 3) { exit(1); } certfile = argv[1]; efifile = argv[2]; ERR_load_crypto_strings(); OpenSSL_add_all_digests(); OpenSSL_add_all_ciphers(); /* here we may get highly unlikely failures or we'll get a * complaint about FIPS signatures (usually becuase the FIPS * module isn't present). In either case ignore the errors * (malloc will cause other failures out lower down */ ERR_clear_error(); BIO *cert_bio = BIO_new_file(certfile, "r"); X509 *cert = PEM_read_bio_X509(cert_bio, NULL, NULL, NULL); int PkCertLen = i2d_X509(cert, NULL); PkCertLen += sizeof(EFI_SIGNATURE_LIST) + OFFSET_OF(EFI_SIGNATURE_DATA, SignatureData); EFI_SIGNATURE_LIST *PkCert = malloc (PkCertLen); if (!PkCert) { fprintf(stderr, "failed to malloc cert\n"); exit(1); } unsigned char *tmp = (unsigned char *)PkCert + sizeof(EFI_SIGNATURE_LIST) + OFFSET_OF(EFI_SIGNATURE_DATA, SignatureData); i2d_X509(cert, &tmp); PkCert->SignatureListSize = PkCertLen; PkCert->SignatureSize = (UINT32) (PkCertLen - sizeof(EFI_SIGNATURE_LIST)); PkCert->SignatureHeaderSize = 0; PkCert->SignatureType = EFI_CERT_X509_GUID; EFI_SIGNATURE_DATA *PkCertData = (void *)PkCert + sizeof(EFI_SIGNATURE_LIST); PkCertData->SignatureOwner = owner; FILE *f = fopen(efifile, "w"); if (!f) { fprintf(stderr, "failed to open efi file %s: ", efifile); perror(""); exit(1); } if (fwrite(PkCert, 1, PkCertLen, f) != PkCertLen) { perror("Did not write enough bytes to efi file"); exit(1); } return 0; } efitools-1.9.2/doc/000077500000000000000000000000001341522017100141105ustar00rootroot00000000000000efitools-1.9.2/doc/cert-to-efi-hash-list.1.in000066400000000000000000000015611341522017100206120ustar00rootroot00000000000000[name] cert-to-efi-hash-list - tool for converting openssl certificates to EFI signature hash revocation lists [examples] To take a standard X509 certificate in PEM format and produce an output EFI signature list file, simply do cert-to-efi-hash-list PK.crt PK.esl Note that the format of EFI signature list files is such that they can simply be concatenated to produce a file with multiple signatures: cat PK1.esl PK2.esl > PK.esl If your platform has a setup mode key manipulation ability, the keys will often only be displayed by GUID, so using the -g option to give your keys recognisable GUIDs will be useful if you plan to manage lots of keys. [see also] sign-efi-sig-list(1) for details on how to create an authenticated update to EFI secure variables when the EFI system is in user mode. [note] Signature revocation hashes are only implemented in UEFI 2.4 and up efitools-1.9.2/doc/cert-to-efi-sig-list.1.in000066400000000000000000000014221341522017100204450ustar00rootroot00000000000000[name] cert-to-efi-sig-list - tool for converting openssl certificates to EFI signature lists [examples] To take a standard X509 certificate in PEM format and produce an output EFI signature list file, simply do cert-to-efi-sig-list PK.crt PK.esl Note that the format of EFI signature list files is such that they can simply be concatenated to produce a file with multiple signatures: cat PK1.esl PK2.esl > PK.esl If your platform has a setup mode key manipulation ability, the keys will often only be displayed by GUID, so using the -g option to give your keys recognisable GUIDs will be useful if you plan to manage lots of keys. [see also] sign-efi-sig-list(1) for details on how to create an authenticated update to EFI secure variables when the EFI system is in user mode. efitools-1.9.2/doc/efi-readvar.1.in000066400000000000000000000012551341522017100167670ustar00rootroot00000000000000[name] efi-readvar - tool for showing secure variables [description] with no arguments, prints out the entire secure variable database and expands the contents of hashes and X509 certificates. May be restricted to specific variables and specific signatures within variables. Note that EFI signature lists are numbered from zero and may contain one or more entries (also numbered from zero), so 0-0 represents the first entry of signature list zero. [examples] To see all the variables, type efi-readvars To see the second entry of signature list 1 for the db variable, do efi-readvars -v db -s 1-1 To see all entries of signature list 0 for the KEK efi-readvars -v KEK -s 0 efitools-1.9.2/doc/efi-updatevar.1.in000066400000000000000000000030171341522017100173340ustar00rootroot00000000000000[name] efi-updatevar - tool for updating secure variables [description] Takes a variety of input files and adds them to one of the UEFI secure boot signature or key databases. Note that the efivarfs filesystem must be mounted somewhere on the box and efi-updatevars must have the ability to write to the files (this usually means it must run as root). [examples] Assuming you own your own platform key and have the PK.auth and noPK.auth files which go with it, you can programmatically move the system out of User Mode by doing efi-updatevar -f noPK.auth PK and put it back again with efi-updatevar -f PK.auth PK To add the hash of an efi binary bin.efi to db in Setup Mode do efi-updatevar -b bin.efi db And to append an EFI signature list append.esl to db in Setup Mode do efi-updatevar -a -e append.esl db To add your key (KEK.crt) to the Key Exchange Key in User Mode, assuming the private part of the platform key is in PK.key, do efi-updatevar -a -c KEK.crt -k PK.key KEK To add certificate DB.crt to db in User Mode assuming the private part of the Key Exchange Key (KEK) is in KEK.key do efi-updatevar -a -c DB.crt -k KEK.key db To replace the old platform key (PK) with a new one in newPK.crt in User Mode assuming the private part of the old platform key is in PK.key, do efi-updatevar -c newPK.crt -k PK.key db To delete the private key, tipping the platform from User Mode to Setup Mode, do efi-updatevar -d 0 -k PK.key PK And to put the private key back again (in Setup Mode) do efi-updatevar -c PK.crt -k PK.key PK efitools-1.9.2/doc/hash-to-efi-sig-list.1.in000066400000000000000000000006611341522017100204370ustar00rootroot00000000000000[name] hash-efi-sig-list - create a hash signature list entry from a binary [examples] To create a hash efi-signature-list in the file hash.esl from the binary HelloWorld.efi do hash-efi-sig-list HelloWorld.efi hash.esl This hash file can now be placed directly (or as an update) into the db variables with UpdateVar [see also] sign-efi-sig-list(1) for details on how to produce authenticated update files for the db variable. efitools-1.9.2/doc/sig-list-to-certs.1.in000066400000000000000000000022561341522017100200750ustar00rootroot00000000000000[name] sig-list-to-certs - tool for converting EFI signature lists back to openssl certificates [description] Takes and converts it to a set of DER format openssl certificates in .n (where n runs from 0 to the number of certificates in the file) [examples] To see what certificates your UEFI system currently has, you can run the dmpstore command to print them to a file dmpstore PK > PK.uc16 This file isn't readily readable on a standard unix system because it's in UC-16 format, so convert it to ordinary text iconv -f utf-16 PK.uc16 > PK.txt Now remove the header which says something like Dump Variable pk Variable NV+RT+BS 'Efi:PK' DataSize = 2DA Leaving only the hex dump. This can then be converted to an EFI signature list by xxd xxd -r PK.txt > PK.esl and you can now extract openssl readable certificates from this sig-list-to-certs PK.esl PK Which will print some information like X509 Header sls=730, header=0, sig=686 file PK.0: Guid 77fa9abd-0359-4d32-4d60-28f4e78f784b Written 686 bytes And finally, you can see the certificate in text format openssl x509 -text -inform DER -in PK.0 Assuming it's an X509 certificate efitools-1.9.2/doc/sign-efi-sig-list.1.in000066400000000000000000000027771341522017100200460ustar00rootroot00000000000000[name] sign-efi-sig-list - signing tool for secure variables as EFI Signature Lists [examples] To sign a simple append update to db which has been prepared as an EFI Signature List in DB.esl and output the result with the authentication header in DB.auth sign-efi-sig-list -a -c KEK.crt -k KEK.key db DB.esl DB.auth To do a detached signature in the same way sign-efi-sig-list -a -t 'Jul 21 09:39:37 BST 2012' -o db DB.esl DB.forsig Now sign the DB.forsig file in the standard openssl way. Note that the standards require sha256 as the signature algorithm openssl smime -sign -binary -in DB.forsig -out DB.signed -signer KEK.crt -inkey KEK.key -outform DER -md sha256 Which produces a detached PKCS7 signature in DB.signed. Now feed this back into the program remembering to keep the same timestamp (and the -a flag): sign-efi-sig-list -a -i DB.signed -t 'Jul 21 09:39:37 BST 2012' db DB.auth To delete a key, simply sign an empty EFI signature list file, so to produce an variable update that will delete the PK: > null.esl And then sign it in the standard way (must not be an append write update): sign-efi-sig-list -c PK.crt -k PK.key PK null.esl PK.auth Once you have the .auth file conveyed to the UEFI platform, you can use the UpdateVars.efi program to apply it UpdateVars [-a] db DB.auth Where the -a flag must be present if the DB.auth file was created as an append write update and absent if its replacing the variable. [see also] cert-to-efi-sig-list(1) for details on how to produce EFI signature lists. efitools-1.9.2/efi-keytool.c000066400000000000000000000012121341522017100157320ustar00rootroot00000000000000/* * Copyright 2013 * * see COPYING file */ #include #include #include #include #include #include #include #include #include #include #define __STDC_VERSION__ 199901L #include #include int main(int argc, char *argv[]) { int setup_mode; kernel_variable_init(); setup_mode = variable_is_setupmode(); printf("Platform is in %s\n", setup_mode ? "Setup Mode" : "User Mode"); printf("Secure boot is %s\n", variable_is_secureboot() ? "on" : "off"); return 0; } efitools-1.9.2/efi-readvar.c000066400000000000000000000113151341522017100156750ustar00rootroot00000000000000/* * Copyright 2013 * * see COPYING file */ #include #include #include #include #include #include #include #include #include #include #include #define __STDC_VERSION__ 199901L #include #include #include #include #include #include "efiauthenticated.h" #define ARRAY_SIZE(a) (sizeof (a) / sizeof ((a)[0])) static void usage(const char *progname) { printf("Usage: %s: [-v ] [-s [-]] [-o ]\n", progname); } static void help(const char *progname) { usage(progname); printf("List the contents of the UEFI signature databases\n\n" "Options:\n" "\t-v \tlist only the contents of \n" "\t-s [-]\tlist only a given signature list (and optionally\n" "\t\tonly a given entry in that list\n" "\t-o \toutput the requested signature lists to \n" ); } void parse_db(const char *name, uint8_t *data, uint32_t len, int sig, int entry) { EFI_SIGNATURE_LIST *CertList = (EFI_SIGNATURE_LIST *)data; EFI_SIGNATURE_DATA *Cert; long count = 0, DataSize = len; int size; certlist_for_each_certentry(CertList, data, size, DataSize) { int Index = 0; const char *ext; if (sig != -1 && count != sig) continue; if (compare_guid(&CertList->SignatureType, &X509_GUID)== 0) { ext = "X509"; } else if (compare_guid(&CertList->SignatureType, &RSA2048_GUID) == 0) { ext = "RSA2048"; } else if (compare_guid(&CertList->SignatureType, &PKCS7_GUID) == 0) { ext = "PKCS7"; } else if (compare_guid(&CertList->SignatureType, &EFI_CERT_SHA256_GUID) == 0) { ext = "SHA256"; } else { ext = "Unknown"; } printf("%s: List %ld, type %s\n", name, count++, ext); certentry_for_each_cert(Cert, CertList) { if (entry != -1 && Index != entry) continue; printf(" Signature %d, size %d, owner %s\n", Index++, CertList->SignatureSize, guid_to_str(&Cert->SignatureOwner)); if (strcmp(ext, "X509") == 0) { const unsigned char *buf = (unsigned char *)Cert->SignatureData; X509 *X = d2i_X509(NULL, &buf, CertList->SignatureSize); X509_NAME *issuer = X509_get_issuer_name(X); X509_NAME *subject = X509_get_subject_name(X); printf(" Subject:\n"); X509_NAME_print_ex_fp(stdout, subject, 12, XN_FLAG_SEP_CPLUS_SPC); printf("\n Issuer:\n"); X509_NAME_print_ex_fp(stdout, issuer, 12, XN_FLAG_SEP_CPLUS_SPC); printf("\n"); } else if (strcmp(ext, "SHA256") == 0) { uint8_t *hash = Cert->SignatureData; int j; printf(" Hash:"); for (j = 0; j < SHA256_DIGEST_SIZE; j++) { printf("%02x", hash[j]); } printf("\n"); } } } } int main(int argc, char *argv[]) { char *variables[] = { "PK", "KEK", "db", "dbx" , "MokList" }; char *progname = argv[0], *var = NULL, *file = NULL; EFI_GUID *owners[] = { &GV_GUID, &GV_GUID, &SIG_DB, &SIG_DB, &MOK_OWNER }; int i, found = 0, sig = -1, entry = -1, fd; while (argc > 1 && argv[1][0] == '-') { if (strcmp("--version", argv[1]) == 0) { version(progname); exit(0); } else if (strcmp("--help", argv[1]) == 0) { help(progname); exit(0); } else if(strcmp(argv[1], "-v") == 0) { var = argv[2]; argv += 2; argc -= 2; } else if (strcmp(argv[1], "-s") == 0) { sscanf(argv[2], "%d-%d", &sig, &entry); argv += 2; argc -= 2; } else if (strcmp(argv[1], "-o") == 0) { file = argv[2]; argv += 2; argc -= 2; } else { /* unrecognised option */ break; } } if (argc != 1) { usage(progname); exit(1); } if (sig != -1 && !var) { fprintf(stderr, "need -v with -s option\n"); exit(1); } if (file) { fd = open(file, O_CREAT|O_TRUNC|O_WRONLY, 0600); if (fd < 0) { fprintf(stderr, "failed to open %s: ", file); perror(""); exit(1); } } kernel_variable_init(); for (i = 0; i < ARRAY_SIZE(owners); i++) { int status; uint32_t len; uint8_t *buf; if (var && strcmp(var, variables[i]) != 0) continue; found = 1; status = get_variable_alloc(variables[i], owners[i], NULL, &len, &buf); if (status == ENOENT) { printf("Variable %s has no entries\n", variables[i]); continue; } else if (status != 0) { printf("Failed to get %s: %d\n", variables[i], status); continue; } printf("Variable %s, length %d\n", variables[i], len); if (file) write(fd, buf, len); else parse_db(variables[i], buf, len, sig, entry); free(buf); } if (file) close(fd); if (!found) { fprintf(stderr, "variable %s is not a UEFI secure boot variable\n", var); exit(1); } return 0; } efitools-1.9.2/efi-updatevar.c000066400000000000000000000267031341522017100162530ustar00rootroot00000000000000/* * Copyright 2013 * * see COPYING file */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define __STDC_VERSION__ 199901L #include #include #include #include #include #include #include "efiauthenticated.h" #define ARRAY_SIZE(a) (sizeof (a) / sizeof ((a)[0])) static void usage(const char *progname) { printf("Usage: %s: [-a] [-e] [-d [-]] [-k ] [-g ] [-b |-f |-c file] \n", progname); } static void help(const char *progname) { usage(progname); printf("Manipulate the UEFI key database via the efivarfs filesystem\n\n" "Options:\n" "\t-a\tappend a value to the variable instead of replacing it\n" "\t-e\tuse EFI Signature List instead of signed update (only works in Setup Mode\n" "\t-b \tAdd hash of to the signature list\n" "\t-f \tAdd or Replace the key file (.esl or .auth) to the \n" "\t-c \tAdd or Replace the x509 certificate to the (with if provided)\n" "\t-g \tOptional for the X509 Certificate\n" "\t-k \tSecret key file for authorising User Mode updates\n" "\t-d [-]\tDelete the signature list (or just a single within the list)\n" "\t--engine \tUse engine for private key\n" ); } int main(int argc, char *argv[]) { char *variables[] = { "PK", "KEK", "db", "dbx" }; char *signedby[] = { "PK", "PK", "KEK", "KEK" }; char *engine = NULL; EFI_GUID *owners[] = { &GV_GUID, &GV_GUID, &SIG_DB, &SIG_DB }; EFI_GUID *owner, guid = MOK_OWNER; int i, esl_mode = 0, fd, ret, delsig = -1, delentry = -1; struct stat st; uint32_t attributes = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS; char *hash_mode = NULL, *file = NULL, *var, *progname = argv[0], *buf, *name, *crt_file = NULL, *key_file = NULL; while (argc > 1 && argv[1][0] == '-') { if (strcmp("--version", argv[1]) == 0) { version(progname); exit(0); } else if (strcmp("--help", argv[1]) == 0) { help(progname); exit(0); } else if(strcmp(argv[1], "-a") == 0) { attributes |= EFI_VARIABLE_APPEND_WRITE; argv += 1; argc -= 1; } if (strcmp(argv[1], "-e") == 0) { esl_mode = 1; argv += 1; argc -= 1; } else if (strcmp(argv[1], "-b") == 0) { hash_mode = argv[2]; argv += 2; argc -= 2; } else if (strcmp(argv[1], "-f") == 0) { file = argv[2]; argv += 2; argc -= 2; } else if (strcmp(argv[1], "-g") == 0) { if (str_to_guid(argv[2], &guid)) { fprintf(stderr, "Invalid GUID %s\n", argv[2]); exit(1); } argv += 2; argc -= 2; } else if (strcmp(argv[1], "-c") == 0) { crt_file = argv[2]; argv += 2; argc -= 2; } else if (strcmp(argv[1], "-k") == 0) { key_file = argv[2]; argv += 2; argc -= 2; } else if (strcmp(argv[1], "-d") == 0) { sscanf(argv[2], "%d-%d", &delsig, &delentry); argv += 2; argc -= 2; } else if (strcmp(argv[1], "--engine") == 0) { engine = argv[2]; argv += 2; argc -= 2; } else { /* unrecognised option */ break; } } if (argc != 2) { usage(progname); exit(1); } var = argv[1]; for(i = 0; i < ARRAY_SIZE(variables); i++) { if (strcmp(var, variables[i]) == 0) { owner = owners[i]; break; } } if (i == ARRAY_SIZE(variables)) { fprintf(stderr, "Invalid Variable %s\nVariable must be one of: ", var); for (i = 0; i < ARRAY_SIZE(variables); i++) fprintf(stderr, "%s ", variables[i]); fprintf(stderr, "\n"); exit(1); } if (delsig == -1 && (!!file + !!hash_mode + !!crt_file != 1)) { fprintf(stderr, "must specify exactly one of -f, -b or -c\n"); exit(1); } kernel_variable_init(); ERR_load_crypto_strings(); OpenSSL_add_all_digests(); OpenSSL_add_all_ciphers(); name = file ? file : hash_mode; if (delsig != -1) { uint32_t len; int status = get_variable_alloc(variables[i], owners[i], NULL, &len, (uint8_t **)&buf); if (status == ENOENT) { fprintf(stderr, "Variable %s has no entries\n", variables[i]); exit(1); } EFI_SIGNATURE_LIST *CertList = (EFI_SIGNATURE_LIST *)buf; EFI_SIGNATURE_DATA *Cert; int size, DataSize = len, count = 0; certlist_for_each_certentry(CertList, buf, size, DataSize) { int Index = 0; if (count++ != delsig) continue; if (delentry == -1) goto found; certentry_for_each_cert(Cert, CertList) { if (Index++ == delentry) goto found; } } if (delentry == -1) fprintf(stderr, "signature %d does not exist in %s\n", delsig, variables[i]); else fprintf(stderr, "signature %d-%d does not exist in %s\n", delsig, delentry, variables[i]); exit(1); found: ; int certs = (CertList->SignatureListSize - sizeof(EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize; if (certs == 1 || delentry == -1) { /* delete entire sig list + data */ DataSize -= CertList->SignatureListSize; if (DataSize > 0) memcpy(CertList, (void *) CertList + CertList->SignatureListSize, DataSize - ((char *) CertList - buf)); } else { int remain = DataSize - ((char *)Cert - buf) - CertList->SignatureSize; /* only delete single sig */ DataSize -= CertList->SignatureSize; CertList->SignatureListSize -= CertList->SignatureSize; if (remain > 0) memcpy(Cert, (void *)Cert + CertList->SignatureSize, remain); } st.st_size = DataSize; /* reduce length of buf */ esl_mode = 1; } else if (name) { fd = open(name, O_RDONLY); if (fd < 0) { fprintf(stderr, "Failed to read file %s: ", name); perror(""); exit(1); } if (fstat(fd, &st) < 0) { perror("stat failed"); exit(1); } buf = malloc(st.st_size); read(fd, buf, st.st_size); close(fd); } else { X509 *X = NULL; BIO *bio; char *crt_file_ext = &crt_file[strlen(crt_file) - 4]; esl_mode = 1; bio = BIO_new_file(crt_file, "r"); if (!bio) { fprintf(stderr, "Failed to load certificate from %s\n", crt_file); ERR_print_errors_fp(stderr); exit(1); } if (strcasecmp(crt_file_ext, ".der") == 0 || strcasecmp(crt_file_ext, ".cer") == 0) /* DER format */ X = d2i_X509_bio(bio, NULL); else /* else assume PEM */ X = PEM_read_bio_X509(bio, NULL, NULL, NULL); if (!X) { fprintf(stderr, "Failed to load certificate from %s\n", crt_file); ERR_print_errors_fp(stderr); exit(1); } BIO_free_all(bio); int cert_len = i2d_X509(X, NULL); cert_len += sizeof(EFI_SIGNATURE_LIST) + OFFSET_OF(EFI_SIGNATURE_DATA, SignatureData); EFI_SIGNATURE_LIST *esl = malloc(cert_len); unsigned char *tmp = (unsigned char *)esl + sizeof(EFI_SIGNATURE_LIST) + OFFSET_OF(EFI_SIGNATURE_DATA, SignatureData); i2d_X509(X, &tmp); esl->SignatureListSize = cert_len; esl->SignatureSize = (cert_len - sizeof(EFI_SIGNATURE_LIST)); esl->SignatureHeaderSize = 0; esl->SignatureType = EFI_CERT_X509_GUID; EFI_SIGNATURE_DATA *sig_data = (void *)esl + sizeof(EFI_SIGNATURE_LIST); sig_data->SignatureOwner = guid; buf = (char *)esl; st.st_size = cert_len; } if (hash_mode) { uint8_t hash[SHA256_DIGEST_SIZE]; EFI_STATUS status; int len; esl_mode = 1; attributes |= EFI_VARIABLE_APPEND_WRITE; status = sha256_get_pecoff_digest_mem(buf, st.st_size, hash); free(buf); if (status != EFI_SUCCESS) { fprintf(stderr, "Failed to get hash of %s\n", name); exit(1); } buf = (char *)hash_to_esl(&guid, &len, hash); st.st_size = len; } if (esl_mode && (!variable_is_setupmode() || strcmp(variables[i], "PK") == 0)) { if (!key_file) { fprintf(stderr, "Can't update variable%s without a key\n", variable_is_setupmode() ? "" : " in User Mode"); exit(1); } EVP_PKEY *pkey = read_private_key(engine, key_file); if (!pkey) { fprintf(stderr, "error reading private key %s\n", key_file); exit(1); } uint8_t *esl; uint32_t esl_len; int ret = get_variable_alloc(signedby[i], &GV_GUID, NULL, &esl_len, &esl); if (ret != 0) { fprintf(stderr, "Failed to get %s: ", signedby[i]); perror(""); exit(1); } EFI_SIGNATURE_LIST *CertList = (EFI_SIGNATURE_LIST *)esl; int DataSize = esl_len, size; X509 *X = NULL; certlist_for_each_certentry(CertList, esl, size, DataSize) { EFI_SIGNATURE_DATA *Cert; if (compare_guid(&CertList->SignatureType, &X509_GUID) != 0) continue; certentry_for_each_cert(Cert, CertList) { const unsigned char *psig = (unsigned char *)Cert->SignatureData; X = d2i_X509(NULL, &psig, CertList->SignatureSize); if (X509_check_private_key(X, pkey)) goto out; X = NULL; } } out: if (!X) { fprintf(stderr, "No public key matching %s in %s\n", key_file, signedby[i]); exit (1); } EFI_TIME timestamp; time_t t; unsigned char *tmp; int sigsize; struct tm *tm; memset(×tamp, 0, sizeof(timestamp)); time(&t); tm = gmtime(&t); /* FIXME: currently timestamp is one year into future because of * the way we set up the secure environment */ timestamp.Year = tm->tm_year + 1900 + 1; timestamp.Month = tm->tm_mon + 1; timestamp.Day = tm->tm_mday; timestamp.Hour = tm->tm_hour; timestamp.Minute = tm->tm_min; timestamp.Second = tm->tm_sec; /* signature is over variable name (no null and uc16 * chars), the vendor GUID, the attributes, the * timestamp and the contents */ int signbuflen = strlen(var)*2 + sizeof(EFI_GUID) + sizeof(attributes) + sizeof(timestamp) + st.st_size; char *signbuf = malloc(signbuflen); char *ptr = signbuf; int j; for (j = 0; j < strlen(var); j++) { *(ptr++) = var[j]; *(ptr++) = 0; } memcpy(ptr, owners[i], sizeof(*owners[i])); ptr += sizeof(*owners[i]); memcpy(ptr, &attributes, sizeof(attributes)); ptr += sizeof(attributes); memcpy(ptr, ×tamp, sizeof(timestamp)); ptr += sizeof(timestamp); memcpy(ptr, buf, st.st_size); sign_efi_var_ssl(signbuf, signbuflen, pkey, X, &tmp, &sigsize); EFI_VARIABLE_AUTHENTICATION_2 *var_auth = malloc(sizeof(EFI_VARIABLE_AUTHENTICATION_2) + sigsize); var_auth->TimeStamp = timestamp; var_auth->AuthInfo.CertType = EFI_CERT_TYPE_PKCS7_GUID; var_auth->AuthInfo.Hdr.dwLength = sigsize + OFFSET_OF(WIN_CERTIFICATE_UEFI_GUID, CertData); var_auth->AuthInfo.Hdr.wRevision = 0x0200; var_auth->AuthInfo.Hdr.wCertificateType = WIN_CERT_TYPE_EFI_GUID; memcpy(var_auth->AuthInfo.CertData, tmp, sigsize); ERR_print_errors_fp(stderr); /* new update now consists of two parts: the * authentication header with the signature and the * payload (the original esl) */ int siglen = OFFSET_OF(EFI_VARIABLE_AUTHENTICATION_2, AuthInfo.CertData) + sigsize; char *newbuf = malloc(siglen + st.st_size); memcpy(newbuf, var_auth, siglen); memcpy(newbuf + siglen, buf, st.st_size); free(buf); free(esl); free(var_auth); buf = newbuf; st.st_size = siglen + st.st_size; esl_mode = 0; } if (esl_mode) { ret = set_variable_esl(var, owner, attributes, st.st_size, buf); } else { ret = set_variable(var, owner, attributes, st.st_size, buf); } if (ret == EACCES) { fprintf(stderr, "Cannot write to %s, wrong filesystem permissions\n", var); exit(1); } else if (ret != 0) { fprintf(stderr, "Failed to update %s: ", var); perror(""); exit(1); } return 0; } efitools-1.9.2/flash-var.c000066400000000000000000000123531341522017100153760ustar00rootroot00000000000000#include #include #include #include #include #include #include #include #include #include #include #define __STDC_VERSION__ 199901L #include #include #include #include "efiauthenticated.h" #include "variableformat.h" static void usage(const char *progname) { printf("Usage: %s: [-l] [-g ] [-t ] \n", progname); } static void help(const char *progname) { usage(progname); printf("Poke a variable definition into a flash file\n\n" "Options:\n" "\t-g Variable owner GUID\n" "\t-t Timestamp for the authenticated variable\n" "\t-l List current flash variables\n" ); } int main(int argc, char *argv[]) { char *progname = argv[0], *buf, *vardata, *timestampstr = NULL; uint32_t attributes = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS; int flashfile, varfile, i, offset, varlen, varfilesize, listvars = 0; const int chunk = 8; wchar_t var[128]; struct stat st; EFI_GUID *owner = NULL, guid; EFI_TIME timestamp; while (argc > 1 && argv[1][0] == '-') { if (strcmp("--version", argv[1]) == 0) { version(progname); exit(0); } else if (strcmp("--help", argv[1]) == 0) { help(progname); exit(0); } else if (strcmp(argv[1], "-g") == 0) { if (str_to_guid(argv[2], &guid)) { fprintf(stderr, "Invalid GUID %s\n", argv[2]); exit(1); } owner = &guid; argv += 2; argc -= 2; } else if (strcmp("-t", argv[1]) == 0) { timestampstr = argv[2]; argv += 2; argc -= 2; } else if (strcmp("-l", argv[1]) == 0) { listvars = 1; argv += 1; argc -= 1; } else { /* unrecognised option */ break; } } if ((argc != 4 && !listvars) || (argc != 2 && listvars)) { usage(progname); exit(1); } /* copy to wchar16_t including trailing zero */ for (i = 0; i < strlen(argv[2]) + 1; i++) var[i] = argv[2][i]; varlen = i*2; /* size of storage including zero */ if (!owner) owner = get_owner_guid(argv[2]); if (!owner) { fprintf(stderr, "variable %s has no defined guid, one must be specified\n", argv[2]); exit(1); } memset(×tamp, 0, sizeof(timestamp)); time_t t; struct tm *tm, tms; memset(&tms, 0, sizeof(tms)); if (timestampstr) { strptime(timestampstr, "%Y-%m-%d %H:%M:%S", &tms); tm = &tms; } else { time(&t); tm = localtime(&t); } /* timestamp.Year is from 0 not 1900 as tm year is */ timestamp.Year = tm->tm_year + 1900; /* timestamp Month is 1-12 not 0-11 as tm_mon is */ timestamp.Month = tm->tm_mon + 1; timestamp.Day = tm->tm_mday; timestamp.Hour = tm->tm_hour; timestamp.Minute = tm->tm_min; timestamp.Second = tm->tm_sec; printf("Timestamp is %d-%d-%d %02d:%02d:%02d\n", timestamp.Year, timestamp.Month, timestamp.Day, timestamp.Hour, timestamp.Minute, timestamp.Second); flashfile = open(argv[1], O_RDWR); if (flashfile < 0) { fprintf(stderr, "Failed to read file %s:", argv[1]); perror(""); } varfile = open(argv[3], O_RDONLY); if (varfile < 0) { fprintf(stderr, "Failed to read file %s:", argv[1]); perror(""); } fstat(varfile, &st); varfilesize = st.st_size; vardata = malloc(varfilesize); if (read(varfile, vardata, varfilesize) != varfilesize) { perror("Failed to read variable file"); exit(1); } close(varfile); buf = malloc(sizeof(EFI_GUID)); for (i = 0; ; i += chunk) { lseek(flashfile, i, SEEK_SET); if (read(flashfile, buf, sizeof(EFI_GUID)) != sizeof(EFI_GUID)) goto eof; if (memcmp(buf, &SECURE_VARIABLE_GUID, sizeof(EFI_GUID)) == 0) break; } offset = i; printf("Variable header found at offset 0x%x\n", offset); lseek(flashfile, offset, SEEK_SET); free(buf); buf = malloc(sizeof(VARIABLE_STORE_HEADER)); read(flashfile, buf, sizeof(VARIABLE_STORE_HEADER)); VARIABLE_STORE_HEADER *vsh = (VARIABLE_STORE_HEADER *)buf; if (vsh->Format != VARIABLE_STORE_FORMATTED && vsh->State != VARIABLE_STORE_HEALTHY) { fprintf(stderr, "Variable store header is corrupt\n"); exit(1); } UINT32 size = vsh->Size; free(buf); buf = malloc(size); lseek(flashfile, offset, SEEK_SET); read(flashfile, buf, size); vsh = (VARIABLE_STORE_HEADER *)buf; printf("Variable Store Size = 0x%x\n", vsh->Size); VARIABLE_HEADER *vh = (void *)HEADER_ALIGN(vsh + 1); printf("variables begin at 0x%x\n", (int)((char *)vh - (char *)vsh)); for (i = 0; IsValidVariableHeader(vh); i++) { vh = (void *)HEADER_ALIGN((char *)(vh + 1) + vh->NameSize + vh->DataSize); } printf("Found %d variables, now at offset %ld\n", i, (long)((char *)vh - (char *)vsh)); memset(vh, 0, sizeof(*vh)); vh->StartId = VARIABLE_DATA; vh->State = VAR_ADDED; vh->Attributes = attributes; vh->NameSize = varlen; vh->DataSize = varfilesize; vh->TimeStamp = timestamp; vh->VendorGuid = *owner; buf = (void *)(vh + 1); memcpy (buf, var, varlen); buf += varlen; memcpy (buf, vardata, varfilesize); lseek(flashfile, offset, SEEK_SET); write(flashfile, vsh, vsh->Size); close(flashfile); exit(0); eof: printf("No variables found in file at offset 0x%x\n", i); exit(2); } efitools-1.9.2/hash-to-efi-sig-list.c000066400000000000000000000056421341522017100173530ustar00rootroot00000000000000/* * Copyright 2012 * * see COPYING file */ #include #define __STDC_VERSION__ 199901L #include #ifdef CONFIG_arm /* FIXME: * arm efi leaves a visibilit pragma pushed that won't work for * non efi programs, so eliminate it */ #pragma GCC visibility pop #endif #include #include #include #include #include #include #include #include #include #include /* for ALIGN_VALUE */ #include #include #include #include static void usage(const char *progname) { printf("Usage: %s efi-binary [efi-binary ...] efi-signature-list\n", progname); } static void help(const char *progname) { usage(progname); printf("Produce an EFI Signature List file containing the sha256 hash of the\n" "passed in EFI binary\n" "\nOptions:\n" "none\n" ); } int main(int argc, char *argv[]) { void *efifile; const char *progname = argv[0]; int i; while (argc > 1) { if (strcmp("--version", argv[1]) == 0) { version(progname); exit(0); } else if (strcmp("--help", argv[1]) == 0) { help(progname); exit(0); } else { break; } } if (argc < 3) { usage(progname); exit(1); } int hashes = argc - 2; UINT8 hash[hashes][SHA256_DIGEST_SIZE]; memset(hash, 0, sizeof(hash)); for (i = 0; i < hashes; i++) { int j; struct stat st; EFI_STATUS status; int fdefifile = open(argv[i + 1], O_RDONLY); if (fdefifile == -1) { fprintf(stderr, "failed to open file %s: ", argv[1]); perror(""); exit(1); } fstat(fdefifile, &st); efifile = malloc(ALIGN_VALUE(st.st_size, 4096)); memset(efifile, 0, ALIGN_VALUE(st.st_size, 4096)); read(fdefifile, efifile, st.st_size); close(fdefifile); status = sha256_get_pecoff_digest_mem(efifile, st.st_size, hash[i]); if (status != EFI_SUCCESS) { printf("Failed to get hash of %s: %d\n", argv[i+1], status); continue; } printf("HASH IS "); for (j = 0; j < SHA256_DIGEST_SIZE; j++) { printf("%02x", hash[i][j]); } printf("\n"); } UINT8 sig[sizeof(EFI_SIGNATURE_LIST) + (sizeof(EFI_SIGNATURE_DATA) - 1 + SHA256_DIGEST_SIZE) * hashes]; EFI_SIGNATURE_LIST *l = (void *)sig; memset(sig, 0, sizeof(sig)); l->SignatureType = EFI_CERT_SHA256_GUID; l->SignatureListSize = sizeof(sig); l->SignatureSize = 16 +32; /* UEFI defined */ for (i = 0; i < hashes; i++) { EFI_SIGNATURE_DATA *d = (void *)sig + sizeof(EFI_SIGNATURE_LIST) + l->SignatureSize * i; d->SignatureOwner = MOK_OWNER; memcpy(&d->SignatureData, hash[i], sizeof(hash[i])); } int fdoutfile = open(argv[hashes + 1], O_CREAT|O_WRONLY|O_TRUNC, S_IWUSR|S_IRUSR); if (fdoutfile == -1) { fprintf(stderr, "failed to open %s: ", argv[hashes + 1]); perror(""); exit(1); } write(fdoutfile, sig, sizeof(sig)); close(fdoutfile); return 0; } efitools-1.9.2/include/000077500000000000000000000000001341522017100147665ustar00rootroot00000000000000efitools-1.9.2/include/PeImage.h000066400000000000000000000654341341522017100164620ustar00rootroot00000000000000/** @file EFI image format for PE32, PE32+ and TE. Please note some data structures are different for PE32 and PE32+. EFI_IMAGE_NT_HEADERS32 is for PE32 and EFI_IMAGE_NT_HEADERS64 is for PE32+. This file is coded to the Visual Studio, Microsoft Portable Executable and Common Object File Format Specification, Revision 8.0 - May 16, 2006. This file also includes some definitions in PI Specification, Revision 1.0. Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License which accompanies this distribution. The full text of the license may be found at http://opensource.org/licenses/bsd-license.php. THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. **/ #ifndef __PE_IMAGE_H__ #define __PE_IMAGE_H__ #include #define SIGNATURE_16(A, B) ((A) | (B << 8)) #define SIGNATURE_32(A, B, C, D) (SIGNATURE_16 (A, B) | (SIGNATURE_16 (C, D) << 16)) #define SIGNATURE_64(A, B, C, D, E, F, G, H) \ (SIGNATURE_32 (A, B, C, D) | ((UINT64) (SIGNATURE_32 (E, F, G, H)) << 32)) #define ALIGN_VALUE(Value, Alignment) ((Value) + (((Alignment) - (Value)) & ((Alignment) - 1))) #define ALIGN_POINTER(Pointer, Alignment) ((VOID *) (ALIGN_VALUE ((UINTN)(Pointer), (Alignment)))) // // PE32+ Subsystem type for EFI images // #define EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION 10 #define EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER 11 #define EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER 12 #define EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER 13 ///< defined PI Specification, 1.0 // // PE32+ Machine type for EFI images // #define IMAGE_FILE_MACHINE_I386 0x014c #define IMAGE_FILE_MACHINE_IA64 0x0200 #define IMAGE_FILE_MACHINE_EBC 0x0EBC #define IMAGE_FILE_MACHINE_X64 0x8664 #define IMAGE_FILE_MACHINE_ARMTHUMB_MIXED 0x01c2 // // EXE file formats // #define EFI_IMAGE_DOS_SIGNATURE SIGNATURE_16('M', 'Z') #define EFI_IMAGE_OS2_SIGNATURE SIGNATURE_16('N', 'E') #define EFI_IMAGE_OS2_SIGNATURE_LE SIGNATURE_16('L', 'E') #define EFI_IMAGE_NT_SIGNATURE SIGNATURE_32('P', 'E', '\0', '\0') /// /// PE images can start with an optional DOS header, so if an image is run /// under DOS it can print an error message. /// typedef struct { UINT16 e_magic; ///< Magic number. UINT16 e_cblp; ///< Bytes on last page of file. UINT16 e_cp; ///< Pages in file. UINT16 e_crlc; ///< Relocations. UINT16 e_cparhdr; ///< Size of header in paragraphs. UINT16 e_minalloc; ///< Minimum extra paragraphs needed. UINT16 e_maxalloc; ///< Maximum extra paragraphs needed. UINT16 e_ss; ///< Initial (relative) SS value. UINT16 e_sp; ///< Initial SP value. UINT16 e_csum; ///< Checksum. UINT16 e_ip; ///< Initial IP value. UINT16 e_cs; ///< Initial (relative) CS value. UINT16 e_lfarlc; ///< File address of relocation table. UINT16 e_ovno; ///< Overlay number. UINT16 e_res[4]; ///< Reserved words. UINT16 e_oemid; ///< OEM identifier (for e_oeminfo). UINT16 e_oeminfo; ///< OEM information; e_oemid specific. UINT16 e_res2[10]; ///< Reserved words. UINT32 e_lfanew; ///< File address of new exe header. } EFI_IMAGE_DOS_HEADER; /// /// COFF File Header (Object and Image). /// typedef struct { UINT16 Machine; UINT16 NumberOfSections; UINT32 TimeDateStamp; UINT32 PointerToSymbolTable; UINT32 NumberOfSymbols; UINT16 SizeOfOptionalHeader; UINT16 Characteristics; } EFI_IMAGE_FILE_HEADER; /// /// Size of EFI_IMAGE_FILE_HEADER. /// #define EFI_IMAGE_SIZEOF_FILE_HEADER 20 // // Characteristics // #define EFI_IMAGE_FILE_RELOCS_STRIPPED (1 << 0) ///< 0x0001 Relocation info stripped from file. #define EFI_IMAGE_FILE_EXECUTABLE_IMAGE (1 << 1) ///< 0x0002 File is executable (i.e. no unresolved externel references). #define EFI_IMAGE_FILE_LINE_NUMS_STRIPPED (1 << 2) ///< 0x0004 Line nunbers stripped from file. #define EFI_IMAGE_FILE_LOCAL_SYMS_STRIPPED (1 << 3) ///< 0x0008 Local symbols stripped from file. #define EFI_IMAGE_FILE_BYTES_REVERSED_LO (1 << 7) ///< 0x0080 Bytes of machine word are reversed. #define EFI_IMAGE_FILE_32BIT_MACHINE (1 << 8) ///< 0x0100 32 bit word machine. #define EFI_IMAGE_FILE_DEBUG_STRIPPED (1 << 9) ///< 0x0200 Debugging info stripped from file in .DBG file. #define EFI_IMAGE_FILE_SYSTEM (1 << 12) ///< 0x1000 System File. #define EFI_IMAGE_FILE_DLL (1 << 13) ///< 0x2000 File is a DLL. #define EFI_IMAGE_FILE_BYTES_REVERSED_HI (1 << 15) ///< 0x8000 Bytes of machine word are reversed. /// /// Header Data Directories. /// typedef struct { UINT32 VirtualAddress; UINT32 Size; } EFI_IMAGE_DATA_DIRECTORY; // // Directory Entries // #define EFI_IMAGE_DIRECTORY_ENTRY_EXPORT 0 #define EFI_IMAGE_DIRECTORY_ENTRY_IMPORT 1 #define EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE 2 #define EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION 3 #define EFI_IMAGE_DIRECTORY_ENTRY_SECURITY 4 #define EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC 5 #define EFI_IMAGE_DIRECTORY_ENTRY_DEBUG 6 #define EFI_IMAGE_DIRECTORY_ENTRY_COPYRIGHT 7 #define EFI_IMAGE_DIRECTORY_ENTRY_GLOBALPTR 8 #define EFI_IMAGE_DIRECTORY_ENTRY_TLS 9 #define EFI_IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG 10 #define EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES 16 /// /// @attention /// EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC means PE32 and /// EFI_IMAGE_OPTIONAL_HEADER32 must be used. The data structures only vary /// after NT additional fields. /// #define EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC 0x10b /// /// Optional Header Standard Fields for PE32. /// typedef struct { /// /// Standard fields. /// UINT16 Magic; UINT8 MajorLinkerVersion; UINT8 MinorLinkerVersion; UINT32 SizeOfCode; UINT32 SizeOfInitializedData; UINT32 SizeOfUninitializedData; UINT32 AddressOfEntryPoint; UINT32 BaseOfCode; UINT32 BaseOfData; ///< PE32 contains this additional field, which is absent in PE32+. /// /// Optional Header Windows-Specific Fields. /// UINT32 ImageBase; UINT32 SectionAlignment; UINT32 FileAlignment; UINT16 MajorOperatingSystemVersion; UINT16 MinorOperatingSystemVersion; UINT16 MajorImageVersion; UINT16 MinorImageVersion; UINT16 MajorSubsystemVersion; UINT16 MinorSubsystemVersion; UINT32 Win32VersionValue; UINT32 SizeOfImage; UINT32 SizeOfHeaders; UINT32 CheckSum; UINT16 Subsystem; UINT16 DllCharacteristics; UINT32 SizeOfStackReserve; UINT32 SizeOfStackCommit; UINT32 SizeOfHeapReserve; UINT32 SizeOfHeapCommit; UINT32 LoaderFlags; UINT32 NumberOfRvaAndSizes; EFI_IMAGE_DATA_DIRECTORY DataDirectory[EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES]; } EFI_IMAGE_OPTIONAL_HEADER32; /// /// @attention /// EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC means PE32+ and /// EFI_IMAGE_OPTIONAL_HEADER64 must be used. The data structures only vary /// after NT additional fields. /// #define EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC 0x20b /// /// Optional Header Standard Fields for PE32+. /// typedef struct { /// /// Standard fields. /// UINT16 Magic; UINT8 MajorLinkerVersion; UINT8 MinorLinkerVersion; UINT32 SizeOfCode; UINT32 SizeOfInitializedData; UINT32 SizeOfUninitializedData; UINT32 AddressOfEntryPoint; UINT32 BaseOfCode; /// /// Optional Header Windows-Specific Fields. /// UINT64 ImageBase; UINT32 SectionAlignment; UINT32 FileAlignment; UINT16 MajorOperatingSystemVersion; UINT16 MinorOperatingSystemVersion; UINT16 MajorImageVersion; UINT16 MinorImageVersion; UINT16 MajorSubsystemVersion; UINT16 MinorSubsystemVersion; UINT32 Win32VersionValue; UINT32 SizeOfImage; UINT32 SizeOfHeaders; UINT32 CheckSum; UINT16 Subsystem; UINT16 DllCharacteristics; UINT64 SizeOfStackReserve; UINT64 SizeOfStackCommit; UINT64 SizeOfHeapReserve; UINT64 SizeOfHeapCommit; UINT32 LoaderFlags; UINT32 NumberOfRvaAndSizes; EFI_IMAGE_DATA_DIRECTORY DataDirectory[EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES]; } EFI_IMAGE_OPTIONAL_HEADER64; /// /// @attention /// EFI_IMAGE_NT_HEADERS32 is for use ONLY by tools. /// typedef struct { UINT32 Signature; EFI_IMAGE_FILE_HEADER FileHeader; EFI_IMAGE_OPTIONAL_HEADER32 OptionalHeader; } EFI_IMAGE_NT_HEADERS32; #define EFI_IMAGE_SIZEOF_NT_OPTIONAL32_HEADER sizeof (EFI_IMAGE_NT_HEADERS32) /// /// @attention /// EFI_IMAGE_HEADERS64 is for use ONLY by tools. /// typedef struct { UINT32 Signature; EFI_IMAGE_FILE_HEADER FileHeader; EFI_IMAGE_OPTIONAL_HEADER64 OptionalHeader; } EFI_IMAGE_NT_HEADERS64; #define EFI_IMAGE_SIZEOF_NT_OPTIONAL64_HEADER sizeof (EFI_IMAGE_NT_HEADERS64) // // Other Windows Subsystem Values // #define EFI_IMAGE_SUBSYSTEM_UNKNOWN 0 #define EFI_IMAGE_SUBSYSTEM_NATIVE 1 #define EFI_IMAGE_SUBSYSTEM_WINDOWS_GUI 2 #define EFI_IMAGE_SUBSYSTEM_WINDOWS_CUI 3 #define EFI_IMAGE_SUBSYSTEM_OS2_CUI 5 #define EFI_IMAGE_SUBSYSTEM_POSIX_CUI 7 /// /// Length of ShortName. /// #define EFI_IMAGE_SIZEOF_SHORT_NAME 8 /// /// Section Table. This table immediately follows the optional header. /// typedef struct { UINT8 Name[EFI_IMAGE_SIZEOF_SHORT_NAME]; union { UINT32 PhysicalAddress; UINT32 VirtualSize; } Misc; UINT32 VirtualAddress; UINT32 SizeOfRawData; UINT32 PointerToRawData; UINT32 PointerToRelocations; UINT32 PointerToLinenumbers; UINT16 NumberOfRelocations; UINT16 NumberOfLinenumbers; UINT32 Characteristics; } EFI_IMAGE_SECTION_HEADER; /// /// Size of EFI_IMAGE_SECTION_HEADER. /// #define EFI_IMAGE_SIZEOF_SECTION_HEADER 40 // // Section Flags Values // #define EFI_IMAGE_SCN_TYPE_NO_PAD BIT3 ///< 0x00000008 ///< Reserved. #define EFI_IMAGE_SCN_CNT_CODE BIT5 ///< 0x00000020 #define EFI_IMAGE_SCN_CNT_INITIALIZED_DATA BIT6 ///< 0x00000040 #define EFI_IMAGE_SCN_CNT_UNINITIALIZED_DATA BIT7 ///< 0x00000080 #define EFI_IMAGE_SCN_LNK_OTHER BIT8 ///< 0x00000100 ///< Reserved. #define EFI_IMAGE_SCN_LNK_INFO BIT9 ///< 0x00000200 ///< Section contains comments or some other type of information. #define EFI_IMAGE_SCN_LNK_REMOVE BIT11 ///< 0x00000800 ///< Section contents will not become part of image. #define EFI_IMAGE_SCN_LNK_COMDAT BIT12 ///< 0x00001000 #define EFI_IMAGE_SCN_ALIGN_1BYTES BIT20 ///< 0x00100000 #define EFI_IMAGE_SCN_ALIGN_2BYTES BIT21 ///< 0x00200000 #define EFI_IMAGE_SCN_ALIGN_4BYTES (BIT20|BIT21) ///< 0x00300000 #define EFI_IMAGE_SCN_ALIGN_8BYTES BIT22 ///< 0x00400000 #define EFI_IMAGE_SCN_ALIGN_16BYTES (BIT20|BIT22) ///< 0x00500000 #define EFI_IMAGE_SCN_ALIGN_32BYTES (BIT21|BIT22) ///< 0x00600000 #define EFI_IMAGE_SCN_ALIGN_64BYTES (BIT20|BIT21|BIT22) ///< 0x00700000 #define EFI_IMAGE_SCN_MEM_DISCARDABLE BIT25 ///< 0x02000000 #define EFI_IMAGE_SCN_MEM_NOT_CACHED BIT26 ///< 0x04000000 #define EFI_IMAGE_SCN_MEM_NOT_PAGED BIT27 ///< 0x08000000 #define EFI_IMAGE_SCN_MEM_SHARED BIT28 ///< 0x10000000 #define EFI_IMAGE_SCN_MEM_EXECUTE BIT29 ///< 0x20000000 #define EFI_IMAGE_SCN_MEM_READ BIT30 ///< 0x40000000 #define EFI_IMAGE_SCN_MEM_WRITE BIT31 ///< 0x80000000 /// /// Size of a Symbol Table Record. /// #define EFI_IMAGE_SIZEOF_SYMBOL 18 // // Symbols have a section number of the section in which they are // defined. Otherwise, section numbers have the following meanings: // #define EFI_IMAGE_SYM_UNDEFINED (UINT16) 0 ///< Symbol is undefined or is common. #define EFI_IMAGE_SYM_ABSOLUTE (UINT16) -1 ///< Symbol is an absolute value. #define EFI_IMAGE_SYM_DEBUG (UINT16) -2 ///< Symbol is a special debug item. // // Symbol Type (fundamental) values. // #define EFI_IMAGE_SYM_TYPE_NULL 0 ///< no type. #define EFI_IMAGE_SYM_TYPE_VOID 1 ///< no valid type. #define EFI_IMAGE_SYM_TYPE_CHAR 2 ///< type character. #define EFI_IMAGE_SYM_TYPE_SHORT 3 ///< type short integer. #define EFI_IMAGE_SYM_TYPE_INT 4 #define EFI_IMAGE_SYM_TYPE_LONG 5 #define EFI_IMAGE_SYM_TYPE_FLOAT 6 #define EFI_IMAGE_SYM_TYPE_DOUBLE 7 #define EFI_IMAGE_SYM_TYPE_STRUCT 8 #define EFI_IMAGE_SYM_TYPE_UNION 9 #define EFI_IMAGE_SYM_TYPE_ENUM 10 ///< enumeration. #define EFI_IMAGE_SYM_TYPE_MOE 11 ///< member of enumeration. #define EFI_IMAGE_SYM_TYPE_BYTE 12 #define EFI_IMAGE_SYM_TYPE_WORD 13 #define EFI_IMAGE_SYM_TYPE_UINT 14 #define EFI_IMAGE_SYM_TYPE_DWORD 15 // // Symbol Type (derived) values. // #define EFI_IMAGE_SYM_DTYPE_NULL 0 ///< no derived type. #define EFI_IMAGE_SYM_DTYPE_POINTER 1 #define EFI_IMAGE_SYM_DTYPE_FUNCTION 2 #define EFI_IMAGE_SYM_DTYPE_ARRAY 3 // // Storage classes. // #define EFI_IMAGE_SYM_CLASS_END_OF_FUNCTION ((UINT8) -1) #define EFI_IMAGE_SYM_CLASS_NULL 0 #define EFI_IMAGE_SYM_CLASS_AUTOMATIC 1 #define EFI_IMAGE_SYM_CLASS_EXTERNAL 2 #define EFI_IMAGE_SYM_CLASS_STATIC 3 #define EFI_IMAGE_SYM_CLASS_REGISTER 4 #define EFI_IMAGE_SYM_CLASS_EXTERNAL_DEF 5 #define EFI_IMAGE_SYM_CLASS_LABEL 6 #define EFI_IMAGE_SYM_CLASS_UNDEFINED_LABEL 7 #define EFI_IMAGE_SYM_CLASS_MEMBER_OF_STRUCT 8 #define EFI_IMAGE_SYM_CLASS_ARGUMENT 9 #define EFI_IMAGE_SYM_CLASS_STRUCT_TAG 10 #define EFI_IMAGE_SYM_CLASS_MEMBER_OF_UNION 11 #define EFI_IMAGE_SYM_CLASS_UNION_TAG 12 #define EFI_IMAGE_SYM_CLASS_TYPE_DEFINITION 13 #define EFI_IMAGE_SYM_CLASS_UNDEFINED_STATIC 14 #define EFI_IMAGE_SYM_CLASS_ENUM_TAG 15 #define EFI_IMAGE_SYM_CLASS_MEMBER_OF_ENUM 16 #define EFI_IMAGE_SYM_CLASS_REGISTER_PARAM 17 #define EFI_IMAGE_SYM_CLASS_BIT_FIELD 18 #define EFI_IMAGE_SYM_CLASS_BLOCK 100 #define EFI_IMAGE_SYM_CLASS_FUNCTION 101 #define EFI_IMAGE_SYM_CLASS_END_OF_STRUCT 102 #define EFI_IMAGE_SYM_CLASS_FILE 103 #define EFI_IMAGE_SYM_CLASS_SECTION 104 #define EFI_IMAGE_SYM_CLASS_WEAK_EXTERNAL 105 // // type packing constants // #define EFI_IMAGE_N_BTMASK 017 #define EFI_IMAGE_N_TMASK 060 #define EFI_IMAGE_N_TMASK1 0300 #define EFI_IMAGE_N_TMASK2 0360 #define EFI_IMAGE_N_BTSHFT 4 #define EFI_IMAGE_N_TSHIFT 2 // // Communal selection types. // #define EFI_IMAGE_COMDAT_SELECT_NODUPLICATES 1 #define EFI_IMAGE_COMDAT_SELECT_ANY 2 #define EFI_IMAGE_COMDAT_SELECT_SAME_SIZE 3 #define EFI_IMAGE_COMDAT_SELECT_EXACT_MATCH 4 #define EFI_IMAGE_COMDAT_SELECT_ASSOCIATIVE 5 // // the following values only be referred in PeCoff, not defined in PECOFF. // #define EFI_IMAGE_WEAK_EXTERN_SEARCH_NOLIBRARY 1 #define EFI_IMAGE_WEAK_EXTERN_SEARCH_LIBRARY 2 #define EFI_IMAGE_WEAK_EXTERN_SEARCH_ALIAS 3 /// /// Relocation format. /// typedef struct { UINT32 VirtualAddress; UINT32 SymbolTableIndex; UINT16 Type; } EFI_IMAGE_RELOCATION; /// /// Size of EFI_IMAGE_RELOCATION /// #define EFI_IMAGE_SIZEOF_RELOCATION 10 // // I386 relocation types. // #define EFI_IMAGE_REL_I386_ABSOLUTE 0x0000 ///< Reference is absolute, no relocation is necessary. #define EFI_IMAGE_REL_I386_DIR16 0x0001 ///< Direct 16-bit reference to the symbols virtual address. #define EFI_IMAGE_REL_I386_REL16 0x0002 ///< PC-relative 16-bit reference to the symbols virtual address. #define EFI_IMAGE_REL_I386_DIR32 0x0006 ///< Direct 32-bit reference to the symbols virtual address. #define EFI_IMAGE_REL_I386_DIR32NB 0x0007 ///< Direct 32-bit reference to the symbols virtual address, base not included. #define EFI_IMAGE_REL_I386_SEG12 0x0009 ///< Direct 16-bit reference to the segment-selector bits of a 32-bit virtual address. #define EFI_IMAGE_REL_I386_SECTION 0x000A #define EFI_IMAGE_REL_I386_SECREL 0x000B #define EFI_IMAGE_REL_I386_REL32 0x0014 ///< PC-relative 32-bit reference to the symbols virtual address. // // x64 processor relocation types. // #define IMAGE_REL_AMD64_ABSOLUTE 0x0000 #define IMAGE_REL_AMD64_ADDR64 0x0001 #define IMAGE_REL_AMD64_ADDR32 0x0002 #define IMAGE_REL_AMD64_ADDR32NB 0x0003 #define IMAGE_REL_AMD64_REL32 0x0004 #define IMAGE_REL_AMD64_REL32_1 0x0005 #define IMAGE_REL_AMD64_REL32_2 0x0006 #define IMAGE_REL_AMD64_REL32_3 0x0007 #define IMAGE_REL_AMD64_REL32_4 0x0008 #define IMAGE_REL_AMD64_REL32_5 0x0009 #define IMAGE_REL_AMD64_SECTION 0x000A #define IMAGE_REL_AMD64_SECREL 0x000B #define IMAGE_REL_AMD64_SECREL7 0x000C #define IMAGE_REL_AMD64_TOKEN 0x000D #define IMAGE_REL_AMD64_SREL32 0x000E #define IMAGE_REL_AMD64_PAIR 0x000F #define IMAGE_REL_AMD64_SSPAN32 0x0010 /// /// Based relocation format. /// typedef struct { UINT32 VirtualAddress; UINT32 SizeOfBlock; } EFI_IMAGE_BASE_RELOCATION; /// /// Size of EFI_IMAGE_BASE_RELOCATION. /// #define EFI_IMAGE_SIZEOF_BASE_RELOCATION 8 // // Based relocation types. // #define EFI_IMAGE_REL_BASED_ABSOLUTE 0 #define EFI_IMAGE_REL_BASED_HIGH 1 #define EFI_IMAGE_REL_BASED_LOW 2 #define EFI_IMAGE_REL_BASED_HIGHLOW 3 #define EFI_IMAGE_REL_BASED_HIGHADJ 4 #define EFI_IMAGE_REL_BASED_MIPS_JMPADDR 5 #define EFI_IMAGE_REL_BASED_ARM_MOV32A 5 #define EFI_IMAGE_REL_BASED_ARM_MOV32T 7 #define EFI_IMAGE_REL_BASED_IA64_IMM64 9 #define EFI_IMAGE_REL_BASED_MIPS_JMPADDR16 9 #define EFI_IMAGE_REL_BASED_DIR64 10 /// /// Line number format. /// typedef struct { union { UINT32 SymbolTableIndex; ///< Symbol table index of function name if Linenumber is 0. UINT32 VirtualAddress; ///< Virtual address of line number. } Type; UINT16 Linenumber; ///< Line number. } EFI_IMAGE_LINENUMBER; /// /// Size of EFI_IMAGE_LINENUMBER. /// #define EFI_IMAGE_SIZEOF_LINENUMBER 6 // // Archive format. // #define EFI_IMAGE_ARCHIVE_START_SIZE 8 #define EFI_IMAGE_ARCHIVE_START "!\n" #define EFI_IMAGE_ARCHIVE_END "`\n" #define EFI_IMAGE_ARCHIVE_PAD "\n" #define EFI_IMAGE_ARCHIVE_LINKER_MEMBER "/ " #define EFI_IMAGE_ARCHIVE_LONGNAMES_MEMBER "// " /// /// Archive Member Headers /// typedef struct { UINT8 Name[16]; ///< File member name - `/' terminated. UINT8 Date[12]; ///< File member date - decimal. UINT8 UserID[6]; ///< File member user id - decimal. UINT8 GroupID[6]; ///< File member group id - decimal. UINT8 Mode[8]; ///< File member mode - octal. UINT8 Size[10]; ///< File member size - decimal. UINT8 EndHeader[2]; ///< String to end header. (0x60 0x0A). } EFI_IMAGE_ARCHIVE_MEMBER_HEADER; /// /// Size of EFI_IMAGE_ARCHIVE_MEMBER_HEADER. /// #define EFI_IMAGE_SIZEOF_ARCHIVE_MEMBER_HDR 60 // // DLL Support // /// /// Export Directory Table. /// typedef struct { UINT32 Characteristics; UINT32 TimeDateStamp; UINT16 MajorVersion; UINT16 MinorVersion; UINT32 Name; UINT32 Base; UINT32 NumberOfFunctions; UINT32 NumberOfNames; UINT32 AddressOfFunctions; UINT32 AddressOfNames; UINT32 AddressOfNameOrdinals; } EFI_IMAGE_EXPORT_DIRECTORY; /// /// Hint/Name Table. /// typedef struct { UINT16 Hint; UINT8 Name[1]; } EFI_IMAGE_IMPORT_BY_NAME; /// /// Import Address Table RVA (Thunk Table). /// typedef struct { union { UINT32 Function; UINT32 Ordinal; EFI_IMAGE_IMPORT_BY_NAME *AddressOfData; } u1; } EFI_IMAGE_THUNK_DATA; #define EFI_IMAGE_ORDINAL_FLAG BIT31 ///< Flag for PE32. #define EFI_IMAGE_SNAP_BY_ORDINAL(Ordinal) ((Ordinal & EFI_IMAGE_ORDINAL_FLAG) != 0) #define EFI_IMAGE_ORDINAL(Ordinal) (Ordinal & 0xffff) /// /// Import Directory Table /// typedef struct { UINT32 Characteristics; UINT32 TimeDateStamp; UINT32 ForwarderChain; UINT32 Name; EFI_IMAGE_THUNK_DATA *FirstThunk; } EFI_IMAGE_IMPORT_DESCRIPTOR; /// /// Debug Directory Format. /// typedef struct { UINT32 Characteristics; UINT32 TimeDateStamp; UINT16 MajorVersion; UINT16 MinorVersion; UINT32 Type; UINT32 SizeOfData; UINT32 RVA; ///< The address of the debug data when loaded, relative to the image base. UINT32 FileOffset; ///< The file pointer to the debug data. } EFI_IMAGE_DEBUG_DIRECTORY_ENTRY; #define EFI_IMAGE_DEBUG_TYPE_CODEVIEW 2 ///< The Visual C++ debug information. /// /// Debug Data Structure defined in Microsoft C++. /// #define CODEVIEW_SIGNATURE_NB10 SIGNATURE_32('N', 'B', '1', '0') typedef struct { UINT32 Signature; ///< "NB10" UINT32 Unknown; UINT32 Unknown2; UINT32 Unknown3; // // Filename of .PDB goes here // } EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY; /// /// Debug Data Structure defined in Microsoft C++. /// #define CODEVIEW_SIGNATURE_RSDS SIGNATURE_32('R', 'S', 'D', 'S') typedef struct { UINT32 Signature; ///< "RSDS". UINT32 Unknown; UINT32 Unknown2; UINT32 Unknown3; UINT32 Unknown4; UINT32 Unknown5; // // Filename of .PDB goes here // } EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY; /// /// Debug Data Structure defined by Apple Mach-O to Coff utility. /// #define CODEVIEW_SIGNATURE_MTOC SIGNATURE_32('M', 'T', 'O', 'C') typedef struct { UINT32 Signature; ///< "MTOC". EFI_GUID MachOUuid; // // Filename of .DLL (Mach-O with debug info) goes here // } EFI_IMAGE_DEBUG_CODEVIEW_MTOC_ENTRY; /// /// Resource format. /// typedef struct { UINT32 Characteristics; UINT32 TimeDateStamp; UINT16 MajorVersion; UINT16 MinorVersion; UINT16 NumberOfNamedEntries; UINT16 NumberOfIdEntries; // // Array of EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY entries goes here. // } EFI_IMAGE_RESOURCE_DIRECTORY; /// /// Resource directory entry format. /// typedef struct { union { struct { UINT32 NameOffset:31; UINT32 NameIsString:1; } s; UINT32 Id; } u1; union { UINT32 OffsetToData; struct { UINT32 OffsetToDirectory:31; UINT32 DataIsDirectory:1; } s; } u2; } EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY; /// /// Resource directory entry for string. /// typedef struct { UINT16 Length; CHAR16 String[1]; } EFI_IMAGE_RESOURCE_DIRECTORY_STRING; /// /// Resource directory entry for data array. /// typedef struct { UINT32 OffsetToData; UINT32 Size; UINT32 CodePage; UINT32 Reserved; } EFI_IMAGE_RESOURCE_DATA_ENTRY; /// /// Header format for TE images, defined in the PI Specification, 1.0. /// typedef struct { UINT16 Signature; ///< The signature for TE format = "VZ". UINT16 Machine; ///< From the original file header. UINT8 NumberOfSections; ///< From the original file header. UINT8 Subsystem; ///< From original optional header. UINT16 StrippedSize; ///< Number of bytes we removed from the header. UINT32 AddressOfEntryPoint; ///< Offset to entry point -- from original optional header. UINT32 BaseOfCode; ///< From original image -- required for ITP debug. UINT64 ImageBase; ///< From original file header. EFI_IMAGE_DATA_DIRECTORY DataDirectory[2]; ///< Only base relocation and debug directory. } EFI_TE_IMAGE_HEADER; #define EFI_TE_IMAGE_HEADER_SIGNATURE SIGNATURE_16('V', 'Z') // // Data directory indexes in our TE image header // #define EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC 0 #define EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG 1 /// /// Union of PE32, PE32+, and TE headers. /// typedef union { EFI_IMAGE_NT_HEADERS32 Pe32; EFI_IMAGE_NT_HEADERS64 Pe32Plus; EFI_TE_IMAGE_HEADER Te; } EFI_IMAGE_OPTIONAL_HEADER_UNION; typedef union { EFI_IMAGE_NT_HEADERS32 *Pe32; EFI_IMAGE_NT_HEADERS64 *Pe32Plus; EFI_TE_IMAGE_HEADER *Te; EFI_IMAGE_OPTIONAL_HEADER_UNION *Union; } EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION; typedef struct { WIN_CERTIFICATE Hdr; UINT8 CertData[1]; } WIN_CERTIFICATE_EFI_PKCS; #define SHA256_DIGEST_SIZE 32 #define WIN_CERT_TYPE_PKCS_SIGNED_DATA 0x0002 typedef struct { UINT64 ImageAddress; UINT64 ImageSize; UINT64 EntryPoint; UINTN SizeOfHeaders; UINT16 ImageType; UINT16 NumberOfSections; UINT32 FileAlignment; 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 efitools-1.9.2/include/buildefi.h000066400000000000000000000005221341522017100167210ustar00rootroot00000000000000#ifndef _BUILDEFI_H #define _BUILDEFI_H #ifndef BUILD_EFI #include #include #include #define Print(...) printf("%ls", __VA_ARGS__) #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 #endif /* _BUILDEFI_H */ efitools-1.9.2/include/configtable.h000066400000000000000000000046311341522017100174200ustar00rootroot00000000000000/* 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); efitools-1.9.2/include/console.h000066400000000000000000000010711341522017100166000ustar00rootroot00000000000000EFI_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 efitools-1.9.2/include/efiauthenticated.h000066400000000000000000000214661341522017100204560ustar00rootroot00000000000000#ifndef _INC_EFIAUTHENTICATED_H #define _INC_EFIAUTHENTICATED_H #include //*********************************************************************** // Signature Database //*********************************************************************** /// /// The format of a signature database. /// typedef UINT8 EFI_SHA256_HASH[32]; typedef UINT8 EFI_SHA384_HASH[48]; typedef UINT8 EFI_SHA512_HASH[64]; #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; typedef struct { /// /// The SHA256 hash of an X.509 certificate's To-Be-Signed contents. /// EFI_SHA256_HASH ToBeSignedHash; /// /// The time that the certificate shall be considered to be revoked. /// EFI_TIME TimeOfRevocation; } EFI_CERT_X509_SHA256; typedef struct { /// /// The SHA384 hash of an X.509 certificate's To-Be-Signed contents. /// EFI_SHA384_HASH ToBeSignedHash; /// /// The time that the certificate shall be considered to be revoked. /// EFI_TIME TimeOfRevocation; } EFI_CERT_X509_SHA384; typedef struct { /// /// The SHA512 hash of an X.509 certificate's To-Be-Signed contents. /// EFI_SHA512_HASH ToBeSignedHash; /// /// The time that the certificate shall be considered to be revoked. /// EFI_TIME TimeOfRevocation; } EFI_CERT_X509_SHA512; #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} \ } #define EFI_CERT_X509_SHA256_GUID \ (EFI_GUID) { 0x3bd2a492, 0x96c0, 0x4079, \ { 0xb4, 0x20, 0xfc, 0xf9, 0x8e, 0xf1, 0x03, 0xed } } #define EFI_CERT_X509_SHA384_GUID \ (EFI_GUID) { 0x7076876e, 0x80c2, 0x4ee6, \ { 0xaa, 0xd2, 0x28, 0xb3, 0x49, 0xa6, 0x86, 0x5b } } #define EFI_CERT_X509_SHA512_GUID \ (EFI_GUID) { 0x446dbf63, 0x2502, 0x4cda, \ { 0xbc, 0xfa, 0x24, 0x65, 0xd2, 0xb0, 0xfe, 0x9d } } /// /// 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 efitools-1.9.2/include/errors.h000066400000000000000000000002731341522017100164550ustar00rootroot00000000000000#include #ifndef EFI_INCOMPATIBLE_VERSION #define EFI_INCOMPATIBLE_VERSION EFIERR(25) #endif #ifndef EFI_SECURITY_VIOLATION #define EFI_SECURITY_VIOLATION EFIERR(26) #endif efitools-1.9.2/include/execute.h000066400000000000000000000002441341522017100166010ustar00rootroot00000000000000EFI_STATUS generate_path(CHAR16* name, EFI_LOADED_IMAGE *li, EFI_DEVICE_PATH **path, CHAR16 **PathName); EFI_STATUS execute(EFI_HANDLE image, CHAR16 *name); efitools-1.9.2/include/guid.h000066400000000000000000000020121341522017100160620ustar00rootroot00000000000000#include #ifndef BUILD_EFI #ifdef CONFIG_arm /* FIXME: * arm efi leaves a visibilit pragma pushed that won't work for * non efi programs, so eliminate it */ #pragma GCC visibility pop #endif 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); EFI_GUID *get_owner_guid(char *var); #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; extern EFI_GUID SECURE_VARIABLE_GUID; extern EFI_GUID PKCS7_VERIFY_PROTOCOL_GUID; extern EFI_GUID EFI_CERT_SHA1_GUID; extern EFI_GUID EFI_CERT_SHA224_GUID; extern EFI_GUID EFI_CERT_SHA384_GUID; extern EFI_GUID EFI_CERT_SHA512_GUID; extern EFI_GUID *allowed_hashes[]; extern UINTN allowed_hashes_size; efitools-1.9.2/include/kernel_efivars.h000066400000000000000000000014241341522017100201370ustar00rootroot00000000000000#include #include void kernel_variable_init(void); int get_variable(const char *var, EFI_GUID *guid, uint32_t *attributes, uint32_t *size, void *buf); int get_variable_alloc(const char *var, EFI_GUID *guid, uint32_t *attributes, uint32_t *size, uint8_t **buf); int variable_is_setupmode(void); int variable_is_secureboot(void); int set_variable(const char *var, EFI_GUID *guid, uint32_t attributes, uint32_t size, void *buf); int set_variable_esl(const char *var, EFI_GUID *guid, uint32_t attributes, uint32_t size, void *buf); int set_variable_hash(const char *var, EFI_GUID *owner, uint32_t attributes, uint8_t hash[SHA256_DIGEST_SIZE]); uint8_t * hash_to_esl(EFI_GUID *owner, int *len, uint8_t hash[SHA256_DIGEST_SIZE]); efitools-1.9.2/include/openssl_sign.h000066400000000000000000000005261341522017100176450ustar00rootroot00000000000000#include int sign_efi_var(char *payload, int payload_size, char *keyfile, char *certfile, unsigned char **sig, int *sigsize, char *engine); int sign_efi_var_ssl(char *payload, int payload_size, EVP_PKEY *pkey, X509 *cert, unsigned char **sig, int *sigsize); EVP_PKEY * read_private_key(char *engine, char *keyfile); efitools-1.9.2/include/pecoff.h000066400000000000000000000014001341522017100163740ustar00rootroot00000000000000#include EFI_STATUS pecoff_read_header(PE_COFF_LOADER_IMAGE_CONTEXT *context, void *data); EFI_STATUS pecoff_relocate(PE_COFF_LOADER_IMAGE_CONTEXT *context, void **data); EFI_STATUS pecoff_image_layout(PE_COFF_LOADER_IMAGE_CONTEXT *context, void **data); EFI_STATUS pecoff_execute_checked(EFI_HANDLE image, EFI_SYSTEM_TABLE *systab, CHAR16 *name); EFI_STATUS pecoff_execute_image(EFI_FILE *file, CHAR16 *name, EFI_HANDLE image, EFI_SYSTEM_TABLE *systab); EFI_STATUS pecoff_get_signature(PE_COFF_LOADER_IMAGE_CONTEXT *context, void *buffer, WIN_CERTIFICATE **data, int signum); static inline void* pecoff_image_address(void *image, int size, unsigned int address) { if (address > size) return NULL; return image + address; } efitools-1.9.2/include/pkcs7verify.h000066400000000000000000000327131341522017100174210ustar00rootroot00000000000000/** @file EFI_PKCS7_VERIFY_PROTOCOL as defined in UEFI 2.5. The EFI_PKCS7_VERIFY_PROTOCOL is used to verify data signed using PKCS#7 formatted authentication. The PKCS#7 data to be verified must be binary DER encoded. PKCS#7 is a general-purpose cryptographic standard (defined by RFC2315, available at http://tools.ietf.org/html/rfc2315). Copyright (c) 2015, Intel Corporation. All rights reserved.
This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License that 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 __EFI_PKCS7_VERIFY_PROTOCOL_H__ #define __EFI_PKCS7_VERIFY_PROTOCOL_H__ typedef struct _EFI_PKCS7_VERIFY_PROTOCOL EFI_PKCS7_VERIFY_PROTOCOL; /** Processes a buffer containing binary DER-encoded PKCS7 signature. The signed data content may be embedded within the buffer or separated. Funtion verifies the signature of the content is valid and signing certificate was not revoked and is contained within a list of trusted signers. @param[in] This Pointer to EFI_PKCS7_VERIFY_PROTOCOL instance. @param[in] SignedData Points to buffer containing ASN.1 DER-encoded PKCS7 signature. @param[in] SignedDataSize The size of SignedData buffer in bytes. @param[in] InData In case of detached signature, InData points to buffer containing the raw message data previously signed and to be verified by function. In case of SignedData containing embedded data, InData must be NULL. @param[in] InDataSize When InData is used, the size of InData buffer in bytes. When InData is NULL. This parameter must be 0. @param[in] AllowedDb Pointer to a list of pointers to EFI_SIGNATURE_LIST structures. The list is terminated by a null pointer. The EFI_SIGNATURE_LIST structures contain lists of X.509 certificates of approved signers. Function recognizes signer certificates of type EFI_CERT_X509_GUID. Any hash certificate in AllowedDb list is ignored by this function. Function returns success if signer of the buffer is within this list (and not within RevokedDb). This parameter is required. @param[in] RevokedDb Optional pointer to a list of pointers to EFI_SIGNATURE_LIST structures. The list is terminated by a null pointer. List of X.509 certificates of revoked signers and revoked file hashes. Except as noted in description of TimeStampDb signature verification will always fail if the signer of the file or the hash of the data component of the buffer is in RevokedDb list. This list is optional and caller may pass Null or pointer to NULL if not required. @param[in] TimeStampDb Optional pointer to a list of pointers to EFI_SIGNATURE_LIST structures. The list is terminated by a null pointer. This parameter can be used to pass a list of X.509 certificates of trusted time stamp signers. This list is optional and caller must pass Null or pointer to NULL if not required. @param[out] Content On input, points to an optional caller-allocated buffer into which the function will copy the content portion of the file after verification succeeds. This parameter is optional and if NULL, no copy of content from file is performed. @param[in,out] ContentSize On input, points to the size in bytes of the optional buffer Content previously allocated by caller. On output, if the verification succeeds, the value referenced by ContentSize will contain the actual size of the content from signed file. If ContentSize indicates the caller-allocated buffer is too small to contain content, an error is returned, and ContentSize will be updated with the required size. This parameter must be 0 if Content is Null. @retval EFI_SUCCESS Content signature was verified against hash of content, the signer's certificate was not found in RevokedDb, and was found in AllowedDb or if in signer is found in both AllowedDb and RevokedDb, the signing was allowed by reference to TimeStampDb as described above, and no hash matching content hash was found in RevokedDb. @retval EFI_SECURITY_VIOLATION The SignedData buffer was correctly formatted but signer was in RevokedDb or not in AllowedDb. Also returned if matching content hash found in RevokedDb. @retval EFI_COMPROMISED_DATA Calculated hash differs from signed hash. @retval EFI_INVALID_PARAMETER SignedData is NULL or SignedDataSize is zero. AllowedDb is NULL. @retval EFI_INVALID_PARAMETER Content is not NULL and ContentSize is NULL. @retval EFI_ABORTED Unsupported or invalid format in TimeStampDb, RevokedDb or AllowedDb list contents was detected. @retval EFI_NOT_FOUND Content not found because InData is NULL and no content embedded in SignedData. @retval EFI_UNSUPPORTED The SignedData buffer was not correctly formatted for processing by the function. @retval EFI_UNSUPPORTED Signed data embedded in SignedData but InData is not NULL. @retval EFI_BUFFER_TOO_SMALL The size of buffer indicated by ContentSize is too small to hold the content. ContentSize updated to required size. **/ typedef EFI_STATUS (EFIAPI *EFI_PKCS7_VERIFY_BUFFER) ( IN EFI_PKCS7_VERIFY_PROTOCOL *This, IN VOID *SignedData, IN UINTN SignedDataSize, IN VOID *InData OPTIONAL, IN UINTN InDataSize, IN EFI_SIGNATURE_LIST **AllowedDb, IN EFI_SIGNATURE_LIST **RevokedDb OPTIONAL, IN EFI_SIGNATURE_LIST **TimeStampDb OPTIONAL, OUT VOID *Content OPTIONAL, IN OUT UINTN *ContentSize ); /** Processes a buffer containing binary DER-encoded detached PKCS7 signature. The hash of the signed data content is calculated and passed by the caller. Function verifies the signature of the content is valid and signing certificate was not revoked and is contained within a list of trusted signers. @param[in] This Pointer to EFI_PKCS7_VERIFY_PROTOCOL instance. @param[in] Signature Points to buffer containing ASN.1 DER-encoded PKCS detached signature. @param[in] SignatureSize The size of Signature buffer in bytes. @param[in] InHash InHash points to buffer containing the caller calculated hash of the data. The parameter may not be NULL. @param[in] InHashSize The size in bytes of InHash buffer. @param[in] AllowedDb Pointer to a list of pointers to EFI_SIGNATURE_LIST structures. The list is terminated by a null pointer. The EFI_SIGNATURE_LIST structures contain lists of X.509 certificates of approved signers. Function recognizes signer certificates of type EFI_CERT_X509_GUID. Any hash certificate in AllowedDb list is ignored by this function. Function returns success if signer of the buffer is within this list (and not within RevokedDb). This parameter is required. @param[in] RevokedDb Optional pointer to a list of pointers to EFI_SIGNATURE_LIST structures. The list is terminated by a null pointer. List of X.509 certificates of revoked signers and revoked file hashes. Signature verification will always fail if the signer of the file or the hash of the data component of the buffer is in RevokedDb list. This parameter is optional and caller may pass Null if not required. @param[in] TimeStampDb Optional pointer to a list of pointers to EFI_SIGNATURE_LIST structures. The list is terminated by a null pointer. This parameter can be used to pass a list of X.509 certificates of trusted time stamp counter-signers. @retval EFI_SUCCESS Signed hash was verified against caller-provided hash of content, the signer's certificate was not found in RevokedDb, and was found in AllowedDb or if in signer is found in both AllowedDb and RevokedDb, the signing was allowed by reference to TimeStampDb as described above, and no hash matching content hash was found in RevokedDb. @retval EFI_SECURITY_VIOLATION The SignedData buffer was correctly formatted but signer was in RevokedDb or not in AllowedDb. Also returned if matching content hash found in RevokedDb. @retval EFI_COMPROMISED_DATA Caller provided hash differs from signed hash. Or, caller and encrypted hash are different sizes. @retval EFI_INVALID_PARAMETER Signature is NULL or SignatureSize is zero. InHash is NULL or InHashSize is zero. AllowedDb is NULL. @retval EFI_ABORTED Unsupported or invalid format in TimeStampDb, RevokedDb or AllowedDb list contents was detected. @retval EFI_UNSUPPORTED The Signature buffer was not correctly formatted for processing by the function. **/ typedef EFI_STATUS (EFIAPI *EFI_PKCS7_VERIFY_SIGNATURE) ( IN EFI_PKCS7_VERIFY_PROTOCOL *This, IN VOID *Signature, IN UINTN SignatureSize, IN VOID *InHash, IN UINTN InHashSize, IN EFI_SIGNATURE_LIST **AllowedDb, IN EFI_SIGNATURE_LIST **RevokedDb OPTIONAL, IN EFI_SIGNATURE_LIST **TimeStampDb OPTIONAL ); /// /// The EFI_PKCS7_VERIFY_PROTOCOL is used to verify data signed using PKCS7 /// structure. The PKCS7 data to be verified must be ASN.1 (DER) encoded. /// SHA256 must be supported as digest algorithm with RSA digest encryption. /// Support of other hash algorithms is optional. /// struct _EFI_PKCS7_VERIFY_PROTOCOL { EFI_PKCS7_VERIFY_BUFFER VerifyBuffer; EFI_PKCS7_VERIFY_SIGNATURE VerifySignature; }; EFI_STATUS pkcs7verify_get_protocol(EFI_HANDLE image, EFI_PKCS7_VERIFY_PROTOCOL **p7vp, CHAR16 **error); BOOLEAN pkcs7verify_deny(VOID *data, UINTN len); EFI_SIGNATURE_LIST ** pkcs7verify_to_cert_list(VOID *data, UINTN len); BOOLEAN pkcs7verify_allow(VOID *data, UINTN len); #endif efitools-1.9.2/include/security_policy.h000066400000000000000000000007461341522017100203740ustar00rootroot00000000000000typedef BOOLEAN (*POLICY_FUNCTION)(VOID *data, UINTN len); EFI_STATUS security_policy_install(BOOLEAN (*override)(void), POLICY_FUNCTION allow, POLICY_FUNCTION deny); EFI_STATUS security_policy_uninstall(void); void security_protocol_set_hashes(unsigned char *esl, int len); /* three policies for MoK based on hashes only */ BOOLEAN security_policy_mok_override(void); BOOLEAN security_policy_mok_deny(VOID *data, UINTN len); BOOLEAN security_policy_mok_allow(VOID *data, UINTN len); efitools-1.9.2/include/sha256.h000066400000000000000000000013671341522017100161560ustar00rootroot00000000000000#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 */ efitools-1.9.2/include/shell.h000066400000000000000000000001021341522017100162370ustar00rootroot00000000000000EFI_STATUS argsplit(EFI_HANDLE image, int *argc, CHAR16*** ARGV); efitools-1.9.2/include/shim_protocol.h000066400000000000000000000013101341522017100200130ustar00rootroot00000000000000#ifndef _SHIM_PROTOCOL_H #define _SHIM_PROTOCOL_H #include #include typedef EFI_STATUS (*EFI_SHIM_LOCK_VERIFY) ( IN VOID *buffer, IN UINT32 size ); typedef EFI_STATUS (*EFI_SHIM_LOCK_HASH) ( IN char *data, IN int datasize, PE_COFF_LOADER_IMAGE_CONTEXT *context, UINT8 *sha256hash, UINT8 *sha1hash ); typedef EFI_STATUS (*EFI_SHIM_LOCK_CONTEXT) ( IN VOID *data, IN unsigned int datasize, PE_COFF_LOADER_IMAGE_CONTEXT *context ); typedef struct _SHIM_LOCK { EFI_SHIM_LOCK_VERIFY Verify; EFI_SHIM_LOCK_HASH Hash; EFI_SHIM_LOCK_CONTEXT Context; } SHIM_LOCK; EFI_STATUS shim_protocol_install(void); void shim_protocol_uninstall(void); #endif /* _SHIM_PROTOCOL_H */ efitools-1.9.2/include/simple_file.h000066400000000000000000000014751341522017100174360ustar00rootroot00000000000000EFI_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); efitools-1.9.2/include/variableformat.h000066400000000000000000000051521341522017100201400ustar00rootroot00000000000000#ifndef _INC_VARIABLEFORMAT_H #define _INC_VARIABLEFORMAT_H /// /// Alignment of Variable Data Header in Variable Store region. /// #define HEADER_ALIGNMENT 4 #define HEADER_ALIGN(Header) (((UINTN) (Header) + HEADER_ALIGNMENT - 1) & (~(HEADER_ALIGNMENT - 1))) /// /// Status of Variable Store Region. /// typedef enum { EfiRaw, EfiValid, EfiInvalid, EfiUnknown } VARIABLE_STORE_STATUS; #pragma pack(1) #define VARIABLE_STORE_SIGNATURE EFI_AUTHENTICATED_VARIABLE_GUID /// /// Variable Store Header Format and State. /// #define VARIABLE_STORE_FORMATTED 0x5a #define VARIABLE_STORE_HEALTHY 0xfe /// /// Variable Store region header. /// typedef struct { /// /// Variable store region signature. /// EFI_GUID Signature; /// /// Size of entire variable store, /// including size of variable store header but not including the size of FvHeader. /// UINT32 Size; /// /// Variable region format state. /// UINT8 Format; /// /// Variable region healthy state. /// UINT8 State; UINT16 Reserved; UINT32 Reserved1; } VARIABLE_STORE_HEADER; /// /// Variable data start flag. /// #define VARIABLE_DATA 0x55AA /// /// Variable State flags. /// #define VAR_IN_DELETED_TRANSITION 0xfe ///< Variable is in obsolete transition. #define VAR_DELETED 0xfd ///< Variable is obsolete. #define VAR_HEADER_VALID_ONLY 0x7f ///< Variable header has been valid. #define VAR_ADDED 0x3f ///< Variable has been completely added. /// /// Single Variable Data Header Structure. /// typedef struct { /// /// Variable Data Start Flag. /// UINT16 StartId; /// /// Variable State defined above. /// UINT8 State; UINT8 Reserved; /// /// Attributes of variable defined in UEFI specification. /// UINT32 Attributes; /// /// Associated monotonic count value against replay attack. /// UINT64 MonotonicCount; /// /// Associated TimeStamp value against replay attack. /// EFI_TIME TimeStamp; /// /// Index of associated public key in database. /// UINT32 PubKeyIndex; /// /// Size of variable null-terminated Unicode string name. /// UINT32 NameSize; /// /// Size of the variable data without this header. /// UINT32 DataSize; /// /// A unique identifier for the vendor that produces and consumes this varaible. /// EFI_GUID VendorGuid; } VARIABLE_HEADER; #pragma pack() inline BOOLEAN IsValidVariableHeader (VARIABLE_HEADER *vh) { if (vh == NULL || vh->StartId != VARIABLE_DATA) return FALSE; return TRUE; } #endif efitools-1.9.2/include/variables.h000066400000000000000000000027731341522017100171200ustar00rootroot00000000000000#include #include /* for SHA256_DIGEST_SIZE */ #include EFI_STATUS CreatePkX509SignatureList ( IN UINT8 *X509Data, IN UINTN X509DataSize, IN EFI_GUID owner, OUT EFI_SIGNATURE_LIST **PkCert ); EFI_STATUS CreateTimeBasedPayload ( IN OUT UINTN *DataSize, IN OUT UINT8 **Data ); EFI_STATUS SetSecureVariable(CHAR16 *var, UINT8 *Data, UINTN len, EFI_GUID owner, UINT32 options, int createtimebased); EFI_STATUS get_variable(CHAR16 *var, UINT8 **data, UINTN *len, EFI_GUID owner); EFI_STATUS get_variable_attr(CHAR16 *var, UINT8 **data, UINTN *len, EFI_GUID owner, UINT32 *attributes); EFI_STATUS find_in_esl(UINT8 *Data, UINTN DataSize, UINT8 *key, UINTN keylen); EFI_STATUS find_in_variable_esl(CHAR16* var, EFI_GUID owner, UINT8 *key, UINTN keylen); #define EFI_OS_INDICATIONS_BOOT_TO_FW_UI 0x0000000000000001 #define EFI_OS_INDICATIONS_TIMESTAMP_REVOCATION 0x0000000000000002 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); int hashes_in_esl(UINT8 *Data, UINTN DataSize, EFI_GUID *hashes[]); int hashes_in_variable(CHAR16* var, EFI_GUID owner, EFI_GUID *hashes[]); efitools-1.9.2/include/variables_iterators.h000066400000000000000000000012511341522017100212020ustar00rootroot00000000000000 #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)) efitools-1.9.2/include/version.h000066400000000000000000000001571341522017100166270ustar00rootroot00000000000000#define VERSION "1.9.2" static void version(const char *progname) { printf("%s " VERSION "\n", progname); } efitools-1.9.2/include/wincert.h000066400000000000000000000016531341522017100166170ustar00rootroot00000000000000#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 efitools-1.9.2/include/x509.h000066400000000000000000000012211341522017100156400ustar00rootroot00000000000000#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); efitools-1.9.2/lib/000077500000000000000000000000001341522017100141115ustar00rootroot00000000000000efitools-1.9.2/lib/Makefile000066400000000000000000000006251341522017100155540ustar00rootroot00000000000000FILES = simple_file.o pecoff.o guid.o sha256.o console.o \ execute.o configtable.o shell.o security_policy.o \ shim_protocol.o pkcs7verify.o LIBFILES = $(FILES) kernel_efivars.o openssl_sign.o EFILIBFILES = $(patsubst %.o,%.efi.o,$(FILES)) variables.o include ../Make.rules lib.a: $(LIBFILES) lib-efi.a: $(EFILIBFILES) clean: rm -f lib.a rm -f lib-efi.a rm -f $(LIBFILES) rm -f $(EFILIBFILES) efitools-1.9.2/lib/asn1/000077500000000000000000000000001341522017100147535ustar00rootroot00000000000000efitools-1.9.2/lib/asn1/.gitignore000066400000000000000000000000051341522017100167360ustar00rootroot00000000000000test efitools-1.9.2/lib/asn1/Makefile000066400000000000000000000007241341522017100164160ustar00rootroot00000000000000LIBFILES = 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.a: $(LIBFILES) libasn1-efi.a: $(EFILIBFILES) test.o: test.c ../../include/x509.h $(CC) $(ARCH3264) -I../../include -c -o $@ $< test: test.o libasn1.a $(CC) $(ARCH3264) -o $@ $< libasn1.a clean: rm -f libasn1.a rm -f libasn1-efi.a rm -f test test.o rm -f $(LIBFILES) rm -f $(EFILIBFILES) efitools-1.9.2/lib/asn1/asn1.c000066400000000000000000000067111341522017100157660ustar00rootroot00000000000000/* * Copyright (C) 2006 Martin Will * Copyright (C) 2000-2008 Andreas Steffen * * Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #include "typedefs.h" #include "enumerator.h" #include "chunk.h" #include "oid.h" #include "asn1.h" #include "asn1_parser.h" /* * Defined in header. */ int asn1_known_oid(chunk_t object) { int oid = 0; while (object.len) { if (oid_names[oid].octet == *object.ptr) { if (--object.len == 0 || oid_names[oid].down == 0) { return oid; /* found terminal symbol */ } else { object.ptr++; oid++; /* advance to next hex octet */ } } else { if (oid_names[oid].next) { oid = oid_names[oid].next; } else { return OID_UNKNOWN; } } } return -1; } /* * Defined in header. */ chunk_t asn1_build_known_oid(int n) { chunk_t oid; int i; if (n < 0 || n >= OID_MAX) { return chunk_empty; } i = oid_names[n].level + 1; oid = chunk_alloc(2 + i); oid.ptr[0] = ASN1_OID; oid.ptr[1] = i; do { if (oid_names[n].level >= i) { n--; continue; } oid.ptr[--i + 2] = oid_names[n--].octet; } while (i > 0); return oid; } /* * Defined in header. */ size_t asn1_length(chunk_t *blob) { u_char n; size_t len; if (blob->len < 2) { DBG1("insufficient number of octets to parse ASN.1 length"); return ASN1_INVALID_LENGTH; } /* read length field, skip tag and length */ n = blob->ptr[1]; blob->ptr += 2; blob->len -= 2; if ((n & 0x80) == 0) { /* single length octet */ if (n > blob->len) { DBG1("length is larger than remaining blob size"); return ASN1_INVALID_LENGTH; } return n; } /* composite length, determine number of length octets */ n &= 0x7f; if (n == 0 || n > blob->len) { DBG1("number of length octets invalid"); return ASN1_INVALID_LENGTH; } if (n > sizeof(len)) { DBG1("number of length octets is larger than limit of" " %d octets", (int)sizeof(len)); return ASN1_INVALID_LENGTH; } len = 0; while (n-- > 0) { len = 256*len + *blob->ptr++; blob->len--; } if (len > blob->len) { DBG1("length is larger than remaining blob size"); return ASN1_INVALID_LENGTH; } return len; } /* * See header. */ int asn1_unwrap(chunk_t *blob, chunk_t *inner) { chunk_t res; u_char len; int type; if (blob->len < 2) { return ASN1_INVALID; } type = blob->ptr[0]; len = blob->ptr[1]; *blob = chunk_skip(*blob, 2); if ((len & 0x80) == 0) { /* single length octet */ res.len = len; } else { /* composite length, determine number of length octets */ len &= 0x7f; if (len == 0 || len > sizeof(res.len)) { return ASN1_INVALID; } res.len = 0; while (len-- > 0) { res.len = 256 * res.len + blob->ptr[0]; *blob = chunk_skip(*blob, 1); } } if (res.len > blob->len) { return ASN1_INVALID; } res.ptr = blob->ptr; *blob = chunk_skip(*blob, res.len); /* updating inner not before we are finished allows a caller to pass * blob = inner */ *inner = res; return type; } efitools-1.9.2/lib/asn1/asn1.h000066400000000000000000000055511341522017100157740ustar00rootroot00000000000000/* * Copyright (C) 2006 Martin Will * Copyright (C) 2000-2008 Andreas Steffen * * Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ /** * @defgroup asn1i asn1 * @{ @ingroup asn1 */ #ifndef ASN1_H_ #define ASN1_H_ /** * Definition of some primitive ASN1 types */ typedef enum { ASN1_EOC = 0x00, ASN1_BOOLEAN = 0x01, ASN1_INTEGER = 0x02, ASN1_BIT_STRING = 0x03, ASN1_OCTET_STRING = 0x04, ASN1_NULL = 0x05, ASN1_OID = 0x06, ASN1_ENUMERATED = 0x0A, ASN1_UTF8STRING = 0x0C, ASN1_NUMERICSTRING = 0x12, ASN1_PRINTABLESTRING = 0x13, ASN1_T61STRING = 0x14, ASN1_VIDEOTEXSTRING = 0x15, ASN1_IA5STRING = 0x16, ASN1_UTCTIME = 0x17, ASN1_GENERALIZEDTIME = 0x18, ASN1_GRAPHICSTRING = 0x19, ASN1_VISIBLESTRING = 0x1A, ASN1_GENERALSTRING = 0x1B, ASN1_UNIVERSALSTRING = 0x1C, ASN1_BMPSTRING = 0x1E, ASN1_CONSTRUCTED = 0x20, ASN1_SEQUENCE = 0x30, ASN1_SET = 0x31, ASN1_CONTEXT_S_0 = 0x80, ASN1_CONTEXT_S_1 = 0x81, ASN1_CONTEXT_S_2 = 0x82, ASN1_CONTEXT_S_3 = 0x83, ASN1_CONTEXT_S_4 = 0x84, ASN1_CONTEXT_S_5 = 0x85, ASN1_CONTEXT_S_6 = 0x86, ASN1_CONTEXT_S_7 = 0x87, ASN1_CONTEXT_S_8 = 0x88, ASN1_CONTEXT_C_0 = 0xA0, ASN1_CONTEXT_C_1 = 0xA1, ASN1_CONTEXT_C_2 = 0xA2, ASN1_CONTEXT_C_3 = 0xA3, ASN1_CONTEXT_C_4 = 0xA4, ASN1_CONTEXT_C_5 = 0xA5, ASN1_INVALID = 0x100, } asn1_t; #define ASN1_INVALID_LENGTH 0xffffffff /** Some ASN.1 analysis functions */ /** * Converts an ASN.1 OID into a known OID index * * @param object body of an OID * @return index into the oid_names[] table or OID_UNKNOWN */ int asn1_known_oid(chunk_t object); /** * Converts a known OID index to an ASN.1 OID * * @param n index into the oid_names[] table * @return allocated OID chunk, chunk_empty if index out of range */ chunk_t asn1_build_known_oid(int n); /** * Returns the length of an ASN.1 object * The blob pointer is advanced past the tag length fields * * @param blob pointer to an ASN.1 coded blob * @return length of ASN.1 object */ size_t asn1_length(chunk_t *blob); /** * Unwrap the inner content of an ASN.1 type/length wrapped object. * * @param blob blob to parse header from, moved behind parsed content * @param content inner content * @return parsed type, ASN1_INVALID if length parsing failed */ int asn1_unwrap(chunk_t *blob, chunk_t *content); #endif /** ASN1_H_ @}*/ efitools-1.9.2/lib/asn1/asn1_parser.c000066400000000000000000000134641341522017100173450ustar00rootroot00000000000000/* * Copyright (C) 2006 Martin Will * Copyright (C) 2000-2008 Andreas Steffen * * Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #include "typedefs.h" #include "chunk.h" #include "asn1.h" #include "asn1_parser.h" #define ASN1_MAX_LEVEL 10 typedef struct private_asn1_parser_t private_asn1_parser_t; /** * Private data of an asn1_cxt_t object. */ struct private_asn1_parser_t { /** * Public interface. */ asn1_parser_t public; /** * Syntax definition of ASN.1 object */ asn1Object_t const *objects; /** * Current syntax definition line */ int line; /** * Current stat of the parsing operation */ bool success; /** * Declare object data as private - use debug level 4 to log it */ bool private; /** * Top-most type is implicit - ignore it */ bool implicit; /** * Top-most parsing level - defaults to 0 */ u_int level0; /** * Jump back address for loops for each level */ int loopAddr[ASN1_MAX_LEVEL + 1]; /** * Current parsing pointer for each level */ chunk_t blobs[ASN1_MAX_LEVEL + 2]; }; METHOD(asn1_parser_t, iterate, bool, private_asn1_parser_t *this, int *objectID, chunk_t *object) { chunk_t *blob, *blob1; u_char *start_ptr; u_int level; asn1Object_t obj; *object = chunk_empty; /* Advance to the next object syntax definition line */ obj = this->objects[++(this->line)]; /* Terminate if the end of the object syntax definition has been reached */ if (obj.flags & ASN1_EXIT) { return FALSE; } if (obj.flags & ASN1_END) /* end of loop or option found */ { if (this->loopAddr[obj.level] && this->blobs[obj.level+1].len > 0) { this->line = this->loopAddr[obj.level]; /* another iteration */ obj = this->objects[this->line]; } else { this->loopAddr[obj.level] = 0; /* exit loop or option*/ goto end; } } level = this->level0 + obj.level; blob = this->blobs + obj.level; blob1 = blob + 1; start_ptr = blob->ptr; /* handle ASN.1 defaults values */ if ((obj.flags & ASN1_DEF) && (blob->len == 0 || *start_ptr != obj.type) ) { /* field is missing */ DBG1("L%d - %a:", level, obj.name); if (obj.type & ASN1_CONSTRUCTED) { this->line++ ; /* skip context-specific tag */ } goto end; } /* handle ASN.1 options */ if ((obj.flags & ASN1_OPT) && (blob->len == 0 || *start_ptr != obj.type)) { /* advance to end of missing option field */ do { this->line++; } while (!((this->objects[this->line].flags & ASN1_END) && (this->objects[this->line].level == obj.level))); goto end; } /* an ASN.1 object must possess at least a tag and length field */ if (blob->len < 2) { DBG1("L%d - %a: ASN.1 object smaller than 2 octets", level, obj.name); this->success = FALSE; goto end; } blob1->len = asn1_length(blob); if (blob1->len == ASN1_INVALID_LENGTH) { DBG1("L%d - %a: length of ASN.1 object invalid or too large", level, obj.name); this->success = FALSE; } blob1->ptr = blob->ptr; blob->ptr += blob1->len; blob->len -= blob1->len; /* return raw ASN.1 object without prior type checking */ if (obj.flags & ASN1_RAW) { DBG1("L%d - %a:", level, obj.name); object->ptr = start_ptr; object->len = (size_t)(blob->ptr - start_ptr); goto end; } if (*start_ptr != obj.type && !(this->implicit && this->line == 0)) { DBG1("L%d - %a: ASN1 tag 0x%02x expected, but is 0x%02x", level, obj.name, obj.type, *start_ptr); DBG1("%b", start_ptr, (u_int)(blob->ptr - start_ptr)); this->success = FALSE; goto end; } DBG1("L%d - %a:", level, obj.name); /* In case of "SEQUENCE OF" or "SET OF" start a loop */ if (obj.flags & ASN1_LOOP) { if (blob1->len > 0) { /* at least one item, start the loop */ this->loopAddr[obj.level] = this->line + 1; } else { /* no items, advance directly to end of loop */ do { this->line++; } while (!((this->objects[this->line].flags & ASN1_END) && (this->objects[this->line].level == obj.level))); goto end; } } if (obj.flags & ASN1_OBJ) { object->ptr = start_ptr; object->len = (size_t)(blob->ptr - start_ptr); if (this->private) { DBG1("%B", object); } else { DBG1("%B", object); } } else if (obj.flags & ASN1_BODY) { *object = *blob1; } end: *objectID = this->line; return this->success; } METHOD(asn1_parser_t, get_level, u_int, private_asn1_parser_t *this) { return this->level0 + this->objects[this->line].level; } METHOD(asn1_parser_t, set_top_level, void, private_asn1_parser_t *this, u_int level0) { this->level0 = level0; } METHOD(asn1_parser_t, set_flags, void, private_asn1_parser_t *this, bool implicit, bool private) { this->implicit = implicit; this->private = private; } METHOD(asn1_parser_t, success, bool, private_asn1_parser_t *this) { return this->success; } METHOD(asn1_parser_t, destroy, void, private_asn1_parser_t *this) { free(this); } /** * Defined in header. */ asn1_parser_t* asn1_parser_create(asn1Object_t const *objects, chunk_t blob) { private_asn1_parser_t *this; this = malloc(sizeof(*this)); *this = (private_asn1_parser_t) { .public = { .iterate = _iterate, .get_level = _get_level, .set_top_level = _set_top_level, .set_flags = _set_flags, .success = _success, .destroy = _destroy, }, .objects = objects, .blobs[0] = blob, .line = -1, .success = TRUE, }; return &this->public; } efitools-1.9.2/lib/asn1/asn1_parser.h000066400000000000000000000052721341522017100173500ustar00rootroot00000000000000/* * Copyright (C) 2006 Martin Will * Copyright (C) 2000-2008 Andreas Steffen * * Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ /** * @defgroup asn1_parser asn1_parser * @{ @ingroup asn1 */ #ifndef ASN1_PARSER_H_ #define ASN1_PARSER_H_ #include #include "asn1.h" /** * Definition of ASN.1 flags */ #define ASN1_NONE 0x00 #define ASN1_DEF 0x01 #define ASN1_OPT 0x02 #define ASN1_LOOP 0x04 #define ASN1_END 0x08 #define ASN1_OBJ 0x10 #define ASN1_BODY 0x20 #define ASN1_RAW 0x40 #define ASN1_EXIT 0x80 typedef struct asn1Object_t asn1Object_t; /** * Syntax definition of an ASN.1 object */ struct asn1Object_t{ u_int level; const u_char *name; asn1_t type; u_char flags; }; typedef struct asn1_parser_t asn1_parser_t; /** * Public interface of an ASN.1 parser */ struct asn1_parser_t { /** * Parse the next ASN.1 object in the hierarchy and return it * * @param objectID current line in the object syntax definition * @param object current object * @return - FALSE if end of object syntax definition was reached * or a parsing error occurred * - TRUE otherwise */ bool (*iterate)(asn1_parser_t *this, int *objectID, chunk_t *object); /** * Get the current parsing level * * @return current level */ u_int (*get_level)(asn1_parser_t *this); /** * Set the top-most level * * @param level top-most level */ void (*set_top_level)(asn1_parser_t *this, u_int level0); /** * Set implicit and private flags * * @param implicit top-most type of object is implicit * @param private object data is private (use debug level 4) */ void (*set_flags)(asn1_parser_t *this, bool implicit, bool private); /** * Show final parsing status * * @return TRUE if parsing was successful, FALSE otherwise */ bool (*success)(asn1_parser_t *this); /** * Destroy the ASN.1 parser */ void (*destroy)(asn1_parser_t *this); }; /** * Create an ASN.1 parser * * @param objects syntax definition of the ASN.1 object to be parsed * @param blob ASN.1 coded binary blob * @return ASN.1 context */ asn1_parser_t* asn1_parser_create(asn1Object_t const *objects, chunk_t blob); #endif /** ASN1_PARSER_H_ @}*/ efitools-1.9.2/lib/asn1/chunk.c000066400000000000000000000032571341522017100162360ustar00rootroot00000000000000/* * Copyright (C) 2008-2009 Tobias Brunner * Copyright (C) 2005-2006 Martin Willi * Copyright (C) 2005 Jan Hutter * Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #include "typedefs.h" #include "chunk.h" /** * Empty chunk. */ chunk_t chunk_empty = { NULL, 0 }; /** * Described in header. */ chunk_t chunk_create_clone(u_char *ptr, chunk_t chunk) { chunk_t clone = chunk_empty; if (chunk.ptr && chunk.len > 0) { clone.ptr = ptr; clone.len = chunk.len; memcpy(clone.ptr, chunk.ptr, chunk.len); } return clone; } /** * Described in header. */ int chunk_compare(chunk_t a, chunk_t b) { int compare_len = a.len - b.len; int len = (compare_len < 0)? a.len : b.len; if (compare_len != 0 || len == 0) { return compare_len; } return memcmp(a.ptr, b.ptr, len); }; /** * Remove non-printable characters from a chunk. */ bool chunk_printable(chunk_t chunk, chunk_t *sane, char replace) { bool printable = TRUE; int i; if (sane) { *sane = chunk_clone(chunk); } for (i = 0; i < chunk.len; i++) { if (!isprint(chunk.ptr[i])) { if (sane) { sane->ptr[i] = replace; } printable = FALSE; } } return printable; } efitools-1.9.2/lib/asn1/chunk.h000066400000000000000000000073601341522017100162420ustar00rootroot00000000000000/* * Copyright (C) 2008-2009 Tobias Brunner * Copyright (C) 2005-2008 Martin Willi * Copyright (C) 2005 Jan Hutter * Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ /** * @defgroup chunk chunk * @{ @ingroup libstrongswan */ #ifndef CHUNK_H_ #define CHUNK_H_ typedef struct chunk_t chunk_t; /** * General purpose pointer/length abstraction. */ struct chunk_t { /** Pointer to start of data */ u_char *ptr; /** Length of data in bytes */ size_t len; }; /** * A { NULL, 0 }-chunk handy for initialization. */ extern chunk_t chunk_empty; /** * Create a new chunk pointing to "ptr" with length "len" */ static inline chunk_t chunk_create(u_char *ptr, size_t len) { chunk_t chunk = {ptr, len}; return chunk; } /** * Free contents of a chunk */ static inline void chunk_free(chunk_t *chunk) { free(chunk->ptr); *chunk = chunk_empty; } /** * Overwrite the contents of a chunk and free it */ static inline void chunk_clear(chunk_t *chunk) { if (chunk->ptr) { memset(chunk->ptr, 0, chunk->len); chunk_free(chunk); } } /** * Initialize a chunk using a char array */ #define chunk_from_chars(...) ((chunk_t){(char[]){__VA_ARGS__}, sizeof((char[]){__VA_ARGS__})}) /** * Initialize a chunk to point to a thing */ #define chunk_from_thing(thing) chunk_create((char*)&(thing), sizeof(thing)) /** * Allocate a chunk on the heap */ #define chunk_alloc(bytes) ({size_t x = (bytes); chunk_create(x ? malloc(x) : NULL, x);}) /** * Allocate a chunk on the stack */ #define chunk_alloca(bytes) ({size_t x = (bytes); chunk_create(x ? alloca(x) : NULL, x);}) /** * Clone a chunk on heap */ #define chunk_clone(chunk) ({chunk_t x = (chunk); chunk_create_clone(x.len ? malloc(x.len) : NULL, x);}) /** * Skip n bytes in chunk (forward pointer, shorten length) */ static inline chunk_t chunk_skip(chunk_t chunk, size_t bytes) { if (chunk.len > bytes) { chunk.ptr += bytes; chunk.len -= bytes; return chunk; } return chunk_empty; } /** * Skip a leading zero-valued byte */ static inline chunk_t chunk_skip_zero(chunk_t chunk) { if (chunk.len > 1 && *chunk.ptr == 0x00) { chunk.ptr++; chunk.len--; } return chunk; } /** * Compare two chunks, returns zero if a equals b * or negative/positive if a is small/greater than b */ int chunk_compare(chunk_t a, chunk_t b); /** * Compare two chunks for equality, * NULL chunks are never equal. */ static inline bool chunk_equals(chunk_t a, chunk_t b) { return a.ptr != NULL && b.ptr != NULL && a.len == b.len && memeq(a.ptr, b.ptr, a.len); } /** * Compare two chunks (given as pointers) for equality (useful as callback), * NULL chunks are never equal. */ static inline bool chunk_equals_ptr(chunk_t *a, chunk_t *b) { return a != NULL && b != NULL && chunk_equals(*a, *b); } /** * Check if a chunk has printable characters only. * * If sane is given, chunk is cloned into sane and all non printable characters * get replaced by "replace". * * @param chunk chunk to check for printability * @param sane pointer where sane version is allocated, or NULL * @param replace character to use for replaceing unprintable characters * @return TRUE if all characters in chunk are printable */ bool chunk_printable(chunk_t chunk, chunk_t *sane, char replace); #endif efitools-1.9.2/lib/asn1/enumerator.c000066400000000000000000000020411341522017100172750ustar00rootroot00000000000000/* * Copyright (C) 2008 Tobias Brunner * Copyright (C) 2007 Martin Willi * Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #include "typedefs.h" #include "enumerator.h" /** * Implementation of enumerator_create_empty().enumerate */ static bool enumerate_empty(enumerator_t *enumerator, ...) { return FALSE; } /** * See header */ enumerator_t* enumerator_create_empty(void) { enumerator_t *this = malloc_thing(enumerator_t); this->enumerate = enumerate_empty; this->destroy = (void*)free; return this; } efitools-1.9.2/lib/asn1/enumerator.h000066400000000000000000000026741341522017100173160ustar00rootroot00000000000000/* * Copyright (C) 2007 Martin Willi * Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ /** * @defgroup enumerator enumerator * @{ @ingroup utils */ #ifndef ENUMERATOR_H_ #define ENUMERATOR_H_ typedef struct enumerator_t enumerator_t; /** * Enumerator interface, allows enumeration over collections. */ struct enumerator_t { /** * Enumerate collection. * * The enumerate function takes a variable argument list containing * pointers where the enumerated values get written. * * @param ... variable list of enumerated items, implementation dependent * @return TRUE if pointers returned */ bool (*enumerate)(enumerator_t *this, ...); /** * Destroy a enumerator instance. */ void (*destroy)(enumerator_t *this); }; /** * Create an enumerator which enumerates over nothing * * @return an enumerator over no values */ enumerator_t* enumerator_create_empty(); #endif /** ENUMERATOR_H_ @}*/ efitools-1.9.2/lib/asn1/identification.c000066400000000000000000000127171341522017100201200ustar00rootroot00000000000000/* * Copyright (C) 2009-2012 Tobias Brunner * Copyright (C) 2005-2009 Martin Willi * Copyright (C) 2005 Jan Hutter * Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #include "typedefs.h" #include "identification.h" #include "oid.h" #include "asn1.h" /** * coding of X.501 distinguished name */ typedef struct { const u_char *name; int oid; u_char type; } x501rdn_t; static const x501rdn_t x501rdns[] = { {"ND", OID_NAME_DISTINGUISHER, ASN1_PRINTABLESTRING}, {"UID", OID_PILOT_USERID, ASN1_PRINTABLESTRING}, {"DC", OID_PILOT_DOMAIN_COMPONENT, ASN1_PRINTABLESTRING}, {"CN", OID_COMMON_NAME, ASN1_PRINTABLESTRING}, {"S", OID_SURNAME, ASN1_PRINTABLESTRING}, {"SN", OID_SERIAL_NUMBER, ASN1_PRINTABLESTRING}, {"serialNumber", OID_SERIAL_NUMBER, ASN1_PRINTABLESTRING}, {"C", OID_COUNTRY, ASN1_PRINTABLESTRING}, {"L", OID_LOCALITY, ASN1_PRINTABLESTRING}, {"ST", OID_STATE_OR_PROVINCE, ASN1_PRINTABLESTRING}, {"O", OID_ORGANIZATION, ASN1_PRINTABLESTRING}, {"OU", OID_ORGANIZATION_UNIT, ASN1_PRINTABLESTRING}, {"T", OID_TITLE, ASN1_PRINTABLESTRING}, {"D", OID_DESCRIPTION, ASN1_PRINTABLESTRING}, {"N", OID_NAME, ASN1_PRINTABLESTRING}, {"G", OID_GIVEN_NAME, ASN1_PRINTABLESTRING}, {"I", OID_INITIALS, ASN1_PRINTABLESTRING}, {"dnQualifier", OID_DN_QUALIFIER, ASN1_PRINTABLESTRING}, {"ID", OID_UNIQUE_IDENTIFIER, ASN1_PRINTABLESTRING}, {"EN", OID_EMPLOYEE_NUMBER, ASN1_PRINTABLESTRING}, {"employeeNumber", OID_EMPLOYEE_NUMBER, ASN1_PRINTABLESTRING}, {"E", OID_EMAIL_ADDRESS, ASN1_IA5STRING}, {"Email", OID_EMAIL_ADDRESS, ASN1_IA5STRING}, {"emailAddress", OID_EMAIL_ADDRESS, ASN1_IA5STRING}, {"UN", OID_UNSTRUCTURED_NAME, ASN1_IA5STRING}, {"unstructuredName", OID_UNSTRUCTURED_NAME, ASN1_IA5STRING}, {"UA", OID_UNSTRUCTURED_ADDRESS, ASN1_PRINTABLESTRING}, {"unstructuredAddress", OID_UNSTRUCTURED_ADDRESS, ASN1_PRINTABLESTRING}, {"TCGID", OID_TCGID, ASN1_PRINTABLESTRING} }; /** * maximum number of RDNs in atodn() */ #define RDN_MAX 20 typedef struct private_identification_t private_identification_t; /** * Private data of an identification_t object. */ struct private_identification_t { /** * Public interface. */ identification_t public; /** * Encoded representation of this ID. */ chunk_t encoded; /** * Type of this ID. */ id_type_t type; }; /** * Enumerator over RDNs */ typedef struct { /* implements enumerator interface */ enumerator_t public; /* next set to parse, if any */ chunk_t sets; /* next sequence in set, if any */ chunk_t seqs; } rdn_enumerator_t; METHOD(enumerator_t, rdn_enumerate, bool, rdn_enumerator_t *this, chunk_t *oid, u_char *type, chunk_t *data) { chunk_t rdn; /* a DN contains one or more SET, each containing one or more SEQUENCES, * each containing a OID/value RDN */ if (!this->seqs.len) { /* no SEQUENCEs in current SET, parse next SET */ if (asn1_unwrap(&this->sets, &this->seqs) != ASN1_SET) { return FALSE; } } if (asn1_unwrap(&this->seqs, &rdn) == ASN1_SEQUENCE && asn1_unwrap(&rdn, oid) == ASN1_OID) { int t = asn1_unwrap(&rdn, data); if (t != ASN1_INVALID) { *type = t; return TRUE; } } return FALSE; } /** * Create an enumerator over all RDNs (oid, string type, data) of a DN */ static enumerator_t* create_rdn_enumerator(chunk_t dn) { rdn_enumerator_t *e; INIT(e, .public = { .enumerate = (void*)_rdn_enumerate, .destroy = (void*)free, }, ); /* a DN is a SEQUENCE, get the first SET of it */ if (asn1_unwrap(&dn, &e->sets) == ASN1_SEQUENCE) { e->seqs = chunk_empty; return &e->public; } free(e); return enumerator_create_empty(); } /** * Print a DN with all its RDN in a buffer to present it to the user */ void dntoa(chunk_t dn, STR *buf, size_t len) { enumerator_t *e; chunk_t oid_data, data, printable; u_char type; int oid, written; bool finished = FALSE, empty = TRUE; e = create_rdn_enumerator(dn); while (e->enumerate(e, &oid_data, &type, &data)) { empty = FALSE; oid = asn1_known_oid(oid_data); if (oid == OID_UNKNOWN) { written = snprintf(buf, len, "UNKNOWN-OID="); } else { written = snprintf(buf, len,"%" STRA "=", oid_names[oid].name); } if (written < 0 || written >= len) { break; } buf += written; len -= written; chunk_printable(data, &printable, '?'); written = snprintf(buf, len, "%.*" STRA, (int)printable.len, printable.ptr); chunk_free(&printable); if (written < 0 || written >= len) { break; } buf += written; len -= written; if (data.ptr + data.len != dn.ptr + dn.len) { written = snprintf(buf, len, ", "); if (written < 0 || written >= len) { break; } buf += written; len -= written; } else { finished = TRUE; break; } } if (empty) { snprintf(buf, len, ""); } else if (!finished) { snprintf(buf, len, "(invalid ID_DER_ASN1_DN)"); } e->destroy(e); } efitools-1.9.2/lib/asn1/identification.h000066400000000000000000000155061341522017100201240ustar00rootroot00000000000000/* * Copyright (C) 2009 Tobias Brunner * Copyright (C) 2005-2009 Martin Willi * Copyright (C) 2005 Jan Hutter * Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ /** * @defgroup identification identification * @{ @ingroup utils */ #ifndef IDENTIFICATION_H_ #define IDENTIFICATION_H_ typedef enum id_type_t id_type_t; typedef struct identification_t identification_t; typedef enum id_match_t id_match_t; typedef enum id_part_t id_part_t; #include "chunk.h" #include "enumerator.h" /** * Matches returned from identification_t.match */ enum id_match_t { /* no match */ ID_MATCH_NONE = 0, /* match to %any ID */ ID_MATCH_ANY = 1, /* match with maximum allowed wildcards */ ID_MATCH_MAX_WILDCARDS = 2, /* match with only one wildcard */ ID_MATCH_ONE_WILDCARD = 19, /* perfect match, won't get better */ ID_MATCH_PERFECT = 20, }; /** * ID Types in a ID payload. */ enum id_type_t { /** * private type which matches any other id. */ ID_ANY = 0, /** * ID data is a single four (4) octet IPv4 address. */ ID_IPV4_ADDR = 1, /** * ID data is a fully-qualified domain name string. * An example of a ID_FQDN is "example.com". * The string MUST not contain any terminators (e.g., NULL, CR, etc.). */ ID_FQDN = 2, /** * ID data is a fully-qualified RFC822 email address string. * An example of an ID_RFC822_ADDR is "jsmith@example.com". * The string MUST NOT contain any terminators. */ ID_USER_FQDN = 3, /* IKEv1 only */ ID_RFC822_ADDR = 3, /* IKEv2 only */ /** * ID data is an IPv4 subnet (IKEv1 only) */ ID_IPV4_ADDR_SUBNET = 4, /** * ID data is a single sixteen (16) octet IPv6 address. */ ID_IPV6_ADDR = 5, /** * ID data is an IPv6 subnet (IKEv1 only) */ ID_IPV6_ADDR_SUBNET = 6, /** * ID data is an IPv4 address range (IKEv1 only) */ ID_IPV4_ADDR_RANGE = 7, /** * ID data is an IPv6 address range (IKEv1 only) */ ID_IPV6_ADDR_RANGE = 8, /** * ID data is the binary DER encoding of an ASN.1 X.501 Distinguished Name */ ID_DER_ASN1_DN = 9, /** * ID data is the binary DER encoding of an ASN.1 X.509 GeneralName */ ID_DER_ASN1_GN = 10, /** * ID data is an opaque octet stream which may be used to pass vendor- * specific information necessary to do certain proprietary * types of identification. */ ID_KEY_ID = 11, /** * private type which represents a GeneralName of type URI */ ID_DER_ASN1_GN_URI = 201, /** * Private ID used by the pluto daemon for opportunistic encryption */ ID_MYID = 203, }; /** * Type of an ID sub part. */ enum id_part_t { /** Username part of an RFC822_ADDR */ ID_PART_USERNAME, /** Domain part of an RFC822_ADDR */ ID_PART_DOMAIN, /** Top-Level domain of a FQDN */ ID_PART_TLD, /** Second-Level domain of a FQDN */ ID_PART_SLD, /** Another Level domain of a FQDN */ ID_PART_ALD, /** Country RDN of a DN */ ID_PART_RDN_C, /** CommonName RDN of a DN */ ID_PART_RDN_CN, /** Description RDN of a DN */ ID_PART_RDN_D, /** Email RDN of a DN */ ID_PART_RDN_E, /** EmployeeNumber RDN of a DN */ ID_PART_RDN_EN, /** GivenName RDN of a DN */ ID_PART_RDN_G, /** Initials RDN of a DN */ ID_PART_RDN_I, /** DN Qualifier RDN of a DN */ ID_PART_RDN_DNQ, /** UniqueIdentifier RDN of a DN */ ID_PART_RDN_ID, /** Locality RDN of a DN */ ID_PART_RDN_L, /** Name RDN of a DN */ ID_PART_RDN_N, /** Organization RDN of a DN */ ID_PART_RDN_O, /** OrganizationUnit RDN of a DN */ ID_PART_RDN_OU, /** Surname RDN of a DN */ ID_PART_RDN_S, /** SerialNumber RDN of a DN */ ID_PART_RDN_SN, /** StateOrProvince RDN of a DN */ ID_PART_RDN_ST, /** Title RDN of a DN */ ID_PART_RDN_T, }; /** * Generic identification, such as used in ID payload. * * @todo Support for ID_DER_ASN1_GN is minimal right now. Comparison * between them and ID_IPV4_ADDR/RFC822_ADDR would be nice. */ struct identification_t { /** * Get the encoding of this id, to send over * the network. * * Result points to internal data, do not free. * * @return a chunk containing the encoded bytes */ chunk_t (*get_encoding) (identification_t *this); /** * Get the type of this identification. * * @return id_type_t */ id_type_t (*get_type) (identification_t *this); /** * Check if two identification_t objects are equal. * * @param other other identification_t object * @return TRUE if the IDs are equal */ bool (*equals) (identification_t *this, identification_t *other); /** * Check if an ID matches a wildcard ID. * * An identification_t may contain wildcards, such as * *.strongswan.org. This call checks if a given ID * (e.g. tester.strongswan.org) belongs to a such wildcard * ID. Returns > 0 if * - IDs are identical * - other is of type ID_ANY * - other contains a wildcard and matches this * * The larger the return value is, the better is the match. Zero means * no match at all, 1 means a bad match, and 2 a slightly better match. * * @param other the ID containing one or more wildcards * @param wildcards returns the number of wildcards, may be NULL * @return match value as described above */ id_match_t (*matches) (identification_t *this, identification_t *other); /** * Check if an ID is a wildcard ID. * * If the ID represents multiple IDs (with wildcards, or * as the type ID_ANY), TRUE is returned. If it is unique, * FALSE is returned. * * @return TRUE if ID contains wildcards */ bool (*contains_wildcards) (identification_t *this); /** * Create an enumerator over subparts of an identity. * * Some identities are built from several parts, e.g. an E-Mail consists * of a username and a domain part, or a DistinguishedName contains several * RDNs. * For identity without subtypes (support), an empty enumerator is * returned. * * @return an enumerator over (id_part_t type, chunk_t data) */ enumerator_t* (*create_part_enumerator)(identification_t *this); /** * Clone a identification_t instance. * * @return clone of this */ identification_t *(*clone) (identification_t *this); /** * Destroys a identification_t object. */ void (*destroy) (identification_t *this); }; /** * creates an ascii representation of a DN * * @param dn chunk pointing to DN * @param buf buffer to have string written to it * @param len length of buf */ void dntoa(chunk_t dn, STR *buf, size_t len); #endif /** IDENTIFICATION_H_ @}*/ efitools-1.9.2/lib/asn1/oid.c000066400000000000000000000755461341522017100157130ustar00rootroot00000000000000/* List of some useful object identifiers (OIDs) * Copyright (C) 2003-2008 Andreas Steffen, Hochschule fuer Technik Rapperswil * * This file has been automatically generated by the script oid.pl * Do not edit manually! */ #include #include "oid.h" const oid_t oid_names[] = { {0x02, 7, 1, 0, "ITU-T Administration" }, /* 0 */ { 0x82, 0, 1, 1, "" }, /* 1 */ { 0x06, 0, 1, 2, "Germany ITU-T member" }, /* 2 */ { 0x01, 0, 1, 3, "Deutsche Telekom AG" }, /* 3 */ { 0x0A, 0, 1, 4, "" }, /* 4 */ { 0x07, 0, 1, 5, "" }, /* 5 */ { 0x14, 0, 0, 6, "ND" }, /* 6 */ {0x09, 18, 1, 0, "data" }, /* 7 */ { 0x92, 0, 1, 1, "" }, /* 8 */ { 0x26, 0, 1, 2, "" }, /* 9 */ { 0x89, 0, 1, 3, "" }, /* 10 */ { 0x93, 0, 1, 4, "" }, /* 11 */ { 0xF2, 0, 1, 5, "" }, /* 12 */ { 0x2C, 0, 1, 6, "" }, /* 13 */ { 0x64, 0, 1, 7, "pilot" }, /* 14 */ { 0x01, 0, 1, 8, "pilotAttributeType" }, /* 15 */ { 0x01, 17, 0, 9, "UID" }, /* 16 */ { 0x19, 0, 0, 9, "DC" }, /* 17 */ {0x55, 65, 1, 0, "X.500" }, /* 18 */ { 0x04, 37, 1, 1, "X.509" }, /* 19 */ { 0x03, 21, 0, 2, "CN" }, /* 20 */ { 0x04, 22, 0, 2, "S" }, /* 21 */ { 0x05, 23, 0, 2, "SN" }, /* 22 */ { 0x06, 24, 0, 2, "C" }, /* 23 */ { 0x07, 25, 0, 2, "L" }, /* 24 */ { 0x08, 26, 0, 2, "ST" }, /* 25 */ { 0x0A, 27, 0, 2, "O" }, /* 26 */ { 0x0B, 28, 0, 2, "OU" }, /* 27 */ { 0x0C, 29, 0, 2, "T" }, /* 28 */ { 0x0D, 30, 0, 2, "D" }, /* 29 */ { 0x24, 31, 0, 2, "userCertificate" }, /* 30 */ { 0x29, 32, 0, 2, "N" }, /* 31 */ { 0x2A, 33, 0, 2, "G" }, /* 32 */ { 0x2B, 34, 0, 2, "I" }, /* 33 */ { 0x2D, 35, 0, 2, "ID" }, /* 34 */ { 0x2E, 36, 0, 2, "dnQualifier" }, /* 35 */ { 0x48, 0, 0, 2, "role" }, /* 36 */ { 0x1D, 0, 1, 1, "id-ce" }, /* 37 */ { 0x09, 39, 0, 2, "subjectDirectoryAttrs" }, /* 38 */ { 0x0E, 40, 0, 2, "subjectKeyIdentifier" }, /* 39 */ { 0x0F, 41, 0, 2, "keyUsage" }, /* 40 */ { 0x10, 42, 0, 2, "privateKeyUsagePeriod" }, /* 41 */ { 0x11, 43, 0, 2, "subjectAltName" }, /* 42 */ { 0x12, 44, 0, 2, "issuerAltName" }, /* 43 */ { 0x13, 45, 0, 2, "basicConstraints" }, /* 44 */ { 0x14, 46, 0, 2, "crlNumber" }, /* 45 */ { 0x15, 47, 0, 2, "reasonCode" }, /* 46 */ { 0x17, 48, 0, 2, "holdInstructionCode" }, /* 47 */ { 0x18, 49, 0, 2, "invalidityDate" }, /* 48 */ { 0x1B, 50, 0, 2, "deltaCrlIndicator" }, /* 49 */ { 0x1C, 51, 0, 2, "issuingDistributionPoint" }, /* 50 */ { 0x1D, 52, 0, 2, "certificateIssuer" }, /* 51 */ { 0x1E, 53, 0, 2, "nameConstraints" }, /* 52 */ { 0x1F, 54, 0, 2, "crlDistributionPoints" }, /* 53 */ { 0x20, 56, 1, 2, "certificatePolicies" }, /* 54 */ { 0x00, 0, 0, 3, "anyPolicy" }, /* 55 */ { 0x21, 57, 0, 2, "policyMappings" }, /* 56 */ { 0x23, 58, 0, 2, "authorityKeyIdentifier" }, /* 57 */ { 0x24, 59, 0, 2, "policyConstraints" }, /* 58 */ { 0x25, 61, 1, 2, "extendedKeyUsage" }, /* 59 */ { 0x00, 0, 0, 3, "anyExtendedKeyUsage" }, /* 60 */ { 0x2E, 62, 0, 2, "freshestCRL" }, /* 61 */ { 0x36, 63, 0, 2, "inhibitAnyPolicy" }, /* 62 */ { 0x37, 64, 0, 2, "targetInformation" }, /* 63 */ { 0x38, 0, 0, 2, "noRevAvail" }, /* 64 */ {0x2A, 169, 1, 0, "" }, /* 65 */ { 0x83, 78, 1, 1, "" }, /* 66 */ { 0x08, 0, 1, 2, "jp" }, /* 67 */ { 0x8C, 0, 1, 3, "" }, /* 68 */ { 0x9A, 0, 1, 4, "" }, /* 69 */ { 0x4B, 0, 1, 5, "" }, /* 70 */ { 0x3D, 0, 1, 6, "" }, /* 71 */ { 0x01, 0, 1, 7, "security" }, /* 72 */ { 0x01, 0, 1, 8, "algorithm" }, /* 73 */ { 0x01, 0, 1, 9, "symm-encryption-alg" }, /* 74 */ { 0x02, 76, 0, 10, "camellia128-cbc" }, /* 75 */ { 0x03, 77, 0, 10, "camellia192-cbc" }, /* 76 */ { 0x04, 0, 0, 10, "camellia256-cbc" }, /* 77 */ { 0x86, 0, 1, 1, "" }, /* 78 */ { 0x48, 0, 1, 2, "us" }, /* 79 */ { 0x86, 128, 1, 3, "" }, /* 80 */ { 0xF6, 86, 1, 4, "" }, /* 81 */ { 0x7D, 0, 1, 5, "NortelNetworks" }, /* 82 */ { 0x07, 0, 1, 6, "Entrust" }, /* 83 */ { 0x41, 0, 1, 7, "nsn-ce" }, /* 84 */ { 0x00, 0, 0, 8, "entrustVersInfo" }, /* 85 */ { 0xF7, 0, 1, 4, "" }, /* 86 */ { 0x0D, 0, 1, 5, "RSADSI" }, /* 87 */ { 0x01, 123, 1, 6, "PKCS" }, /* 88 */ { 0x01, 100, 1, 7, "PKCS-1" }, /* 89 */ { 0x01, 91, 0, 8, "rsaEncryption" }, /* 90 */ { 0x02, 92, 0, 8, "md2WithRSAEncryption" }, /* 91 */ { 0x04, 93, 0, 8, "md5WithRSAEncryption" }, /* 92 */ { 0x05, 94, 0, 8, "sha-1WithRSAEncryption" }, /* 93 */ { 0x07, 95, 0, 8, "id-RSAES-OAEP" }, /* 94 */ { 0x09, 96, 0, 8, "id-pSpecified" }, /* 95 */ { 0x0B, 97, 0, 8, "sha256WithRSAEncryption" }, /* 96 */ { 0x0C, 98, 0, 8, "sha384WithRSAEncryption" }, /* 97 */ { 0x0D, 99, 0, 8, "sha512WithRSAEncryption" }, /* 98 */ { 0x0E, 0, 0, 8, "sha224WithRSAEncryption" }, /* 99 */ { 0x05, 105, 1, 7, "PKCS-5" }, /* 100 */ { 0x03, 102, 0, 8, "pbeWithMD5AndDES-CBC" }, /* 101 */ { 0x0A, 103, 0, 8, "pbeWithSHA1AndDES-CBC" }, /* 102 */ { 0x0C, 104, 0, 8, "id-PBKDF2" }, /* 103 */ { 0x0D, 0, 0, 8, "id-PBES2" }, /* 104 */ { 0x07, 112, 1, 7, "PKCS-7" }, /* 105 */ { 0x01, 107, 0, 8, "data" }, /* 106 */ { 0x02, 108, 0, 8, "signedData" }, /* 107 */ { 0x03, 109, 0, 8, "envelopedData" }, /* 108 */ { 0x04, 110, 0, 8, "signedAndEnvelopedData" }, /* 109 */ { 0x05, 111, 0, 8, "digestedData" }, /* 110 */ { 0x06, 0, 0, 8, "encryptedData" }, /* 111 */ { 0x09, 0, 1, 7, "PKCS-9" }, /* 112 */ { 0x01, 114, 0, 8, "E" }, /* 113 */ { 0x02, 115, 0, 8, "unstructuredName" }, /* 114 */ { 0x03, 116, 0, 8, "contentType" }, /* 115 */ { 0x04, 117, 0, 8, "messageDigest" }, /* 116 */ { 0x05, 118, 0, 8, "signingTime" }, /* 117 */ { 0x06, 119, 0, 8, "counterSignature" }, /* 118 */ { 0x07, 120, 0, 8, "challengePassword" }, /* 119 */ { 0x08, 121, 0, 8, "unstructuredAddress" }, /* 120 */ { 0x0E, 122, 0, 8, "extensionRequest" }, /* 121 */ { 0x0F, 0, 0, 8, "S/MIME Capabilities" }, /* 122 */ { 0x02, 126, 1, 6, "digestAlgorithm" }, /* 123 */ { 0x02, 125, 0, 7, "md2" }, /* 124 */ { 0x05, 0, 0, 7, "md5" }, /* 125 */ { 0x03, 0, 1, 6, "encryptionAlgorithm" }, /* 126 */ { 0x07, 0, 0, 7, "3des-ede-cbc" }, /* 127 */ { 0xCE, 0, 1, 3, "" }, /* 128 */ { 0x3D, 0, 1, 4, "ansi-X9-62" }, /* 129 */ { 0x02, 132, 1, 5, "id-publicKeyType" }, /* 130 */ { 0x01, 0, 0, 6, "id-ecPublicKey" }, /* 131 */ { 0x03, 162, 1, 5, "ellipticCurve" }, /* 132 */ { 0x00, 154, 1, 6, "c-TwoCurve" }, /* 133 */ { 0x01, 135, 0, 7, "c2pnb163v1" }, /* 134 */ { 0x02, 136, 0, 7, "c2pnb163v2" }, /* 135 */ { 0x03, 137, 0, 7, "c2pnb163v3" }, /* 136 */ { 0x04, 138, 0, 7, "c2pnb176w1" }, /* 137 */ { 0x05, 139, 0, 7, "c2tnb191v1" }, /* 138 */ { 0x06, 140, 0, 7, "c2tnb191v2" }, /* 139 */ { 0x07, 141, 0, 7, "c2tnb191v3" }, /* 140 */ { 0x08, 142, 0, 7, "c2onb191v4" }, /* 141 */ { 0x09, 143, 0, 7, "c2onb191v5" }, /* 142 */ { 0x0A, 144, 0, 7, "c2pnb208w1" }, /* 143 */ { 0x0B, 145, 0, 7, "c2tnb239v1" }, /* 144 */ { 0x0C, 146, 0, 7, "c2tnb239v2" }, /* 145 */ { 0x0D, 147, 0, 7, "c2tnb239v3" }, /* 146 */ { 0x0E, 148, 0, 7, "c2onb239v4" }, /* 147 */ { 0x0F, 149, 0, 7, "c2onb239v5" }, /* 148 */ { 0x10, 150, 0, 7, "c2pnb272w1" }, /* 149 */ { 0x11, 151, 0, 7, "c2pnb304w1" }, /* 150 */ { 0x12, 152, 0, 7, "c2tnb359v1" }, /* 151 */ { 0x13, 153, 0, 7, "c2pnb368w1" }, /* 152 */ { 0x14, 0, 0, 7, "c2tnb431r1" }, /* 153 */ { 0x01, 0, 1, 6, "primeCurve" }, /* 154 */ { 0x01, 156, 0, 7, "prime192v1" }, /* 155 */ { 0x02, 157, 0, 7, "prime192v2" }, /* 156 */ { 0x03, 158, 0, 7, "prime192v3" }, /* 157 */ { 0x04, 159, 0, 7, "prime239v1" }, /* 158 */ { 0x05, 160, 0, 7, "prime239v2" }, /* 159 */ { 0x06, 161, 0, 7, "prime239v3" }, /* 160 */ { 0x07, 0, 0, 7, "prime256v1" }, /* 161 */ { 0x04, 0, 1, 5, "id-ecSigType" }, /* 162 */ { 0x01, 164, 0, 6, "ecdsa-with-SHA1" }, /* 163 */ { 0x03, 0, 1, 6, "ecdsa-with-Specified" }, /* 164 */ { 0x01, 166, 0, 7, "ecdsa-with-SHA224" }, /* 165 */ { 0x02, 167, 0, 7, "ecdsa-with-SHA256" }, /* 166 */ { 0x03, 168, 0, 7, "ecdsa-with-SHA384" }, /* 167 */ { 0x04, 0, 0, 7, "ecdsa-with-SHA512" }, /* 168 */ {0x2B, 323, 1, 0, "" }, /* 169 */ { 0x06, 237, 1, 1, "dod" }, /* 170 */ { 0x01, 0, 1, 2, "internet" }, /* 171 */ { 0x04, 194, 1, 3, "private" }, /* 172 */ { 0x01, 0, 1, 4, "enterprise" }, /* 173 */ { 0x82, 187, 1, 5, "" }, /* 174 */ { 0x37, 184, 1, 6, "Microsoft" }, /* 175 */ { 0x0A, 180, 1, 7, "" }, /* 176 */ { 0x03, 0, 1, 8, "" }, /* 177 */ { 0x03, 179, 0, 9, "msSGC" }, /* 178 */ { 0x04, 0, 0, 9, "msEncryptingFileSystem" }, /* 179 */ { 0x14, 0, 1, 7, "msEnrollmentInfrastructure"}, /* 180 */ { 0x02, 0, 1, 8, "msCertificateTypeExtension"}, /* 181 */ { 0x02, 183, 0, 9, "msSmartcardLogon" }, /* 182 */ { 0x03, 0, 0, 9, "msUPN" }, /* 183 */ { 0xA0, 0, 1, 6, "" }, /* 184 */ { 0x2A, 0, 1, 7, "ITA" }, /* 185 */ { 0x01, 0, 0, 8, "strongSwan" }, /* 186 */ { 0x89, 0, 1, 5, "" }, /* 187 */ { 0x31, 0, 1, 6, "" }, /* 188 */ { 0x01, 0, 1, 7, "" }, /* 189 */ { 0x01, 0, 1, 8, "" }, /* 190 */ { 0x02, 0, 1, 9, "" }, /* 191 */ { 0x02, 0, 1, 10, "" }, /* 192 */ { 0x4B, 0, 0, 11, "TCGID" }, /* 193 */ { 0x05, 0, 1, 3, "security" }, /* 194 */ { 0x05, 0, 1, 4, "mechanisms" }, /* 195 */ { 0x07, 234, 1, 5, "id-pkix" }, /* 196 */ { 0x01, 201, 1, 6, "id-pe" }, /* 197 */ { 0x01, 199, 0, 7, "authorityInfoAccess" }, /* 198 */ { 0x03, 200, 0, 7, "qcStatements" }, /* 199 */ { 0x07, 0, 0, 7, "ipAddrBlocks" }, /* 200 */ { 0x02, 204, 1, 6, "id-qt" }, /* 201 */ { 0x01, 203, 0, 7, "cps" }, /* 202 */ { 0x02, 0, 0, 7, "unotice" }, /* 203 */ { 0x03, 214, 1, 6, "id-kp" }, /* 204 */ { 0x01, 206, 0, 7, "serverAuth" }, /* 205 */ { 0x02, 207, 0, 7, "clientAuth" }, /* 206 */ { 0x03, 208, 0, 7, "codeSigning" }, /* 207 */ { 0x04, 209, 0, 7, "emailProtection" }, /* 208 */ { 0x05, 210, 0, 7, "ipsecEndSystem" }, /* 209 */ { 0x06, 211, 0, 7, "ipsecTunnel" }, /* 210 */ { 0x07, 212, 0, 7, "ipsecUser" }, /* 211 */ { 0x08, 213, 0, 7, "timeStamping" }, /* 212 */ { 0x09, 0, 0, 7, "ocspSigning" }, /* 213 */ { 0x08, 216, 1, 6, "id-otherNames" }, /* 214 */ { 0x05, 0, 0, 7, "xmppAddr" }, /* 215 */ { 0x0A, 221, 1, 6, "id-aca" }, /* 216 */ { 0x01, 218, 0, 7, "authenticationInfo" }, /* 217 */ { 0x02, 219, 0, 7, "accessIdentity" }, /* 218 */ { 0x03, 220, 0, 7, "chargingIdentity" }, /* 219 */ { 0x04, 0, 0, 7, "group" }, /* 220 */ { 0x0B, 222, 0, 6, "subjectInfoAccess" }, /* 221 */ { 0x30, 0, 1, 6, "id-ad" }, /* 222 */ { 0x01, 231, 1, 7, "ocsp" }, /* 223 */ { 0x01, 225, 0, 8, "basic" }, /* 224 */ { 0x02, 226, 0, 8, "nonce" }, /* 225 */ { 0x03, 227, 0, 8, "crl" }, /* 226 */ { 0x04, 228, 0, 8, "response" }, /* 227 */ { 0x05, 229, 0, 8, "noCheck" }, /* 228 */ { 0x06, 230, 0, 8, "archiveCutoff" }, /* 229 */ { 0x07, 0, 0, 8, "serviceLocator" }, /* 230 */ { 0x02, 232, 0, 7, "caIssuers" }, /* 231 */ { 0x03, 233, 0, 7, "timeStamping" }, /* 232 */ { 0x05, 0, 0, 7, "caRepository" }, /* 233 */ { 0x08, 0, 1, 5, "ipsec" }, /* 234 */ { 0x02, 0, 1, 6, "certificate" }, /* 235 */ { 0x02, 0, 0, 7, "iKEIntermediate" }, /* 236 */ { 0x0E, 243, 1, 1, "oiw" }, /* 237 */ { 0x03, 0, 1, 2, "secsig" }, /* 238 */ { 0x02, 0, 1, 3, "algorithms" }, /* 239 */ { 0x07, 241, 0, 4, "des-cbc" }, /* 240 */ { 0x1A, 242, 0, 4, "sha-1" }, /* 241 */ { 0x1D, 0, 0, 4, "sha-1WithRSASignature" }, /* 242 */ { 0x24, 289, 1, 1, "TeleTrusT" }, /* 243 */ { 0x03, 0, 1, 2, "algorithm" }, /* 244 */ { 0x03, 0, 1, 3, "signatureAlgorithm" }, /* 245 */ { 0x01, 250, 1, 4, "rsaSignature" }, /* 246 */ { 0x02, 248, 0, 5, "rsaSigWithripemd160" }, /* 247 */ { 0x03, 249, 0, 5, "rsaSigWithripemd128" }, /* 248 */ { 0x04, 0, 0, 5, "rsaSigWithripemd256" }, /* 249 */ { 0x02, 0, 1, 4, "ecSign" }, /* 250 */ { 0x01, 252, 0, 5, "ecSignWithsha1" }, /* 251 */ { 0x02, 253, 0, 5, "ecSignWithripemd160" }, /* 252 */ { 0x03, 254, 0, 5, "ecSignWithmd2" }, /* 253 */ { 0x04, 255, 0, 5, "ecSignWithmd5" }, /* 254 */ { 0x05, 272, 1, 5, "ttt-ecg" }, /* 255 */ { 0x01, 260, 1, 6, "fieldType" }, /* 256 */ { 0x01, 0, 1, 7, "characteristictwoField" }, /* 257 */ { 0x01, 0, 1, 8, "basisType" }, /* 258 */ { 0x01, 0, 0, 9, "ipBasis" }, /* 259 */ { 0x02, 262, 1, 6, "keyType" }, /* 260 */ { 0x01, 0, 0, 7, "ecgPublicKey" }, /* 261 */ { 0x03, 263, 0, 6, "curve" }, /* 262 */ { 0x04, 270, 1, 6, "signatures" }, /* 263 */ { 0x01, 265, 0, 7, "ecgdsa-with-RIPEMD160" }, /* 264 */ { 0x02, 266, 0, 7, "ecgdsa-with-SHA1" }, /* 265 */ { 0x03, 267, 0, 7, "ecgdsa-with-SHA224" }, /* 266 */ { 0x04, 268, 0, 7, "ecgdsa-with-SHA256" }, /* 267 */ { 0x05, 269, 0, 7, "ecgdsa-with-SHA384" }, /* 268 */ { 0x06, 0, 0, 7, "ecgdsa-with-SHA512" }, /* 269 */ { 0x05, 0, 1, 6, "module" }, /* 270 */ { 0x01, 0, 0, 7, "1" }, /* 271 */ { 0x08, 0, 1, 5, "ecStdCurvesAndGeneration" }, /* 272 */ { 0x01, 0, 1, 6, "ellipticCurve" }, /* 273 */ { 0x01, 0, 1, 7, "versionOne" }, /* 274 */ { 0x01, 276, 0, 8, "brainpoolP160r1" }, /* 275 */ { 0x02, 277, 0, 8, "brainpoolP160t1" }, /* 276 */ { 0x03, 278, 0, 8, "brainpoolP192r1" }, /* 277 */ { 0x04, 279, 0, 8, "brainpoolP192t1" }, /* 278 */ { 0x05, 280, 0, 8, "brainpoolP224r1" }, /* 279 */ { 0x06, 281, 0, 8, "brainpoolP224t1" }, /* 280 */ { 0x07, 282, 0, 8, "brainpoolP256r1" }, /* 281 */ { 0x08, 283, 0, 8, "brainpoolP256t1" }, /* 282 */ { 0x09, 284, 0, 8, "brainpoolP320r1" }, /* 283 */ { 0x0A, 285, 0, 8, "brainpoolP320t1" }, /* 284 */ { 0x0B, 286, 0, 8, "brainpoolP384r1" }, /* 285 */ { 0x0C, 287, 0, 8, "brainpoolP384t1" }, /* 286 */ { 0x0D, 288, 0, 8, "brainpoolP512r1" }, /* 287 */ { 0x0E, 0, 0, 8, "brainpoolP512t1" }, /* 288 */ { 0x81, 0, 1, 1, "" }, /* 289 */ { 0x04, 0, 1, 2, "Certicom" }, /* 290 */ { 0x00, 0, 1, 3, "curve" }, /* 291 */ { 0x01, 293, 0, 4, "sect163k1" }, /* 292 */ { 0x02, 294, 0, 4, "sect163r1" }, /* 293 */ { 0x03, 295, 0, 4, "sect239k1" }, /* 294 */ { 0x04, 296, 0, 4, "sect113r1" }, /* 295 */ { 0x05, 297, 0, 4, "sect113r2" }, /* 296 */ { 0x06, 298, 0, 4, "secp112r1" }, /* 297 */ { 0x07, 299, 0, 4, "secp112r2" }, /* 298 */ { 0x08, 300, 0, 4, "secp160r1" }, /* 299 */ { 0x09, 301, 0, 4, "secp160k1" }, /* 300 */ { 0x0A, 302, 0, 4, "secp256k1" }, /* 301 */ { 0x0F, 303, 0, 4, "sect163r2" }, /* 302 */ { 0x10, 304, 0, 4, "sect283k1" }, /* 303 */ { 0x11, 305, 0, 4, "sect283r1" }, /* 304 */ { 0x16, 306, 0, 4, "sect131r1" }, /* 305 */ { 0x17, 307, 0, 4, "sect131r2" }, /* 306 */ { 0x18, 308, 0, 4, "sect193r1" }, /* 307 */ { 0x19, 309, 0, 4, "sect193r2" }, /* 308 */ { 0x1A, 310, 0, 4, "sect233k1" }, /* 309 */ { 0x1B, 311, 0, 4, "sect233r1" }, /* 310 */ { 0x1C, 312, 0, 4, "secp128r1" }, /* 311 */ { 0x1D, 313, 0, 4, "secp128r2" }, /* 312 */ { 0x1E, 314, 0, 4, "secp160r2" }, /* 313 */ { 0x1F, 315, 0, 4, "secp192k1" }, /* 314 */ { 0x20, 316, 0, 4, "secp224k1" }, /* 315 */ { 0x21, 317, 0, 4, "secp224r1" }, /* 316 */ { 0x22, 318, 0, 4, "secp384r1" }, /* 317 */ { 0x23, 319, 0, 4, "secp521r1" }, /* 318 */ { 0x24, 320, 0, 4, "sect409k1" }, /* 319 */ { 0x25, 321, 0, 4, "sect409r1" }, /* 320 */ { 0x26, 322, 0, 4, "sect571k1" }, /* 321 */ { 0x27, 0, 0, 4, "sect571r1" }, /* 322 */ {0x60, 369, 1, 0, "" }, /* 323 */ { 0x86, 0, 1, 1, "" }, /* 324 */ { 0x48, 0, 1, 2, "" }, /* 325 */ { 0x01, 0, 1, 3, "organization" }, /* 326 */ { 0x65, 345, 1, 4, "gov" }, /* 327 */ { 0x03, 0, 1, 5, "csor" }, /* 328 */ { 0x04, 0, 1, 6, "nistalgorithm" }, /* 329 */ { 0x01, 340, 1, 7, "aes" }, /* 330 */ { 0x02, 332, 0, 8, "id-aes128-CBC" }, /* 331 */ { 0x06, 333, 0, 8, "id-aes128-GCM" }, /* 332 */ { 0x07, 334, 0, 8, "id-aes128-CCM" }, /* 333 */ { 0x16, 335, 0, 8, "id-aes192-CBC" }, /* 334 */ { 0x1A, 336, 0, 8, "id-aes192-GCM" }, /* 335 */ { 0x1B, 337, 0, 8, "id-aes192-CCM" }, /* 336 */ { 0x2A, 338, 0, 8, "id-aes256-CBC" }, /* 337 */ { 0x2E, 339, 0, 8, "id-aes256-GCM" }, /* 338 */ { 0x2F, 0, 0, 8, "id-aes256-CCM" }, /* 339 */ { 0x02, 0, 1, 7, "hashalgs" }, /* 340 */ { 0x01, 342, 0, 8, "id-SHA-256" }, /* 341 */ { 0x02, 343, 0, 8, "id-SHA-384" }, /* 342 */ { 0x03, 344, 0, 8, "id-SHA-512" }, /* 343 */ { 0x04, 0, 0, 8, "id-SHA-224" }, /* 344 */ { 0x86, 0, 1, 4, "" }, /* 345 */ { 0xf8, 0, 1, 5, "" }, /* 346 */ { 0x42, 359, 1, 6, "netscape" }, /* 347 */ { 0x01, 354, 1, 7, "" }, /* 348 */ { 0x01, 350, 0, 8, "nsCertType" }, /* 349 */ { 0x03, 351, 0, 8, "nsRevocationUrl" }, /* 350 */ { 0x04, 352, 0, 8, "nsCaRevocationUrl" }, /* 351 */ { 0x08, 353, 0, 8, "nsCaPolicyUrl" }, /* 352 */ { 0x0d, 0, 0, 8, "nsComment" }, /* 353 */ { 0x03, 357, 1, 7, "directory" }, /* 354 */ { 0x01, 0, 1, 8, "" }, /* 355 */ { 0x03, 0, 0, 9, "employeeNumber" }, /* 356 */ { 0x04, 0, 1, 7, "policy" }, /* 357 */ { 0x01, 0, 0, 8, "nsSGC" }, /* 358 */ { 0x45, 0, 1, 6, "verisign" }, /* 359 */ { 0x01, 0, 1, 7, "pki" }, /* 360 */ { 0x09, 0, 1, 8, "attributes" }, /* 361 */ { 0x02, 363, 0, 9, "messageType" }, /* 362 */ { 0x03, 364, 0, 9, "pkiStatus" }, /* 363 */ { 0x04, 365, 0, 9, "failInfo" }, /* 364 */ { 0x05, 366, 0, 9, "senderNonce" }, /* 365 */ { 0x06, 367, 0, 9, "recipientNonce" }, /* 366 */ { 0x07, 368, 0, 9, "transID" }, /* 367 */ { 0x08, 0, 0, 9, "extensionReq" }, /* 368 */ {0x67, 0, 1, 0, "" }, /* 369 */ { 0x81, 0, 1, 1, "" }, /* 370 */ { 0x05, 0, 1, 2, "" }, /* 371 */ { 0x02, 0, 1, 3, "tcg-attribute" }, /* 372 */ { 0x01, 374, 0, 4, "tcg-at-tpmManufacturer" }, /* 373 */ { 0x02, 375, 0, 4, "tcg-at-tpmModel" }, /* 374 */ { 0x03, 376, 0, 4, "tcg-at-tpmVersion" }, /* 375 */ { 0x0F, 0, 0, 4, "tcg-at-tpmIdLabel" } /* 376 */ }; efitools-1.9.2/lib/asn1/oid.h000066400000000000000000000157561341522017100157150ustar00rootroot00000000000000/* 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! */ #include #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_ */ efitools-1.9.2/lib/asn1/oid.pl000066400000000000000000000062261341522017100160710ustar00rootroot00000000000000#!/usr/bin/perl # Generates oid.h and oid.c out of oid.txt # # Copyright (C) 2003-2008 Andreas Steffen # Hochschule fuer Technik Rapperswil # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2 of the License, or (at your # option) any later version. See . # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # $copyright="Copyright (C) 2003-2008 Andreas Steffen, Hochschule fuer Technik Rapperswil"; $automatic="This file has been automatically generated by the script oid.pl"; $warning="Do not edit manually!"; print "oid.pl generating oid.h and oid.c\n"; # Generate oid.h open(OID_H, ">oid.h") or die "could not open 'oid.h': $!"; print OID_H "/* Object identifiers (OIDs) used by strongSwan\n", " * ", $copyright, "\n", " * \n", " * ", $automatic, "\n", " * ", $warning, "\n", " */\n\n", "#include \n\n", "#ifndef OID_H_\n", "#define OID_H_\n\n", "typedef struct {\n", " u_char octet;\n", " u_int next;\n", " u_int down;\n", " u_int level;\n", " const u_char *name;\n", "} oid_t;\n", "\n", "extern const oid_t oid_names[];\n", "\n", "#define OID_UNKNOWN -1\n"; # parse oid.txt open(SRC, ") { $line =~ m/( *?)(0x\w{2})\s+(".*?")[ \t]*?([\w_]*?)\Z/; @order[$counter] = length($1); @octet[$counter] = $2; @name[$counter] = $3; if (length($1) > $max_order) { $max_order = length($1); } if (length($3) > $max_name) { $max_name = length($3); } if (length($4) > 0) { printf OID_H "#define %s%s%d\n", $4, "\t" x ((39-length($4))/4), $counter; } $counter++; } printf OID_H "\n#define OID_MAX%s%d\n", "\t" x 8, $counter; print OID_H "\n#endif /* OID_H_ */\n"; close SRC; close OID_H; # Generate oid.c open(OID_C, ">oid.c") or die "could not open 'oid.c': $!"; print OID_C "/* List of some useful object identifiers (OIDs)\n", " * ", $copyright, "\n", " * \n", " * ", $automatic, "\n", " * ", $warning, "\n", " */\n", "\n", "#include \n", "\n", "#include \"oid.h\"\n", "\n", "const oid_t oid_names[] = {\n"; for ($c = 0; $c < $counter; $c++) { $next = 0; for ($d = $c+1; $d < $counter && @order[$d] >= @order[$c]; $d++) { if (@order[$d] == @order[$c]) { @next[$c] = $d; last; } } printf OID_C " {%s%s,%s%3d, %d, %2d, %s%s}%s /* %3d */\n" ,' ' x @order[$c] , @octet[$c] , ' ' x (1 + $max_order - @order[$c]) , @next[$c] , @order[$c+1] > @order[$c] , @order[$c] / 2 , @name[$c] , ' ' x ($max_name - length(@name[$c])) , $c != $counter-1 ? "," : " " , $c; } print OID_C "};\n" ; close OID_C; efitools-1.9.2/lib/asn1/oid.txt000066400000000000000000000465371341522017100163060ustar00rootroot000000000000000x02 "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 efitools-1.9.2/lib/asn1/test.c000066400000000000000000000010571341522017100161010ustar00rootroot00000000000000#include "typedefs.h" #include #include int main(int argc, char *argv[]) { void *buf; int fd; struct stat st; char out[512]; fd = open(argv[1], O_RDONLY); if (fd<0) { fprintf(stderr, "Failed to open file %s\n", argv[1]); perror(""); exit(1); } fstat(fd, &st); buf = malloc(st.st_size); read(fd, buf, st.st_size); x509_to_str(buf, st.st_size, X509_OBJ_SUBJECT, out, sizeof(out)); printf("Subject: %s\n", out); x509_to_str(buf, st.st_size, X509_OBJ_ISSUER, out, sizeof(out)); printf("Issuer: %s\n", out); exit(0); } efitools-1.9.2/lib/asn1/typedefs.h000066400000000000000000000052371341522017100167560ustar00rootroot00000000000000#ifdef BUILD_EFI #include #include #define malloc(x) AllocatePool(x) #define free FreePool #define strcmp(x,y) StrCmp(x,y) #define memset(m,c,l) ZeroMem(m,l) #define memcmp(x,y,z) strncmpa(x,y,z) #define isprint(x) (1) #define snprintf(s, l, f...) SPrint(s, l, L ## f) /* STR is the native string and STRA is how to printf and ASCII string */ #define STR CHAR16 #define STRA "a" #define size_t UINTN static inline void MEMCPY(void *dest, void *src, size_t n) { UINTN i; char *d = dest, *s = src; for (i = 0; i < n; i++) d[i] = s[i]; } #define memcpy MEMCPY typedef unsigned char u_char; #else #include #include #include #include #include #include #include #include #include #include #include #include #define STR char #define STRA "s" #define FALSE 0 #define TRUE 1 #endif typedef unsigned char bool; typedef unsigned int u_int; #define DBG1(s...) #define DBG2(s...) /** * Method declaration/definition macro, providing private and public interface. * * Defines a method name with this as first parameter and a return value ret, * and an alias for this method with a _ prefix, having the this argument * safely casted to the public interface iface. * _name is provided a function pointer, but will get optimized out by GCC. */ #define METHOD(iface, name, ret, this, ...) \ static ret name(union {iface *_public; this;} \ __attribute__((transparent_union)), ##__VA_ARGS__); \ static typeof(name) *_##name = (typeof(name)*)name; \ static ret name(this, ##__VA_ARGS__) /** * Object allocation/initialization macro, using designated initializer. */ #define INIT(this, ...) { (this) = malloc(sizeof(*(this))); \ *(this) = (typeof(*(this))){ __VA_ARGS__ }; } /** * Macro to allocate a sized type. */ #define malloc_thing(thing) ((thing*)malloc(sizeof(thing))) /** * Get the number of elements in an array */ #define countof(array) (sizeof(array)/sizeof(array[0])) /** * Helper function that compares two strings for equality */ static inline bool streq(STR *x, STR *y) { return strcmp(x, y) == 0; } /** * Macro compares two binary blobs for equality */ #define memeq(x,y,len) (memcmp(x, y, len) == 0) /** * Call destructor of an object, if object != NULL */ #define DESTROY_IF(obj) if (obj) (obj)->destroy(obj) /** * Macro gives back smaller of two values. */ #define min(x,y) ({ \ typeof(x) _x = (x); \ typeof(y) _y = (y); \ _x < _y ? _x : _y; }) #define TIME_32_BIT_SIGNED_MAX 0x7fffffff #define BUF_LEN 512 efitools-1.9.2/lib/asn1/x509.c000066400000000000000000000044551341522017100156340ustar00rootroot00000000000000#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; } efitools-1.9.2/lib/configtable.c000066400000000000000000000110011341522017100165230ustar00rootroot00000000000000/* * Copyright 2013 * * see COPYING file * * read some platform configuration tables */ #include #include #include #include void * configtable_get_table(EFI_GUID *guid) { int i; for (i = 0; i < ST->NumberOfTableEntries; i++) { EFI_CONFIGURATION_TABLE *CT = &ST->ConfigurationTable[i]; if (CompareGuid(guid, &CT->VendorGuid) == 0) { return CT->VendorTable; } } return NULL; } EFI_IMAGE_EXECUTION_INFO_TABLE * configtable_get_image_table(void) { return configtable_get_table(&SIG_DB); } EFI_IMAGE_EXECUTION_INFO * configtable_find_image(const EFI_DEVICE_PATH *DevicePath) { EFI_IMAGE_EXECUTION_INFO_TABLE *t = configtable_get_image_table(); if (!t) return NULL; int entries = t->NumberOfImages; EFI_IMAGE_EXECUTION_INFO *e = t->InformationInfo; int i; for (i = 0; i < entries; i++) { #ifdef DEBUG_CONFIG Print(L"InfoSize = %d Action = %d\n", e->InfoSize, e->Action); /* print what we have for debugging */ UINT8 *d = (UINT8 *)e; // + sizeof(UINT32)*2; Print(L"Data: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]); d += 16; Print(L"Data: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]); d += 16; Print(L"Data: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]); d += 16; Print(L"Data: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]); d += 16; Print(L"Data: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]); d += 16; Print(L"Data: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]); #endif CHAR16 *name = (CHAR16 *)(e->Data); int skip = 0; /* There's a bug in a lot of EFI platforms and they forget to * put the name here. The only real way of detecting it is to * look for either a UC16 NULL or ASCII as UC16 */ if (name[0] == '\0' || (e->Data[1] == 0 && e->Data[3] == 0)) { skip = StrSize(name); #ifdef DEBUG_CONFIG Print(L"FOUND NAME %s (%d)\n", name, skip); #endif } EFI_DEVICE_PATH *dp = (EFI_DEVICE_PATH *)(e->Data + skip), *dpn = dp; if (dp->Type == 0 || dp->Type > 6 || dp->SubType == 0 || (((dp->Length[1] << 8) + dp->Length[0]) > e->InfoSize)) { /* Parse error, table corrupt, bail */ Print(L"Image Execution Information table corrupt\n"); break; } UINTN Size; DevicePathInstance(&dpn, &Size); #ifdef DEBUG_CONFIG Print(L"Path: %s\n", DevicePathToStr(dp)); Print(L"Device Path Size %d\n", Size); #endif if (Size > e->InfoSize) { /* parse error; the platform obviously has a * corrupted image table; bail */ Print(L"Image Execution Information table corrupt\n"); break; } if (CompareMem(dp, DevicePath, Size) == 0) { #ifdef DEBUG_CONFIG Print(L"***FOUND\n"); console_get_keystroke(); #endif return e; } e = (EFI_IMAGE_EXECUTION_INFO *)((UINT8 *)e + e->InfoSize); } #ifdef DEBUG_CONFIG Print(L"***NOT FOUND\n"); console_get_keystroke(); #endif return NULL; } int configtable_image_is_forbidden(const EFI_DEVICE_PATH *DevicePath) { EFI_IMAGE_EXECUTION_INFO *e = configtable_find_image(DevicePath); /* Image may not be in DB if it gets executed successfully If it is, * and EFI_IMAGE_EXECUTION_INITIALIZED is not set, then the image * isn't authenticated. If there's no signature, usually * EFI_IMAGE_EXECUTION_AUTH_UNTESTED is set, if the hash is in dbx, * EFI_IMAGE_EXECUTION_AUTH_SIG_FOUND is returned, and if the key is * in dbx, EFI_IMAGE_EXECUTION_AUTH_SIG_FAILED is returned*/ if (e && (e->Action == EFI_IMAGE_EXECUTION_AUTH_SIG_FOUND || e->Action == EFI_IMAGE_EXECUTION_AUTH_SIG_FAILED)) { /* this means the images signing key is in dbx */ #ifdef DEBUG_CONFIG Print(L"SIGNATURE IS IN DBX, FORBIDDING EXECUTION\n"); #endif return 1; } return 0; } efitools-1.9.2/lib/console.c000066400000000000000000000231401341522017100157170ustar00rootroot00000000000000/* * Copyright 2012 * * see COPYING file */ #include #include #include #include static int min(int a, int b) { if (a < b) return a; return b; } static int count_lines(CHAR16 *str_arr[]) { int i = 0; while (str_arr[i]) i++; return i; } static void SetMem16(CHAR16 *dst, UINT32 n, CHAR16 c) { int i; for (i = 0; i < n/2; i++) { dst[i] = c; } } EFI_INPUT_KEY console_get_keystroke(void) { EFI_INPUT_KEY key; UINTN EventIndex; BS->WaitForEvent(1, &ST->ConIn->WaitForKey, &EventIndex); ST->ConIn->ReadKeyStroke(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 = ST->ConIn->ReadKeyStroke(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; co->QueryMode(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'; co->SetCursorPosition(co, start_col, start_row); co->OutputString(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) co->SetAttribute(co, EFI_LIGHTGRAY | EFI_BACKGROUND_BLACK); co->SetCursorPosition(co, start_col, i); co->OutputString(co, Line); if (line >= 0 && line == highlight) co->SetAttribute(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'; co->SetCursorPosition(co, start_col, i); co->OutputString(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)); co->EnableCursor(co, FALSE); co->SetAttribute(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(); co->EnableCursor(co, SavedConsoleMode.CursorVisible); co->EnableCursor(co, SavedConsoleMode.CursorVisible); co->SetCursorPosition(co, SavedConsoleMode.CursorColumn, SavedConsoleMode.CursorRow); co->SetAttribute(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; int title_lines = count_lines(title); UINTN cols, rows; co->QueryMode(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 - 6 - title_lines) { offs_row = title_lines + 2; size_rows = rows - 4 - title_lines; lines = size_rows - 2; } else { offs_row = (rows + title_lines - 1 - selector_lines)/2; 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)); co->EnableCursor(co, FALSE); co->SetAttribute(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)); co->EnableCursor(co, SavedConsoleMode.CursorVisible); co->EnableCursor(co, SavedConsoleMode.CursorVisible); co->SetCursorPosition(co, SavedConsoleMode.CursorColumn, SavedConsoleMode.CursorRow); co->SetAttribute(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; co->Reset(co, TRUE); /* set mode 0 - required to be 80x25 */ co->SetMode(co, 0); co->ClearScreen(co); } efitools-1.9.2/lib/execute.c000066400000000000000000000062211341522017100157200ustar00rootroot00000000000000/* * Copyright 2012 * * see COPYING file * * -- * * generate_path is a cut and paste from * * git://github.com/mjg59/shim.git * * Code Copyright 2012 Red Hat, Inc * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the * distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include #include EFI_STATUS generate_path(CHAR16* name, EFI_LOADED_IMAGE *li, EFI_DEVICE_PATH **path, CHAR16 **PathName) { unsigned int pathlen; EFI_STATUS efi_status = EFI_SUCCESS; CHAR16 *devpathstr = DevicePathToStr(li->FilePath), *found = NULL; int i; for (i = 0; i < StrLen(devpathstr); i++) { if (devpathstr[i] == '/') devpathstr[i] = '\\'; if (devpathstr[i] == '\\') found = &devpathstr[i]; } if (!found) { pathlen = 0; } else { while (*(found - 1) == '\\') --found; *found = '\0'; pathlen = StrLen(devpathstr); } if (name[0] != '\\') pathlen++; *PathName = AllocatePool((pathlen + 1 + StrLen(name))*sizeof(CHAR16)); if (!*PathName) { Print(L"Failed to allocate path buffer\n"); efi_status = EFI_OUT_OF_RESOURCES; goto error; } StrCpy(*PathName, devpathstr); if (name[0] != '\\') StrCat(*PathName, L"\\"); StrCat(*PathName, name); *path = FileDevicePath(li->DeviceHandle, *PathName); error: FreePool(devpathstr); return efi_status; } EFI_STATUS execute(EFI_HANDLE image, CHAR16 *name) { EFI_STATUS status; EFI_HANDLE h; EFI_LOADED_IMAGE *li; EFI_DEVICE_PATH *devpath; CHAR16 *PathName; status = BS->HandleProtocol(image, &IMAGE_PROTOCOL, (VOID **)&li); if (status != EFI_SUCCESS) return status; status = generate_path(name, li, &devpath, &PathName); if (status != EFI_SUCCESS) return status; status = BS->LoadImage(FALSE, image, devpath, NULL, 0, &h); if (status != EFI_SUCCESS) goto out; status = BS->StartImage(h, NULL, NULL); BS->UnloadImage(h); out: FreePool(PathName); FreePool(devpath); return status; } efitools-1.9.2/lib/guid.c000066400000000000000000000065421341522017100152140ustar00rootroot00000000000000/* * Copyright 2012 * * see COPYING file */ #include #include #include #define ARRAY_SIZE(a) (sizeof (a) / sizeof ((a)[0])) #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)); } EFI_GUID * get_owner_guid(char *var) { char *variables[] = { "PK", "KEK", "db", "dbx", "dbt", "MokList" }; EFI_GUID *owners[] = { &GV_GUID, &GV_GUID, &SIG_DB, &SIG_DB, &SIG_DB, &MOK_OWNER }; EFI_GUID *owner = NULL; int i; for(i = 0; i < ARRAY_SIZE(variables); i++) { if (strcmp(var, variables[i]) == 0) { owner = owners[i]; break; } } return owner; } #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 } }; EFI_GUID SECURE_VARIABLE_GUID = { 0xaaf32c78, 0x947b, 0x439a, { 0xa1, 0x80, 0x2e, 0x14, 0x4e, 0xc3, 0x77, 0x92 } }; EFI_GUID PKCS7_VERIFY_PROTOCOL_GUID = { 0x47889fb2, 0xd671, 0x4fab, {0xa0, 0xca, 0xdf, 0x0e, 0x44, 0xdf, 0x70, 0xd6 } }; EFI_GUID EFI_CERT_SHA1_GUID = { 0x826ca512, 0xcf10, 0x4ac9, { 0xb1, 0x87, 0xbe, 0x01, 0x49, 0x66, 0x31, 0xbd } }; EFI_GUID EFI_CERT_SHA224_GUID = { 0xb6e5233, 0xa65c, 0x44c9, {0x94, 0x07, 0xd9, 0xab, 0x83, 0xbf, 0xc8, 0xbd} }; EFI_GUID EFI_CERT_SHA384_GUID = { 0xff3e5307, 0x9fd0, 0x48c9, {0x85, 0xf1, 0x8a, 0xd5, 0x6c, 0x70, 0x1e, 0x01}}; EFI_GUID EFI_CERT_SHA512_GUID = { 0x93e0fae, 0xa6c4, 0x4f50, {0x9f, 0x1b, 0xd4, 0x1e, 0x2b, 0x89, 0xc1, 0x9a} }; EFI_GUID *allowed_hashes[] = { &EFI_CERT_SHA1_GUID, &EFI_CERT_SHA224_GUID, &EFI_CERT_SHA256_GUID, &EFI_CERT_SHA384_GUID, &EFI_CERT_SHA512_GUID, }; UINTN allowed_hashes_size = ARRAY_SIZE(allowed_hashes); efitools-1.9.2/lib/kernel_efivars.c000066400000000000000000000133271341522017100172620ustar00rootroot00000000000000/* * Copyright 2013 * * see COPYING file */ #include #include #include #include #include #include #include #include #include #include #include #include #define __STDC_VERSION__ 199901L #include #include #include #include #include "efiauthenticated.h" static char *kernel_efi_path = NULL; void kernel_variable_init(void) { char fname[] = "/tmp/efi.XXXXXX"; char cmdline[256]; int fd, ret; struct stat st; char *buf; if (kernel_efi_path) return; mktemp(fname); snprintf(cmdline, sizeof(cmdline), "mount -l > %s", fname); ret = system(cmdline); if (WEXITSTATUS(ret) != 0) /* hopefully stderr said what was wrong */ exit(1); fd = open(fname, O_RDONLY); unlink(fname); if (fd < 0) { fprintf(stderr, "Failed to open output of %s\n", cmdline); exit(1); } if (fstat(fd, &st) < 0) { perror("stat failed"); exit(1); } if (st.st_size == 0) { fprintf(stderr, "No efivarfs filesystem is mounted\n"); exit(1); } buf = malloc(st.st_size); read(fd, buf, st.st_size); close(fd); char *ptr = buf; char path[512], type[512]; while (ptr < buf + st.st_size) { int count; sscanf(ptr, "%*s on %s type %s %*[^\n]\n%n", path, type, &count); ptr += count; if (strcmp(type, "efivarfs") == 0) break; } if (strcmp(type, "efivarfs") != 0) { fprintf(stderr, "No efivarfs filesystem is mounted\n"); exit(1); } kernel_efi_path = malloc(strlen(path) + 1); strcpy(kernel_efi_path, path); } int get_variable(const char *var, EFI_GUID *guid, uint32_t *attributes, uint32_t *size, void *buf) { if (!kernel_efi_path) return -EINVAL; int varfs_len = strlen(var) + 48 + strlen(kernel_efi_path); char *varfs = malloc(varfs_len); uint32_t attr; int fd; struct stat st; snprintf(varfs, varfs_len, "%s/%s-%s", kernel_efi_path, var, guid_to_str(guid)); fd = open(varfs, O_RDONLY); free(varfs); if (fd < 0) return errno; if (fstat(fd, &st) < 0) return errno; if (size) *size = st.st_size - sizeof(attr); read(fd, &attr, sizeof(attr)); if (attributes) *attributes = attr; if (buf) read(fd, buf, st.st_size - sizeof(attr)); close(fd); return 0; } int get_variable_alloc(const char *var, EFI_GUID *guid, uint32_t *attributes, uint32_t *size, uint8_t **buf) { uint32_t len; int ret = get_variable(var, guid, NULL, &len, NULL); if (ret) return ret; *buf = malloc(len); if (!buf) return -ENOMEM; return get_variable(var, guid, attributes, size, *buf); } int variable_is_setupmode(void) { uint8_t setup_mode; get_variable("SetupMode", &GV_GUID, NULL, NULL, &setup_mode); return setup_mode; } int variable_is_secureboot(void) { uint8_t secure_boot; get_variable("SecureBoot", &GV_GUID, NULL, NULL, &secure_boot); return secure_boot; } int set_variable(const char *var, EFI_GUID *guid, uint32_t attributes, uint32_t size, void *buf) { if (!kernel_efi_path) return -EINVAL; int varfs_len = strlen(var) + 48 + strlen(kernel_efi_path); char *varfs = malloc(varfs_len), *newbuf = malloc(size + sizeof(attributes)); int fd; snprintf(varfs, varfs_len, "%s/%s-%s", kernel_efi_path, var, guid_to_str(guid)); fd = open(varfs, O_RDWR|O_CREAT|O_TRUNC, 0644); free(varfs); if (fd < 0) return errno; memcpy(newbuf, &attributes, sizeof(attributes)); memcpy(newbuf + sizeof(attributes), buf, size); if (write(fd, newbuf, size + sizeof(attributes)) != size + sizeof(attributes)) return errno; close(fd); return 0; } int set_variable_esl(const char *var, EFI_GUID *guid, uint32_t attributes, uint32_t size, void *buf) { if (!kernel_efi_path) return -EINVAL; int newsize = size + OFFSET_OF(EFI_VARIABLE_AUTHENTICATION_2, AuthInfo) + OFFSET_OF(WIN_CERTIFICATE_UEFI_GUID, CertData); char *newdata = malloc(newsize); EFI_VARIABLE_AUTHENTICATION_2 *DescriptorData; EFI_TIME *Time; struct tm tm; time_t t; time(&t); memset(newdata, '\0', newsize); memcpy(newdata + newsize - size, buf, size); DescriptorData = (EFI_VARIABLE_AUTHENTICATION_2 *)newdata; Time = &DescriptorData->TimeStamp; gmtime_r(&t, &tm); /* FIXME: currently timestamp is one year into future because of * the way we set up the secure environment */ Time->Year = tm.tm_year + 1900 + 1; /* EFI_TIME Month is 1-12; Unix tm_mon is 0-11 */ Time->Month = tm.tm_mon + 1; Time->Day = tm.tm_mday; Time->Hour = tm.tm_hour; Time->Minute = tm.tm_min; Time->Second = tm.tm_sec; 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_PKCS7_GUID; int ret = set_variable(var, guid, attributes, newsize, newdata); free(newdata); return ret; } uint8_t * hash_to_esl(EFI_GUID *owner, int *len, uint8_t hash[SHA256_DIGEST_SIZE]) { const int siglen = sizeof(EFI_SIGNATURE_LIST) + sizeof(EFI_SIGNATURE_DATA) - 1 + SHA256_DIGEST_SIZE; uint8_t *sig = malloc(siglen); EFI_SIGNATURE_LIST *l = (void *)sig; EFI_SIGNATURE_DATA *d = (void *)sig + sizeof(EFI_SIGNATURE_LIST); if (len) *len = siglen; memset(sig, 0, siglen); l->SignatureType = EFI_CERT_SHA256_GUID; l->SignatureListSize = siglen; l->SignatureSize = 16 +32; /* UEFI defined */ memcpy(&d->SignatureData, hash, SHA256_DIGEST_SIZE); d->SignatureOwner = *owner; return sig; } int set_variable_hash(const char *var, EFI_GUID *owner, uint32_t attributes, uint8_t hash[SHA256_DIGEST_SIZE]) { int len; uint8_t *sig = hash_to_esl(&MOK_OWNER, &len, hash); int ret = set_variable_esl(var, owner, attributes, len, sig); free(sig); return ret; } efitools-1.9.2/lib/openssl_sign.c000066400000000000000000000071431341522017100167650ustar00rootroot00000000000000/* * Copyright 2019 * * see COPYING file */ #include #include #include #include #include int sign_efi_var_ssl(char *payload, int payload_size, EVP_PKEY *pkey, X509 *cert, unsigned char **sig, int *sigsize) { BIO *bio_data = BIO_new_mem_buf(payload, payload_size); PKCS7 *p7; p7 = PKCS7_sign(NULL, NULL, NULL, bio_data, PKCS7_BINARY|PKCS7_PARTIAL|PKCS7_DETACHED|PKCS7_NOATTR); const EVP_MD *md = EVP_get_digestbyname("SHA256"); PKCS7_sign_add_signer(p7, cert, pkey, md, PKCS7_BINARY|PKCS7_DETACHED|PKCS7_NOATTR); PKCS7_final(p7, bio_data, PKCS7_BINARY|PKCS7_DETACHED|PKCS7_NOATTR); *sig = NULL; *sigsize = i2d_PKCS7_SIGNED(p7->d.sign, sig); PKCS7_free(p7); ERR_print_errors_fp(stdout); return 0; } int sign_efi_var(char *payload, int payload_size, char *keyfile, char *certfile, unsigned char **sig, int *sigsize, char *engine) { int ret; ERR_load_crypto_strings(); OpenSSL_add_all_digests(); OpenSSL_add_all_ciphers(); /* here we may get highly unlikely failures or we'll get a * complaint about FIPS signatures (usually becuase the FIPS * module isn't present). In either case ignore the errors * (malloc will cause other failures out lower down */ ERR_clear_error(); BIO *cert_bio = BIO_new_file(certfile, "r"); if (!cert_bio) { ERR_print_errors_fp(stdout); fprintf(stderr, "error reading certificate %s\n", certfile); return 1; } X509 *cert = PEM_read_bio_X509(cert_bio, NULL, NULL, NULL); BIO_free(cert_bio); if (!cert) { ERR_print_errors_fp(stdout); fprintf(stderr, "error reading certificate %s\n", certfile); return 1; } EVP_PKEY *pkey = read_private_key(engine, keyfile); if (!pkey) { ERR_print_errors_fp(stdout); fprintf(stderr, "error reading private key %s\n", keyfile); return 1; } ret = sign_efi_var_ssl(payload, payload_size, pkey, cert, sig, sigsize); EVP_PKEY_free(pkey); X509_free(cert); return ret; } static EVP_PKEY * read_pem_private_key(char *keyfile) { BIO *key = BIO_new_file(keyfile, "r"); EVP_PKEY *pkey; if (!key) { ERR_print_errors_fp(stdout); fprintf(stderr, "error reading private key file %s\n", keyfile); return NULL; } pkey = PEM_read_bio_PrivateKey(key, NULL, NULL, NULL); BIO_free(key); if (!pkey) { ERR_print_errors_fp(stdout); fprintf(stderr, "error processing private key file %s\n", keyfile); return NULL; } return pkey; } static int ui_read(UI *ui, UI_STRING *uis) { char password[128]; if (UI_get_string_type(uis) != UIT_PROMPT) return 0; EVP_read_pw_string(password, sizeof(password), "Enter engine key pass phrase:", 0); UI_set_result(ui, uis, password); return 1; } static EVP_PKEY * read_engine_private_key(char *engine, char *keyfile) { UI_METHOD *ui; ENGINE *e; EVP_PKEY *pkey = NULL; ENGINE_load_builtin_engines(); e = ENGINE_by_id(engine); if (!e) { fprintf(stderr, "Failed to load engine: %s\n", engine); ERR_print_errors_fp(stderr); return NULL; } ui = UI_create_method("sbsigntools"); if (!ui) { fprintf(stderr, "Failed to create UI method\n"); ERR_print_errors_fp(stderr); goto out_free; } UI_method_set_reader(ui, ui_read); if (!ENGINE_init(e)) { fprintf(stderr, "Failed to initialize engine %s\n", engine); ERR_print_errors_fp(stderr); goto out_free; } pkey = ENGINE_load_private_key(e, keyfile, ui, NULL); ENGINE_finish(e); out_free: ENGINE_free(e); return pkey; } EVP_PKEY * read_private_key(char *engine, char *keyfile) { if (engine) return read_engine_private_key(engine, keyfile); else return read_pem_private_key(keyfile); } efitools-1.9.2/lib/pecoff.c000066400000000000000000000330071341522017100155220ustar00rootroot00000000000000/* * Code Copyright 2012 Red Hat, Inc * * Functions cut and pasted from * * git://github.com/mjg59/shim.git * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the * distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * * --- * * This file is a functional simplification of Original code from TianoCore * (http://tianocore.sf.net) * * MdePkg/Library/BasePeCoffLib/BasePeCoff.c * * Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.
* Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
* This program and the accompanying materials * are licensed and made available under the terms and conditions of the BSD License * which accompanies this distribution. The full text of the license may be found at * http://opensource.org/licenses/bsd-license.php. * * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, * WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. */ #include #include #ifdef CONFIG_arm #ifndef BUILD_EFI /* FIXME: * arm efi leaves a visibilit pragma pushed that won't work for * non efi programs, so eliminate it */ #pragma GCC visibility pop #endif #endif #include #include #include #include #include #include #include #include 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 && PEHdr->Pe32.OptionalHeader.Magic != EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { Print(L"Only IA32 or X64 images supported\n"); return EFI_UNSUPPORTED; } context->PEHdr = PEHdr; if (PEHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) { 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->SecDir = (EFI_IMAGE_DATA_DIRECTORY *) &PEHdr->Pe32Plus.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]; context->FileAlignment = PEHdr->Pe32Plus.OptionalHeader.FileAlignment; } else if (PEHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { context->ImageAddress = PEHdr->Pe32.OptionalHeader.ImageBase; context->ImageSize = (UINT64)PEHdr->Pe32.OptionalHeader.SizeOfImage; context->SizeOfHeaders = PEHdr->Pe32.OptionalHeader.SizeOfHeaders; context->EntryPoint = PEHdr->Pe32.OptionalHeader.AddressOfEntryPoint; context->RelocDir = &PEHdr->Pe32.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC]; context->NumberOfRvaAndSizes = PEHdr->Pe32.OptionalHeader.NumberOfRvaAndSizes; context->SecDir = (EFI_IMAGE_DATA_DIRECTORY *) &PEHdr->Pe32.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]; context->FileAlignment = PEHdr->Pe32.OptionalHeader.FileAlignment; } 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)); 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 = ALIGN_VALUE(s->SizeOfRawData, context->FileAlignment); 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; } if (context->PEHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) { context->PEHdr->Pe32Plus.OptionalHeader.ImageBase = (UINT64)*data; } else if (context->PEHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { context->PEHdr->Pe32.OptionalHeader.ImageBase = (UINT32)(long)*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; } EFI_STATUS pecoff_get_signature(PE_COFF_LOADER_IMAGE_CONTEXT *context, void *buffer, WIN_CERTIFICATE **data, int signum) { WIN_CERTIFICATE *cert; UINT32 offset; int i; if (!context->SecDir->Size) return EFI_NOT_FOUND; offset = context->SecDir->VirtualAddress; cert = (WIN_CERTIFICATE *)(buffer + offset); for (i = 0; i < signum; i++) { offset += ALIGN_VALUE(cert->dwLength, 8); cert = (WIN_CERTIFICATE *)(buffer + offset); if (offset >= context->SecDir->VirtualAddress + context->SecDir->Size) break; } if (i != signum) return EFI_NOT_FOUND; *data = cert; 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 = BS->HandleProtocol(image, &IMAGE_PROTOCOL, (VOID **)&li); if (status != EFI_SUCCESS) return status; status = generate_path(name, li, &loadpath, &PathName); if (status != EFI_SUCCESS) return status; status = BS->LoadImage(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; BS->UnloadImage(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 = entry_point(image, systab); out: FreePool(buffer); return efi_status; } #endif efitools-1.9.2/lib/pkcs7verify.c000066400000000000000000000134751341522017100165430ustar00rootroot00000000000000#include #include #include #include #include #include #include #include #define ARRAY_SIZE(a) (sizeof (a) / sizeof ((a)[0])) static CHAR16 *p7bin = L"\\Pkcs7VerifyDxe.efi"; static EFI_PKCS7_VERIFY_PROTOCOL *pkcs7verifyprotocol; EFI_STATUS pkcs7verify_get_protocol(EFI_HANDLE image, EFI_PKCS7_VERIFY_PROTOCOL **p7vp, CHAR16 **error) { EFI_LOADED_IMAGE *li; EFI_DEVICE_PATH *loadpath = NULL; CHAR16 *PathName = NULL; EFI_HANDLE loader_handle; EFI_STATUS status; status = BS->LocateProtocol(&PKCS7_VERIFY_PROTOCOL_GUID, NULL, (VOID **)p7vp); if (status == EFI_SUCCESS) return status; Print(L"Platform doesn't provide PKCS7_VERIFY protocol, trying to load\n"); status = BS->HandleProtocol(image, &IMAGE_PROTOCOL, (VOID **)&li); if (status != EFI_SUCCESS) { *error = L"Can't find loaded image protocol"; return status; } status = generate_path(p7bin, li, &loadpath, &PathName); if (status != EFI_SUCCESS) { *error = L"generate_path failed"; return status; } status = BS->LoadImage(FALSE, image, loadpath, NULL, 0, &loader_handle); if (status != EFI_SUCCESS) { *error = L"LoadImage failed for external module"; return status; } status = BS->StartImage(loader_handle, NULL, NULL); if (status != EFI_SUCCESS) { *error = L"StartImage failed for external module (loaded OK)"; return status; } status = BS->LocateProtocol(&PKCS7_VERIFY_PROTOCOL_GUID, NULL, (VOID **)p7vp); if (status != EFI_SUCCESS) *error = L"Loaded module but it didn't provide the pkcs7Verify protocol"; else pkcs7verifyprotocol = *p7vp; return status; } /* * Checks the variable for the binary hash. Returns 1 if found, 0 if * not and -1 on error. */ static int pkcs7verify_is_hash_present(CHAR16 *var, EFI_GUID owner, VOID *data, UINTN len) { EFI_GUID **hashes; UINT8 *hash; int count, i; int present = -1; hashes = AllocatePool(allowed_hashes_size * sizeof(EFI_GUID *)); if (!hashes) goto out; count = hashes_in_variable(var, owner, hashes); if (count < 0) goto out; for (i = 0; i < count; i++) { if (CompareGuid(hashes[i], &EFI_CERT_SHA256_GUID) == 0) { hash = AllocatePool(SHA256_DIGEST_SIZE); if (!hash) goto out; if (sha256_get_pecoff_digest_mem(data, len, hash) != EFI_SUCCESS) { FreePool(hash); goto out; } if (find_in_variable_esl(var, owner, hash, SHA256_DIGEST_SIZE) == EFI_SUCCESS) { present = 1; FreePool(hash); goto out; } FreePool(hash); } else { Print(L"FIXME: found an unrecognised hash algorithm %g\n", hashes[i]); goto out; } } present = 0; out: if (hashes) FreePool(hashes); return present; } BOOLEAN pkcs7verify_deny(VOID *data, UINTN len) { int deny; deny = pkcs7verify_is_hash_present(L"dbx", SIG_DB, data, len); if (deny == 1 || deny < 0) { deny = 1; goto out; } deny = pkcs7verify_is_hash_present(L"MokListX", MOK_OWNER, data, len); if (deny == 1 || deny < 0) deny = 1; out: return deny ? TRUE : FALSE; } /* * The Plcs7Verify protocol doesn't take raw signature lists and lengths, * it takes a null terminated list of pointers to signature lists, so * make the conversion */ EFI_SIGNATURE_LIST ** pkcs7verify_to_cert_list(VOID *data, UINTN len) { EFI_SIGNATURE_LIST *CertList, **retval; int size, count=0; if (!data) return data; certlist_for_each_certentry(CertList, data, size, len) count++; retval = AllocatePool((count + 1) * sizeof(void *)); if (!retval) return NULL; count = 0; certlist_for_each_certentry(CertList, data, size, len) retval[count++] = CertList; retval[count] = NULL; return retval; } BOOLEAN pkcs7verify_allow(VOID *data, UINTN len) { PE_COFF_LOADER_IMAGE_CONTEXT context; UINT8 hash[SHA256_DIGEST_SIZE]; BOOLEAN allow = FALSE; CHAR16 *check[] = { L"MokList", L"db" }; CHAR16 *forbid[] = { L"MokListX", L"dbx" }; EFI_GUID owners[] = { MOK_OWNER, SIG_DB }; EFI_STATUS status; int i; status = pecoff_read_header(&context, data); if (status != EFI_SUCCESS) goto out; /* FIXME: this is technically wrong, because the hash * could be non-sha256, but it isn't a security breach * because we'll refuse a binary we should have accepted */ status = sha256_get_pecoff_digest_mem(data, len, hash); if (status != EFI_SUCCESS) goto out; /* first look up the hashes because the verify protocol can't * do this anyway */ if (find_in_variable_esl(L"MokList", MOK_OWNER, hash, SHA256_DIGEST_SIZE) == EFI_SUCCESS || find_in_variable_esl(L"db", SIG_DB, hash, SHA256_DIGEST_SIZE) == EFI_SUCCESS) { allow = TRUE; goto out; } for (i = 0; i < ARRAY_SIZE(check); i++) { VOID *db = NULL, *dbx = NULL; EFI_SIGNATURE_LIST **dblist = NULL, **dbxlist = NULL; UINTN db_len = 0, dbx_len = 0; int j; status = get_variable(check[i], (UINT8 **)&db, &db_len, owners[i]); if (status != EFI_SUCCESS) goto next; status = get_variable(forbid[i], (UINT8 **)&dbx, &dbx_len, owners[i]); if (status != EFI_SUCCESS && status != EFI_NOT_FOUND) goto next; dblist = pkcs7verify_to_cert_list(db, db_len); if (status != EFI_NOT_FOUND) dbxlist = pkcs7verify_to_cert_list(dbx, dbx_len); if ((db_len != 0 && dblist == NULL) || (dbx_len != 0 && dbxlist == NULL)) goto next; for (j = 0; ; j++) { WIN_CERTIFICATE *cert; status = pecoff_get_signature(&context, data, &cert, j); if (status != EFI_SUCCESS) break; status = pkcs7verifyprotocol-> VerifySignature(pkcs7verifyprotocol, (VOID *)(cert + 1), cert->dwLength - sizeof(*cert), hash, sizeof(hash), dblist, dbxlist, NULL); if (status == EFI_SUCCESS) { allow = TRUE; break; } } next: if (dblist) FreePool(dblist); if (dbxlist) FreePool(dbxlist); if (db) FreePool(db); if (dbx) FreePool(dbx); if (allow) break; } out: return allow; } efitools-1.9.2/lib/security_policy.c000066400000000000000000000173151341522017100175120ustar00rootroot00000000000000/* * Copyright 2012 * * see COPYING file * * Install and remove a platform security2 override policy */ #include #include #include #include #include #include #include #include /* * See the UEFI Platform Initialization manual (Vol2: DXE) for this */ struct _EFI_SECURITY2_PROTOCOL; struct _EFI_SECURITY_PROTOCOL; typedef struct _EFI_SECURITY2_PROTOCOL EFI_SECURITY2_PROTOCOL; typedef struct _EFI_SECURITY_PROTOCOL EFI_SECURITY_PROTOCOL; typedef EFI_DEVICE_PATH EFI_DEVICE_PATH_PROTOCOL; typedef EFI_STATUS (EFIAPI *EFI_SECURITY_FILE_AUTHENTICATION_STATE) ( const EFI_SECURITY_PROTOCOL *This, UINT32 AuthenticationStatus, const EFI_DEVICE_PATH_PROTOCOL *File ); typedef EFI_STATUS (EFIAPI *EFI_SECURITY2_FILE_AUTHENTICATION) ( const EFI_SECURITY2_PROTOCOL *This, const EFI_DEVICE_PATH_PROTOCOL *DevicePath, VOID *FileBuffer, UINTN FileSize, BOOLEAN BootPolicy ); struct _EFI_SECURITY2_PROTOCOL { EFI_SECURITY2_FILE_AUTHENTICATION FileAuthentication; }; struct _EFI_SECURITY_PROTOCOL { EFI_SECURITY_FILE_AUTHENTICATION_STATE FileAuthenticationState; }; static UINT8 *security_policy_esl = NULL; static UINTN security_policy_esl_len; BOOLEAN security_policy_mok_override(void) { UINT8 *VarData; UINTN VarLen; UINT32 attr; EFI_STATUS status; /* Secure Boot Override: 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 TRUE; } return FALSE; } BOOLEAN security_policy_mok_deny(VOID *data, UINTN len) { EFI_STATUS status; UINT8 hash[SHA256_DIGEST_SIZE]; status = sha256_get_pecoff_digest_mem(data, len, hash); if (status != EFI_SUCCESS) return TRUE; if (find_in_variable_esl(L"dbx", SIG_DB, hash, SHA256_DIGEST_SIZE) == EFI_SUCCESS) /* MOK list cannot override dbx */ return FALSE; if (find_in_variable_esl(L"MokListX", SIG_DB, hash, SHA256_DIGEST_SIZE) == EFI_SUCCESS) return TRUE; return FALSE; } BOOLEAN security_policy_mok_allow(VOID *data, UINTN len) { EFI_STATUS status; UINT8 hash[SHA256_DIGEST_SIZE]; UINT32 attr; UINT8 *VarData; UINTN VarLen; status = sha256_get_pecoff_digest_mem(data, len, hash); if (status != EFI_SUCCESS) return TRUE; 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 TRUE; check_tmplist: if (security_policy_esl && find_in_esl(security_policy_esl, security_policy_esl_len, hash, SHA256_DIGEST_SIZE) == EFI_SUCCESS) return TRUE; return FALSE; } static EFIAPI EFI_SECURITY_FILE_AUTHENTICATION_STATE esfas = NULL; static EFIAPI EFI_SECURITY2_FILE_AUTHENTICATION es2fa = NULL; static BOOLEAN(*sp_override)(void) = NULL; static POLICY_FUNCTION sp_allow = NULL; static POLICY_FUNCTION sp_deny = NULL; EFI_STATUS EFIAPI security2_policy_authentication ( const EFI_SECURITY2_PROTOCOL *This, const EFI_DEVICE_PATH_PROTOCOL *DevicePath, VOID *FileBuffer, UINTN FileSize, BOOLEAN BootPolicy ) { EFI_STATUS status; if (sp_override && sp_override()) return EFI_SUCCESS; /* if policy would deny, fail now */ if (sp_deny && sp_deny(FileBuffer, FileSize)) return EFI_SECURITY_VIOLATION; /* Chain original security policy */ status = es2fa(This, DevicePath, FileBuffer, FileSize, BootPolicy); /* if OK, don't bother with allow check */ if (status == EFI_SUCCESS) return status; if (sp_allow && sp_allow(FileBuffer, FileSize)) return EFI_SUCCESS; return status; } EFI_STATUS EFIAPI 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; if (sp_override && sp_override()) return EFI_SUCCESS; /* Chain original security policy */ status = esfas(This, AuthenticationStatus, DevicePathConst); /* capture failure status: may be either EFI_ACCESS_DENIED or * EFI_SECURITY_VIOLATION */ fail_status = status; status = 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; status = EFI_SECURITY_VIOLATION; if (sp_deny && sp_deny(FileBuffer, FileSize)) goto out; status = fail_status; if (status == EFI_SUCCESS) goto out; /* fail status is platform security failure now */ if (sp_allow && sp_allow(FileBuffer, FileSize)) status = EFI_SUCCESS; out: if (FileBuffer) FreePool(FileBuffer); if (OrigDevPath) FreePool(OrigDevPath); return status; } EFI_STATUS security_policy_install(BOOLEAN (*override)(void), POLICY_FUNCTION allow, POLICY_FUNCTION deny) { EFI_SECURITY_PROTOCOL *security_protocol; EFI_SECURITY2_PROTOCOL *security2_protocol = NULL; EFI_STATUS status; sp_override = override; sp_allow = allow; sp_deny = deny; 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 */ BS->LocateProtocol(&SECURITY2_PROTOCOL_GUID, NULL, (VOID **)&security2_protocol); status = BS->LocateProtocol(&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; security2_protocol->FileAuthentication = security2_policy_authentication; /* check for security policy in write protected memory */ if (security2_protocol->FileAuthentication != security2_policy_authentication) return EFI_ACCESS_DENIED; } esfas = security_protocol->FileAuthenticationState; security_protocol->FileAuthenticationState = security_policy_authentication; /* check for security policy in write protected memory */ if (security_protocol->FileAuthenticationState != 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 = BS->LocateProtocol(&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 = BS->LocateProtocol(&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; } efitools-1.9.2/lib/sha256.c000066400000000000000000000316241341522017100152730ustar00rootroot00000000000000/* * FIPS-180-2 compliant SHA-256 implementation * * Copyright (C) 2001-2003 Christophe Devine * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #ifdef CONFIG_arm #ifndef BUILD_EFI /* FIXME: * arm efi leaves a visibilit pragma pushed that won't work for * non efi programs, so eliminate it */ #pragma GCC visibility pop #endif #endif #include #include #include #include #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, checksum_size; EFI_STATUS efi_status; void *checksum_ptr; /* add extra end alignment; rely on data buffer being zero * filled to the end of the page */ DataSize = ALIGN_VALUE(DataSize, 8); efi_status = pecoff_read_header(&context, buffer); if (efi_status != EFI_SUCCESS) { Print(L"Failed to read header\n"); return efi_status; } if (context.PEHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) { checksum_ptr = &context.PEHdr->Pe32Plus.OptionalHeader.CheckSum; checksum_size = sizeof(context.PEHdr->Pe32Plus.OptionalHeader.CheckSum); } else { checksum_ptr = &context.PEHdr->Pe32.OptionalHeader.CheckSum; checksum_size = sizeof(context.PEHdr->Pe32.OptionalHeader.CheckSum); } sections = AllocatePool(context.NumberOfSections * sizeof(*sections)); if (!sections) return EFI_OUT_OF_RESOURCES; sha256_starts(&ctx); /* hash start to checksum */ hashbase = buffer; hashsize = checksum_ptr - buffer; sha256_update(&ctx, hashbase, hashsize); /* hash post-checksum to start of certificate table */ hashbase = checksum_ptr + checksum_size; hashsize = (void *)context.SecDir - hashbase; sha256_update(&ctx, hashbase, hashsize); /* Hash end of certificate table to end of image header */ hashbase = context.SecDir + 1; hashsize = context.SizeOfHeaders - (int) (hashbase - buffer); sha256_update(&ctx, hashbase, hashsize); sum_of_bytes = context.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.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.NumberOfSections; i++) { section = sections[i]; hashbase = pecoff_image_address(buffer, DataSize, section->PointerToRawData); hashsize = section->SizeOfRawData; if (hashsize == 0) continue; sha256_update(&ctx, hashbase, hashsize); sum_of_bytes += hashsize; } if (DataSize > sum_of_bytes + context.SecDir->Size) { /* stuff at end to hash */ hashbase = buffer + sum_of_bytes; hashsize = (unsigned int)(DataSize - context.SecDir->Size - sum_of_bytes); sha256_update(&ctx, hashbase, hashsize); } else if (DataSize < sum_of_bytes + context.SecDir->Size) { /* warn but hope the checksum is right */ Print(L"Invalid Data Size %d bytes too small\n", DataSize + context.SecDir->Size - sum_of_bytes); } 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 efitools-1.9.2/lib/shell.c000066400000000000000000000021661341522017100153710ustar00rootroot00000000000000/* * Copyright 2012 * * see COPYING file * * misc shell helper functions */ #include #include #include EFI_STATUS argsplit(EFI_HANDLE image, int *argc, CHAR16*** ARGV) { int i, count = 1; EFI_STATUS status; EFI_LOADED_IMAGE *info; CHAR16 *start; *argc = 0; status = BS->HandleProtocol(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; } efitools-1.9.2/lib/shim_protocol.c000066400000000000000000000022441341522017100171400ustar00rootroot00000000000000#include #include #include #include #include #include #include #include #include #include static EFI_STATUS shimprotocol_context(void *data, unsigned int size, PE_COFF_LOADER_IMAGE_CONTEXT *context) { return pecoff_read_header(context, data); } static EFI_STATUS shimprotocol_verify(void *buffer, UINT32 size) { EFI_STATUS status; if (!variable_is_secureboot() || variable_is_setupmode()) return EFI_SUCCESS; if (pkcs7verify_deny(buffer, size)) return EFI_ACCESS_DENIED; if (pkcs7verify_allow(buffer, size)) return EFI_SUCCESS; return EFI_ACCESS_DENIED; return status; } static SHIM_LOCK shim_protocol_interface = { .Verify = shimprotocol_verify, .Context = shimprotocol_context, }; static EFI_HANDLE shim_protocol_handle; EFI_STATUS shim_protocol_install(void) { return BS->InstallProtocolInterface(&shim_protocol_handle, &MOK_OWNER, EFI_NATIVE_INTERFACE, &shim_protocol_interface); } void shim_protocol_uninstall(void) { BS->UninstallProtocolInterface(shim_protocol_handle, &MOK_OWNER, &shim_protocol_interface); } efitools-1.9.2/lib/simple_file.c000066400000000000000000000250461341522017100165540ustar00rootroot00000000000000/* * Copyright 2012 * * see COPYING file */ #include #include #include /* for ALIGN_VALUE */ #include #include #include #include /* for generate_path() */ static EFI_GUID IMAGE_PROTOCOL = LOADED_IMAGE_PROTOCOL; static EFI_GUID SIMPLE_FS_PROTOCOL = SIMPLE_FILE_SYSTEM_PROTOCOL; static EFI_GUID FILE_INFO = EFI_FILE_INFO_ID; static EFI_GUID FS_INFO = EFI_FILE_SYSTEM_INFO_ID; EFI_STATUS simple_file_open_by_handle(EFI_HANDLE device, CHAR16 *name, EFI_FILE **file, UINT64 mode) { EFI_STATUS efi_status; EFI_FILE_IO_INTERFACE *drive; EFI_FILE *root; efi_status = BS->HandleProtocol(device, &SIMPLE_FS_PROTOCOL, (VOID **)&drive); if (efi_status != EFI_SUCCESS) { Print(L"Unable to find simple file protocol (%d)\n", efi_status); goto error; } efi_status = drive->OpenVolume(drive, &root); if (efi_status != EFI_SUCCESS) { Print(L"Failed to open drive volume (%d)\n", efi_status); goto error; } efi_status = root->Open(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 = BS->HandleProtocol(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_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 = file->GetInfo(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 = file->Read(file, &len, buf); if (status != EFI_SUCCESS || len == 0) break; (*count)++; size += len; } file->SetPosition(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++) { UINTN len = size; file->Read(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 = file->GetInfo(file, &FILE_INFO, size, fi); if (efi_status != EFI_SUCCESS) { Print(L"Failed to get file info\n"); return efi_status; } *size = fi->FileSize; /* might use memory mapped, so align up to nearest page */ *buffer = AllocateZeroPool(ALIGN_VALUE(*size, 4096)); if (!*buffer) { Print(L"Failed to allocate buffer of size %d\n", *size); return EFI_OUT_OF_RESOURCES; } efi_status = file->Read(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 = file->Write(file, &size, buffer); return efi_status; } void simple_file_close(EFI_FILE *file) { file->Close(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; BS->LocateHandleBuffer(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 = BS->HandleProtocol(vol_handles[i], &SIMPLE_FS_PROTOCOL, (VOID **)&drive); if (status != EFI_SUCCESS || !drive) continue; status = drive->OpenVolume(drive, &root); if (status != EFI_SUCCESS) continue; status = root->GetInfo(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); } efitools-1.9.2/lib/variables.c000066400000000000000000000230741341522017100162330ustar00rootroot00000000000000/* * Copyright 2012 * * see COPYING file * * Portions of this file are a direct cut and paste from Tianocore * (http://tianocore.sf.net) * * SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.c * * Copyright (c) 2011 - 2012, Intel Corporation. All rights reserved.
* This program and the accompanying materials * are licensed and made available under the terms and conditions of the BSD License * which accompanies this distribution. The full text of the license may be found * at * http://opensource.org/licenses/bsd-license.php * * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, * WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. * */ #include #include #include #include #include #include #include #include EFI_STATUS variable_create_esl(void *cert, int cert_len, EFI_GUID *type, EFI_GUID *owner, void **out, int *outlen) { *outlen = cert_len + sizeof(EFI_SIGNATURE_LIST) + sizeof(EFI_GUID); *out = AllocateZeroPool(*outlen); if (!*out) return EFI_OUT_OF_RESOURCES; EFI_SIGNATURE_LIST *sl = *out; sl->SignatureHeaderSize = 0; sl->SignatureType = *type; sl->SignatureSize = cert_len + sizeof(EFI_GUID); sl->SignatureListSize = *outlen; EFI_SIGNATURE_DATA *sd = *out + sizeof(EFI_SIGNATURE_LIST); if (owner) sd->SignatureOwner = *owner; CopyMem(sd->SignatureData, cert, cert_len); return EFI_SUCCESS; } EFI_STATUS CreateTimeBasedPayload ( IN OUT UINTN *DataSize, IN OUT UINT8 **Data ) { EFI_STATUS Status; UINT8 *NewData; UINT8 *Payload; UINTN PayloadSize; EFI_VARIABLE_AUTHENTICATION_2 *DescriptorData; UINTN DescriptorSize; EFI_TIME Time; EFI_GUID efi_cert_type = EFI_CERT_TYPE_PKCS7_GUID; if (Data == NULL || DataSize == NULL) { return EFI_INVALID_PARAMETER; } // // In Setup mode or Custom mode, the variable does not need to be signed but the // parameters to the SetVariable() call still need to be prepared as authenticated // variable. So we create EFI_VARIABLE_AUTHENTICATED_2 descriptor without certificate // data in it. // Payload = *Data; PayloadSize = *DataSize; DescriptorSize = OFFSET_OF(EFI_VARIABLE_AUTHENTICATION_2, AuthInfo) + OFFSET_OF(WIN_CERTIFICATE_UEFI_GUID, CertData); NewData = (UINT8*) AllocateZeroPool (DescriptorSize + PayloadSize); if (NewData == NULL) { return EFI_OUT_OF_RESOURCES; } if ((Payload != NULL) && (PayloadSize != 0)) { CopyMem (NewData + DescriptorSize, Payload, PayloadSize); } DescriptorData = (EFI_VARIABLE_AUTHENTICATION_2 *) (NewData); ZeroMem (&Time, sizeof (EFI_TIME)); Status = RT->GetTime(&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 = RT->SetVariable(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 = RT->GetVariable(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 = RT->SetVariable(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; RT->ResetSystem(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 = RT->GetVariable(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 = RT->GetVariable(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 hashes_in_esl(UINT8 *Data, UINTN DataSize, EFI_GUID *hashes[]) { int count = 0; EFI_SIGNATURE_LIST *CertList; certlist_for_each_certentry(CertList, Data, DataSize, DataSize) { int i; for (i = 0; i < count; i++) { if (CompareGuid(&CertList->SignatureType, hashes[i]) == 0) goto found_skip; } for (i = 0; i < allowed_hashes_size; i++) { if (CompareGuid(&CertList->SignatureType, allowed_hashes[i]) == 0) goto found; } found_skip: continue; found: hashes[count++] = allowed_hashes[i]; } return count; } int hashes_in_variable(CHAR16* var, EFI_GUID owner, EFI_GUID *hashes[]) { UINTN DataSize; UINT8 *Data; EFI_STATUS status; int count; status = get_variable(var, &Data, &DataSize, owner); if (status == EFI_NOT_FOUND) return 0; if (status != EFI_SUCCESS) return -1; count = hashes_in_esl(Data, DataSize, hashes); FreePool(Data); return count; } int variable_is_setupmode(void) { /* set to 1 because we return true if SetupMode doesn't exist */ UINT8 SetupMode = 1; UINTN DataSize = sizeof(SetupMode); RT->GetVariable(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); RT->GetVariable(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 = RT->SetVariable(var, &owner, EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_APPEND_WRITE, sizeof(sig), sig); return status; } efitools-1.9.2/mkusb.sh000077500000000000000000000017311341522017100150250ustar00rootroot00000000000000#!/bin/sh k=$1 e=$2 o=$3 if [ $# -ne 3 ]; then echo "Usage $0: key_dir efi_dir output_image_file" exit 1; fi t=/var/tmp/tmpusb.$$.img if [ ! -d "$k" ]; then echo "Failed to find directory $k" exit 1; fi if [ ! -d "$e" ]; then echo "Failed to find directory $e" exit 1; fi dd if=/dev/zero of=${o} bs=512 count=102096 parted ${o} "mktable gpt" parted ${o} "mkpart p fat32 2048s 102049s" parted ${o} "toggle 1 boot" parted ${o} "name 1 UEFI" dd if=/dev/zero of=${t} bs=512 count=100000 mkfs -t vfat -n UEFI-Tools ${t} mmd -i ${t} ::/EFI mmd -i ${t} ::/EFI/BOOT mmd -i ${t} ::/keys mcopy -i ${t} ${k}/*.esl ::/keys mcopy -i ${t} ${k}/*.auth ::/keys mcopy -i ${t} ${e}/HashTool-signed.efi ::/EFI/BOOT/HashTool.efi mcopy -i ${t} ${e}/KeyTool-signed.efi ::/EFI/BOOT/KeyTool.efi mcopy -i ${t} ${e}/PreLoader-signed.efi ::/EFI/BOOT/BOOTX64.efi mcopy -i ${t} ${e}/HelloWorld.efi ::/EFI/BOOT/loader.efi dd if=${t} of=${o} bs=512 seek=2048 count=100000 rm -f ${t} exit 0; efitools-1.9.2/ms-kek.crt000066400000000000000000000150671341522017100152550ustar00rootroot00000000000000Certificate: Data: Version: 3 (0x2) Serial Number: 61:0a:d1:88:00:00:00:00:00:03 Signature Algorithm: sha256WithRSAEncryption Issuer: C=US, ST=Washington, L=Redmond, O=Microsoft Corporation, CN=Microsoft Corporation Third Party Marketplace Root Validity Not Before: Jun 24 20:41:29 2011 GMT Not After : Jun 24 20:51:29 2026 GMT Subject: C=US, ST=Washington, L=Redmond, O=Microsoft Corporation, CN=Microsoft Corporation KEK CA 2011 Subject Public Key Info: Public Key Algorithm: rsaEncryption Public-Key: (2048 bit) Modulus: 00:c4:e8:b5:8a:bf:ad:57:26:b0:26:c3:ea:e7:fb: 57:7a:44:02:5d:07:0d:da:4a:e5:74:2a:e6:b0:0f: ec:6d:eb:ec:7f:b9:e3:5a:63:32:7c:11:17:4f:0e: e3:0b:a7:38:15:93:8e:c6:f5:e0:84:b1:9a:9b:2c: e7:f5:b7:91:d6:09:e1:e2:c0:04:a8:ac:30:1c:df: 48:f3:06:50:9a:64:a7:51:7f:c8:85:4f:8f:20:86: ce:fe:2f:e1:9f:ff:82:c0:ed:e9:cd:ce:f4:53:6a: 62:3a:0b:43:b9:e2:25:fd:fe:05:f9:d4:c4:14:ab: 11:e2:23:89:8d:70:b7:a4:1d:4d:ec:ae:e5:9c:fa: 16:c2:d7:c1:cb:d4:e8:c4:2f:e5:99:ee:24:8b:03: ec:8d:f2:8b:ea:c3:4a:fb:43:11:12:0b:7e:b5:47: 92:6c:dc:e6:04:89:eb:f5:33:04:eb:10:01:2a:71: e5:f9:83:13:3c:ff:25:09:2f:68:76:46:ff:ba:4f: be:dc:ad:71:2a:58:aa:fb:0e:d2:79:3d:e4:9b:65: 3b:cc:29:2a:9f:fc:72:59:a2:eb:ae:92:ef:f6:35: 13:80:c6:02:ec:e4:5f:cc:9d:76:cd:ef:63:92:c1: af:79:40:84:79:87:7f:e3:52:a8:e8:9d:7b:07:69: 8f:15 Exponent: 65537 (0x10001) X509v3 extensions: 1.3.6.1.4.1.311.21.1: ... X509v3 Subject Key Identifier: 62:FC:43:CD:A0:3E:A4:CB:67:12:D2:5B:D9:55:AC:7B:CC:B6:8A:5F 1.3.6.1.4.1.311.20.2: . .S.u.b.C.A X509v3 Key Usage: Digital Signature, Certificate Sign, CRL Sign X509v3 Basic Constraints: critical CA:TRUE X509v3 Authority Key Identifier: keyid:45:66:52:43:E1:7E:58:11:BF:D6:4E:9E:23:55:08:3B:3A:22:6A:A8 X509v3 CRL Distribution Points: Full Name: URI:http://crl.microsoft.com/pki/crl/products/MicCorThiParMarRoo_2010-10-05.crl Authority Information Access: CA Issuers - URI:http://www.microsoft.com/pki/certs/MicCorThiParMarRoo_2010-10-05.crt Signature Algorithm: sha256WithRSAEncryption d4:84:88:f5:14:94:18:02:ca:2a:3c:fb:2a:92:1c:0c:d7:a0: d1:f1:e8:52:66:a8:ee:a2:b5:75:7a:90:00:aa:2d:a4:76:5a: ea:79:b7:b9:37:6a:51:7b:10:64:f6:e1:64:f2:02:67:be:f7: a8:1b:78:bd:ba:ce:88:58:64:0c:d6:57:c8:19:a3:5f:05:d6: db:c6:d0:69:ce:48:4b:32:b7:eb:5d:d2:30:f5:c0:f5:b8:ba: 78:07:a3:2b:fe:9b:db:34:56:84:ec:82:ca:ae:41:25:70:9c: 6b:e9:fe:90:0f:d7:96:1f:e5:e7:94:1f:b2:2a:0c:8d:4b:ff: 28:29:10:7b:f7:d7:7c:a5:d1:76:b9:05:c8:79:ed:0f:90:92: 9c:c2:fe:df:6f:7e:6c:0f:7b:d4:c1:45:dd:34:51:96:39:0f: e5:5e:56:d8:18:05:96:f4:07:a6:42:b3:a0:77:fd:08:19:f2: 71:56:cc:9f:86:23:a4:87:cb:a6:fd:58:7e:d4:69:67:15:91: 7e:81:f2:7f:13:e5:0d:8b:8a:3c:87:84:eb:e3:ce:bd:43:e5: ad:2d:84:93:8e:6a:2b:5a:7c:44:fa:52:aa:81:c8:2d:1c:bb: e0:52:df:00:11:f8:9a:3d:c1:60:b0:e1:33:b5:a3:88:d1:65: 19:0a:1a:e7:ac:7c:a4:c1:82:87:4e:38:b1:2f:0d:c5:14:87: 6f:fd:8d:2e:bc:39:b6:e7:e6:c3:e0:e4:cd:27:84:ef:94:42: ef:29:8b:90:46:41:3b:81:1b:67:d8:f9:43:59:65:cb:0d:bc: fd:00:92:4f:f4:75:3b:a7:a9:24:fc:50:41:40:79:e0:2d:4f: 0a:6a:27:76:6e:52:ed:96:69:7b:af:0f:f7:87:05:d0:45:c2: ad:53:14:81:1f:fb:30:04:aa:37:36:61:da:4a:69:1b:34:d8: 68:ed:d6:02:cf:6c:94:0c:d3:cf:6c:22:79:ad:b1:f0:bc:03: a2:46:60:a9:c4:07:c2:21:82:f1:fd:f2:e8:79:32:60:bf:d8: ac:a5:22:14:4b:ca:c1:d8:4b:eb:7d:3f:57:35:b2:e6:4f:75: b4:b0:60:03:22:53:ae:91:79:1d:d6:9b:41:1f:15:86:54:70: b2:de:0d:35:0f:7c:b0:34:72:ba:97:60:3b:f0:79:eb:a2:b2: 1c:5d:a2:16:b8:87:c5:e9:1b:f6:b5:97:25:6f:38:9f:e3:91: fa:8a:79:98:c3:69:0e:b7:a3:1c:20:05:97:f8:ca:14:ae:00: d7:c4:f3:c0:14:10:75:6b:34:a0:1b:b5:99:60:f3:5c:b0:c5: 57:4e:36:d2:32:84:bf:9e -----BEGIN CERTIFICATE----- MIIF6DCCA9CgAwIBAgIKYQrRiAAAAAAAAzANBgkqhkiG9w0BAQsFADCBkTELMAkG A1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQx HjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjE7MDkGA1UEAxMyTWljcm9z b2Z0IENvcnBvcmF0aW9uIFRoaXJkIFBhcnR5IE1hcmtldHBsYWNlIFJvb3QwHhcN MTEwNjI0MjA0MTI5WhcNMjYwNjI0MjA1MTI5WjCBgDELMAkGA1UEBhMCVVMxEzAR BgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1p Y3Jvc29mdCBDb3Jwb3JhdGlvbjEqMCgGA1UEAxMhTWljcm9zb2Z0IENvcnBvcmF0 aW9uIEtFSyBDQSAyMDExMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA xOi1ir+tVyawJsPq5/tXekQCXQcN2krldCrmsA/sbevsf7njWmMyfBEXTw7jC6c4 FZOOxvXghLGamyzn9beR1gnh4sAEqKwwHN9I8wZQmmSnUX/IhU+PIIbO/i/hn/+C wO3pzc70U2piOgtDueIl/f4F+dTEFKsR4iOJjXC3pB1N7K7lnPoWwtfBy9ToxC/l me4kiwPsjfKL6sNK+0MREgt+tUeSbNzmBInr9TME6xABKnHl+YMTPP8lCS9odkb/ uk++3K1xKliq+w7SeT3km2U7zCkqn/xyWaLrrpLv9jUTgMYC7ORfzJ12ze9jksGv eUCEeYd/41Ko6J17B2mPFQIDAQABo4IBTzCCAUswEAYJKwYBBAGCNxUBBAMCAQAw HQYDVR0OBBYEFGL8Q82gPqTLZxLSW9lVrHvMtopfMBkGCSsGAQQBgjcUAgQMHgoA UwB1AGIAQwBBMAsGA1UdDwQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQY MBaAFEVmUkPhflgRv9ZOniNVCDs6ImqoMFwGA1UdHwRVMFMwUaBPoE2GS2h0dHA6 Ly9jcmwubWljcm9zb2Z0LmNvbS9wa2kvY3JsL3Byb2R1Y3RzL01pY0NvclRoaVBh ck1hclJvb18yMDEwLTEwLTA1LmNybDBgBggrBgEFBQcBAQRUMFIwUAYIKwYBBQUH MAKGRGh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2kvY2VydHMvTWljQ29yVGhp UGFyTWFyUm9vXzIwMTAtMTAtMDUuY3J0MA0GCSqGSIb3DQEBCwUAA4ICAQDUhIj1 FJQYAsoqPPsqkhwM16DR8ehSZqjuorV1epAAqi2kdlrqebe5N2pRexBk9uFk8gJn vveoG3i9us6IWGQM1lfIGaNfBdbbxtBpzkhLMrfrXdIw9cD1uLp4B6Mr/pvbNFaE 7ILKrkElcJxr6f6QD9eWH+XnlB+yKgyNS/8oKRB799d8pdF2uQXIee0PkJKcwv7f b35sD3vUwUXdNFGWOQ/lXlbYGAWW9AemQrOgd/0IGfJxVsyfhiOkh8um/Vh+1Gln FZF+gfJ/E+UNi4o8h4Tr4869Q+WtLYSTjmorWnxE+lKqgcgtHLvgUt8AEfiaPcFg sOEztaOI0WUZChrnrHykwYKHTjixLw3FFIdv/Y0uvDm25+bD4OTNJ4TvlELvKYuQ RkE7gRtn2PlDWWXLDbz9AJJP9HU7p6kk/FBBQHngLU8Kaid2blLtlml7rw/3hwXQ RcKtUxSBH/swBKo3NmHaSmkbNNho7dYCz2yUDNPPbCJ5rbHwvAOiRmCpxAfCIYLx /fLoeTJgv9ispSIUS8rB2EvrfT9XNbLmT3W0sGADIlOukXkd1ptBHxWGVHCy3g01 D3ywNHK6l2A78HnrorIcXaIWuIfF6Rv2tZclbzif45H6inmYw2kOt6McIAWX+MoU rgDXxPPAFBB1azSgG7WZYPNcsMVXTjbSMoS/ng== -----END CERTIFICATE----- efitools-1.9.2/ms-uefi.crt000066400000000000000000000041631341522017100154260ustar00rootroot00000000000000-----BEGIN CERTIFICATE----- MIIGEDCCA/igAwIBAgIKYQjTxAAAAAAABDANBgkqhkiG9w0BAQsFADCBkTELMAkG A1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQx HjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjE7MDkGA1UEAxMyTWljcm9z b2Z0IENvcnBvcmF0aW9uIFRoaXJkIFBhcnR5IE1hcmtldHBsYWNlIFJvb3QwHhcN MTEwNjI3MjEyMjQ1WhcNMjYwNjI3MjEzMjQ1WjCBgTELMAkGA1UEBhMCVVMxEzAR BgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1p Y3Jvc29mdCBDb3Jwb3JhdGlvbjErMCkGA1UEAxMiTWljcm9zb2Z0IENvcnBvcmF0 aW9uIFVFRkkgQ0EgMjAxMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB AKUIbEzHRQlqSwykwId/BnUMQwFUZOAWfwftkn0LsnO/DArGSkVhoMUWLZbT9Sug +01Jm0GAkDy5VP3mvNGdxKQYin9BilxZg2gyu4xHye5xvCFPmop8/0Q/jY8ysiZI rnW17slMHkoZfuSCmh14d00MsL32D9MW07z6K6VROF31+7rbeALb/+wKG5bVg7gZ E+m2wHtAe+EfKCfJ+u9WXhzmfpR+wPBEsnk55dqyYotNvzhw4mgkFMkzpAg31Vhp XtN87cEEUwjnTrAqh2MIYW9jFVnqsit51wxhZ4pb/V6th3+6hmdPcVgSIgQiIs6L 71RxAM5QNVh2lQjuarGiAdUCAwEAAaOCAXYwggFyMBIGCSsGAQQBgjcVAQQFAgMB AAEwIwYJKwYBBAGCNxUCBBYEFPjBa7d/d1NK8yU3HU6hJnsPIHCAMB0GA1UdDgQW BBQTrb9DCb2CcJyM1U8xbtUimIob1DAZBgkrBgEEAYI3FAIEDB4KAFMAdQBiAEMA QTALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBRFZlJD 4X5YEb/WTp4jVQg7OiJqqDBcBgNVHR8EVTBTMFGgT6BNhktodHRwOi8vY3JsLm1p Y3Jvc29mdC5jb20vcGtpL2NybC9wcm9kdWN0cy9NaWNDb3JUaGlQYXJNYXJSb29f MjAxMC0xMC0wNS5jcmwwYAYIKwYBBQUHAQEEVDBSMFAGCCsGAQUFBzAChkRodHRw Oi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpL2NlcnRzL01pY0NvclRoaVBhck1hclJv b18yMDEwLTEwLTA1LmNydDANBgkqhkiG9w0BAQsFAAOCAgEANQhC/zDMzvd2DK0Q aFg1KUYydid87xJBJ0IbSqptgThIWRNV8+lYNKYWC4KqXa2C2oCDQQaPtB3yA7nz Gl0b8VCQ+bNVhEIoHCC9sq5RFMXArJeVIRyQ2w/8d56Vc5GIyr29UrkFUA3fV56g Ye0N5W0l2UAPF0DIzqNKwk2vmhIdCFSPvce8uSs9SSsfMvxqIWlPm8h+QjT8NgYX i48gQMCzmiV1J83JA6P2XdHnNlR6uVC10xLRB7+7dN/cHo+A1e0Y9C8UFmsv3maM sCPlx4TY7erBM4KtVksYLfFolQfNz/By8K673YaFmCwhTDMr8A9K8GiHtZJVMnWh aoJqPKMlEaTtrdcErsvYQFmghNGVTGKRIhp0HYw9Rw5EpuSwmzQ1sfq2U6gsgeyk BXHInbi66BtEZuRHVA6OVn+znxaYsobQaD6QI7UvXo9QhY3GjYJfQaH0Lg3gmdJs deS2abUhhvoH0fbiTdHarSx3Ux4lMjfHbFJylYaw8TVhahn1sjuBUFamMi3+oon5 QoYnGFWhgspam/gwmFQUpkeWJS/IJuRBlBpcAj/lluOFWzw+P7tHFnJV4iUisdl7 5wMGKqP3HpBGwwAN1hmJ4w41J2IDcRWm79AnoKBZN2D4OJS44Hhw+LpMhoeU9uCu AkXuZcK2o35pFnUHkpv1prxZg1g= -----END CERTIFICATE----- efitools-1.9.2/sig-list-to-certs.c000066400000000000000000000060431341522017100170030ustar00rootroot00000000000000/* * Copyright 2012 * * see COPYING file */ #include #define __STDC_VERSION__ 199901L #include #ifdef CONFIG_arm /* FIXME: * arm efi leaves a visibilit pragma pushed that won't work for * non efi programs, so eliminate it */ #pragma GCC visibility pop #endif #include #include #include #include #include #include #include #include #include #include #include int main(int argc, char *argv[]) { char *certfile, *efifile, *name, *esl_name; const char *progname = argv[0]; int output_esl = 0; if (argc != 3 && argc != 4) { printf("Usage: %s \n", progname); exit(1); } if (strcmp("-e", argv[1]) == 0) { output_esl = 1; argc--; argv++; } efifile = argv[1]; certfile = argv[2]; name = malloc(strlen(certfile)+10); esl_name = malloc(strlen(certfile)+10); int fd = open(efifile, O_RDONLY); if (fd < 0) { fprintf(stderr, "Failed to open file %s: ", efifile); perror(""); exit(1); } struct stat st; if (fstat(fd, &st) < 0) { fprintf(stderr, "Failed to stat file %s: ", efifile); perror(""); exit(1); } void *buf = malloc(st.st_size); if (!buf) { fprintf(stderr, "Malloc failed: "); perror(""); exit(1); } if (read(fd, buf, st.st_size) != st.st_size) { fprintf(stderr, "Failed to read %d bytes from %s: ", (int)st.st_size, efifile); perror(""); exit(1); } close(fd); EFI_SIGNATURE_LIST *sl; int s, count = 0; certlist_for_each_certentry(sl, buf, s, st.st_size) { EFI_SIGNATURE_DATA *sd; const char *ext; certentry_for_each_cert(sd, sl) { FILE *g; if (memcmp(&sl->SignatureType, &EFI_CERT_X509_GUID, sizeof(EFI_GUID)) == 0) { printf("X509 "); ext = "der"; } else if (memcmp(&sl->SignatureType, &EFI_CERT_TYPE_PKCS7_GUID, sizeof(EFI_GUID)) == 0) { printf("PKCS7 "); ext = "pk7"; } else if (memcmp(&sl->SignatureType, &EFI_CERT_RSA2048_GUID, sizeof(EFI_GUID)) == 0) { printf("RSA2048 "); ext = "rsa"; } else if (memcmp(&sl->SignatureType, &EFI_CERT_SHA256_GUID, sizeof(EFI_GUID)) == 0) { printf("SHA256 "); ext = "hash"; } else { printf("UNKNOWN "); ext = "txt"; } printf("Header sls=%d, header=%d, sig=%d\n", sl->SignatureListSize, sl->SignatureHeaderSize, sl->SignatureSize - (UINT32)OFFSET_OF(EFI_SIGNATURE_DATA, SignatureData)); EFI_GUID *guid = &sd->SignatureOwner; sprintf(esl_name, "%s-%d.esl",certfile,count); sprintf(name, "%s-%d.%s",certfile,count++,ext); printf("file %s: Guid %s\n", name, guid_to_str(guid)); if (output_esl) { g = fopen(esl_name, "w"); fwrite(sl, 1, sl->SignatureListSize, g); fclose(g); } g = fopen(name, "w"); fwrite(sd->SignatureData, 1, sl->SignatureSize - OFFSET_OF(EFI_SIGNATURE_DATA, SignatureData), g); printf("Written %d bytes\n", sl->SignatureSize - (UINT32)OFFSET_OF(EFI_SIGNATURE_DATA, SignatureData)); fclose(g); } } return 0; } efitools-1.9.2/sign-efi-sig-list.c000066400000000000000000000212631341522017100167450ustar00rootroot00000000000000/* * Copyright 2012 * * see COPYING file */ #include #define __STDC_VERSION__ 199901L #include #ifdef CONFIG_arm /* FIXME: * arm efi leaves a visibilit pragma pushed that won't work for * non efi programs, so eliminate it */ #pragma GCC visibility pop #endif #include #include #include #include #include #include #include #include #include #include #include #include #include static void usage(const char *progname) { printf("Usage: %s [-r] [-m] [-a] [-g ] [-o] [-t ] [-i ] [-c ] [-k ] [-e ] \n", progname); } static void help(const char *progname) { usage(progname); printf("Produce an output file with an authentication header for direct\n" "update to a secure variable. This output may be signed by the usual keys directly\n" "or may be split for external signing using the -o and -i options.\n\n" "Options:\n" "\t-r the certificate is rsa2048 rather than x509 [UNIMPLEMENTED]\n" "\t-m Use a monotonic count instead of a timestamp [UNIMPLEMENTED]\n" "\t-a Prepare the variable for APPEND_WRITE rather than replacement\n" "\t-o Do not sign, but output a file of the exact bundle to be signed\n" "\t-t Use as the timestamp of the timed variable update\n" "\t If not present, then the timestamp will be taken from system\n" "\t time. Note you must use this option when doing detached\n" "\t signing otherwise the signature will be incorrect because\n" "\t of timestamp mismatches.\n" "\t-i take a detached signature (in PEM format) of the bundle\n" "\t produced by -o and complete the creation of the update\n" "\t-g Use as the signature owner GUID\n" "\t-c is the file containing the signing certificate in PEM format\n" "\t-k is the file containing the key for in PEM format\n" "\t-e Use openssl engine for the private key\n" ); } int main(int argc, char *argv[]) { char *certfile = NULL, *efifile, *keyfile = NULL, *outfile, *str, *signedinput = NULL, *timestampstr = NULL; void *out; const char *progname = argv[0]; char *engine = NULL; unsigned char *sigbuf; int rsasig = 0, monotonic = 0, varlen, i, outputforsign = 0, outlen, sigsize; EFI_GUID vendor_guid; struct stat st; wchar_t var[256]; UINT32 attributes = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS; EFI_TIME timestamp = { 0 }; while (argc > 1) { if (strcmp("--version", argv[1]) == 0) { version(progname); exit(0); } else if (strcmp("--help", argv[1]) == 0) { help(progname); exit(0); } else if (strcmp("-g", argv[1]) == 0) { str_to_guid(argv[2], &vendor_guid); argv += 2; argc -= 2; } else if (strcmp("-r", argv[1]) == 0) { rsasig = 1; argv += 1; argc -= 1; } else if (strcmp("-t", argv[1]) == 0) { timestampstr = argv[2]; argv += 2; argc -= 2; } else if (strcmp("-m", argv[1]) == 0) { monotonic = 1; argv += 1; argc -= 1; attributes &= ~EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS; attributes |= EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS; } else if (strcmp("-o", argv[1]) == 0) { outputforsign = 1; argv += 1; argc -= 1; } else if (strcmp("-i", argv[1]) == 0) { signedinput = argv[2]; argv += 2; argc -= 2; } else if (strcmp("-a", argv[1]) == 0) { attributes |= EFI_VARIABLE_APPEND_WRITE; argv += 1; argc -= 1; } else if (strcmp("-k", argv[1]) == 0) { keyfile = argv[2]; argv += 2; argc -= 2; } else if (strcmp("-c", argv[1]) == 0) { certfile = argv[2]; argv += 2; argc -= 2; } else if (strcmp("-e", argv[1]) == 0) { engine = argv[2]; argv += 2; argc -= 2; } else { break; } } if (argc != 4) { usage(progname); exit(1); } if (rsasig || monotonic) { fprintf(stderr, "FIXME: rsa signatures and monotonic payloads are not implemented\n"); exit(1); } str = argv[1]; efifile = argv[2]; outfile = argv[3]; /* Specific GUIDs for special variables */ if (strcmp(str, "PK") == 0 || strcmp(str, "KEK") == 0) { vendor_guid = (EFI_GUID)EFI_GLOBAL_VARIABLE; } else if (strcmp(str, "db") == 0 || strcmp(str, "dbx") == 0) { vendor_guid = (EFI_GUID){ 0xd719b2cb, 0x3d3a, 0x4596, {0xa3, 0xbc, 0xda, 0xd0, 0xe, 0x67, 0x65, 0x6f }}; } memset(×tamp, 0, sizeof(timestamp)); time_t t; struct tm *tm, tms; memset(&tms, 0, sizeof(tms)); if (timestampstr) { strptime(timestampstr, "%Y-%m-%d %H:%M:%S", &tms); tm = &tms; /* timestamp.Year is from 0 not 1900 as tm year is */ tm->tm_year += 1900; tm->tm_mon += 1; /* tm_mon is 0-11 not 1-12 */ } else if (attributes & EFI_VARIABLE_APPEND_WRITE) { /* for append update timestamp should be zero */ memset(&tms, 0, sizeof(tms)); tm = &tms; } else { time(&t); tm = localtime(&t); /* timestamp.Year is from 0 not 1900 as tm year is */ tm->tm_year += 1900; tm->tm_mon += 1; /* tm_mon is 0-11 not 1-12 */ } timestamp.Year = tm->tm_year; timestamp.Month = tm->tm_mon; timestamp.Day = tm->tm_mday; timestamp.Hour = tm->tm_hour; timestamp.Minute = tm->tm_min; timestamp.Second = tm->tm_sec; printf("Timestamp is %d-%d-%d %02d:%02d:%02d\n", timestamp.Year, timestamp.Month, timestamp.Day, timestamp.Hour, timestamp.Minute, timestamp.Second); /* Warning: don't use any glibc wchar functions. We're building * with -fshort-wchar which breaks the glibc ABI */ i = 0; do { var[i] = str[i]; } while (str[i++] != '\0'); varlen = (i - 1)*sizeof(wchar_t); int fdefifile = open(efifile, O_RDONLY); if (fdefifile == -1) { fprintf(stderr, "failed to open file %s: ", efifile); perror(""); exit(1); } fstat(fdefifile, &st); /* signature is over variable name (no null), the vendor GUID, the * attributes, the timestamp and the contents */ int signbuflen = varlen + sizeof(EFI_GUID) + sizeof(UINT32) + sizeof(EFI_TIME) + st.st_size; char *signbuf = malloc(signbuflen); char *ptr = signbuf; memcpy(ptr, var, varlen); ptr += varlen; memcpy(ptr, &vendor_guid, sizeof(vendor_guid)); ptr += sizeof(vendor_guid); memcpy(ptr, &attributes, sizeof(attributes)); ptr += sizeof(attributes); memcpy(ptr, ×tamp, sizeof(timestamp)); ptr += sizeof(timestamp); read(fdefifile, ptr, st.st_size); printf("Authentication Payload size %d\n", signbuflen); if (outputforsign) { out = signbuf; outlen = signbuflen; goto output; } if (signedinput) { struct stat sti; int infile = open(signedinput, O_RDONLY); if (infile == -1) { fprintf(stderr, "failed to open file %s: ", signedinput); perror(""); exit(1); } fstat(infile, &sti); sigbuf = malloc(sti.st_size); sigsize = sti.st_size; read(infile, sigbuf, sigsize); } else { if (!keyfile || !certfile) { fprintf(stderr, "Doing signing, need certificate and key\n"); exit(1); } if (sign_efi_var(signbuf, signbuflen, keyfile, certfile, &sigbuf, &sigsize, engine)) exit(1); } printf("Signature of size %d\n", sigsize); EFI_VARIABLE_AUTHENTICATION_2 *var_auth = malloc(sizeof(EFI_VARIABLE_AUTHENTICATION_2) + sigsize); var_auth->TimeStamp = timestamp; var_auth->AuthInfo.CertType = EFI_CERT_TYPE_PKCS7_GUID; var_auth->AuthInfo.Hdr.dwLength = sigsize + OFFSET_OF(WIN_CERTIFICATE_UEFI_GUID, CertData); var_auth->AuthInfo.Hdr.wRevision = 0x0200; var_auth->AuthInfo.Hdr.wCertificateType = WIN_CERT_TYPE_EFI_GUID; memcpy(var_auth->AuthInfo.CertData, sigbuf, sigsize); sigbuf = var_auth->AuthInfo.CertData; if (!signedinput) { printf("Signature at: %ld\n", sigbuf - (unsigned char *)var_auth); } out = var_auth; outlen = OFFSET_OF(EFI_VARIABLE_AUTHENTICATION_2, AuthInfo.CertData) + sigsize; output: ; int fdoutfile = open(outfile, O_CREAT|O_WRONLY|O_TRUNC, S_IWUSR|S_IRUSR); if (fdoutfile == -1) { fprintf(stderr, "failed to open %s: ", outfile); perror(""); exit(1); } /* first we write the authentication header */ write(fdoutfile, out, outlen); if (!outputforsign) /* Then we write the payload */ write(fdoutfile, ptr, st.st_size); /* so now the file is complete and can be fed straight into * SetVariable() as an authenticated variable update */ #if 0 write (fdoutfile, var_auth->AuthInfo.CertData, sigsize); #endif close(fdoutfile); return 0; } efitools-1.9.2/xxdi.pl000077500000000000000000000024441341522017100146630ustar00rootroot00000000000000#!/usr/bin/env perl # # xxdi.pl - perl implementation of 'xxd -i' mode # # Copyright 2013 Greg Kroah-Hartman # Copyright 2013 Linux Foundation # # Released under the GPLv2. # # Implements the "basic" functionality of 'xxd -i' in perl to keep build # systems from having to build/install/rely on vim-core, which not all # distros want to do. But everyone has perl, so use it instead. # use strict; use warnings; use File::Slurp qw(slurp); my $indata = slurp(@ARGV ? $ARGV[0] : \*STDIN); my $len_data = length($indata); my $num_digits_per_line = 12; my $var_name; my $outdata; # Use the variable name of the file we read from, converting '/' and '. # to '_', or, if this is stdin, just use "stdin" as the name. if (@ARGV) { $var_name = $ARGV[0]; $var_name =~ s/\//_/g; $var_name =~ s/\./_/g; } else { $var_name = "stdin"; } $outdata .= "unsigned char $var_name\[] = {"; # trailing ',' is acceptable, so instead of duplicating the logic for # just the last character, live with the extra ','. for (my $key= 0; $key < $len_data; $key++) { if ($key % $num_digits_per_line == 0) { $outdata .= "\n\t"; } $outdata .= sprintf("0x%.2x, ", ord(substr($indata, $key, 1))); } $outdata .= "\n};\nunsigned int $var_name\_len = $len_data;\n"; binmode STDOUT; print {*STDOUT} $outdata;