summaryrefslogtreecommitdiff
path: root/util/ldid-xerub
diff options
context:
space:
mode:
Diffstat (limited to 'util/ldid-xerub')
-rw-r--r--util/ldid-xerub/.gitignore8
-rw-r--r--util/ldid-xerub/.gitmodules0
-rw-r--r--util/ldid-xerub/COPYING661
-rw-r--r--util/ldid-xerub/Makefile2
-rw-r--r--util/ldid-xerub/README.md21
-rwxr-xr-xutil/ldid-xerub/aridbin0 -> 17776 bytes
-rw-r--r--util/ldid-xerub/arid.cpp30
-rw-r--r--util/ldid-xerub/control11
-rwxr-xr-xutil/ldid-xerub/control.sh5
-rwxr-xr-xutil/ldid-xerub/ios.sh17
-rwxr-xr-xutil/ldid-xerub/ldidbin0 -> 143432 bytes
-rw-r--r--util/ldid-xerub/ldid.cpp1362
-rwxr-xr-xutil/ldid-xerub/ldid2bin0 -> 152504 bytes
-rw-r--r--util/ldid-xerub/ldid2.cpp1362
-rw-r--r--util/ldid-xerub/lookup2.c416
-rwxr-xr-xutil/ldid-xerub/make.sh32
-rw-r--r--util/ldid-xerub/minimal/hexdump.h76
-rw-r--r--util/ldid-xerub/minimal/mapping.h72
-rw-r--r--util/ldid-xerub/minimal/sqlite3.h71
-rw-r--r--util/ldid-xerub/minimal/stdlib.h129
-rw-r--r--util/ldid-xerub/minimal/string.h51
-rw-r--r--util/ldid-xerub/sha-private.h28
-rw-r--r--util/ldid-xerub/sha.h356
-rw-r--r--util/ldid-xerub/sha1.c389
-rw-r--r--util/ldid-xerub/sha1.h64
-rw-r--r--util/ldid-xerub/sha224-256.c581
-rwxr-xr-xutil/ldid-xerub/version.sh2
27 files changed, 5746 insertions, 0 deletions
diff --git a/util/ldid-xerub/.gitignore b/util/ldid-xerub/.gitignore
new file mode 100644
index 000000000..30eb3b36d
--- /dev/null
+++ b/util/ldid-xerub/.gitignore
@@ -0,0 +1,8 @@
+ldid.arm
+ldid.o
+ldid.deb
+ldid2.arm
+ldid2.o
+ldid2.deb
+debs
+_
diff --git a/util/ldid-xerub/.gitmodules b/util/ldid-xerub/.gitmodules
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/util/ldid-xerub/.gitmodules
diff --git a/util/ldid-xerub/COPYING b/util/ldid-xerub/COPYING
new file mode 100644
index 000000000..dba13ed2d
--- /dev/null
+++ b/util/ldid-xerub/COPYING
@@ -0,0 +1,661 @@
+ GNU AFFERO GENERAL PUBLIC LICENSE
+ Version 3, 19 November 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU Affero General Public License is a free, copyleft license for
+software and other kinds of works, specifically designed to ensure
+cooperation with the community in the case of network server software.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+our General Public Licenses are intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users.
+
+ 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
+them 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.
+
+ Developers that use our General Public Licenses protect your rights
+with two steps: (1) assert copyright on the software, and (2) offer
+you this License which gives you legal permission to copy, distribute
+and/or modify the software.
+
+ A secondary benefit of defending all users' freedom is that
+improvements made in alternate versions of the program, if they
+receive widespread use, become available for other developers to
+incorporate. Many developers of free software are heartened and
+encouraged by the resulting cooperation. However, in the case of
+software used on network servers, this result may fail to come about.
+The GNU General Public License permits making a modified version and
+letting the public access it on a server without ever releasing its
+source code to the public.
+
+ The GNU Affero General Public License is designed specifically to
+ensure that, in such cases, the modified source code becomes available
+to the community. It requires the operator of a network server to
+provide the source code of the modified version running there to the
+users of that server. Therefore, public use of a modified version, on
+a publicly accessible server, gives the public access to the source
+code of the modified version.
+
+ An older license, called the Affero General Public License and
+published by Affero, was designed to accomplish similar goals. This is
+a different license, not a version of the Affero GPL, but Affero has
+released a new version of the Affero GPL which permits relicensing under
+this license.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU Affero General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey 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;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If 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 convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Remote Network Interaction; Use with the GNU General Public License.
+
+ Notwithstanding any other provision of this License, if you modify the
+Program, your modified version must prominently offer all users
+interacting with it remotely through a computer network (if your version
+supports such interaction) an opportunity to receive the Corresponding
+Source of your version by providing access to the Corresponding Source
+from a network server at no charge, through some standard or customary
+means of facilitating copying of software. This Corresponding Source
+shall include the Corresponding Source for any work covered by version 3
+of the GNU General Public License that is incorporated pursuant to the
+following paragraph.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the work with which it is combined will remain governed by version
+3 of the GNU General Public License.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU Affero 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 that a certain numbered version of the GNU Affero General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU Affero General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU Affero General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ 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.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+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.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ 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
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 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 Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If your software can interact with users remotely through a computer
+network, you should also make sure that it provides a way for users to
+get its source. For example, if your program is a web application, its
+interface could display a "Source" link that leads users to an archive
+of the code. There are many ways you could offer source, and different
+solutions will be better for different programs; see section 13 for the
+specific requirements.
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU AGPL, see
+<http://www.gnu.org/licenses/>.
diff --git a/util/ldid-xerub/Makefile b/util/ldid-xerub/Makefile
new file mode 100644
index 000000000..f318ab23f
--- /dev/null
+++ b/util/ldid-xerub/Makefile
@@ -0,0 +1,2 @@
+all:
+ sh make.sh \ No newline at end of file
diff --git a/util/ldid-xerub/README.md b/util/ldid-xerub/README.md
new file mode 100644
index 000000000..32ef83724
--- /dev/null
+++ b/util/ldid-xerub/README.md
@@ -0,0 +1,21 @@
+# ldid
+
+This is simply a small update to [xerub's unofficial fork](https://github.com/xerub/ldid), originally from saurik's repo `git://git.saurik.com/ldid.git`. This has been updated to compile for ldid2 which is necessary for some iOS jailbreaks.
+
+`ldid` and `ldid2` macOS binaries are provided for convenience.
+
+# Compiling
+
+To compile from source:
+```
+make
+```
+
+# Troubleshooting
+
+If you're trying to install something like [Electra jailbreak](https://github.com/coolstar/electra) from source, you'll want to:
+```
+cp ldid2 /usr/local/bin
+```
+
+-samy \ No newline at end of file
diff --git a/util/ldid-xerub/arid b/util/ldid-xerub/arid
new file mode 100755
index 000000000..1699d16e3
--- /dev/null
+++ b/util/ldid-xerub/arid
Binary files differ
diff --git a/util/ldid-xerub/arid.cpp b/util/ldid-xerub/arid.cpp
new file mode 100644
index 000000000..99b4ae85b
--- /dev/null
+++ b/util/ldid-xerub/arid.cpp
@@ -0,0 +1,30 @@
+#include <iostream>
+#include <string.h>
+#include "minimal/mapping.h"
+
+struct ar_hdr {
+ char ar_name[16];
+ char ar_date[12];
+ char ar_uid[6];
+ char ar_gid[6];
+ char ar_mode[8];
+ char ar_size[10];
+#define ARFMAG "`\n"
+ char ar_fmag[2];
+};
+
+int main(int argc, char *argv[]) {
+ size_t size;
+ _assert(argc == 2);
+ uint8_t *data = reinterpret_cast<uint8_t *>(map(argv[1], 0, _not(size_t), &size, false));
+ data += 8;
+ uint8_t *end = data + size;
+ while (end - data >= sizeof(struct ar_hdr)) {
+ struct ar_hdr *head = reinterpret_cast<struct ar_hdr *>(data);
+ memset(head->ar_date + 1, ' ', sizeof(head->ar_date) - 1);
+ head->ar_date[0] = '0';
+ size_t length = strtoul(head->ar_size, NULL, 10);
+ data += length + sizeof(struct ar_hdr);
+ }
+ return 0;
+}
diff --git a/util/ldid-xerub/control b/util/ldid-xerub/control
new file mode 100644
index 000000000..9accbb845
--- /dev/null
+++ b/util/ldid-xerub/control
@@ -0,0 +1,11 @@
+Package: ldid
+Priority: optional
+Section: Development
+Maintainer: Jay Freeman (saurik) <saurik@saurik.com>
+Architecture: iphoneos-arm
+Version:
+Description: pseudo-codesign Mach-O files
+Name: Link Identity Editor
+Author: Jay Freeman (saurik) <saurik@saurik.com>
+Depiction: http://cydia.saurik.com/info/ldid/
+Tag: purpose::console, role::developer
diff --git a/util/ldid-xerub/control.sh b/util/ldid-xerub/control.sh
new file mode 100755
index 000000000..7a11d56ac
--- /dev/null
+++ b/util/ldid-xerub/control.sh
@@ -0,0 +1,5 @@
+#!/bin/bash
+dir=$1
+dir=${dir:=_}
+sed -e "s@^\(Version:.*\)@\1$(./version.sh)@" control
+echo "Installed-Size: $(du -s "${dir}" | cut -f 1)"
diff --git a/util/ldid-xerub/ios.sh b/util/ldid-xerub/ios.sh
new file mode 100755
index 000000000..a9dae809e
--- /dev/null
+++ b/util/ldid-xerub/ios.sh
@@ -0,0 +1,17 @@
+#!/bin/bash
+
+set -e -x
+
+sudo xcode-select --switch /Applications/Xcode-4.6.3.app
+cycc -i2.0 -oldid.arm -- -c -std=c++11 ldid.cpp -I.
+cycc -i2.0 -oldid.arm -- ldid.arm -x c sha1.c lookup2.c -I .
+
+rm -rf _
+mkdir -p _/usr/bin
+cp -a ldid.arm _/usr/bin/ldid
+mkdir -p _/DEBIAN
+./control.sh _ >_/DEBIAN/control
+mkdir -p debs
+ln -sf debs/ldid_$(./version.sh)_iphoneos-arm.deb ldid.deb
+dpkg-deb -b _ ldid.deb
+readlink ldid.deb
diff --git a/util/ldid-xerub/ldid b/util/ldid-xerub/ldid
new file mode 100755
index 000000000..5593ed10e
--- /dev/null
+++ b/util/ldid-xerub/ldid
Binary files differ
diff --git a/util/ldid-xerub/ldid.cpp b/util/ldid-xerub/ldid.cpp
new file mode 100644
index 000000000..7238767c9
--- /dev/null
+++ b/util/ldid-xerub/ldid.cpp
@@ -0,0 +1,1362 @@
+/* ldid - (Mach-O) Link-Loader Identity Editor
+ * Copyright (C) 2007-2012 Jay Freeman (saurik)
+*/
+
+/* GNU Affero General Public License, Version 3 {{{ */
+/*
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 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 Affero General Public License for more details.
+
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+**/
+/* }}} */
+
+#include "minimal/stdlib.h"
+#include "minimal/string.h"
+#include "minimal/mapping.h"
+
+extern "C" {
+#include "sha1.h"
+}
+
+#include <cstring>
+#include <string>
+#include <vector>
+
+struct fat_header {
+ uint32_t magic;
+ uint32_t nfat_arch;
+} _packed;
+
+#define FAT_MAGIC 0xcafebabe
+#define FAT_CIGAM 0xbebafeca
+
+struct fat_arch {
+ uint32_t cputype;
+ uint32_t cpusubtype;
+ uint32_t offset;
+ uint32_t size;
+ uint32_t align;
+} _packed;
+
+struct mach_header {
+ uint32_t magic;
+ uint32_t cputype;
+ uint32_t cpusubtype;
+ uint32_t filetype;
+ uint32_t ncmds;
+ uint32_t sizeofcmds;
+ uint32_t flags;
+} _packed;
+
+#define MH_MAGIC 0xfeedface
+#define MH_CIGAM 0xcefaedfe
+
+#define MH_MAGIC_64 0xfeedfacf
+#define MH_CIGAM_64 0xcffaedfe
+
+#define MH_DYLDLINK 0x4
+
+#define MH_OBJECT 0x1
+#define MH_EXECUTE 0x2
+#define MH_DYLIB 0x6
+#define MH_BUNDLE 0x8
+#define MH_DYLIB_STUB 0x9
+
+struct load_command {
+ uint32_t cmd;
+ uint32_t cmdsize;
+} _packed;
+
+#define LC_REQ_DYLD uint32_t(0x80000000)
+
+#define LC_SEGMENT uint32_t(0x01)
+#define LC_SYMTAB uint32_t(0x02)
+#define LC_DYSYMTAB uint32_t(0x0b)
+#define LC_LOAD_DYLIB uint32_t(0x0c)
+#define LC_ID_DYLIB uint32_t(0x0d)
+#define LC_SEGMENT_64 uint32_t(0x19)
+#define LC_UUID uint32_t(0x1b)
+#define LC_CODE_SIGNATURE uint32_t(0x1d)
+#define LC_SEGMENT_SPLIT_INFO uint32_t(0x1e)
+#define LC_REEXPORT_DYLIB uint32_t(0x1f | LC_REQ_DYLD)
+#define LC_ENCRYPTION_INFO uint32_t(0x21)
+#define LC_DYLD_INFO uint32_t(0x22)
+#define LC_DYLD_INFO_ONLY uint32_t(0x22 | LC_REQ_DYLD)
+
+struct dylib {
+ uint32_t name;
+ uint32_t timestamp;
+ uint32_t current_version;
+ uint32_t compatibility_version;
+} _packed;
+
+struct dylib_command {
+ uint32_t cmd;
+ uint32_t cmdsize;
+ struct dylib dylib;
+} _packed;
+
+struct uuid_command {
+ uint32_t cmd;
+ uint32_t cmdsize;
+ uint8_t uuid[16];
+} _packed;
+
+struct symtab_command {
+ uint32_t cmd;
+ uint32_t cmdsize;
+ uint32_t symoff;
+ uint32_t nsyms;
+ uint32_t stroff;
+ uint32_t strsize;
+} _packed;
+
+struct dyld_info_command {
+ uint32_t cmd;
+ uint32_t cmdsize;
+ uint32_t rebase_off;
+ uint32_t rebase_size;
+ uint32_t bind_off;
+ uint32_t bind_size;
+ uint32_t weak_bind_off;
+ uint32_t weak_bind_size;
+ uint32_t lazy_bind_off;
+ uint32_t lazy_bind_size;
+ uint32_t export_off;
+ uint32_t export_size;
+} _packed;
+
+struct dysymtab_command {
+ uint32_t cmd;
+ uint32_t cmdsize;
+ uint32_t ilocalsym;
+ uint32_t nlocalsym;
+ uint32_t iextdefsym;
+ uint32_t nextdefsym;
+ uint32_t iundefsym;
+ uint32_t nundefsym;
+ uint32_t tocoff;
+ uint32_t ntoc;
+ uint32_t modtaboff;
+ uint32_t nmodtab;
+ uint32_t extrefsymoff;
+ uint32_t nextrefsyms;
+ uint32_t indirectsymoff;
+ uint32_t nindirectsyms;
+ uint32_t extreloff;
+ uint32_t nextrel;
+ uint32_t locreloff;
+ uint32_t nlocrel;
+} _packed;
+
+struct dylib_table_of_contents {
+ uint32_t symbol_index;
+ uint32_t module_index;
+} _packed;
+
+struct dylib_module {
+ uint32_t module_name;
+ uint32_t iextdefsym;
+ uint32_t nextdefsym;
+ uint32_t irefsym;
+ uint32_t nrefsym;
+ uint32_t ilocalsym;
+ uint32_t nlocalsym;
+ uint32_t iextrel;
+ uint32_t nextrel;
+ uint32_t iinit_iterm;
+ uint32_t ninit_nterm;
+ uint32_t objc_module_info_addr;
+ uint32_t objc_module_info_size;
+} _packed;
+
+struct dylib_reference {
+ uint32_t isym:24;
+ uint32_t flags:8;
+} _packed;
+
+struct relocation_info {
+ int32_t r_address;
+ uint32_t r_symbolnum:24;
+ uint32_t r_pcrel:1;
+ uint32_t r_length:2;
+ uint32_t r_extern:1;
+ uint32_t r_type:4;
+} _packed;
+
+struct nlist {
+ union {
+ char *n_name;
+ int32_t n_strx;
+ } n_un;
+
+ uint8_t n_type;
+ uint8_t n_sect;
+ uint8_t n_desc;
+ uint32_t n_value;
+} _packed;
+
+struct segment_command {
+ uint32_t cmd;
+ uint32_t cmdsize;
+ char segname[16];
+ uint32_t vmaddr;
+ uint32_t vmsize;
+ uint32_t fileoff;
+ uint32_t filesize;
+ uint32_t maxprot;
+ uint32_t initprot;
+ uint32_t nsects;
+ uint32_t flags;
+} _packed;
+
+struct segment_command_64 {
+ uint32_t cmd;
+ uint32_t cmdsize;
+ char segname[16];
+ uint64_t vmaddr;
+ uint64_t vmsize;
+ uint64_t fileoff;
+ uint64_t filesize;
+ uint32_t maxprot;
+ uint32_t initprot;
+ uint32_t nsects;
+ uint32_t flags;
+} _packed;
+
+struct section {
+ char sectname[16];
+ char segname[16];
+ uint32_t addr;
+ uint32_t size;
+ uint32_t offset;
+ uint32_t align;
+ uint32_t reloff;
+ uint32_t nreloc;
+ uint32_t flags;
+ uint32_t reserved1;
+ uint32_t reserved2;
+} _packed;
+
+struct section_64 {
+ char sectname[16];
+ char segname[16];
+ uint64_t addr;
+ uint64_t size;
+ uint32_t offset;
+ uint32_t align;
+ uint32_t reloff;
+ uint32_t nreloc;
+ uint32_t flags;
+ uint32_t reserved1;
+ uint32_t reserved2;
+} _packed;
+
+struct linkedit_data_command {
+ uint32_t cmd;
+ uint32_t cmdsize;
+ uint32_t dataoff;
+ uint32_t datasize;
+} _packed;
+
+struct encryption_info_command {
+ uint32_t cmd;
+ uint32_t cmdsize;
+ uint32_t cryptoff;
+ uint32_t cryptsize;
+ uint32_t cryptid;
+} _packed;
+
+#define BIND_OPCODE_MASK 0xf0
+#define BIND_IMMEDIATE_MASK 0x0f
+#define BIND_OPCODE_DONE 0x00
+#define BIND_OPCODE_SET_DYLIB_ORDINAL_IMM 0x10
+#define BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB 0x20
+#define BIND_OPCODE_SET_DYLIB_SPECIAL_IMM 0x30
+#define BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM 0x40
+#define BIND_OPCODE_SET_TYPE_IMM 0x50
+#define BIND_OPCODE_SET_ADDEND_SLEB 0x60
+#define BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB 0x70
+#define BIND_OPCODE_ADD_ADDR_ULEB 0x80
+#define BIND_OPCODE_DO_BIND 0x90
+#define BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB 0xa0
+#define BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED 0xb0
+#define BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB 0xc0
+
+template <typename Type_>
+Type_ Align(Type_ value, size_t align) {
+ value += align - 1;
+ value /= align;
+ value *= align;
+ return value;
+}
+
+uint16_t Swap_(uint16_t value) {
+ return
+ ((value >> 8) & 0x00ff) |
+ ((value << 8) & 0xff00);
+}
+
+uint32_t Swap_(uint32_t value) {
+ value = ((value >> 8) & 0x00ff00ff) |
+ ((value << 8) & 0xff00ff00);
+ value = ((value >> 16) & 0x0000ffff) |
+ ((value << 16) & 0xffff0000);
+ return value;
+}
+
+uint64_t Swap_(uint64_t value) {
+ value = (value & 0x00000000ffffffffULL) << 32 | (value & 0xffffffff00000000ULL) >> 32;
+ value = (value & 0x0000ffff0000ffffULL) << 16 | (value & 0xffff0000ffff0000ULL) >> 16;
+ value = (value & 0x00ff00ff00ff00ffULL) << 8 | (value & 0xff00ff00ff00ff00ULL) >> 8;
+ return value;
+}
+
+int16_t Swap_(int16_t value) {
+ return Swap_(static_cast<uint16_t>(value));
+}
+
+int32_t Swap_(int32_t value) {
+ return Swap_(static_cast<uint32_t>(value));
+}
+
+int64_t Swap_(int64_t value) {
+ return Swap_(static_cast<uint64_t>(value));
+}
+
+bool little_(true);
+
+uint16_t Swap(uint16_t value) {
+ return little_ ? Swap_(value) : value;
+}
+
+uint32_t Swap(uint32_t value) {
+ return little_ ? Swap_(value) : value;
+}
+
+uint64_t Swap(uint64_t value) {
+ return little_ ? Swap_(value) : value;
+}
+
+int16_t Swap(int16_t value) {
+ return Swap(static_cast<uint16_t>(value));
+}
+
+int32_t Swap(int32_t value) {
+ return Swap(static_cast<uint32_t>(value));
+}
+
+int64_t Swap(int64_t value) {
+ return Swap(static_cast<uint64_t>(value));
+}
+
+template <typename Target_>
+class Pointer;
+
+class Data {
+ private:
+ void *base_;
+ size_t size_;
+
+ protected:
+ bool swapped_;
+
+ public:
+ Data(void *base, size_t size) :
+ base_(base),
+ size_(size),
+ swapped_(false)
+ {
+ }
+
+ uint16_t Swap(uint16_t value) const {
+ return swapped_ ? Swap_(value) : value;
+ }
+
+ uint32_t Swap(uint32_t value) const {
+ return swapped_ ? Swap_(value) : value;
+ }
+
+ uint64_t Swap(uint64_t value) const {
+ return swapped_ ? Swap_(value) : value;
+ }
+
+ int16_t Swap(int16_t value) const {
+ return Swap(static_cast<uint16_t>(value));
+ }
+
+ int32_t Swap(int32_t value) const {
+ return Swap(static_cast<uint32_t>(value));
+ }
+
+ int64_t Swap(int64_t value) const {
+ return Swap(static_cast<uint64_t>(value));
+ }
+
+ void *GetBase() const {
+ return base_;
+ }
+
+ size_t GetSize() const {
+ return size_;
+ }
+};
+
+class MachHeader :
+ public Data
+{
+ private:
+ bool bits64_;
+
+ struct mach_header *mach_header_;
+ struct load_command *load_command_;
+
+ public:
+ MachHeader(void *base, size_t size) :
+ Data(base, size)
+ {
+ mach_header_ = (mach_header *) base;
+
+ switch (Swap(mach_header_->magic)) {
+ case MH_CIGAM:
+ swapped_ = !swapped_;
+ case MH_MAGIC:
+ bits64_ = false;
+ break;
+
+ case MH_CIGAM_64:
+ swapped_ = !swapped_;
+ case MH_MAGIC_64:
+ bits64_ = true;
+ break;
+
+ default:
+ _assert(false);
+ }
+
+ void *post = mach_header_ + 1;
+ if (bits64_)
+ post = (uint32_t *) post + 1;
+ load_command_ = (struct load_command *) post;
+
+ _assert(
+ Swap(mach_header_->filetype) == MH_EXECUTE ||
+ Swap(mach_header_->filetype) == MH_DYLIB ||
+ Swap(mach_header_->filetype) == MH_BUNDLE
+ );
+ }
+
+ struct mach_header *operator ->() const {
+ return mach_header_;
+ }
+
+ operator struct mach_header *() const {
+ return mach_header_;
+ }
+
+ uint32_t GetCPUType() const {
+ return Swap(mach_header_->cputype);
+ }
+
+ uint32_t GetCPUSubtype() const {
+ return Swap(mach_header_->cpusubtype) & 0xff;
+ }
+
+ struct load_command *GetLoadCommand() const {
+ return load_command_;
+ }
+
+ std::vector<struct load_command *> GetLoadCommands() const {
+ std::vector<struct load_command *> load_commands;
+
+ struct load_command *load_command = load_command_;
+ for (uint32_t cmd = 0; cmd != Swap(mach_header_->ncmds); ++cmd) {
+ load_commands.push_back(load_command);
+ load_command = (struct load_command *) ((uint8_t *) load_command + Swap(load_command->cmdsize));
+ }
+
+ return load_commands;
+ }
+
+ std::vector<segment_command *> GetSegments(const char *segment_name) const {
+ std::vector<struct segment_command *> segment_commands;
+
+ _foreach (load_command, GetLoadCommands()) {
+ if (Swap(load_command->cmd) == LC_SEGMENT) {
+ segment_command *segment_command = reinterpret_cast<struct segment_command *>(load_command);
+ if (strncmp(segment_command->segname, segment_name, 16) == 0)
+ segment_commands.push_back(segment_command);
+ }
+ }
+
+ return segment_commands;
+ }
+
+ std::vector<segment_command_64 *> GetSegments64(const char *segment_name) const {
+ std::vector<struct segment_command_64 *> segment_commands;
+
+ _foreach (load_command, GetLoadCommands()) {
+ if (Swap(load_command->cmd) == LC_SEGMENT_64) {
+ segment_command_64 *segment_command = reinterpret_cast<struct segment_command_64 *>(load_command);
+ if (strncmp(segment_command->segname, segment_name, 16) == 0)
+ segment_commands.push_back(segment_command);
+ }
+ }
+
+ return segment_commands;
+ }
+
+ std::vector<section *> GetSections(const char *segment_name, const char *section_name) const {
+ std::vector<section *> sections;
+
+ _foreach (segment, GetSegments(segment_name)) {
+ section *section = (struct section *) (segment + 1);
+
+ uint32_t sect;
+ for (sect = 0; sect != Swap(segment->nsects); ++sect) {
+ if (strncmp(section->sectname, section_name, 16) == 0)
+ sections.push_back(section);
+ ++section;
+ }
+ }
+
+ return sections;
+ }
+
+ template <typename Target_>
+ Pointer<Target_> GetPointer(uint32_t address, const char *segment_name = NULL) const {
+ load_command *load_command = (struct load_command *) (mach_header_ + 1);
+ uint32_t cmd;
+
+ for (cmd = 0; cmd != Swap(mach_header_->ncmds); ++cmd) {
+ if (Swap(load_command->cmd) == LC_SEGMENT) {
+ segment_command *segment_command = (struct segment_command *) load_command;
+ if (segment_name != NULL && strncmp(segment_command->segname, segment_name, 16) != 0)
+ goto next_command;
+
+ section *sections = (struct section *) (segment_command + 1);
+
+ uint32_t sect;
+ for (sect = 0; sect != Swap(segment_command->nsects); ++sect) {
+ section *section = &sections[sect];
+ //printf("%s %u %p %p %u\n", segment_command->segname, sect, address, section->addr, section->size);
+ if (address >= Swap(section->addr) && address < Swap(section->addr) + Swap(section->size)) {
+ //printf("0x%.8x %s\n", address, segment_command->segname);
+ return Pointer<Target_>(this, reinterpret_cast<Target_ *>(address - Swap(section->addr) + Swap(section->offset) + (char *) mach_header_));
+ }
+ }
+ }
+
+ next_command:
+ load_command = (struct load_command *) ((char *) load_command + Swap(load_command->cmdsize));
+ }
+
+ return Pointer<Target_>(this);
+ }
+
+ template <typename Target_>
+ Pointer<Target_> GetOffset(uint32_t offset) {
+ return Pointer<Target_>(this, reinterpret_cast<Target_ *>(offset + (uint8_t *) mach_header_));
+ }
+};
+
+class FatMachHeader :
+ public MachHeader
+{
+ private:
+ fat_arch *fat_arch_;
+
+ public:
+ FatMachHeader(void *base, size_t size, fat_arch *fat_arch) :
+ MachHeader(base, size),
+ fat_arch_(fat_arch)
+ {
+ }
+
+ fat_arch *GetFatArch() const {
+ return fat_arch_;
+ }
+};
+
+class FatHeader :
+ public Data
+{
+ private:
+ fat_header *fat_header_;
+ std::vector<FatMachHeader> mach_headers_;
+
+ public:
+ FatHeader(void *base, size_t size) :
+ Data(base, size)
+ {
+ fat_header_ = reinterpret_cast<struct fat_header *>(base);
+
+ if (Swap(fat_header_->magic) == FAT_CIGAM) {
+ swapped_ = !swapped_;
+ goto fat;
+ } else if (Swap(fat_header_->magic) != FAT_MAGIC) {
+ fat_header_ = NULL;
+ mach_headers_.push_back(FatMachHeader(base, size, NULL));
+ } else fat: {
+ size_t fat_narch = Swap(fat_header_->nfat_arch);
+ fat_arch *fat_arch = reinterpret_cast<struct fat_arch *>(fat_header_ + 1);
+ size_t arch;
+ for (arch = 0; arch != fat_narch; ++arch) {
+ uint32_t arch_offset = Swap(fat_arch->offset);
+ uint32_t arch_size = Swap(fat_arch->size);
+ mach_headers_.push_back(FatMachHeader((uint8_t *) base + arch_offset, arch_size, fat_arch));
+ ++fat_arch;
+ }
+ }
+ }
+
+ std::vector<FatMachHeader> &GetMachHeaders() {
+ return mach_headers_;
+ }
+
+ bool IsFat() const {
+ return fat_header_ != NULL;
+ }
+
+ struct fat_header *operator ->() const {
+ return fat_header_;
+ }
+
+ operator struct fat_header *() const {
+ return fat_header_;
+ }
+};
+
+FatHeader Map(const char *path, bool ro = false) {
+ size_t size;
+ void *base(map(path, 0, _not(size_t), &size, ro));
+ return FatHeader(base, size);
+}
+
+template <typename Target_>
+class Pointer {
+ private:
+ const MachHeader *framework_;
+ const Target_ *pointer_;
+
+ public:
+ Pointer(const MachHeader *framework = NULL, const Target_ *pointer = NULL) :
+ framework_(framework),
+ pointer_(pointer)
+ {
+ }
+
+ operator const Target_ *() const {
+ return pointer_;
+ }
+
+ const Target_ *operator ->() const {
+ return pointer_;
+ }
+
+ Pointer<Target_> &operator ++() {
+ ++pointer_;
+ return *this;
+ }
+
+ template <typename Value_>
+ Value_ Swap(Value_ value) {
+ return framework_->Swap(value);
+ }
+};
+
+#define CSMAGIC_CODEDIRECTORY uint32_t(0xfade0c02)
+#define CSMAGIC_EMBEDDED_SIGNATURE uint32_t(0xfade0cc0)
+#define CSMAGIC_ENTITLEMENTS uint32_t(0xfade7171)
+
+#define CSSLOT_CODEDIRECTORY uint32_t(0)
+#define CSSLOT_REQUIREMENTS uint32_t(2)
+#define CSSLOT_ENTITLEMENTS uint32_t(5)
+
+struct BlobIndex {
+ uint32_t type;
+ uint32_t offset;
+} _packed;
+
+struct Blob {
+ uint32_t magic;
+ uint32_t length;
+} _packed;
+
+struct SuperBlob {
+ struct Blob blob;
+ uint32_t count;
+ struct BlobIndex index[];
+} _packed;
+
+struct CodeDirectory {
+ struct Blob blob;
+ uint32_t version;
+ uint32_t flags;
+ uint32_t hashOffset;
+ uint32_t identOffset;
+ uint32_t nSpecialSlots;
+ uint32_t nCodeSlots;
+ uint32_t codeLimit;
+ uint8_t hashSize;
+ uint8_t hashType;
+ uint8_t spare1;
+ uint8_t pageSize;
+ uint32_t spare2;
+} _packed;
+
+extern "C" uint32_t hash(uint8_t *k, uint32_t length, uint32_t initval);
+
+void sha1(uint8_t *hash, uint8_t *data, size_t size) {
+ SHA1Context context;
+ SHA1Reset(&context);
+ SHA1Input(&context, data, size);
+ SHA1Result(&context, hash);
+}
+
+struct CodesignAllocation {
+ FatMachHeader mach_header_;
+ uint32_t offset_;
+ uint32_t size_;
+ uint32_t alloc_;
+ uint32_t align_;
+
+ CodesignAllocation(FatMachHeader mach_header, size_t offset, size_t size, size_t alloc, size_t align) :
+ mach_header_(mach_header),
+ offset_(offset),
+ size_(size),
+ alloc_(alloc),
+ align_(align)
+ {
+ }
+};
+
+int main(int argc, const char *argv[]) {
+ union {
+ uint16_t word;
+ uint8_t byte[2];
+ } endian = {1};
+
+ little_ = endian.byte[0];
+
+ bool flag_R(false);
+ bool flag_r(false);
+
+ bool flag_t(false);
+ bool flag_p(false);
+ bool flag_u(false);
+ bool flag_e(false);
+
+ bool flag_T(false);
+
+ bool flag_S(false);
+ bool flag_s(false);
+
+ bool flag_O(false);
+
+ bool flag_D(false);
+ bool flag_d(false);
+
+ bool flag_A(false);
+ bool flag_a(false);
+
+ uint32_t flag_CPUType(_not(uint32_t));
+ uint32_t flag_CPUSubtype(_not(uint32_t));
+
+ const char *flag_I(NULL);
+
+ bool timeh(false);
+ uint32_t timev(0);
+
+ const void *xmld(NULL);
+ size_t xmls(0);
+
+ uintptr_t noffset(_not(uintptr_t));
+ uintptr_t woffset(_not(uintptr_t));
+
+ std::vector<std::string> files;
+
+ if (argc == 1) {
+ fprintf(stderr, "usage: %s -S[entitlements.xml] <binary>\n", argv[0]);
+ fprintf(stderr, " %s -e MobileSafari\n", argv[0]);
+ fprintf(stderr, " %s -S cat\n", argv[0]);
+ fprintf(stderr, " %s -Stfp.xml gdb\n", argv[0]);
+ exit(0);
+ }
+
+ for (int argi(1); argi != argc; ++argi)
+ if (argv[argi][0] != '-')
+ files.push_back(argv[argi]);
+ else switch (argv[argi][1]) {
+ case 'R': flag_R = true; break;
+ case 'r': flag_r = true; break;
+
+ case 't': flag_t = true; break;
+ case 'u': flag_u = true; break;
+ case 'p': flag_p = true; break;
+ case 'e': flag_e = true; break;
+ case 'O': flag_O = true; break;
+
+ case 'D': flag_D = true; break;
+ case 'd': flag_d = true; break;
+
+ case 'a': flag_a = true; break;
+
+ case 'A':
+ flag_A = true;
+ if (argv[argi][2] != '\0') {
+ const char *cpu = argv[argi] + 2;
+ const char *colon = strchr(cpu, ':');
+ _assert(colon != NULL);
+ char *arge;
+ flag_CPUType = strtoul(cpu, &arge, 0);
+ _assert(arge == colon);
+ flag_CPUSubtype = strtoul(colon + 1, &arge, 0);
+ _assert(arge == argv[argi] + strlen(argv[argi]));
+ }
+ break;
+
+ case 's':
+ _assert(!flag_S);
+ flag_s = true;
+ break;
+
+ case 'S':
+ _assert(!flag_s);
+ flag_S = true;
+ if (argv[argi][2] != '\0') {
+ const char *xml = argv[argi] + 2;
+ xmld = map(xml, 0, _not(size_t), &xmls, true);
+ }
+ break;
+
+ case 'T': {
+ flag_T = true;
+ if (argv[argi][2] == '-')
+ timeh = true;
+ else {
+ char *arge;
+ timev = strtoul(argv[argi] + 2, &arge, 0);
+ _assert(arge == argv[argi] + strlen(argv[argi]));
+ }
+ } break;
+
+ case 'I': {
+ flag_I = argv[argi] + 2;
+ } break;
+
+ case 'n': {
+ char *arge;
+ noffset = strtoul(argv[argi] + 2, &arge, 0);
+ _assert(arge == argv[argi] + strlen(argv[argi]));
+ } break;
+
+ case 'w': {
+ char *arge;
+ woffset = strtoul(argv[argi] + 2, &arge, 0);
+ _assert(arge == argv[argi] + strlen(argv[argi]));
+ } break;
+
+ default:
+ goto usage;
+ break;
+ }
+
+ if (files.empty()) usage: {
+ exit(0);
+ }
+
+ size_t filei(0), filee(0);
+ _foreach (file, files) try {
+ const char *path(file.c_str());
+ const char *base = strrchr(path, '/');
+ char *temp(NULL), *dir;
+
+ if (base != NULL)
+ dir = strndup_(path, base++ - path + 1);
+ else {
+ dir = strdup("");
+ base = path;
+ }
+
+ const char *name(flag_I ?: base);
+
+ if (flag_r) {
+ uint32_t clip(0); {
+ FatHeader fat_header(Map(path));
+ _foreach (mach_header, fat_header.GetMachHeaders()) {
+ if (flag_A) {
+ if (mach_header.GetCPUType() != flag_CPUType)
+ continue;
+ if (mach_header.GetCPUSubtype() != flag_CPUSubtype)
+ continue;
+ }
+
+ mach_header->flags = mach_header.Swap(mach_header.Swap(mach_header->flags) | MH_DYLDLINK);
+
+ uint32_t size(_not(uint32_t)); {
+ _foreach (load_command, mach_header.GetLoadCommands()) {
+ switch (mach_header.Swap(load_command->cmd)) {
+ case LC_CODE_SIGNATURE: {
+ struct linkedit_data_command *signature = reinterpret_cast<struct linkedit_data_command *>(load_command);
+ memset(reinterpret_cast<uint8_t *>(mach_header.GetBase()) + mach_header.Swap(signature->dataoff), 0, mach_header.Swap(signature->datasize));
+ memset(signature, 0, sizeof(struct linkedit_data_command));
+
+ mach_header->ncmds = mach_header.Swap(mach_header.Swap(mach_header->ncmds) - 1);
+ mach_header->sizeofcmds = mach_header.Swap(uint32_t(mach_header.Swap(mach_header->sizeofcmds) - sizeof(struct linkedit_data_command)));
+ } break;
+
+ case LC_SYMTAB: {
+ struct symtab_command *symtab = reinterpret_cast<struct symtab_command *>(load_command);
+ size = mach_header.Swap(symtab->stroff) + mach_header.Swap(symtab->strsize);
+ } break;
+ }
+ }
+ }
+
+ _assert(size != _not(uint32_t));
+
+ _foreach (segment, mach_header.GetSegments("__LINKEDIT")) {
+ segment->filesize -= mach_header.GetSize() - size;
+
+ if (fat_arch *fat_arch = mach_header.GetFatArch()) {
+ fat_arch->size = fat_header.Swap(size);
+ clip = std::max(clip, fat_header.Swap(fat_arch->offset) + size);
+ } else
+ clip = std::max(clip, size);
+ }
+
+ _foreach (segment, mach_header.GetSegments64("__LINKEDIT")) {
+ segment->filesize -= mach_header.GetSize() - size;
+
+ if (fat_arch *fat_arch = mach_header.GetFatArch()) {
+ fat_arch->size = fat_header.Swap(size);
+ clip = std::max(clip, fat_header.Swap(fat_arch->offset) + size);
+ } else
+ clip = std::max(clip, size);
+ }
+ }
+ }
+
+ if (clip != 0)
+ _syscall(truncate(path, clip));
+ }
+
+ if (flag_S) {
+ FatHeader source(Map(path));
+
+ size_t offset(0);
+
+ if (source.IsFat())
+ offset += sizeof(fat_header) + sizeof(fat_arch) * source.Swap(source->nfat_arch);
+
+ std::vector<CodesignAllocation> allocations; {
+ _foreach (mach_header, source.GetMachHeaders()) {
+ if (flag_A) {
+ if (mach_header.GetCPUType() != flag_CPUType)
+ continue;
+ if (mach_header.GetCPUSubtype() != flag_CPUSubtype)
+ continue;
+ }
+
+ mach_header->flags = mach_header.Swap(mach_header.Swap(mach_header->flags) | MH_DYLDLINK);
+
+ size_t size(_not(size_t)); {
+ _foreach (load_command, mach_header.GetLoadCommands()) {
+ uint32_t cmd(mach_header.Swap(load_command->cmd));
+ if (cmd == LC_CODE_SIGNATURE) {
+ struct linkedit_data_command *signature = reinterpret_cast<struct linkedit_data_command *>(load_command);
+ size = mach_header.Swap(signature->dataoff);
+ _assert(size < mach_header.GetSize());
+ break;
+ }
+ }
+
+ if (size == _not(size_t))
+ size = mach_header.GetSize();
+ }
+
+ size_t alloc(0);
+ alloc += sizeof(struct SuperBlob);
+ uint32_t special(0);
+
+ special = std::max(special, CSSLOT_CODEDIRECTORY);
+ alloc += sizeof(struct BlobIndex);
+ alloc += sizeof(struct CodeDirectory);
+ alloc += strlen(name) + 1;
+
+ special = std::max(special, CSSLOT_REQUIREMENTS);
+ alloc += sizeof(struct BlobIndex);
+ alloc += 0xc;
+
+ if (xmld != NULL) {
+ special = std::max(special, CSSLOT_ENTITLEMENTS);
+ alloc += sizeof(struct BlobIndex);
+ alloc += sizeof(struct Blob);
+ alloc += xmls;
+ }
+
+ size_t normal((size + 0x1000 - 1) / 0x1000);
+ alloc = Align(alloc + (special + normal) * 0x14, 16);
+
+ fat_arch *fat_arch(mach_header.GetFatArch());
+ uint32_t align(fat_arch == NULL ? 0 : source.Swap(fat_arch->align));
+ offset = Align(offset, 1 << align);
+
+ allocations.push_back(CodesignAllocation(mach_header, offset, size, alloc, align));
+ offset += size + alloc;
+ offset = Align(offset, 16);
+ }
+ }
+
+ asprintf(&temp, "%s.%s.cs", dir, base);
+ fclose(fopen(temp, "w+"));
+ _syscall(truncate(temp, offset));
+
+ void *file(map(temp, 0, offset, NULL, false));
+ memset(file, 0, offset);
+
+ fat_arch *fat_arch;
+ if (!source.IsFat())
+ fat_arch = NULL;
+ else {
+ fat_header *fat_header(reinterpret_cast<struct fat_header *>(file));
+ fat_header->magic = Swap(FAT_MAGIC);
+ fat_header->nfat_arch = Swap(source.Swap(source->nfat_arch));
+ fat_arch = reinterpret_cast<struct fat_arch *>(fat_header + 1);
+ }
+
+ _foreach (allocation, allocations) {
+ const FatMachHeader &source(allocation.mach_header_);
+
+ uint32_t align(allocation.size_);
+ align = Align(align, 0x10);
+
+ if (fat_arch != NULL) {
+ fat_arch->cputype = Swap(source->cputype);
+ fat_arch->cpusubtype = Swap(source->cpusubtype);
+ fat_arch->offset = Swap(allocation.offset_);
+ fat_arch->size = Swap(align + allocation.alloc_);
+ fat_arch->align = Swap(allocation.align_);
+ ++fat_arch;
+ }
+
+ void *target(reinterpret_cast<uint8_t *>(file) + allocation.offset_);
+ memcpy(target, source, allocation.size_);
+ MachHeader mach_header(target, align + allocation.alloc_);
+
+ struct linkedit_data_command *signature(NULL);
+ _foreach (load_command, mach_header.GetLoadCommands()) {
+ uint32_t cmd(mach_header.Swap(load_command->cmd));
+ if (cmd != LC_CODE_SIGNATURE)
+ continue;
+ signature = reinterpret_cast<struct linkedit_data_command *>(load_command);
+ break;
+ }
+
+ if (signature == NULL) {
+ mach_header->ncmds = mach_header.Swap(mach_header.Swap(mach_header->ncmds) + 1);
+ signature = reinterpret_cast<struct linkedit_data_command *>(reinterpret_cast<uint8_t *>(mach_header.GetLoadCommand()) + mach_header.Swap(mach_header->sizeofcmds));
+ mach_header->sizeofcmds = mach_header.Swap(mach_header.Swap(mach_header->sizeofcmds) + uint32_t(sizeof(*signature)));
+ signature->cmd = mach_header.Swap(LC_CODE_SIGNATURE);
+ signature->cmdsize = mach_header.Swap(uint32_t(sizeof(*signature)));
+ }
+
+ signature->dataoff = mach_header.Swap(align);
+ signature->datasize = mach_header.Swap(allocation.alloc_);
+
+ _foreach (segment, mach_header.GetSegments("__LINKEDIT")) {
+ size_t size(mach_header.Swap(align + allocation.alloc_ - mach_header.Swap(segment->fileoff)));
+ segment->filesize = size;
+ segment->vmsize = Align(size, 0x1000);
+ }
+
+ _foreach (segment, mach_header.GetSegments64("__LINKEDIT")) {
+ size_t size(mach_header.Swap(align + allocation.alloc_ - mach_header.Swap(segment->fileoff)));
+ segment->filesize = size;
+ segment->vmsize = Align(size, 0x1000);
+ }
+ }
+ }
+
+ if (flag_p)
+ printf("path%zu='%s'\n", filei, file.c_str());
+
+ FatHeader fat_header(Map(temp == NULL ? path : temp, !(flag_R || flag_T || flag_s || flag_S || flag_O || flag_D)));
+ struct linkedit_data_command *signature(NULL);
+
+ _foreach (mach_header, fat_header.GetMachHeaders()) {
+ if (flag_A) {
+ if (mach_header.GetCPUType() != flag_CPUType)
+ continue;
+ if (mach_header.GetCPUSubtype() != flag_CPUSubtype)
+ continue;
+ }
+
+ if (flag_a)
+ printf("cpu=0x%x:0x%x\n", mach_header.GetCPUType(), mach_header.GetCPUSubtype());
+
+ if (flag_d) {
+ if (struct fat_arch *fat_arch = mach_header.GetFatArch())
+ printf("offset=0x%x\n", Swap(fat_arch->offset));
+ else
+ printf("offset=0x0\n");
+ }
+
+ if (woffset != _not(uintptr_t)) {
+ Pointer<uint32_t> wvalue(mach_header.GetPointer<uint32_t>(woffset));
+ if (wvalue == NULL)
+ printf("(null) %p\n", reinterpret_cast<void *>(woffset));
+ else
+ printf("0x%.08x\n", *wvalue);
+ }
+
+ if (noffset != _not(uintptr_t))
+ printf("%s\n", &*mach_header.GetPointer<char>(noffset));
+
+ if (flag_d)
+ _foreach(segment, mach_header.GetSegments("__TEXT")) {
+ printf("vmaddr=0x%x\n", mach_header.Swap(segment->vmaddr));
+ printf("fileoff=0x%x\n", mach_header.Swap(segment->fileoff));
+ }
+
+ if (flag_O) {
+ _foreach(section, mach_header.GetSections("__TEXT", "__text"))
+ section->addr = mach_header.Swap(0);
+ }
+
+ _foreach (load_command, mach_header.GetLoadCommands()) {
+ uint32_t cmd(mach_header.Swap(load_command->cmd));
+
+ if (flag_R && cmd == LC_REEXPORT_DYLIB)
+ load_command->cmd = mach_header.Swap(LC_LOAD_DYLIB);
+ else if (cmd == LC_CODE_SIGNATURE)
+ signature = reinterpret_cast<struct linkedit_data_command *>(load_command);
+ else if (cmd == LC_UUID) {
+ volatile struct uuid_command *uuid_command(reinterpret_cast<struct uuid_command *>(load_command));
+
+ if (flag_u) {
+ printf("uuid%zu=%.2x%.2x%.2x%.2x-%.2x%.2x-%.2x%.2x-%.2x%.2x-%.2x%.2x%.2x%.2x%.2x%.2x\n", filei,
+ uuid_command->uuid[ 0], uuid_command->uuid[ 1], uuid_command->uuid[ 2], uuid_command->uuid[ 3],
+ uuid_command->uuid[ 4], uuid_command->uuid[ 5], uuid_command->uuid[ 6], uuid_command->uuid[ 7],
+ uuid_command->uuid[ 8], uuid_command->uuid[ 9], uuid_command->uuid[10], uuid_command->uuid[11],
+ uuid_command->uuid[12], uuid_command->uuid[13], uuid_command->uuid[14], uuid_command->uuid[15]
+ );
+ }
+ } else if (cmd == LC_ID_DYLIB) {
+ volatile struct dylib_command *dylib_command(reinterpret_cast<struct dylib_command *>(load_command));
+
+ if (flag_t)
+ printf("time%zu=0x%.8x\n", filei, mach_header.Swap(dylib_command->dylib.timestamp));
+
+ if (flag_T) {
+ uint32_t timed;
+
+ if (!timeh)
+ timed = timev;
+ else {
+ dylib_command->dylib.timestamp = 0;
+ timed = hash(reinterpret_cast<uint8_t *>(mach_header.GetBase()), mach_header.GetSize(), timev);
+ }
+
+ dylib_command->dylib.timestamp = mach_header.Swap(timed);
+ }
+ } else if (cmd == LC_ENCRYPTION_INFO) {
+ volatile struct encryption_info_command *encryption_info_command(reinterpret_cast<struct encryption_info_command *>(load_command));
+
+ if (flag_D)
+ encryption_info_command->cryptid = mach_header.Swap(0);
+
+ if (flag_d) {
+ printf("cryptoff=0x%x\n", mach_header.Swap(encryption_info_command->cryptoff));
+ printf("cryptsize=0x%x\n", mach_header.Swap(encryption_info_command->cryptsize));
+ printf("cryptid=0x%x\n", mach_header.Swap(encryption_info_command->cryptid));
+ }
+ }
+ }
+
+ if (flag_e) {
+ _assert(signature != NULL);
+
+ uint32_t data = mach_header.Swap(signature->dataoff);
+
+ uint8_t *top = reinterpret_cast<uint8_t *>(mach_header.GetBase());
+ uint8_t *blob = top + data;
+ struct SuperBlob *super = reinterpret_cast<struct SuperBlob *>(blob);
+
+ for (size_t index(0); index != Swap(super->count); ++index)
+ if (Swap(super->index[index].type) == CSSLOT_ENTITLEMENTS) {
+ uint32_t begin = Swap(super->index[index].offset);
+ struct Blob *entitlements = reinterpret_cast<struct Blob *>(blob + begin);
+ fwrite(entitlements + 1, 1, Swap(entitlements->length) - sizeof(struct Blob), stdout);
+ }
+ }
+
+ if (flag_s) {
+ _assert(signature != NULL);
+
+ uint32_t data = mach_header.Swap(signature->dataoff);
+
+ uint8_t *top = reinterpret_cast<uint8_t *>(mach_header.GetBase());
+ uint8_t *blob = top + data;
+ struct SuperBlob *super = reinterpret_cast<struct SuperBlob *>(blob);
+
+ for (size_t index(0); index != Swap(super->count); ++index)
+ if (Swap(super->index[index].type) == CSSLOT_CODEDIRECTORY) {
+ uint32_t begin = Swap(super->index[index].offset);
+ struct CodeDirectory *directory = reinterpret_cast<struct CodeDirectory *>(blob + begin);
+
+ uint8_t (*hashes)[20] = reinterpret_cast<uint8_t (*)[20]>(blob + begin + Swap(directory->hashOffset));
+ uint32_t pages = Swap(directory->nCodeSlots);
+
+ if (pages != 1)
+ for (size_t i = 0; i != pages - 1; ++i)
+ sha1(hashes[i], top + 0x1000 * i, 0x1000);
+ if (pages != 0)
+ sha1(hashes[pages - 1], top + 0x1000 * (pages - 1), ((data - 1) % 0x1000) + 1);
+ }
+ }
+
+ if (flag_S) {
+ _assert(signature != NULL);
+
+ uint32_t data = mach_header.Swap(signature->dataoff);
+ uint32_t size = mach_header.Swap(signature->datasize);
+
+ uint8_t *top = reinterpret_cast<uint8_t *>(mach_header.GetBase());
+ uint8_t *blob = top + data;
+ struct SuperBlob *super = reinterpret_cast<struct SuperBlob *>(blob);
+ super->blob.magic = Swap(CSMAGIC_EMBEDDED_SIGNATURE);
+
+ uint32_t count = xmld == NULL ? 2 : 3;
+ uint32_t offset = sizeof(struct SuperBlob) + count * sizeof(struct BlobIndex);
+
+ super->index[0].type = Swap(CSSLOT_CODEDIRECTORY);
+ super->index[0].offset = Swap(offset);
+
+ uint32_t begin = offset;
+ struct CodeDirectory *directory = reinterpret_cast<struct CodeDirectory *>(blob + begin);
+ offset += sizeof(struct CodeDirectory);
+
+ directory->blob.magic = Swap(CSMAGIC_CODEDIRECTORY);
+ directory->version = Swap(uint32_t(0x00020001));
+ directory->flags = Swap(uint32_t(0));
+ directory->codeLimit = Swap(data);
+ directory->hashSize = 0x14;
+ directory->hashType = 0x01;
+ directory->spare1 = 0x00;
+ directory->pageSize = 0x0c;
+ directory->spare2 = Swap(uint32_t(0));
+
+ directory->identOffset = Swap(offset - begin);
+ strcpy(reinterpret_cast<char *>(blob + offset), name);
+ offset += strlen(name) + 1;
+
+ uint32_t special = xmld == NULL ? CSSLOT_REQUIREMENTS : CSSLOT_ENTITLEMENTS;
+ directory->nSpecialSlots = Swap(special);
+
+ uint8_t (*hashes)[20] = reinterpret_cast<uint8_t (*)[20]>(blob + offset);
+ memset(hashes, 0, sizeof(*hashes) * special);
+
+ offset += sizeof(*hashes) * special;
+ hashes += special;
+
+ uint32_t pages = (data + 0x1000 - 1) / 0x1000;
+ directory->nCodeSlots = Swap(pages);
+
+ if (pages != 1)
+ for (size_t i = 0; i != pages - 1; ++i)
+ sha1(hashes[i], top + 0x1000 * i, 0x1000);
+ if (pages != 0)
+ sha1(hashes[pages - 1], top + 0x1000 * (pages - 1), ((data - 1) % 0x1000) + 1);
+
+ directory->hashOffset = Swap(offset - begin);
+ offset += sizeof(*hashes) * pages;
+ directory->blob.length = Swap(offset - begin);
+
+ super->index[1].type = Swap(CSSLOT_REQUIREMENTS);
+ super->index[1].offset = Swap(offset);
+
+ memcpy(blob + offset, "\xfa\xde\x0c\x01\x00\x00\x00\x0c\x00\x00\x00\x00", 0xc);
+ offset += 0xc;
+
+ if (xmld != NULL) {
+ super->index[2].type = Swap(CSSLOT_ENTITLEMENTS);
+ super->index[2].offset = Swap(offset);
+
+ uint32_t begin = offset;
+ struct Blob *entitlements = reinterpret_cast<struct Blob *>(blob + begin);
+ offset += sizeof(struct Blob);
+
+ memcpy(blob + offset, xmld, xmls);
+ offset += xmls;
+
+ entitlements->magic = Swap(CSMAGIC_ENTITLEMENTS);
+ entitlements->length = Swap(offset - begin);
+ }
+
+ for (size_t index(0); index != count; ++index) {
+ uint32_t type = Swap(super->index[index].type);
+ if (type != 0 && type <= special) {
+ uint32_t offset = Swap(super->index[index].offset);
+ struct Blob *local = (struct Blob *) (blob + offset);
+ sha1((uint8_t *) (hashes - type), (uint8_t *) local, Swap(local->length));
+ }
+ }
+
+ super->count = Swap(count);
+ super->blob.length = Swap(offset);
+
+ if (offset > size) {
+ fprintf(stderr, "offset (%u) > size (%u)\n", offset, size);
+ _assert(false);
+ } //else fprintf(stderr, "offset (%zu) <= size (%zu)\n", offset, size);
+
+ memset(blob + offset, 0, size - offset);
+ }
+ }
+
+ if (flag_S) {
+ uint8_t *top = reinterpret_cast<uint8_t *>(fat_header.GetBase());
+ size_t size = fat_header.GetSize();
+
+ char *copy;
+ asprintf(&copy, "%s.%s.cp", dir, base);
+ FILE *file = fopen(copy, "w+");
+ size_t writ = fwrite(top, 1, size, file);
+ _assert(writ == size);
+ fclose(file);
+
+ _syscall(unlink(temp));
+ free(temp);
+ temp = copy;
+ }
+
+ if (temp != NULL) {
+ struct stat info;
+ _syscall(stat(path, &info));
+ _syscall(chown(temp, info.st_uid, info.st_gid));
+ _syscall(chmod(temp, info.st_mode));
+ _syscall(unlink(path));
+ _syscall(rename(temp, path));
+ free(temp);
+ }
+
+ free(dir);
+ ++filei;
+ } catch (const char *) {
+ ++filee;
+ ++filei;
+ }
+
+ return filee;
+}
diff --git a/util/ldid-xerub/ldid2 b/util/ldid-xerub/ldid2
new file mode 100755
index 000000000..6b1df0d72
--- /dev/null
+++ b/util/ldid-xerub/ldid2
Binary files differ
diff --git a/util/ldid-xerub/ldid2.cpp b/util/ldid-xerub/ldid2.cpp
new file mode 100644
index 000000000..30badb00c
--- /dev/null
+++ b/util/ldid-xerub/ldid2.cpp
@@ -0,0 +1,1362 @@
+/* ldid - (Mach-O) Link-Loader Identity Editor
+ * Copyright (C) 2007-2012 Jay Freeman (saurik)
+*/
+
+/* GNU Affero General Public License, Version 3 {{{ */
+/*
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 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 Affero General Public License for more details.
+
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+**/
+/* }}} */
+
+#include "minimal/stdlib.h"
+#include "minimal/string.h"
+#include "minimal/mapping.h"
+
+extern "C" {
+#include "sha.h"
+}
+
+#include <cstring>
+#include <string>
+#include <vector>
+
+struct fat_header {
+ uint32_t magic;
+ uint32_t nfat_arch;
+} _packed;
+
+#define FAT_MAGIC 0xcafebabe
+#define FAT_CIGAM 0xbebafeca
+
+struct fat_arch {
+ uint32_t cputype;
+ uint32_t cpusubtype;
+ uint32_t offset;
+ uint32_t size;
+ uint32_t align;
+} _packed;
+
+struct mach_header {
+ uint32_t magic;
+ uint32_t cputype;
+ uint32_t cpusubtype;
+ uint32_t filetype;
+ uint32_t ncmds;
+ uint32_t sizeofcmds;
+ uint32_t flags;
+} _packed;
+
+#define MH_MAGIC 0xfeedface
+#define MH_CIGAM 0xcefaedfe
+
+#define MH_MAGIC_64 0xfeedfacf
+#define MH_CIGAM_64 0xcffaedfe
+
+#define MH_DYLDLINK 0x4
+
+#define MH_OBJECT 0x1
+#define MH_EXECUTE 0x2
+#define MH_DYLIB 0x6
+#define MH_BUNDLE 0x8
+#define MH_DYLIB_STUB 0x9
+
+struct load_command {
+ uint32_t cmd;
+ uint32_t cmdsize;
+} _packed;
+
+#define LC_REQ_DYLD uint32_t(0x80000000)
+
+#define LC_SEGMENT uint32_t(0x01)
+#define LC_SYMTAB uint32_t(0x02)
+#define LC_DYSYMTAB uint32_t(0x0b)
+#define LC_LOAD_DYLIB uint32_t(0x0c)
+#define LC_ID_DYLIB uint32_t(0x0d)
+#define LC_SEGMENT_64 uint32_t(0x19)
+#define LC_UUID uint32_t(0x1b)
+#define LC_CODE_SIGNATURE uint32_t(0x1d)
+#define LC_SEGMENT_SPLIT_INFO uint32_t(0x1e)
+#define LC_REEXPORT_DYLIB uint32_t(0x1f | LC_REQ_DYLD)
+#define LC_ENCRYPTION_INFO uint32_t(0x21)
+#define LC_DYLD_INFO uint32_t(0x22)
+#define LC_DYLD_INFO_ONLY uint32_t(0x22 | LC_REQ_DYLD)
+
+struct dylib {
+ uint32_t name;
+ uint32_t timestamp;
+ uint32_t current_version;
+ uint32_t compatibility_version;
+} _packed;
+
+struct dylib_command {
+ uint32_t cmd;
+ uint32_t cmdsize;
+ struct dylib dylib;
+} _packed;
+
+struct uuid_command {
+ uint32_t cmd;
+ uint32_t cmdsize;
+ uint8_t uuid[16];
+} _packed;
+
+struct symtab_command {
+ uint32_t cmd;
+ uint32_t cmdsize;
+ uint32_t symoff;
+ uint32_t nsyms;
+ uint32_t stroff;
+ uint32_t strsize;
+} _packed;
+
+struct dyld_info_command {
+ uint32_t cmd;
+ uint32_t cmdsize;
+ uint32_t rebase_off;
+ uint32_t rebase_size;
+ uint32_t bind_off;
+ uint32_t bind_size;
+ uint32_t weak_bind_off;
+ uint32_t weak_bind_size;
+ uint32_t lazy_bind_off;
+ uint32_t lazy_bind_size;
+ uint32_t export_off;
+ uint32_t export_size;
+} _packed;
+
+struct dysymtab_command {
+ uint32_t cmd;
+ uint32_t cmdsize;
+ uint32_t ilocalsym;
+ uint32_t nlocalsym;
+ uint32_t iextdefsym;
+ uint32_t nextdefsym;
+ uint32_t iundefsym;
+ uint32_t nundefsym;
+ uint32_t tocoff;
+ uint32_t ntoc;
+ uint32_t modtaboff;
+ uint32_t nmodtab;
+ uint32_t extrefsymoff;
+ uint32_t nextrefsyms;
+ uint32_t indirectsymoff;
+ uint32_t nindirectsyms;
+ uint32_t extreloff;
+ uint32_t nextrel;
+ uint32_t locreloff;
+ uint32_t nlocrel;
+} _packed;
+
+struct dylib_table_of_contents {
+ uint32_t symbol_index;
+ uint32_t module_index;
+} _packed;
+
+struct dylib_module {
+ uint32_t module_name;
+ uint32_t iextdefsym;
+ uint32_t nextdefsym;
+ uint32_t irefsym;
+ uint32_t nrefsym;
+ uint32_t ilocalsym;
+ uint32_t nlocalsym;
+ uint32_t iextrel;
+ uint32_t nextrel;
+ uint32_t iinit_iterm;
+ uint32_t ninit_nterm;
+ uint32_t objc_module_info_addr;
+ uint32_t objc_module_info_size;
+} _packed;
+
+struct dylib_reference {
+ uint32_t isym:24;
+ uint32_t flags:8;
+} _packed;
+
+struct relocation_info {
+ int32_t r_address;
+ uint32_t r_symbolnum:24;
+ uint32_t r_pcrel:1;
+ uint32_t r_length:2;
+ uint32_t r_extern:1;
+ uint32_t r_type:4;
+} _packed;
+
+struct nlist {
+ union {
+ char *n_name;
+ int32_t n_strx;
+ } n_un;
+
+ uint8_t n_type;
+ uint8_t n_sect;
+ uint8_t n_desc;
+ uint32_t n_value;
+} _packed;
+
+struct segment_command {
+ uint32_t cmd;
+ uint32_t cmdsize;
+ char segname[16];
+ uint32_t vmaddr;
+ uint32_t vmsize;
+ uint32_t fileoff;
+ uint32_t filesize;
+ uint32_t maxprot;
+ uint32_t initprot;
+ uint32_t nsects;
+ uint32_t flags;
+} _packed;
+
+struct segment_command_64 {
+ uint32_t cmd;
+ uint32_t cmdsize;
+ char segname[16];
+ uint64_t vmaddr;
+ uint64_t vmsize;
+ uint64_t fileoff;
+ uint64_t filesize;
+ uint32_t maxprot;
+ uint32_t initprot;
+ uint32_t nsects;
+ uint32_t flags;
+} _packed;
+
+struct section {
+ char sectname[16];
+ char segname[16];
+ uint32_t addr;
+ uint32_t size;
+ uint32_t offset;
+ uint32_t align;
+ uint32_t reloff;
+ uint32_t nreloc;
+ uint32_t flags;
+ uint32_t reserved1;
+ uint32_t reserved2;
+} _packed;
+
+struct section_64 {
+ char sectname[16];
+ char segname[16];
+ uint64_t addr;
+ uint64_t size;
+ uint32_t offset;
+ uint32_t align;
+ uint32_t reloff;
+ uint32_t nreloc;
+ uint32_t flags;
+ uint32_t reserved1;
+ uint32_t reserved2;
+} _packed;
+
+struct linkedit_data_command {
+ uint32_t cmd;
+ uint32_t cmdsize;
+ uint32_t dataoff;
+ uint32_t datasize;
+} _packed;
+
+struct encryption_info_command {
+ uint32_t cmd;
+ uint32_t cmdsize;
+ uint32_t cryptoff;
+ uint32_t cryptsize;
+ uint32_t cryptid;
+} _packed;
+
+#define BIND_OPCODE_MASK 0xf0
+#define BIND_IMMEDIATE_MASK 0x0f
+#define BIND_OPCODE_DONE 0x00
+#define BIND_OPCODE_SET_DYLIB_ORDINAL_IMM 0x10
+#define BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB 0x20
+#define BIND_OPCODE_SET_DYLIB_SPECIAL_IMM 0x30
+#define BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM 0x40
+#define BIND_OPCODE_SET_TYPE_IMM 0x50
+#define BIND_OPCODE_SET_ADDEND_SLEB 0x60
+#define BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB 0x70
+#define BIND_OPCODE_ADD_ADDR_ULEB 0x80
+#define BIND_OPCODE_DO_BIND 0x90
+#define BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB 0xa0
+#define BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED 0xb0
+#define BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB 0xc0
+
+template <typename Type_>
+Type_ Align(Type_ value, size_t align) {
+ value += align - 1;
+ value /= align;
+ value *= align;
+ return value;
+}
+
+uint16_t Swap_(uint16_t value) {
+ return
+ ((value >> 8) & 0x00ff) |
+ ((value << 8) & 0xff00);
+}
+
+uint32_t Swap_(uint32_t value) {
+ value = ((value >> 8) & 0x00ff00ff) |
+ ((value << 8) & 0xff00ff00);
+ value = ((value >> 16) & 0x0000ffff) |
+ ((value << 16) & 0xffff0000);
+ return value;
+}
+
+uint64_t Swap_(uint64_t value) {
+ value = (value & 0x00000000ffffffffULL) << 32 | (value & 0xffffffff00000000ULL) >> 32;
+ value = (value & 0x0000ffff0000ffffULL) << 16 | (value & 0xffff0000ffff0000ULL) >> 16;
+ value = (value & 0x00ff00ff00ff00ffULL) << 8 | (value & 0xff00ff00ff00ff00ULL) >> 8;
+ return value;
+}
+
+int16_t Swap_(int16_t value) {
+ return Swap_(static_cast<uint16_t>(value));
+}
+
+int32_t Swap_(int32_t value) {
+ return Swap_(static_cast<uint32_t>(value));
+}
+
+int64_t Swap_(int64_t value) {
+ return Swap_(static_cast<uint64_t>(value));
+}
+
+bool little_(true);
+
+uint16_t Swap(uint16_t value) {
+ return little_ ? Swap_(value) : value;
+}
+
+uint32_t Swap(uint32_t value) {
+ return little_ ? Swap_(value) : value;
+}
+
+uint64_t Swap(uint64_t value) {
+ return little_ ? Swap_(value) : value;
+}
+
+int16_t Swap(int16_t value) {
+ return Swap(static_cast<uint16_t>(value));
+}
+
+int32_t Swap(int32_t value) {
+ return Swap(static_cast<uint32_t>(value));
+}
+
+int64_t Swap(int64_t value) {
+ return Swap(static_cast<uint64_t>(value));
+}
+
+template <typename Target_>
+class Pointer;
+
+class Data {
+ private:
+ void *base_;
+ size_t size_;
+
+ protected:
+ bool swapped_;
+
+ public:
+ Data(void *base, size_t size) :
+ base_(base),
+ size_(size),
+ swapped_(false)
+ {
+ }
+
+ uint16_t Swap(uint16_t value) const {
+ return swapped_ ? Swap_(value) : value;
+ }
+
+ uint32_t Swap(uint32_t value) const {
+ return swapped_ ? Swap_(value) : value;
+ }
+
+ uint64_t Swap(uint64_t value) const {
+ return swapped_ ? Swap_(value) : value;
+ }
+
+ int16_t Swap(int16_t value) const {
+ return Swap(static_cast<uint16_t>(value));
+ }
+
+ int32_t Swap(int32_t value) const {
+ return Swap(static_cast<uint32_t>(value));
+ }
+
+ int64_t Swap(int64_t value) const {
+ return Swap(static_cast<uint64_t>(value));
+ }
+
+ void *GetBase() const {
+ return base_;
+ }
+
+ size_t GetSize() const {
+ return size_;
+ }
+};
+
+class MachHeader :
+ public Data
+{
+ private:
+ bool bits64_;
+
+ struct mach_header *mach_header_;
+ struct load_command *load_command_;
+
+ public:
+ MachHeader(void *base, size_t size) :
+ Data(base, size)
+ {
+ mach_header_ = (mach_header *) base;
+
+ switch (Swap(mach_header_->magic)) {
+ case MH_CIGAM:
+ swapped_ = !swapped_;
+ case MH_MAGIC:
+ bits64_ = false;
+ break;
+
+ case MH_CIGAM_64:
+ swapped_ = !swapped_;
+ case MH_MAGIC_64:
+ bits64_ = true;
+ break;
+
+ default:
+ _assert(false);
+ }
+
+ void *post = mach_header_ + 1;
+ if (bits64_)
+ post = (uint32_t *) post + 1;
+ load_command_ = (struct load_command *) post;
+
+ _assert(
+ Swap(mach_header_->filetype) == MH_EXECUTE ||
+ Swap(mach_header_->filetype) == MH_DYLIB ||
+ Swap(mach_header_->filetype) == MH_BUNDLE
+ );
+ }
+
+ struct mach_header *operator ->() const {
+ return mach_header_;
+ }
+
+ operator struct mach_header *() const {
+ return mach_header_;
+ }
+
+ uint32_t GetCPUType() const {
+ return Swap(mach_header_->cputype);
+ }
+
+ uint32_t GetCPUSubtype() const {
+ return Swap(mach_header_->cpusubtype) & 0xff;
+ }
+
+ struct load_command *GetLoadCommand() const {
+ return load_command_;
+ }
+
+ std::vector<struct load_command *> GetLoadCommands() const {
+ std::vector<struct load_command *> load_commands;
+
+ struct load_command *load_command = load_command_;
+ for (uint32_t cmd = 0; cmd != Swap(mach_header_->ncmds); ++cmd) {
+ load_commands.push_back(load_command);
+ load_command = (struct load_command *) ((uint8_t *) load_command + Swap(load_command->cmdsize));
+ }
+
+ return load_commands;
+ }
+
+ std::vector<segment_command *> GetSegments(const char *segment_name) const {
+ std::vector<struct segment_command *> segment_commands;
+
+ _foreach (load_command, GetLoadCommands()) {
+ if (Swap(load_command->cmd) == LC_SEGMENT) {
+ segment_command *segment_command = reinterpret_cast<struct segment_command *>(load_command);
+ if (strncmp(segment_command->segname, segment_name, 16) == 0)
+ segment_commands.push_back(segment_command);
+ }
+ }
+
+ return segment_commands;
+ }
+
+ std::vector<segment_command_64 *> GetSegments64(const char *segment_name) const {
+ std::vector<struct segment_command_64 *> segment_commands;
+
+ _foreach (load_command, GetLoadCommands()) {
+ if (Swap(load_command->cmd) == LC_SEGMENT_64) {
+ segment_command_64 *segment_command = reinterpret_cast<struct segment_command_64 *>(load_command);
+ if (strncmp(segment_command->segname, segment_name, 16) == 0)
+ segment_commands.push_back(segment_command);
+ }
+ }
+
+ return segment_commands;
+ }
+
+ std::vector<section *> GetSections(const char *segment_name, const char *section_name) const {
+ std::vector<section *> sections;
+
+ _foreach (segment, GetSegments(segment_name)) {
+ section *section = (struct section *) (segment + 1);
+
+ uint32_t sect;
+ for (sect = 0; sect != Swap(segment->nsects); ++sect) {
+ if (strncmp(section->sectname, section_name, 16) == 0)
+ sections.push_back(section);
+ ++section;
+ }
+ }
+
+ return sections;
+ }
+
+ template <typename Target_>
+ Pointer<Target_> GetPointer(uint32_t address, const char *segment_name = NULL) const {
+ load_command *load_command = (struct load_command *) (mach_header_ + 1);
+ uint32_t cmd;
+
+ for (cmd = 0; cmd != Swap(mach_header_->ncmds); ++cmd) {
+ if (Swap(load_command->cmd) == LC_SEGMENT) {
+ segment_command *segment_command = (struct segment_command *) load_command;
+ if (segment_name != NULL && strncmp(segment_command->segname, segment_name, 16) != 0)
+ goto next_command;
+
+ section *sections = (struct section *) (segment_command + 1);
+
+ uint32_t sect;
+ for (sect = 0; sect != Swap(segment_command->nsects); ++sect) {
+ section *section = &sections[sect];
+ //printf("%s %u %p %p %u\n", segment_command->segname, sect, address, section->addr, section->size);
+ if (address >= Swap(section->addr) && address < Swap(section->addr) + Swap(section->size)) {
+ //printf("0x%.8x %s\n", address, segment_command->segname);
+ return Pointer<Target_>(this, reinterpret_cast<Target_ *>(address - Swap(section->addr) + Swap(section->offset) + (char *) mach_header_));
+ }
+ }
+ }
+
+ next_command:
+ load_command = (struct load_command *) ((char *) load_command + Swap(load_command->cmdsize));
+ }
+
+ return Pointer<Target_>(this);
+ }
+
+ template <typename Target_>
+ Pointer<Target_> GetOffset(uint32_t offset) {
+ return Pointer<Target_>(this, reinterpret_cast<Target_ *>(offset + (uint8_t *) mach_header_));
+ }
+};
+
+class FatMachHeader :
+ public MachHeader
+{
+ private:
+ fat_arch *fat_arch_;
+
+ public:
+ FatMachHeader(void *base, size_t size, fat_arch *fat_arch) :
+ MachHeader(base, size),
+ fat_arch_(fat_arch)
+ {
+ }
+
+ fat_arch *GetFatArch() const {
+ return fat_arch_;
+ }
+};
+
+class FatHeader :
+ public Data
+{
+ private:
+ fat_header *fat_header_;
+ std::vector<FatMachHeader> mach_headers_;
+
+ public:
+ FatHeader(void *base, size_t size) :
+ Data(base, size)
+ {
+ fat_header_ = reinterpret_cast<struct fat_header *>(base);
+
+ if (Swap(fat_header_->magic) == FAT_CIGAM) {
+ swapped_ = !swapped_;
+ goto fat;
+ } else if (Swap(fat_header_->magic) != FAT_MAGIC) {
+ fat_header_ = NULL;
+ mach_headers_.push_back(FatMachHeader(base, size, NULL));
+ } else fat: {
+ size_t fat_narch = Swap(fat_header_->nfat_arch);
+ fat_arch *fat_arch = reinterpret_cast<struct fat_arch *>(fat_header_ + 1);
+ size_t arch;
+ for (arch = 0; arch != fat_narch; ++arch) {
+ uint32_t arch_offset = Swap(fat_arch->offset);
+ uint32_t arch_size = Swap(fat_arch->size);
+ mach_headers_.push_back(FatMachHeader((uint8_t *) base + arch_offset, arch_size, fat_arch));
+ ++fat_arch;
+ }
+ }
+ }
+
+ std::vector<FatMachHeader> &GetMachHeaders() {
+ return mach_headers_;
+ }
+
+ bool IsFat() const {
+ return fat_header_ != NULL;
+ }
+
+ struct fat_header *operator ->() const {
+ return fat_header_;
+ }
+
+ operator struct fat_header *() const {
+ return fat_header_;
+ }
+};
+
+FatHeader Map(const char *path, bool ro = false) {
+ size_t size;
+ void *base(map(path, 0, _not(size_t), &size, ro));
+ return FatHeader(base, size);
+}
+
+template <typename Target_>
+class Pointer {
+ private:
+ const MachHeader *framework_;
+ const Target_ *pointer_;
+
+ public:
+ Pointer(const MachHeader *framework = NULL, const Target_ *pointer = NULL) :
+ framework_(framework),
+ pointer_(pointer)
+ {
+ }
+
+ operator const Target_ *() const {
+ return pointer_;
+ }
+
+ const Target_ *operator ->() const {
+ return pointer_;
+ }
+
+ Pointer<Target_> &operator ++() {
+ ++pointer_;
+ return *this;
+ }
+
+ template <typename Value_>
+ Value_ Swap(Value_ value) {
+ return framework_->Swap(value);
+ }
+};
+
+#define CSMAGIC_CODEDIRECTORY uint32_t(0xfade0c02)
+#define CSMAGIC_EMBEDDED_SIGNATURE uint32_t(0xfade0cc0)
+#define CSMAGIC_ENTITLEMENTS uint32_t(0xfade7171)
+
+#define CSSLOT_CODEDIRECTORY uint32_t(0)
+#define CSSLOT_REQUIREMENTS uint32_t(2)
+#define CSSLOT_ENTITLEMENTS uint32_t(5)
+
+struct BlobIndex {
+ uint32_t type;
+ uint32_t offset;
+} _packed;
+
+struct Blob {
+ uint32_t magic;
+ uint32_t length;
+} _packed;
+
+struct SuperBlob {
+ struct Blob blob;
+ uint32_t count;
+ struct BlobIndex index[];
+} _packed;
+
+struct CodeDirectory {
+ struct Blob blob;
+ uint32_t version;
+ uint32_t flags;
+ uint32_t hashOffset;
+ uint32_t identOffset;
+ uint32_t nSpecialSlots;
+ uint32_t nCodeSlots;
+ uint32_t codeLimit;
+ uint8_t hashSize;
+ uint8_t hashType;
+ uint8_t spare1;
+ uint8_t pageSize;
+ uint32_t spare2;
+} _packed;
+
+extern "C" uint32_t hash(uint8_t *k, uint32_t length, uint32_t initval);
+
+void sha2(uint8_t *hash, uint8_t *data, size_t size) {
+ SHA256Context context;
+ SHA256Reset(&context);
+ SHA256Input(&context, data, size);
+ SHA256Result(&context, hash);
+}
+
+struct CodesignAllocation {
+ FatMachHeader mach_header_;
+ uint32_t offset_;
+ uint32_t size_;
+ uint32_t alloc_;
+ uint32_t align_;
+
+ CodesignAllocation(FatMachHeader mach_header, size_t offset, size_t size, size_t alloc, size_t align) :
+ mach_header_(mach_header),
+ offset_(offset),
+ size_(size),
+ alloc_(alloc),
+ align_(align)
+ {
+ }
+};
+
+int main(int argc, const char *argv[]) {
+ union {
+ uint16_t word;
+ uint8_t byte[2];
+ } endian = {1};
+
+ little_ = endian.byte[0];
+
+ bool flag_R(false);
+ bool flag_r(false);
+
+ bool flag_t(false);
+ bool flag_p(false);
+ bool flag_u(false);
+ bool flag_e(false);
+
+ bool flag_T(false);
+
+ bool flag_S(false);
+ bool flag_s(false);
+
+ bool flag_O(false);
+
+ bool flag_D(false);
+ bool flag_d(false);
+
+ bool flag_A(false);
+ bool flag_a(false);
+
+ uint32_t flag_CPUType(_not(uint32_t));
+ uint32_t flag_CPUSubtype(_not(uint32_t));
+
+ const char *flag_I(NULL);
+
+ bool timeh(false);
+ uint32_t timev(0);
+
+ const void *xmld(NULL);
+ size_t xmls(0);
+
+ uintptr_t noffset(_not(uintptr_t));
+ uintptr_t woffset(_not(uintptr_t));
+
+ std::vector<std::string> files;
+
+ if (argc == 1) {
+ fprintf(stderr, "usage: %s -S[entitlements.xml] <binary>\n", argv[0]);
+ fprintf(stderr, " %s -e MobileSafari\n", argv[0]);
+ fprintf(stderr, " %s -S cat\n", argv[0]);
+ fprintf(stderr, " %s -Stfp.xml gdb\n", argv[0]);
+ exit(0);
+ }
+
+ for (int argi(1); argi != argc; ++argi)
+ if (argv[argi][0] != '-')
+ files.push_back(argv[argi]);
+ else switch (argv[argi][1]) {
+ case 'R': flag_R = true; break;
+ case 'r': flag_r = true; break;
+
+ case 't': flag_t = true; break;
+ case 'u': flag_u = true; break;
+ case 'p': flag_p = true; break;
+ case 'e': flag_e = true; break;
+ case 'O': flag_O = true; break;
+
+ case 'D': flag_D = true; break;
+ case 'd': flag_d = true; break;
+
+ case 'a': flag_a = true; break;
+
+ case 'A':
+ flag_A = true;
+ if (argv[argi][2] != '\0') {
+ const char *cpu = argv[argi] + 2;
+ const char *colon = strchr(cpu, ':');
+ _assert(colon != NULL);
+ char *arge;
+ flag_CPUType = strtoul(cpu, &arge, 0);
+ _assert(arge == colon);
+ flag_CPUSubtype = strtoul(colon + 1, &arge, 0);
+ _assert(arge == argv[argi] + strlen(argv[argi]));
+ }
+ break;
+
+ case 's':
+ _assert(!flag_S);
+ flag_s = true;
+ break;
+
+ case 'S':
+ _assert(!flag_s);
+ flag_S = true;
+ if (argv[argi][2] != '\0') {
+ const char *xml = argv[argi] + 2;
+ xmld = map(xml, 0, _not(size_t), &xmls, true);
+ }
+ break;
+
+ case 'T': {
+ flag_T = true;
+ if (argv[argi][2] == '-')
+ timeh = true;
+ else {
+ char *arge;
+ timev = strtoul(argv[argi] + 2, &arge, 0);
+ _assert(arge == argv[argi] + strlen(argv[argi]));
+ }
+ } break;
+
+ case 'I': {
+ flag_I = argv[argi] + 2;
+ } break;
+
+ case 'n': {
+ char *arge;
+ noffset = strtoul(argv[argi] + 2, &arge, 0);
+ _assert(arge == argv[argi] + strlen(argv[argi]));
+ } break;
+
+ case 'w': {
+ char *arge;
+ woffset = strtoul(argv[argi] + 2, &arge, 0);
+ _assert(arge == argv[argi] + strlen(argv[argi]));
+ } break;
+
+ default:
+ goto usage;
+ break;
+ }
+
+ if (files.empty()) usage: {
+ exit(0);
+ }
+
+ size_t filei(0), filee(0);
+ _foreach (file, files) try {
+ const char *path(file.c_str());
+ const char *base = strrchr(path, '/');
+ char *temp(NULL), *dir;
+
+ if (base != NULL)
+ dir = strndup_(path, base++ - path + 1);
+ else {
+ dir = strdup("");
+ base = path;
+ }
+
+ const char *name(flag_I ?: base);
+
+ if (flag_r) {
+ uint32_t clip(0); {
+ FatHeader fat_header(Map(path));
+ _foreach (mach_header, fat_header.GetMachHeaders()) {
+ if (flag_A) {
+ if (mach_header.GetCPUType() != flag_CPUType)
+ continue;
+ if (mach_header.GetCPUSubtype() != flag_CPUSubtype)
+ continue;
+ }
+
+ mach_header->flags = mach_header.Swap(mach_header.Swap(mach_header->flags) | MH_DYLDLINK);
+
+ uint32_t size(_not(uint32_t)); {
+ _foreach (load_command, mach_header.GetLoadCommands()) {
+ switch (mach_header.Swap(load_command->cmd)) {
+ case LC_CODE_SIGNATURE: {
+ struct linkedit_data_command *signature = reinterpret_cast<struct linkedit_data_command *>(load_command);
+ memset(reinterpret_cast<uint8_t *>(mach_header.GetBase()) + mach_header.Swap(signature->dataoff), 0, mach_header.Swap(signature->datasize));
+ memset(signature, 0, sizeof(struct linkedit_data_command));
+
+ mach_header->ncmds = mach_header.Swap(mach_header.Swap(mach_header->ncmds) - 1);
+ mach_header->sizeofcmds = mach_header.Swap(uint32_t(mach_header.Swap(mach_header->sizeofcmds) - sizeof(struct linkedit_data_command)));
+ } break;
+
+ case LC_SYMTAB: {
+ struct symtab_command *symtab = reinterpret_cast<struct symtab_command *>(load_command);
+ size = mach_header.Swap(symtab->stroff) + mach_header.Swap(symtab->strsize);
+ } break;
+ }
+ }
+ }
+
+ _assert(size != _not(uint32_t));
+
+ _foreach (segment, mach_header.GetSegments("__LINKEDIT")) {
+ segment->filesize -= mach_header.GetSize() - size;
+
+ if (fat_arch *fat_arch = mach_header.GetFatArch()) {
+ fat_arch->size = fat_header.Swap(size);
+ clip = std::max(clip, fat_header.Swap(fat_arch->offset) + size);
+ } else
+ clip = std::max(clip, size);
+ }
+
+ _foreach (segment, mach_header.GetSegments64("__LINKEDIT")) {
+ segment->filesize -= mach_header.GetSize() - size;
+
+ if (fat_arch *fat_arch = mach_header.GetFatArch()) {
+ fat_arch->size = fat_header.Swap(size);
+ clip = std::max(clip, fat_header.Swap(fat_arch->offset) + size);
+ } else
+ clip = std::max(clip, size);
+ }
+ }
+ }
+
+ if (clip != 0)
+ _syscall(truncate(path, clip));
+ }
+
+ if (flag_S) {
+ FatHeader source(Map(path));
+
+ size_t offset(0);
+
+ if (source.IsFat())
+ offset += sizeof(fat_header) + sizeof(fat_arch) * source.Swap(source->nfat_arch);
+
+ std::vector<CodesignAllocation> allocations; {
+ _foreach (mach_header, source.GetMachHeaders()) {
+ if (flag_A) {
+ if (mach_header.GetCPUType() != flag_CPUType)
+ continue;
+ if (mach_header.GetCPUSubtype() != flag_CPUSubtype)
+ continue;
+ }
+
+ mach_header->flags = mach_header.Swap(mach_header.Swap(mach_header->flags) | MH_DYLDLINK);
+
+ size_t size(_not(size_t)); {
+ _foreach (load_command, mach_header.GetLoadCommands()) {
+ uint32_t cmd(mach_header.Swap(load_command->cmd));
+ if (cmd == LC_CODE_SIGNATURE) {
+ struct linkedit_data_command *signature = reinterpret_cast<struct linkedit_data_command *>(load_command);
+ size = mach_header.Swap(signature->dataoff);
+ _assert(size < mach_header.GetSize());
+ break;
+ }
+ }
+
+ if (size == _not(size_t))
+ size = mach_header.GetSize();
+ }
+
+ size_t alloc(0);
+ alloc += sizeof(struct SuperBlob);
+ uint32_t special(0);
+
+ special = std::max(special, CSSLOT_CODEDIRECTORY);
+ alloc += sizeof(struct BlobIndex);
+ alloc += sizeof(struct CodeDirectory);
+ alloc += strlen(name) + 1;
+
+ special = std::max(special, CSSLOT_REQUIREMENTS);
+ alloc += sizeof(struct BlobIndex);
+ alloc += 0xc;
+
+ if (xmld != NULL) {
+ special = std::max(special, CSSLOT_ENTITLEMENTS);
+ alloc += sizeof(struct BlobIndex);
+ alloc += sizeof(struct Blob);
+ alloc += xmls;
+ }
+
+ size_t normal((size + 0x1000 - 1) / 0x1000);
+ alloc = Align(alloc + (special + normal) * 0x20, 16);
+
+ fat_arch *fat_arch(mach_header.GetFatArch());
+ uint32_t align(fat_arch == NULL ? 0 : source.Swap(fat_arch->align));
+ offset = Align(offset, 1 << align);
+
+ allocations.push_back(CodesignAllocation(mach_header, offset, size, alloc, align));
+ offset += size + alloc;
+ offset = Align(offset, 16);
+ }
+ }
+
+ asprintf(&temp, "%s.%s.cs", dir, base);
+ fclose(fopen(temp, "w+"));
+ _syscall(truncate(temp, offset));
+
+ void *file(map(temp, 0, offset, NULL, false));
+ memset(file, 0, offset);
+
+ fat_arch *fat_arch;
+ if (!source.IsFat())
+ fat_arch = NULL;
+ else {
+ fat_header *fat_header(reinterpret_cast<struct fat_header *>(file));
+ fat_header->magic = Swap(FAT_MAGIC);
+ fat_header->nfat_arch = Swap(source.Swap(source->nfat_arch));
+ fat_arch = reinterpret_cast<struct fat_arch *>(fat_header + 1);
+ }
+
+ _foreach (allocation, allocations) {
+ const FatMachHeader &source(allocation.mach_header_);
+
+ uint32_t align(allocation.size_);
+ align = Align(align, 0x10);
+
+ if (fat_arch != NULL) {
+ fat_arch->cputype = Swap(source->cputype);
+ fat_arch->cpusubtype = Swap(source->cpusubtype);
+ fat_arch->offset = Swap(allocation.offset_);
+ fat_arch->size = Swap(align + allocation.alloc_);
+ fat_arch->align = Swap(allocation.align_);
+ ++fat_arch;
+ }
+
+ void *target(reinterpret_cast<uint8_t *>(file) + allocation.offset_);
+ memcpy(target, source, allocation.size_);
+ MachHeader mach_header(target, align + allocation.alloc_);
+
+ struct linkedit_data_command *signature(NULL);
+ _foreach (load_command, mach_header.GetLoadCommands()) {
+ uint32_t cmd(mach_header.Swap(load_command->cmd));
+ if (cmd != LC_CODE_SIGNATURE)
+ continue;
+ signature = reinterpret_cast<struct linkedit_data_command *>(load_command);
+ break;
+ }
+
+ if (signature == NULL) {
+ mach_header->ncmds = mach_header.Swap(mach_header.Swap(mach_header->ncmds) + 1);
+ signature = reinterpret_cast<struct linkedit_data_command *>(reinterpret_cast<uint8_t *>(mach_header.GetLoadCommand()) + mach_header.Swap(mach_header->sizeofcmds));
+ mach_header->sizeofcmds = mach_header.Swap(mach_header.Swap(mach_header->sizeofcmds) + uint32_t(sizeof(*signature)));
+ signature->cmd = mach_header.Swap(LC_CODE_SIGNATURE);
+ signature->cmdsize = mach_header.Swap(uint32_t(sizeof(*signature)));
+ }
+
+ signature->dataoff = mach_header.Swap(align);
+ signature->datasize = mach_header.Swap(allocation.alloc_);
+
+ _foreach (segment, mach_header.GetSegments("__LINKEDIT")) {
+ size_t size(mach_header.Swap(align + allocation.alloc_ - mach_header.Swap(segment->fileoff)));
+ segment->filesize = size;
+ segment->vmsize = Align(size, 0x1000);
+ }
+
+ _foreach (segment, mach_header.GetSegments64("__LINKEDIT")) {
+ size_t size(mach_header.Swap(align + allocation.alloc_ - mach_header.Swap(segment->fileoff)));
+ segment->filesize = size;
+ segment->vmsize = Align(size, 0x1000);
+ }
+ }
+ }
+
+ if (flag_p)
+ printf("path%zu='%s'\n", filei, file.c_str());
+
+ FatHeader fat_header(Map(temp == NULL ? path : temp, !(flag_R || flag_T || flag_s || flag_S || flag_O || flag_D)));
+ struct linkedit_data_command *signature(NULL);
+
+ _foreach (mach_header, fat_header.GetMachHeaders()) {
+ if (flag_A) {
+ if (mach_header.GetCPUType() != flag_CPUType)
+ continue;
+ if (mach_header.GetCPUSubtype() != flag_CPUSubtype)
+ continue;
+ }
+
+ if (flag_a)
+ printf("cpu=0x%x:0x%x\n", mach_header.GetCPUType(), mach_header.GetCPUSubtype());
+
+ if (flag_d) {
+ if (struct fat_arch *fat_arch = mach_header.GetFatArch())
+ printf("offset=0x%x\n", Swap(fat_arch->offset));
+ else
+ printf("offset=0x0\n");
+ }
+
+ if (woffset != _not(uintptr_t)) {
+ Pointer<uint32_t> wvalue(mach_header.GetPointer<uint32_t>(woffset));
+ if (wvalue == NULL)
+ printf("(null) %p\n", reinterpret_cast<void *>(woffset));
+ else
+ printf("0x%.08x\n", *wvalue);
+ }
+
+ if (noffset != _not(uintptr_t))
+ printf("%s\n", &*mach_header.GetPointer<char>(noffset));
+
+ if (flag_d)
+ _foreach(segment, mach_header.GetSegments("__TEXT")) {
+ printf("vmaddr=0x%x\n", mach_header.Swap(segment->vmaddr));
+ printf("fileoff=0x%x\n", mach_header.Swap(segment->fileoff));
+ }
+
+ if (flag_O) {
+ _foreach(section, mach_header.GetSections("__TEXT", "__text"))
+ section->addr = mach_header.Swap(0);
+ }
+
+ _foreach (load_command, mach_header.GetLoadCommands()) {
+ uint32_t cmd(mach_header.Swap(load_command->cmd));
+
+ if (flag_R && cmd == LC_REEXPORT_DYLIB)
+ load_command->cmd = mach_header.Swap(LC_LOAD_DYLIB);
+ else if (cmd == LC_CODE_SIGNATURE)
+ signature = reinterpret_cast<struct linkedit_data_command *>(load_command);
+ else if (cmd == LC_UUID) {
+ volatile struct uuid_command *uuid_command(reinterpret_cast<struct uuid_command *>(load_command));
+
+ if (flag_u) {
+ printf("uuid%zu=%.2x%.2x%.2x%.2x-%.2x%.2x-%.2x%.2x-%.2x%.2x-%.2x%.2x%.2x%.2x%.2x%.2x\n", filei,
+ uuid_command->uuid[ 0], uuid_command->uuid[ 1], uuid_command->uuid[ 2], uuid_command->uuid[ 3],
+ uuid_command->uuid[ 4], uuid_command->uuid[ 5], uuid_command->uuid[ 6], uuid_command->uuid[ 7],
+ uuid_command->uuid[ 8], uuid_command->uuid[ 9], uuid_command->uuid[10], uuid_command->uuid[11],
+ uuid_command->uuid[12], uuid_command->uuid[13], uuid_command->uuid[14], uuid_command->uuid[15]
+ );
+ }
+ } else if (cmd == LC_ID_DYLIB) {
+ volatile struct dylib_command *dylib_command(reinterpret_cast<struct dylib_command *>(load_command));
+
+ if (flag_t)
+ printf("time%zu=0x%.8x\n", filei, mach_header.Swap(dylib_command->dylib.timestamp));
+
+ if (flag_T) {
+ uint32_t timed;
+
+ if (!timeh)
+ timed = timev;
+ else {
+ dylib_command->dylib.timestamp = 0;
+ timed = hash(reinterpret_cast<uint8_t *>(mach_header.GetBase()), mach_header.GetSize(), timev);
+ }
+
+ dylib_command->dylib.timestamp = mach_header.Swap(timed);
+ }
+ } else if (cmd == LC_ENCRYPTION_INFO) {
+ volatile struct encryption_info_command *encryption_info_command(reinterpret_cast<struct encryption_info_command *>(load_command));
+
+ if (flag_D)
+ encryption_info_command->cryptid = mach_header.Swap(0);
+
+ if (flag_d) {
+ printf("cryptoff=0x%x\n", mach_header.Swap(encryption_info_command->cryptoff));
+ printf("cryptsize=0x%x\n", mach_header.Swap(encryption_info_command->cryptsize));
+ printf("cryptid=0x%x\n", mach_header.Swap(encryption_info_command->cryptid));
+ }
+ }
+ }
+
+ if (flag_e) {
+ _assert(signature != NULL);
+
+ uint32_t data = mach_header.Swap(signature->dataoff);
+
+ uint8_t *top = reinterpret_cast<uint8_t *>(mach_header.GetBase());
+ uint8_t *blob = top + data;
+ struct SuperBlob *super = reinterpret_cast<struct SuperBlob *>(blob);
+
+ for (size_t index(0); index != Swap(super->count); ++index)
+ if (Swap(super->index[index].type) == CSSLOT_ENTITLEMENTS) {
+ uint32_t begin = Swap(super->index[index].offset);
+ struct Blob *entitlements = reinterpret_cast<struct Blob *>(blob + begin);
+ fwrite(entitlements + 1, 1, Swap(entitlements->length) - sizeof(struct Blob), stdout);
+ }
+ }
+
+ if (flag_s) {
+ _assert(signature != NULL);
+
+ uint32_t data = mach_header.Swap(signature->dataoff);
+
+ uint8_t *top = reinterpret_cast<uint8_t *>(mach_header.GetBase());
+ uint8_t *blob = top + data;
+ struct SuperBlob *super = reinterpret_cast<struct SuperBlob *>(blob);
+
+ for (size_t index(0); index != Swap(super->count); ++index)
+ if (Swap(super->index[index].type) == CSSLOT_CODEDIRECTORY) {
+ uint32_t begin = Swap(super->index[index].offset);
+ struct CodeDirectory *directory = reinterpret_cast<struct CodeDirectory *>(blob + begin);
+
+ uint8_t (*hashes)[32] = reinterpret_cast<uint8_t (*)[32]>(blob + begin + Swap(directory->hashOffset));
+ uint32_t pages = Swap(directory->nCodeSlots);
+
+ if (pages != 1)
+ for (size_t i = 0; i != pages - 1; ++i)
+ sha2(hashes[i], top + 0x1000 * i, 0x1000);
+ if (pages != 0)
+ sha2(hashes[pages - 1], top + 0x1000 * (pages - 1), ((data - 1) % 0x1000) + 1);
+ }
+ }
+
+ if (flag_S) {
+ _assert(signature != NULL);
+
+ uint32_t data = mach_header.Swap(signature->dataoff);
+ uint32_t size = mach_header.Swap(signature->datasize);
+
+ uint8_t *top = reinterpret_cast<uint8_t *>(mach_header.GetBase());
+ uint8_t *blob = top + data;
+ struct SuperBlob *super = reinterpret_cast<struct SuperBlob *>(blob);
+ super->blob.magic = Swap(CSMAGIC_EMBEDDED_SIGNATURE);
+
+ uint32_t count = xmld == NULL ? 2 : 3;
+ uint32_t offset = sizeof(struct SuperBlob) + count * sizeof(struct BlobIndex);
+
+ super->index[0].type = Swap(CSSLOT_CODEDIRECTORY);
+ super->index[0].offset = Swap(offset);
+
+ uint32_t begin = offset;
+ struct CodeDirectory *directory = reinterpret_cast<struct CodeDirectory *>(blob + begin);
+ offset += sizeof(struct CodeDirectory);
+
+ directory->blob.magic = Swap(CSMAGIC_CODEDIRECTORY);
+ directory->version = Swap(uint32_t(0x00020001));
+ directory->flags = Swap(uint32_t(0));
+ directory->codeLimit = Swap(data);
+ directory->hashSize = 0x20;
+ directory->hashType = 0x02;
+ directory->spare1 = 0x00;
+ directory->pageSize = 0x0c;
+ directory->spare2 = Swap(uint32_t(0));
+
+ directory->identOffset = Swap(offset - begin);
+ strcpy(reinterpret_cast<char *>(blob + offset), name);
+ offset += strlen(name) + 1;
+
+ uint32_t special = xmld == NULL ? CSSLOT_REQUIREMENTS : CSSLOT_ENTITLEMENTS;
+ directory->nSpecialSlots = Swap(special);
+
+ uint8_t (*hashes)[32] = reinterpret_cast<uint8_t (*)[32]>(blob + offset);
+ memset(hashes, 0, sizeof(*hashes) * special);
+
+ offset += sizeof(*hashes) * special;
+ hashes += special;
+
+ uint32_t pages = (data + 0x1000 - 1) / 0x1000;
+ directory->nCodeSlots = Swap(pages);
+
+ if (pages != 1)
+ for (size_t i = 0; i != pages - 1; ++i)
+ sha2(hashes[i], top + 0x1000 * i, 0x1000);
+ if (pages != 0)
+ sha2(hashes[pages - 1], top + 0x1000 * (pages - 1), ((data - 1) % 0x1000) + 1);
+
+ directory->hashOffset = Swap(offset - begin);
+ offset += sizeof(*hashes) * pages;
+ directory->blob.length = Swap(offset - begin);
+
+ super->index[1].type = Swap(CSSLOT_REQUIREMENTS);
+ super->index[1].offset = Swap(offset);
+
+ memcpy(blob + offset, "\xfa\xde\x0c\x01\x00\x00\x00\x0c\x00\x00\x00\x00", 0xc);
+ offset += 0xc;
+
+ if (xmld != NULL) {
+ super->index[2].type = Swap(CSSLOT_ENTITLEMENTS);
+ super->index[2].offset = Swap(offset);
+
+ uint32_t begin = offset;
+ struct Blob *entitlements = reinterpret_cast<struct Blob *>(blob + begin);
+ offset += sizeof(struct Blob);
+
+ memcpy(blob + offset, xmld, xmls);
+ offset += xmls;
+
+ entitlements->magic = Swap(CSMAGIC_ENTITLEMENTS);
+ entitlements->length = Swap(offset - begin);
+ }
+
+ for (size_t index(0); index != count; ++index) {
+ uint32_t type = Swap(super->index[index].type);
+ if (type != 0 && type <= special) {
+ uint32_t offset = Swap(super->index[index].offset);
+ struct Blob *local = (struct Blob *) (blob + offset);
+ sha2((uint8_t *) (hashes - type), (uint8_t *) local, Swap(local->length));
+ }
+ }
+
+ super->count = Swap(count);
+ super->blob.length = Swap(offset);
+
+ if (offset > size) {
+ fprintf(stderr, "offset (%u) > size (%u)\n", offset, size);
+ _assert(false);
+ } //else fprintf(stderr, "offset (%zu) <= size (%zu)\n", offset, size);
+
+ memset(blob + offset, 0, size - offset);
+ }
+ }
+
+ if (flag_S) {
+ uint8_t *top = reinterpret_cast<uint8_t *>(fat_header.GetBase());
+ size_t size = fat_header.GetSize();
+
+ char *copy;
+ asprintf(&copy, "%s.%s.cp", dir, base);
+ FILE *file = fopen(copy, "w+");
+ size_t writ = fwrite(top, 1, size, file);
+ _assert(writ == size);
+ fclose(file);
+
+ _syscall(unlink(temp));
+ free(temp);
+ temp = copy;
+ }
+
+ if (temp != NULL) {
+ struct stat info;
+ _syscall(stat(path, &info));
+ _syscall(chown(temp, info.st_uid, info.st_gid));
+ _syscall(chmod(temp, info.st_mode));
+ _syscall(unlink(path));
+ _syscall(rename(temp, path));
+ free(temp);
+ }
+
+ free(dir);
+ ++filei;
+ } catch (const char *) {
+ ++filee;
+ ++filei;
+ }
+
+ return filee;
+}
diff --git a/util/ldid-xerub/lookup2.c b/util/ldid-xerub/lookup2.c
new file mode 100644
index 000000000..cd87c4d17
--- /dev/null
+++ b/util/ldid-xerub/lookup2.c
@@ -0,0 +1,416 @@
+/*
+--------------------------------------------------------------------
+lookup2.c, by Bob Jenkins, December 1996, Public Domain.
+hash(), hash2(), hash3, and mix() are externally useful functions.
+Routines to test the hash are included if SELF_TEST is defined.
+You can use this free for any purpose. It has no warranty.
+--------------------------------------------------------------------
+*/
+#include <stdio.h>
+#include <stddef.h>
+#include <stdlib.h>
+typedef unsigned long int ub4; /* unsigned 4-byte quantities */
+typedef unsigned char ub1;
+
+#define hashsize(n) ((ub4)1<<(n))
+#define hashmask(n) (hashsize(n)-1)
+
+/*
+--------------------------------------------------------------------
+mix -- mix 3 32-bit values reversibly.
+For every delta with one or two bit set, and the deltas of all three
+ high bits or all three low bits, whether the original value of a,b,c
+ is almost all zero or is uniformly distributed,
+* If mix() is run forward or backward, at least 32 bits in a,b,c
+ have at least 1/4 probability of changing.
+* If mix() is run forward, every bit of c will change between 1/3 and
+ 2/3 of the time. (Well, 22/100 and 78/100 for some 2-bit deltas.)
+mix() was built out of 36 single-cycle latency instructions in a
+ structure that could supported 2x parallelism, like so:
+ a -= b;
+ a -= c; x = (c>>13);
+ b -= c; a ^= x;
+ b -= a; x = (a<<8);
+ c -= a; b ^= x;
+ c -= b; x = (b>>13);
+ ...
+ Unfortunately, superscalar Pentiums and Sparcs can't take advantage
+ of that parallelism. They've also turned some of those single-cycle
+ latency instructions into multi-cycle latency instructions. Still,
+ this is the fastest good hash I could find. There were about 2^^68
+ to choose from. I only looked at a billion or so.
+--------------------------------------------------------------------
+*/
+#define mix(a,b,c) \
+{ \
+ a -= b; a -= c; a ^= (c>>13); \
+ b -= c; b -= a; b ^= (a<<8); \
+ c -= a; c -= b; c ^= (b>>13); \
+ a -= b; a -= c; a ^= (c>>12); \
+ b -= c; b -= a; b ^= (a<<16); \
+ c -= a; c -= b; c ^= (b>>5); \
+ a -= b; a -= c; a ^= (c>>3); \
+ b -= c; b -= a; b ^= (a<<10); \
+ c -= a; c -= b; c ^= (b>>15); \
+}
+
+/* same, but slower, works on systems that might have 8 byte ub4's */
+#define mix2(a,b,c) \
+{ \
+ a -= b; a -= c; a ^= (c>>13); \
+ b -= c; b -= a; b ^= (a<< 8); \
+ c -= a; c -= b; c ^= ((b&0xffffffff)>>13); \
+ a -= b; a -= c; a ^= ((c&0xffffffff)>>12); \
+ b -= c; b -= a; b = (b ^ (a<<16)) & 0xffffffff; \
+ c -= a; c -= b; c = (c ^ (b>> 5)) & 0xffffffff; \
+ a -= b; a -= c; a = (a ^ (c>> 3)) & 0xffffffff; \
+ b -= c; b -= a; b = (b ^ (a<<10)) & 0xffffffff; \
+ c -= a; c -= b; c = (c ^ (b>>15)) & 0xffffffff; \
+}
+
+/*
+--------------------------------------------------------------------
+hash() -- hash a variable-length key into a 32-bit value
+ k : the key (the unaligned variable-length array of bytes)
+ len : the length of the key, counting by bytes
+ level : can be any 4-byte value
+Returns a 32-bit value. Every bit of the key affects every bit of
+the return value. Every 1-bit and 2-bit delta achieves avalanche.
+About 36+6len instructions.
+
+The best hash table sizes are powers of 2. There is no need to do
+mod a prime (mod is sooo slow!). If you need less than 32 bits,
+use a bitmask. For example, if you need only 10 bits, do
+ h = (h & hashmask(10));
+In which case, the hash table should have hashsize(10) elements.
+
+If you are hashing n strings (ub1 **)k, do it like this:
+ for (i=0, h=0; i<n; ++i) h = hash( k[i], len[i], h);
+
+By Bob Jenkins, 1996. bob_jenkins@burtleburtle.net. You may use this
+code any way you wish, private, educational, or commercial. It's free.
+
+See http://burlteburtle.net/bob/hash/evahash.html
+Use for hash table lookup, or anything where one collision in 2^32 is
+acceptable. Do NOT use for cryptographic purposes.
+--------------------------------------------------------------------
+*/
+
+ub4 hash( k, length, initval)
+register ub1 *k; /* the key */
+register ub4 length; /* the length of the key */
+register ub4 initval; /* the previous hash, or an arbitrary value */
+{
+ register ub4 a,b,c,len;
+
+ /* Set up the internal state */
+ len = length;
+ a = b = 0x9e3779b9; /* the golden ratio; an arbitrary value */
+ c = initval; /* the previous hash value */
+
+ /*---------------------------------------- handle most of the key */
+ while (len >= 12)
+ {
+ a += (k[0] +((ub4)k[1]<<8) +((ub4)k[2]<<16) +((ub4)k[3]<<24));
+ b += (k[4] +((ub4)k[5]<<8) +((ub4)k[6]<<16) +((ub4)k[7]<<24));
+ c += (k[8] +((ub4)k[9]<<8) +((ub4)k[10]<<16)+((ub4)k[11]<<24));
+ mix(a,b,c);
+ k += 12; len -= 12;
+ }
+
+ /*------------------------------------- handle the last 11 bytes */
+ c += length;
+ switch(len) /* all the case statements fall through */
+ {
+ case 11: c+=((ub4)k[10]<<24);
+ case 10: c+=((ub4)k[9]<<16);
+ case 9 : c+=((ub4)k[8]<<8);
+ /* the first byte of c is reserved for the length */
+ case 8 : b+=((ub4)k[7]<<24);
+ case 7 : b+=((ub4)k[6]<<16);
+ case 6 : b+=((ub4)k[5]<<8);
+ case 5 : b+=k[4];
+ case 4 : a+=((ub4)k[3]<<24);
+ case 3 : a+=((ub4)k[2]<<16);
+ case 2 : a+=((ub4)k[1]<<8);
+ case 1 : a+=k[0];
+ /* case 0: nothing left to add */
+ }
+ mix(a,b,c);
+ /*-------------------------------------------- report the result */
+ return c;
+}
+
+
+/*
+--------------------------------------------------------------------
+ This works on all machines. hash2() is identical to hash() on
+ little-endian machines, except that the length has to be measured
+ in ub4s instead of bytes. It is much faster than hash(). It
+ requires
+ -- that the key be an array of ub4's, and
+ -- that all your machines have the same endianness, and
+ -- that the length be the number of ub4's in the key
+--------------------------------------------------------------------
+*/
+ub4 hash2( k, length, initval)
+register ub4 *k; /* the key */
+register ub4 length; /* the length of the key, in ub4s */
+register ub4 initval; /* the previous hash, or an arbitrary value */
+{
+ register ub4 a,b,c,len;
+
+ /* Set up the internal state */
+ len = length;
+ a = b = 0x9e3779b9; /* the golden ratio; an arbitrary value */
+ c = initval; /* the previous hash value */
+
+ /*---------------------------------------- handle most of the key */
+ while (len >= 3)
+ {
+ a += k[0];
+ b += k[1];
+ c += k[2];
+ mix(a,b,c);
+ k += 3; len -= 3;
+ }
+
+ /*-------------------------------------- handle the last 2 ub4's */
+ c += length;
+ switch(len) /* all the case statements fall through */
+ {
+ /* c is reserved for the length */
+ case 2 : b+=k[1];
+ case 1 : a+=k[0];
+ /* case 0: nothing left to add */
+ }
+ mix(a,b,c);
+ /*-------------------------------------------- report the result */
+ return c;
+}
+
+/*
+--------------------------------------------------------------------
+ This is identical to hash() on little-endian machines (like Intel
+ x86s or VAXen). It gives nondeterministic results on big-endian
+ machines. It is faster than hash(), but a little slower than
+ hash2(), and it requires
+ -- that all your machines be little-endian
+--------------------------------------------------------------------
+*/
+
+ub4 hash3( k, length, initval)
+register ub1 *k; /* the key */
+register ub4 length; /* the length of the key */
+register ub4 initval; /* the previous hash, or an arbitrary value */
+{
+ register ub4 a,b,c,len;
+
+ /* Set up the internal state */
+ len = length;
+ a = b = 0x9e3779b9; /* the golden ratio; an arbitrary value */
+ c = initval; /* the previous hash value */
+
+ /*---------------------------------------- handle most of the key */
+ if (((ub4)k)&3)
+ {
+ while (len >= 12) /* unaligned */
+ {
+ a += (k[0] +((ub4)k[1]<<8) +((ub4)k[2]<<16) +((ub4)k[3]<<24));
+ b += (k[4] +((ub4)k[5]<<8) +((ub4)k[6]<<16) +((ub4)k[7]<<24));
+ c += (k[8] +((ub4)k[9]<<8) +((ub4)k[10]<<16)+((ub4)k[11]<<24));
+ mix(a,b,c);
+ k += 12; len -= 12;
+ }
+ }
+ else
+ {
+ while (len >= 12) /* aligned */
+ {
+ a += *(ub4 *)(k+0);
+ b += *(ub4 *)(k+4);
+ c += *(ub4 *)(k+8);
+ mix(a,b,c);
+ k += 12; len -= 12;
+ }
+ }
+
+ /*------------------------------------- handle the last 11 bytes */
+ c += length;
+ switch(len) /* all the case statements fall through */
+ {
+ case 11: c+=((ub4)k[10]<<24);
+ case 10: c+=((ub4)k[9]<<16);
+ case 9 : c+=((ub4)k[8]<<8);
+ /* the first byte of c is reserved for the length */
+ case 8 : b+=((ub4)k[7]<<24);
+ case 7 : b+=((ub4)k[6]<<16);
+ case 6 : b+=((ub4)k[5]<<8);
+ case 5 : b+=k[4];
+ case 4 : a+=((ub4)k[3]<<24);
+ case 3 : a+=((ub4)k[2]<<16);
+ case 2 : a+=((ub4)k[1]<<8);
+ case 1 : a+=k[0];
+ /* case 0: nothing left to add */
+ }
+ mix(a,b,c);
+ /*-------------------------------------------- report the result */
+ return c;
+}
+
+
+
+#ifdef SELF_TEST
+
+/* used for timings */
+void driver1()
+{
+ ub4 buf[256];
+ ub4 i;
+ ub4 h=0;
+
+ for (i=0; i<256; ++i)
+ {
+ h = hash(buf,i,h);
+ }
+}
+
+/* check that every input bit changes every output bit half the time */
+#define HASHSTATE 1
+#define HASHLEN 1
+#define MAXPAIR 80
+#define MAXLEN 70
+void driver2()
+{
+ ub1 qa[MAXLEN+1], qb[MAXLEN+2], *a = &qa[0], *b = &qb[1];
+ ub4 c[HASHSTATE], d[HASHSTATE], i, j=0, k, l, m, z;
+ ub4 e[HASHSTATE],f[HASHSTATE],g[HASHSTATE],h[HASHSTATE];
+ ub4 x[HASHSTATE],y[HASHSTATE];
+ ub4 hlen;
+
+ printf("No more than %d trials should ever be needed \n",MAXPAIR/2);
+ for (hlen=0; hlen < MAXLEN; ++hlen)
+ {
+ z=0;
+ for (i=0; i<hlen; ++i) /*----------------------- for each input byte, */
+ {
+ for (j=0; j<8; ++j) /*------------------------ for each input bit, */
+ {
+ for (m=1; m<8; ++m) /*------------ for serveral possible initvals, */
+ {
+ for (l=0; l<HASHSTATE; ++l) e[l]=f[l]=g[l]=h[l]=x[l]=y[l]=~((ub4)0);
+
+ /*---- check that every output bit is affected by that input bit */
+ for (k=0; k<MAXPAIR; k+=2)
+ {
+ ub4 finished=1;
+ /* keys have one bit different */
+ for (l=0; l<hlen+1; ++l) {a[l] = b[l] = (ub1)0;}
+ /* have a and b be two keys differing in only one bit */
+ a[i] ^= (k<<j);
+ a[i] ^= (k>>(8-j));
+ c[0] = hash(a, hlen, m);
+ b[i] ^= ((k+1)<<j);
+ b[i] ^= ((k+1)>>(8-j));
+ d[0] = hash(b, hlen, m);
+ /* check every bit is 1, 0, set, and not set at least once */
+ for (l=0; l<HASHSTATE; ++l)
+ {
+ e[l] &= (c[l]^d[l]);
+ f[l] &= ~(c[l]^d[l]);
+ g[l] &= c[l];
+ h[l] &= ~c[l];
+ x[l] &= d[l];
+ y[l] &= ~d[l];
+ if (e[l]|f[l]|g[l]|h[l]|x[l]|y[l]) finished=0;
+ }
+ if (finished) break;
+ }
+ if (k>z) z=k;
+ if (k==MAXPAIR)
+ {
+ printf("Some bit didn't change: ");
+ printf("%.8lx %.8lx %.8lx %.8lx %.8lx %.8lx ",
+ e[0],f[0],g[0],h[0],x[0],y[0]);
+ printf("i %ld j %ld m %ld len %ld\n",i,j,m,hlen);
+ }
+ if (z==MAXPAIR) goto done;
+ }
+ }
+ }
+ done:
+ if (z < MAXPAIR)
+ {
+ printf("Mix success %2ld bytes %2ld initvals ",i,m);
+ printf("required %ld trials\n",z/2);
+ }
+ }
+ printf("\n");
+}
+
+/* Check for reading beyond the end of the buffer and alignment problems */
+void driver3()
+{
+ ub1 buf[MAXLEN+20], *b;
+ ub4 len;
+ ub1 q[] = "This is the time for all good men to come to the aid of their country";
+ ub1 qq[] = "xThis is the time for all good men to come to the aid of their country";
+ ub1 qqq[] = "xxThis is the time for all good men to come to the aid of their country";
+ ub1 qqqq[] = "xxxThis is the time for all good men to come to the aid of their country";
+ ub4 h,i,j,ref,x,y;
+
+ printf("Endianness. These should all be the same:\n");
+ printf("%.8lx\n", hash(q, sizeof(q)-1, (ub4)0));
+ printf("%.8lx\n", hash(qq+1, sizeof(q)-1, (ub4)0));
+ printf("%.8lx\n", hash(qqq+2, sizeof(q)-1, (ub4)0));
+ printf("%.8lx\n", hash(qqqq+3, sizeof(q)-1, (ub4)0));
+ printf("\n");
+ for (h=0, b=buf+1; h<8; ++h, ++b)
+ {
+ for (i=0; i<MAXLEN; ++i)
+ {
+ len = i;
+ for (j=0; j<i; ++j) *(b+j)=0;
+
+ /* these should all be equal */
+ ref = hash(b, len, (ub4)1);
+ *(b+i)=(ub1)~0;
+ *(b-1)=(ub1)~0;
+ x = hash(b, len, (ub4)1);
+ y = hash(b, len, (ub4)1);
+ if ((ref != x) || (ref != y))
+ {
+ printf("alignment error: %.8lx %.8lx %.8lx %ld %ld\n",ref,x,y,h,i);
+ }
+ }
+ }
+}
+
+/* check for problems with nulls */
+ void driver4()
+{
+ ub1 buf[1];
+ ub4 h,i,state[HASHSTATE];
+
+
+ buf[0] = ~0;
+ for (i=0; i<HASHSTATE; ++i) state[i] = 1;
+ printf("These should all be different\n");
+ for (i=0, h=0; i<8; ++i)
+ {
+ h = hash(buf, (ub4)0, h);
+ printf("%2ld 0-byte strings, hash is %.8lx\n", i, h);
+ }
+}
+
+
+int main()
+{
+ driver1(); /* test that the key is hashed: used for timings */
+ driver2(); /* test that whole key is hashed thoroughly */
+ driver3(); /* test that nothing but the key is hashed */
+ driver4(); /* test hashing multiple buffers (all buffers are null) */
+ return 1;
+}
+
+#endif /* SELF_TEST */
diff --git a/util/ldid-xerub/make.sh b/util/ldid-xerub/make.sh
new file mode 100755
index 000000000..1630759e8
--- /dev/null
+++ b/util/ldid-xerub/make.sh
@@ -0,0 +1,32 @@
+#!/bin/bash
+
+set -e
+
+if [ -d /Applications/Xcode-5.1.1.app ]; then
+ sudo xcode-select --switch /Applications/Xcode-5.1.1.app
+fi
+
+if which xcrun &>/dev/null; then
+ flags=(xcrun -sdk macosx g++)
+ flags+=(-mmacosx-version-min=10.4)
+
+ for arch in i386 x86_64; do
+ flags+=(-arch "${arch}")
+ done
+else
+ flags=(g++)
+fi
+
+flags+=(-I.)
+
+set -x
+"${flags[@]}" -c -std=c++11 -o ldid.o ldid.cpp
+"${flags[@]}" -o ldid ldid.o -x c lookup2.c -x c sha1.c
+
+"${flags[@]}" -c -std=c++11 -o ldid2.o ldid2.cpp
+"${flags[@]}" -o ldid2 ldid2.o -x c lookup2.c -x c sha1.c -x c sha224-256.c
+
+"${flags[@]}" -std=c++11 -o arid arid.cpp
+
+cp ldid ../
+cp arid ../
diff --git a/util/ldid-xerub/minimal/hexdump.h b/util/ldid-xerub/minimal/hexdump.h
new file mode 100644
index 000000000..a8df7d8a0
--- /dev/null
+++ b/util/ldid-xerub/minimal/hexdump.h
@@ -0,0 +1,76 @@
+/* Minimal - the simplest thing that could possibly work
+ * Copyright (C) 2007 Jay Freeman (saurik)
+*/
+
+/*
+ * Redistribution and use in source and binary
+ * forms, with or without modification, are permitted
+ * provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the
+ * above copyright notice, this list of conditions
+ * and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the
+ * above copyright notice, this list of conditions
+ * and the following disclaimer in the documentation
+ * and/or other materials provided with the
+ * distribution.
+ * 3. The name of the author may not be used to endorse
+ * or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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.
+*/
+
+#ifndef MINIMAL_HEXDUMP_H
+#define MINIMAL_HEXDUMP_H
+
+#include "minimal/stdlib.h"
+
+_disused static char hexchar(uint8_t value) {
+ return value < 0x20 || value >= 0x80 ? '.' : value;
+}
+
+#define HexWidth_ 12
+
+_disused static void hexdump(const char *mark, const uint8_t *data, size_t size) {
+ size_t i = 0, j;
+
+ while (i != size) {
+ if (i % HexWidth_ == 0)
+ printf("[%s] 0x%.3zx:", mark, i);
+
+ printf(" %.2x", data[i]);
+
+ if (++i % HexWidth_ == 0) {
+ printf(" ");
+ for (j = i - HexWidth_; j != i; ++j)
+ printf("%c", hexchar(data[j]));
+ printf("\n");
+ }
+ }
+
+ if (i % HexWidth_ != 0) {
+ for (j = i % HexWidth_; j != HexWidth_; ++j)
+ printf(" ");
+ printf(" ");
+ for (j = i / HexWidth_ * HexWidth_; j != i; ++j)
+ printf("%c", hexchar(data[j]));
+ printf("\n");
+ }
+}
+
+#endif/*MINIMAL_HEXDUMP_H*/ \ No newline at end of file
diff --git a/util/ldid-xerub/minimal/mapping.h b/util/ldid-xerub/minimal/mapping.h
new file mode 100644
index 000000000..2eb53d05d
--- /dev/null
+++ b/util/ldid-xerub/minimal/mapping.h
@@ -0,0 +1,72 @@
+/* Minimal - the simplest thing that could possibly work
+ * Copyright (C) 2007 Jay Freeman (saurik)
+*/
+
+/*
+ * Redistribution and use in source and binary
+ * forms, with or without modification, are permitted
+ * provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the
+ * above copyright notice, this list of conditions
+ * and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the
+ * above copyright notice, this list of conditions
+ * and the following disclaimer in the documentation
+ * and/or other materials provided with the
+ * distribution.
+ * 3. The name of the author may not be used to endorse
+ * or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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.
+*/
+
+#ifndef MINIMAL_MAPPING_H
+#define MINIMAL_MAPPING_H
+
+#include <sys/mman.h>
+
+#include <errno.h>
+#include <unistd.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include "minimal/stdlib.h"
+
+void *map(const char *path, size_t offset, size_t size, size_t *psize, bool ro) {
+ int fd;
+ _syscall(fd = open(path, ro ? O_RDONLY : O_RDWR));
+
+ if (size == _not(size_t)) {
+ struct stat stat;
+ _syscall(fstat(fd, &stat));
+ size = stat.st_size;
+ }
+
+ if (psize != NULL)
+ *psize = size;
+
+ void *base;
+ _syscall(base = mmap(NULL, size, ro ? PROT_READ : PROT_READ | PROT_WRITE, MAP_SHARED, fd, offset));
+
+ _syscall(close(fd));
+ return base;
+}
+
+#endif/*MINIMAL_MAPPING_H*/
diff --git a/util/ldid-xerub/minimal/sqlite3.h b/util/ldid-xerub/minimal/sqlite3.h
new file mode 100644
index 000000000..50c3bd571
--- /dev/null
+++ b/util/ldid-xerub/minimal/sqlite3.h
@@ -0,0 +1,71 @@
+/* Minimal - the simplest thing that could possibly work
+ * Copyright (C) 2007 Jay Freeman (saurik)
+*/
+
+/*
+ * Redistribution and use in source and binary
+ * forms, with or without modification, are permitted
+ * provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the
+ * above copyright notice, this list of conditions
+ * and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the
+ * above copyright notice, this list of conditions
+ * and the following disclaimer in the documentation
+ * and/or other materials provided with the
+ * distribution.
+ * 3. The name of the author may not be used to endorse
+ * or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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.
+*/
+
+#ifndef MINIMAL_SQLITE3_H
+#define MINIMAL_SQLITE3_H
+
+#include <sqlite3.h>
+#include <string.h>
+
+#define _sqlcall(expr) ({ \
+ __typeof__(expr) _value = (expr); \
+ if (_value != 0 && (_value < 100 || _value >= 200)) \
+ _assert(false, "_sqlcall(%u:%s): %s\n", _value, #expr, sqlite3_errmsg(database_)); \
+ _value; \
+})
+
+int sqlite3_bind_string(sqlite3_stmt *stmt, int n, const char *value) {
+ if (value == NULL)
+ return sqlite3_bind_null(stmt, n);
+ else
+ return sqlite3_bind_text(stmt, n, strdup(value), -1, &free);
+}
+
+int sqlite3_bind_boolean(sqlite3_stmt *stmt, int n, bool value) {
+ return sqlite3_bind_int(stmt, n, value ? 1 : 0);
+}
+
+char *sqlite3_column_string(sqlite3_stmt *stmt, int n) {
+ const unsigned char *value = sqlite3_column_text(stmt, n);
+ return value == NULL ? NULL : strdup((const char *) value);
+}
+
+bool sqlite3_column_boolean(sqlite3_stmt *stmt, int n) {
+ return sqlite3_column_int(stmt, n) != 0;
+}
+
+#endif/*MINIMAL_SQLITE3_H*/
diff --git a/util/ldid-xerub/minimal/stdlib.h b/util/ldid-xerub/minimal/stdlib.h
new file mode 100644
index 000000000..80fa2fbef
--- /dev/null
+++ b/util/ldid-xerub/minimal/stdlib.h
@@ -0,0 +1,129 @@
+/* Minimal - the simplest thing that could possibly work
+ * Copyright (C) 2007 Jay Freeman (saurik)
+*/
+
+/*
+ * Redistribution and use in source and binary
+ * forms, with or without modification, are permitted
+ * provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the
+ * above copyright notice, this list of conditions
+ * and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the
+ * above copyright notice, this list of conditions
+ * and the following disclaimer in the documentation
+ * and/or other materials provided with the
+ * distribution.
+ * 3. The name of the author may not be used to endorse
+ * or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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.
+*/
+
+#ifndef MINIMAL_STDLIB_H
+#define MINIMAL_STDLIB_H
+
+#ifdef __i386__
+#define _breakpoint() \
+ __asm__ ("int $0x03")
+#else
+#define _breakpoint()
+#endif
+
+#ifdef __cplusplus
+#define _assert___(line) \
+ #line
+#define _assert__(line) \
+ _assert___(line)
+#define _assert_(e) \
+ throw __FILE__ "(" _assert__(__LINE__) "): _assert(" e ")"
+#else
+#define _assert_(e) \
+ exit(1)
+#endif
+
+#define _assert(expr) \
+ do if (!(expr)) { \
+ fprintf(stderr, "%s(%u): _assert(%s); errno=%u\n", __FILE__, __LINE__, #expr, errno); \
+ _breakpoint(); \
+ _assert_(#expr); \
+ } while (false)
+
+#define _syscall(expr) ({ \
+ __typeof__(expr) _value; \
+ do if ((long) (_value = (expr)) != -1) \
+ break; \
+ else switch (errno) { \
+ case EINTR: \
+ continue; \
+ default: \
+ _assert(false); \
+ } while (true); \
+ _value; \
+})
+
+#define _aprcall(expr) \
+ do { \
+ apr_status_t _aprstatus((expr)); \
+ _assert(_aprstatus == APR_SUCCESS); \
+ } while (false)
+
+#define _forever \
+ for (;;)
+
+#define _trace() \
+ fprintf(stderr, "_trace(%s:%u): %s\n", __FILE__, __LINE__, __FUNCTION__)
+
+#define _not(type) \
+ ((type) ~ (type) 0)
+
+#define _finline \
+ inline __attribute__((always_inline))
+#define _disused \
+ __attribute__((unused))
+
+#define _label__(x) _label ## x
+#define _label_(y) _label__(y)
+#define _label _label_(__LINE__)
+
+#define _packed \
+ __attribute__((packed))
+
+#ifdef __cplusplus
+
+template <typename Type_>
+struct Iterator_ {
+ typedef typename Type_::const_iterator Result;
+};
+
+#define _foreach(item, list) \
+ for (bool _stop(true); _stop; ) \
+ for (const __typeof__(list) &_list = (list); _stop; _stop = false) \
+ for (Iterator_<__typeof__(list)>::Result _item = _list.begin(); _item != _list.end(); ++_item) \
+ for (bool _suck(true); _suck; _suck = false) \
+ for (const __typeof__(*_item) &item = *_item; _suck; _suck = false)
+
+#endif
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <stdint.h>
+
+#endif/*MINIMAL_STDLIB_H*/
diff --git a/util/ldid-xerub/minimal/string.h b/util/ldid-xerub/minimal/string.h
new file mode 100644
index 000000000..c6ebe8bfb
--- /dev/null
+++ b/util/ldid-xerub/minimal/string.h
@@ -0,0 +1,51 @@
+/* Minimal - the simplest thing that could possibly work
+ * Copyright (C) 2007 Jay Freeman (saurik)
+*/
+
+/*
+ * Redistribution and use in source and binary
+ * forms, with or without modification, are permitted
+ * provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the
+ * above copyright notice, this list of conditions
+ * and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the
+ * above copyright notice, this list of conditions
+ * and the following disclaimer in the documentation
+ * and/or other materials provided with the
+ * distribution.
+ * 3. The name of the author may not be used to endorse
+ * or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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.
+*/
+
+#ifndef MINIMAL_STRING_H
+#define MINIMAL_STRING_H
+
+#include <string.h>
+
+_disused static char *strndup_(const char *src, int len) {
+ char *dst = (char *) malloc(len + 1);
+ _assert(dst != NULL);
+ strncpy(dst, src, len);
+ dst[len] = '\0';
+ return dst;
+}
+
+#endif/*MINIMAL_STRING_H*/
diff --git a/util/ldid-xerub/sha-private.h b/util/ldid-xerub/sha-private.h
new file mode 100644
index 000000000..6e9c4520f
--- /dev/null
+++ b/util/ldid-xerub/sha-private.h
@@ -0,0 +1,28 @@
+/************************ sha-private.h ************************/
+/***************** See RFC 6234 for details. *******************/
+#ifndef _SHA_PRIVATE__H
+#define _SHA_PRIVATE__H
+/*
+ * These definitions are defined in FIPS 180-3, section 4.1.
+ * Ch() and Maj() are defined identically in sections 4.1.1,
+ * 4.1.2, and 4.1.3.
+ *
+ * The definitions used in FIPS 180-3 are as follows:
+ */
+
+#ifndef USE_MODIFIED_MACROS
+#define SHA_Ch(x,y,z) (((x) & (y)) ^ ((~(x)) & (z)))
+#define SHA_Maj(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
+#else /* USE_MODIFIED_MACROS */
+/*
+ * The following definitions are equivalent and potentially faster.
+ */
+
+#define SHA_Ch(x, y, z) (((x) & ((y) ^ (z))) ^ (z))
+#define SHA_Maj(x, y, z) (((x) & ((y) | (z))) | ((y) & (z)))
+
+#endif /* USE_MODIFIED_MACROS */
+
+#define SHA_Parity(x, y, z) ((x) ^ (y) ^ (z))
+
+#endif /* _SHA_PRIVATE__H */
diff --git a/util/ldid-xerub/sha.h b/util/ldid-xerub/sha.h
new file mode 100644
index 000000000..1ffd68807
--- /dev/null
+++ b/util/ldid-xerub/sha.h
@@ -0,0 +1,356 @@
+/**************************** sha.h ****************************/
+/***************** See RFC 6234 for details. *******************/
+/*
+ Copyright (c) 2011 IETF Trust and the persons identified as
+ authors of the code. All rights reserved.
+
+ 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.
+
+ - Neither the name of Internet Society, IETF or IETF Trust, nor
+ the names of specific contributors, may be used to endorse or
+ promote products derived from this software without specific
+ prior written permission.
+
+ 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 OWNER 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.
+*/
+#ifndef _SHA_H_
+#define _SHA_H_
+
+/*
+ * Description:
+ * This file implements the Secure Hash Algorithms
+ * as defined in the U.S. National Institute of Standards
+ * and Technology Federal Information Processing Standards
+ * Publication (FIPS PUB) 180-3 published in October 2008
+ * and formerly defined in its predecessors, FIPS PUB 180-1
+ * and FIP PUB 180-2.
+ *
+ * A combined document showing all algorithms is available at
+ * http://csrc.nist.gov/publications/fips/
+ * fips180-3/fips180-3_final.pdf
+ *
+ * The five hashes are defined in these sizes:
+ * SHA-1 20 byte / 160 bit
+ * SHA-224 28 byte / 224 bit
+ * SHA-256 32 byte / 256 bit
+ * SHA-384 48 byte / 384 bit
+ * SHA-512 64 byte / 512 bit
+ *
+ * Compilation Note:
+ * These files may be compiled with two options:
+ * USE_32BIT_ONLY - use 32-bit arithmetic only, for systems
+ * without 64-bit integers
+ *
+ * USE_MODIFIED_MACROS - use alternate form of the SHA_Ch()
+ * and SHA_Maj() macros that are equivalent
+ * and potentially faster on many systems
+ *
+ */
+
+#include <stdint.h>
+/*
+ * If you do not have the ISO standard stdint.h header file, then you
+ * must typedef the following:
+ * name meaning
+ * uint64_t unsigned 64-bit integer
+ * uint32_t unsigned 32-bit integer
+ * uint8_t unsigned 8-bit integer (i.e., unsigned char)
+ * int_least16_t integer of >= 16 bits
+ *
+ * See stdint-example.h
+ */
+
+#ifndef _SHA_enum_
+#define _SHA_enum_
+/*
+ * All SHA functions return one of these values.
+ */
+enum {
+ shaSuccess = 0,
+ shaNull, /* Null pointer parameter */
+ shaInputTooLong, /* input data too long */
+ shaStateError, /* called Input after FinalBits or Result */
+ shaBadParam /* passed a bad parameter */
+};
+#endif /* _SHA_enum_ */
+
+/*
+ * These constants hold size information for each of the SHA
+ * hashing operations
+ */
+enum {
+ SHA1_Message_Block_Size = 64, SHA224_Message_Block_Size = 64,
+ SHA256_Message_Block_Size = 64, SHA384_Message_Block_Size = 128,
+ SHA512_Message_Block_Size = 128,
+ USHA_Max_Message_Block_Size = SHA512_Message_Block_Size,
+
+ SHA1HashSize = 20, SHA224HashSize = 28, SHA256HashSize = 32,
+ SHA384HashSize = 48, SHA512HashSize = 64,
+ USHAMaxHashSize = SHA512HashSize,
+
+ SHA1HashSizeBits = 160, SHA224HashSizeBits = 224,
+ SHA256HashSizeBits = 256, SHA384HashSizeBits = 384,
+ SHA512HashSizeBits = 512, USHAMaxHashSizeBits = SHA512HashSizeBits
+};
+
+/*
+ * These constants are used in the USHA (Unified SHA) functions.
+ */
+typedef enum SHAversion {
+ SHA1, SHA224, SHA256, SHA384, SHA512
+} SHAversion;
+
+/*
+ * This structure will hold context information for the SHA-1
+ * hashing operation.
+ */
+typedef struct SHA1Context {
+ uint32_t Intermediate_Hash[SHA1HashSize/4]; /* Message Digest */
+
+ uint32_t Length_High; /* Message length in bits */
+ uint32_t Length_Low; /* Message length in bits */
+
+ int_least16_t Message_Block_Index; /* Message_Block array index */
+ /* 512-bit message blocks */
+ uint8_t Message_Block[SHA1_Message_Block_Size];
+
+ int Computed; /* Is the hash computed? */
+ int Corrupted; /* Cumulative corruption code */
+} SHA1Context;
+
+/*
+ * This structure will hold context information for the SHA-256
+ * hashing operation.
+ */
+typedef struct SHA256Context {
+ uint32_t Intermediate_Hash[SHA256HashSize/4]; /* Message Digest */
+
+ uint32_t Length_High; /* Message length in bits */
+ uint32_t Length_Low; /* Message length in bits */
+
+ int_least16_t Message_Block_Index; /* Message_Block array index */
+ /* 512-bit message blocks */
+ uint8_t Message_Block[SHA256_Message_Block_Size];
+
+ int Computed; /* Is the hash computed? */
+ int Corrupted; /* Cumulative corruption code */
+} SHA256Context;
+
+/*
+ * This structure will hold context information for the SHA-512
+ * hashing operation.
+ */
+typedef struct SHA512Context {
+#ifdef USE_32BIT_ONLY
+ uint32_t Intermediate_Hash[SHA512HashSize/4]; /* Message Digest */
+ uint32_t Length[4]; /* Message length in bits */
+#else /* !USE_32BIT_ONLY */
+ uint64_t Intermediate_Hash[SHA512HashSize/8]; /* Message Digest */
+ uint64_t Length_High, Length_Low; /* Message length in bits */
+#endif /* USE_32BIT_ONLY */
+
+ int_least16_t Message_Block_Index; /* Message_Block array index */
+ /* 1024-bit message blocks */
+ uint8_t Message_Block[SHA512_Message_Block_Size];
+
+ int Computed; /* Is the hash computed?*/
+ int Corrupted; /* Cumulative corruption code */
+} SHA512Context;
+
+/*
+ * This structure will hold context information for the SHA-224
+ * hashing operation. It uses the SHA-256 structure for computation.
+ */
+typedef struct SHA256Context SHA224Context;
+
+/*
+ * This structure will hold context information for the SHA-384
+ * hashing operation. It uses the SHA-512 structure for computation.
+ */
+typedef struct SHA512Context SHA384Context;
+
+/*
+ * This structure holds context information for all SHA
+ * hashing operations.
+ */
+typedef struct USHAContext {
+ int whichSha; /* which SHA is being used */
+ union {
+ SHA1Context sha1Context;
+ SHA224Context sha224Context; SHA256Context sha256Context;
+ SHA384Context sha384Context; SHA512Context sha512Context;
+ } ctx;
+} USHAContext;
+
+/*
+ * This structure will hold context information for the HMAC
+ * keyed-hashing operation.
+ */
+typedef struct HMACContext {
+ int whichSha; /* which SHA is being used */
+ int hashSize; /* hash size of SHA being used */
+ int blockSize; /* block size of SHA being used */
+ USHAContext shaContext; /* SHA context */
+ unsigned char k_opad[USHA_Max_Message_Block_Size];
+ /* outer padding - key XORd with opad */
+ int Computed; /* Is the MAC computed? */
+ int Corrupted; /* Cumulative corruption code */
+
+} HMACContext;
+
+/*
+ * This structure will hold context information for the HKDF
+ * extract-and-expand Key Derivation Functions.
+ */
+typedef struct HKDFContext {
+ int whichSha; /* which SHA is being used */
+ HMACContext hmacContext;
+ int hashSize; /* hash size of SHA being used */
+ unsigned char prk[USHAMaxHashSize];
+ /* pseudo-random key - output of hkdfInput */
+ int Computed; /* Is the key material computed? */
+ int Corrupted; /* Cumulative corruption code */
+} HKDFContext;
+
+/*
+ * Function Prototypes
+ */
+
+/* SHA-1 */
+extern int SHA1Reset(SHA1Context *);
+extern int SHA1Input(SHA1Context *, const uint8_t *bytes,
+ unsigned int bytecount);
+extern int SHA1FinalBits(SHA1Context *, uint8_t bits,
+ unsigned int bit_count);
+extern int SHA1Result(SHA1Context *,
+ uint8_t Message_Digest[SHA1HashSize]);
+
+/* SHA-224 */
+extern int SHA224Reset(SHA224Context *);
+extern int SHA224Input(SHA224Context *, const uint8_t *bytes,
+ unsigned int bytecount);
+extern int SHA224FinalBits(SHA224Context *, uint8_t bits,
+ unsigned int bit_count);
+extern int SHA224Result(SHA224Context *,
+ uint8_t Message_Digest[SHA224HashSize]);
+
+/* SHA-256 */
+extern int SHA256Reset(SHA256Context *);
+extern int SHA256Input(SHA256Context *, const uint8_t *bytes,
+ unsigned int bytecount);
+extern int SHA256FinalBits(SHA256Context *, uint8_t bits,
+ unsigned int bit_count);
+extern int SHA256Result(SHA256Context *,
+ uint8_t Message_Digest[SHA256HashSize]);
+
+/* SHA-384 */
+extern int SHA384Reset(SHA384Context *);
+extern int SHA384Input(SHA384Context *, const uint8_t *bytes,
+ unsigned int bytecount);
+extern int SHA384FinalBits(SHA384Context *, uint8_t bits,
+ unsigned int bit_count);
+extern int SHA384Result(SHA384Context *,
+ uint8_t Message_Digest[SHA384HashSize]);
+
+/* SHA-512 */
+extern int SHA512Reset(SHA512Context *);
+extern int SHA512Input(SHA512Context *, const uint8_t *bytes,
+ unsigned int bytecount);
+extern int SHA512FinalBits(SHA512Context *, uint8_t bits,
+ unsigned int bit_count);
+extern int SHA512Result(SHA512Context *,
+ uint8_t Message_Digest[SHA512HashSize]);
+
+/* Unified SHA functions, chosen by whichSha */
+extern int USHAReset(USHAContext *context, SHAversion whichSha);
+extern int USHAInput(USHAContext *context,
+ const uint8_t *bytes, unsigned int bytecount);
+extern int USHAFinalBits(USHAContext *context,
+ uint8_t bits, unsigned int bit_count);
+extern int USHAResult(USHAContext *context,
+ uint8_t Message_Digest[USHAMaxHashSize]);
+extern int USHABlockSize(enum SHAversion whichSha);
+extern int USHAHashSize(enum SHAversion whichSha);
+extern int USHAHashSizeBits(enum SHAversion whichSha);
+extern const char *USHAHashName(enum SHAversion whichSha);
+
+/*
+ * HMAC Keyed-Hashing for Message Authentication, RFC 2104,
+ * for all SHAs.
+ * This interface allows a fixed-length text input to be used.
+ */
+extern int hmac(SHAversion whichSha, /* which SHA algorithm to use */
+ const unsigned char *text, /* pointer to data stream */
+ int text_len, /* length of data stream */
+ const unsigned char *key, /* pointer to authentication key */
+ int key_len, /* length of authentication key */
+ uint8_t digest[USHAMaxHashSize]); /* caller digest to fill in */
+
+/*
+ * HMAC Keyed-Hashing for Message Authentication, RFC 2104,
+ * for all SHAs.
+ * This interface allows any length of text input to be used.
+ */
+extern int hmacReset(HMACContext *context, enum SHAversion whichSha,
+ const unsigned char *key, int key_len);
+extern int hmacInput(HMACContext *context, const unsigned char *text,
+ int text_len);
+extern int hmacFinalBits(HMACContext *context, uint8_t bits,
+ unsigned int bit_count);
+extern int hmacResult(HMACContext *context,
+ uint8_t digest[USHAMaxHashSize]);
+
+/*
+ * HKDF HMAC-based Extract-and-Expand Key Derivation Function,
+ * RFC 5869, for all SHAs.
+ */
+extern int hkdf(SHAversion whichSha, const unsigned char *salt,
+ int salt_len, const unsigned char *ikm, int ikm_len,
+ const unsigned char *info, int info_len,
+ uint8_t okm[ ], int okm_len);
+extern int hkdfExtract(SHAversion whichSha, const unsigned char *salt,
+ int salt_len, const unsigned char *ikm,
+ int ikm_len, uint8_t prk[USHAMaxHashSize]);
+extern int hkdfExpand(SHAversion whichSha, const uint8_t prk[ ],
+ int prk_len, const unsigned char *info,
+ int info_len, uint8_t okm[ ], int okm_len);
+
+/*
+ * HKDF HMAC-based Extract-and-Expand Key Derivation Function,
+ * RFC 5869, for all SHAs.
+ * This interface allows any length of text input to be used.
+ */
+extern int hkdfReset(HKDFContext *context, enum SHAversion whichSha,
+ const unsigned char *salt, int salt_len);
+extern int hkdfInput(HKDFContext *context, const unsigned char *ikm,
+ int ikm_len);
+extern int hkdfFinalBits(HKDFContext *context, uint8_t ikm_bits,
+ unsigned int ikm_bit_count);
+extern int hkdfResult(HKDFContext *context,
+ uint8_t prk[USHAMaxHashSize],
+ const unsigned char *info, int info_len,
+ uint8_t okm[USHAMaxHashSize], int okm_len);
+#endif /* _SHA_H_ */
diff --git a/util/ldid-xerub/sha1.c b/util/ldid-xerub/sha1.c
new file mode 100644
index 000000000..2b74de8dd
--- /dev/null
+++ b/util/ldid-xerub/sha1.c
@@ -0,0 +1,389 @@
+/*
+ * sha1.c
+ *
+ * Description:
+ * This file implements the Secure Hashing Algorithm 1 as
+ * defined in FIPS PUB 180-1 published April 17, 1995.
+ *
+ * The SHA-1, produces a 160-bit message digest for a given
+ * data stream. It should take about 2**n steps to find a
+ * message with the same digest as a given message and
+ * 2**(n/2) to find any two messages with the same digest,
+ * when n is the digest size in bits. Therefore, this
+ * algorithm can serve as a means of providing a
+ * "fingerprint" for a message.
+ *
+ * Portability Issues:
+ * SHA-1 is defined in terms of 32-bit "words". This code
+ * uses <stdint.h> (included via "sha1.h" to define 32 and 8
+ * bit unsigned integer types. If your C compiler does not
+ * support 32 bit unsigned integers, this code is not
+ * appropriate.
+ *
+ * Caveats:
+ * SHA-1 is designed to work with messages less than 2^64 bits
+ * long. Although SHA-1 allows a message digest to be generated
+ * for messages of any number of bits less than 2^64, this
+ * implementation only works with messages with a length that is
+ * a multiple of the size of an 8-bit character.
+ *
+ */
+
+#include "sha1.h"
+
+/*
+ * Define the SHA1 circular left shift macro
+ */
+#define SHA1CircularShift(bits,word) \
+ (((word) << (bits)) | ((word) >> (32-(bits))))
+
+/* Local Function Prototyptes */
+void SHA1PadMessage(SHA1Context *);
+void SHA1ProcessMessageBlock(SHA1Context *);
+
+/*
+ * SHA1Reset
+ *
+ * Description:
+ * This function will initialize the SHA1Context in preparation
+ * for computing a new SHA1 message digest.
+ *
+ * Parameters:
+ * context: [in/out]
+ * The context to reset.
+ *
+ * Returns:
+ * sha Error Code.
+ *
+ */
+int SHA1Reset(SHA1Context *context)
+{
+ if (!context)
+ {
+ return shaNull;
+ }
+
+ context->Length_Low = 0;
+ context->Length_High = 0;
+ context->Message_Block_Index = 0;
+
+ context->Intermediate_Hash[0] = 0x67452301;
+ context->Intermediate_Hash[1] = 0xEFCDAB89;
+ context->Intermediate_Hash[2] = 0x98BADCFE;
+ context->Intermediate_Hash[3] = 0x10325476;
+ context->Intermediate_Hash[4] = 0xC3D2E1F0;
+
+ context->Computed = 0;
+ context->Corrupted = 0;
+
+ return shaSuccess;
+}
+
+/*
+ * SHA1Result
+ *
+ * Description:
+ * This function will return the 160-bit message digest into the
+ * Message_Digest array provided by the caller.
+ * NOTE: The first octet of hash is stored in the 0th element,
+ * the last octet of hash in the 19th element.
+ *
+ * Parameters:
+ * context: [in/out]
+ * The context to use to calculate the SHA-1 hash.
+ * Message_Digest: [out]
+ * Where the digest is returned.
+ *
+ * Returns:
+ * sha Error Code.
+ *
+ */
+int SHA1Result( SHA1Context *context,
+ uint8_t Message_Digest[SHA1HashSize])
+{
+ int i;
+
+ if (!context || !Message_Digest)
+ {
+ return shaNull;
+ }
+
+ if (context->Corrupted)
+ {
+ return context->Corrupted;
+ }
+
+ if (!context->Computed)
+ {
+ SHA1PadMessage(context);
+ for(i=0; i<64; ++i)
+ {
+ /* message may be sensitive, clear it out */
+ context->Message_Block[i] = 0;
+ }
+ context->Length_Low = 0; /* and clear length */
+ context->Length_High = 0;
+ context->Computed = 1;
+
+ }
+
+ for(i = 0; i < SHA1HashSize; ++i)
+ {
+ Message_Digest[i] = context->Intermediate_Hash[i>>2]
+ >> 8 * ( 3 - ( i & 0x03 ) );
+ }
+
+ return shaSuccess;
+}
+
+/*
+ * SHA1Input
+ *
+ * Description:
+ * This function accepts an array of octets as the next portion
+ * of the message.
+ *
+ * Parameters:
+ * context: [in/out]
+ * The SHA context to update
+ * message_array: [in]
+ * An array of characters representing the next portion of
+ * the message.
+ * length: [in]
+ * The length of the message in message_array
+ *
+ * Returns:
+ * sha Error Code.
+ *
+ */
+int SHA1Input( SHA1Context *context,
+ const uint8_t *message_array,
+ unsigned length)
+{
+ if (!length)
+ {
+ return shaSuccess;
+ }
+
+ if (!context || !message_array)
+ {
+ return shaNull;
+ }
+
+ if (context->Computed)
+ {
+ context->Corrupted = shaStateError;
+
+ return shaStateError;
+ }
+
+ if (context->Corrupted)
+ {
+ return context->Corrupted;
+ }
+ while(length-- && !context->Corrupted)
+ {
+ context->Message_Block[context->Message_Block_Index++] =
+ (*message_array & 0xFF);
+
+ context->Length_Low += 8;
+ if (context->Length_Low == 0)
+ {
+ context->Length_High++;
+ if (context->Length_High == 0)
+ {
+ /* Message is too long */
+ context->Corrupted = 1;
+ }
+ }
+
+ if (context->Message_Block_Index == 64)
+ {
+ SHA1ProcessMessageBlock(context);
+ }
+
+ message_array++;
+ }
+
+ return shaSuccess;
+}
+
+/*
+ * SHA1ProcessMessageBlock
+ *
+ * Description:
+ * This function will process the next 512 bits of the message
+ * stored in the Message_Block array.
+ *
+ * Parameters:
+ * None.
+ *
+ * Returns:
+ * Nothing.
+ *
+ * Comments:
+
+ * Many of the variable names in this code, especially the
+ * single character names, were used because those were the
+ * names used in the publication.
+ *
+ *
+ */
+void SHA1ProcessMessageBlock(SHA1Context *context)
+{
+ const uint32_t K[] = { /* Constants defined in SHA-1 */
+ 0x5A827999,
+ 0x6ED9EBA1,
+ 0x8F1BBCDC,
+ 0xCA62C1D6
+ };
+ int t; /* Loop counter */
+ uint32_t temp; /* Temporary word value */
+ uint32_t W[80]; /* Word sequence */
+ uint32_t A, B, C, D, E; /* Word buffers */
+
+ /*
+ * Initialize the first 16 words in the array W
+ */
+ for(t = 0; t < 16; t++)
+ {
+ W[t] = context->Message_Block[t * 4] << 24;
+ W[t] |= context->Message_Block[t * 4 + 1] << 16;
+ W[t] |= context->Message_Block[t * 4 + 2] << 8;
+ W[t] |= context->Message_Block[t * 4 + 3];
+ }
+
+ for(t = 16; t < 80; t++)
+ {
+ W[t] = SHA1CircularShift(1,W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]);
+ }
+
+ A = context->Intermediate_Hash[0];
+ B = context->Intermediate_Hash[1];
+ C = context->Intermediate_Hash[2];
+ D = context->Intermediate_Hash[3];
+ E = context->Intermediate_Hash[4];
+
+ for(t = 0; t < 20; t++)
+ {
+ temp = SHA1CircularShift(5,A) +
+ ((B & C) | ((~B) & D)) + E + W[t] + K[0];
+ E = D;
+ D = C;
+ C = SHA1CircularShift(30,B);
+
+ B = A;
+ A = temp;
+ }
+
+ for(t = 20; t < 40; t++)
+ {
+ temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[1];
+ E = D;
+ D = C;
+ C = SHA1CircularShift(30,B);
+ B = A;
+ A = temp;
+ }
+
+ for(t = 40; t < 60; t++)
+ {
+ temp = SHA1CircularShift(5,A) +
+ ((B & C) | (B & D) | (C & D)) + E + W[t] + K[2];
+ E = D;
+ D = C;
+ C = SHA1CircularShift(30,B);
+ B = A;
+ A = temp;
+ }
+
+ for(t = 60; t < 80; t++)
+ {
+ temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[3];
+ E = D;
+ D = C;
+ C = SHA1CircularShift(30,B);
+ B = A;
+ A = temp;
+ }
+
+ context->Intermediate_Hash[0] += A;
+ context->Intermediate_Hash[1] += B;
+ context->Intermediate_Hash[2] += C;
+ context->Intermediate_Hash[3] += D;
+ context->Intermediate_Hash[4] += E;
+
+ context->Message_Block_Index = 0;
+}
+
+/*
+ * SHA1PadMessage
+ *
+
+ * Description:
+ * According to the standard, the message must be padded to an even
+ * 512 bits. The first padding bit must be a '1'. The last 64
+ * bits represent the length of the original message. All bits in
+ * between should be 0. This function will pad the message
+ * according to those rules by filling the Message_Block array
+ * accordingly. It will also call the ProcessMessageBlock function
+ * provided appropriately. When it returns, it can be assumed that
+ * the message digest has been computed.
+ *
+ * Parameters:
+ * context: [in/out]
+ * The context to pad
+ * ProcessMessageBlock: [in]
+ * The appropriate SHA*ProcessMessageBlock function
+ * Returns:
+ * Nothing.
+ *
+ */
+
+void SHA1PadMessage(SHA1Context *context)
+{
+ /*
+ * Check to see if the current message block is too small to hold
+ * the initial padding bits and length. If so, we will pad the
+ * block, process it, and then continue padding into a second
+ * block.
+ */
+ if (context->Message_Block_Index > 55)
+ {
+ context->Message_Block[context->Message_Block_Index++] = 0x80;
+ while(context->Message_Block_Index < 64)
+ {
+ context->Message_Block[context->Message_Block_Index++] = 0;
+ }
+
+ SHA1ProcessMessageBlock(context);
+
+ while(context->Message_Block_Index < 56)
+ {
+ context->Message_Block[context->Message_Block_Index++] = 0;
+ }
+ }
+ else
+ {
+ context->Message_Block[context->Message_Block_Index++] = 0x80;
+ while(context->Message_Block_Index < 56)
+ {
+
+ context->Message_Block[context->Message_Block_Index++] = 0;
+ }
+ }
+
+ /*
+ * Store the message length as the last 8 octets
+ */
+ context->Message_Block[56] = context->Length_High >> 24;
+ context->Message_Block[57] = context->Length_High >> 16;
+ context->Message_Block[58] = context->Length_High >> 8;
+ context->Message_Block[59] = context->Length_High;
+ context->Message_Block[60] = context->Length_Low >> 24;
+ context->Message_Block[61] = context->Length_Low >> 16;
+ context->Message_Block[62] = context->Length_Low >> 8;
+ context->Message_Block[63] = context->Length_Low;
+
+ SHA1ProcessMessageBlock(context);
+}
diff --git a/util/ldid-xerub/sha1.h b/util/ldid-xerub/sha1.h
new file mode 100644
index 000000000..32a62a367
--- /dev/null
+++ b/util/ldid-xerub/sha1.h
@@ -0,0 +1,64 @@
+/*
+ * sha1.h
+ *
+ * Description:
+ * This is the header file for code which implements the Secure
+ * Hashing Algorithm 1 as defined in FIPS PUB 180-1 published
+ * April 17, 1995.
+ *
+ * Many of the variable names in this code, especially the
+ * single character names, were used because those were the names
+ * used in the publication.
+ *
+ * Please read the file sha1.c for more information.
+ *
+ */
+
+#ifndef _SHA1_H_
+#define _SHA1_H_
+
+#include <stdint.h>
+
+#ifndef _SHA_enum_
+#define _SHA_enum_
+enum
+{
+ shaSuccess = 0,
+ shaNull, /* Null pointer parameter */
+ shaInputTooLong, /* input data too long */
+ shaStateError /* called Input after Result */
+};
+#endif
+#define SHA1HashSize 20
+
+/*
+ * This structure will hold context information for the SHA-1
+ * hashing operation
+ */
+typedef struct SHA1Context
+{
+ uint32_t Intermediate_Hash[SHA1HashSize/4]; /* Message Digest */
+
+ uint32_t Length_Low; /* Message length in bits */
+ uint32_t Length_High; /* Message length in bits */
+
+ /* Index into message block array */
+ int_least16_t Message_Block_Index;
+ uint8_t Message_Block[64]; /* 512-bit message blocks */
+
+ int Computed; /* Is the digest computed? */
+ int Corrupted; /* Is the message digest corrupted? */
+} SHA1Context;
+
+/*
+ * Function Prototypes
+ */
+
+int SHA1Reset( SHA1Context *);
+int SHA1Input( SHA1Context *,
+ const uint8_t *,
+ unsigned int);
+int SHA1Result( SHA1Context *,
+ uint8_t Message_Digest[SHA1HashSize]);
+
+#endif
diff --git a/util/ldid-xerub/sha224-256.c b/util/ldid-xerub/sha224-256.c
new file mode 100644
index 000000000..b77fa2f94
--- /dev/null
+++ b/util/ldid-xerub/sha224-256.c
@@ -0,0 +1,581 @@
+/************************* sha224-256.c ************************/
+/***************** See RFC 6234 for details. *******************/
+/* Copyright (c) 2011 IETF Trust and the persons identified as */
+/* authors of the code. All rights reserved. */
+/* See sha.h for terms of use and redistribution. */
+
+/*
+ * Description:
+ * This file implements the Secure Hash Algorithms SHA-224 and
+ * SHA-256 as defined in the U.S. National Institute of Standards
+ * and Technology Federal Information Processing Standards
+ * Publication (FIPS PUB) 180-3 published in October 2008
+ * and formerly defined in its predecessors, FIPS PUB 180-1
+ * and FIP PUB 180-2.
+ *
+ * A combined document showing all algorithms is available at
+ * http://csrc.nist.gov/publications/fips/
+ * fips180-3/fips180-3_final.pdf
+ *
+ * The SHA-224 and SHA-256 algorithms produce 224-bit and 256-bit
+ * message digests for a given data stream. It should take about
+ * 2**n steps to find a message with the same digest as a given
+ * message and 2**(n/2) to find any two messages with the same
+ * digest, when n is the digest size in bits. Therefore, this
+ * algorithm can serve as a means of providing a
+ * "fingerprint" for a message.
+ *
+ * Portability Issues:
+ * SHA-224 and SHA-256 are defined in terms of 32-bit "words".
+ * This code uses <stdint.h> (included via "sha.h") to define 32-
+ * and 8-bit unsigned integer types. If your C compiler does not
+ * support 32-bit unsigned integers, this code is not
+ * appropriate.
+ *
+ * Caveats:
+ * SHA-224 and SHA-256 are designed to work with messages less
+ * than 2^64 bits long. This implementation uses SHA224/256Input()
+ * to hash the bits that are a multiple of the size of an 8-bit
+ * octet, and then optionally uses SHA224/256FinalBits()
+ * to hash the final few bits of the input.
+ */
+
+#include "sha.h"
+#include "sha-private.h"
+
+/* Define the SHA shift, rotate left, and rotate right macros */
+#define SHA256_SHR(bits,word) ((word) >> (bits))
+#define SHA256_ROTL(bits,word) \
+ (((word) << (bits)) | ((word) >> (32-(bits))))
+#define SHA256_ROTR(bits,word) \
+ (((word) >> (bits)) | ((word) << (32-(bits))))
+
+/* Define the SHA SIGMA and sigma macros */
+#define SHA256_SIGMA0(word) \
+ (SHA256_ROTR( 2,word) ^ SHA256_ROTR(13,word) ^ SHA256_ROTR(22,word))
+#define SHA256_SIGMA1(word) \
+ (SHA256_ROTR( 6,word) ^ SHA256_ROTR(11,word) ^ SHA256_ROTR(25,word))
+#define SHA256_sigma0(word) \
+ (SHA256_ROTR( 7,word) ^ SHA256_ROTR(18,word) ^ SHA256_SHR( 3,word))
+#define SHA256_sigma1(word) \
+ (SHA256_ROTR(17,word) ^ SHA256_ROTR(19,word) ^ SHA256_SHR(10,word))
+
+/*
+ * Add "length" to the length.
+ * Set Corrupted when overflow has occurred.
+ */
+static uint32_t addTemp;
+#define SHA224_256AddLength(context, length) \
+ (addTemp = (context)->Length_Low, (context)->Corrupted = \
+ (((context)->Length_Low += (length)) < addTemp) && \
+ (++(context)->Length_High == 0) ? shaInputTooLong : \
+ (context)->Corrupted )
+
+/* Local Function Prototypes */
+static int SHA224_256Reset(SHA256Context *context, uint32_t *H0);
+static void SHA224_256ProcessMessageBlock(SHA256Context *context);
+static void SHA224_256Finalize(SHA256Context *context,
+ uint8_t Pad_Byte);
+static void SHA224_256PadMessage(SHA256Context *context,
+ uint8_t Pad_Byte);
+static int SHA224_256ResultN(SHA256Context *context,
+ uint8_t Message_Digest[ ], int HashSize);
+
+/* Initial Hash Values: FIPS 180-3 section 5.3.2 */
+static uint32_t SHA224_H0[SHA256HashSize/4] = {
+ 0xC1059ED8, 0x367CD507, 0x3070DD17, 0xF70E5939,
+ 0xFFC00B31, 0x68581511, 0x64F98FA7, 0xBEFA4FA4
+};
+
+/* Initial Hash Values: FIPS 180-3 section 5.3.3 */
+static uint32_t SHA256_H0[SHA256HashSize/4] = {
+ 0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A,
+ 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19
+};
+
+/*
+ * SHA224Reset
+ *
+ * Description:
+ * This function will initialize the SHA224Context in preparation
+ * for computing a new SHA224 message digest.
+ *
+ * Parameters:
+ * context: [in/out]
+ * The context to reset.
+ *
+ * Returns:
+ * sha Error Code.
+ */
+int SHA224Reset(SHA224Context *context)
+{
+ return SHA224_256Reset(context, SHA224_H0);
+}
+
+/*
+ * SHA224Input
+ *
+ * Description:
+ * This function accepts an array of octets as the next portion
+ * of the message.
+ *
+ * Parameters:
+ * context: [in/out]
+ * The SHA context to update.
+ * message_array[ ]: [in]
+ * An array of octets representing the next portion of
+ * the message.
+ * length: [in]
+ * The length of the message in message_array.
+ *
+ * Returns:
+ * sha Error Code.
+ *
+ */
+int SHA224Input(SHA224Context *context, const uint8_t *message_array,
+ unsigned int length)
+{
+ return SHA256Input(context, message_array, length);
+}
+
+/*
+ * SHA224FinalBits
+ *
+ * Description:
+ * This function will add in any final bits of the message.
+ *
+ * Parameters:
+ * context: [in/out]
+ * The SHA context to update.
+ * message_bits: [in]
+ * The final bits of the message, in the upper portion of the
+ * byte. (Use 0b###00000 instead of 0b00000### to input the
+ * three bits ###.)
+ * length: [in]
+ * The number of bits in message_bits, between 1 and 7.
+ *
+ * Returns:
+ * sha Error Code.
+ */
+int SHA224FinalBits(SHA224Context *context,
+ uint8_t message_bits, unsigned int length)
+{
+ return SHA256FinalBits(context, message_bits, length);
+}
+
+/*
+ * SHA224Result
+ *
+ * Description:
+ * This function will return the 224-bit message digest
+ * into the Message_Digest array provided by the caller.
+ * NOTE:
+ * The first octet of hash is stored in the element with index 0,
+ * the last octet of hash in the element with index 27.
+ *
+ * Parameters:
+ * context: [in/out]
+ * The context to use to calculate the SHA hash.
+ * Message_Digest[ ]: [out]
+ * Where the digest is returned.
+ *
+ * Returns:
+ * sha Error Code.
+ */
+int SHA224Result(SHA224Context *context,
+ uint8_t Message_Digest[SHA224HashSize])
+{
+ return SHA224_256ResultN(context, Message_Digest, SHA224HashSize);
+}
+
+/*
+ * SHA256Reset
+ *
+ * Description:
+ * This function will initialize the SHA256Context in preparation
+ * for computing a new SHA256 message digest.
+ *
+ * Parameters:
+ * context: [in/out]
+ * The context to reset.
+ *
+ * Returns:
+ * sha Error Code.
+ */
+int SHA256Reset(SHA256Context *context)
+{
+ return SHA224_256Reset(context, SHA256_H0);
+}
+
+/*
+ * SHA256Input
+ *
+ * Description:
+ * This function accepts an array of octets as the next portion
+ * of the message.
+ *
+ * Parameters:
+ * context: [in/out]
+ * The SHA context to update.
+ * message_array[ ]: [in]
+ * An array of octets representing the next portion of
+ * the message.
+ * length: [in]
+ * The length of the message in message_array.
+ *
+ * Returns:
+ * sha Error Code.
+ */
+int SHA256Input(SHA256Context *context, const uint8_t *message_array,
+ unsigned int length)
+{
+ if (!context) return shaNull;
+ if (!length) return shaSuccess;
+ if (!message_array) return shaNull;
+ if (context->Computed) return context->Corrupted = shaStateError;
+ if (context->Corrupted) return context->Corrupted;
+
+ while (length--) {
+ context->Message_Block[context->Message_Block_Index++] =
+ *message_array;
+
+ if ((SHA224_256AddLength(context, 8) == shaSuccess) &&
+ (context->Message_Block_Index == SHA256_Message_Block_Size))
+ SHA224_256ProcessMessageBlock(context);
+
+ message_array++;
+ }
+
+ return context->Corrupted;
+
+}
+
+/*
+ * SHA256FinalBits
+ *
+ * Description:
+ * This function will add in any final bits of the message.
+ *
+ * Parameters:
+ * context: [in/out]
+ * The SHA context to update.
+ * message_bits: [in]
+ * The final bits of the message, in the upper portion of the
+ * byte. (Use 0b###00000 instead of 0b00000### to input the
+ * three bits ###.)
+ * length: [in]
+ * The number of bits in message_bits, between 1 and 7.
+ *
+ * Returns:
+ * sha Error Code.
+ */
+int SHA256FinalBits(SHA256Context *context,
+ uint8_t message_bits, unsigned int length)
+{
+ static uint8_t masks[8] = {
+ /* 0 0b00000000 */ 0x00, /* 1 0b10000000 */ 0x80,
+ /* 2 0b11000000 */ 0xC0, /* 3 0b11100000 */ 0xE0,
+ /* 4 0b11110000 */ 0xF0, /* 5 0b11111000 */ 0xF8,
+ /* 6 0b11111100 */ 0xFC, /* 7 0b11111110 */ 0xFE
+ };
+ static uint8_t markbit[8] = {
+ /* 0 0b10000000 */ 0x80, /* 1 0b01000000 */ 0x40,
+ /* 2 0b00100000 */ 0x20, /* 3 0b00010000 */ 0x10,
+ /* 4 0b00001000 */ 0x08, /* 5 0b00000100 */ 0x04,
+ /* 6 0b00000010 */ 0x02, /* 7 0b00000001 */ 0x01
+ };
+
+ if (!context) return shaNull;
+ if (!length) return shaSuccess;
+ if (context->Corrupted) return context->Corrupted;
+ if (context->Computed) return context->Corrupted = shaStateError;
+ if (length >= 8) return context->Corrupted = shaBadParam;
+
+ SHA224_256AddLength(context, length);
+ SHA224_256Finalize(context, (uint8_t)
+ ((message_bits & masks[length]) | markbit[length]));
+
+ return context->Corrupted;
+}
+
+/*
+ * SHA256Result
+ *
+ * Description:
+ * This function will return the 256-bit message digest
+ * into the Message_Digest array provided by the caller.
+ * NOTE:
+ * The first octet of hash is stored in the element with index 0,
+ * the last octet of hash in the element with index 31.
+ *
+ * Parameters:
+ * context: [in/out]
+ * The context to use to calculate the SHA hash.
+ * Message_Digest[ ]: [out]
+ * Where the digest is returned.
+ *
+ * Returns:
+ * sha Error Code.
+ */
+int SHA256Result(SHA256Context *context,
+ uint8_t Message_Digest[SHA256HashSize])
+{
+ return SHA224_256ResultN(context, Message_Digest, SHA256HashSize);
+}
+
+/*
+ * SHA224_256Reset
+ *
+ * Description:
+ * This helper function will initialize the SHA256Context in
+ * preparation for computing a new SHA-224 or SHA-256 message digest.
+ *
+ * Parameters:
+ * context: [in/out]
+ * The context to reset.
+ * H0[ ]: [in]
+ * The initial hash value array to use.
+ *
+ * Returns:
+ * sha Error Code.
+ */
+static int SHA224_256Reset(SHA256Context *context, uint32_t *H0)
+{
+ if (!context) return shaNull;
+
+ context->Length_High = context->Length_Low = 0;
+ context->Message_Block_Index = 0;
+
+ context->Intermediate_Hash[0] = H0[0];
+ context->Intermediate_Hash[1] = H0[1];
+ context->Intermediate_Hash[2] = H0[2];
+ context->Intermediate_Hash[3] = H0[3];
+ context->Intermediate_Hash[4] = H0[4];
+ context->Intermediate_Hash[5] = H0[5];
+ context->Intermediate_Hash[6] = H0[6];
+ context->Intermediate_Hash[7] = H0[7];
+
+ context->Computed = 0;
+ context->Corrupted = shaSuccess;
+
+ return shaSuccess;
+}
+
+/*
+ * SHA224_256ProcessMessageBlock
+ *
+ * Description:
+ * This helper function will process the next 512 bits of the
+ * message stored in the Message_Block array.
+ *
+ * Parameters:
+ * context: [in/out]
+ * The SHA context to update.
+ *
+ * Returns:
+ * Nothing.
+ *
+ * Comments:
+ * Many of the variable names in this code, especially the
+ * single character names, were used because those were the
+ * names used in the Secure Hash Standard.
+ */
+static void SHA224_256ProcessMessageBlock(SHA256Context *context)
+{
+ /* Constants defined in FIPS 180-3, section 4.2.2 */
+ static const uint32_t K[64] = {
+ 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b,
+ 0x59f111f1, 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01,
+ 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7,
+ 0xc19bf174, 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
+ 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 0x983e5152,
+ 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147,
+ 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc,
+ 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
+ 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819,
+ 0xd6990624, 0xf40e3585, 0x106aa070, 0x19a4c116, 0x1e376c08,
+ 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f,
+ 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
+ 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
+ };
+ int t, t4; /* Loop counter */
+ uint32_t temp1, temp2; /* Temporary word value */
+ uint32_t W[64]; /* Word sequence */
+ uint32_t A, B, C, D, E, F, G, H; /* Word buffers */
+
+ /*
+ * Initialize the first 16 words in the array W
+ */
+ for (t = t4 = 0; t < 16; t++, t4 += 4)
+ W[t] = (((uint32_t)context->Message_Block[t4]) << 24) |
+ (((uint32_t)context->Message_Block[t4 + 1]) << 16) |
+ (((uint32_t)context->Message_Block[t4 + 2]) << 8) |
+ (((uint32_t)context->Message_Block[t4 + 3]));
+
+ for (t = 16; t < 64; t++)
+ W[t] = SHA256_sigma1(W[t-2]) + W[t-7] +
+ SHA256_sigma0(W[t-15]) + W[t-16];
+
+ A = context->Intermediate_Hash[0];
+ B = context->Intermediate_Hash[1];
+ C = context->Intermediate_Hash[2];
+ D = context->Intermediate_Hash[3];
+ E = context->Intermediate_Hash[4];
+ F = context->Intermediate_Hash[5];
+ G = context->Intermediate_Hash[6];
+ H = context->Intermediate_Hash[7];
+
+ for (t = 0; t < 64; t++) {
+ temp1 = H + SHA256_SIGMA1(E) + SHA_Ch(E,F,G) + K[t] + W[t];
+ temp2 = SHA256_SIGMA0(A) + SHA_Maj(A,B,C);
+ H = G;
+ G = F;
+ F = E;
+ E = D + temp1;
+ D = C;
+ C = B;
+ B = A;
+ A = temp1 + temp2;
+ }
+
+ context->Intermediate_Hash[0] += A;
+ context->Intermediate_Hash[1] += B;
+ context->Intermediate_Hash[2] += C;
+ context->Intermediate_Hash[3] += D;
+ context->Intermediate_Hash[4] += E;
+ context->Intermediate_Hash[5] += F;
+ context->Intermediate_Hash[6] += G;
+ context->Intermediate_Hash[7] += H;
+
+ context->Message_Block_Index = 0;
+}
+
+/*
+ * SHA224_256Finalize
+ *
+ * Description:
+ * This helper function finishes off the digest calculations.
+ *
+ * Parameters:
+ * context: [in/out]
+ * The SHA context to update.
+ * Pad_Byte: [in]
+ * The last byte to add to the message block before the 0-padding
+ * and length. This will contain the last bits of the message
+ * followed by another single bit. If the message was an
+ * exact multiple of 8-bits long, Pad_Byte will be 0x80.
+ *
+ * Returns:
+ * sha Error Code.
+ */
+static void SHA224_256Finalize(SHA256Context *context,
+ uint8_t Pad_Byte)
+{
+ int i;
+ SHA224_256PadMessage(context, Pad_Byte);
+ /* message may be sensitive, so clear it out */
+ for (i = 0; i < SHA256_Message_Block_Size; ++i)
+ context->Message_Block[i] = 0;
+ context->Length_High = 0; /* and clear length */
+ context->Length_Low = 0;
+ context->Computed = 1;
+}
+
+/*
+ * SHA224_256PadMessage
+ *
+ * Description:
+ * According to the standard, the message must be padded to the next
+ * even multiple of 512 bits. The first padding bit must be a '1'.
+ * The last 64 bits represent the length of the original message.
+ * All bits in between should be 0. This helper function will pad
+ * the message according to those rules by filling the
+ * Message_Block array accordingly. When it returns, it can be
+ * assumed that the message digest has been computed.
+ *
+ * Parameters:
+ * context: [in/out]
+ * The context to pad.
+ * Pad_Byte: [in]
+ * The last byte to add to the message block before the 0-padding
+ * and length. This will contain the last bits of the message
+ * followed by another single bit. If the message was an
+ * exact multiple of 8-bits long, Pad_Byte will be 0x80.
+ *
+ * Returns:
+ * Nothing.
+ */
+static void SHA224_256PadMessage(SHA256Context *context,
+ uint8_t Pad_Byte)
+{
+ /*
+ * Check to see if the current message block is too small to hold
+ * the initial padding bits and length. If so, we will pad the
+ * block, process it, and then continue padding into a second
+ * block.
+ */
+ if (context->Message_Block_Index >= (SHA256_Message_Block_Size-8)) {
+ context->Message_Block[context->Message_Block_Index++] = Pad_Byte;
+ while (context->Message_Block_Index < SHA256_Message_Block_Size)
+ context->Message_Block[context->Message_Block_Index++] = 0;
+ SHA224_256ProcessMessageBlock(context);
+ } else
+ context->Message_Block[context->Message_Block_Index++] = Pad_Byte;
+
+ while (context->Message_Block_Index < (SHA256_Message_Block_Size-8))
+ context->Message_Block[context->Message_Block_Index++] = 0;
+
+ /*
+ * Store the message length as the last 8 octets
+ */
+ context->Message_Block[56] = (uint8_t)(context->Length_High >> 24);
+ context->Message_Block[57] = (uint8_t)(context->Length_High >> 16);
+ context->Message_Block[58] = (uint8_t)(context->Length_High >> 8);
+ context->Message_Block[59] = (uint8_t)(context->Length_High);
+ context->Message_Block[60] = (uint8_t)(context->Length_Low >> 24);
+ context->Message_Block[61] = (uint8_t)(context->Length_Low >> 16);
+ context->Message_Block[62] = (uint8_t)(context->Length_Low >> 8);
+ context->Message_Block[63] = (uint8_t)(context->Length_Low);
+
+ SHA224_256ProcessMessageBlock(context);
+}
+
+/*
+ * SHA224_256ResultN
+ *
+ * Description:
+ * This helper function will return the 224-bit or 256-bit message
+ * digest into the Message_Digest array provided by the caller.
+ * NOTE:
+ * The first octet of hash is stored in the element with index 0,
+ * the last octet of hash in the element with index 27/31.
+ *
+ * Parameters:
+ * context: [in/out]
+ * The context to use to calculate the SHA hash.
+ * Message_Digest[ ]: [out]
+ * Where the digest is returned.
+ * HashSize: [in]
+ * The size of the hash, either 28 or 32.
+ *
+ * Returns:
+ * sha Error Code.
+ */
+static int SHA224_256ResultN(SHA256Context *context,
+ uint8_t Message_Digest[ ], int HashSize)
+{
+ int i;
+
+ if (!context) return shaNull;
+ if (!Message_Digest) return shaNull;
+ if (context->Corrupted) return context->Corrupted;
+
+ if (!context->Computed)
+ SHA224_256Finalize(context, 0x80);
+
+ for (i = 0; i < HashSize; ++i)
+ Message_Digest[i] = (uint8_t)
+ (context->Intermediate_Hash[i>>2] >> 8 * ( 3 - ( i & 0x03 ) ));
+
+ return shaSuccess;
+}
diff --git a/util/ldid-xerub/version.sh b/util/ldid-xerub/version.sh
new file mode 100755
index 000000000..6e484edbb
--- /dev/null
+++ b/util/ldid-xerub/version.sh
@@ -0,0 +1,2 @@
+#!/bin/bash
+echo "$(git describe --tags --dirty="+" --match="v*" | sed -e 's@-\([^-]*\)-\([^-]*\)$@+\1.\2@;s@^v@1:@')"