pax_global_header00006660000000000000000000000064145370526500014521gustar00rootroot0000000000000052 comment=52a88f7f7751285158e452286a111ed30dd217d5 cryptokit-release119/000077500000000000000000000000001453705265000147665ustar00rootroot00000000000000cryptokit-release119/.gitignore000066400000000000000000000001731453705265000167570ustar00rootroot00000000000000_build setup.data setup.log *.native *~ .merlin # This file is generated by the configure script src/config/config_vars.ml cryptokit-release119/Changes000066400000000000000000000120571453705265000162660ustar00rootroot00000000000000Release 1.19: - Fix missing root registration in some Chacha20, Blake2, and Blake3 functions (#34) Release 1.18: - Add BLAKE3 hash and MAC functions. - Fix compile-time error "SSE4.1 instruction set not enabled" (#32, #33). Release 1.17: - Add interfaces for authenticated encryption (AEAD) and two implementations: AES-GCM and Chacha20-Poly1305. - Use `getentropy()` for `system_rng` when available (Linux, macOS, BSD). - Removed support for EGD (the Entropy Gathering Daemon). - Added compile-time alerts on uses of broken or weak ciphers and hashes. (Can be silenced with "-alert -crypto".) - Add the hmac_sha384 MAC (#8). - Add the SipHash MAC. - Set file descriptor to close-on-exec in `device_rng` (#27). - Improve compatibility with OCaml 5.0 (#28). - Make sure CryptokitBignum is installed like before the switch to Dune (#31). Release 1.16.1: - Make the tests faster and more robust - Update dependencies and documentation. Release 1.16: - Use dune as the build system (contributed by Andrey Mokhov, PR #24) - Add BLAKE2b and BLAKE2s hash and MAC functions. Release 1.15: - Added constant-time `string_equal` and `bytes_equal` comparison functions (execution time depends on the lengths of the strings but not on their contents) (issue #13, PR #14) - Caml FFI: use caml_ long names and CAML_NAME_SPACE; get rid of Begin_roots - OASIS files regenerated in dynamic mode for OCaml 4.09 compatibility. For this reason, OASIS is now a build dependency. Release 1.14: - Ensure compatibility with OCaml 4.09 and up. - Detect early AMD Ryzen 3000 bug where the RDRAND instruction always generates 0xFF...FF, and, in this case, report the hardware RNG as unavailable. - Fix formatting of documentation comments (issue #3, PR #5) - Optional argument to control whether the zlib transform expects a zlib header (PR #12). - Fix issue with zlib >= 1.2.9 where internal sanity check is affected by the stream data block being moved by OCaml's GC (issue #7, PR #17). - DH.new_parameters: update documentation to suggest at least 2048 bits (PR #18). - DH.derive_key: use SHA256 instead of SHA1 (PR #19). Release 1.13: - Add the Chacha20 stream cipher. - Add the AES-CMAC (a.k.a. AES-OMAC1) message authentication code. - Pseudo-random number generator: replace the old AES-CBC-Fibonacci generator with a faster, simpler generator based on Chacha20. - Add an alternate pseudo-random number generator based on AES in CTR mode. - Documentation: warn about known cryptographic weaknesses in Triple DES, Blowfish, and ARCfour. - Documentation: warn about problems with variable-length messages in MACs based on block ciphers in CBC mode. Release 1.12: - Fix x86-32 compilation error and improve detection of AES-NI for x86 processors (Jeremie Dimino, Etienne Millon) (Closes: #1646) - AES-NI: align key_schedule on a 16 byte boundary (Etienne Millon) (Closes: #1709) - Add original Keccak submission to SHA-3 (Yoichi Hirai) Release 1.11: - Adapt to "safe string" mode (OCaml 4.02 and later required). The API should remain backward-compatible for clients compiled in "unsafe string" mode. - Update SHA-3 to the official NIST standard (different padding than in the Keccak submission). (Closes: #1528) - Fixed bounds checking in "add_substring" methods of hash functions and other functions that operate on a substring of a string. (Closes: #1480) - Use hardware implementation of AES when available on x86 processors. (Faster than the software implementation and less sensitive to side channel attacks.) - Use the Zarith library to implement RSA. (Faster than the previous implementation and less sensitive to side channel attacks.) - Support the hardware random number generator present in recent x86 processors. - Rebuilt generated files with Oasis 0.4.6 for OCaml 4.03 compatibility. Release 1.10: - Add all SHA-2 hash functions: SHA-224, SHA-384 and SHA-512 in addition to the existing SHA-256. (Closes: #1223) - Add support for CTR (Counter) chaining mode. - Fix compilation error with OCaml 4.03+dev. - Avoid using some obsolete OCaml stdlib functions. Release 1.9: - More fixes to build in Windows with zlib (mingw and msvc). Release 1.8: - Build .cmxs with C bindings (Closes: #1303) - Use advapi32 on Windows (Close: #1055) - Allow to define --zlib-include and --zlib-libdir if zlib is not installed in the standard location. Release 1.7: - Added SHA-3 hash function. Release 1.6: - Regenerate setup.ml with oasis 0.3.0~rc6 version Release 1.5: - Fix bug check in buffered_output#ensure_capacity (Closes: #879) - Allow to have padding in Base64 (Closes: #897) Release 1.4: - Added Blowfish block cipher. - Added MAC functions based on HMAC construction applied to SHA-256 and RIPEMD-160. - Added OASIS and findlib support (Closes: #589) Release 1.3: - Added hash functions SHA-256 and RIPEMD-160. - Added "flush" method to transforms. - Fixed infinite loop in decompression of incorrect data. Release 1.2: - MS Windows port Release 1.1: - Added Diffie-Hellman key agreement - Exported raw modular arithmetic operations (mod_power, mod_mult) Release 1.0: - First public release cryptokit-release119/LICENSE000066400000000000000000000634321453705265000160030ustar00rootroot00000000000000This Library is distributed under the terms of the GNU Library General Public License version 2 (included below). As a special exception to the GNU Library General Public License, you may link, statically or dynamically, a "work that uses the Library" with a publicly distributed version of the Library to produce an executable file containing portions of the Library, and distribute that executable file under terms of your choice, without any of the additional requirements listed in clause 6 of the GNU Library General Public License. By "a publicly distributed version of the Library", we mean either the unmodified Library as distributed by INRIA, or a modified version of the Library that is distributed under the conditions defined in clause 3 of the GNU Library General Public License. This exception does not however invalidate any other reasons why the executable file might be covered by the GNU Library General Public License. ---------------------------------------------------------------------- GNU LIBRARY GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1991 Free Software Foundation, Inc. 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the library GPL. It is numbered 2 because it goes with version 2 of the ordinary GPL.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Library General Public License, applies to some specially designated Free Software Foundation software, and to any other libraries whose authors decide to use it. You can use it for your libraries, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library, or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link a program with the library, you must provide complete object files to the recipients so that they can relink them with the library, after making changes to the library and recompiling it. And you must show them these terms so they know their rights. Our method of protecting your rights has two steps: (1) copyright the library, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the library. Also, for each distributor's protection, we want to make certain that everyone understands that there is no warranty for this free library. If the library is modified by someone else and passed on, we want its recipients to know that what they have is not the original version, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that companies distributing free software will individually obtain patent licenses, thus in effect transforming the program into proprietary software. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License, which was designed for utility programs. This license, the GNU Library General Public License, applies to certain designated libraries. This license is quite different from the ordinary one; be sure to read it in full, and don't assume that anything in it is the same as in the ordinary license. The reason we have a separate public license for some libraries is that they blur the distinction we usually make between modifying or adding to a program and simply using it. Linking a program with a library, without changing the library, is in some sense simply using the library, and is analogous to running a utility program or application program. However, in a textual and legal sense, the linked executable is a combined work, a derivative of the original library, and the ordinary General Public License treats it as such. Because of this blurred distinction, using the ordinary General Public License for libraries did not effectively promote software sharing, because most developers did not use the libraries. We concluded that weaker conditions might promote sharing better. However, unrestricted linking of non-free programs would deprive the users of those programs of all benefit from the free status of the libraries themselves. This Library General Public License is intended to permit developers of non-free programs to use free libraries, while preserving your freedom as a user of such programs to change the free libraries that are incorporated in them. (We have not seen how to achieve this as regards changes in header files, but we have achieved it as regards changes in the actual functions of the Library.) The hope is that this will lead to faster development of free libraries. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, while the latter only works together with the library. Note that it is possible for a library to be covered by the ordinary General Public License rather than by this special one. GNU LIBRARY GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Library General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also compile or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. c) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. d) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Library General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS Appendix: How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! cryptokit-release119/README.md000066400000000000000000000205211453705265000162450ustar00rootroot00000000000000# The Cryptokit library ## Overview The Cryptokit library for OCaml provides a variety of cryptographic primitives that can be used to implement cryptographic protocols in security-sensitive applications. The primitives provided include: * Symmetric-key ciphers: AES, Chacha20, DES, Triple-DES, Blowfish, ARCfour, in ECB, CBC, CFB, OFB and counter modes. * Authenticated encryption: AES-GCM, Chacha20-Poly1305. * Public-key cryptography: RSA encryption and signature, Diffie-Hellman key agreement. * Hash functions and MACs: SHA-3, SHA-2, BLAKE2, BLAKE3, RIPEMD-160; MACs based on AES and DES; SipHash. (SHA-1 and MD5, despite being broken, are also provided for historical value.) * Random number generation. * Encodings and compression: base 64, hexadecimal, Zlib compression. Additional ciphers and hashes can easily be used in conjunction with the library. In particular, basic mechanisms such as chaining modes, output buffering, and padding are provided by generic classes that can easily be composed with user-provided ciphers. More generally, the library promotes a "Lego"-like style of constructing and composing transformations over character streams. This library is distributed under the conditions of the GNU Library General Public license version 2 or any later version, with the special OCaml exception on linking described in file LICENSE. ## Requirements * OCaml 4.08 or more recent. * The Dune build system, version 2.0 or more recent. * The Zarith library, version 1.4 or more recent. * The Zlib C library, version 1.1.3 or up is recommended. If it is not installed on your system (look for libz.a or libz.so), get it from http://www.gzip.org/, or indicate in the Makefile that you do not have it. If you are running Linux or BSD or MacOS, your distribution provides precompiled binaries for this library. ## Build, test and install * To configure, run `./configure`. There are options to disable or enable some features (run `./configure --help` for a list), but the default configuration is fine most of the time. * To build, run `dune build`. * To execute a test, run `dune exec test/.exe` where `` can be `test`, `prngtest` or `speedtest`, supplying additional command line arguments if needed. The main test file `test/test.ml` is also included into the `runtest` alias, so it can be executed simply by `dune test`. * To install, run `dune install`. ## Using the library The package name is `cryptokit`. With Dune, use `(library cryptokit)`. With ocamlfind, do ``` ocamlfind ocamlopt -package cryptokit ... # for compilation ocamlfind ocamlopt -package cryptokit -linkpkg ... # for linking ``` ## Documentation See the extensive documentation comments in file `src/cryptokit.mli`. To build HTML documentation, run `dune build @doc`. The resulting index file is located at `_build/default/_doc/_html/cryptokit/Cryptokit/index.html`. ## Warnings and disclaimers Disclaimer 1: the author is not an expert in cryptography. While reasonable care has been taken to select good, widely-used implementations of the ciphers and hashes, and follow recommended practices found in reputable applied cryptography textbooks, you are advised to review thoroughly the implementation of this module before using it in a security-critical application. Disclaimer 2: some knowledge of cryptography is needed to use effectively this library. A good introduction is the book __Serious Cryptography__ by J.-P. Aumasson (2018). Building secure applications out of cryptographic primitives also requires a general background in computer security. Disclaimer 3: in some countries, the use, distribution, import and/or export of cryptographic applications is restricted by law. The precise restrictions may depend on the strenght of the cryptography used (e.g. key size), but also on its purpose (e.g. confidentiality vs. authentication). It is up to the users of this library to comply with regulations applicable in their country. ## Design notes and references The library is organized around the concept of "transforms". A transform is an object that accepts strings, sub-strings, characters and bytes as input, transforms them, and buffers the output. While it is possible to enter all input, then fetch the output, lower memory requirements can be achieved by purging the output periodically during data input. The AES implementation is the public-domain optimized reference implementation by Daemen, Rijmen and Barreto. On x86 processors that support the AES-NI extensions, hardware implementation is used instead. The Chacha20 implementation is due to D.J.Bernstein, https://cr.yp.to/streamciphers/timings/estreambench/submissions/salsa20/chacha8/regs/chacha.c . It is in the public domain. The DES implementation is based on Outerbridge's popular "d3des" implementation. This is not the fastest DES implementation available, but one of the cleanest. Outerbridge's code is marked as public domain. The Blowfish implementation is that of Paul Kocher with some performance improvements. It is under the LGPL. It passes the test vectors listed at http://www.schneier.com/code/vectors.txt ARCfour (``alleged RC4'') is implemented from scratch, based on the algorithm described in Schneier's _Applied Cryptography_ For AES-GCM, the GHASH implementation is that of Steven M. Gibson at https://github.com/mko-x/SharedAES-GCM/blob/master/Sources/gcm.c . On x86 processors that support the PCLMUL extension, hardware implementation is used instead. Test vectors are taken from "The Galois/Counter Mode of Operation (GCM)" by David A. McGrew and John Viega. For Chacha20-Poly1305, Poly1305 is based on the "Donna" implementation by Andrew Moon, https://github.com/floodyberry/poly1305-donna . Test vectors are taken from RFC 7539 and from the BoringSSL project. SHA-1 is also implemented from scratch, based on the algorithm described in the _Handbook of Applied Cryptography_. It passes the FIPS test vectors. SHA-2 is implemented from scratch based on FIPS publication 180-2. It passes the FIPS test vectors. SHA-3 is based on the "readable" implementation of Keccak written by Markku-Juhani O. Saarinen . BLAKE2b and BLAKE2s are implemented from scratch based on RFC 7693. The test vectors are taken from https://github.com/BLAKE2/BLAKE2/tree/master/testvectors; others were obtained with the b2sum program. BLAKE3 uses the portable C implementation from https://github.com/BLAKE3-team/BLAKE3 . The authors released the code into the public domain with CC0 1.0. The test vectors come from the same source. RIPEMD-160 is based on the reference implementation by A.Bosselaers. It passes the test vectors listed at http://www.esat.kuleuven.ac.be/~bosselae/ripemd160.html MD5 uses the public-domain implementation by Colin Plumb that is also used in the OCaml runtime system for module Digest. SipHash is based on the reference implementation by J.-P. Aumasson and D. J. Bernstein, https://github.com/veorq/SipHash . It passes their test vectors. RSA encryption and decryption was implemented from scratch, using the Zarith OCaml library for arbitrary-precision arithmetic, which itself uses GMP. Modular exponentiation is the constant-time implementation provided by GMP. The Chinese remainder theorem is exploited when possible, though. Like all ciphers in this library, the RSA implementation is *not* protected against timing attacks. RSA key generation uses GMP's `nextprime` function for probabilistic primality testing. The hardware RNG uses the RDRAND instruction of recent x86 processors, if supported. It is not available on other platforms. A check is included to reject the broken RDRAND on AMD Ryzen 3000 processors (https://arstechnica.com/gadgets/2019/10/how-a-months-old-amd-microcode-bug-destroyed-my-weekend/). The system RNG uses the `getentropy` function provided by Linux, macOS and the BSDs, or the `CryptGenRandom` function from the Windows cryptographic API. The seeded PRNG is just the Chacha20 stream cipher encrypting the all-zeroes message. The seed is used as the Chacha20 key. An alternate seeded PRNG is provided, based on AES encryption of a 128-bit counter. Both PRNGs pass the Dieharder statistical tests. Still, better use the system RNG or the hardware RNG if high-quality random numbers are needed. ## Performance If you run `dune exec test/speedtest.exe`, a simple benchmark is performed and shows the speed of various operations from this library. cryptokit-release119/configure000077500000000000000000000027201453705265000166760ustar00rootroot00000000000000#!/usr/bin/env ocaml (* -*- tuareg -*- *) type 'a value = | This of 'a | Auto let string_of_value to_string = function | This a -> "This (" ^ to_string a ^ ")" | Auto -> "Auto" let () = let declare_flag arg description = let reference = ref Auto in let args = [ "--enable-" ^ arg, Arg.Unit (fun () -> reference := This true), " Enable " ^ description ; "--disable-" ^ arg, Arg.Unit (fun () -> reference := This false), " Disable " ^ description ] in args, reference in let args_zlib, ref_zlib = declare_flag "zlib" "ZLib" in let args_hardware_support, ref_hardware_support = declare_flag "hardwaresupport" "hardware support for AES and GCM (needs GCC or Clang)" in Arg.parse (Arg.align (args_zlib @ args_hardware_support)) (fun s -> raise (Arg.Bad (Printf.sprintf "don't know what to do with %S" s))) "Usage: ./configure [OPTIONS]"; let oc = open_out_bin "src/config/config_vars.ml" in Printf.fprintf oc {| type 'a value = | This of 'a | Auto let enable_zlib = %s let enable_hardware_support = %s |} (string_of_value string_of_bool !ref_zlib) (string_of_value string_of_bool !ref_hardware_support); close_out oc; (* Below is a temporary workaround to make sure the configuration happens every time this script is run. *) (try Sys.remove "_build/default/src/flags.sexp"; with _ -> ()); exit (Sys.command "dune build @configure --release") cryptokit-release119/cryptokit.opam000066400000000000000000000021551453705265000176770ustar00rootroot00000000000000# This file is generated by dune, edit dune-project instead opam-version: "2.0" version: "1.19" synopsis: "A library of cryptographic primitives" description: "Cryptokit includes authenticated encryption (AES-GCM, Chacha20-Poly1305), block ciphers (AES, DES, 3DES), stream ciphers (Chacha20, ARCfour), public-key cryptography (RSA, DH), hashes (SHA-256, SHA-512, SHA-3, Blake2, Blake3), MACs, compression, random number generation -- all presented with a compositional, extensible interface." maintainer: ["Xavier Leroy "] authors: ["Xavier Leroy"] license: "LGPL-2.0-or-later WITH OCaml-LGPL-linking-exception" homepage: "https://github.com/xavierleroy/cryptokit" bug-reports: "https://github.com/xavierleroy/cryptokit/issues" depends: [ "ocaml" {>= "4.08.0"} "dune" {>= "2.5"} "dune-configurator" "zarith" {>= "1.4"} "conf-zlib" "conf-gmp-powm-sec" ] build: [ ["dune" "subst"] {pinned} [ "dune" "build" "-p" name "-j" jobs "@install" "@runtest" {with-test} "@doc" {with-doc} ] ] dev-repo: "git+https://github.com/xavierleroy/cryptokit.git" cryptokit-release119/dune-project000066400000000000000000000014711453705265000173130ustar00rootroot00000000000000(lang dune 2.5) (generate_opam_files true) (name cryptokit) (source (github xavierleroy/cryptokit)) (authors "Xavier Leroy") (maintainers "Xavier Leroy ") (package (name cryptokit) (synopsis "A library of cryptographic primitives") (version 1.19) (license "LGPL-2.0-or-later WITH OCaml-LGPL-linking-exception") (description "Cryptokit includes authenticated encryption (AES-GCM, Chacha20-Poly1305), block ciphers (AES, DES, 3DES), stream ciphers (Chacha20, ARCfour), public-key cryptography (RSA, DH), hashes (SHA-256, SHA-512, SHA-3, Blake2, Blake3), MACs, compression, random number generation -- all presented with a compositional, extensible interface.") (depends (ocaml (>= 4.08.0)) (dune (>= 2.5)) dune-configurator (zarith (>= 1.4)) conf-zlib conf-gmp-powm-sec)) cryptokit-release119/src/000077500000000000000000000000001453705265000155555ustar00rootroot00000000000000cryptokit-release119/src/aesni.c000066400000000000000000000243521453705265000170260ustar00rootroot00000000000000/***********************************************************************/ /* */ /* The Cryptokit library */ /* */ /* Xavier Leroy, projet Gallium, INRIA Paris */ /* */ /* Copyright 2016 Institut National de Recherche en Informatique et */ /* en Automatique. All rights reserved. This file is distributed */ /* under the terms of the GNU Library General Public License, with */ /* the special exception on linking described in file LICENSE. */ /* */ /***********************************************************************/ /* Hardware-accelerated implementation of AES */ #include "stdlib.h" #include "aesni.h" #ifdef __AES__ #include #include #include int aesni_available = -1; int aesni_check_available(void) { unsigned int eax, ebx, ecx, edx; if(__get_cpuid(1, &eax, &ebx, &ecx, &edx)) { aesni_available = (ecx & 0x2000000) != 0; } else { aesni_available = 0; } return aesni_available; } static inline __m128i aesni_128_assist(__m128i t1, __m128i t2) { __m128i t3; t2 = _mm_shuffle_epi32 (t2 ,0xff); t3 = _mm_slli_si128 (t1, 0x4); t1 = _mm_xor_si128 (t1, t3); t3 = _mm_slli_si128 (t3, 0x4); t1 = _mm_xor_si128 (t1, t3); t3 = _mm_slli_si128 (t3, 0x4); t1 = _mm_xor_si128 (t1, t3); t1 = _mm_xor_si128 (t1, t2); return t1; } static inline void aesni_192_assist(__m128i * t1, __m128i * t2, __m128i * t3) { __m128i t4; *t2 = _mm_shuffle_epi32 (*t2, 0x55); t4 = _mm_slli_si128 (*t1, 0x4); *t1 = _mm_xor_si128 (*t1, t4); t4 = _mm_slli_si128 (t4, 0x4); *t1 = _mm_xor_si128 (*t1, t4); t4 = _mm_slli_si128 (t4, 0x4); *t1 = _mm_xor_si128 (*t1, t4); *t1 = _mm_xor_si128 (*t1, *t2); *t2 = _mm_shuffle_epi32(*t1, 0xff); t4 = _mm_slli_si128 (*t3, 0x4); *t3 = _mm_xor_si128 (*t3, t4); *t3 = _mm_xor_si128 (*t3, *t2); } static inline void aesni_256_assist_1(__m128i * t1, __m128i * t2) { __m128i t4; *t2 = _mm_shuffle_epi32(*t2, 0xff); t4 = _mm_slli_si128 (*t1, 0x4); *t1 = _mm_xor_si128 (*t1, t4); t4 = _mm_slli_si128 (t4, 0x4); *t1 = _mm_xor_si128 (*t1, t4); t4 = _mm_slli_si128 (t4, 0x4); *t1 = _mm_xor_si128 (*t1, t4); *t1 = _mm_xor_si128 (*t1, *t2); } static inline void aesni_256_assist_2(__m128i * t1, __m128i * t3) { __m128i t2, t4; t4 = _mm_aeskeygenassist_si128 (*t1, 0x0); t2 = _mm_shuffle_epi32(t4, 0xaa); t4 = _mm_slli_si128 (*t3, 0x4); *t3 = _mm_xor_si128 (*t3, t4); t4 = _mm_slli_si128 (t4, 0x4); *t3 = _mm_xor_si128 (*t3, t4); t4 = _mm_slli_si128 (t4, 0x4); *t3 = _mm_xor_si128 (*t3, t4); *t3 = _mm_xor_si128 (*t3, t2); } static int aesni_key_expansion(const unsigned char * userkey, int keylength, __m128i * key_schedule) { __m128i t1, t2, t3; switch (keylength) { case 128: t1 = _mm_loadu_si128((__m128i*)userkey); key_schedule[0] = t1; t2 = _mm_aeskeygenassist_si128 (t1 ,0x1); t1 = aesni_128_assist(t1, t2); key_schedule[1] = t1; t2 = _mm_aeskeygenassist_si128 (t1,0x2); t1 = aesni_128_assist(t1, t2); key_schedule[2] = t1; t2 = _mm_aeskeygenassist_si128 (t1,0x4); t1 = aesni_128_assist(t1, t2); key_schedule[3] = t1; t2 = _mm_aeskeygenassist_si128 (t1,0x8); t1 = aesni_128_assist(t1, t2); key_schedule[4] = t1; t2 = _mm_aeskeygenassist_si128 (t1,0x10); t1 = aesni_128_assist(t1, t2); key_schedule[5] = t1; t2 = _mm_aeskeygenassist_si128 (t1,0x20); t1 = aesni_128_assist(t1, t2); key_schedule[6] = t1; t2 = _mm_aeskeygenassist_si128 (t1,0x40); t1 = aesni_128_assist(t1, t2); key_schedule[7] = t1; t2 = _mm_aeskeygenassist_si128 (t1,0x80); t1 = aesni_128_assist(t1, t2); key_schedule[8] = t1; t2 = _mm_aeskeygenassist_si128 (t1,0x1b); t1 = aesni_128_assist(t1, t2); key_schedule[9] = t1; t2 = _mm_aeskeygenassist_si128 (t1,0x36); t1 = aesni_128_assist(t1, t2); key_schedule[10] = t1; return 10; case 192: t1 = _mm_loadu_si128((__m128i*)userkey); t3 = _mm_loadu_si128((__m128i*)(userkey+16)); key_schedule[0] = t1; key_schedule[1] = t3; t2 = _mm_aeskeygenassist_si128 (t3,0x1); aesni_192_assist(&t1, &t2, &t3); key_schedule[1] = (__m128i)_mm_shuffle_pd((__m128d)key_schedule[1], (__m128d)t1,0); key_schedule[2] = (__m128i)_mm_shuffle_pd((__m128d)t1,(__m128d)t3,1); t2 = _mm_aeskeygenassist_si128 (t3,0x2); aesni_192_assist(&t1, &t2, &t3); key_schedule[3] = t1; key_schedule[4] = t3; t2 = _mm_aeskeygenassist_si128 (t3,0x4); aesni_192_assist(&t1, &t2, &t3); key_schedule[4] = (__m128i)_mm_shuffle_pd((__m128d)key_schedule[4], (__m128d)t1,0); key_schedule[5] = (__m128i)_mm_shuffle_pd((__m128d)t1,(__m128d)t3,1); t2 = _mm_aeskeygenassist_si128 (t3,0x8); aesni_192_assist(&t1, &t2, &t3); key_schedule[6] = t1; key_schedule[7] = t3; t2 = _mm_aeskeygenassist_si128 (t3,0x10); aesni_192_assist(&t1, &t2, &t3); key_schedule[7] = (__m128i)_mm_shuffle_pd((__m128d)key_schedule[7], (__m128d)t1,0); key_schedule[8] = (__m128i)_mm_shuffle_pd((__m128d)t1,(__m128d)t3,1); t2 = _mm_aeskeygenassist_si128 (t3,0x20); aesni_192_assist(&t1, &t2, &t3); key_schedule[9] = t1; key_schedule[10] = t3; t2 = _mm_aeskeygenassist_si128 (t3,0x40); aesni_192_assist(&t1, &t2, &t3); key_schedule[10] = (__m128i)_mm_shuffle_pd((__m128d)key_schedule[10], (__m128d)t1,0); key_schedule[11] = (__m128i)_mm_shuffle_pd((__m128d)t1,(__m128d)t3,1); t2 = _mm_aeskeygenassist_si128 (t3,0x80); aesni_192_assist(&t1, &t2, &t3); key_schedule[12] = t1; return 12; case 256: t1 = _mm_loadu_si128((__m128i*)userkey); t3 = _mm_loadu_si128((__m128i*)(userkey+16)); key_schedule[0] = t1; key_schedule[1] = t3; t2 = _mm_aeskeygenassist_si128 (t3,0x01); aesni_256_assist_1(&t1, &t2); key_schedule[2] = t1; aesni_256_assist_2(&t1, &t3); key_schedule[3] = t3; t2 = _mm_aeskeygenassist_si128(t3,0x02); aesni_256_assist_1(&t1, &t2); key_schedule[4] = t1; aesni_256_assist_2(&t1, &t3); key_schedule[5] = t3; t2 = _mm_aeskeygenassist_si128(t3,0x04); aesni_256_assist_1(&t1, &t2); key_schedule[6] = t1; aesni_256_assist_2(&t1, &t3); key_schedule[7] = t3; t2 = _mm_aeskeygenassist_si128(t3,0x08); aesni_256_assist_1(&t1, &t2); key_schedule[8] = t1; aesni_256_assist_2(&t1, &t3); key_schedule[9] = t3; t2 = _mm_aeskeygenassist_si128(t3,0x10); aesni_256_assist_1(&t1, &t2); key_schedule[10] = t1; aesni_256_assist_2(&t1, &t3); key_schedule[11] = t3; t2 = _mm_aeskeygenassist_si128(t3,0x20); aesni_256_assist_1(&t1, &t2); key_schedule[12] = t1; aesni_256_assist_2(&t1, &t3); key_schedule[13] = t3; t2 = _mm_aeskeygenassist_si128(t3,0x40); aesni_256_assist_1(&t1, &t2); key_schedule[14] = t1; return 14; default: abort(); } } static void * align16(void * p) { uintptr_t n = (uintptr_t) p; n = (n + 15) & -16; return (void *) n; } int aesniKeySetupEnc(unsigned char * ckey, const unsigned char * key, int keylength) { __m128i unaligned_key_schedule[15 + 1]; /* + 1 to leave space for alignment */ __m128i *key_schedule = align16(unaligned_key_schedule); int nrounds, i; nrounds = aesni_key_expansion(key, keylength, key_schedule); for (i = 0; i <= nrounds; i++) { _mm_storeu_si128((__m128i*) ckey + i, key_schedule[i]); } return nrounds; } int aesniKeySetupDec(unsigned char * ckey, const unsigned char * key, int keylength) { __m128i unaligned_key_schedule[15 + 1]; /* + 1 to leave space for alignment */ __m128i *key_schedule = align16(unaligned_key_schedule); int nrounds, i; nrounds = aesni_key_expansion(key, keylength, key_schedule); _mm_storeu_si128((__m128i*) ckey + 0, key_schedule[nrounds]); for (i = 1; i < nrounds; i++) { _mm_storeu_si128((__m128i*) ckey + i, _mm_aesimc_si128(key_schedule[nrounds - i])); } _mm_storeu_si128((__m128i*) ckey + nrounds, key_schedule[0]); return nrounds; } void aesniEncrypt(const unsigned char * key, int nrounds, const unsigned char * in, unsigned char * out) { __m128i t, k; int j; t = _mm_loadu_si128 ((__m128i*) in); k = _mm_loadu_si128 ((__m128i*) key + 0); t = _mm_xor_si128 (t, k); j = 1; do { k = _mm_loadu_si128 ((__m128i*) key + j); t = _mm_aesenc_si128 (t, k); j++; } while (j < nrounds); k = _mm_loadu_si128 ((__m128i*) key + j); t = _mm_aesenclast_si128 (t, k); _mm_storeu_si128 ((__m128i*) out, t); } void aesniDecrypt(const unsigned char * key, int nrounds, const unsigned char * in, unsigned char * out) { __m128i t, k; int j; t = _mm_loadu_si128 ((__m128i*) in); k = _mm_loadu_si128 ((__m128i*) key + 0); t = _mm_xor_si128 (t, k); j = 1; do { k = _mm_loadu_si128 ((__m128i*) key + j); t = _mm_aesdec_si128 (t, k); j++; } while (j < nrounds); k = _mm_loadu_si128 ((__m128i*) key + j); t = _mm_aesdeclast_si128 (t, k); _mm_storeu_si128 ((__m128i*) out, t); } #else int aesni_available = 0; int aesni_check_available(void) { return 0; } int aesniKeySetupEnc(unsigned char * ckey, const unsigned char * key, int keylength) { abort(); } int aesniKeySetupDec(unsigned char * ckey, const unsigned char * key, int keylength) { abort(); } void aesniEncrypt(const unsigned char * key, int nrounds, const unsigned char * in, unsigned char * out) { abort(); } void aesniDecrypt(const unsigned char * key, int nrounds, const unsigned char * in, unsigned char * out) { abort(); } #endif cryptokit-release119/src/aesni.h000066400000000000000000000033161453705265000170300ustar00rootroot00000000000000/***********************************************************************/ /* */ /* The Cryptokit library */ /* */ /* Xavier Leroy, projet Gallium, INRIA Paris */ /* */ /* Copyright 2016 Institut National de Recherche en Informatique et */ /* en Automatique. All rights reserved. This file is distributed */ /* under the terms of the GNU Library General Public License, with */ /* the special exception on linking described in file LICENSE. */ /* */ /***********************************************************************/ /* Hardware-accelerated implementation of AES */ extern int aesni_available; /* -1: unknown, call aesni_check_available() to determine 0: not available 1: available */ extern int aesni_check_available(void); extern int aesniKeySetupEnc(unsigned char * ckey, const unsigned char * key, int keylength); extern int aesniKeySetupDec(unsigned char * ckey, const unsigned char * key, int keylength); extern void aesniEncrypt(const unsigned char * key, int nrounds, const unsigned char * in, unsigned char * out); extern void aesniDecrypt(const unsigned char * key, int nrounds, const unsigned char * in, unsigned char * out); cryptokit-release119/src/arcfour.c000066400000000000000000000034761453705265000173740ustar00rootroot00000000000000/***********************************************************************/ /* */ /* The Cryptokit library */ /* */ /* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ /* */ /* Copyright 2002 Institut National de Recherche en Informatique et */ /* en Automatique. All rights reserved. This file is distributed */ /* under the terms of the GNU Library General Public License, with */ /* the special exception on linking described in file LICENSE. */ /* */ /***********************************************************************/ /* $Id$ */ #include "arcfour.h" void arcfour_cook_key(struct arcfour_key * key, unsigned char * key_data, int key_data_len) { unsigned char * s; int i; unsigned char t, index1, index2; s = &key->state[0]; for (i = 0; i < 256; i++) s[i] = i; key->x = 0; key->y = 0; index1 = 0; index2 = 0; for (i = 0; i < 256; i++) { index2 = key_data[index1] + s[i] + index2; t = s[i]; s[i] = s[index2]; s[index2] = t; index1++; if (index1 >= key_data_len) index1 = 0; } } void arcfour_encrypt(struct arcfour_key * key, char * src, char * dst, long len) { int x, y, kx, ky; x = key->x; y = key->y; for (/*nothing*/; len > 0; len--) { x = (x + 1) & 0xFF; kx = key->state[x]; y = (kx + y) & 0xFF; ky = key->state[y]; key->state[x] = ky; key->state[y] = kx; *dst++ = *src++ ^ key->state[(kx + ky) & 0xFF]; } key->x = x; key->y = y; } cryptokit-release119/src/arcfour.h000066400000000000000000000023621453705265000173720ustar00rootroot00000000000000/***********************************************************************/ /* */ /* The Cryptokit library */ /* */ /* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ /* */ /* Copyright 2002 Institut National de Recherche en Informatique et */ /* en Automatique. All rights reserved. This file is distributed */ /* under the terms of the GNU Library General Public License, with */ /* the special exception on linking described in file LICENSE. */ /* */ /***********************************************************************/ /* $Id$ */ struct arcfour_key { unsigned char state[256]; unsigned char x, y; }; extern void arcfour_cook_key(struct arcfour_key * key, unsigned char * key_data, int key_data_len); extern void arcfour_encrypt(struct arcfour_key * key, char * src, char * dst, long len); cryptokit-release119/src/blake2.c000066400000000000000000000270451453705265000170710ustar00rootroot00000000000000/***********************************************************************/ /* */ /* The Cryptokit library */ /* */ /* Xavier Leroy, Collège de France and Inria */ /* */ /* Copyright 2020 Institut National de Recherche en Informatique et */ /* en Automatique. All rights reserved. This file is distributed */ /* under the terms of the GNU Library General Public License, with */ /* the special exception on linking described in file LICENSE. */ /* */ /***********************************************************************/ /* BLAKE2 hashing */ #include #include #include #include "blake2.h" static const uint8_t BLAKE2_sigma[12][16] = { { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }, { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 }, { 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 }, { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 }, { 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 }, { 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 }, { 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 }, { 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 }, { 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 }, { 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0 }, { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }, { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 } }; /* BLAKE2b */ static inline uint64_t U8TO64LE(unsigned char * src) { return (uint64_t) src[0] | ((uint64_t) src[1] << 8) | ((uint64_t) src[2] << 16) | ((uint64_t) src[3] << 24) | ((uint64_t) src[4] << 32) | ((uint64_t) src[5] << 40) | ((uint64_t) src[6] << 48) | ((uint64_t) src[7] << 56); } static inline uint64_t ROTR64(uint64_t x, int amount) { return (x >> amount) | (x << (64 - amount)); } static const uint64_t blake2b_iv[8] = { UINT64_C(0x6a09e667f3bcc908), UINT64_C(0xbb67ae8584caa73b), UINT64_C(0x3c6ef372fe94f82b), UINT64_C(0xa54ff53a5f1d36f1), UINT64_C(0x510e527fade682d1), UINT64_C(0x9b05688c2b3e6c1f), UINT64_C(0x1f83d9abfb41bd6b), UINT64_C(0x5be0cd19137e2179) }; #define MIX2B(a,b,c,d,x,y) \ do { \ a += b + x; \ d = ROTR64(d ^ a, 32); \ c += d; \ b = ROTR64(b ^ c, 24); \ a += b + y; \ d = ROTR64(d ^ a, 16); \ c += d; \ b = ROTR64(b ^ c, 63); \ } while(0) \ static void blake2b_compress(struct blake2b * s, unsigned char * data, unsigned int numbytes, int is_last_block) { uint64_t v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15; uint64_t m[16]; int i; const uint8_t * sigma; /* Update the length */ s->len[0] += numbytes; if (s->len[0] < numbytes) s->len[1]++; /* carry */ /* Initialize work space */ v0 = s->h[0]; v1 = s->h[1]; v2 = s->h[2]; v3 = s->h[3]; v4 = s->h[4]; v5 = s->h[5]; v6 = s->h[6]; v7 = s->h[7]; v8 = blake2b_iv[0]; v9 = blake2b_iv[1]; v10 = blake2b_iv[2]; v11 = blake2b_iv[3]; v12 = blake2b_iv[4] ^ s->len[0]; v13 = blake2b_iv[5] ^ s->len[1]; v14 = is_last_block ? ~ blake2b_iv[6] : blake2b_iv[6]; v15 = blake2b_iv[7]; /* Convert data to 16 64-bit words */ for (i = 0; i < 16; i++) { m[i] = U8TO64LE(data + i * 8); } /* Twelve rounds of mixing */ for (i = 0; i < 12; i++) { sigma = BLAKE2_sigma[i]; MIX2B(v0, v4, v8, v12, m[sigma[0]], m[sigma[1]]); MIX2B(v1, v5, v9, v13, m[sigma[2]], m[sigma[3]]); MIX2B(v2, v6, v10, v14, m[sigma[4]], m[sigma[5]]); MIX2B(v3, v7, v11, v15, m[sigma[6]], m[sigma[7]]); MIX2B(v0, v5, v10, v15, m[sigma[8]], m[sigma[9]]); MIX2B(v1, v6, v11, v12, m[sigma[10]], m[sigma[11]]); MIX2B(v2, v7, v8, v13, m[sigma[12]], m[sigma[13]]); MIX2B(v3, v4, v9, v14, m[sigma[14]], m[sigma[15]]); } /* Update state */ s->h[0] ^= v0 ^ v8; s->h[1] ^= v1 ^ v9; s->h[2] ^= v2 ^ v10; s->h[3] ^= v3 ^ v11; s->h[4] ^= v4 ^ v12; s->h[5] ^= v5 ^ v13; s->h[6] ^= v6 ^ v14; s->h[7] ^= v7 ^ v15; } void blake2b_init(struct blake2b * s, int hashlen, int keylen, unsigned char * key) { int i; assert (0 < hashlen && hashlen <= 64); assert (0 <= keylen && keylen <= 64); for (i = 0; i < 8; i++) s->h[i] = blake2b_iv[i]; s->h[0] ^= 0x01010000 | (keylen << 8) | hashlen; s->len[0] = s->len[1] = 0; s->numbytes = 0; /* If key was supplied, pad to 128 bytes and prepend to message */ if (keylen > 0) { memset(s->buffer, 0, BLAKE2b_BLOCKSIZE); memcpy(s->buffer, key, keylen); s->numbytes = BLAKE2b_BLOCKSIZE; } } void blake2b_add_data(struct blake2b * s, unsigned char * data, size_t len) { int n; /* If data was left in buffer, pad it with fresh data and compress */ if (s->numbytes > 0) { n = BLAKE2b_BLOCKSIZE - s->numbytes; if (len <= n) { /* Not enough fresh data to compress. Buffer the data. */ memcpy(s->buffer + s->numbytes, data, len); s->numbytes += len; return; } memcpy(s->buffer + s->numbytes, data, n); blake2b_compress(s, s->buffer, BLAKE2b_BLOCKSIZE, 0); data += n; len -= n; } /* Process data by blocks of BLAKE2b_BLOCKSIZE */ while (len > BLAKE2b_BLOCKSIZE) { blake2b_compress(s, data, BLAKE2b_BLOCKSIZE, 0); data += BLAKE2b_BLOCKSIZE; len -= BLAKE2b_BLOCKSIZE; } /* Save remaining data */ memcpy(s->buffer, data, len); s->numbytes = len; } void blake2b_final(struct blake2b * s, int hashlen, unsigned char * hash) { unsigned int i; assert (0 < hashlen && hashlen <= 64); /* The final block is composed of the remaining data padded with zeros. */ memset(s->buffer + s->numbytes, 0, BLAKE2b_BLOCKSIZE - s->numbytes); blake2b_compress(s, s->buffer, s->numbytes, 1); /* Extract the hash */ for (i = 0; i < hashlen; i++) { hash[i] = s->h[i / 8] >> (8 * (i % 8)); } } /* BLAKE2s */ static inline uint32_t U8TO32LE(unsigned char * src) { return (uint32_t) src[0] | ((uint32_t) src[1] << 8) | ((uint32_t) src[2] << 16) | ((uint32_t) src[3] << 24); } static inline uint32_t ROTR32(uint32_t x, int amount) { return (x >> amount) | (x << (32 - amount)); } static const uint32_t blake2s_iv[8] = { UINT32_C(0x6A09E667), UINT32_C(0xBB67AE85), UINT32_C(0x3C6EF372), UINT32_C(0xA54FF53A), UINT32_C(0x510E527F), UINT32_C(0x9B05688C), UINT32_C(0x1F83D9AB), UINT32_C(0x5BE0CD19) }; #define MIX2S(a,b,c,d,x,y) \ do { \ a += b + x; \ d = ROTR32(d ^ a, 16); \ c += d; \ b = ROTR32(b ^ c, 12); \ a += b + y; \ d = ROTR32(d ^ a, 8); \ c += d; \ b = ROTR32(b ^ c, 7); \ } while(0) \ static void blake2s_compress(struct blake2s * s, unsigned char * data, unsigned int numbytes, int is_last_block) { uint32_t v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15; uint32_t m[16]; int i; const uint8_t * sigma; /* Update the length */ s->len[0] += numbytes; if (s->len[0] < numbytes) s->len[1]++; /* carry */ /* Initialize work space */ v0 = s->h[0]; v1 = s->h[1]; v2 = s->h[2]; v3 = s->h[3]; v4 = s->h[4]; v5 = s->h[5]; v6 = s->h[6]; v7 = s->h[7]; v8 = blake2s_iv[0]; v9 = blake2s_iv[1]; v10 = blake2s_iv[2]; v11 = blake2s_iv[3]; v12 = blake2s_iv[4] ^ s->len[0]; v13 = blake2s_iv[5] ^ s->len[1]; v14 = is_last_block ? ~ blake2s_iv[6] : blake2s_iv[6]; v15 = blake2s_iv[7]; /* Convert data to 16 32-bit words */ for (i = 0; i < 16; i++) { m[i] = U8TO32LE(data + i * 4); } /* Ten rounds of mixing */ for (i = 0; i < 10; i++) { sigma = BLAKE2_sigma[i]; MIX2S(v0, v4, v8, v12, m[sigma[0]], m[sigma[1]]); MIX2S(v1, v5, v9, v13, m[sigma[2]], m[sigma[3]]); MIX2S(v2, v6, v10, v14, m[sigma[4]], m[sigma[5]]); MIX2S(v3, v7, v11, v15, m[sigma[6]], m[sigma[7]]); MIX2S(v0, v5, v10, v15, m[sigma[8]], m[sigma[9]]); MIX2S(v1, v6, v11, v12, m[sigma[10]], m[sigma[11]]); MIX2S(v2, v7, v8, v13, m[sigma[12]], m[sigma[13]]); MIX2S(v3, v4, v9, v14, m[sigma[14]], m[sigma[15]]); } /* Update state */ s->h[0] ^= v0 ^ v8; s->h[1] ^= v1 ^ v9; s->h[2] ^= v2 ^ v10; s->h[3] ^= v3 ^ v11; s->h[4] ^= v4 ^ v12; s->h[5] ^= v5 ^ v13; s->h[6] ^= v6 ^ v14; s->h[7] ^= v7 ^ v15; } void blake2s_init(struct blake2s * s, int hashlen, int keylen, unsigned char * key) { int i; assert (0 < hashlen && hashlen <= 32); assert (0 <= keylen && keylen <= 32); for (i = 0; i < 8; i++) s->h[i] = blake2s_iv[i]; s->h[0] ^= 0x01010000 | (keylen << 8) | hashlen; s->len[0] = s->len[1] = 0; s->numbytes = 0; /* If key was supplied, pad to 64 bytes and prepend to message */ if (keylen > 0) { memset(s->buffer, 0, BLAKE2s_BLOCKSIZE); memcpy(s->buffer, key, keylen); s->numbytes = BLAKE2s_BLOCKSIZE; } } void blake2s_add_data(struct blake2s * s, unsigned char * data, size_t len) { int n; /* If data was left in buffer, pad it with fresh data and compress */ if (s->numbytes > 0) { n = BLAKE2s_BLOCKSIZE - s->numbytes; if (len <= n) { /* Not enough fresh data to compress. Buffer the data. */ memcpy(s->buffer + s->numbytes, data, len); s->numbytes += len; return; } memcpy(s->buffer + s->numbytes, data, n); blake2s_compress(s, s->buffer, BLAKE2s_BLOCKSIZE, 0); data += n; len -= n; } /* Process data by blocks of BLAKE2s_BLOCKSIZE */ while (len > BLAKE2s_BLOCKSIZE) { blake2s_compress(s, data, BLAKE2s_BLOCKSIZE, 0); data += BLAKE2s_BLOCKSIZE; len -= BLAKE2s_BLOCKSIZE; } /* Save remaining data */ memcpy(s->buffer, data, len); s->numbytes = len; } void blake2s_final(struct blake2s * s, int hashlen, unsigned char * hash) { unsigned int i; assert (0 < hashlen && hashlen <= 32); /* The final block is composed of the remaining data padded with zeros. */ memset(s->buffer + s->numbytes, 0, BLAKE2s_BLOCKSIZE - s->numbytes); blake2s_compress(s, s->buffer, s->numbytes, 1); /* Extract the hash */ for (i = 0; i < hashlen; i++) { hash[i] = s->h[i / 4] >> (8 * (i % 4)); } } cryptokit-release119/src/blake2.h000066400000000000000000000035341453705265000170730ustar00rootroot00000000000000/***********************************************************************/ /* */ /* The Cryptokit library */ /* */ /* Xavier Leroy, Collège de France and Inria */ /* */ /* Copyright 2020 Institut National de Recherche en Informatique et */ /* en Automatique. All rights reserved. This file is distributed */ /* under the terms of the GNU Library General Public License, with */ /* the special exception on linking described in file LICENSE. */ /* */ /***********************************************************************/ /* BLAKE2b hashing */ #define BLAKE2b_BLOCKSIZE 128 struct blake2b { uint64_t h[8]; uint64_t len[2]; int numbytes; unsigned char buffer[BLAKE2b_BLOCKSIZE]; }; extern void blake2b_init(struct blake2b * s, int hashlen, int keylen, unsigned char * key); extern void blake2b_add_data(struct blake2b * s, unsigned char * data, size_t len); extern void blake2b_final(struct blake2b * s, int hashlen, unsigned char * hash); #define BLAKE2s_BLOCKSIZE 64 struct blake2s { uint32_t h[8]; uint32_t len[2]; int numbytes; unsigned char buffer[BLAKE2s_BLOCKSIZE]; }; extern void blake2s_init(struct blake2s * s, int hashlen, int keylen, unsigned char * key); extern void blake2s_add_data(struct blake2s * s, unsigned char * data, size_t len); extern void blake2s_final(struct blake2s * s, int hashlen, unsigned char * hash); cryptokit-release119/src/blake3.c000066400000000000000000000656451453705265000171020ustar00rootroot00000000000000#include #include #include #include "blake3.h" #include "blake3_impl.h" const char *blake3_version(void) { return BLAKE3_VERSION_STRING; } INLINE void chunk_state_init(blake3_chunk_state *self, const uint32_t key[8], uint8_t flags) { memcpy(self->cv, key, BLAKE3_KEY_LEN); self->chunk_counter = 0; memset(self->buf, 0, BLAKE3_BLOCK_LEN); self->buf_len = 0; self->blocks_compressed = 0; self->flags = flags; } INLINE void chunk_state_reset(blake3_chunk_state *self, const uint32_t key[8], uint64_t chunk_counter) { memcpy(self->cv, key, BLAKE3_KEY_LEN); self->chunk_counter = chunk_counter; self->blocks_compressed = 0; memset(self->buf, 0, BLAKE3_BLOCK_LEN); self->buf_len = 0; } INLINE size_t chunk_state_len(const blake3_chunk_state *self) { return (BLAKE3_BLOCK_LEN * (size_t)self->blocks_compressed) + ((size_t)self->buf_len); } INLINE size_t chunk_state_fill_buf(blake3_chunk_state *self, const uint8_t *input, size_t input_len) { size_t take = BLAKE3_BLOCK_LEN - ((size_t)self->buf_len); if (take > input_len) { take = input_len; } uint8_t *dest = self->buf + ((size_t)self->buf_len); memcpy(dest, input, take); self->buf_len += (uint8_t)take; return take; } INLINE uint8_t chunk_state_maybe_start_flag(const blake3_chunk_state *self) { if (self->blocks_compressed == 0) { return CHUNK_START; } else { return 0; } } typedef struct { uint32_t input_cv[8]; uint64_t counter; uint8_t block[BLAKE3_BLOCK_LEN]; uint8_t block_len; uint8_t flags; } output_t; INLINE output_t make_output(const uint32_t input_cv[8], const uint8_t block[BLAKE3_BLOCK_LEN], uint8_t block_len, uint64_t counter, uint8_t flags) { output_t ret; memcpy(ret.input_cv, input_cv, 32); memcpy(ret.block, block, BLAKE3_BLOCK_LEN); ret.block_len = block_len; ret.counter = counter; ret.flags = flags; return ret; } // Chaining values within a given chunk (specifically the compress_in_place // interface) are represented as words. This avoids unnecessary bytes<->words // conversion overhead in the portable implementation. However, the hash_many // interface handles both user input and parent node blocks, so it accepts // bytes. For that reason, chaining values in the CV stack are represented as // bytes. INLINE void output_chaining_value(const output_t *self, uint8_t cv[32]) { uint32_t cv_words[8]; memcpy(cv_words, self->input_cv, 32); blake3_compress_in_place(cv_words, self->block, self->block_len, self->counter, self->flags); store_cv_words(cv, cv_words); } INLINE void output_root_bytes(const output_t *self, uint64_t seek, uint8_t *out, size_t out_len) { uint64_t output_block_counter = seek / 64; size_t offset_within_block = seek % 64; uint8_t wide_buf[64]; while (out_len > 0) { blake3_compress_xof(self->input_cv, self->block, self->block_len, output_block_counter, self->flags | ROOT, wide_buf); size_t available_bytes = 64 - offset_within_block; size_t memcpy_len; if (out_len > available_bytes) { memcpy_len = available_bytes; } else { memcpy_len = out_len; } memcpy(out, wide_buf + offset_within_block, memcpy_len); out += memcpy_len; out_len -= memcpy_len; output_block_counter += 1; offset_within_block = 0; } } INLINE void chunk_state_update(blake3_chunk_state *self, const uint8_t *input, size_t input_len) { if (self->buf_len > 0) { size_t take = chunk_state_fill_buf(self, input, input_len); input += take; input_len -= take; if (input_len > 0) { blake3_compress_in_place( self->cv, self->buf, BLAKE3_BLOCK_LEN, self->chunk_counter, self->flags | chunk_state_maybe_start_flag(self)); self->blocks_compressed += 1; self->buf_len = 0; memset(self->buf, 0, BLAKE3_BLOCK_LEN); } } while (input_len > BLAKE3_BLOCK_LEN) { blake3_compress_in_place(self->cv, input, BLAKE3_BLOCK_LEN, self->chunk_counter, self->flags | chunk_state_maybe_start_flag(self)); self->blocks_compressed += 1; input += BLAKE3_BLOCK_LEN; input_len -= BLAKE3_BLOCK_LEN; } size_t take = chunk_state_fill_buf(self, input, input_len); input += take; input_len -= take; } INLINE output_t chunk_state_output(const blake3_chunk_state *self) { uint8_t block_flags = self->flags | chunk_state_maybe_start_flag(self) | CHUNK_END; return make_output(self->cv, self->buf, self->buf_len, self->chunk_counter, block_flags); } INLINE output_t parent_output(const uint8_t block[BLAKE3_BLOCK_LEN], const uint32_t key[8], uint8_t flags) { return make_output(key, block, BLAKE3_BLOCK_LEN, 0, flags | PARENT); } // Given some input larger than one chunk, return the number of bytes that // should go in the left subtree. This is the largest power-of-2 number of // chunks that leaves at least 1 byte for the right subtree. INLINE size_t left_len(size_t content_len) { // Subtract 1 to reserve at least one byte for the right side. content_len // should always be greater than BLAKE3_CHUNK_LEN. size_t full_chunks = (content_len - 1) / BLAKE3_CHUNK_LEN; return round_down_to_power_of_2(full_chunks) * BLAKE3_CHUNK_LEN; } // Use SIMD parallelism to hash up to MAX_SIMD_DEGREE chunks at the same time // on a single thread. Write out the chunk chaining values and return the // number of chunks hashed. These chunks are never the root and never empty; // those cases use a different codepath. INLINE size_t compress_chunks_parallel(const uint8_t *input, size_t input_len, const uint32_t key[8], uint64_t chunk_counter, uint8_t flags, uint8_t *out) { #if defined(BLAKE3_TESTING) assert(0 < input_len); assert(input_len <= MAX_SIMD_DEGREE * BLAKE3_CHUNK_LEN); #endif const uint8_t *chunks_array[MAX_SIMD_DEGREE]; size_t input_position = 0; size_t chunks_array_len = 0; while (input_len - input_position >= BLAKE3_CHUNK_LEN) { chunks_array[chunks_array_len] = &input[input_position]; input_position += BLAKE3_CHUNK_LEN; chunks_array_len += 1; } blake3_hash_many(chunks_array, chunks_array_len, BLAKE3_CHUNK_LEN / BLAKE3_BLOCK_LEN, key, chunk_counter, true, flags, CHUNK_START, CHUNK_END, out); // Hash the remaining partial chunk, if there is one. Note that the empty // chunk (meaning the empty message) is a different codepath. if (input_len > input_position) { uint64_t counter = chunk_counter + (uint64_t)chunks_array_len; blake3_chunk_state chunk_state; chunk_state_init(&chunk_state, key, flags); chunk_state.chunk_counter = counter; chunk_state_update(&chunk_state, &input[input_position], input_len - input_position); output_t output = chunk_state_output(&chunk_state); output_chaining_value(&output, &out[chunks_array_len * BLAKE3_OUT_LEN]); return chunks_array_len + 1; } else { return chunks_array_len; } } // Use SIMD parallelism to hash up to MAX_SIMD_DEGREE parents at the same time // on a single thread. Write out the parent chaining values and return the // number of parents hashed. (If there's an odd input chaining value left over, // return it as an additional output.) These parents are never the root and // never empty; those cases use a different codepath. INLINE size_t compress_parents_parallel(const uint8_t *child_chaining_values, size_t num_chaining_values, const uint32_t key[8], uint8_t flags, uint8_t *out) { #if defined(BLAKE3_TESTING) assert(2 <= num_chaining_values); assert(num_chaining_values <= 2 * MAX_SIMD_DEGREE_OR_2); #endif const uint8_t *parents_array[MAX_SIMD_DEGREE_OR_2]; size_t parents_array_len = 0; while (num_chaining_values - (2 * parents_array_len) >= 2) { parents_array[parents_array_len] = &child_chaining_values[2 * parents_array_len * BLAKE3_OUT_LEN]; parents_array_len += 1; } blake3_hash_many(parents_array, parents_array_len, 1, key, 0, // Parents always use counter 0. false, flags | PARENT, 0, // Parents have no start flags. 0, // Parents have no end flags. out); // If there's an odd child left over, it becomes an output. if (num_chaining_values > 2 * parents_array_len) { memcpy(&out[parents_array_len * BLAKE3_OUT_LEN], &child_chaining_values[2 * parents_array_len * BLAKE3_OUT_LEN], BLAKE3_OUT_LEN); return parents_array_len + 1; } else { return parents_array_len; } } // The wide helper function returns (writes out) an array of chaining values // and returns the length of that array. The number of chaining values returned // is the dynamically detected SIMD degree, at most MAX_SIMD_DEGREE. Or fewer, // if the input is shorter than that many chunks. The reason for maintaining a // wide array of chaining values going back up the tree, is to allow the // implementation to hash as many parents in parallel as possible. // // As a special case when the SIMD degree is 1, this function will still return // at least 2 outputs. This guarantees that this function doesn't perform the // root compression. (If it did, it would use the wrong flags, and also we // wouldn't be able to implement exendable output.) Note that this function is // not used when the whole input is only 1 chunk long; that's a different // codepath. // // Why not just have the caller split the input on the first update(), instead // of implementing this special rule? Because we don't want to limit SIMD or // multi-threading parallelism for that update(). static size_t blake3_compress_subtree_wide(const uint8_t *input, size_t input_len, const uint32_t key[8], uint64_t chunk_counter, uint8_t flags, uint8_t *out) { // Note that the single chunk case does *not* bump the SIMD degree up to 2 // when it is 1. If this implementation adds multi-threading in the future, // this gives us the option of multi-threading even the 2-chunk case, which // can help performance on smaller platforms. if (input_len <= blake3_simd_degree() * BLAKE3_CHUNK_LEN) { return compress_chunks_parallel(input, input_len, key, chunk_counter, flags, out); } // With more than simd_degree chunks, we need to recurse. Start by dividing // the input into left and right subtrees. (Note that this is only optimal // as long as the SIMD degree is a power of 2. If we ever get a SIMD degree // of 3 or something, we'll need a more complicated strategy.) size_t left_input_len = left_len(input_len); size_t right_input_len = input_len - left_input_len; const uint8_t *right_input = &input[left_input_len]; uint64_t right_chunk_counter = chunk_counter + (uint64_t)(left_input_len / BLAKE3_CHUNK_LEN); // Make space for the child outputs. Here we use MAX_SIMD_DEGREE_OR_2 to // account for the special case of returning 2 outputs when the SIMD degree // is 1. uint8_t cv_array[2 * MAX_SIMD_DEGREE_OR_2 * BLAKE3_OUT_LEN]; size_t degree = blake3_simd_degree(); if (left_input_len > BLAKE3_CHUNK_LEN && degree == 1) { // The special case: We always use a degree of at least two, to make // sure there are two outputs. Except, as noted above, at the chunk // level, where we allow degree=1. (Note that the 1-chunk-input case is // a different codepath.) degree = 2; } uint8_t *right_cvs = &cv_array[degree * BLAKE3_OUT_LEN]; // Recurse! If this implementation adds multi-threading support in the // future, this is where it will go. size_t left_n = blake3_compress_subtree_wide(input, left_input_len, key, chunk_counter, flags, cv_array); size_t right_n = blake3_compress_subtree_wide( right_input, right_input_len, key, right_chunk_counter, flags, right_cvs); // The special case again. If simd_degree=1, then we'll have left_n=1 and // right_n=1. Rather than compressing them into a single output, return // them directly, to make sure we always have at least two outputs. if (left_n == 1) { memcpy(out, cv_array, 2 * BLAKE3_OUT_LEN); return 2; } // Otherwise, do one layer of parent node compression. size_t num_chaining_values = left_n + right_n; return compress_parents_parallel(cv_array, num_chaining_values, key, flags, out); } // Hash a subtree with compress_subtree_wide(), and then condense the resulting // list of chaining values down to a single parent node. Don't compress that // last parent node, however. Instead, return its message bytes (the // concatenated chaining values of its children). This is necessary when the // first call to update() supplies a complete subtree, because the topmost // parent node of that subtree could end up being the root. It's also necessary // for extended output in the general case. // // As with compress_subtree_wide(), this function is not used on inputs of 1 // chunk or less. That's a different codepath. INLINE void compress_subtree_to_parent_node( const uint8_t *input, size_t input_len, const uint32_t key[8], uint64_t chunk_counter, uint8_t flags, uint8_t out[2 * BLAKE3_OUT_LEN]) { #if defined(BLAKE3_TESTING) assert(input_len > BLAKE3_CHUNK_LEN); #endif uint8_t cv_array[MAX_SIMD_DEGREE_OR_2 * BLAKE3_OUT_LEN]; size_t num_cvs = blake3_compress_subtree_wide(input, input_len, key, chunk_counter, flags, cv_array); assert(num_cvs <= MAX_SIMD_DEGREE_OR_2); // If MAX_SIMD_DEGREE is greater than 2 and there's enough input, // compress_subtree_wide() returns more than 2 chaining values. Condense // them into 2 by forming parent nodes repeatedly. uint8_t out_array[MAX_SIMD_DEGREE_OR_2 * BLAKE3_OUT_LEN / 2]; // The second half of this loop condition is always true, and we just // asserted it above. But GCC can't tell that it's always true, and if NDEBUG // is set on platforms where MAX_SIMD_DEGREE_OR_2 == 2, GCC emits spurious // warnings here. GCC 8.5 is particularly sensitive, so if you're changing // this code, test it against that version. while (num_cvs > 2 && num_cvs <= MAX_SIMD_DEGREE_OR_2) { num_cvs = compress_parents_parallel(cv_array, num_cvs, key, flags, out_array); memcpy(cv_array, out_array, num_cvs * BLAKE3_OUT_LEN); } memcpy(out, cv_array, 2 * BLAKE3_OUT_LEN); } INLINE void hasher_init_base(blake3_hasher *self, const uint32_t key[8], uint8_t flags) { memcpy(self->key, key, BLAKE3_KEY_LEN); chunk_state_init(&self->chunk, key, flags); self->cv_stack_len = 0; } void blake3_hasher_init(blake3_hasher *self) { hasher_init_base(self, IV, 0); } void blake3_hasher_init_keyed(blake3_hasher *self, const uint8_t key[BLAKE3_KEY_LEN]) { uint32_t key_words[8]; load_key_words(key, key_words); hasher_init_base(self, key_words, KEYED_HASH); } void blake3_hasher_init_derive_key_raw(blake3_hasher *self, const void *context, size_t context_len) { blake3_hasher context_hasher; hasher_init_base(&context_hasher, IV, DERIVE_KEY_CONTEXT); blake3_hasher_update(&context_hasher, context, context_len); uint8_t context_key[BLAKE3_KEY_LEN]; blake3_hasher_finalize(&context_hasher, context_key, BLAKE3_KEY_LEN); uint32_t context_key_words[8]; load_key_words(context_key, context_key_words); hasher_init_base(self, context_key_words, DERIVE_KEY_MATERIAL); } void blake3_hasher_init_derive_key(blake3_hasher *self, const char *context) { blake3_hasher_init_derive_key_raw(self, context, strlen(context)); } // As described in hasher_push_cv() below, we do "lazy merging", delaying // merges until right before the next CV is about to be added. This is // different from the reference implementation. Another difference is that we // aren't always merging 1 chunk at a time. Instead, each CV might represent // any power-of-two number of chunks, as long as the smaller-above-larger stack // order is maintained. Instead of the "count the trailing 0-bits" algorithm // described in the spec, we use a "count the total number of 1-bits" variant // that doesn't require us to retain the subtree size of the CV on top of the // stack. The principle is the same: each CV that should remain in the stack is // represented by a 1-bit in the total number of chunks (or bytes) so far. INLINE void hasher_merge_cv_stack(blake3_hasher *self, uint64_t total_len) { size_t post_merge_stack_len = (size_t)popcnt(total_len); while (self->cv_stack_len > post_merge_stack_len) { uint8_t *parent_node = &self->cv_stack[(self->cv_stack_len - 2) * BLAKE3_OUT_LEN]; output_t output = parent_output(parent_node, self->key, self->chunk.flags); output_chaining_value(&output, parent_node); self->cv_stack_len -= 1; } } // In reference_impl.rs, we merge the new CV with existing CVs from the stack // before pushing it. We can do that because we know more input is coming, so // we know none of the merges are root. // // This setting is different. We want to feed as much input as possible to // compress_subtree_wide(), without setting aside anything for the chunk_state. // If the user gives us 64 KiB, we want to parallelize over all 64 KiB at once // as a single subtree, if at all possible. // // This leads to two problems: // 1) This 64 KiB input might be the only call that ever gets made to update. // In this case, the root node of the 64 KiB subtree would be the root node // of the whole tree, and it would need to be ROOT finalized. We can't // compress it until we know. // 2) This 64 KiB input might complete a larger tree, whose root node is // similarly going to be the the root of the whole tree. For example, maybe // we have 196 KiB (that is, 128 + 64) hashed so far. We can't compress the // node at the root of the 256 KiB subtree until we know how to finalize it. // // The second problem is solved with "lazy merging". That is, when we're about // to add a CV to the stack, we don't merge it with anything first, as the // reference impl does. Instead we do merges using the *previous* CV that was // added, which is sitting on top of the stack, and we put the new CV // (unmerged) on top of the stack afterwards. This guarantees that we never // merge the root node until finalize(). // // Solving the first problem requires an additional tool, // compress_subtree_to_parent_node(). That function always returns the top // *two* chaining values of the subtree it's compressing. We then do lazy // merging with each of them separately, so that the second CV will always // remain unmerged. (That also helps us support extendable output when we're // hashing an input all-at-once.) INLINE void hasher_push_cv(blake3_hasher *self, uint8_t new_cv[BLAKE3_OUT_LEN], uint64_t chunk_counter) { hasher_merge_cv_stack(self, chunk_counter); memcpy(&self->cv_stack[self->cv_stack_len * BLAKE3_OUT_LEN], new_cv, BLAKE3_OUT_LEN); self->cv_stack_len += 1; } void blake3_hasher_update(blake3_hasher *self, const void *input, size_t input_len) { // Explicitly checking for zero avoids causing UB by passing a null pointer // to memcpy. This comes up in practice with things like: // std::vector v; // blake3_hasher_update(&hasher, v.data(), v.size()); if (input_len == 0) { return; } const uint8_t *input_bytes = (const uint8_t *)input; // If we have some partial chunk bytes in the internal chunk_state, we need // to finish that chunk first. if (chunk_state_len(&self->chunk) > 0) { size_t take = BLAKE3_CHUNK_LEN - chunk_state_len(&self->chunk); if (take > input_len) { take = input_len; } chunk_state_update(&self->chunk, input_bytes, take); input_bytes += take; input_len -= take; // If we've filled the current chunk and there's more coming, finalize this // chunk and proceed. In this case we know it's not the root. if (input_len > 0) { output_t output = chunk_state_output(&self->chunk); uint8_t chunk_cv[32]; output_chaining_value(&output, chunk_cv); hasher_push_cv(self, chunk_cv, self->chunk.chunk_counter); chunk_state_reset(&self->chunk, self->key, self->chunk.chunk_counter + 1); } else { return; } } // Now the chunk_state is clear, and we have more input. If there's more than // a single chunk (so, definitely not the root chunk), hash the largest whole // subtree we can, with the full benefits of SIMD (and maybe in the future, // multi-threading) parallelism. Two restrictions: // - The subtree has to be a power-of-2 number of chunks. Only subtrees along // the right edge can be incomplete, and we don't know where the right edge // is going to be until we get to finalize(). // - The subtree must evenly divide the total number of chunks up until this // point (if total is not 0). If the current incomplete subtree is only // waiting for 1 more chunk, we can't hash a subtree of 4 chunks. We have // to complete the current subtree first. // Because we might need to break up the input to form powers of 2, or to // evenly divide what we already have, this part runs in a loop. while (input_len > BLAKE3_CHUNK_LEN) { size_t subtree_len = round_down_to_power_of_2(input_len); uint64_t count_so_far = self->chunk.chunk_counter * BLAKE3_CHUNK_LEN; // Shrink the subtree_len until it evenly divides the count so far. We know // that subtree_len itself is a power of 2, so we can use a bitmasking // trick instead of an actual remainder operation. (Note that if the caller // consistently passes power-of-2 inputs of the same size, as is hopefully // typical, this loop condition will always fail, and subtree_len will // always be the full length of the input.) // // An aside: We don't have to shrink subtree_len quite this much. For // example, if count_so_far is 1, we could pass 2 chunks to // compress_subtree_to_parent_node. Since we'll get 2 CVs back, we'll still // get the right answer in the end, and we might get to use 2-way SIMD // parallelism. The problem with this optimization, is that it gets us // stuck always hashing 2 chunks. The total number of chunks will remain // odd, and we'll never graduate to higher degrees of parallelism. See // https://github.com/BLAKE3-team/BLAKE3/issues/69. while ((((uint64_t)(subtree_len - 1)) & count_so_far) != 0) { subtree_len /= 2; } // The shrunken subtree_len might now be 1 chunk long. If so, hash that one // chunk by itself. Otherwise, compress the subtree into a pair of CVs. uint64_t subtree_chunks = subtree_len / BLAKE3_CHUNK_LEN; if (subtree_len <= BLAKE3_CHUNK_LEN) { blake3_chunk_state chunk_state; chunk_state_init(&chunk_state, self->key, self->chunk.flags); chunk_state.chunk_counter = self->chunk.chunk_counter; chunk_state_update(&chunk_state, input_bytes, subtree_len); output_t output = chunk_state_output(&chunk_state); uint8_t cv[BLAKE3_OUT_LEN]; output_chaining_value(&output, cv); hasher_push_cv(self, cv, chunk_state.chunk_counter); } else { // This is the high-performance happy path, though getting here depends // on the caller giving us a long enough input. uint8_t cv_pair[2 * BLAKE3_OUT_LEN]; compress_subtree_to_parent_node(input_bytes, subtree_len, self->key, self->chunk.chunk_counter, self->chunk.flags, cv_pair); hasher_push_cv(self, cv_pair, self->chunk.chunk_counter); hasher_push_cv(self, &cv_pair[BLAKE3_OUT_LEN], self->chunk.chunk_counter + (subtree_chunks / 2)); } self->chunk.chunk_counter += subtree_chunks; input_bytes += subtree_len; input_len -= subtree_len; } // If there's any remaining input less than a full chunk, add it to the chunk // state. In that case, also do a final merge loop to make sure the subtree // stack doesn't contain any unmerged pairs. The remaining input means we // know these merges are non-root. This merge loop isn't strictly necessary // here, because hasher_push_chunk_cv already does its own merge loop, but it // simplifies blake3_hasher_finalize below. if (input_len > 0) { chunk_state_update(&self->chunk, input_bytes, input_len); hasher_merge_cv_stack(self, self->chunk.chunk_counter); } } void blake3_hasher_finalize(const blake3_hasher *self, uint8_t *out, size_t out_len) { blake3_hasher_finalize_seek(self, 0, out, out_len); } void blake3_hasher_finalize_seek(const blake3_hasher *self, uint64_t seek, uint8_t *out, size_t out_len) { // Explicitly checking for zero avoids causing UB by passing a null pointer // to memcpy. This comes up in practice with things like: // std::vector v; // blake3_hasher_finalize(&hasher, v.data(), v.size()); if (out_len == 0) { return; } // If the subtree stack is empty, then the current chunk is the root. if (self->cv_stack_len == 0) { output_t output = chunk_state_output(&self->chunk); output_root_bytes(&output, seek, out, out_len); return; } // If there are any bytes in the chunk state, finalize that chunk and do a // roll-up merge between that chunk hash and every subtree in the stack. In // this case, the extra merge loop at the end of blake3_hasher_update // guarantees that none of the subtrees in the stack need to be merged with // each other first. Otherwise, if there are no bytes in the chunk state, // then the top of the stack is a chunk hash, and we start the merge from // that. output_t output; size_t cvs_remaining; if (chunk_state_len(&self->chunk) > 0) { cvs_remaining = self->cv_stack_len; output = chunk_state_output(&self->chunk); } else { // There are always at least 2 CVs in the stack in this case. cvs_remaining = self->cv_stack_len - 2; output = parent_output(&self->cv_stack[cvs_remaining * 32], self->key, self->chunk.flags); } while (cvs_remaining > 0) { cvs_remaining -= 1; uint8_t parent_block[BLAKE3_BLOCK_LEN]; memcpy(parent_block, &self->cv_stack[cvs_remaining * 32], 32); output_chaining_value(&output, &parent_block[32]); output = parent_output(parent_block, self->key, self->chunk.flags); } output_root_bytes(&output, seek, out, out_len); } void blake3_hasher_reset(blake3_hasher *self) { chunk_state_reset(&self->chunk, self->key, 0); self->cv_stack_len = 0; } cryptokit-release119/src/blake3.h000066400000000000000000000037011453705265000170700ustar00rootroot00000000000000#ifndef BLAKE3_H #define BLAKE3_H #include #include #ifdef __cplusplus extern "C" { #endif #define BLAKE3_VERSION_STRING "1.3.1" #define BLAKE3_KEY_LEN 32 #define BLAKE3_OUT_LEN 32 #define BLAKE3_BLOCK_LEN 64 #define BLAKE3_CHUNK_LEN 1024 #define BLAKE3_MAX_DEPTH 54 // This struct is a private implementation detail. It has to be here because // it's part of blake3_hasher below. typedef struct { uint32_t cv[8]; uint64_t chunk_counter; uint8_t buf[BLAKE3_BLOCK_LEN]; uint8_t buf_len; uint8_t blocks_compressed; uint8_t flags; } blake3_chunk_state; typedef struct { uint32_t key[8]; blake3_chunk_state chunk; uint8_t cv_stack_len; // The stack size is MAX_DEPTH + 1 because we do lazy merging. For example, // with 7 chunks, we have 3 entries in the stack. Adding an 8th chunk // requires a 4th entry, rather than merging everything down to 1, because we // don't know whether more input is coming. This is different from how the // reference implementation does things. uint8_t cv_stack[(BLAKE3_MAX_DEPTH + 1) * BLAKE3_OUT_LEN]; } blake3_hasher; const char *blake3_version(void); void blake3_hasher_init(blake3_hasher *self); void blake3_hasher_init_keyed(blake3_hasher *self, const uint8_t key[BLAKE3_KEY_LEN]); void blake3_hasher_init_derive_key(blake3_hasher *self, const char *context); void blake3_hasher_init_derive_key_raw(blake3_hasher *self, const void *context, size_t context_len); void blake3_hasher_update(blake3_hasher *self, const void *input, size_t input_len); void blake3_hasher_finalize(const blake3_hasher *self, uint8_t *out, size_t out_len); void blake3_hasher_finalize_seek(const blake3_hasher *self, uint64_t seek, uint8_t *out, size_t out_len); void blake3_hasher_reset(blake3_hasher *self); #ifdef __cplusplus } #endif #endif /* BLAKE3_H */ cryptokit-release119/src/blake3_dispatch.c000066400000000000000000000165741453705265000207560ustar00rootroot00000000000000#include #include #include #include "blake3_impl.h" #if defined(IS_X86) #if defined(_MSC_VER) #include #elif defined(__GNUC__) #include #else #undef IS_X86 /* Unimplemented! */ #endif #endif #define MAYBE_UNUSED(x) (void)((x)) #if defined(IS_X86) static uint64_t xgetbv(void) { #if defined(_MSC_VER) return _xgetbv(0); #else uint32_t eax = 0, edx = 0; __asm__ __volatile__("xgetbv\n" : "=a"(eax), "=d"(edx) : "c"(0)); return ((uint64_t)edx << 32) | eax; #endif } static void cpuid(uint32_t out[4], uint32_t id) { #if defined(_MSC_VER) __cpuid((int *)out, id); #elif defined(__i386__) || defined(_M_IX86) __asm__ __volatile__("movl %%ebx, %1\n" "cpuid\n" "xchgl %1, %%ebx\n" : "=a"(out[0]), "=r"(out[1]), "=c"(out[2]), "=d"(out[3]) : "a"(id)); #else __asm__ __volatile__("cpuid\n" : "=a"(out[0]), "=b"(out[1]), "=c"(out[2]), "=d"(out[3]) : "a"(id)); #endif } static void cpuidex(uint32_t out[4], uint32_t id, uint32_t sid) { #if defined(_MSC_VER) __cpuidex((int *)out, id, sid); #elif defined(__i386__) || defined(_M_IX86) __asm__ __volatile__("movl %%ebx, %1\n" "cpuid\n" "xchgl %1, %%ebx\n" : "=a"(out[0]), "=r"(out[1]), "=c"(out[2]), "=d"(out[3]) : "a"(id), "c"(sid)); #else __asm__ __volatile__("cpuid\n" : "=a"(out[0]), "=b"(out[1]), "=c"(out[2]), "=d"(out[3]) : "a"(id), "c"(sid)); #endif } #endif enum cpu_feature { SSE2 = 1 << 0, SSSE3 = 1 << 1, SSE41 = 1 << 2, AVX = 1 << 3, AVX2 = 1 << 4, AVX512F = 1 << 5, AVX512VL = 1 << 6, /* ... */ UNDEFINED = 1 << 30 }; #if !defined(BLAKE3_TESTING) static /* Allow the variable to be controlled manually for testing */ #endif enum cpu_feature g_cpu_features = UNDEFINED; #if !defined(BLAKE3_TESTING) static #endif enum cpu_feature get_cpu_features(void) { if (g_cpu_features != UNDEFINED) { return g_cpu_features; } else { #if defined(IS_X86) uint32_t regs[4] = {0}; uint32_t *eax = ®s[0], *ebx = ®s[1], *ecx = ®s[2], *edx = ®s[3]; (void)edx; enum cpu_feature features = 0; cpuid(regs, 0); const int max_id = *eax; cpuid(regs, 1); #if defined(__amd64__) || defined(_M_X64) features |= SSE2; #else if (*edx & (1UL << 26)) features |= SSE2; #endif if (*ecx & (1UL << 0)) features |= SSSE3; if (*ecx & (1UL << 19)) features |= SSE41; if (*ecx & (1UL << 27)) { // OSXSAVE const uint64_t mask = xgetbv(); if ((mask & 6) == 6) { // SSE and AVX states if (*ecx & (1UL << 28)) features |= AVX; if (max_id >= 7) { cpuidex(regs, 7, 0); if (*ebx & (1UL << 5)) features |= AVX2; if ((mask & 224) == 224) { // Opmask, ZMM_Hi256, Hi16_Zmm if (*ebx & (1UL << 31)) features |= AVX512VL; if (*ebx & (1UL << 16)) features |= AVX512F; } } } } g_cpu_features = features; return features; #else /* How to detect NEON? */ return 0; #endif } } void blake3_compress_in_place(uint32_t cv[8], const uint8_t block[BLAKE3_BLOCK_LEN], uint8_t block_len, uint64_t counter, uint8_t flags) { #if defined(IS_X86) const enum cpu_feature features = get_cpu_features(); MAYBE_UNUSED(features); #if !defined(BLAKE3_NO_AVX512) if (features & AVX512VL) { blake3_compress_in_place_avx512(cv, block, block_len, counter, flags); return; } #endif #if !defined(BLAKE3_NO_SSE41) if (features & SSE41) { blake3_compress_in_place_sse41(cv, block, block_len, counter, flags); return; } #endif #if !defined(BLAKE3_NO_SSE2) if (features & SSE2) { blake3_compress_in_place_sse2(cv, block, block_len, counter, flags); return; } #endif #endif blake3_compress_in_place_portable(cv, block, block_len, counter, flags); } void blake3_compress_xof(const uint32_t cv[8], const uint8_t block[BLAKE3_BLOCK_LEN], uint8_t block_len, uint64_t counter, uint8_t flags, uint8_t out[64]) { #if defined(IS_X86) const enum cpu_feature features = get_cpu_features(); MAYBE_UNUSED(features); #if !defined(BLAKE3_NO_AVX512) if (features & AVX512VL) { blake3_compress_xof_avx512(cv, block, block_len, counter, flags, out); return; } #endif #if !defined(BLAKE3_NO_SSE41) if (features & SSE41) { blake3_compress_xof_sse41(cv, block, block_len, counter, flags, out); return; } #endif #if !defined(BLAKE3_NO_SSE2) if (features & SSE2) { blake3_compress_xof_sse2(cv, block, block_len, counter, flags, out); return; } #endif #endif blake3_compress_xof_portable(cv, block, block_len, counter, flags, out); } void blake3_hash_many(const uint8_t *const *inputs, size_t num_inputs, size_t blocks, const uint32_t key[8], uint64_t counter, bool increment_counter, uint8_t flags, uint8_t flags_start, uint8_t flags_end, uint8_t *out) { #if defined(IS_X86) const enum cpu_feature features = get_cpu_features(); MAYBE_UNUSED(features); #if !defined(BLAKE3_NO_AVX512) if ((features & (AVX512F|AVX512VL)) == (AVX512F|AVX512VL)) { blake3_hash_many_avx512(inputs, num_inputs, blocks, key, counter, increment_counter, flags, flags_start, flags_end, out); return; } #endif #if !defined(BLAKE3_NO_AVX2) if (features & AVX2) { blake3_hash_many_avx2(inputs, num_inputs, blocks, key, counter, increment_counter, flags, flags_start, flags_end, out); return; } #endif #if !defined(BLAKE3_NO_SSE41) if (features & SSE41) { blake3_hash_many_sse41(inputs, num_inputs, blocks, key, counter, increment_counter, flags, flags_start, flags_end, out); return; } #endif #if !defined(BLAKE3_NO_SSE2) if (features & SSE2) { blake3_hash_many_sse2(inputs, num_inputs, blocks, key, counter, increment_counter, flags, flags_start, flags_end, out); return; } #endif #endif #if BLAKE3_USE_NEON == 1 blake3_hash_many_neon(inputs, num_inputs, blocks, key, counter, increment_counter, flags, flags_start, flags_end, out); return; #endif blake3_hash_many_portable(inputs, num_inputs, blocks, key, counter, increment_counter, flags, flags_start, flags_end, out); } // The dynamically detected SIMD degree of the current platform. size_t blake3_simd_degree(void) { #if defined(IS_X86) const enum cpu_feature features = get_cpu_features(); MAYBE_UNUSED(features); #if !defined(BLAKE3_NO_AVX512) if ((features & (AVX512F|AVX512VL)) == (AVX512F|AVX512VL)) { return 16; } #endif #if !defined(BLAKE3_NO_AVX2) if (features & AVX2) { return 8; } #endif #if !defined(BLAKE3_NO_SSE41) if (features & SSE41) { return 4; } #endif #if !defined(BLAKE3_NO_SSE2) if (features & SSE2) { return 4; } #endif #endif #if BLAKE3_USE_NEON == 1 return 4; #endif return 1; } cryptokit-release119/src/blake3_impl.h000066400000000000000000000237241453705265000201200ustar00rootroot00000000000000#ifndef BLAKE3_IMPL_H #define BLAKE3_IMPL_H #include #include #include #include #include #include "blake3.h" // internal flags enum blake3_flags { CHUNK_START = 1 << 0, CHUNK_END = 1 << 1, PARENT = 1 << 2, ROOT = 1 << 3, KEYED_HASH = 1 << 4, DERIVE_KEY_CONTEXT = 1 << 5, DERIVE_KEY_MATERIAL = 1 << 6, }; // This C implementation tries to support recent versions of GCC, Clang, and // MSVC. #if defined(_MSC_VER) #define INLINE static __forceinline #else #define INLINE static inline __attribute__((always_inline)) #endif #if defined(__x86_64__) || defined(_M_X64) #define IS_X86 #define IS_X86_64 #endif #if defined(__i386__) || defined(_M_IX86) #define IS_X86 #define IS_X86_32 #endif #if defined(__aarch64__) || defined(_M_ARM64) #define IS_AARCH64 #endif #if defined(IS_X86) #if defined(_MSC_VER) #include #endif #endif #if !defined(BLAKE3_USE_NEON) // If BLAKE3_USE_NEON not manually set, autodetect based on AArch64ness #if defined(IS_AARCH64) #define BLAKE3_USE_NEON 1 #else #define BLAKE3_USE_NEON 0 #endif #endif #if defined(IS_X86) #define MAX_SIMD_DEGREE 16 #elif BLAKE3_USE_NEON == 1 #define MAX_SIMD_DEGREE 4 #else #define MAX_SIMD_DEGREE 1 #endif // There are some places where we want a static size that's equal to the // MAX_SIMD_DEGREE, but also at least 2. #define MAX_SIMD_DEGREE_OR_2 (MAX_SIMD_DEGREE > 2 ? MAX_SIMD_DEGREE : 2) static const uint32_t IV[8] = {0x6A09E667UL, 0xBB67AE85UL, 0x3C6EF372UL, 0xA54FF53AUL, 0x510E527FUL, 0x9B05688CUL, 0x1F83D9ABUL, 0x5BE0CD19UL}; static const uint8_t MSG_SCHEDULE[7][16] = { {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, {2, 6, 3, 10, 7, 0, 4, 13, 1, 11, 12, 5, 9, 14, 15, 8}, {3, 4, 10, 12, 13, 2, 7, 14, 6, 5, 9, 0, 11, 15, 8, 1}, {10, 7, 12, 9, 14, 3, 13, 15, 4, 0, 11, 2, 5, 8, 1, 6}, {12, 13, 9, 11, 15, 10, 14, 8, 7, 2, 5, 3, 0, 1, 6, 4}, {9, 14, 11, 5, 8, 12, 15, 1, 13, 3, 0, 10, 2, 6, 4, 7}, {11, 15, 5, 0, 1, 9, 8, 6, 14, 10, 2, 12, 3, 4, 7, 13}, }; /* Find index of the highest set bit */ /* x is assumed to be nonzero. */ static unsigned int highest_one(uint64_t x) { #if defined(__GNUC__) || defined(__clang__) return 63 ^ __builtin_clzll(x); #elif defined(_MSC_VER) && defined(IS_X86_64) unsigned long index; _BitScanReverse64(&index, x); return index; #elif defined(_MSC_VER) && defined(IS_X86_32) if(x >> 32) { unsigned long index; _BitScanReverse(&index, (unsigned long)(x >> 32)); return 32 + index; } else { unsigned long index; _BitScanReverse(&index, (unsigned long)x); return index; } #else unsigned int c = 0; if(x & 0xffffffff00000000ULL) { x >>= 32; c += 32; } if(x & 0x00000000ffff0000ULL) { x >>= 16; c += 16; } if(x & 0x000000000000ff00ULL) { x >>= 8; c += 8; } if(x & 0x00000000000000f0ULL) { x >>= 4; c += 4; } if(x & 0x000000000000000cULL) { x >>= 2; c += 2; } if(x & 0x0000000000000002ULL) { c += 1; } return c; #endif } // Count the number of 1 bits. INLINE unsigned int popcnt(uint64_t x) { #if defined(__GNUC__) || defined(__clang__) return __builtin_popcountll(x); #else unsigned int count = 0; while (x != 0) { count += 1; x &= x - 1; } return count; #endif } // Largest power of two less than or equal to x. As a special case, returns 1 // when x is 0. INLINE uint64_t round_down_to_power_of_2(uint64_t x) { return 1ULL << highest_one(x | 1); } INLINE uint32_t counter_low(uint64_t counter) { return (uint32_t)counter; } INLINE uint32_t counter_high(uint64_t counter) { return (uint32_t)(counter >> 32); } INLINE uint32_t load32(const void *src) { const uint8_t *p = (const uint8_t *)src; return ((uint32_t)(p[0]) << 0) | ((uint32_t)(p[1]) << 8) | ((uint32_t)(p[2]) << 16) | ((uint32_t)(p[3]) << 24); } INLINE void load_key_words(const uint8_t key[BLAKE3_KEY_LEN], uint32_t key_words[8]) { key_words[0] = load32(&key[0 * 4]); key_words[1] = load32(&key[1 * 4]); key_words[2] = load32(&key[2 * 4]); key_words[3] = load32(&key[3 * 4]); key_words[4] = load32(&key[4 * 4]); key_words[5] = load32(&key[5 * 4]); key_words[6] = load32(&key[6 * 4]); key_words[7] = load32(&key[7 * 4]); } INLINE void store32(void *dst, uint32_t w) { uint8_t *p = (uint8_t *)dst; p[0] = (uint8_t)(w >> 0); p[1] = (uint8_t)(w >> 8); p[2] = (uint8_t)(w >> 16); p[3] = (uint8_t)(w >> 24); } INLINE void store_cv_words(uint8_t bytes_out[32], uint32_t cv_words[8]) { store32(&bytes_out[0 * 4], cv_words[0]); store32(&bytes_out[1 * 4], cv_words[1]); store32(&bytes_out[2 * 4], cv_words[2]); store32(&bytes_out[3 * 4], cv_words[3]); store32(&bytes_out[4 * 4], cv_words[4]); store32(&bytes_out[5 * 4], cv_words[5]); store32(&bytes_out[6 * 4], cv_words[6]); store32(&bytes_out[7 * 4], cv_words[7]); } void blake3_compress_in_place(uint32_t cv[8], const uint8_t block[BLAKE3_BLOCK_LEN], uint8_t block_len, uint64_t counter, uint8_t flags); void blake3_compress_xof(const uint32_t cv[8], const uint8_t block[BLAKE3_BLOCK_LEN], uint8_t block_len, uint64_t counter, uint8_t flags, uint8_t out[64]); void blake3_hash_many(const uint8_t *const *inputs, size_t num_inputs, size_t blocks, const uint32_t key[8], uint64_t counter, bool increment_counter, uint8_t flags, uint8_t flags_start, uint8_t flags_end, uint8_t *out); size_t blake3_simd_degree(void); // Declarations for implementation-specific functions. void blake3_compress_in_place_portable(uint32_t cv[8], const uint8_t block[BLAKE3_BLOCK_LEN], uint8_t block_len, uint64_t counter, uint8_t flags); void blake3_compress_xof_portable(const uint32_t cv[8], const uint8_t block[BLAKE3_BLOCK_LEN], uint8_t block_len, uint64_t counter, uint8_t flags, uint8_t out[64]); void blake3_hash_many_portable(const uint8_t *const *inputs, size_t num_inputs, size_t blocks, const uint32_t key[8], uint64_t counter, bool increment_counter, uint8_t flags, uint8_t flags_start, uint8_t flags_end, uint8_t *out); #if defined(IS_X86) #if !defined(BLAKE3_NO_SSE2) void blake3_compress_in_place_sse2(uint32_t cv[8], const uint8_t block[BLAKE3_BLOCK_LEN], uint8_t block_len, uint64_t counter, uint8_t flags); void blake3_compress_xof_sse2(const uint32_t cv[8], const uint8_t block[BLAKE3_BLOCK_LEN], uint8_t block_len, uint64_t counter, uint8_t flags, uint8_t out[64]); void blake3_hash_many_sse2(const uint8_t *const *inputs, size_t num_inputs, size_t blocks, const uint32_t key[8], uint64_t counter, bool increment_counter, uint8_t flags, uint8_t flags_start, uint8_t flags_end, uint8_t *out); #endif #if !defined(BLAKE3_NO_SSE41) void blake3_compress_in_place_sse41(uint32_t cv[8], const uint8_t block[BLAKE3_BLOCK_LEN], uint8_t block_len, uint64_t counter, uint8_t flags); void blake3_compress_xof_sse41(const uint32_t cv[8], const uint8_t block[BLAKE3_BLOCK_LEN], uint8_t block_len, uint64_t counter, uint8_t flags, uint8_t out[64]); void blake3_hash_many_sse41(const uint8_t *const *inputs, size_t num_inputs, size_t blocks, const uint32_t key[8], uint64_t counter, bool increment_counter, uint8_t flags, uint8_t flags_start, uint8_t flags_end, uint8_t *out); #endif #if !defined(BLAKE3_NO_AVX2) void blake3_hash_many_avx2(const uint8_t *const *inputs, size_t num_inputs, size_t blocks, const uint32_t key[8], uint64_t counter, bool increment_counter, uint8_t flags, uint8_t flags_start, uint8_t flags_end, uint8_t *out); #endif #if !defined(BLAKE3_NO_AVX512) void blake3_compress_in_place_avx512(uint32_t cv[8], const uint8_t block[BLAKE3_BLOCK_LEN], uint8_t block_len, uint64_t counter, uint8_t flags); void blake3_compress_xof_avx512(const uint32_t cv[8], const uint8_t block[BLAKE3_BLOCK_LEN], uint8_t block_len, uint64_t counter, uint8_t flags, uint8_t out[64]); void blake3_hash_many_avx512(const uint8_t *const *inputs, size_t num_inputs, size_t blocks, const uint32_t key[8], uint64_t counter, bool increment_counter, uint8_t flags, uint8_t flags_start, uint8_t flags_end, uint8_t *out); #endif #endif #if BLAKE3_USE_NEON == 1 void blake3_hash_many_neon(const uint8_t *const *inputs, size_t num_inputs, size_t blocks, const uint32_t key[8], uint64_t counter, bool increment_counter, uint8_t flags, uint8_t flags_start, uint8_t flags_end, uint8_t *out); #endif #endif /* BLAKE3_IMPL_H */ cryptokit-release119/src/blake3_portable.c000066400000000000000000000134011453705265000207510ustar00rootroot00000000000000#include "blake3_impl.h" #include INLINE uint32_t rotr32(uint32_t w, uint32_t c) { return (w >> c) | (w << (32 - c)); } INLINE void g(uint32_t *state, size_t a, size_t b, size_t c, size_t d, uint32_t x, uint32_t y) { state[a] = state[a] + state[b] + x; state[d] = rotr32(state[d] ^ state[a], 16); state[c] = state[c] + state[d]; state[b] = rotr32(state[b] ^ state[c], 12); state[a] = state[a] + state[b] + y; state[d] = rotr32(state[d] ^ state[a], 8); state[c] = state[c] + state[d]; state[b] = rotr32(state[b] ^ state[c], 7); } INLINE void round_fn(uint32_t state[16], const uint32_t *msg, size_t round) { // Select the message schedule based on the round. const uint8_t *schedule = MSG_SCHEDULE[round]; // Mix the columns. g(state, 0, 4, 8, 12, msg[schedule[0]], msg[schedule[1]]); g(state, 1, 5, 9, 13, msg[schedule[2]], msg[schedule[3]]); g(state, 2, 6, 10, 14, msg[schedule[4]], msg[schedule[5]]); g(state, 3, 7, 11, 15, msg[schedule[6]], msg[schedule[7]]); // Mix the rows. g(state, 0, 5, 10, 15, msg[schedule[8]], msg[schedule[9]]); g(state, 1, 6, 11, 12, msg[schedule[10]], msg[schedule[11]]); g(state, 2, 7, 8, 13, msg[schedule[12]], msg[schedule[13]]); g(state, 3, 4, 9, 14, msg[schedule[14]], msg[schedule[15]]); } INLINE void compress_pre(uint32_t state[16], const uint32_t cv[8], const uint8_t block[BLAKE3_BLOCK_LEN], uint8_t block_len, uint64_t counter, uint8_t flags) { uint32_t block_words[16]; block_words[0] = load32(block + 4 * 0); block_words[1] = load32(block + 4 * 1); block_words[2] = load32(block + 4 * 2); block_words[3] = load32(block + 4 * 3); block_words[4] = load32(block + 4 * 4); block_words[5] = load32(block + 4 * 5); block_words[6] = load32(block + 4 * 6); block_words[7] = load32(block + 4 * 7); block_words[8] = load32(block + 4 * 8); block_words[9] = load32(block + 4 * 9); block_words[10] = load32(block + 4 * 10); block_words[11] = load32(block + 4 * 11); block_words[12] = load32(block + 4 * 12); block_words[13] = load32(block + 4 * 13); block_words[14] = load32(block + 4 * 14); block_words[15] = load32(block + 4 * 15); state[0] = cv[0]; state[1] = cv[1]; state[2] = cv[2]; state[3] = cv[3]; state[4] = cv[4]; state[5] = cv[5]; state[6] = cv[6]; state[7] = cv[7]; state[8] = IV[0]; state[9] = IV[1]; state[10] = IV[2]; state[11] = IV[3]; state[12] = counter_low(counter); state[13] = counter_high(counter); state[14] = (uint32_t)block_len; state[15] = (uint32_t)flags; round_fn(state, &block_words[0], 0); round_fn(state, &block_words[0], 1); round_fn(state, &block_words[0], 2); round_fn(state, &block_words[0], 3); round_fn(state, &block_words[0], 4); round_fn(state, &block_words[0], 5); round_fn(state, &block_words[0], 6); } void blake3_compress_in_place_portable(uint32_t cv[8], const uint8_t block[BLAKE3_BLOCK_LEN], uint8_t block_len, uint64_t counter, uint8_t flags) { uint32_t state[16]; compress_pre(state, cv, block, block_len, counter, flags); cv[0] = state[0] ^ state[8]; cv[1] = state[1] ^ state[9]; cv[2] = state[2] ^ state[10]; cv[3] = state[3] ^ state[11]; cv[4] = state[4] ^ state[12]; cv[5] = state[5] ^ state[13]; cv[6] = state[6] ^ state[14]; cv[7] = state[7] ^ state[15]; } void blake3_compress_xof_portable(const uint32_t cv[8], const uint8_t block[BLAKE3_BLOCK_LEN], uint8_t block_len, uint64_t counter, uint8_t flags, uint8_t out[64]) { uint32_t state[16]; compress_pre(state, cv, block, block_len, counter, flags); store32(&out[0 * 4], state[0] ^ state[8]); store32(&out[1 * 4], state[1] ^ state[9]); store32(&out[2 * 4], state[2] ^ state[10]); store32(&out[3 * 4], state[3] ^ state[11]); store32(&out[4 * 4], state[4] ^ state[12]); store32(&out[5 * 4], state[5] ^ state[13]); store32(&out[6 * 4], state[6] ^ state[14]); store32(&out[7 * 4], state[7] ^ state[15]); store32(&out[8 * 4], state[8] ^ cv[0]); store32(&out[9 * 4], state[9] ^ cv[1]); store32(&out[10 * 4], state[10] ^ cv[2]); store32(&out[11 * 4], state[11] ^ cv[3]); store32(&out[12 * 4], state[12] ^ cv[4]); store32(&out[13 * 4], state[13] ^ cv[5]); store32(&out[14 * 4], state[14] ^ cv[6]); store32(&out[15 * 4], state[15] ^ cv[7]); } INLINE void hash_one_portable(const uint8_t *input, size_t blocks, const uint32_t key[8], uint64_t counter, uint8_t flags, uint8_t flags_start, uint8_t flags_end, uint8_t out[BLAKE3_OUT_LEN]) { uint32_t cv[8]; memcpy(cv, key, BLAKE3_KEY_LEN); uint8_t block_flags = flags | flags_start; while (blocks > 0) { if (blocks == 1) { block_flags |= flags_end; } blake3_compress_in_place_portable(cv, input, BLAKE3_BLOCK_LEN, counter, block_flags); input = &input[BLAKE3_BLOCK_LEN]; blocks -= 1; block_flags = flags; } store_cv_words(out, cv); } void blake3_hash_many_portable(const uint8_t *const *inputs, size_t num_inputs, size_t blocks, const uint32_t key[8], uint64_t counter, bool increment_counter, uint8_t flags, uint8_t flags_start, uint8_t flags_end, uint8_t *out) { while (num_inputs > 0) { hash_one_portable(inputs[0], blocks, key, counter, flags, flags_start, flags_end, out); if (increment_counter) { counter += 1; } inputs += 1; num_inputs -= 1; out = &out[BLAKE3_OUT_LEN]; } } cryptokit-release119/src/blowfish.c000066400000000000000000000527141453705265000175470ustar00rootroot00000000000000/* blowfish.c: C implementation of the Blowfish algorithm. Copyright (C) 1997 by Paul Kocher This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA COMMENTS ON USING THIS CODE: Normal usage is as follows: [1] Allocate a BLOWFISH_CTX. (It may be too big for the stack.) [2] Call Blowfish_Init with a pointer to your BLOWFISH_CTX, a pointer to the key, and the number of bytes in the key. [3] To encrypt a 64-bit block, call Blowfish_Encrypt with a pointer to BLOWFISH_CTX, a pointer to the 32-bit left half of the plaintext and a pointer to the 32-bit right half. The plaintext will be overwritten with the ciphertext. [4] Decryption is the same as encryption except that the plaintext and ciphertext are reversed. Warning #1: The code does not check key lengths. (Caveat encryptor.) Warning #2: Beware that Blowfish keys repeat such that "ab" = "abab". Warning #3: It is normally a good idea to zeroize the BLOWFISH_CTX before freeing it. Warning #4: Endianness conversions are the responsibility of the caller. (To encrypt bytes on a little-endian platforms, you'll probably want to swap bytes around instead of just casting.) Warning #5: Make sure to use a reasonable mode of operation for your application. (If you don't know what CBC mode is, see Warning #7.) Warning #6: This code is susceptible to timing attacks. Warning #7: Security engineering is risky and non-intuitive. Have someone check your work. If you don't know what you are doing, get help. This is code is fast enough for most applications, but is not optimized for speed. If you require this code under a license other than LGPL, please ask. (I can be located using your favorite search engine.) Unfortunately, I do not have time to provide unpaid support for everyone who uses this code. -- Paul Kocher Modifications by Xavier.Leroy@inria.fr, 2005. (Marked "XL".) - Speed improvements - Endianness handling. */ #include #include "blowfish.h" #define N 16 static const u32 ORIG_P[16 + 2] = { 0x243F6A88L, 0x85A308D3L, 0x13198A2EL, 0x03707344L, 0xA4093822L, 0x299F31D0L, 0x082EFA98L, 0xEC4E6C89L, 0x452821E6L, 0x38D01377L, 0xBE5466CFL, 0x34E90C6CL, 0xC0AC29B7L, 0xC97C50DDL, 0x3F84D5B5L, 0xB5470917L, 0x9216D5D9L, 0x8979FB1BL }; static const u32 ORIG_S[4][256] = { { 0xD1310BA6L, 0x98DFB5ACL, 0x2FFD72DBL, 0xD01ADFB7L, 0xB8E1AFEDL, 0x6A267E96L, 0xBA7C9045L, 0xF12C7F99L, 0x24A19947L, 0xB3916CF7L, 0x0801F2E2L, 0x858EFC16L, 0x636920D8L, 0x71574E69L, 0xA458FEA3L, 0xF4933D7EL, 0x0D95748FL, 0x728EB658L, 0x718BCD58L, 0x82154AEEL, 0x7B54A41DL, 0xC25A59B5L, 0x9C30D539L, 0x2AF26013L, 0xC5D1B023L, 0x286085F0L, 0xCA417918L, 0xB8DB38EFL, 0x8E79DCB0L, 0x603A180EL, 0x6C9E0E8BL, 0xB01E8A3EL, 0xD71577C1L, 0xBD314B27L, 0x78AF2FDAL, 0x55605C60L, 0xE65525F3L, 0xAA55AB94L, 0x57489862L, 0x63E81440L, 0x55CA396AL, 0x2AAB10B6L, 0xB4CC5C34L, 0x1141E8CEL, 0xA15486AFL, 0x7C72E993L, 0xB3EE1411L, 0x636FBC2AL, 0x2BA9C55DL, 0x741831F6L, 0xCE5C3E16L, 0x9B87931EL, 0xAFD6BA33L, 0x6C24CF5CL, 0x7A325381L, 0x28958677L, 0x3B8F4898L, 0x6B4BB9AFL, 0xC4BFE81BL, 0x66282193L, 0x61D809CCL, 0xFB21A991L, 0x487CAC60L, 0x5DEC8032L, 0xEF845D5DL, 0xE98575B1L, 0xDC262302L, 0xEB651B88L, 0x23893E81L, 0xD396ACC5L, 0x0F6D6FF3L, 0x83F44239L, 0x2E0B4482L, 0xA4842004L, 0x69C8F04AL, 0x9E1F9B5EL, 0x21C66842L, 0xF6E96C9AL, 0x670C9C61L, 0xABD388F0L, 0x6A51A0D2L, 0xD8542F68L, 0x960FA728L, 0xAB5133A3L, 0x6EEF0B6CL, 0x137A3BE4L, 0xBA3BF050L, 0x7EFB2A98L, 0xA1F1651DL, 0x39AF0176L, 0x66CA593EL, 0x82430E88L, 0x8CEE8619L, 0x456F9FB4L, 0x7D84A5C3L, 0x3B8B5EBEL, 0xE06F75D8L, 0x85C12073L, 0x401A449FL, 0x56C16AA6L, 0x4ED3AA62L, 0x363F7706L, 0x1BFEDF72L, 0x429B023DL, 0x37D0D724L, 0xD00A1248L, 0xDB0FEAD3L, 0x49F1C09BL, 0x075372C9L, 0x80991B7BL, 0x25D479D8L, 0xF6E8DEF7L, 0xE3FE501AL, 0xB6794C3BL, 0x976CE0BDL, 0x04C006BAL, 0xC1A94FB6L, 0x409F60C4L, 0x5E5C9EC2L, 0x196A2463L, 0x68FB6FAFL, 0x3E6C53B5L, 0x1339B2EBL, 0x3B52EC6FL, 0x6DFC511FL, 0x9B30952CL, 0xCC814544L, 0xAF5EBD09L, 0xBEE3D004L, 0xDE334AFDL, 0x660F2807L, 0x192E4BB3L, 0xC0CBA857L, 0x45C8740FL, 0xD20B5F39L, 0xB9D3FBDBL, 0x5579C0BDL, 0x1A60320AL, 0xD6A100C6L, 0x402C7279L, 0x679F25FEL, 0xFB1FA3CCL, 0x8EA5E9F8L, 0xDB3222F8L, 0x3C7516DFL, 0xFD616B15L, 0x2F501EC8L, 0xAD0552ABL, 0x323DB5FAL, 0xFD238760L, 0x53317B48L, 0x3E00DF82L, 0x9E5C57BBL, 0xCA6F8CA0L, 0x1A87562EL, 0xDF1769DBL, 0xD542A8F6L, 0x287EFFC3L, 0xAC6732C6L, 0x8C4F5573L, 0x695B27B0L, 0xBBCA58C8L, 0xE1FFA35DL, 0xB8F011A0L, 0x10FA3D98L, 0xFD2183B8L, 0x4AFCB56CL, 0x2DD1D35BL, 0x9A53E479L, 0xB6F84565L, 0xD28E49BCL, 0x4BFB9790L, 0xE1DDF2DAL, 0xA4CB7E33L, 0x62FB1341L, 0xCEE4C6E8L, 0xEF20CADAL, 0x36774C01L, 0xD07E9EFEL, 0x2BF11FB4L, 0x95DBDA4DL, 0xAE909198L, 0xEAAD8E71L, 0x6B93D5A0L, 0xD08ED1D0L, 0xAFC725E0L, 0x8E3C5B2FL, 0x8E7594B7L, 0x8FF6E2FBL, 0xF2122B64L, 0x8888B812L, 0x900DF01CL, 0x4FAD5EA0L, 0x688FC31CL, 0xD1CFF191L, 0xB3A8C1ADL, 0x2F2F2218L, 0xBE0E1777L, 0xEA752DFEL, 0x8B021FA1L, 0xE5A0CC0FL, 0xB56F74E8L, 0x18ACF3D6L, 0xCE89E299L, 0xB4A84FE0L, 0xFD13E0B7L, 0x7CC43B81L, 0xD2ADA8D9L, 0x165FA266L, 0x80957705L, 0x93CC7314L, 0x211A1477L, 0xE6AD2065L, 0x77B5FA86L, 0xC75442F5L, 0xFB9D35CFL, 0xEBCDAF0CL, 0x7B3E89A0L, 0xD6411BD3L, 0xAE1E7E49L, 0x00250E2DL, 0x2071B35EL, 0x226800BBL, 0x57B8E0AFL, 0x2464369BL, 0xF009B91EL, 0x5563911DL, 0x59DFA6AAL, 0x78C14389L, 0xD95A537FL, 0x207D5BA2L, 0x02E5B9C5L, 0x83260376L, 0x6295CFA9L, 0x11C81968L, 0x4E734A41L, 0xB3472DCAL, 0x7B14A94AL, 0x1B510052L, 0x9A532915L, 0xD60F573FL, 0xBC9BC6E4L, 0x2B60A476L, 0x81E67400L, 0x08BA6FB5L, 0x571BE91FL, 0xF296EC6BL, 0x2A0DD915L, 0xB6636521L, 0xE7B9F9B6L, 0xFF34052EL, 0xC5855664L, 0x53B02D5DL, 0xA99F8FA1L, 0x08BA4799L, 0x6E85076AL }, { 0x4B7A70E9L, 0xB5B32944L, 0xDB75092EL, 0xC4192623L, 0xAD6EA6B0L, 0x49A7DF7DL, 0x9CEE60B8L, 0x8FEDB266L, 0xECAA8C71L, 0x699A17FFL, 0x5664526CL, 0xC2B19EE1L, 0x193602A5L, 0x75094C29L, 0xA0591340L, 0xE4183A3EL, 0x3F54989AL, 0x5B429D65L, 0x6B8FE4D6L, 0x99F73FD6L, 0xA1D29C07L, 0xEFE830F5L, 0x4D2D38E6L, 0xF0255DC1L, 0x4CDD2086L, 0x8470EB26L, 0x6382E9C6L, 0x021ECC5EL, 0x09686B3FL, 0x3EBAEFC9L, 0x3C971814L, 0x6B6A70A1L, 0x687F3584L, 0x52A0E286L, 0xB79C5305L, 0xAA500737L, 0x3E07841CL, 0x7FDEAE5CL, 0x8E7D44ECL, 0x5716F2B8L, 0xB03ADA37L, 0xF0500C0DL, 0xF01C1F04L, 0x0200B3FFL, 0xAE0CF51AL, 0x3CB574B2L, 0x25837A58L, 0xDC0921BDL, 0xD19113F9L, 0x7CA92FF6L, 0x94324773L, 0x22F54701L, 0x3AE5E581L, 0x37C2DADCL, 0xC8B57634L, 0x9AF3DDA7L, 0xA9446146L, 0x0FD0030EL, 0xECC8C73EL, 0xA4751E41L, 0xE238CD99L, 0x3BEA0E2FL, 0x3280BBA1L, 0x183EB331L, 0x4E548B38L, 0x4F6DB908L, 0x6F420D03L, 0xF60A04BFL, 0x2CB81290L, 0x24977C79L, 0x5679B072L, 0xBCAF89AFL, 0xDE9A771FL, 0xD9930810L, 0xB38BAE12L, 0xDCCF3F2EL, 0x5512721FL, 0x2E6B7124L, 0x501ADDE6L, 0x9F84CD87L, 0x7A584718L, 0x7408DA17L, 0xBC9F9ABCL, 0xE94B7D8CL, 0xEC7AEC3AL, 0xDB851DFAL, 0x63094366L, 0xC464C3D2L, 0xEF1C1847L, 0x3215D908L, 0xDD433B37L, 0x24C2BA16L, 0x12A14D43L, 0x2A65C451L, 0x50940002L, 0x133AE4DDL, 0x71DFF89EL, 0x10314E55L, 0x81AC77D6L, 0x5F11199BL, 0x043556F1L, 0xD7A3C76BL, 0x3C11183BL, 0x5924A509L, 0xF28FE6EDL, 0x97F1FBFAL, 0x9EBABF2CL, 0x1E153C6EL, 0x86E34570L, 0xEAE96FB1L, 0x860E5E0AL, 0x5A3E2AB3L, 0x771FE71CL, 0x4E3D06FAL, 0x2965DCB9L, 0x99E71D0FL, 0x803E89D6L, 0x5266C825L, 0x2E4CC978L, 0x9C10B36AL, 0xC6150EBAL, 0x94E2EA78L, 0xA5FC3C53L, 0x1E0A2DF4L, 0xF2F74EA7L, 0x361D2B3DL, 0x1939260FL, 0x19C27960L, 0x5223A708L, 0xF71312B6L, 0xEBADFE6EL, 0xEAC31F66L, 0xE3BC4595L, 0xA67BC883L, 0xB17F37D1L, 0x018CFF28L, 0xC332DDEFL, 0xBE6C5AA5L, 0x65582185L, 0x68AB9802L, 0xEECEA50FL, 0xDB2F953BL, 0x2AEF7DADL, 0x5B6E2F84L, 0x1521B628L, 0x29076170L, 0xECDD4775L, 0x619F1510L, 0x13CCA830L, 0xEB61BD96L, 0x0334FE1EL, 0xAA0363CFL, 0xB5735C90L, 0x4C70A239L, 0xD59E9E0BL, 0xCBAADE14L, 0xEECC86BCL, 0x60622CA7L, 0x9CAB5CABL, 0xB2F3846EL, 0x648B1EAFL, 0x19BDF0CAL, 0xA02369B9L, 0x655ABB50L, 0x40685A32L, 0x3C2AB4B3L, 0x319EE9D5L, 0xC021B8F7L, 0x9B540B19L, 0x875FA099L, 0x95F7997EL, 0x623D7DA8L, 0xF837889AL, 0x97E32D77L, 0x11ED935FL, 0x16681281L, 0x0E358829L, 0xC7E61FD6L, 0x96DEDFA1L, 0x7858BA99L, 0x57F584A5L, 0x1B227263L, 0x9B83C3FFL, 0x1AC24696L, 0xCDB30AEBL, 0x532E3054L, 0x8FD948E4L, 0x6DBC3128L, 0x58EBF2EFL, 0x34C6FFEAL, 0xFE28ED61L, 0xEE7C3C73L, 0x5D4A14D9L, 0xE864B7E3L, 0x42105D14L, 0x203E13E0L, 0x45EEE2B6L, 0xA3AAABEAL, 0xDB6C4F15L, 0xFACB4FD0L, 0xC742F442L, 0xEF6ABBB5L, 0x654F3B1DL, 0x41CD2105L, 0xD81E799EL, 0x86854DC7L, 0xE44B476AL, 0x3D816250L, 0xCF62A1F2L, 0x5B8D2646L, 0xFC8883A0L, 0xC1C7B6A3L, 0x7F1524C3L, 0x69CB7492L, 0x47848A0BL, 0x5692B285L, 0x095BBF00L, 0xAD19489DL, 0x1462B174L, 0x23820E00L, 0x58428D2AL, 0x0C55F5EAL, 0x1DADF43EL, 0x233F7061L, 0x3372F092L, 0x8D937E41L, 0xD65FECF1L, 0x6C223BDBL, 0x7CDE3759L, 0xCBEE7460L, 0x4085F2A7L, 0xCE77326EL, 0xA6078084L, 0x19F8509EL, 0xE8EFD855L, 0x61D99735L, 0xA969A7AAL, 0xC50C06C2L, 0x5A04ABFCL, 0x800BCADCL, 0x9E447A2EL, 0xC3453484L, 0xFDD56705L, 0x0E1E9EC9L, 0xDB73DBD3L, 0x105588CDL, 0x675FDA79L, 0xE3674340L, 0xC5C43465L, 0x713E38D8L, 0x3D28F89EL, 0xF16DFF20L, 0x153E21E7L, 0x8FB03D4AL, 0xE6E39F2BL, 0xDB83ADF7L }, { 0xE93D5A68L, 0x948140F7L, 0xF64C261CL, 0x94692934L, 0x411520F7L, 0x7602D4F7L, 0xBCF46B2EL, 0xD4A20068L, 0xD4082471L, 0x3320F46AL, 0x43B7D4B7L, 0x500061AFL, 0x1E39F62EL, 0x97244546L, 0x14214F74L, 0xBF8B8840L, 0x4D95FC1DL, 0x96B591AFL, 0x70F4DDD3L, 0x66A02F45L, 0xBFBC09ECL, 0x03BD9785L, 0x7FAC6DD0L, 0x31CB8504L, 0x96EB27B3L, 0x55FD3941L, 0xDA2547E6L, 0xABCA0A9AL, 0x28507825L, 0x530429F4L, 0x0A2C86DAL, 0xE9B66DFBL, 0x68DC1462L, 0xD7486900L, 0x680EC0A4L, 0x27A18DEEL, 0x4F3FFEA2L, 0xE887AD8CL, 0xB58CE006L, 0x7AF4D6B6L, 0xAACE1E7CL, 0xD3375FECL, 0xCE78A399L, 0x406B2A42L, 0x20FE9E35L, 0xD9F385B9L, 0xEE39D7ABL, 0x3B124E8BL, 0x1DC9FAF7L, 0x4B6D1856L, 0x26A36631L, 0xEAE397B2L, 0x3A6EFA74L, 0xDD5B4332L, 0x6841E7F7L, 0xCA7820FBL, 0xFB0AF54EL, 0xD8FEB397L, 0x454056ACL, 0xBA489527L, 0x55533A3AL, 0x20838D87L, 0xFE6BA9B7L, 0xD096954BL, 0x55A867BCL, 0xA1159A58L, 0xCCA92963L, 0x99E1DB33L, 0xA62A4A56L, 0x3F3125F9L, 0x5EF47E1CL, 0x9029317CL, 0xFDF8E802L, 0x04272F70L, 0x80BB155CL, 0x05282CE3L, 0x95C11548L, 0xE4C66D22L, 0x48C1133FL, 0xC70F86DCL, 0x07F9C9EEL, 0x41041F0FL, 0x404779A4L, 0x5D886E17L, 0x325F51EBL, 0xD59BC0D1L, 0xF2BCC18FL, 0x41113564L, 0x257B7834L, 0x602A9C60L, 0xDFF8E8A3L, 0x1F636C1BL, 0x0E12B4C2L, 0x02E1329EL, 0xAF664FD1L, 0xCAD18115L, 0x6B2395E0L, 0x333E92E1L, 0x3B240B62L, 0xEEBEB922L, 0x85B2A20EL, 0xE6BA0D99L, 0xDE720C8CL, 0x2DA2F728L, 0xD0127845L, 0x95B794FDL, 0x647D0862L, 0xE7CCF5F0L, 0x5449A36FL, 0x877D48FAL, 0xC39DFD27L, 0xF33E8D1EL, 0x0A476341L, 0x992EFF74L, 0x3A6F6EABL, 0xF4F8FD37L, 0xA812DC60L, 0xA1EBDDF8L, 0x991BE14CL, 0xDB6E6B0DL, 0xC67B5510L, 0x6D672C37L, 0x2765D43BL, 0xDCD0E804L, 0xF1290DC7L, 0xCC00FFA3L, 0xB5390F92L, 0x690FED0BL, 0x667B9FFBL, 0xCEDB7D9CL, 0xA091CF0BL, 0xD9155EA3L, 0xBB132F88L, 0x515BAD24L, 0x7B9479BFL, 0x763BD6EBL, 0x37392EB3L, 0xCC115979L, 0x8026E297L, 0xF42E312DL, 0x6842ADA7L, 0xC66A2B3BL, 0x12754CCCL, 0x782EF11CL, 0x6A124237L, 0xB79251E7L, 0x06A1BBE6L, 0x4BFB6350L, 0x1A6B1018L, 0x11CAEDFAL, 0x3D25BDD8L, 0xE2E1C3C9L, 0x44421659L, 0x0A121386L, 0xD90CEC6EL, 0xD5ABEA2AL, 0x64AF674EL, 0xDA86A85FL, 0xBEBFE988L, 0x64E4C3FEL, 0x9DBC8057L, 0xF0F7C086L, 0x60787BF8L, 0x6003604DL, 0xD1FD8346L, 0xF6381FB0L, 0x7745AE04L, 0xD736FCCCL, 0x83426B33L, 0xF01EAB71L, 0xB0804187L, 0x3C005E5FL, 0x77A057BEL, 0xBDE8AE24L, 0x55464299L, 0xBF582E61L, 0x4E58F48FL, 0xF2DDFDA2L, 0xF474EF38L, 0x8789BDC2L, 0x5366F9C3L, 0xC8B38E74L, 0xB475F255L, 0x46FCD9B9L, 0x7AEB2661L, 0x8B1DDF84L, 0x846A0E79L, 0x915F95E2L, 0x466E598EL, 0x20B45770L, 0x8CD55591L, 0xC902DE4CL, 0xB90BACE1L, 0xBB8205D0L, 0x11A86248L, 0x7574A99EL, 0xB77F19B6L, 0xE0A9DC09L, 0x662D09A1L, 0xC4324633L, 0xE85A1F02L, 0x09F0BE8CL, 0x4A99A025L, 0x1D6EFE10L, 0x1AB93D1DL, 0x0BA5A4DFL, 0xA186F20FL, 0x2868F169L, 0xDCB7DA83L, 0x573906FEL, 0xA1E2CE9BL, 0x4FCD7F52L, 0x50115E01L, 0xA70683FAL, 0xA002B5C4L, 0x0DE6D027L, 0x9AF88C27L, 0x773F8641L, 0xC3604C06L, 0x61A806B5L, 0xF0177A28L, 0xC0F586E0L, 0x006058AAL, 0x30DC7D62L, 0x11E69ED7L, 0x2338EA63L, 0x53C2DD94L, 0xC2C21634L, 0xBBCBEE56L, 0x90BCB6DEL, 0xEBFC7DA1L, 0xCE591D76L, 0x6F05E409L, 0x4B7C0188L, 0x39720A3DL, 0x7C927C24L, 0x86E3725FL, 0x724D9DB9L, 0x1AC15BB4L, 0xD39EB8FCL, 0xED545578L, 0x08FCA5B5L, 0xD83D7CD3L, 0x4DAD0FC4L, 0x1E50EF5EL, 0xB161E6F8L, 0xA28514D9L, 0x6C51133CL, 0x6FD5C7E7L, 0x56E14EC4L, 0x362ABFCEL, 0xDDC6C837L, 0xD79A3234L, 0x92638212L, 0x670EFA8EL, 0x406000E0L }, { 0x3A39CE37L, 0xD3FAF5CFL, 0xABC27737L, 0x5AC52D1BL, 0x5CB0679EL, 0x4FA33742L, 0xD3822740L, 0x99BC9BBEL, 0xD5118E9DL, 0xBF0F7315L, 0xD62D1C7EL, 0xC700C47BL, 0xB78C1B6BL, 0x21A19045L, 0xB26EB1BEL, 0x6A366EB4L, 0x5748AB2FL, 0xBC946E79L, 0xC6A376D2L, 0x6549C2C8L, 0x530FF8EEL, 0x468DDE7DL, 0xD5730A1DL, 0x4CD04DC6L, 0x2939BBDBL, 0xA9BA4650L, 0xAC9526E8L, 0xBE5EE304L, 0xA1FAD5F0L, 0x6A2D519AL, 0x63EF8CE2L, 0x9A86EE22L, 0xC089C2B8L, 0x43242EF6L, 0xA51E03AAL, 0x9CF2D0A4L, 0x83C061BAL, 0x9BE96A4DL, 0x8FE51550L, 0xBA645BD6L, 0x2826A2F9L, 0xA73A3AE1L, 0x4BA99586L, 0xEF5562E9L, 0xC72FEFD3L, 0xF752F7DAL, 0x3F046F69L, 0x77FA0A59L, 0x80E4A915L, 0x87B08601L, 0x9B09E6ADL, 0x3B3EE593L, 0xE990FD5AL, 0x9E34D797L, 0x2CF0B7D9L, 0x022B8B51L, 0x96D5AC3AL, 0x017DA67DL, 0xD1CF3ED6L, 0x7C7D2D28L, 0x1F9F25CFL, 0xADF2B89BL, 0x5AD6B472L, 0x5A88F54CL, 0xE029AC71L, 0xE019A5E6L, 0x47B0ACFDL, 0xED93FA9BL, 0xE8D3C48DL, 0x283B57CCL, 0xF8D56629L, 0x79132E28L, 0x785F0191L, 0xED756055L, 0xF7960E44L, 0xE3D35E8CL, 0x15056DD4L, 0x88F46DBAL, 0x03A16125L, 0x0564F0BDL, 0xC3EB9E15L, 0x3C9057A2L, 0x97271AECL, 0xA93A072AL, 0x1B3F6D9BL, 0x1E6321F5L, 0xF59C66FBL, 0x26DCF319L, 0x7533D928L, 0xB155FDF5L, 0x03563482L, 0x8ABA3CBBL, 0x28517711L, 0xC20AD9F8L, 0xABCC5167L, 0xCCAD925FL, 0x4DE81751L, 0x3830DC8EL, 0x379D5862L, 0x9320F991L, 0xEA7A90C2L, 0xFB3E7BCEL, 0x5121CE64L, 0x774FBE32L, 0xA8B6E37EL, 0xC3293D46L, 0x48DE5369L, 0x6413E680L, 0xA2AE0810L, 0xDD6DB224L, 0x69852DFDL, 0x09072166L, 0xB39A460AL, 0x6445C0DDL, 0x586CDECFL, 0x1C20C8AEL, 0x5BBEF7DDL, 0x1B588D40L, 0xCCD2017FL, 0x6BB4E3BBL, 0xDDA26A7EL, 0x3A59FF45L, 0x3E350A44L, 0xBCB4CDD5L, 0x72EACEA8L, 0xFA6484BBL, 0x8D6612AEL, 0xBF3C6F47L, 0xD29BE463L, 0x542F5D9EL, 0xAEC2771BL, 0xF64E6370L, 0x740E0D8DL, 0xE75B1357L, 0xF8721671L, 0xAF537D5DL, 0x4040CB08L, 0x4EB4E2CCL, 0x34D2466AL, 0x0115AF84L, 0xE1B00428L, 0x95983A1DL, 0x06B89FB4L, 0xCE6EA048L, 0x6F3F3B82L, 0x3520AB82L, 0x011A1D4BL, 0x277227F8L, 0x611560B1L, 0xE7933FDCL, 0xBB3A792BL, 0x344525BDL, 0xA08839E1L, 0x51CE794BL, 0x2F32C9B7L, 0xA01FBAC9L, 0xE01CC87EL, 0xBCC7D1F6L, 0xCF0111C3L, 0xA1E8AAC7L, 0x1A908749L, 0xD44FBD9AL, 0xD0DADECBL, 0xD50ADA38L, 0x0339C32AL, 0xC6913667L, 0x8DF9317CL, 0xE0B12B4FL, 0xF79E59B7L, 0x43F5BB3AL, 0xF2D519FFL, 0x27D9459CL, 0xBF97222CL, 0x15E6FC2AL, 0x0F91FC71L, 0x9B941525L, 0xFAE59361L, 0xCEB69CEBL, 0xC2A86459L, 0x12BAA8D1L, 0xB6C1075EL, 0xE3056A0CL, 0x10D25065L, 0xCB03A442L, 0xE0EC6E0EL, 0x1698DB3BL, 0x4C98A0BEL, 0x3278E964L, 0x9F1F9532L, 0xE0D392DFL, 0xD3A0342BL, 0x8971F21EL, 0x1B0A7441L, 0x4BA3348CL, 0xC5BE7120L, 0xC37632D8L, 0xDF359F8DL, 0x9B992F2EL, 0xE60B6F47L, 0x0FE3F11DL, 0xE54CDA54L, 0x1EDAD891L, 0xCE6279CFL, 0xCD3E7E6FL, 0x1618B166L, 0xFD2C1D05L, 0x848FD2C5L, 0xF6FB2299L, 0xF523F357L, 0xA6327623L, 0x93A83531L, 0x56CCCD02L, 0xACF08162L, 0x5A75EBB5L, 0x6E163697L, 0x88D273CCL, 0xDE966292L, 0x81B949D0L, 0x4C50901BL, 0x71C65614L, 0xE6C6C7BDL, 0x327A140AL, 0x45E1D006L, 0xC3F27B9AL, 0xC9AA53FDL, 0x62A80F00L, 0xBB25BFE2L, 0x35BDD2F6L, 0x71126905L, 0xB2040222L, 0xB6CBCF7CL, 0xCD769C2BL, 0x53113EC0L, 0x1640E3D3L, 0x38ABBD60L, 0x2547ADF0L, 0xBA38209CL, 0xF746CE76L, 0x77AFA1C5L, 0x20756060L, 0x85CBFE4EL, 0x8AE88DD8L, 0x7AAAF9B0L, 0x4CF9AA7EL, 0x1948C25CL, 0x02FB8A8CL, 0x01C36AE4L, 0xD6EBE1F9L, 0x90D4F869L, 0xA65CDEA0L, 0x3F09252DL, 0xC208E69FL, 0xB74E6132L, 0xCE77E25BL, 0x578FDFE3L, 0x3AC372E6L } }; /* XL: turned F into a macro + endianness handling */ #if 0 static u32 F(BLOWFISH_CTX *ctx, u32 x) { unsigned short a, b, c, d; u32 y; d = (unsigned short)(x & 0xFF); x >>= 8; c = (unsigned short)(x & 0xFF); x >>= 8; b = (unsigned short)(x & 0xFF); x >>= 8; a = (unsigned short)(x & 0xFF); y = ctx->S[0][a] + ctx->S[1][b]; y = y ^ ctx->S[2][c]; y = y + ctx->S[3][d]; return y; } #else #define F(ctx,x) \ (((ctx->S[0][x >> 24] \ + ctx->S[1][(x >> 16) & 0xFF]) \ ^ ctx->S[2][(x >> 8) & 0xFF]) \ + ctx->S[3][x & 0xFF]) #endif void Blowfish_Encrypt(BLOWFISH_CTX *ctx, u32 *xl, u32 *xr){ u32 Xl; u32 Xr; #if 0 u32 temp; short i; Xl = *xl; Xr = *xr; for (i = 0; i < N; ++i) { Xl = Xl ^ ctx->P[i]; Xr = F(ctx, Xl) ^ Xr; temp = Xl; Xl = Xr; Xr = temp; } temp = Xl; Xl = Xr; Xr = temp; Xr = Xr ^ ctx->P[N]; Xl = Xl ^ ctx->P[N + 1]; *xl = Xl; *xr = Xr; #else Xl = *xl; Xr = *xr; /* XL: loop unrolling */ Xl ^= ctx->P[0]; Xr ^= F(ctx,Xl) ^ ctx->P[1]; Xl ^= F(ctx,Xr) ^ ctx->P[2]; Xr ^= F(ctx,Xl) ^ ctx->P[3]; Xl ^= F(ctx,Xr) ^ ctx->P[4]; Xr ^= F(ctx,Xl) ^ ctx->P[5]; Xl ^= F(ctx,Xr) ^ ctx->P[6]; Xr ^= F(ctx,Xl) ^ ctx->P[7]; Xl ^= F(ctx,Xr) ^ ctx->P[8]; Xr ^= F(ctx,Xl) ^ ctx->P[9]; Xl ^= F(ctx,Xr) ^ ctx->P[10]; Xr ^= F(ctx,Xl) ^ ctx->P[11]; Xl ^= F(ctx,Xr) ^ ctx->P[12]; Xr ^= F(ctx,Xl) ^ ctx->P[13]; Xl ^= F(ctx,Xr) ^ ctx->P[14]; Xr ^= F(ctx,Xl) ^ ctx->P[15]; Xl ^= F(ctx,Xr) ^ ctx->P[16]; Xr ^= ctx->P[17]; *xl = Xr; *xr = Xl; #endif } void Blowfish_Decrypt(BLOWFISH_CTX *ctx, u32 *xl, u32 *xr){ u32 Xl; u32 Xr; #if 0 u32 temp; short i; Xl = *xl; Xr = *xr; for (i = N + 1; i > 1; --i) { Xl = Xl ^ ctx->P[i]; Xr = F(ctx, Xl) ^ Xr; /* Exchange Xl and Xr */ temp = Xl; Xl = Xr; Xr = temp; } /* Exchange Xl and Xr */ temp = Xl; Xl = Xr; Xr = temp; Xr = Xr ^ ctx->P[1]; Xl = Xl ^ ctx->P[0]; *xl = Xl; *xr = Xr; #else Xl = *xl; Xr = *xr; /* XL: loop unrolling */ Xl ^= ctx->P[17]; Xr ^= F(ctx,Xl) ^ ctx->P[16]; Xl ^= F(ctx,Xr) ^ ctx->P[15]; Xr ^= F(ctx,Xl) ^ ctx->P[14]; Xl ^= F(ctx,Xr) ^ ctx->P[13]; Xr ^= F(ctx,Xl) ^ ctx->P[12]; Xl ^= F(ctx,Xr) ^ ctx->P[11]; Xr ^= F(ctx,Xl) ^ ctx->P[10]; Xl ^= F(ctx,Xr) ^ ctx->P[9]; Xr ^= F(ctx,Xl) ^ ctx->P[8]; Xl ^= F(ctx,Xr) ^ ctx->P[7]; Xr ^= F(ctx,Xl) ^ ctx->P[6]; Xl ^= F(ctx,Xr) ^ ctx->P[5]; Xr ^= F(ctx,Xl) ^ ctx->P[4]; Xl ^= F(ctx,Xr) ^ ctx->P[3]; Xr ^= F(ctx,Xl) ^ ctx->P[2]; Xl ^= F(ctx,Xr) ^ ctx->P[1]; Xr ^= ctx->P[0]; *xl = Xr; *xr = Xl; #endif } void Blowfish_Init(BLOWFISH_CTX *ctx, unsigned char *key, int keyLen) { int i, j, k; u32 data, datal, datar; for (i = 0; i < 4; i++) { for (j = 0; j < 256; j++) ctx->S[i][j] = ORIG_S[i][j]; } j = 0; for (i = 0; i < N + 2; ++i) { data = 0x00000000; for (k = 0; k < 4; ++k) { data = (data << 8) | key[j]; j = j + 1; if (j >= keyLen) j = 0; } ctx->P[i] = ORIG_P[i] ^ data; } datal = 0x00000000; datar = 0x00000000; for (i = 0; i < N + 2; i += 2) { Blowfish_Encrypt(ctx, &datal, &datar); ctx->P[i] = datal; ctx->P[i + 1] = datar; } for (i = 0; i < 4; ++i) { for (j = 0; j < 256; j += 2) { Blowfish_Encrypt(ctx, &datal, &datar); ctx->S[i][j] = datal; ctx->S[i][j + 1] = datar; } } } cryptokit-release119/src/blowfish.h000066400000000000000000000021461453705265000175460ustar00rootroot00000000000000/* blowfish.h: Header file for blowfish.c Copyright (C) 1997 by Paul Kocher This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA See blowfish.c for more information about this file. */ typedef unsigned int u32; typedef struct { u32 P[16 + 2]; u32 S[4][256]; } BLOWFISH_CTX; void Blowfish_Init(BLOWFISH_CTX *ctx, unsigned char *key, int keyLen); void Blowfish_Encrypt(BLOWFISH_CTX *ctx, u32 *xl, u32 *xr); void Blowfish_Decrypt(BLOWFISH_CTX *ctx, u32 *xl, u32 *xr); cryptokit-release119/src/chacha20.c000066400000000000000000000116761453705265000173050ustar00rootroot00000000000000/* Based on D. J. Bernstein's chacha-regs.c version 200801118, https://cr.yp.to/streamciphers/timings/estreambench/submissions/salsa20/chacha8/regs/chacha.c The initial code is in the public domain */ #include #include #include #include #include #include "chacha20.h" static inline void U32TO8_LITTLE(uint8_t * dst, uint32_t val) { #ifdef ARCH_BIG_ENDIAN dst[0] = val; dst[1] = val >> 8; dst[2] = val >> 16; dst[3] = val >> 24; #else *((uint32_t *) dst) = val; #endif } static inline uint32_t U8TO32_LITTLE(const uint8_t * src) { return (uint32_t) src[0] + ((uint32_t) src[1] << 8) + ((uint32_t) src[2] << 16) + ((uint32_t) src[3] << 24); } #define ROTATE(v,c) ((v) << (c) | (v) >> (32 - (c))) #define XOR(v,w) ((v) ^ (w)) #define PLUS(v,w) ((v) + (w)) #define PLUSONE(v) ((v) + 1) #define QUARTERROUND(a,b,c,d) \ a = PLUS(a,b); d = ROTATE(XOR(d,a),16); \ c = PLUS(c,d); b = ROTATE(XOR(b,c),12); \ a = PLUS(a,b); d = ROTATE(XOR(d,a), 8); \ c = PLUS(c,d); b = ROTATE(XOR(b,c), 7); static void chacha20_block(chacha20_ctx * ctx) { uint32_t x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15; int i; x0 = ctx->input[0]; x1 = ctx->input[1]; x2 = ctx->input[2]; x3 = ctx->input[3]; x4 = ctx->input[4]; x5 = ctx->input[5]; x6 = ctx->input[6]; x7 = ctx->input[7]; x8 = ctx->input[8]; x9 = ctx->input[9]; x10 = ctx->input[10]; x11 = ctx->input[11]; x12 = ctx->input[12]; x13 = ctx->input[13]; x14 = ctx->input[14]; x15 = ctx->input[15]; for (i = 10; i > 0; i --) { QUARTERROUND( x0, x4, x8,x12) QUARTERROUND( x1, x5, x9,x13) QUARTERROUND( x2, x6,x10,x14) QUARTERROUND( x3, x7,x11,x15) QUARTERROUND( x0, x5,x10,x15) QUARTERROUND( x1, x6,x11,x12) QUARTERROUND( x2, x7, x8,x13) QUARTERROUND( x3, x4, x9,x14) } x0 = PLUS(x0,ctx->input[0]); x1 = PLUS(x1,ctx->input[1]); x2 = PLUS(x2,ctx->input[2]); x3 = PLUS(x3,ctx->input[3]); x4 = PLUS(x4,ctx->input[4]); x5 = PLUS(x5,ctx->input[5]); x6 = PLUS(x6,ctx->input[6]); x7 = PLUS(x7,ctx->input[7]); x8 = PLUS(x8,ctx->input[8]); x9 = PLUS(x9,ctx->input[9]); x10 = PLUS(x10,ctx->input[10]); x11 = PLUS(x11,ctx->input[11]); x12 = PLUS(x12,ctx->input[12]); x13 = PLUS(x13,ctx->input[13]); x14 = PLUS(x14,ctx->input[14]); x15 = PLUS(x15,ctx->input[15]); U32TO8_LITTLE(ctx->output + 0,x0); U32TO8_LITTLE(ctx->output + 4,x1); U32TO8_LITTLE(ctx->output + 8,x2); U32TO8_LITTLE(ctx->output + 12,x3); U32TO8_LITTLE(ctx->output + 16,x4); U32TO8_LITTLE(ctx->output + 20,x5); U32TO8_LITTLE(ctx->output + 24,x6); U32TO8_LITTLE(ctx->output + 28,x7); U32TO8_LITTLE(ctx->output + 32,x8); U32TO8_LITTLE(ctx->output + 36,x9); U32TO8_LITTLE(ctx->output + 40,x10); U32TO8_LITTLE(ctx->output + 44,x11); U32TO8_LITTLE(ctx->output + 48,x12); U32TO8_LITTLE(ctx->output + 52,x13); U32TO8_LITTLE(ctx->output + 56,x14); U32TO8_LITTLE(ctx->output + 60,x15); /* Increment the 32- or 64-bit counter */ if (++ ctx->input[12] == 0) { if (ctx->iv_length == 8) ++ ctx->input[13]; } } void chacha20_transform(chacha20_ctx * ctx, const uint8_t * in, uint8_t * out, size_t len) { int n = ctx->next; for (/*nothing*/; len > 0; len--) { if (n >= 64) { chacha20_block(ctx); n = 0; } *out++ = *in++ ^ ctx->output[n++]; } ctx->next = n; } void chacha20_extract(chacha20_ctx * ctx, uint8_t * out, size_t len) { int n = ctx->next; for (/*nothing*/; len > 0; len--) { if (n >= 64) { chacha20_block(ctx); n = 0; } *out++ = ctx->output[n++]; } ctx->next = n; } void chacha20_init(chacha20_ctx * ctx, const uint8_t * key, size_t key_length, const uint8_t * iv, size_t iv_length, uint64_t counter) { const uint8_t *constants = (uint8_t *) (key_length == 32 ? "expand 32-byte k" : "expand 16-byte k"); assert (key_length == 16 || key_length == 32); assert (iv_length == 8 || iv_length == 12); ctx->input[0] = U8TO32_LITTLE(constants + 0); ctx->input[1] = U8TO32_LITTLE(constants + 4); ctx->input[2] = U8TO32_LITTLE(constants + 8); ctx->input[3] = U8TO32_LITTLE(constants + 12); ctx->input[4] = U8TO32_LITTLE(key + 0); ctx->input[5] = U8TO32_LITTLE(key + 4); ctx->input[6] = U8TO32_LITTLE(key + 8); ctx->input[7] = U8TO32_LITTLE(key + 12); if (key_length == 32) key += 16; ctx->input[8] = U8TO32_LITTLE(key + 0); ctx->input[9] = U8TO32_LITTLE(key + 4); ctx->input[10] = U8TO32_LITTLE(key + 8); ctx->input[11] = U8TO32_LITTLE(key + 12); ctx->input[12] = (uint32_t) counter; if (iv_length == 8) { ctx->input[13] = (uint32_t) (counter >> 32); ctx->input[14] = U8TO32_LITTLE(iv + 0); ctx->input[15] = U8TO32_LITTLE(iv + 4); } else { ctx->input[13] = U8TO32_LITTLE(iv + 0); ctx->input[14] = U8TO32_LITTLE(iv + 4); ctx->input[15] = U8TO32_LITTLE(iv + 8); } ctx->iv_length = iv_length; ctx->next = 64; } cryptokit-release119/src/chacha20.h000066400000000000000000000016401453705265000173000ustar00rootroot00000000000000/* Based on D. J. Bernstein's chacha-regs.c version 200801118, https://cr.yp.to/streamciphers/timings/estreambench/submissions/salsa20/chacha8/regs/chacha.c The initial code is in the public domain */ #include #include typedef struct { uint32_t input[16]; /* The current state */ uint8_t output[64]; /* Output data for the current state */ int next; /* Index of next unused byte in output */ int iv_length; /* 8 or 12 */ } chacha20_ctx; void chacha20_init(chacha20_ctx * ctx, const uint8_t * key, size_t key_length, const uint8_t * iv, size_t iv_length, uint64_t ctr); void chacha20_extract(chacha20_ctx * ctx, uint8_t * out, size_t len); void chacha20_transform(chacha20_ctx * ctx, const uint8_t * in, uint8_t * out, size_t len); cryptokit-release119/src/config/000077500000000000000000000000001453705265000170225ustar00rootroot00000000000000cryptokit-release119/src/config/config_vars.ml.default000066400000000000000000000001501453705265000232730ustar00rootroot00000000000000type 'a value = | This of 'a | Auto let enable_zlib = Auto let enable_hardware_support = Auto cryptokit-release119/src/config/dune000066400000000000000000000002161453705265000176770ustar00rootroot00000000000000(executable (name flags) (libraries dune-configurator)) (rule (mode fallback) (action (copy config_vars.ml.default config_vars.ml))) cryptokit-release119/src/config/flags.ml000066400000000000000000000047061453705265000204570ustar00rootroot00000000000000(* Compute compilation and linking flags *) open Printf open Config_vars module Configurator = Configurator.V1 (* Compile and link a dummy C program with the given flags. *) let test ~cfg ~c_flags ~link_flags = let test_program = "int main() { return 0; }" in Configurator.c_test cfg test_program ~c_flags ~link_flags (* Check that a list of header files declare a list of identifiers. *) let provides ~cfg ~c_flags ~link_flags ~headers ~functions = let test_program = List.map (fun h -> sprintf "#include <%s>\n" h) headers @ ["int main() {\n"] @ List.map (fun f -> sprintf " void * ptr_%s = &%s;\n" f f) functions @ ["}\n"] in Configurator.c_test cfg (String.concat "" test_program) ~c_flags ~link_flags let () = Configurator.main ~name:"cryptokit" @@ fun cfg -> let os_type = Configurator.ocaml_config_var_exn cfg "os_type" in let system = Configurator.ocaml_config_var_exn cfg "system" in let architecture = Configurator.ocaml_config_var_exn cfg "architecture" in let zlib = match enable_zlib with | This bool -> bool | Auto -> os_type <> "Win32" in let hardware_support = match enable_hardware_support with | This bool -> bool | Auto -> (architecture = "amd64" || architecture = "i386") && test ~cfg ~c_flags:[ "-maes"; "-mpclmul" ] ~link_flags:[] in let has_getentropy = provides ~cfg ~c_flags:[] ~link_flags:[] ~headers:["unistd.h"] ~functions:["getentropy"] in let append_if c y x = if c then x @ [ y ] else x in let flags = [] |> append_if has_getentropy "-DHAVE_GETENTROPY" |> append_if zlib "-DHAVE_ZLIB" |> append_if hardware_support "-maes" |> append_if hardware_support "-mpclmul" in let library_flags = [] |> append_if (zlib && (system = "win32" || system = "win64")) "zlib.lib" |> append_if (zlib && system <> "win32" && system <> "win64") "-lz" |> append_if (system = "win32" || system = "win64") "advapi32.lib" |> append_if (system = "mingw" || system = "mingw64") "-ladvapi32" in Configurator.Flags.write_sexp "flags.sexp" flags; Configurator.Flags.write_sexp "library_flags.sexp" library_flags; let describe_bool = function | true -> "enabled" | false -> "disabled" in printf "ZLib: ............................... %s\n" (describe_bool zlib); printf "Hardware support for AES and GCM: ... %s\n" (describe_bool hardware_support); printf "getentropy():........................ %s\n" (describe_bool has_getentropy) cryptokit-release119/src/cryptokit.ml000066400000000000000000002300761453705265000201470ustar00rootroot00000000000000(***********************************************************************) (* *) (* The Cryptokit library *) (* *) (* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) (* *) (* Copyright 2002 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file LICENSE. *) (* *) (***********************************************************************) (* Utilities *) let seq_equal (len: 'a -> int) (get: 'a -> int -> char) (s1: 'a) (s2: 'a) = let l = len s1 in let rec equal i accu = if i >= l then accu = 0 else equal (i + 1) (accu lor ((Char.code (get s1 i)) lxor (Char.code (get s2 i)))) in l = len s2 && equal 0 0 let string_equal = seq_equal String.length String.get let bytes_equal = seq_equal Bytes.length Bytes.get let wipe_bytes s = Bytes.fill s 0 (Bytes.length s) '\000' let wipe_string s = wipe_bytes (Bytes.unsafe_of_string s) let shl1_bytes src soff dst doff len = let rec shl1 carry i = if i >= 0 then begin let n = Char.code (Bytes.get src (soff + i)) in Bytes.set dst (doff + i) (Char.unsafe_chr ((n lsl 1) lor carry)); shl1 (n lsr 7) (i - 1) end in shl1 0 (len - 1) (* Error reporting *) type error = | Wrong_key_size | Wrong_IV_size | Wrong_data_length | Bad_padding | Output_buffer_overflow | Incompatible_block_size | Number_too_long | Seed_too_short | Message_too_long | Bad_encoding | Compression_error of string * string | No_entropy_source | Entropy_source_closed | Compression_not_supported exception Error of error let _ = Callback.register_exception "Cryptokit.Error" (Error Wrong_key_size) (* Interface with C *) type dir = Encrypt | Decrypt external xor_bytes: bytes -> int -> bytes -> int -> int -> unit = "caml_xor_string" external xor_string: string -> int -> bytes -> int -> int -> unit = "caml_xor_string" external aes_cook_encrypt_key : string -> bytes = "caml_aes_cook_encrypt_key" external aes_cook_decrypt_key : string -> bytes = "caml_aes_cook_decrypt_key" external aes_encrypt : bytes -> bytes -> int -> bytes -> int -> unit = "caml_aes_encrypt" external aes_decrypt : bytes -> bytes -> int -> bytes -> int -> unit = "caml_aes_decrypt" external blowfish_cook_key : string -> bytes = "caml_blowfish_cook_key" external blowfish_encrypt : bytes -> bytes -> int -> bytes -> int -> unit = "caml_blowfish_encrypt" external blowfish_decrypt : bytes -> bytes -> int -> bytes -> int -> unit = "caml_blowfish_decrypt" external des_cook_key : string -> int -> dir -> bytes = "caml_des_cook_key" external des_transform : bytes -> bytes -> int -> bytes -> int -> unit = "caml_des_transform" external arcfour_cook_key : string -> bytes = "caml_arcfour_cook_key" external arcfour_transform : bytes -> bytes -> int -> bytes -> int -> int -> unit = "caml_arcfour_transform_bytecode" "caml_arcfour_transform" external chacha20_cook_key : string -> bytes -> int64 -> bytes = "caml_chacha20_cook_key" external chacha20_transform : bytes -> bytes -> int -> bytes -> int -> int -> unit = "caml_chacha20_transform_bytecode" "caml_chacha20_transform" external chacha20_extract : bytes -> bytes -> int -> int -> unit = "caml_chacha20_extract" external sha1_init: unit -> bytes = "caml_sha1_init" external sha1_update: bytes -> bytes -> int -> int -> unit = "caml_sha1_update" external sha1_final: bytes -> string = "caml_sha1_final" external sha256_init: unit -> bytes = "caml_sha256_init" external sha224_init: unit -> bytes = "caml_sha224_init" external sha256_update: bytes -> bytes -> int -> int -> unit = "caml_sha256_update" external sha256_final: bytes -> string = "caml_sha256_final" external sha224_final: bytes -> string = "caml_sha224_final" external sha512_init: unit -> bytes = "caml_sha512_init" external sha384_init: unit -> bytes = "caml_sha384_init" external sha512_update: bytes -> bytes -> int -> int -> unit = "caml_sha512_update" external sha512_final: bytes -> string = "caml_sha512_final" external sha384_final: bytes -> string = "caml_sha384_final" type sha3_context external sha3_init: int -> sha3_context = "caml_sha3_init" external sha3_absorb: sha3_context -> bytes -> int -> int -> unit = "caml_sha3_absorb" external sha3_extract: bool -> sha3_context -> string = "caml_sha3_extract" external sha3_wipe: sha3_context -> unit = "caml_sha3_wipe" external ripemd160_init: unit -> bytes = "caml_ripemd160_init" external ripemd160_update: bytes -> bytes -> int -> int -> unit = "caml_ripemd160_update" external ripemd160_final: bytes -> string = "caml_ripemd160_final" external md5_init: unit -> bytes = "caml_md5_init" external md5_update: bytes -> bytes -> int -> int -> unit = "caml_md5_update" external md5_final: bytes -> string = "caml_md5_final" external blake2b_init: int -> string -> bytes = "caml_blake2b_init" external blake2b_update: bytes -> bytes -> int -> int -> unit = "caml_blake2b_update" external blake2b_final: bytes -> int -> string = "caml_blake2b_final" external blake2s_init: int -> string -> bytes = "caml_blake2s_init" external blake2s_update: bytes -> bytes -> int -> int -> unit = "caml_blake2s_update" external blake2s_final: bytes -> int -> string = "caml_blake2s_final" type ghash_context external ghash_init: bytes -> ghash_context = "caml_ghash_init" external ghash_mult: ghash_context -> bytes -> unit = "caml_ghash_mult" external poly1305_init: bytes -> bytes = "caml_poly1305_init" external poly1305_update: bytes -> bytes -> int -> int -> unit = "caml_poly1305_update" external poly1305_final: bytes -> string = "caml_poly1305_final" external siphash_init: string -> int -> bytes = "caml_siphash_init" external siphash_update: bytes -> bytes -> int -> int -> unit = "caml_siphash_update" external siphash_final: bytes -> int -> string = "caml_siphash_final" type blake3_context external blake3_init: string -> blake3_context = "caml_blake3_init" external blake3_update: blake3_context -> bytes -> int -> int -> unit = "caml_blake3_update" external blake3_final: blake3_context -> int -> string = "caml_blake3_extract" external blake3_wipe: blake3_context -> unit = "caml_blake3_wipe" (* Abstract transform type *) class type transform = object method input_block_size: int method output_block_size: int method put_substring: bytes -> int -> int -> unit method put_string: string -> unit method put_char: char -> unit method put_byte: int -> unit method finish: unit method flush: unit method available_output: int method get_string: string method get_substring: bytes * int * int method get_char: char method get_byte: int method wipe: unit end let transform_string tr s = tr#put_string s; tr#finish; let r = tr#get_string in tr#wipe; r let transform_channel tr ?len ic oc = let ibuf = Bytes.create 256 in let rec transf_to_eof () = let r = input ic ibuf 0 256 in if r > 0 then begin tr#put_substring ibuf 0 r; let (obuf, opos, olen) = tr#get_substring in output oc obuf opos olen; transf_to_eof() end and transf_bounded numleft = if numleft > 0 then begin let r = input ic ibuf 0 (min 256 numleft) in if r = 0 then raise End_of_file; tr#put_substring ibuf 0 r; let (obuf, opos, olen) = tr#get_substring in output oc obuf opos olen; transf_bounded (numleft - r) end in begin match len with None -> transf_to_eof () | Some l -> transf_bounded l end; wipe_bytes ibuf; tr#finish; let (obuf, opos, olen) = tr#get_substring in output oc obuf opos olen; tr#wipe class compose (tr1 : transform) (tr2 : transform) = object(self) method input_block_size = tr1#input_block_size method output_block_size = tr2#output_block_size method put_substring buf ofs len = tr1#put_substring buf ofs len; self#transfer method put_string s = tr1#put_string s; self#transfer method put_char c = tr1#put_char c; self#transfer method put_byte b = tr1#put_byte b; self#transfer method private transfer = let (buf, ofs, len) = tr1#get_substring in tr2#put_substring buf ofs len method available_output = tr2#available_output method get_string = tr2#get_string method get_substring = tr2#get_substring method get_char = tr2#get_char method get_byte = tr2#get_byte method flush = tr1#flush; self#transfer; tr2#flush method finish = tr1#finish; self#transfer; tr2#finish method wipe = tr1#wipe; tr2#wipe end let compose tr1 tr2 = new compose tr1 tr2 class type hash = object method hash_size: int method add_substring: bytes -> int -> int -> unit method add_string: string -> unit method add_char: char -> unit method add_byte: int -> unit method result: string method wipe: unit end let hash_string hash s = hash#add_string s; let r = hash#result in hash#wipe; r let hash_channel hash ?len ic = let ibuf = Bytes.create 256 in let rec hash_to_eof () = let r = input ic ibuf 0 256 in if r > 0 then begin hash#add_substring ibuf 0 r; hash_to_eof() end and hash_bounded numleft = if numleft > 0 then begin let r = input ic ibuf 0 (min 256 numleft) in if r = 0 then raise End_of_file; hash#add_substring ibuf 0 r; hash_bounded (numleft - r) end in begin match len with None -> hash_to_eof () | Some l -> hash_bounded l end; wipe_bytes ibuf; let res = hash#result in hash#wipe; res class type authenticated_transform = object method input_block_size: int method output_block_size: int method tag_size: int method put_substring: bytes -> int -> int -> unit method put_string: string -> unit method put_char: char -> unit method put_byte: int -> unit method finish_and_get_tag: string method available_output: int method get_string: string method get_substring: bytes * int * int method get_char: char method get_byte: int method wipe: unit end let auth_transform_string_detached tr s = tr#put_string s; let tag = tr#finish_and_get_tag in let txt = tr#get_string in tr#wipe; (txt, tag) let auth_transform_string tr s = let (txt, tag) = auth_transform_string_detached tr s in txt ^ tag let auth_check_transform_string tr s = let ls = String.length s in let lt = tr#tag_size in if ls < lt then raise (Error Wrong_data_length); tr#put_string (String.sub s 0 (ls - lt)); let tag = tr#finish_and_get_tag in let res = if string_equal tag (String.sub s (ls - lt) lt) then Some (tr#get_string) else None in tr#wipe; res (* Generic handling of output buffering *) class buffered_output initial_buffer_size = object(self) val mutable obuf = Bytes.create initial_buffer_size val mutable obeg = 0 val mutable oend = 0 method private ensure_capacity n = let len = Bytes.length obuf in if oend + n > len then begin if oend - obeg + n < len then begin Bytes.blit obuf obeg obuf 0 (oend - obeg); oend <- oend - obeg; obeg <- 0 end else begin let newlen = ref (2 * len) in while oend - obeg + n > (!newlen) do newlen := (!newlen) * 2 done; if (!newlen) > Sys.max_string_length then begin if (oend - obeg + n) <= Sys.max_string_length then newlen := Sys.max_string_length else raise (Error Output_buffer_overflow) end; let newbuf = Bytes.create (!newlen) in Bytes.blit obuf obeg newbuf 0 (oend - obeg); obuf <- newbuf; oend <- oend - obeg; obeg <- 0 end end method available_output = oend - obeg method get_substring = let res = (obuf, obeg, oend - obeg) in obeg <- 0; oend <- 0; res method get_string = let res = Bytes.sub_string obuf obeg (oend - obeg) in obeg <- 0; oend <- 0; res method get_char = if obeg >= oend then raise End_of_file; let r = Bytes.get obuf obeg in obeg <- obeg + 1; r method get_byte = Char.code self#get_char method wipe = wipe_bytes obuf end (* Combining a transform and a hash to get an authenticated transform *) class transform_then_hash (tr: transform) (h: hash) = object(self) inherit buffered_output 256 as output_buffer method private transfer = let (buf, ofs, len) = tr#get_substring in h#add_substring buf ofs len; self#ensure_capacity len; Bytes.blit buf ofs obuf oend len; oend <- oend + len method input_block_size = tr#input_block_size method output_block_size = tr#output_block_size method tag_size = h#hash_size method put_substring buf ofs len = tr#put_substring buf ofs len; self#transfer method put_string s = tr#put_string s; self#transfer method put_char c = tr#put_char c; self#transfer method put_byte b = tr#put_byte b; self#transfer method finish_and_get_tag = tr#finish; self#transfer; h#result method wipe = output_buffer#wipe; tr#wipe; h#wipe end let transform_then_hash tr h = new transform_then_hash tr h class transform_and_hash (tr: transform) (h: hash) = object(self) method input_block_size = tr#input_block_size method output_block_size = tr#output_block_size method tag_size = h#hash_size method put_substring buf ofs len = tr#put_substring buf ofs len; h#add_substring buf ofs len method put_string s = tr#put_string s; h#add_string s method put_char c = tr#put_char c; h#add_char c method put_byte b = tr#put_byte b; h#add_byte b method finish_and_get_tag = tr#finish; h#result method wipe = tr#wipe; h#wipe method available_output = tr#available_output method get_substring = tr#get_substring method get_string = tr#get_string method get_char = tr#get_char method get_byte = tr#get_byte end let transform_and_hash tr h = new transform_and_hash tr h (* Padding schemes *) module Padding = struct class type scheme = object method pad: bytes -> int -> unit method strip: bytes -> int end class length = object method pad buffer used = let n = Bytes.length buffer - used in assert (n > 0 && n < 256); Bytes.fill buffer used n (Char.chr n) method strip buffer = let blocksize = Bytes.length buffer in let n = Char.code (Bytes.get buffer (blocksize - 1)) in if n = 0 || n > blocksize then raise (Error Bad_padding); (* Characters blocksize - n to blocksize - 1 must be equal to n *) for i = blocksize - n to blocksize - 2 do if Char.code (Bytes.get buffer i) <> n then raise (Error Bad_padding) done; blocksize - n end let length = new length class _8000 = object method pad buffer used = Bytes.set buffer used '\128'; for i = used + 1 to Bytes.length buffer - 1 do Bytes.set buffer i '\000' done method strip buffer = let rec strip pos = if pos < 0 then raise (Error Bad_padding) else match Bytes.get buffer pos with '\128' -> pos | '\000' -> strip (pos - 1) | _ -> raise (Error Bad_padding) in strip (Bytes.length buffer - 1) end let _8000 = new _8000 end (* Block ciphers *) module Block = struct class type block_cipher = object method blocksize: int method transform: bytes -> int -> bytes -> int -> unit method wipe: unit end class aes_encrypt key = object val ckey = let kl = String.length key in if kl = 16 || kl = 24 || kl = 32 then aes_cook_encrypt_key key else raise(Error Wrong_key_size) method blocksize = 16 method transform src src_ofs dst dst_ofs = if src_ofs < 0 || src_ofs > Bytes.length src - 16 || dst_ofs < 0 || dst_ofs > Bytes.length dst - 16 then invalid_arg "aes#transform"; aes_encrypt ckey src src_ofs dst dst_ofs method wipe = wipe_bytes ckey; Bytes.set ckey (Bytes.length ckey - 1) '\016' end class aes_decrypt key = object val ckey = let kl = String.length key in if kl = 16 || kl = 24 || kl = 32 then aes_cook_decrypt_key key else raise(Error Wrong_key_size) method blocksize = 16 method transform src src_ofs dst dst_ofs = if src_ofs < 0 || src_ofs > Bytes.length src - 16 || dst_ofs < 0 || dst_ofs > Bytes.length dst - 16 then invalid_arg "aes#transform"; aes_decrypt ckey src src_ofs dst dst_ofs method wipe = wipe_bytes ckey; Bytes.set ckey (Bytes.length ckey - 1) '\016' end class blowfish_encrypt key = object val ckey = let kl = String.length key in if kl >= 4 && kl <= 56 then blowfish_cook_key key else raise(Error Wrong_key_size) method blocksize = 8 method transform src src_ofs dst dst_ofs = if src_ofs < 0 || src_ofs > Bytes.length src - 8 || dst_ofs < 0 || dst_ofs > Bytes.length dst - 8 then invalid_arg "blowfish#transform"; blowfish_encrypt ckey src src_ofs dst dst_ofs method wipe = wipe_bytes ckey end class blowfish_decrypt key = object val ckey = let kl = String.length key in if kl >= 4 && kl <= 56 then blowfish_cook_key key else raise(Error Wrong_key_size) method blocksize = 8 method transform src src_ofs dst dst_ofs = if src_ofs < 0 || src_ofs > Bytes.length src - 8 || dst_ofs < 0 || dst_ofs > Bytes.length dst - 8 then invalid_arg "blowfish#transform"; blowfish_decrypt ckey src src_ofs dst dst_ofs method wipe = wipe_bytes ckey end class des direction key = object val ckey = if String.length key = 8 then des_cook_key key 0 direction else raise(Error Wrong_key_size) method blocksize = 8 method transform src src_ofs dst dst_ofs = if src_ofs < 0 || src_ofs > Bytes.length src - 8 || dst_ofs < 0 || dst_ofs > Bytes.length dst - 8 then invalid_arg "des#transform"; des_transform ckey src src_ofs dst dst_ofs method wipe = wipe_bytes ckey end class des_encrypt = des Encrypt class des_decrypt = des Decrypt class triple_des_encrypt key = let _ = let kl = String.length key in if kl <> 16 && kl <> 24 then raise (Error Wrong_key_size) in let ckey1 = des_cook_key key 0 Encrypt in let ckey2 = des_cook_key key 8 Decrypt in let ckey3 = if String.length key = 24 then des_cook_key key 16 Encrypt else ckey1 in object method blocksize = 8 method transform src src_ofs dst dst_ofs = if src_ofs < 0 || src_ofs > Bytes.length src - 8 || dst_ofs < 0 || dst_ofs > Bytes.length dst - 8 then invalid_arg "triple_des#transform"; des_transform ckey1 src src_ofs dst dst_ofs; des_transform ckey2 dst dst_ofs dst dst_ofs; des_transform ckey3 dst dst_ofs dst dst_ofs method wipe = wipe_bytes ckey1; wipe_bytes ckey2; wipe_bytes ckey3 end class triple_des_decrypt key = let _ = let kl = String.length key in if kl <> 16 && kl <> 24 then raise (Error Wrong_key_size) in let ckey3 = des_cook_key key 0 Decrypt in let ckey2 = des_cook_key key 8 Encrypt in let ckey1 = if String.length key = 24 then des_cook_key key 16 Decrypt else ckey3 in object method blocksize = 8 method transform src src_ofs dst dst_ofs = if src_ofs < 0 || src_ofs > Bytes.length src - 8 || dst_ofs < 0 || dst_ofs > Bytes.length dst - 8 then invalid_arg "triple_des#transform"; des_transform ckey1 src src_ofs dst dst_ofs; des_transform ckey2 dst dst_ofs dst dst_ofs; des_transform ckey3 dst dst_ofs dst dst_ofs method wipe = wipe_bytes ckey1; wipe_bytes ckey2; wipe_bytes ckey3 end (* Chaining modes *) let make_initial_iv blocksize = function | None -> Bytes.make blocksize '\000' | Some s -> if String.length s <> blocksize then raise (Error Wrong_IV_size); Bytes.of_string s class cbc_encrypt ?iv:iv_init (cipher : block_cipher) = let blocksize = cipher#blocksize in object(self) val iv = make_initial_iv blocksize iv_init method blocksize = blocksize method transform src src_off dst dst_off = xor_bytes src src_off iv 0 blocksize; cipher#transform iv 0 dst dst_off; Bytes.blit dst dst_off iv 0 blocksize method wipe = cipher#wipe; wipe_bytes iv end class cbc_decrypt ?iv:iv_init (cipher : block_cipher) = let blocksize = cipher#blocksize in object(self) val iv = make_initial_iv blocksize iv_init val next_iv = Bytes.create blocksize method blocksize = blocksize method transform src src_off dst dst_off = Bytes.blit src src_off next_iv 0 blocksize; cipher#transform src src_off dst dst_off; xor_bytes iv 0 dst dst_off blocksize; Bytes.blit next_iv 0 iv 0 blocksize method wipe = cipher#wipe; wipe_bytes iv; wipe_bytes next_iv end class cfb_encrypt ?iv:iv_init chunksize (cipher : block_cipher) = let blocksize = cipher#blocksize in let _ = assert (chunksize > 0 && chunksize <= blocksize) in object(self) val iv = make_initial_iv blocksize iv_init val out = Bytes.create blocksize method blocksize = chunksize method transform src src_off dst dst_off = cipher#transform iv 0 out 0; Bytes.blit src src_off dst dst_off chunksize; xor_bytes out 0 dst dst_off chunksize; Bytes.blit iv chunksize iv 0 (blocksize - chunksize); Bytes.blit dst dst_off iv (blocksize - chunksize) chunksize method wipe = cipher#wipe; wipe_bytes iv; wipe_bytes out end class cfb_decrypt ?iv:iv_init chunksize (cipher : block_cipher) = let blocksize = cipher#blocksize in let _ = assert (chunksize > 0 && chunksize <= blocksize) in object(self) val iv = make_initial_iv blocksize iv_init val out = Bytes.create blocksize method blocksize = chunksize method transform src src_off dst dst_off = cipher#transform iv 0 out 0; Bytes.blit iv chunksize iv 0 (blocksize - chunksize); Bytes.blit src src_off iv (blocksize - chunksize) chunksize; Bytes.blit src src_off dst dst_off chunksize; xor_bytes out 0 dst dst_off chunksize method wipe = cipher#wipe; wipe_bytes iv; wipe_bytes out end class ofb ?iv:iv_init chunksize (cipher : block_cipher) = let blocksize = cipher#blocksize in let _ = assert (chunksize > 0 && chunksize <= blocksize) in object(self) val iv = make_initial_iv blocksize iv_init method blocksize = chunksize method transform src src_off dst dst_off = cipher#transform iv 0 iv 0; Bytes.blit src src_off dst dst_off chunksize; xor_bytes iv 0 dst dst_off chunksize method wipe = cipher#wipe; wipe_bytes iv end let rec increment_counter c lim pos = if pos >= lim then begin let i = 1 + Char.code (Bytes.get c pos) in Bytes.set c pos (Char.unsafe_chr i); if i = 0x100 then increment_counter c lim (pos - 1) end class ctr ?iv:iv_init ?inc (cipher : block_cipher) = let blocksize = cipher#blocksize in let nincr = match inc with | None -> blocksize | Some n -> assert (n > 0 && n <= blocksize); n in object(self) val iv = make_initial_iv blocksize iv_init val out = Bytes.create blocksize val mutable max_transf = if nincr < 8 then Int64.(shift_left 1L (nincr * 8)) else 0L method blocksize = blocksize method transform src src_off dst dst_off = cipher#transform iv 0 out 0; Bytes.blit src src_off dst dst_off blocksize; xor_bytes out 0 dst dst_off blocksize; increment_counter iv (blocksize - nincr) (blocksize - 1); let m = Int64.pred max_transf in if m = 0L then raise (Error Message_too_long); max_transf <- m method wipe = cipher#wipe; wipe_bytes iv; wipe_bytes out end (* Wrapping of a block cipher as a transform *) class cipher (cipher : block_cipher) = let blocksize = cipher#blocksize in object(self) val ibuf = Bytes.create blocksize val mutable used = 0 inherit buffered_output (max 256 (2 * blocksize)) as output_buffer method input_block_size = blocksize method output_block_size = blocksize method put_substring src ofs len = if len <= 0 then () else if used + len <= blocksize then begin (* Just accumulate len characters in ibuf *) Bytes.blit src ofs ibuf used len; used <- used + len end else begin (* Fill buffer and run it through cipher *) let n = blocksize - used in Bytes.blit src ofs ibuf used n; self#ensure_capacity blocksize; cipher#transform ibuf 0 obuf oend; oend <- oend + blocksize; used <- 0; (* Recurse on remainder of string *) self#put_substring src (ofs + n) (len - n) end method put_string s = self#put_substring (Bytes.unsafe_of_string s) 0 (String.length s) method put_char c = if used < blocksize then begin Bytes.set ibuf used c; used <- used + 1 end else begin self#ensure_capacity blocksize; cipher#transform ibuf 0 obuf oend; oend <- oend + blocksize; Bytes.set ibuf 0 c; used <- 1 end method put_byte b = self#put_char (Char.unsafe_chr b) method wipe = cipher#wipe; output_buffer#wipe; wipe_bytes ibuf method flush = if used = 0 then () else if used = blocksize then begin self#ensure_capacity blocksize; cipher#transform ibuf 0 obuf oend; used <- 0; oend <- oend + blocksize end else raise (Error Wrong_data_length) method finish = self#flush end (* Block cipher with padding *) class cipher_padded_encrypt (padding : Padding.scheme) (cipher : block_cipher) = let blocksize = cipher#blocksize in object(self) inherit cipher cipher method input_block_size = 1 method finish = if used >= blocksize then begin self#ensure_capacity blocksize; cipher#transform ibuf 0 obuf oend; oend <- oend + blocksize; used <- 0 end; padding#pad ibuf used; self#ensure_capacity blocksize; cipher#transform ibuf 0 obuf oend; oend <- oend + blocksize end class cipher_padded_decrypt (padding : Padding.scheme) (cipher : block_cipher) = let blocksize = cipher#blocksize in object(self) inherit cipher cipher method output_block_size = 1 method finish = if used <> blocksize then raise (Error Wrong_data_length); cipher#transform ibuf 0 ibuf 0; let valid = padding#strip ibuf in self#ensure_capacity valid; Bytes.blit ibuf 0 obuf oend valid; oend <- oend + valid end (* Wrapping of a block cipher as a MAC, using CBC mode *) class mac ?iv:iv_init ?(pad: Padding.scheme option) (cipher : block_cipher) = let blocksize = cipher#blocksize in object(self) val iv = make_initial_iv blocksize iv_init val buffer = Bytes.create blocksize val mutable used = 0 method hash_size = blocksize method add_substring src src_ofs len = let rec add src_ofs len = if len <= 0 then () else if used + len <= blocksize then begin (* Just accumulate len characters in buffer *) Bytes.blit src src_ofs buffer used len; used <- used + len end else begin (* Fill buffer and run it through cipher *) let n = blocksize - used in Bytes.blit src src_ofs buffer used n; xor_bytes iv 0 buffer 0 blocksize; cipher#transform buffer 0 iv 0; used <- 0; (* Recurse on remainder of string *) add (src_ofs + n) (len - n) end in add src_ofs len method add_string s = self#add_substring (Bytes.unsafe_of_string s) 0 (String.length s) method add_char c = if used < blocksize then begin Bytes.set buffer used c; used <- used + 1 end else begin xor_bytes iv 0 buffer 0 blocksize; cipher#transform buffer 0 iv 0; Bytes.set buffer 0 c; used <- 1 end method add_byte b = self#add_char (Char.unsafe_chr b) method wipe = cipher#wipe; wipe_bytes buffer; wipe_bytes iv method result = if used = blocksize then begin xor_bytes iv 0 buffer 0 blocksize; cipher#transform buffer 0 iv 0; used <- 0 end; begin match pad with None -> if used <> 0 then raise (Error Wrong_data_length) | Some p -> p#pad buffer used; xor_bytes iv 0 buffer 0 blocksize; cipher#transform buffer 0 iv 0; used <- 0 end; Bytes.to_string iv end class mac_final_triple ?iv ?pad (cipher1 : block_cipher) (cipher2 : block_cipher) (cipher3 : block_cipher) = let _ = if cipher1#blocksize <> cipher2#blocksize || cipher2#blocksize <> cipher3#blocksize then raise(Error Incompatible_block_size) in object inherit mac ?iv ?pad cipher1 as super method result = let r = Bytes.of_string super#result in cipher2#transform r 0 r 0; cipher3#transform r 0 r 0; Bytes.unsafe_to_string r method wipe = super#wipe; cipher2#wipe; cipher3#wipe end (* Wrapping of a block ciper as a MAC, in CMAC mode (a.k.a. OMAC1) *) class cmac ?iv:iv_init (cipher : block_cipher) k1 k2 = object (self) inherit mac ?iv:iv_init cipher as super method result = let blocksize = cipher#blocksize in let k' = if used = blocksize then k1 else (Padding._8000#pad buffer used; k2) in xor_bytes iv 0 buffer 0 blocksize; xor_bytes k' 0 buffer 0 blocksize; cipher#transform buffer 0 iv 0; used <- 0; (* really useful? *) Bytes.to_string iv method wipe = super#wipe; wipe_bytes k1; wipe_bytes k2 end end (* Stream ciphers *) module Stream = struct class type stream_cipher = object method transform: bytes -> int -> bytes -> int -> int -> unit method wipe: unit end class arcfour key = object val ckey = if String.length key > 0 && String.length key <= 256 then arcfour_cook_key key else raise(Error Wrong_key_size) method transform src src_ofs dst dst_ofs len = if len < 0 || src_ofs < 0 || src_ofs > Bytes.length src - len || dst_ofs < 0 || dst_ofs > Bytes.length dst - len then invalid_arg "arcfour#transform"; arcfour_transform ckey src src_ofs dst dst_ofs len method wipe = wipe_bytes ckey end class chacha20 ?iv ?(ctr = 0L) key = object val ckey = if not (String.length key = 16 || String.length key = 32) then raise (Error Wrong_key_size); let iv = match iv with | None -> Bytes.make 8 '\000' | Some s -> if String.length s = 8 || String.length s = 12 && ctr < 0x1_000_000L then Bytes.of_string s else raise (Error Wrong_IV_size) in chacha20_cook_key key iv ctr method transform src src_ofs dst dst_ofs len = if len < 0 || src_ofs < 0 || src_ofs > Bytes.length src - len || dst_ofs < 0 || dst_ofs > Bytes.length dst - len then invalid_arg "chacha20#transform"; chacha20_transform ckey src src_ofs dst dst_ofs len method wipe = wipe_bytes ckey end (* Wrapping of a stream cipher as a cipher *) class cipher (cipher : stream_cipher) = object(self) val charbuf = Bytes.create 1 inherit buffered_output 256 as output_buffer method input_block_size = 1 method output_block_size = 1 method put_substring src ofs len = self#ensure_capacity len; cipher#transform src ofs obuf oend len; oend <- oend + len method put_string s = self#put_substring (Bytes.unsafe_of_string s) 0 (String.length s) method put_char c = Bytes.set charbuf 0 c; self#ensure_capacity 1; cipher#transform charbuf 0 obuf oend 1; oend <- oend + 1 method put_byte b = self#put_char (Char.unsafe_chr b) method flush = () method finish = () method wipe = cipher#wipe; output_buffer#wipe; wipe_bytes charbuf end end (* Hash functions *) module Hash = struct class sha1 = object(self) val context = sha1_init() method hash_size = 20 method add_substring src ofs len = if ofs < 0 || len < 0 || ofs > Bytes.length src - len then invalid_arg "sha1#add_substring"; sha1_update context src ofs len method add_string src = sha1_update context (Bytes.unsafe_of_string src) 0 (String.length src) method add_char c = self#add_string (String.make 1 c) method add_byte b = self#add_char (Char.unsafe_chr b) method result = sha1_final context method wipe = wipe_bytes context end let sha1 () = new sha1 class sha224 = object(self) val context = sha224_init() method hash_size = 24 method add_substring src ofs len = if ofs < 0 || len < 0 || ofs > Bytes.length src - len then invalid_arg "sha224#add_substring"; sha256_update context src ofs len method add_string src = sha256_update context (Bytes.unsafe_of_string src) 0 (String.length src) method add_char c = self#add_string (String.make 1 c) method add_byte b = self#add_char (Char.unsafe_chr b) method result = sha224_final context method wipe = wipe_bytes context end let sha224 () = new sha224 class sha256 = object(self) val context = sha256_init() method hash_size = 32 method add_substring src ofs len = if ofs < 0 || len < 0 || ofs > Bytes.length src - len then invalid_arg "sha256#add_substring"; sha256_update context src ofs len method add_string src = sha256_update context (Bytes.unsafe_of_string src) 0 (String.length src) method add_char c = self#add_string (String.make 1 c) method add_byte b = self#add_char (Char.unsafe_chr b) method result = sha256_final context method wipe = wipe_bytes context end let sha256 () = new sha256 class sha384 = object(self) val context = sha384_init() method hash_size = 48 method add_substring src ofs len = if ofs < 0 || len < 0 || ofs > Bytes.length src - len then invalid_arg "sha384#add_substring"; sha512_update context src ofs len method add_string src = sha512_update context (Bytes.unsafe_of_string src) 0 (String.length src) method add_char c = self#add_string (String.make 1 c) method add_byte b = self#add_char (Char.unsafe_chr b) method result = sha384_final context method wipe = wipe_bytes context end let sha384 () = new sha384 class sha512 = object(self) val context = sha512_init() method hash_size = 64 method add_substring src ofs len = if ofs < 0 || len < 0 || ofs > Bytes.length src - len then invalid_arg "sha512#add_substring"; sha512_update context src ofs len method add_string src = sha512_update context (Bytes.unsafe_of_string src) 0 (String.length src) method add_char c = self#add_string (String.make 1 c) method add_byte b = self#add_char (Char.unsafe_chr b) method result = sha512_final context method wipe = wipe_bytes context end let sha512 () = new sha512 let sha2 sz = match sz with | 224 -> new sha224 | 256 -> new sha256 | 384 -> new sha384 | 512 -> new sha512 | _ -> raise (Error Wrong_key_size) class sha3 sz official = object(self) val context = if sz = 224 || sz = 256 || sz = 384 || sz = 512 then sha3_init sz else raise (Error Wrong_key_size) method hash_size = sz / 8 method add_substring src ofs len = if ofs < 0 || len < 0 || ofs > Bytes.length src - len then invalid_arg ((if official then "sha3" else "keccak")^"#add_substring"); sha3_absorb context src ofs len method add_string src = sha3_absorb context (Bytes.unsafe_of_string src) 0 (String.length src) method add_char c = self#add_string (String.make 1 c) method add_byte b = self#add_char (Char.unsafe_chr b) method result = sha3_extract official context method wipe = sha3_wipe context end let sha3 sz = new sha3 sz true let keccak sz = new sha3 sz false class ripemd160 = object(self) val context = ripemd160_init() method hash_size = 32 method add_substring src ofs len = if ofs < 0 || len < 0 || ofs > Bytes.length src - len then invalid_arg "ripemd160#add_substring"; ripemd160_update context src ofs len method add_string src = ripemd160_update context (Bytes.unsafe_of_string src) 0 (String.length src) method add_char c = self#add_string (String.make 1 c) method add_byte b = self#add_char (Char.unsafe_chr b) method result = ripemd160_final context method wipe = wipe_bytes context end let ripemd160 () = new ripemd160 class md5 = object(self) val context = md5_init() method hash_size = 16 method add_substring src ofs len = if ofs < 0 || len < 0 || ofs > Bytes.length src - len then invalid_arg "md5#add_substring"; md5_update context src ofs len method add_string src = md5_update context (Bytes.unsafe_of_string src) 0 (String.length src) method add_char c = self#add_string (String.make 1 c) method add_byte b = self#add_char (Char.unsafe_chr b) method result = md5_final context method wipe = wipe_bytes context end let md5 () = new md5 class blake2b sz key = object(self) val context = if sz >= 8 && sz <= 512 && sz mod 8 = 0 && String.length key <= 64 then blake2b_init (sz / 8) key else raise (Error Wrong_key_size) method hash_size = sz / 8 method add_substring src ofs len = if ofs < 0 || len < 0 || ofs > Bytes.length src - len then invalid_arg "blake2b#add_substring"; blake2b_update context src ofs len method add_string src = blake2b_update context (Bytes.unsafe_of_string src) 0 (String.length src) method add_char c = self#add_string (String.make 1 c) method add_byte b = self#add_char (Char.unsafe_chr b) method result = blake2b_final context (sz / 8) method wipe = wipe_bytes context end let blake2b sz = new blake2b sz "" let blake2b512 () = new blake2b 512 "" class blake2s sz key = object(self) val context = if sz >= 8 && sz <= 256 && sz mod 8 = 0 && String.length key <= 32 then blake2s_init (sz / 8) key else raise (Error Wrong_key_size) method hash_size = sz / 8 method add_substring src ofs len = if ofs < 0 || len < 0 || ofs > Bytes.length src - len then invalid_arg "blake2s#add_substring"; blake2s_update context src ofs len method add_string src = blake2s_update context (Bytes.unsafe_of_string src) 0 (String.length src) method add_char c = self#add_string (String.make 1 c) method add_byte b = self#add_char (Char.unsafe_chr b) method result = blake2s_final context (sz / 8) method wipe = wipe_bytes context end let blake2s sz = new blake2s sz "" let blake2s256 () = new blake2s 256 "" class blake3 key sz = object(self) val context = if sz > 0 && sz mod 8 = 0 && (String.length key = 0 || String.length key = 32) then blake3_init key else raise (Error Wrong_key_size) method hash_size = sz / 8 method add_substring src ofs len = if ofs < 0 || len < 0 || ofs > Bytes.length src - len then invalid_arg "blake3#add_substring"; blake3_update context src ofs len method add_string src = blake3_update context (Bytes.unsafe_of_string src) 0 (String.length src) method add_char c = self#add_string (String.make 1 c) method add_byte b = self#add_char (Char.unsafe_chr b) method result = blake3_final context (sz / 8) method wipe = blake3_wipe context end let blake3 sz = new blake3 "" sz let blake3_256 () = new blake3 "" 256 end (* High-level entry points for ciphers *) module Cipher = struct type direction = dir = Encrypt | Decrypt type chaining_mode = ECB | CBC | CFB of int | OFB of int | CTR | CTR_N of int let make_block_cipher ?(mode = CBC) ?pad ?iv dir block_cipher = let chained_cipher = match (mode, dir) with (ECB, _) -> block_cipher | (CBC, Encrypt) -> new Block.cbc_encrypt ?iv block_cipher | (CBC, Decrypt) -> new Block.cbc_decrypt ?iv block_cipher | (CFB n, Encrypt) -> new Block.cfb_encrypt ?iv n block_cipher | (CFB n, Decrypt) -> new Block.cfb_decrypt ?iv n block_cipher | (OFB n, _) -> new Block.ofb ?iv n block_cipher | (CTR, _) -> new Block.ctr ?iv block_cipher | (CTR_N n, _) -> new Block.ctr ?iv ~inc:n block_cipher in match pad with None -> new Block.cipher chained_cipher | Some p -> match dir with Encrypt -> new Block.cipher_padded_encrypt p chained_cipher | Decrypt -> new Block.cipher_padded_decrypt p chained_cipher let normalize_dir mode dir = match mode with | Some(CFB _) | Some(OFB _) | Some(CTR) | Some(CTR_N _) -> Encrypt | _ -> dir let aes ?mode ?pad ?iv key dir = make_block_cipher ?mode ?pad ?iv dir (match normalize_dir mode dir with Encrypt -> new Block.aes_encrypt key | Decrypt -> new Block.aes_decrypt key) let blowfish ?mode ?pad ?iv key dir = make_block_cipher ?mode ?pad ?iv dir (match normalize_dir mode dir with Encrypt -> new Block.blowfish_encrypt key | Decrypt -> new Block.blowfish_decrypt key) let des ?mode ?pad ?iv key dir = make_block_cipher ?mode ?pad ?iv dir (new Block.des (normalize_dir mode dir) key) let triple_des ?mode ?pad ?iv key dir = make_block_cipher ?mode ?pad ?iv dir (match normalize_dir mode dir with Encrypt -> new Block.triple_des_encrypt key | Decrypt -> new Block.triple_des_decrypt key) let arcfour key dir = new Stream.cipher (new Stream.arcfour key) let chacha20 ?iv ?ctr key dir = new Stream.cipher (new Stream.chacha20 key ?iv ?ctr) end (* The hmac construction *) module HMAC(H: sig class h: hash val blocksize: int end) = struct let hmac_pad key byte = let key = if String.length key > H.blocksize then hash_string (new H.h) key else key in let r = Bytes.make H.blocksize (Char.chr byte) in xor_string key 0 r 0 (String.length key); r class hmac key = object(self) inherit H.h as super initializer (let b = hmac_pad key 0x36 in self#add_substring b 0 (Bytes.length b); wipe_bytes b) method result = let h' = new H.h in let b = hmac_pad key 0x5C in h'#add_substring b 0 (Bytes.length b); wipe_bytes b; h'#add_string (super#result); let r = h'#result in h'#wipe; r end end (* High-level entry points for MACs *) module MAC = struct module HMAC_SHA1 = HMAC(struct class h = Hash.sha1 let blocksize = 64 end) module HMAC_SHA256 = HMAC(struct class h = Hash.sha256 let blocksize = 64 end) module HMAC_SHA384 = HMAC(struct class h = Hash.sha384 let blocksize = 128 end) module HMAC_SHA512 = HMAC(struct class h = Hash.sha512 let blocksize = 128 end) module HMAC_RIPEMD160 = HMAC(struct class h = Hash.ripemd160 let blocksize = 64 end) module HMAC_MD5 = HMAC(struct class h = Hash.md5 let blocksize = 64 end) let hmac_sha1 key = new HMAC_SHA1.hmac key let hmac_sha256 key = new HMAC_SHA256.hmac key let hmac_sha384 key = new HMAC_SHA384.hmac key let hmac_sha512 key = new HMAC_SHA512.hmac key let hmac_ripemd160 key = new HMAC_RIPEMD160.hmac key let hmac_md5 key = new HMAC_MD5.hmac key let blake2b sz key = new Hash.blake2b sz key let blake2b512 key = new Hash.blake2b 512 key let blake2s sz key = new Hash.blake2s sz key let blake2s256 key = new Hash.blake2s 256 key let blake3 sz key = new Hash.blake3 key sz let blake3_256 key = new Hash.blake3 key 256 let aes ?iv ?pad key = new Block.mac ?iv ?pad (new Block.aes_encrypt key) let des ?iv ?pad key = new Block.mac ?iv ?pad (new Block.des_encrypt key) let triple_des ?iv ?pad key = new Block.mac ?iv ?pad (new Block.triple_des_encrypt key) let des_final_triple_des ?iv ?pad key = let kl = String.length key in if kl <> 16 && kl <> 24 then raise (Error Wrong_key_size); let k1 = String.sub key 0 8 in let k2 = String.sub key 8 8 in let k3 = if kl = 24 then String.sub key 16 8 else k1 in let c1 = new Block.des_encrypt k1 and c2 = new Block.des_decrypt k2 and c3 = new Block.des_encrypt k3 in wipe_string k1; wipe_string k2; wipe_string k3; new Block.mac_final_triple ?iv ?pad c1 c2 c3 let aes_cmac ?iv key = let cipher = new Block.aes_encrypt key in let b = Bytes.make 16 '\000' in let l = Bytes.create 16 in cipher#transform b 0 l 0; (* l = AES-128(K, 000...000 *) Bytes.set b 15 '\x87'; (* b = the Rb constant *) let k1 = Bytes.create 16 in shl1_bytes l 0 k1 0 16; if Char.code (Bytes.get l 0) land 0x80 > 0 then xor_bytes b 0 k1 0 16; let k2 = Bytes.create 16 in shl1_bytes k1 0 k2 0 16; if Char.code (Bytes.get k1 0) land 0x80 > 0 then xor_bytes b 0 k2 0 16; wipe_bytes l; new Block.cmac ?iv cipher k1 k2 class siphash sz key = object(self) val context = if String.length key = 16 && (sz = 64 || sz = 128) then siphash_init key (sz / 8) else raise (Error Wrong_key_size) method hash_size = sz / 8 method add_substring src ofs len = if ofs < 0 || len < 0 || ofs > Bytes.length src - len then invalid_arg "siphash#add_substring"; siphash_update context src ofs len method add_string src = siphash_update context (Bytes.unsafe_of_string src) 0 (String.length src) method add_char c = self#add_string (String.make 1 c) method add_byte b = self#add_char (Char.unsafe_chr b) method result = siphash_final context (sz / 8) method wipe = wipe_bytes context end let siphash key = new siphash 64 key let siphash128 key = new siphash 128 key end (* Authenticated encryption with associated data *) module AEAD = struct type direction = dir = Encrypt | Decrypt (* AES-GCM *) (* The H multiplier for GHASH is derived from the AES key by encrypting the all-zero block. *) let ghash_multiplier (aes: Block.block_cipher) = let b = Bytes.make 16 '\000' in aes#transform b 0 b 0; ghash_init b (* Add a block to the rolling MAC. len must be between 0 and 16. If less than 16, we logically pad with zeros at the end, i.e. we "xor with zero" (= keep unchanged) the MAC bytes between len and 16. *) let ghash_block h mac buf ofs len = xor_bytes buf ofs mac 0 len; ghash_mult h mac let ghash_block_s h mac buf ofs len = xor_string buf ofs mac 0 len; ghash_mult h mac (* Hash the given string, with zero padding. Used for the non-encrypted authenticated data and for counter generation. *) let ghash_string h msg = let mac = Bytes.make 16 '\000' in let l = String.length msg in let i = ref 0 in while !i + 16 <= l do ghash_block_s h mac msg !i 16; i := !i + 16 done; if !i < l then ghash_block_s h mac msg !i (l - !i); mac (* Produce the final authentication tag *) let ghash_final h mac headerlen cipherlen e0 = let buf = Bytes.create 16 in (* Hash the extra block containing the lengths *) Bytes.set_int64_be buf 0 (Int64.mul headerlen 8L); (* in bits *) Bytes.set_int64_be buf 8 (Int64.mul cipherlen 8L); (* in bits *) ghash_block h mac buf 0 16; (* Authentication tag = final MAC xor encryption of the IV *) Bytes.blit mac 0 buf 0 16; xor_bytes e0 0 buf 0 16; Bytes.to_string buf (* Initial value of the counter *) let counter0 h iv = if String.length iv = 12 then Bytes.of_string (iv ^ "\000\000\000\001") else begin let mac = ghash_string h iv in let buf = Bytes.make 16 '\000' in Bytes.set_int64_be buf 8 (Int64.mul (Int64.of_int (String.length iv)) 8L); ghash_block h mac buf 0 16; mac end (* Encryption of the initial counter *) let enc_initial_counter (aes: Block.block_cipher) counter0 = let b = Bytes.create 16 in aes#transform counter0 0 b 0; b (* CTR encryption / decryption *) let ctr_enc_dec (aes: Block.block_cipher) ctr buf src soff dst doff len = Block.increment_counter ctr 12 15; aes#transform ctr 0 buf 0; xor_bytes src soff buf 0 len; Bytes.blit buf 0 dst doff len class aes_gcm_encrypt ?(header = "") ~iv key = (* The AES block cipher *) let aes = new Block.aes_encrypt key in (* The multiplier for the GHASH MAC *) let h = ghash_multiplier aes in (* The counter for use in CTR mode. *) let ctr = counter0 h iv in (* The encryption of the initial counter, to be used for the final MAC *) let e0 = enc_initial_counter aes ctr in (* The current MAC, initialized with the header (the non-encrypted authenticated data) *) let mac = ghash_string h header in (* Lengths of the authenticated data and the encrypted data *) let headerlen = Int64.of_int (String.length header) and cipherlen = ref 0L in (* A wrapper around the block cipher that - performs encryption in CTR mode - updates the MAC - updates the length of encrypted data *) let enc_wrapped : Block.block_cipher = let buf = Bytes.create 16 in object method blocksize = 16 method wipe = aes#wipe method transform src soff dst doff = ctr_enc_dec aes ctr buf src soff dst doff 16; ghash_block h mac dst doff 16; cipherlen := Int64.(add !cipherlen 16L); if !cipherlen > 0xfffffffe0L then raise (Error Message_too_long) end in object(self) inherit (Block.cipher enc_wrapped) method input_block_size = 1 method output_block_size = 1 method tag_size = 16 method finish_and_get_tag = if used > 0 then begin let buf = Bytes.create 16 in (* Encrypt final block *) self#ensure_capacity used; ctr_enc_dec aes ctr buf ibuf 0 obuf oend used; (* Hash final block padded with zeros *) ghash_block h mac obuf oend used; oend <- oend + used; cipherlen := Int64.(add !cipherlen (of_int used)); if !cipherlen > 0xfffffffe0L then raise (Error Message_too_long) end; (* Produce authentication tag *) ghash_final h mac headerlen !cipherlen e0 end class aes_gcm_decrypt ?(header = "") ~iv key = (* The AES block cipher *) let aes = new Block.aes_encrypt key in (* The multiplier for the GHASH MAC *) let h = ghash_multiplier aes in (* The counter for use in CTR mode. *) let ctr = counter0 h iv in (* The encryption of the initial counter, to be used for the final MAC *) let e0 = enc_initial_counter aes ctr in (* The current MAC, initialized with the header (the non-encrypted authenticated data) *) let mac = ghash_string h header in (* Lengths of the authenticated data and the encrypted data *) let headerlen = Int64.of_int (String.length header) and cipherlen = ref 0L in (* A wrapper around the block cipher that - updates the MAC - performs decryption in CTR mode - updates the length of encrypted data *) let dec_wrapped : Block.block_cipher = let buf = Bytes.create 16 in object method blocksize = 16 method wipe = aes#wipe method transform src soff dst doff = ghash_block h mac src soff 16; ctr_enc_dec aes ctr buf src soff dst doff 16; cipherlen := Int64.(add !cipherlen 16L) end in object(self) inherit (Block.cipher dec_wrapped) method input_block_size = 1 method output_block_size = 1 method tag_size = 16 method finish_and_get_tag = if used > 0 then begin let buf = Bytes.create 16 in (* Hash final block padded with zeros *) ghash_block h mac ibuf 0 used; (* Decrypt final block *) self#ensure_capacity used; ctr_enc_dec aes ctr buf ibuf 0 obuf oend used; oend <- oend + used; cipherlen := Int64.(add !cipherlen (of_int used)) end; (* Produce authentication tag *) ghash_final h mac headerlen !cipherlen e0 end let aes_gcm ?header ~iv key dir = match dir with | Encrypt -> (new aes_gcm_encrypt ?header ~iv key :> authenticated_transform) | Decrypt -> (new aes_gcm_decrypt ?header ~iv key :> authenticated_transform) (* Chacha20-Poly1305 *) let poly1305_update_pad h n = let n = (0x10 - n) land 0xF in if n > 0 then poly1305_update h (Bytes.make n '\000') 0 n let poly1305_init_hash cha header = let buf = Bytes.make 64 '\000' in cha#transform buf 0 buf 0 64; let h = poly1305_init buf in (* only the first 32 bytes are used *) wipe_bytes buf; poly1305_update h (Bytes.unsafe_of_string header) 0 (String.length header); (* Pad header to a multiple of 16 bytes *) poly1305_update_pad h (String.length header land 0xF); h let poly1305_finish_and_get_tag h headerlen cipherlen = (* Pad ciphertext to a multiple of 16 bytes *) poly1305_update_pad h Int64.(to_int (logand cipherlen 0xFL)); (* Add lengths as 64-bit little-endian numbers *) let buf = Bytes.create 16 in Bytes.set_int64_le buf 0 headerlen; Bytes.set_int64_le buf 8 cipherlen; poly1305_update h buf 0 16; (* The final hash is the authentication tag *) poly1305_final h class chapoly_encrypt ?(header = "") ~iv key = (* The Chacha20 stream cipher *) let cha = new Stream.chacha20 ~iv key in (* The Poly1305 hash *) let h = poly1305_init_hash cha header in (* Lengths of the authenticated data and the encrypted data *) let headerlen = Int64.of_int (String.length header) and cipherlen = ref 0L in (* Maximum length for encrypted data *) let maxlen = if String.length iv = 12 then 0x4000000000L else Int64.max_int in (* The stream cipher that wraps Chacha20 with hash updates *) let enc = object method transform src soff dst doff len = cha#transform src soff dst doff len; poly1305_update h dst doff len; cipherlen := Int64.(add !cipherlen (of_int len)); if !cipherlen > maxlen then raise (Error Message_too_long) method wipe = cha#wipe; wipe_bytes h end in object(self) inherit (Stream.cipher enc) method input_block_size = 1 method output_block_size = 1 method tag_size = 16 method finish_and_get_tag = poly1305_finish_and_get_tag h headerlen !cipherlen end class chapoly_decrypt ?(header = "") ~iv key = (* The Chacha20 stream cipher *) let cha = new Stream.chacha20 ~iv key in (* The Poly1305 hash *) let h = poly1305_init_hash cha header in (* Lengths of the authenticated data and the encrypted data *) let headerlen = Int64.of_int (String.length header) and cipherlen = ref 0L in (* The stream cipher that wraps Chacha20 with hash updates *) let enc = object method transform src soff dst doff len = poly1305_update h src soff len; cha#transform src soff dst doff len; cipherlen := Int64.(add !cipherlen (of_int len)) method wipe = cha#wipe; wipe_bytes h end in object(self) inherit (Stream.cipher enc) method input_block_size = 1 method output_block_size = 1 method tag_size = 16 method finish_and_get_tag = poly1305_finish_and_get_tag h headerlen !cipherlen end let chacha20_poly1305 ?header ~iv key dir = match dir with | Encrypt -> (new chapoly_encrypt ?header ~iv key :> authenticated_transform) | Decrypt -> (new chapoly_decrypt ?header ~iv key :> authenticated_transform) end (* Random number generation *) module Random = struct class type rng = object method random_bytes: bytes -> int -> int -> unit method wipe: unit end let string rng len = let res = Bytes.create len in rng#random_bytes res 0 len; Bytes.unsafe_to_string res type system_rng_handle external get_system_rng: unit -> system_rng_handle = "caml_get_system_rng" external close_system_rng: system_rng_handle -> unit = "caml_close_system_rng" external system_rng_random_bytes: system_rng_handle -> bytes -> int -> int -> bool = "caml_system_rng_random_bytes" class system_rng = object(self) val h = get_system_rng () method random_bytes buf ofs len = if ofs < 0 || len < 0 || ofs > Bytes.length buf - len then invalid_arg "random_bytes"; if system_rng_random_bytes h buf ofs len then () else raise(Error Entropy_source_closed) method wipe = close_system_rng h end let system_rng () = try new system_rng with Not_found -> raise(Error No_entropy_source) class device_rng filename = object(self) val fd = Unix.openfile filename [Unix.O_RDONLY; Unix.O_CLOEXEC] 0 method random_bytes buf ofs len = if len > 0 then begin let n = Unix.read fd buf ofs len in if n = 0 then raise(Error Entropy_source_closed); if n < len then self#random_bytes buf (ofs + n) (len - n) end method wipe = Unix.close fd end let device_rng filename = new device_rng filename external hardware_rng_available: unit -> bool = "caml_hardware_rng_available" external hardware_rng_random_bytes: bytes -> int -> int -> bool = "caml_hardware_rng_random_bytes" class hardware_rng = object method random_bytes buf ofs len = if ofs < 0 || len < 0 || ofs > Bytes.length buf - len then invalid_arg "hardware_rng#random_bytes"; if not (hardware_rng_random_bytes buf ofs len) then raise (Error Entropy_source_closed) method wipe = () end let hardware_rng () = if hardware_rng_available () then new hardware_rng else raise (Error No_entropy_source) class no_rng = object method random_bytes (buf:bytes) (ofs:int) (len:int) : unit = raise (Error No_entropy_source) method wipe = () end let secure_rng = try new system_rng with Not_found -> try new device_rng "/dev/random" with Unix.Unix_error(_,_,_) -> if hardware_rng_available () then new hardware_rng else new no_rng class pseudo_rng seed = let _ = if String.length seed < 16 then raise (Error Seed_too_short) in object (self) val ckey = let l = String.length seed in chacha20_cook_key (if l >= 32 then String.sub seed 0 32 else if l > 16 then seed ^ String.make (32 - l) '\000' else seed) (Bytes.make 8 '\000') 0L method random_bytes buf ofs len = if len < 0 || ofs < 0 || ofs > Bytes.length buf - len then invalid_arg "pseudo_rng#random_bytes" else chacha20_extract ckey buf ofs len method wipe = wipe_bytes ckey; wipe_string seed end let pseudo_rng seed = new pseudo_rng seed class pseudo_rng_aes_ctr seed = let _ = if String.length seed < 16 then raise (Error Seed_too_short) in object (self) val cipher = new Block.aes_encrypt (String.sub seed 0 16) val ctr = Bytes.make 16 '\000' val obuf = Bytes.create 16 val mutable opos = 16 method random_bytes buf ofs len = if len > 0 then begin if opos >= 16 then begin (* Encrypt the counter *) cipher#transform ctr 0 obuf 0; (* Increment the counter *) Block.increment_counter ctr 0 15; (* We have 16 fresh bytes of pseudo-random data *) opos <- 0 end; let r = min (16 - opos) len in Bytes.blit obuf opos buf ofs r; opos <- opos + r; if r < len then self#random_bytes buf (ofs + r) (len - r) end method wipe = wipe_bytes obuf; wipe_string seed end let pseudo_rng_aes_ctr seed = new pseudo_rng_aes_ctr seed end (* RSA operations *) module Bn = CryptokitBignum module RSA = struct type key = { size: int; n: string; e: string; d: string; p: string; q: string; dp: string; dq: string; qinv: string } let wipe_key k = wipe_string k.n; wipe_string k.e; wipe_string k.d; wipe_string k.p; wipe_string k.q; wipe_string k.dp; wipe_string k.dq; wipe_string k.qinv let encrypt key msg = let msg = Bn.of_bytes msg in let n = Bn.of_bytes key.n in let e = Bn.of_bytes key.e in if Bn.compare msg n >= 0 then raise (Error Message_too_long); let r = Bn.mod_power msg e n in let s = Bn.to_bytes ~numbits:key.size r in Bn.wipe msg; Bn.wipe n; Bn.wipe e; Bn.wipe r; s let unwrap_signature = encrypt let decrypt key msg = let msg = Bn.of_bytes msg in let n = Bn.of_bytes key.n in let d = Bn.of_bytes key.d in if Bn.compare msg n >= 0 then raise (Error Message_too_long); let r = Bn.mod_power msg d n in let s = Bn.to_bytes ~numbits:key.size r in Bn.wipe msg; Bn.wipe n; Bn.wipe d; Bn.wipe r; s let sign = decrypt let decrypt_CRT key msg = let msg = Bn.of_bytes msg in let n = Bn.of_bytes key.n in let p = Bn.of_bytes key.p in let q = Bn.of_bytes key.q in let dp = Bn.of_bytes key.dp in let dq = Bn.of_bytes key.dq in let qinv = Bn.of_bytes key.qinv in if Bn.compare msg n >= 0 then raise (Error Message_too_long); let r = Bn.mod_power_CRT msg p q dp dq qinv in let s = Bn.to_bytes ~numbits:key.size r in Bn.wipe msg; Bn.wipe n; Bn.wipe p; Bn.wipe q; Bn.wipe dp; Bn.wipe dq; Bn.wipe qinv; Bn.wipe r; s let sign_CRT = decrypt_CRT let new_key ?(rng = Random.secure_rng) ?e numbits = if numbits < 32 || numbits land 1 > 0 then raise(Error Wrong_key_size); let numbits2 = numbits / 2 in (* Generate primes p, q with numbits / 2 digits. If fixed exponent e, make sure gcd(p-1,e) = 1 and gcd(q-1,e) = 1. *) let rec gen_factor nbits = let n = Bn.random_prime ~rng:(rng#random_bytes) nbits in match e with None -> n | Some e -> if Bn.relative_prime (Bn.sub n Bn.one) (Bn.of_int e) then n else gen_factor nbits in (* Make sure p > q *) let rec gen_factors nbits = let p = gen_factor nbits and q = gen_factor nbits in let cmp = Bn.compare p q in if cmp = 0 then gen_factors nbits else if cmp < 0 then (q, p) else (p, q) in let (p, q) = gen_factors numbits2 in (* p1 = p - 1 and q1 = q - 1 *) let p1 = Bn.sub p Bn.one and q1 = Bn.sub q Bn.one in (* If no fixed exponent specified, generate random exponent e such that gcd(p-1,e) = 1 and gcd(q-1,e) = 1 *) let e = match e with Some e -> Bn.of_int e | None -> let rec gen_exponent () = let n = Bn.random ~rng:(rng#random_bytes) numbits in if Bn.relative_prime n p1 && Bn.relative_prime n q1 then n else gen_exponent () in gen_exponent () in (* n = pq *) let n = Bn.mult p q in (* d = e^-1 mod (p-1)(q-1) *) let d = Bn.mod_inv e (Bn.mult p1 q1) in (* dp = d mod p-1 and dq = d mod q-1 *) let dp = Bn.mod_ d p1 and dq = Bn.mod_ d q1 in (* qinv = q^-1 mod p *) let qinv = Bn.mod_inv q p in (* Build key *) let res = { size = numbits; n = Bn.to_bytes ~numbits:numbits n; e = Bn.to_bytes ~numbits:numbits e; d = Bn.to_bytes ~numbits:numbits d; p = Bn.to_bytes ~numbits:numbits2 p; q = Bn.to_bytes ~numbits:numbits2 q; dp = Bn.to_bytes ~numbits:numbits2 dp; dq = Bn.to_bytes ~numbits:numbits2 dq; qinv = Bn.to_bytes ~numbits:numbits2 qinv } in Bn.wipe n; Bn.wipe e; Bn.wipe d; Bn.wipe p; Bn.wipe q; Bn.wipe p1; Bn.wipe q1; Bn.wipe dp; Bn.wipe dq; Bn.wipe qinv; res end (* Diffie-Hellman key agreement *) module DH = struct type parameters = { p: string; g: string; privlen: int } let new_parameters ?(rng = Random.secure_rng) ?(privlen = 160) numbits = if numbits < 32 || numbits <= privlen then raise(Error Wrong_key_size); let np = Bn.random_prime ~rng:(rng#random_bytes) numbits in let rec find_generator () = let g = Bn.random ~rng:(rng#random_bytes) (numbits - 1) in if Bn.compare g Bn.one <= 0 then find_generator() else g in let ng = find_generator () in { p = Bn.to_bytes ~numbits np; g = Bn.to_bytes ~numbits ng; privlen = privlen } type private_secret = Bn.t let private_secret ?(rng = Random.secure_rng) params = Bn.random ~rng:(rng#random_bytes) params.privlen let message params privsec = Bn.to_bytes ~numbits:(String.length params.p * 8) (Bn.mod_power (Bn.of_bytes params.g) privsec (Bn.of_bytes params.p)) let shared_secret params privsec othermsg = let res = Bn.to_bytes ~numbits:(String.length params.p * 8) (Bn.mod_power (Bn.of_bytes othermsg) privsec (Bn.of_bytes params.p)) in Bn.wipe privsec; res let derive_key ?(diversification = "") sharedsec numbytes = let result = Bytes.create numbytes in let rec derive pos counter = if pos < numbytes then begin let h = hash_string (Hash.sha256()) (diversification ^ sharedsec ^ string_of_int counter) in String.blit h 0 result pos (min (String.length h) (numbytes - pos)); wipe_string h; derive (pos + String.length h) (counter + 1) end in derive 0 1; Bytes.unsafe_to_string result end (* Base64 encoding *) module Base64 = struct let base64_conv_table = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" class encode multiline padding = object (self) method input_block_size = 1 method output_block_size = 1 inherit buffered_output 256 as output_buffer val ibuf = Bytes.create 3 val mutable ipos = 0 val mutable ocolumn = 0 method put_char c = Bytes.set ibuf ipos c; ipos <- ipos + 1; if ipos = 3 then begin let b0 = Char.code (Bytes.get ibuf 0) and b1 = Char.code (Bytes.get ibuf 1) and b2 = Char.code (Bytes.get ibuf 2) in self#ensure_capacity 4; Bytes.set obuf oend base64_conv_table.[b0 lsr 2]; Bytes.set obuf (oend+1) base64_conv_table.[(b0 land 3) lsl 4 + (b1 lsr 4)]; Bytes.set obuf (oend+2) base64_conv_table.[(b1 land 15) lsl 2 + (b2 lsr 6)]; Bytes.set obuf (oend+3) base64_conv_table.[b2 land 63]; oend <- oend + 4; ipos <- 0; ocolumn <- ocolumn + 4; if multiline && ocolumn >= 72 then begin self#ensure_capacity 1; Bytes.set obuf oend '\n'; oend <- oend + 1; ocolumn <- 0 end end method put_substring s ofs len = for i = ofs to ofs + len - 1 do self#put_char (Bytes.get s i) done method put_string s = String.iter self#put_char s method put_byte b = self#put_char (Char.chr b) method flush : unit = raise (Error Wrong_data_length) method finish = begin match ipos with 1 -> self#ensure_capacity 2; let b0 = Char.code (Bytes.get ibuf 0) in Bytes.set obuf oend base64_conv_table.[b0 lsr 2]; Bytes.set obuf (oend+1) base64_conv_table.[(b0 land 3) lsl 4]; oend <- oend + 2 | 2 -> self#ensure_capacity 3; let b0 = Char.code (Bytes.get ibuf 0) and b1 = Char.code (Bytes.get ibuf 1) in Bytes.set obuf oend base64_conv_table.[b0 lsr 2]; Bytes.set obuf (oend+1) base64_conv_table.[(b0 land 3) lsl 4 + (b1 lsr 4)]; Bytes.set obuf (oend+2) (base64_conv_table.[(b1 land 15) lsl 2]); oend <- oend + 3 | _ -> () end; if multiline || padding then begin let num_equals = match ipos with 1 -> 2 | 2 -> 1 | _ -> 0 in self#ensure_capacity num_equals; Bytes.fill obuf oend num_equals '='; oend <- oend + num_equals end; if multiline && ocolumn > 0 then begin self#ensure_capacity 1; Bytes.set obuf oend '\n'; oend <- oend + 1 end; ocolumn <- 0 method wipe = wipe_bytes ibuf; output_buffer#wipe end let encode_multiline () = new encode true true let encode_compact () = new encode false false let encode_compact_pad () = new encode false true let base64_decode_char c = match c with 'A' .. 'Z' -> Char.code c - 65 | 'a' .. 'z' -> Char.code c - 97 + 26 | '0' .. '9' -> Char.code c - 48 + 52 | '+' -> 62 | '/' -> 63 | ' '|'\t'|'\n'|'\r' -> -1 | _ -> raise (Error Bad_encoding) class decode = object (self) inherit buffered_output 256 as output_buffer method input_block_size = 1 method output_block_size = 1 val ibuf = Array.make 4 0 val mutable ipos = 0 val mutable finished = false method put_char c = if c = '=' then finished <- true else begin let n = base64_decode_char c in if n >= 0 then begin if finished then raise(Error Bad_encoding); ibuf.(ipos) <- n; ipos <- ipos + 1; if ipos = 4 then begin self#ensure_capacity 3; Bytes.set obuf oend (Char.chr(ibuf.(0) lsl 2 + ibuf.(1) lsr 4)); Bytes.set obuf (oend+1) (Char.chr((ibuf.(1) land 15) lsl 4 + ibuf.(2) lsr 2)); Bytes.set obuf (oend+2) (Char.chr((ibuf.(2) land 3) lsl 6 + ibuf.(3))); oend <- oend + 3; ipos <- 0 end end end method put_substring s ofs len = for i = ofs to ofs + len - 1 do self#put_char (Bytes.get s i) done method put_string s = String.iter self#put_char s method put_byte b = self#put_char (Char.chr b) method flush : unit = raise (Error Wrong_data_length) method finish = finished <- true; match ipos with | 1 -> raise(Error Bad_encoding) | 2 -> self#ensure_capacity 1; Bytes.set obuf oend (Char.chr(ibuf.(0) lsl 2 + ibuf.(1) lsr 4)); oend <- oend + 1 | 3 -> self#ensure_capacity 2; Bytes.set obuf oend (Char.chr(ibuf.(0) lsl 2 + ibuf.(1) lsr 4)); Bytes.set obuf (oend+1) (Char.chr((ibuf.(1) land 15) lsl 4 + ibuf.(2) lsr 2)); oend <- oend + 2 | _ -> () method wipe = Array.fill ibuf 0 4 0; output_buffer#wipe end let decode () = new decode end (* Hexadecimal encoding *) module Hexa = struct let hex_conv_table = "0123456789abcdef" class encode = object (self) method input_block_size = 1 method output_block_size = 1 inherit buffered_output 256 as output_buffer method put_byte b = self#ensure_capacity 2; Bytes.set obuf oend (hex_conv_table.[b lsr 4]); Bytes.set obuf (oend+1) (hex_conv_table.[b land 0xF]); oend <- oend + 2 method put_char c = self#put_byte (Char.code c) method put_substring s ofs len = for i = ofs to ofs + len - 1 do self#put_char (Bytes.get s i) done method put_string s = String.iter self#put_char s method flush = () method finish = () method wipe = output_buffer#wipe end let encode () = new encode let hex_decode_char c = match c with | '0' .. '9' -> Char.code c - 48 | 'A' .. 'F' -> Char.code c - 65 + 10 | 'a' .. 'f' -> Char.code c - 97 + 10 | ' '|'\t'|'\n'|'\r' -> -1 | _ -> raise (Error Bad_encoding) class decode = object (self) inherit buffered_output 256 as output_buffer method input_block_size = 1 method output_block_size = 1 val ibuf = Array.make 2 0 val mutable ipos = 0 method put_char c = let n = hex_decode_char c in if n >= 0 then begin ibuf.(ipos) <- n; ipos <- ipos + 1; if ipos = 2 then begin self#ensure_capacity 1; Bytes.set obuf oend (Char.chr(ibuf.(0) lsl 4 lor ibuf.(1))); oend <- oend + 1; ipos <- 0 end end method put_substring s ofs len = for i = ofs to ofs + len - 1 do self#put_char (Bytes.get s i) done method put_string s = String.iter self#put_char s method put_byte b = self#put_char (Char.chr b) method flush = if ipos <> 0 then raise(Error Wrong_data_length) method finish = if ipos <> 0 then raise(Error Bad_encoding) method wipe = Array.fill ibuf 0 2 0; output_buffer#wipe end let decode () = new decode end (* Compression *) module Zlib = struct type stream type flush_command = Z_NO_FLUSH | Z_SYNC_FLUSH | Z_FULL_FLUSH | Z_FINISH external deflate_init: int -> bool -> stream = "caml_zlib_deflateInit" external deflate: stream -> bytes -> int -> int -> bytes -> int -> int -> flush_command -> bool * int * int = "caml_zlib_deflate_bytecode" "caml_zlib_deflate" external deflate_end: stream -> unit = "caml_zlib_deflateEnd" external inflate_init: bool -> stream = "caml_zlib_inflateInit" external inflate: stream -> bytes -> int -> int -> bytes -> int -> int -> flush_command -> bool * int * int = "caml_zlib_inflate_bytecode" "caml_zlib_inflate" external inflate_end: stream -> unit = "caml_zlib_inflateEnd" class compress level write_zlib_header = object(self) val zs = deflate_init level write_zlib_header inherit buffered_output 512 as output_buffer method input_block_size = 1 method output_block_size = 1 method put_substring src ofs len = if len > 0 then begin self#ensure_capacity 256; let (_, used_in, used_out) = deflate zs src ofs len obuf oend (Bytes.length obuf - oend) Z_NO_FLUSH in oend <- oend + used_out; if used_in < len then self#put_substring src (ofs + used_in) (len - used_in) end method put_string s = self#put_substring (Bytes.unsafe_of_string s) 0 (String.length s) method put_char c = self#put_string (String.make 1 c) method put_byte b = self#put_char (Char.chr b) method flush = self#ensure_capacity 256; let (_, _, used_out) = deflate zs (Bytes.unsafe_of_string "") 0 0 obuf oend (Bytes.length obuf - oend) Z_SYNC_FLUSH in oend <- oend + used_out; if oend = Bytes.length obuf then self#flush method finish = self#ensure_capacity 256; let (finished, _, used_out) = deflate zs (Bytes.unsafe_of_string "") 0 0 obuf oend (Bytes.length obuf - oend) Z_FINISH in oend <- oend + used_out; if finished then deflate_end zs else self#finish method wipe = output_buffer#wipe end let compress ?(level = 6) ?(write_zlib_header = false) () = new compress level write_zlib_header class uncompress expect_zlib_header = object(self) val zs = inflate_init expect_zlib_header inherit buffered_output 512 as output_buffer method input_block_size = 1 method output_block_size = 1 method put_substring src ofs len = if len > 0 then begin self#ensure_capacity 256; let (finished, used_in, used_out) = inflate zs src ofs len obuf oend (Bytes.length obuf - oend) Z_SYNC_FLUSH in oend <- oend + used_out; if used_in < len then begin if finished then raise(Error(Compression_error("Zlib.uncompress", "garbage at end of compressed data"))); self#put_substring src (ofs + used_in) (len - used_in) end end method put_string s = self#put_substring (Bytes.unsafe_of_string s) 0 (String.length s) method put_char c = self#put_string (String.make 1 c) method put_byte b = self#put_char (Char.chr b) method flush = () method finish = let rec do_finish first_finish = self#ensure_capacity 256; let (finished, _, used_out) = inflate zs (Bytes.unsafe_of_string " ") 0 (if first_finish then 1 else 0) obuf oend (Bytes.length obuf - oend) Z_SYNC_FLUSH in oend <- oend + used_out; if not finished then do_finish false in do_finish true; inflate_end zs method wipe = output_buffer#wipe end let uncompress ?(expect_zlib_header = false) () = new uncompress expect_zlib_header end (* Utilities *) let xor_bytes src src_ofs dst dst_ofs len = if len < 0 || src_ofs < 0 || src_ofs > Bytes.length src - len || dst_ofs < 0 || dst_ofs > Bytes.length dst - len then invalid_arg "xor_bytes"; xor_bytes src src_ofs dst dst_ofs len let xor_string src src_ofs dst dst_ofs len = if len < 0 || src_ofs < 0 || src_ofs > String.length src - len || dst_ofs < 0 || dst_ofs > Bytes.length dst - len then invalid_arg "xor_string"; xor_string src src_ofs dst dst_ofs len let mod_power a b c = Bn.to_bytes ~numbits:(String.length c * 8) (Bn.mod_power (Bn.of_bytes a) (Bn.of_bytes b) (Bn.of_bytes c)) let mod_mult a b c = Bn.to_bytes ~numbits:(String.length c * 8) (Bn.mod_ (Bn.mult (Bn.of_bytes a) (Bn.of_bytes b)) (Bn.of_bytes c)) cryptokit-release119/src/cryptokit.mli000066400000000000000000002166371453705265000203270ustar00rootroot00000000000000(***********************************************************************) (* *) (* The Cryptokit library *) (* *) (* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) (* *) (* Copyright 2002 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file LICENSE. *) (* *) (***********************************************************************) (** The Cryptokit library provides a variety of cryptographic primitives that can be used to implement cryptographic protocols in security-sensitive applications. The primitives provided include: - Symmetric-key ciphers: AES, Chacha20, DES, Triple-DES, Blowfish, ARCfour, in ECB, CBC, CFB, OFB and counter modes. - Authenticated encryption: AES-GCM, Chacha20-Poly1305 - Public-key cryptography: RSA encryption, Diffie-Hellman key agreement. - Hash functions and MACs: SHA-3, SHA-2, BLAKE2, RIPEMD-160, and MACs based on AES, DES, and SipHash. - Random number generation. - Encodings and compression: base 64, hexadecimal, Zlib compression. *) (** {1 General-purpose abstract interfaces} *) (** A {i transform} is an arbitrary mapping from sequences of characters to sequences of characters. Examples of transforms include ciphering, deciphering, compression, decompression, and encoding of binary data as text. Input data to a transform is provided by successive calls to the methods [put_substring], [put_string], [put_char] or [put_byte]. The result of transforming the input data is buffered internally, and can be obtained via the [get_string], [get_substring], [get_char] and [get_byte] methods. *) class type transform = object method put_substring: bytes -> int -> int -> unit (** [put_substring b pos len] processes [len] characters of byte sequence [b], starting at character number [pos], through the transform. *) method put_string: string -> unit (** [put_string str] processes all characters of string [str] through the transform. *) method put_char: char -> unit (** [put_char c] processes character [c] through the transform. *) method put_byte: int -> unit (** [put_byte b] processes the character having code [b] through the transform. [b] must be between [0] and [255] inclusive. *) method finish: unit (** Call method [finish] to indicate that no further data will be processed through the transform. This causes the transform to flush its internal buffers and perform all appropriate finalization actions, e.g. add final padding. Raise [Error Wrong_data_length] if the total length of input data provided via the [put_*] methods is not an integral number of the input block size (see {!Cryptokit.transform.input_block_size}). After calling [finish], the transform can no longer accept additional data. Hence, do not call any of the [put_*] methods nor [flush] after calling [finish]. *) method flush: unit (** [flush] causes the transform to flush its internal buffers and make all output processed up to this point available through the [get_*] methods. Raise [Error Wrong_data_length] if the total length of input data provided via the [put_*] methods is not an integral number of the input block size (see {!Cryptokit.transform.input_block_size}). (For padded block ciphers, the input block size used here is that of the underlying block cipher, without the padding.) Unlike method [finish], method [flush] does not add final padding and leaves the transform in a state where it can still accept more input. *) method available_output: int (** Return the number of characters of output currently available. The output can be recovered with the [get_*] methods. *) method get_string: string (** Return a character string containing all output characters available at this point. The internal output buffer is emptied; in other terms, all currently available output is consumed (and returned to the caller) by a call to [get_string]. *) method get_substring: bytes * int * int (** Return a triple [(buf,pos,len)], where [buf] is the internal output buffer for the transform, [pos] the position of the first character of available output, and [len] the number of characters of available output. The byte array [buf] will be modified later, so the caller must immediately copy characters [pos] to [pos+len-1] of [buf] to some other location. The internal output buffer is emptied; in other terms, all currently available output is consumed (and returned to the caller) by a call to [get_substring]. *) method get_char: char (** Return the first character of output, and remove it from the internal output buffer. Raise [End_of_file] if no output is currently available. *) method get_byte: int (** Return the code of the first character of output, and remove it from the internal output buffer. Raise [End_of_file] if no output is currently available. *) method input_block_size: int (** Some transforms (e.g. unpadded block ciphers) process input data by blocks of several characters. This method returns the size of input blocks for the current transform. If [input_block_size > 1], the user of the transform must ensure that the total length of input data provided between calls to [flush] and [finish] is an integral multiple of [input_block_size]. If [input_block_size = 1], the transform can accept input data of arbitrary length. *) method output_block_size: int (** Some transforms (e.g. block ciphers) always produce output data by blocks of several characters. This method returns the size of output blocks for the current transform. If [output_block_size > 1], the total length of output data produced by the transform is always an integral multiple of [output_block_size]. If [output_block_size = 1], the transform produces output data of arbitrary length. *) method wipe: unit (** Erase all internal buffers and data structures of this transform, overwriting them with zeroes. A transform may contain sensitive data such as secret key-derived material, or parts of the input or output data. Calling [wipe] ensures that this sensitive data will not remain in memory longer than strictly necessary, thus making invasive attacks more difficult. It is thus prudent practice to call [wipe] on every transform that the program no longer needs. After calling [wipe], the transform is no longer in a working state: do not call any other methods after calling [wipe]. *) end val transform_string: transform -> string -> string (** [transform_string t s] runs the string [s] through the transform [t] and returns the transformed string. The transform [t] is wiped before returning, hence can no longer be used for further transformations. *) val transform_channel: transform -> ?len:int -> in_channel -> out_channel -> unit (** [transform_channel t ic oc] reads characters from input channel [ic], runs them through the transform [t], and writes the transformed data to the output channel [oc]. If the optional [len] argument is provided, exactly [len] characters are read from [ic] and transformed; [End_of_file] is raised if [ic] does not contain at least [len] characters. If [len] is not provided, [ic] is read all the way to end of file. The transform [t] is wiped before returning, hence can no longer be used for further transformations. *) val compose: transform -> transform -> transform (** Compose two transforms, feeding the output of the first transform to the input of the second transform. *) (** A {i hash} is a function that maps arbitrarily-long character sequences to small, fixed-size strings. *) class type hash = object method add_substring: bytes -> int -> int -> unit (** [add_substring b pos len] adds [len] characters from byte array [b], starting at character number [pos], to the running hash computation. *) method add_string: string -> unit (** [add_string str] adds all characters of string [str] to the running hash computation. *) method add_char: char -> unit (** [add_char c] adds character [c] to the running hash computation. *) method add_byte: int -> unit (** [add_byte b] adds the character having code [b] to the running hash computation. [b] must be between [0] and [255] inclusive. *) method result: string (** Terminate the hash computation and return the hash value for the input data provided via the [add_*] methods. The hash value is a string of length [hash_size] characters. After calling [result], the hash can no longer accept additional data. Hence, do not call any of the [add_*] methods after [result]. *) method hash_size: int (** Return the size of hash values produced by this hash function, in bytes. *) method wipe: unit (** Erase all internal buffers and data structures of this hash, overwriting them with zeroes. See {!Cryptokit.transform.wipe}. *) end val hash_string: hash -> string -> string (** [hash_string h s] runs the string [s] through the hash function [h] and returns the hash value of [s]. The hash [h] is wiped before returning, hence can no longer be used for further hash computations. *) val hash_channel: hash -> ?len:int -> in_channel -> string (** [hash_channel h ic] reads characters from the input channel [ic], computes their hash value and returns it. If the optional [len] argument is provided, exactly [len] characters are read from [ic] and hashed; [End_of_file] is raised if [ic] does not contain at least [len] characters. If [len] is not provided, [ic] is read all the way to end of file. The hash [h] is wiped before returning, hence can no longer be used for further hash computations. *) (** An {i authenticated transform} maps sequences of bytes to sequences of bytes, just like a transform, but also builds a message authentication tag for the transformed data. The tag is returned by the [finish] method. Authenticated transforms are used for authenticated encryption and decryption. *) class type authenticated_transform = object method input_block_size: int method output_block_size: int method tag_size: int method put_substring: bytes -> int -> int -> unit (** See {!Cryptokit.transform.put_substring}. *) method put_string: string -> unit (** See {!Cryptokit.transform.put_string}. *) method put_char: char -> unit (** See {!Cryptokit.transform.put_char}. *) method put_byte: int -> unit (** See {!Cryptokit.transform.put_byte}. *) method finish_and_get_tag: string (** Call method [finish_and_get_tag] to indicate that no further data will be processed through the transform. This causes the transform to flush its internal buffers and perform all appropriate finalization actions, e.g. add final padding. The authentication tag for the transformed data is computed and returned. It's a string of length {!Cryptokit.authenticated_transform.tag_size}. After calling [finish_and_get_tag], the transform can no longer accept additional data. Hence, after calling [finish_and_get_tag], do not call any of the [put_*] methods nor [finish_and_get_tag] again. *) method available_output: int (** See {!Cryptokit.transform.available_output}. *) method get_string: string (** See {!Cryptokit.transform.get_string}. *) method get_substring: bytes * int * int (** See {!Cryptokit.transform.get_substring}. *) method get_char: char (** See {!Cryptokit.transform.get_char}. *) method get_byte: int (** See {!Cryptokit.transform.get_byte}. *) method tag_size: int (** The size in bytes of the authentication tags. *) method wipe: unit (** See {!Cryptokit.transform.wipe}. *) end val auth_transform_string: authenticated_transform -> string -> string (** [auth_transform_string t s] runs the string [s] through the authenticated transform [t] and returns the concatenation of the transformed string and its authentication tag. The transform [t] is wiped before returning, hence can no longer be used for further transformations. *) val auth_check_transform_string: authenticated_transform -> string -> string option (** [auth_check_transform_string t s] splits the string [s] into an input string [s1] and an expected authentication tag [a]. It runs [s1] through the authenticated transform [t] and checks that the authentication tag is the expected tag [a]. If so, the transformed string is returned. If not, [None] is returned. The input string [s] must have length greater than or equal to [t#tag_size]. Otherwise, the [Wrong_data_length] exception is raised. The transform [t] is wiped before returning, hence can no longer be used for further transformations. *) val auth_transform_string_detached: authenticated_transform -> string -> string * string (** [auth_transform_string_detached t s] runs the string [s] through the authenticated transform [t] and returns a pair of the transformed string and its authentication tag. The transform [t] is wiped before returning, hence can no longer be used for further transformations. *) val transform_then_hash: transform -> hash -> authenticated_transform (** Build an authenticated transform from a transform [t] and a hash [h]. Input data is run through [t], producing transformed data. The transformed data is hashed using [h]. The authentication tag is the final hash value. *) val transform_and_hash: transform -> hash -> authenticated_transform (** Build an authenticated transform from a transform [t] and a hash [h]. Input data is run through [t], producing transformed data. In parallel, the input data is hashed using [h]. The authentication tag is the final hash value. *) (** {1 Utilities: random numbers and padding schemes} *) (** The [Random] module provides random and pseudo-random number generators suitable for generating cryptographic keys, nonces, or challenges. *) module Random : sig class type rng = object method random_bytes: bytes -> int -> int -> unit (** [random_bytes buf pos len] stores [len] random bytes in byte array [buf], starting at position [pos]. *) method wipe: unit (** Erases the internal state of the generator. Do not call [random_bytes] after calling [wipe]. *) end (** Generic interface for a random number generator. *) val string: rng -> int -> string (** [string rng len] returns a string of [len] random bytes read from the generator [rng]. *) val secure_rng: rng (** A high-quality random number generator, using hard-to-predict system data to generate entropy. This generator either uses the OS-provided RNG, if any, or reads from [/dev/random] if available, or uses the hardware random number generator, if available. The method [secure_rng#random_bytes] fails if no suitable RNG is available. [secure_rng#random_bytes] may block until enough entropy has been gathered. Do not use for generating large quantities of random data, otherwise you could exhaust the entropy sources of the system. *) val system_rng: unit -> rng (** [system_rng ()] returns a random number generator derived from the OS-provided RNG. It raises [Error No_entropy_source] if the OS does not provide a secure RNG. Currently, this function is supported under Win32, and under Unix if the [getentropy()] function is provided. *) val device_rng: string -> rng (** [device_rng devicename] returns a random number generator that reads from the special file [devicename], e.g. [/dev/random] or [/dev/urandom]. *) val hardware_rng: unit -> rng (** A hardware random number generator based on the [RDRAND] instruction of the x86 architecture. Available only on recent Intel and AMD x86 processors in 64-bit mode. Raises [Error No_entropy_source] if not available. *) val pseudo_rng: string -> rng (** [pseudo_rng seed] returns a pseudo-random number generator seeded by the string [seed]. [seed] must contain at least 16 characters, and can be arbitrarily longer than this, except that only the first 32 characters are used. The seed is used as a key for the Chacha20 stream cipher. The generated pseudo-random data is the result of encrypting the all-zero input with Chacha20. While this generator is believed to have very good statistical properties, it still does not generate ``true'' randomness: the entropy of the byte strings it produces cannot exceed the entropy contained in the seed. As a typical use, [Random.pseudo_rng (Random.string Random.secure_rng 20)] returns a generator that can generate arbitrarily long strings of pseudo-random data without delays, and with a total entropy of approximately 160 bits. *) val pseudo_rng_aes_ctr: string -> rng (** This is another pseudo-random number generator, based on the AES block cipher in counter mode. It is slightly slower than [pseudo_rng] while having similar randomness characteristics. The only reason to use it instead of [pseudo_rng] is that AES has been cryptanalyzed even more than Chacha20. The [seed] argument must contain at least 16 characters. Only the first 16 characters are used, as an AES key. The generated pseudo-random data is the result of encrypting the 128-bit integers [0, 1, 2, ...] with this key. *) end (** The [Padding] module defines a generic interface for padding input data to an integral number of blocks, as well as two popular padding schemes. *) module Padding : sig class type scheme = object method pad: bytes -> int -> unit (** [pad buf used] is called with a byte array [buf] containing valid input data at positions [0, ..., used-1]. The [pad] method must write padding characters in positions [used] to [Bytes.length str - 1]. It is guaranteed that [used < Bytes.length str], so that at least one character of padding must be added. The padding scheme must be unambiguous in the following sense: from [buf] after padding, it must be possible to determine [used] unambiguously. (This is what method {!Cryptokit.Padding.scheme.strip} does.) *) method strip: bytes -> int (** This is the converse of the [pad] operation: from a padded byte array [buf] as built by method [pad], [strip buf] determines and returns the starting position of the padding data, or equivalently the length of valid, non-padded input data in [buf]. This method must raise [Error Bad_padding] if [buf] does not have the format of a padded block as produced by [pad]. *) end (** Generic interface of a padding scheme. *) val length: scheme (** This padding scheme pads data with [n] copies of the character having code [n]. The integer [n] lies between 1 and the block size (included). This constraint ensures non-ambiguity. This scheme is defined in RFC 2040 and in PKCS 5 and 7. *) val _8000: scheme (** This padding scheme pads data with one [0x80] byte, followed by as many [0] bytes as needed to fill the block. *) end (** {1 Cryptographic primitives (simplified interface)} *) (** The [Cipher] module implements the AES, DES, Triple-DES, ARCfour and Blowfish symmetric ciphers. Symmetric ciphers are presented as transforms parameterized by a secret key and a "direction" indicating whether encryption or decryption is to be performed. The same secret key is used for encryption and for decryption. *) module Cipher : sig type direction = Encrypt | Decrypt (** *) (** Indicate whether the cipher should perform encryption (transforming plaintext to ciphertext) or decryption (transforming ciphertext to plaintext). *) (** Block ciphers such as AES or DES map a fixed-sized block of input data to a block of output data of the same size. A chaining mode indicates how to extend them to multiple blocks of data. The chaining modes supported in this library are: *) type chaining_mode = ECB [@alert crypto "ECB mode is weak"] (** Electronic Code Book mode *) | CBC (** Cipher Block Chaining mode *) | CFB of int (** Cipher Feedback Block with [n] bytes *) | OFB of int (** Output Feedback Block with [n] bytes *) | CTR (** Counter mode, incrementing all the bytes of the IV *) | CTR_N of int (** Counter mode, incrementing only the final [n] bytes of the IV. *) (** A detailed description of these modes is beyond the scope of this documentation; refer to a good cryptography book. [CTR] is a recommended default. For [CFB n] and [OFB n], note that the blocksize is reduced to [n], but encryption speed drops by a factor of [blocksize / n], where [blocksize] is the block size of the underlying cipher; moreover, [n] must be between [1] and [blocksize] included. For [CTR_N n], [n] must be between [1] and [blocksize] included. [CTR] is equivalent to [CTR_N blocksize]. NIST Special Publication 800-38D uses [CTR_N 4], which increments the final 32 bits of the IV. *) (** {2 Recommended ciphers} *) val aes: ?mode:chaining_mode -> ?pad:Padding.scheme -> ?iv:string -> string -> direction -> transform (** AES is the Advanced Encryption Standard. This is a modern block cipher, standardized in 2001. It processes data by blocks of 128 bits (16 bytes), and supports keys of 128, 192 or 256 bits. The string argument is the key; it must have length 16, 24 or 32. The direction argument specifies whether encryption or decryption is to be performed. The optional [mode] argument specifies a chaining mode, as described above; [CBC] is used by default. The optional [pad] argument specifies a padding scheme to pad cleartext to an integral number of blocks. If no [pad] argument is given, no padding is performed and the length of the cleartext must be an integral number of blocks. The optional [iv] argument is the initialization vector used by the chaining mode. It is ignored in ECB mode. If provided, it must be a string of the same size as the block size (16 bytes). If omitted, the null initialization vector (16 zero bytes) is used. The [aes] function returns a transform that performs encryption or decryption, depending on the direction argument. *) val chacha20: ?iv:string -> ?ctr:int64 -> string -> direction -> transform (** Chacha20 is a stream cipher proposed by D. J. Bernstein in 2008. The Chacha20 cipher is a stream cipher, not a block cipher. Hence, its natural block size is 1, and no padding is required. Chaining modes do not apply. A feature of stream ciphers is that the xor of two ciphertexts obtained with the same key, IV and counter is the xor of the corresponding plaintexts, which allows various attacks. Hence, the same key can be used several times, but only with different IVs or different counters. The string argument is the key; its length must be either 16 or (better) 32. The optional [iv] argument is the initialization vector (also called nonce) that can be used to diversify the key. If present, it must be 8 or 12 characters long. If absent, it is taken to be eight zero bytes. The optional [ctr] argument is the initial value of the internal counter. If absent, it defaults to 0. The direction argument is present for consistency with the other ciphers only, and is actually ignored: for all stream ciphers, decryption is the same function as encryption. *) (** {2 Weaker, older ciphers, not recommended for new applications} *) val des: ?mode:chaining_mode -> ?pad:Padding.scheme -> ?iv:string -> string -> direction -> transform [@@alert crypto "DES is broken"] (** DES is the Data Encryption Standard. Very popular in the past, but now completely insecure owing to its small key size (56 bits) which can easily be broken by brute-force enumeration. It should therefore be considered as weak encryption. Its block size is 64 bits (8 bytes). The arguments to the [des] function have the same meaning as for the {!Cryptokit.Cipher.aes} function. The key argument is a string of length 8 (64 bits); the least significant bit of each key byte is ignored. *) val triple_des: ?mode:chaining_mode -> ?pad:Padding.scheme -> ?iv:string -> string -> direction -> transform [@@alert crypto "Triple-DES is weak (small block size)"] (** Triple DES with two or three DES keys. This is a popular variant of DES where each block is encrypted with a 56-bit key [k1], decrypted with another 56-bit key [k2], then re-encrypted with either [k1] or a third 56-bit key [k3]. This results in a 112-bit or 168-bit key length that resists brute-force attacks. However, the three encryptions required on each block make this cipher quite slow (4 times slower than AES). Moreover, the small block size (64 bits) opens the way to collision-based attacks. Triple DES should therefore be considered as relatively weak encryption. The arguments to the [triple_des] function have the same meaning as for the {!Cryptokit.Cipher.aes} function. The key argument is a string of length 16 or 24, representing the concatenation of the key parts [k1], [k2], and optionally [k3]. The least significant bit of each key byte is ignored. *) val arcfour: string -> direction -> transform [@@alert crypto "ARCfour is weak (statistical biases)"] (** ARCfour (``alleged RC4'') is a fast stream cipher that appears to produce equivalent results with the commercial RC4 cipher from RSA Data Security Inc. This company holds the RC4 trademark, and sells the real RC4 cipher. So, it is prudent not to use ARCfour in a commercial product. ARCfour is popular for its speed: approximately 2 times faster than AES. It accepts any key length up to 2048 bits. However, the security of ARCfour is being questioned owing to several statistical biases in its output. It should not be used for new applications. The ARCfour cipher is a stream cipher, not a block cipher. Hence, its natural block size is 1, and no padding is required. Chaining modes do not apply. A feature of stream ciphers is that the xor of two ciphertexts obtained with the same key is the xor of the corresponding plaintexts, which allows various attacks. Hence, the same key must never be reused. The string argument is the key; its length must be between 1 and 256 inclusive. The direction argument is present for consistency with the other ciphers only, and is actually ignored: for all stream ciphers, decryption is the same function as encryption. *) val blowfish: ?mode:chaining_mode -> ?pad:Padding.scheme -> ?iv:string -> string -> direction -> transform [@@alert crypto "Blowfish is weak (small block size)"] (** Blowfish is a fast block cipher proposed by B.Schneier in 1994. It processes data by blocks of 64 bits (8 bytes), and supports keys of 32 to 448 bits. The small block size (64 bits) of Blowfish opens the way to some collision-based attacks. Depending on the application, ciphers with larger block size should be preferred. The string argument is the key; its length must be between 4 and 56. The direction argument specifies whether encryption or decryption is to be performed. The optional [mode] argument specifies a chaining mode, as described above; [CBC] is used by default. The optional [pad] argument specifies a padding scheme to pad cleartext to an integral number of blocks. If no [pad] argument is given, no padding is performed and the length of the cleartext must be an integral number of blocks. The optional [iv] argument is the initialization vector used by the chaining mode. It is ignored in ECB mode. If provided, it must be a string of the same size as the block size (8 bytes). If omitted, the null initialization vector (8 zero bytes) is used. The [blowfish] function returns a transform that performs encryption or decryption, depending on the direction argument. *) end (** The [AEAD] module implements authenticated encryption with associated data. This provides the same confidentiality guarantees as plain encryption, but also provides integrity guarantees. This module implements the AES-GCM and Chacha20-Poly1305 algorithms. *) module AEAD : sig type direction = Encrypt | Decrypt (** *) (** Indicate whether the cipher should perform encryption (transforming plaintext to ciphertext) or decryption (transforming ciphertext to plaintext). *) val aes_gcm: ?header: string -> iv: string -> string -> direction -> authenticated_transform (** AES-GCM is a standardized and widely-used authenticated encryption algorithm. It's an encrypt-then-MAC schema based on the AES cipher in counter mode and on the GHASH hash function. It supports keys of size 128, 192, or 256 bits, and produces authentication tags of size 128 bits (16 bytes). [aes_gcm ?header ~iv key dir] returns an authenticated transform (see {!Cryptokit.authenticated_transform}). - [key] is the encryption key; it must have length 16, 24 or 32. - [dir] specifies whether encryption or decryption is to be performed. - [iv] (mandatory) is the initialization vector used for counter mode. It must not be reused for several encryptions. It is recommended to use a 96-bit (12 bytes) randomly-generated initialization vector. Initialization vectors of size other than 12 bytes are supported but trigger additional computations. - [header] is the associated data. It is not encrypted but it is authenticated, i.e. taken into account for computing the authentication tag. If not provided, it defaults to the empty string. *) val chacha20_poly1305: ?header: string -> iv: string -> string -> direction -> authenticated_transform (** Chacha20-Poly1305 is a fast authenticated encryption algorithm. It's an encrypt-then-MAC schema combining the Chacha20 cipher with the Poly1305 one-time authentication function. It supports keys of size 128 or 256 bits, and produces authentication tags of size 128 bits (16 bytes). [chacha20_poly1305 ?header ~iv key dir] returns an authenticated transform (see {!Cryptokit.authenticated_transform}). - [key] is the encryption key; it must have length 16 or 32. - [dir] specifies whether encryption or decryption is to be performed. - [iv] (mandatory) is the initialization vector used for counter mode. It must not be reused for several encryptions. It must have length 8 bytes (for the original Chacha20-Poly1305 algorithm) or 12 bytes (for the IETF variant described in RFC 7539). - [header] is the associated data. It is not encrypted but it is authenticated, i.e. taken into account for computing the authentication tag. If not provided, it defaults to the empty string. *) end (** The [Hash] module implements unkeyed cryptographic hashes (SHA-1, SHA-256, SHA-512, SHA-3, RIPEMD-160 and MD5), also known as message digest functions. Hash functions used in cryptography are characterized as being {i one-way} (given a hash value, it is computationally infeasible to find a text that hashes to this value) and {i collision-resistant} (it is computationally infeasible to find two different texts that hash to the same value). Thus, the hash of a text can be used as a compact replacement for this text for the purposes of ensuring integrity of the text. *) module Hash : sig (** {2 Recommended hashes} *) val sha3: int -> hash (** SHA-3, the latest NIST standard for cryptographic hashing, produces hashes of 224, 256, 384 or 512 bits (24, 32, 48 or 64 bytes). The parameter is the desired size of the hash, in bits. It must be one of 224, 256, 384 or 512. *) val keccak: int -> hash (** The Keccak submission for the SHA-3 is very similar to [sha3] but uses a slightly different padding. The parameter is the same as that of [sha3]. *) val sha2: int -> hash (** SHA-2, another NIST standard for cryptographic hashing, produces hashes of 224, 256, 384, or 512 bits (24, 32, 48 or 64 bytes). The parameter is the desired size of the hash, in bits. It must be one of 224, 256, 384 or 512. *) val sha224: unit -> hash (** SHA-224 is SHA-2 specialized to 224 bit hashes (24 bytes). *) val sha256: unit -> hash (** SHA-256 is SHA-2 specialized to 256 bit hashes (32 bytes). *) val sha384: unit -> hash (** SHA-384 is SHA-2 specialized to 384 bit hashes (48 bytes). *) val sha512: unit -> hash (** SHA-512 is SHA-2 specialized to 512 bit hashes (64 bytes). *) val blake2b: int -> hash (** The BLAKE2b hash function produces hashes of length 1 to 64 bytes. The parameter is the desired size of the hash, in bits. It must be between 8 and 512, and a multiple of 8. *) val blake2b512: unit -> hash (** BLAKE2b512 is BLAKE2b specialized to 512 bit hashes (64 bytes). *) val blake2s: int -> hash (** The BLAKE2s hash function produces hashes of length 1 to 32 bytes. The parameter is the desired size of the hash, in bits. It must be between 8 and 256, and a multiple of 8. *) val blake2s256: unit -> hash (** BLAKE2s256 is BLAKE2s specialized to 256 bit hashes (32 bytes). *) val blake3: int -> hash (** The BLAKE3 hash function produces hashes of arbitrary length. The recommended length is 32 bytes (256 bits). Shorter hashes are less secure, but longer hashes are not more secure. The parameter is the desired size of the hash, in bits. It must be positive and a multiple of 8. *) val blake3_256: unit -> hash (** The BLAKE3 hash function, specialized to 256 bit hashes (32 bytes). *) val ripemd160: unit -> hash (** RIPEMD-160 produces 160-bit hashes (20 bytes). *) (** {2 Weak hashes, not recommended for new applications} *) val sha1: unit -> hash [@@alert crypto "SHA1 is broken"] (** SHA-1 is the Secure Hash Algorithm revision 1. It is a NIST standard, is widely used, and produces 160-bit hashes (20 bytes). While popular in many legacy applications, it is now known to be insecure. In particular, it is not collision-resistant. *) val md5: unit -> hash [@@alert crypto "MD5 is broken"] (** MD5 is an older hash function, producing 128-bit hashes (16 bytes). While popular in many legacy applications, it is now known to be insecure. In particular, it is not collision-resistant. *) end (** The [MAC] module implements message authentication codes, also known as keyed hash functions. These are hash functions parameterized by a secret key. In addition to being one-way and collision-resistant, a MAC has the property that without knowing the secret key, it is computationally infeasible to find the hash for a known text, even if many pairs of (text, MAC) are known to the attacker. Thus, MAC can be used to authenticate the sender of a text: the receiver of a (text, MAC) pair can recompute the MAC from the text, and if it matches the transmitted MAC, be reasonably certain that the text was authentified by someone who possesses the secret key. The module [MAC] provides six MAC functions based on the hashes BLAKE2b, SHA-1, SHA256, SHA512, RIPEMD160 and MD5; five MAC functions based on the block ciphers AES, DES, and Triple-DES; and the SipHash algorithm. *) module MAC: sig val hmac_sha1: string -> hash (** [hmac_sha1 key] returns a MAC based on the HMAC construction (RFC2104) applied to SHA-1. The returned hash values are 160 bits (20 bytes) long. The [key] argument is the MAC key; it can have any length, but a minimal length of 20 bytes is recommended. *) val hmac_sha256: string -> hash (** [hmac_sha256 key] returns a MAC based on the HMAC construction (RFC2104) applied to SHA-256. The returned hash values are 256 bits (32 bytes) long. The [key] argument is the MAC key; it can have any length, but a minimal length of 32 bytes is recommended. *) val hmac_sha384: string -> hash (** [hmac_sha384 key] returns a MAC based on the HMAC construction (RFC2104) applied to SHA-384. The returned hash values are 384 bits (48 bytes) long. The [key] argument is the MAC key; it can have any length, but a minimal length of 64 bytes is recommended. *) val hmac_sha512: string -> hash (** [hmac_sha512 key] returns a MAC based on the HMAC construction (RFC2104) applied to SHA-512. The returned hash values are 512 bits (64 bytes) long. The [key] argument is the MAC key; it can have any length, but a minimal length of 64 bytes is recommended. *) val hmac_ripemd160: string -> hash (** [hmac_ripemd160 key] returns a MAC based on the HMAC construction (RFC2104) applied to RIPEMD-160. The returned hash values are 160 bits (20 bytes) long. The [key] argument is the MAC key; it can have any length, but a minimal length of 20 bytes is recommended. *) val hmac_md5: string -> hash (** [hmac_md5 key] returns a MAC based on the HMAC construction (RFC2104) applied to MD5. The returned hash values are 128 bits (16 bytes) long. The [key] argument is the MAC key; it can have any length, but a minimal length of 16 bytes is recommended. *) val blake2b: int -> string -> hash (** [blake2b sz key] is the BLAKE2b keyed hash function. The returned hash values have length 1 to 64 bytes. The [sz] is the desired size of the hash, in bits. It must be between 8 and 512, and a multiple of 8. The [key] argument is the MAC key. It must have length 64 at most. A length of 64 bytes is recommended. *) val blake2b512: string -> hash (** [blake2b512 key] is the BLAKE2b keyed hash function specialized to 512 bit hashes (64 bytes). The [key] argument is the MAC key. It must have length 64 at most. A length of 64 bytes is recommended. *) val blake2s: int -> string -> hash (** [blake2s sz key] is the BLAKE2s keyed hash function. The returned hash values have length 1 to 32 bytes. The [sz] is the desired size of the hash, in bits. It must be between 8 and 256, and a multiple of 8. The [key] argument is the MAC key. It must have length 32 at most. A length of 32 bytes is recommended. *) val blake2s256: string -> hash (** [blake2s256 key] is the BLAKE2s keyed hash function specialized to 256 bit hashes (32 bytes). The [key] argument is the MAC key. It must have length 32 at most. A length of 32 bytes is recommended. *) val blake3: int -> string -> hash (** [blake3 sz key] is the BLAKE3 keyed hash function. [key] is the MAC key. It must have length 32. [sz] is the desired size of the hash, in bits. The recommended length is 256 bits (32 bytes). Shorter hashes are less secure, but longer hashes are not more secure. *) val blake3_256: string -> hash (** [blake3_256 key] is the BLAKE3 keyed hash function specialized to 256 bit hashes (32 bytes). [key] is the MAC key. It must have length 32. *) val aes_cmac: ?iv:string -> string -> hash (** [aes_cmac key] returns a MAC based on AES encryption in CMAC mode, also known as OMAC1 mode. The input data is encrypted using AES in CBC mode, with a special treatment of the final block that makes this MAC suitable for input data of variable length. The final value of the initialization vector is the MAC value. Thus, the returned hash values are 128 bit (16 bytes) long. The [key] argument is the MAC key; it must have length 16, 24, or 32. The optional [iv] argument is the first value of the initialization vector, and defaults to 0. *) val aes: ?iv:string -> ?pad:Padding.scheme -> string -> hash (** [aes key] returns a MAC based on AES encryption in CBC mode. Unlike [aes_cmac], there is no special treatment for the final block, except padding it as per the optional [pad] argument. This makes this MAC weak when used with input data of variable length. (It is fine for data of fixed length, though.) The returned hash values are 128 bit (16 bytes) long. The [key] argument is the MAC key; it must have length 16, 24, or 32. The optional [iv] argument is the first value of the initialization vector, and defaults to 0. The optional [pad] argument specifies a padding scheme to pad input to an integral number of 16-byte blocks. *) val des: ?iv:string -> ?pad:Padding.scheme -> string -> hash [@@alert crypto "DES MAC is weak"] (** [des key] returns a MAC based on DES encryption in CBC mode. The construction is identical to that used for the [aes] MAC. The key size is 64 bits (8 bytes), of which only 56 are used. The returned hash value has length 8 bytes. Due to the small hash size and key size, this MAC is weak. *) val triple_des: ?iv:string -> ?pad:Padding.scheme -> string -> hash [@@alert crypto "Triple-DES MAC is weak"] (** [triple_des key] returns a MAC based on triple DES encryption in CBC mode. The construction is identical to that used for the [aes] MAC. The key size is 16 or 24 bytes. The returned hash value has length 8 bytes. The key size is sufficient to protect against brute-force attacks, but the small hash size means that this MAC is not collision-resistant. *) val des_final_triple_des: ?iv:string -> ?pad:Padding.scheme -> string -> hash [@@alert crypto "Triple-DES MAC is weak"] (** [des_final_triple_des key] returns a MAC that uses DES CBC with the first 8 bytes of [key] as key. The final initialization vector is then DES-decrypted with bytes 8 to 15 of [key], and DES-encrypted again with either the last 8 bytes of [key] (if a triple-length key is provided) or the first 8 bytes of [key] (if a double-length key is provided). Thus, the key is 16 or 24 bytes long, of which 112 or 168 bits are used. The overall construction has the same key size as a triple DES MAC, but runs faster because triple encryption is not performed on all data blocks, but only on the final MAC. *) val siphash: string -> hash (** [siphash key] is the SipHash-2-4 function. The returned hash values have length 8 bytes. The [key] argument is the MAC key. It must be 16 bytes (128 bits) long. This MAC is very fast, especially for short inputs. However, it has not been cryptanalyzed as intensively as the other MACs above. *) val siphash128: string -> hash (** [siphash128 key] is a variant of [siphash] that returns hash values of length 16 bytes instead of 8 bytes. *) end (** The [RSA] module implements RSA public-key cryptography. Public-key cryptography is asymmetric: two distinct keys are used for encrypting a message, then decrypting it. Moreover, while one of the keys must remain secret, the other can be made public, since it is computationally very hard to reconstruct the private key from the public key. This feature supports both public-key encryption (anyone can encode with the public key, but only the owner of the private key can decrypt) and digital signature (only the owner of the private key can sign, but anyone can check the signature with the public key). *) module RSA: sig type key = { size: int; (** Size of the modulus [n], in bits *) n: string; (** Modulus [n = p.q] *) e: string; (** Public exponent [e] *) d: string; (** Private exponent [d] *) p: string; (** Prime factor [p] of [n] *) q: string; (** The other prime factor [q] of [n] *) dp: string; (** [dp] is [d mod (p-1)] *) dq: string; (** [dq] is [d mod (q-1)] *) qinv: string (** [qinv] is a multiplicative inverse of [q] modulo [p] *) } (** The type of RSA keys. Components [size], [n] and [e] define the public part of the key. Components [size], [n] and [d] define the private part of the key. To speed up private key operations through the use of the Chinese remainder theorem (CRT), additional components [p], [q], [dp], [dq] and [qinv] are provided. These are part of the private key. *) val wipe_key: key -> unit (** Erase all components of a RSA key. *) val new_key: ?rng: Random.rng -> ?e: int -> int -> key (** Generate a new, random RSA key. The non-optional [int] argument is the desired size for the modulus, in bits (e.g. 2048). The optional [rng] argument specifies a random number generator to use for generating the key; it defaults to {!Cryptokit.Random.secure_rng}. The optional [e] argument specifies the public exponent desired. If not specified, [e] is chosen randomly. Small values of [e] such as [e = 65537] significantly speeds up encryption and signature checking compared with a random [e]. Very small values of [e] such as [e = 3] can weaken security and are best avoided. The result of [new_key] is a complete RSA key with all components defined: public, private, and private for use with the CRT. *) val encrypt: key -> string -> string (** [encrypt k msg] encrypts the string [msg] with the public part of key [k] (components [n] and [e]). [msg] must be smaller than [key.n] when both strings are viewed as natural numbers in big-endian notation. In practice, [msg] should be of length [key.size / 8 - 1], using padding if necessary. If you need to encrypt longer plaintexts using RSA, encrypt them with a symmetric cipher, using a randomly-generated key, and encrypt only that key with RSA. *) val decrypt: key -> string -> string (** [decrypt k msg] decrypts the ciphertext string [msg] with the private part of key [k] (components [n] and [d]). The size of [msg] is limited as described for {!Cryptokit.RSA.encrypt}. *) val decrypt_CRT: key -> string -> string (** [decrypt_CRT k msg] decrypts the ciphertext string [msg] with the CRT private part of key [k] (components [n], [p], [q], [dp], [dq] and [qinv]). The use of the Chinese remainder theorem (CRT) allows significantly faster decryption than {!Cryptokit.RSA.decrypt}, at no loss in security. The size of [msg] is limited as described for {!Cryptokit.RSA.encrypt}. *) val sign: key -> string -> string (** [sign k msg] encrypts the plaintext string [msg] with the private part of key [k] (components [n] and [d]), thus performing a digital signature on [msg]. The size of [msg] is limited as described for {!Cryptokit.RSA.encrypt}. If you need to sign longer messages, compute a cryptographic hash of the message and sign only the hash with RSA. *) val sign_CRT: key -> string -> string (** [sign_CRT k msg] encrypts the plaintext string [msg] with the CRT private part of key [k] (components [n], [p], [q], [dp], [dq] and [qinv]), thus performing a digital signature on [msg]. The use of the Chinese remainder theorem (CRT) allows significantly faster signature than {!Cryptokit.RSA.sign}, at no loss in security. The size of [msg] is limited as described for {!Cryptokit.RSA.encrypt}. *) val unwrap_signature: key -> string -> string (** [unwrap_signature k msg] decrypts the ciphertext string [msg] with the public part of key [k] (components [n] and [d]), thus extracting the plaintext that was signed by the sender. The size of [msg] is limited as described for {!Cryptokit.RSA.encrypt}. *) end (** The [DH] module implements Diffie-Hellman key agreement. Key agreement is a protocol by which two parties can establish a shared secret (typically a key for a symmetric cipher or MAC) by exchanging messages, with the guarantee that even if an attacker eavesdrop on the messages, he cannot recover the shared secret. Diffie-Hellman is one such key agreement protocol, relying on the difficulty of computing discrete logarithms. Notice that the Diffie-Hellman protocol is vulnerable to active attacks (man-in-the-middle attacks). The protocol executes as follows: - Both parties must agree beforehand on a set of public parameters (type {!Cryptokit.DH.parameters}). Suitable parameters can be generated by calling {!Cryptokit.DH.new_parameters}, or fixed parameters taken from the literature can be used. - Each party computes a random private secret using the function {!Cryptokit.DH.private_secret}. - From its private secrets and the public parameters, each party computes a message (a string) with the function {!Cryptokit.DH.message}, and sends it to the other party. - Each party recovers the shared secret by applying the function {!Cryptokit.DH.shared_secret} to its private secret and to the message received from the other party. - Fixed-size keys can then be derived from the shared secret using the function {!Cryptokit.DH.derive_key}. *) module DH: sig type parameters = { p: string; (** Large prime number *) g: string; (** Generator of [Z/pZ] *) privlen: int (** Length of private secrets in bits *) } (** The type of Diffie-Hellman parameters. These parameters need to be agreed upon by the two parties before the key agreement protocol is run. The parameters are public and can be reused for several runs of the protocol. *) val new_parameters: ?rng: Random.rng -> ?privlen: int -> int -> parameters (** Generate a new set of Diffie-Hellman parameters. The non-optional argument is the size in bits of the [p] parameter. It must be large enough that the discrete logarithm problem modulo [p] is computationally unsolvable. 2048 is a reasonable value. The optional [rng] argument specifies a random number generator to use for generating the parameters; it defaults to {!Cryptokit.Random.secure_rng}. The optional [privlen] argument is the size in bits of the private secrets that are generated during the key agreement protocol; the default is 160. *) type private_secret (** The abstract type of private secrets generated during key agreement. *) val private_secret: ?rng: Random.rng -> parameters -> private_secret (** Generate a random private secret. The optional [rng] argument specifies a random number generator to use; it defaults to {!Cryptokit.Random.secure_rng}. *) val message: parameters -> private_secret -> string (** Compute the message to be sent to the other party. *) val shared_secret: parameters -> private_secret -> string -> string (** Recover the shared secret from the private secret of the present party and the message received from the other party. The shared secret returned is a string of the same length as the [p] parameter. The private secret is destroyed and can no longer be used afterwards. *) val derive_key: ?diversification: string -> string -> int -> string (** [derive_key shared_secret numbytes] derives a secret string (typically, a key for symmetric encryption) from the given shared secret. [numbytes] is the desired length for the returned string. The optional [diversification] argument is an arbitrary string that defaults to the empty string. Different secret strings can be obtained from the same shared secret by supplying different [diversification] argument. The computation of the secret string is performed by SHA-1 hashing of the diversification string, followed by the shared secret, followed by an integer counter. The hashing is repeated with increasing values of the counter until [numbytes] bytes have been obtained. *) end (** {1 Advanced, compositional interface to block ciphers and stream ciphers} *) (** The [Block] module provides classes that implements popular block ciphers, chaining modes, and wrapping of a block cipher as a general transform or as a hash function. The classes can be composed in a Lego-like fashion, facilitating the integration of new block ciphers, modes, etc. *) module Block : sig class type block_cipher = object method blocksize: int (** The size in bytes of the blocks manipulated by the cipher. *) method transform: bytes -> int -> bytes -> int -> unit (** [transform src spos dst dpos] encrypts or decrypts one block of data. The input data is read from byte array [src] at positions [spos, ..., spos + blocksize - 1], and the output data is stored in byte array [dst] at positions [dpos, ..., dpos + blocksize - 1]. *) method wipe: unit (** Erase the internal state of the block cipher, such as all key-dependent material. *) end (** Abstract interface for a block cipher. *) (** {1 Deriving transforms and hashes from block ciphers} *) class cipher: block_cipher -> transform (** Wraps a block cipher as a general transform. The transform has input block size and output block size equal to the block size of the block cipher. No padding is performed. Example: [new cipher (new cbc_encrypt (new aes_encrypt key))] returns a transform that performs AES encryption in CBC mode. *) class cipher_padded_encrypt: Padding.scheme -> block_cipher -> transform (** Like {!Cryptokit.Block.cipher}, but performs padding on the input data as specified by the first argument. The input block size of the returned transform is 1; the output block size is the block size of the block cipher. *) class cipher_padded_decrypt: Padding.scheme -> block_cipher -> transform (** Like {!Cryptokit.Block.cipher}, but removes padding on the output data as specified by the first argument. The output block size of the returned transform is 1; the input block size is the block size of the block cipher. *) class mac: ?iv: string -> ?pad: Padding.scheme -> block_cipher -> hash (** Build a MAC (keyed hash function) from the given block cipher. The block cipher is run in CBC mode, and the MAC value is the final value of the initialization vector. Thus, the hash size of the resulting hash is the block size of the block cipher. The optional argument [iv] specifies the first initialization vector, with a default of all zeroes. The optional argument [pad] specifies a padding scheme to be applied to the input data; if not provided, no padding is performed. *) class mac_final_triple: ?iv: string -> ?pad: Padding.scheme -> block_cipher -> block_cipher -> block_cipher -> hash (** Build a MAC (keyed hash function) from the given block ciphers [c1], [c2] and [c3]. The input is run through [c1] in CBC mode, as described for {!Cryptokit.Block.mac}. The final initialization vector is then super-enciphered by [c2], then by [c3], to provide the final MAC. This construction results in a MAC that is as nearly as fast as {!Cryptokit.Block.mac} [c1], but more resistant against brute-force key search because of the additional final encryption through [c2] and [c3]. *) (** {1 Some block ciphers: AES, DES, triple DES, Blowfish} *) class aes_encrypt: string -> block_cipher (** The AES block cipher, in encryption mode. The string argument is the key; its length must be 16, 24 or 32 bytes. *) class aes_decrypt: string -> block_cipher (** The AES block cipher, in decryption mode. *) class des_encrypt: string -> block_cipher [@@alert crypto "DES is broken"] (** The DES block cipher, in encryption mode. The string argument is the key; its length must be 8 bytes. *) class des_decrypt: string -> block_cipher [@@alert crypto "DES is broken"] (** The DES block cipher, in decryption mode. *) class triple_des_encrypt: string -> block_cipher [@@alert crypto "Triple-DES is weak"] (** The Triple-DES block cipher, in encryption mode. The key argument must have length 16 (two keys) or 24 (three keys). *) class triple_des_decrypt: string -> block_cipher [@@alert crypto "Triple-DES is weak"] (** The Triple-DES block cipher, in decryption mode. *) class blowfish_encrypt: string -> block_cipher [@@alert crypto "Blowfish is weak"] (** The Blowfish block cipher, in encryption mode. The string argument is the key; its length must be between 4 and 56. *) class blowfish_decrypt: string -> block_cipher [@@alert crypto "Blowfish is weak"] (** The Blowfish block cipher, in decryption mode. *) (** {1 Chaining modes} *) class cbc_encrypt: ?iv: string -> block_cipher -> block_cipher (** Add Cipher Block Chaining (CBC) to the given block cipher in encryption mode. Each block of input is xor-ed with the previous output block before being encrypted through the given block cipher. The optional [iv] argument specifies the string to be xor-ed with the first input block, and defaults to all zeroes. The returned block cipher has the same block size as the underlying block cipher. *) class cbc_decrypt: ?iv: string -> block_cipher -> block_cipher (** Add Cipher Block Chaining (CBC) to the given block cipher in decryption mode. This works like {!Cryptokit.Block.cbc_encrypt}, except that input blocks are first decrypted by the block cipher before being xor-ed with the previous input block. *) class cfb_encrypt: ?iv: string -> int -> block_cipher -> block_cipher (** Add Cipher Feedback Block (CFB) to the given block cipher in encryption mode. The integer argument [n] is the number of bytes processed at a time; it must lie between [1] and the block size of the underlying cipher, included. The returned block cipher has block size [n]. *) class cfb_decrypt: ?iv: string -> int -> block_cipher -> block_cipher (** Add Cipher Feedback Block (CFB) to the given block cipher in decryption mode. See {!Cryptokit.Block.cfb_encrypt}. *) class ofb: ?iv: string -> int -> block_cipher -> block_cipher (** Add Output Feedback Block (OFB) to the given block cipher. The integer argument [n] is the number of bytes processed at a time; it must lie between [1] and the block size of the underlying cipher, included. The returned block cipher has block size [n]. It is usable both for encryption and decryption. *) class ctr: ?iv: string -> ?inc:int -> block_cipher -> block_cipher (** Add Counter mode to the given block cipher. Viewing the IV as a [blocksize]-byte integer in big-endian representation, the blocks [IV], [IV+1], [IV+2], ... are encrypted using the given block cipher, and the result is xor-ed with the input blocks to produce the output blocks. The additions [IV+n] are performed modulo 2 to the [8 * inc] power. In other words, only the low [inc] bytes of the [IV] are subject to incrementation; the high [blocksize - inc] bytes are unaffected. [inc] defaults to [blocksize]. The returned block cipher has the same block size as the underlying block cipher, and is usable both for encryption and decryption. *) end (** The [Stream] module provides classes that implement the ARCfour stream cipher, and the wrapping of a stream cipher as a general transform. The classes can be composed in a Lego-like fashion, facilitating the integration of new stream ciphers. *) module Stream : sig class type stream_cipher = object method transform: bytes -> int -> bytes -> int -> int -> unit (** [transform src spos dst dpos len] encrypts or decrypts [len] characters, read from byte array [src] starting at position [spos]. The resulting [len] characters are stored in byte array [dst] starting at position [dpos]. *) method wipe: unit (** Erase the internal state of the stream cipher, such as all key-dependent material. *) end (** Abstract interface for a stream cipher. *) class cipher: stream_cipher -> transform (** Wraps an arbitrary stream cipher as a transform. The transform has input and output block size of 1. *) class arcfour: string -> stream_cipher [@@alert crypto "ARCfour is weak"] (** The ARCfour (``alleged RC4'') stream cipher. The argument is the key, and must be of length 1 to 256. This stream cipher works by xor-ing the input with the output of a key-dependent pseudo random number generator. Thus, decryption is the same function as encryption. *) class chacha20: ?iv:string -> ?ctr:int64 -> string -> stream_cipher (** The Chacha20 stream cipher. The string argument is the key, and must be of length 16 or 32. The optional [iv] argument is the initialization vector (also known as the nonce). If present, it must be 8 bytes long. If absent, it is taken to be eight zero bytes. The optional [ctr] argument is the initial value of the internal counter. If absent, it is taken to be 0. This stream cipher works by xor-ing the input with the output of a key-dependent pseudo random number generator. Thus, decryption is the same function as encryption. *) end (** {1 Encoding and compression of data} *) (** The [Base64] module supports the encoding and decoding of binary data in base 64 format, using only alphanumeric characters that can safely be transmitted over e-mail or in URLs. *) module Base64: sig val encode_multiline : unit -> transform (** Return a transform that performs base 64 encoding. The output is divided in lines of length 76 characters, and final [=] characters are used to pad the output, as specified in the MIME standard. The output is approximately [4/3] longer than the input. *) val encode_compact : unit -> transform (** Same as {!Cryptokit.Base64.encode_multiline}, but the output is not split into lines, and no final padding is added. This is adequate for encoding short strings for transmission as part of URLs, for instance. *) val encode_compact_pad : unit -> transform (** Same as {!Cryptokit.Base64.encode_compact}, but the output is padded with [=] characters at the end (if necessary). *) val decode : unit -> transform (** Return a transform that performs base 64 decoding. The input must consist of valid base 64 characters; blanks are ignored. Raise [Error Bad_encoding] if invalid base 64 characters are encountered in the input. *) end (** The [Hexa] module supports the encoding and decoding of binary data as hexadecimal strings. This is a popular format for transmitting keys in textual form. *) module Hexa: sig val encode : unit -> transform (** Return a transform that encodes its input in hexadecimal. The output is twice as long as the input, and contains no spaces or newlines. *) val decode : unit -> transform (** Return a transform that decodes its input from hexadecimal. The output is twice as short as the input. Blanks (spaces, tabs, newlines) in the input are ignored. Raise [Error Bad_encoding] if the input contains characters other than hexadecimal digits and blanks. *) end (** The [Zlib] module supports the compression and decompression of data, using the [zlib] library. The algorithm used is Lempel-Ziv compression as in the [gzip] and [zip] compressors. While compression itself is not encryption, it is often used prior to encryption to reduce the size of the ciphertext. *) module Zlib: sig val compress : ?level:int -> ?write_zlib_header:bool -> unit -> transform (** Return a transform that compresses its input. The optional [level] argument is an integer between 1 and 9 specifying how hard the transform should try to compress data: 1 is lowest but fastest compression, while 9 is highest but slowest compression. The default level is 6. The optional [write_zlib_header] argument dictates whether the output should be wrapped within a zlib header and checksum. The default is false. *) val uncompress : ?expect_zlib_header:bool -> unit -> transform (** Return a transform that decompresses its input. The optional [expect_zlib_header] argument dictates whether the input is wrapped within a zlib header and checksum. The default is false. *) end (** {1 Error reporting} *) (** Error codes for this library. *) type error = | Wrong_key_size (** The key is too long or too short for the given cipher. *) | Wrong_IV_size (** The initialization vector does not have the same size as the block size. *) | Wrong_data_length (** The total length of the input data for a transform is not an integral multiple of the input block size. *) | Bad_padding (** Incorrect padding bytes were found after decryption. *) | Output_buffer_overflow (** The output buffer for a transform exceeds the maximal length of a Caml string. *) | Incompatible_block_size (** A combination of two block ciphers was attempted whereby the ciphers have different block sizes, while they must have the same. *) | Number_too_long (** Denotes an internal error in RSA key generation or encryption. *) | Seed_too_short (** The seed given to a pseudo random number generator is too short. *) | Message_too_long (** For symmetric ciphers in counter mode (CTR): the message exceeds the maximal length supported, causing the counter to wrap around. For RSA encryption or decryption: the message is greater than the modulus of the RSA key. *) | Bad_encoding (** Illegal characters were found in an encoding of binary data such as base 64 or hexadecimal. *) | Compression_error of string * string (** Error during compression or decompression. *) | No_entropy_source (** No entropy source (OS, hardware, or [/dev/random]) was found for {!Cryptokit.Random.secure_rng}. *) | Entropy_source_closed (** End of file on a device or EGD entropy source. *) | Compression_not_supported (** The data compression functions are not available. *) exception Error of error (** Exception raised by functions in this library to report error conditions. *) (** {1 Miscellaneous utilities} *) val wipe_bytes : bytes -> unit (** [wipe_bytes b] overwrites [b] with zeroes. Can be used to reduce the memory lifetime of sensitive data. *) val wipe_string : string -> unit (** [wipe_string s] overwrites [s] with zeroes. Can be used to reduce the memory lifetime of sensitive data. Note that strings are normally immutable and this operation violates this immutability property. Therefore, this is an unsafe operation, and it should be used only by code that is the only owner of the string [s]. See {!Stdlib.Bytes.unsafe_of_string} for more details on the ownership policy. *) val string_equal : string -> string -> bool (** Constant-time comparison between strings. [string_equal s1 s2] returns [true] if the strings [s1] and [s2] have the same length and contain the same characters. The execution time of this function is determined by the lengths of [s1] and [s2], but is independent of their contents. *) val bytes_equal : bytes -> bytes -> bool (** Constant-time comparison between byte sequences. Like {!Cryptokit.string_equal}, but for byte sequences. *) val xor_bytes: bytes -> int -> bytes -> int -> int -> unit (** [xor_bytes src spos dst dpos len] performs the xor (exclusive or) of characters [spos, ..., spos + len - 1] of [src] with characters [dpos, ..., dpos + len - 1] of [dst], storing the result in [dst] starting at position [dpos]. *) val xor_string: string -> int -> bytes -> int -> int -> unit (** Same as [xor_bytes], but the source is a string instead of a byte array. *) val mod_power: string -> string -> string -> string (** [mod_power a b c] computes [a^b mod c], where the strings [a], [b], [c] and the result are viewed as arbitrary-precision integers in big-endian format. Requires [a < c]. *) val mod_mult: string -> string -> string -> string (** [mod_mult a b c] computes [a*b mod c], where the strings [a], [b], [c] and the result are viewed as arbitrary-precision integers in big-endian format. *) cryptokit-release119/src/cryptokitBignum.ml000066400000000000000000000072371453705265000213120ustar00rootroot00000000000000(***********************************************************************) (* *) (* The Cryptokit library *) (* *) (* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) (* *) (* Copyright 2002 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file LICENSE. *) (* *) (***********************************************************************) (* Arithmetic on big integers, based on the ZArith library. *) type t = Z.t external wipe: t -> unit = "caml_wipe_z" let zero = Z.zero let one = Z.one let of_int = Z.of_int let compare = Z.compare let add = Z.add let sub = Z.sub let mult = Z.mul let mod_ = Z.rem let relative_prime a b = Z.equal (Z.gcd a b) Z.one let mod_power = Z.powm_sec let sub_mod a b p = let d = Z.sub a b in if Z.sign d < 0 then Z.add d p else d (* Modular exponentiation via the Chinese Remainder Theorem. Compute a ^ d mod pq, where d is defined by dp = d mod (p-1) and dq = d mod (q-1). qinv is q^-1 mod p. Formula: mp = (a mod p)^dp mod p mq = (a mod q)^dq mod q m = ((((mp - mq) mod p) * qInv) mod p) * q + mq *) let mod_power_CRT a p q dp dq qinv = let amodp = Z.rem a p and amodq = Z.rem a q in let mp = mod_power amodp dp p and mq = mod_power amodq dq q in let diff = sub_mod mp mq p in let diff_qinv = Z.mul diff qinv in let diff_qinv_mod_p = Z.rem diff_qinv p in let res = Z.(add (mul q diff_qinv_mod_p) mq) in wipe amodp; wipe amodq; (* It is possible that res == mq, so we cannot wipe mq. For consistency we don't wipe any of the intermediate results besides amodp and amodq. *) res let mod_inv = Z.invert let wipe_bytes s = Bytes.fill s 0 (Bytes.length s) '\000' let of_bytes s = let l = String.length s in let t = Bytes.create l in for i = 0 to l - 1 do Bytes.set t i s.[l - 1 - i] done; let n = Z.of_bits (Bytes.unsafe_to_string t) in wipe_bytes t; n let to_bytes ?numbits n = let s = Z.to_bits n in let l = match numbits with | None -> String.length s | Some nb -> assert (Z.numbits n <= nb); (nb + 7) / 8 in let t = Bytes.make l '\000' in for i = 0 to String.length s - 1 do Bytes.set t (l - 1 - i) s.[i] done; wipe_bytes (Bytes.unsafe_of_string s); Bytes.unsafe_to_string t let change_byte s i f = Bytes.set s i (Char.chr (f (Char.code (Bytes.get s i)))) let random ~rng ?(odd = false) numbits = let numbytes = (numbits + 7) / 8 in let buf = Bytes.create numbytes in rng buf 0 numbytes; (* adjust low byte if requested *) if odd then change_byte buf 0 (fun b -> b lor 1); (* adjust high byte so that the number is exactly numbits long *) let mask = 1 lsl ((numbits - 1) land 7) in change_byte buf (numbytes - 1) (fun b -> (b land (mask - 1)) lor mask); (* convert to a number *) let n = Z.of_bits (Bytes.unsafe_to_string buf) in wipe_bytes buf; assert (Z.numbits n = numbits); if odd then assert (Z.is_odd n); n let rec random_prime ~rng numbits = (* Generate random odd number *) let n = random ~rng ~odd:true numbits in (* Find next prime above n *) let p = Z.nextprime n in (* Make sure it has the right number of bits *) if Z.numbits p = numbits then p else random_prime ~rng numbits cryptokit-release119/src/cryptokitBignum.mli000066400000000000000000000030001453705265000214430ustar00rootroot00000000000000(***********************************************************************) (* *) (* The Cryptokit library *) (* *) (* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) (* *) (* Copyright 2002 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file LICENSE. *) (* *) (***********************************************************************) (** Operations on big integers, used for the implementation of module {!Cryptokit}. *) type t val zero : t val one : t val of_int : int -> t val compare : t -> t -> int val add : t -> t -> t val sub : t -> t -> t val mult : t -> t -> t val mod_ : t -> t -> t val relative_prime : t -> t -> bool val mod_power : t -> t -> t -> t val mod_power_CRT : t -> t -> t -> t -> t -> t -> t val mod_inv : t -> t -> t val of_bytes : string -> t val to_bytes : ?numbits:int -> t -> string val random : rng:(bytes -> int -> int -> unit) -> ?odd:bool -> int -> t val random_prime : rng:(bytes -> int -> int -> unit) -> int -> t val wipe : t -> unit cryptokit-release119/src/cryptokitBignumOld.ml000066400000000000000000000406671453705265000217550ustar00rootroot00000000000000(***********************************************************************) (* *) (* The Cryptokit library *) (* *) (* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) (* *) (* Copyright 2002 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file LICENSE. *) (* *) (***********************************************************************) (* Arithmetic on big integers, based on the Nums library. *) (* This implementation is obsolete and was replaced by another based on the ZArith library. It is kept for reference. *) open Nat type t = nat let wipe n = set_to_zero_nat n 0 (length_nat n) let zero = nat_of_int 0 let one = nat_of_int 1 let of_int = nat_of_int let compare a b = compare_nat a 0 (length_nat a) b 0 (length_nat b) let num_digits a = num_digits_nat a 0 (length_nat a) let num_bits a = let ndigits = num_digits a in ndigits * length_of_digit - num_leading_zero_bits_in_digit a (ndigits-1) let copy a = copy_nat a 0 (num_digits a) let add a b = let la = num_digits a and lb = num_digits b in if la >= lb then begin let r = create_nat (la + 1) in blit_nat r 0 a 0 la; set_digit_nat r la 0; ignore(add_nat r 0 (la + 1) b 0 lb 0); r end else begin let r = create_nat (lb + 1) in blit_nat r 0 b 0 lb; set_digit_nat r lb 0; ignore(add_nat r 0 (lb + 1) a 0 la 0); r end let sub a b = let la = num_digits a and lb = num_digits b in let lr = max la lb in let r = create_nat lr in blit_nat r 0 a 0 la; set_to_zero_nat r la (lr - la); let carry = sub_nat r 0 lr b 0 lb 1 in assert (carry = 1); r let sub_mod a b c = let la = num_digits a and lb = num_digits b and lc = num_digits c in let lr = max (max la lb) lc in let r = create_nat lr in blit_nat r 0 a 0 la; set_to_zero_nat r la (lr - la); if sub_nat r 0 lr b 0 lb 1 = 0 then ignore (add_nat r 0 lr c 0 lc 0); r let mult a b = let la = num_digits a and lb = num_digits b in let r = make_nat (la + lb) in ignore(mult_nat r 0 (la + lb) a 0 la b 0 lb); r let mult_add a b c = let la = num_digits a and lb = num_digits b and lc = num_digits c in let lr = 1 + max (la + lb) lc in let r = create_nat lr in blit_nat r 0 c 0 lc; set_to_zero_nat r lc (lr - lc); ignore(mult_nat r 0 lr a 0 la b 0 lb); r let mod_ a b = let la = num_digits a and lb = num_digits b in let ltmp = max la lb + 1 in let tmp = create_nat ltmp in blit_nat tmp 0 a 0 la; set_to_zero_nat tmp la (ltmp - la); div_nat tmp 0 ltmp b 0 lb; let lres = num_digits_nat tmp 0 lb in let res = create_nat lres in blit_nat res 0 tmp 0 lres; wipe tmp; res let quo_mod a b = let la = num_digits a and lb = num_digits b in let ltmp = max la lb + 1 in let tmp = create_nat ltmp in blit_nat tmp 0 a 0 la; set_to_zero_nat tmp la (ltmp - la); div_nat tmp 0 ltmp b 0 lb; let lq = num_digits_nat tmp lb (ltmp - lb) in let lm = num_digits_nat tmp 0 lb in let q = create_nat lq in let m = create_nat lm in blit_nat q 0 tmp lb lq; blit_nat m 0 tmp 0 lm; wipe tmp; (q, m) let relative_prime a b = let la = num_digits a and lb = num_digits b in let ltmp = max la lb in let tmp = create_nat ltmp in blit_nat tmp 0 a 0 la; set_to_zero_nat tmp la (ltmp - la); let lgcd = gcd_nat tmp 0 la b 0 lb in let res = lgcd = 1 && is_digit_int tmp 0 && nth_digit_nat tmp 0 = 1 in wipe tmp; res (* Compute a^b mod c. Must have [a < c]. *) let mod_power a b c = let la = num_digits a and lb = num_digits b and lc = num_digits c in let res = make_nat lc in set_digit_nat res 0 1; (* res = 1 initially *) let prod = create_nat (lc + lc + 1) in let window = create_nat 2 in (* For each bit of b, from MSB to LSB... *) for i = lb - 1 downto 0 do blit_nat window 0 b i 1; for j = length_of_digit downto 1 do (* res <- res ^ 2 mod c *) set_to_zero_nat prod 0 (lc + lc + 1); ignore(square_nat prod 0 (lc + lc) res 0 lc); (* prod[lc+lc] = 0 < c[lc-1] != 0 *) div_nat prod 0 (lc + lc + 1) c 0 lc; (* remainder is in (prod,0,lc) *) blit_nat res 0 prod 0 lc; (* shift window[0] left 1 bit and test carry out; that is, test bit number j of b[i] *) shift_left_nat window 0 1 window 1 1; if is_digit_odd window 1 then begin (* res <- res * a mod c *) set_to_zero_nat prod 0 (lc + la + 1); ignore(mult_nat prod 0 (lc + la) res 0 lc a 0 la); (* prod[lc+la] = 0 < c[lc-1] != 0 *) div_nat prod 0 (lc + la + 1) c 0 lc; (* remainder in (prod,0,lc) *) blit_nat res 0 prod 0 lc; end done done; wipe prod; wipe window; res (* Modular exponentiation via the Chinese Remainder Theorem. Compute a ^ d mod pq, where d is defined by dp = d mod (p-1) and dq = d mod (q-1). qinv is q^-1 mod p. Formula: mp = (a mod p)^dp mod p mq = (a mod q)^dq mod q m = ((((mp - mq) mod p) * qInv) mod p) * q + mq *) let mod_power_CRT a p q dp dq qinv = let amodp = mod_ a p and amodq = mod_ a q in let mp = mod_power amodp dp p and mq = mod_power amodq dq q in let diff = sub_mod mp mq p in let diff_qinv = mult diff qinv in let diff_qinv_mod_p = mod_ diff_qinv p in let res = mult_add q diff_qinv_mod_p mq in wipe amodp; wipe amodq; wipe mp; wipe mq; wipe diff; wipe diff_qinv; wipe diff_qinv_mod_p; res (* Modular inverse. Return u such that n.u mod m = 1, or raise Division_by_zero if no such u exists (i.e. gcd(n,m) <> 1). Must have [n < m]. *) let mod_inv b c = let rec extended_euclid u1 v1 u3 v3 sign = if compare v3 zero = 0 then if compare u3 one = 0 then begin wipe v1; if sign < 0 then sub c u1 else u1 end else begin wipe u1; wipe v1; wipe u3; raise Division_by_zero end else begin let (q,r) = quo_mod u3 v3 in let t1 = mult_add q v1 u1 in wipe u3; wipe q; wipe u1; extended_euclid v1 t1 v3 r (-sign) end in extended_euclid (nat_of_int 1) (nat_of_int 0) (copy b) (copy c) 1 (* Conversions between nats and strings *) let bytes_per_digit = length_of_digit / 8 let of_bytes s = let l = String.length s in if l = 0 then make_nat 1 else begin let n = make_nat ((l + bytes_per_digit - 1) / bytes_per_digit) in let tmp = create_nat 2 in for i = 0 to l - 1 do let pos = i / bytes_per_digit and shift = (i mod bytes_per_digit) * 8 in set_digit_nat tmp 0 (Char.code s.[l-1-i]); shift_left_nat tmp 0 1 tmp 1 shift; lor_digit_nat n pos tmp 0 done; wipe tmp; n end let to_bytes ?numbits n = let nbits = num_bits n in begin match numbits with None -> () | Some n -> assert (nbits <= n) end; let l = ((nbits + 7) / 8) in let s = String.create ((nbits + 7) / 8) in let tmp = create_nat 2 in for i = 0 to l - 1 do let pos = i / bytes_per_digit and shift = (i mod bytes_per_digit) * 8 in blit_nat tmp 0 n pos 1; shift_right_nat tmp 0 1 tmp 1 shift; s.[l-1-i] <- Char.unsafe_chr(nth_digit_nat tmp 0) done; wipe tmp; match numbits with None -> s | Some n -> let l' = ((n + 7) / 8) in if l = l' then s else String.make (l' - l) '\000' ^ s let wipe_string s = String.fill s 0 (String.length s) '\000' let random ~rng ?(odd = false) numbits = let numdigits = ((numbits + length_of_digit - 1) / length_of_digit) in let buf = String.create (numdigits * length_of_digit / 8) in rng buf 0 (String.length buf); (* move them to a nat *) let n = of_bytes buf in wipe_string buf; let tmp = create_nat 2 in (* adjust low digit of n if requested *) if odd then set_digit_nat tmp 0 1; lor_digit_nat n 0 tmp 0 end; (* adjust high digit of n so that it is exactly numbits long *) shift_left_nat tmp 0 1 tmp 1 ((numbits - 1) land (length_of_digit - 1)); ignore(decr_nat tmp 0 1 0); land_digit_nat n (numdigits - 1) tmp 0; ignore(incr_nat tmp 0 1 1); lor_digit_nat n (numdigits - 1) tmp 0; (* done *) n let small_primes = [ 2; 3; 5; 7; 11; 13; 17; 19; 23; 29; 31; 37; 41; 43; 47; 53; 59; 61; 67; 71; 73; 79; 83; 89; 97; 101; 103; 107; 109; 113; 127; 131; 137; 139; 149; 151; 157; 163; 167; 173; 179; 181; 191; 193; 197; 199; 211; 223; 227; 229; 233; 239; 241; 251; 257; 263; 269; 271; 277; 281; 283; 293; 307; 311; 313; 317; 331; 337; 347; 349; 353; 359; 367; 373; 379; 383; 389; 397; 401; 409; 419; 421; 431; 433; 439; 443; 449; 457; 461; 463; 467; 479; 487; 491; 499; 503; 509; 521; 523; 541; 547; 557; 563; 569; 571; 577; 587; 593; 599; 601; 607; 613; 617; 619; 631; 641; 643; 647; 653; 659; 661; 673; 677; 683; 691; 701; 709; 719; 727; 733; 739; 743; 751; 757; 761; 769; 773; 787; 797; 809; 811; 821; 823; 827; 829; 839; 853; 857; 859; 863; 877; 881; 883; 887; 907; 911; 919; 929; 937; 941; 947; 953; 967; 971; 977; 983; 991; 997; 1009; 1013; 1019; 1021; 1031; 1033; 1039; 1049; 1051; 1061; 1063; 1069; 1087; 1091; 1093; 1097; 1103; 1109; 1117; 1123; 1129; 1151; 1153; 1163; 1171; 1181; 1187; 1193; 1201; 1213; 1217; 1223; 1229; 1231; 1237; 1249; 1259; 1277; 1279; 1283; 1289; 1291; 1297; 1301; 1303; 1307; 1319; 1321; 1327; 1361; 1367; 1373; 1381; 1399; 1409; 1423; 1427; 1429; 1433; 1439; 1447; 1451; 1453; 1459; 1471; 1481; 1483; 1487; 1489; 1493; 1499; 1511; 1523; 1531; 1543; 1549; 1553; 1559; 1567; 1571; 1579; 1583; 1597; 1601; 1607; 1609; 1613; 1619; 1621; 1627; 1637; 1657; 1663; 1667; 1669; 1693; 1697; 1699; 1709; 1721; 1723; 1733; 1741; 1747; 1753; 1759; 1777; 1783; 1787; 1789; 1801; 1811; 1823; 1831; 1847; 1861; 1867; 1871; 1873; 1877; 1879; 1889; 1901; 1907; 1913; 1931; 1933; 1949; 1951; 1973; 1979; 1987; 1993; 1997; 1999; 2003; 2011; 2017; 2027; 2029; 2039; 2053; 2063; 2069; 2081; 2083; 2087; 2089; 2099; 2111; 2113; 2129; 2131; 2137; 2141; 2143; 2153; 2161; 2179; 2203; 2207; 2213; 2221; 2237; 2239; 2243; 2251; 2267; 2269; 2273; 2281; 2287; 2293; 2297; 2309; 2311; 2333; 2339; 2341; 2347; 2351; 2357; 2371; 2377; 2381; 2383; 2389; 2393; 2399; 2411; 2417; 2423; 2437; 2441; 2447; 2459; 2467; 2473; 2477; 2503; 2521; 2531; 2539; 2543; 2549; 2551; 2557; 2579; 2591; 2593; 2609; 2617; 2621; 2633; 2647; 2657; 2659; 2663; 2671; 2677; 2683; 2687; 2689; 2693; 2699; 2707; 2711; 2713; 2719; 2729; 2731; 2741; 2749; 2753; 2767; 2777; 2789; 2791; 2797; 2801; 2803; 2819; 2833; 2837; 2843; 2851; 2857; 2861; 2879; 2887; 2897; 2903; 2909; 2917; 2927; 2939; 2953; 2957; 2963; 2969; 2971; 2999; 3001; 3011; 3019; 3023; 3037; 3041; 3049; 3061; 3067; 3079; 3083; 3089; 3109; 3119; 3121; 3137; 3163; 3167; 3169; 3181; 3187; 3191; 3203; 3209; 3217; 3221; 3229; 3251; 3253; 3257; 3259; 3271; 3299; 3301; 3307; 3313; 3319; 3323; 3329; 3331; 3343; 3347; 3359; 3361; 3371; 3373; 3389; 3391; 3407; 3413; 3433; 3449; 3457; 3461; 3463; 3467; 3469; 3491; 3499; 3511; 3517; 3527; 3529; 3533; 3539; 3541; 3547; 3557; 3559; 3571; 3581; 3583; 3593; 3607; 3613; 3617; 3623; 3631; 3637; 3643; 3659; 3671; 3673; 3677; 3691; 3697; 3701; 3709; 3719; 3727; 3733; 3739; 3761; 3767; 3769; 3779; 3793; 3797; 3803; 3821; 3823; 3833; 3847; 3851; 3853; 3863; 3877; 3881; 3889; 3907; 3911; 3917; 3919; 3923; 3929; 3931; 3943; 3947; 3967; 3989; 4001; 4003; 4007; 4013; 4019; 4021; 4027; 4049; 4051; 4057; 4073; 4079; 4091; 4093; 4099; 4111; 4127; 4129; 4133; 4139; 4153; 4157; 4159; 4177; 4201; 4211; 4217; 4219; 4229; 4231; 4241; 4243; 4253; 4259; 4261; 4271; 4273; 4283; 4289; 4297; 4327; 4337; 4339; 4349; 4357; 4363; 4373; 4391; 4397; 4409; 4421; 4423; 4441; 4447; 4451; 4457; 4463; 4481; 4483; 4493; 4507; 4513; 4517; 4519; 4523; 4547; 4549; 4561; 4567; 4583; 4591; 4597; 4603; 4621; 4637; 4639; 4643; 4649; 4651; 4657; 4663; 4673; 4679; 4691; 4703; 4721; 4723; 4729; 4733; 4751; 4759; 4783; 4787; 4789; 4793; 4799; 4801; 4813; 4817; 4831; 4861; 4871; 4877; 4889; 4903; 4909; 4919; 4931; 4933; 4937; 4943; 4951; 4957; 4967; 4969; 4973; 4987; 4993; 4999; 5003; 5009; 5011; 5021; 5023; 5039; 5051; 5059; 5077; 5081; 5087; 5099; 5101; 5107; 5113; 5119; 5147; 5153; 5167; 5171; 5179; 5189; 5197; 5209; 5227; 5231; 5233; 5237; 5261; 5273; 5279; 5281; 5297; 5303; 5309; 5323; 5333; 5347; 5351; 5381; 5387; 5393; 5399; 5407; 5413; 5417; 5419; 5431; 5437; 5441; 5443; 5449; 5471; 5477; 5479; 5483; 5501; 5503; 5507; 5519; 5521; 5527; 5531; 5557; 5563; 5569; 5573; 5581; 5591; 5623; 5639; 5641; 5647; 5651; 5653; 5657; 5659; 5669; 5683; 5689; 5693; 5701; 5711; 5717; 5737; 5741; 5743; 5749; 5779; 5783; 5791; 5801; 5807; 5813; 5821; 5827; 5839; 5843; 5849; 5851; 5857; 5861; 5867; 5869; 5879; 5881; 5897; 5903; 5923; 5927; 5939; 5953; 5981; 5987; 6007; 6011; 6029; 6037; 6043; 6047; 6053; 6067; 6073; 6079; 6089; 6091; 6101; 6113; 6121; 6131; 6133; 6143; 6151; 6163; 6173; 6197; 6199; 6203; 6211; 6217; 6221; 6229; 6247; 6257; 6263; 6269; 6271; 6277; 6287; 6299; 6301; 6311; 6317; 6323; 6329; 6337; 6343; 6353; 6359; 6361; 6367; 6373; 6379; 6389; 6397; 6421; 6427; 6449; 6451; 6469; 6473; 6481; 6491; 6521; 6529; 6547; 6551; 6553; 6563; 6569; 6571; 6577; 6581; 6599; 6607; 6619; 6637; 6653; 6659; 6661; 6673; 6679; 6689; 6691; 6701; 6703; 6709; 6719; 6733; 6737; 6761; 6763; 6779; 6781; 6791; 6793; 6803; 6823; 6827; 6829; 6833; 6841; 6857; 6863; 6869; 6871; 6883; 6899; 6907; 6911; 6917; 6947; 6949; 6959; 6961; 6967; 6971; 6977; 6983; 6991; 6997; 7001; 7013; 7019; 7027; 7039; 7043; 7057; 7069; 7079; 7103; 7109; 7121; 7127; 7129; 7151; 7159; 7177; 7187; 7193; 7207; 7211; 7213; 7219; 7229; 7237; 7243; 7247; 7253; 7283; 7297; 7307; 7309; 7321; 7331; 7333; 7349; 7351; 7369; 7393; 7411; 7417; 7433; 7451; 7457; 7459; 7477; 7481; 7487; 7489; 7499; 7507; 7517; 7523; 7529; 7537; 7541; 7547; 7549; 7559; 7561; 7573; 7577; 7583; 7589; 7591; 7603; 7607; 7621; 7639; 7643; 7649; 7669; 7673; 7681; 7687; 7691; 7699; 7703; 7717; 7723; 7727; 7741; 7753; 7757; 7759; 7789; 7793; 7817; 7823; 7829; 7841; 7853; 7867; 7873; 7877; 7879; 7883; 7901; 7907; 7919; 7927; 7933; 7937; 7949; 7951; 7963; 7993; 8009; 8011; 8017; 8039; 8053; 8059; 8069; 8081; 8087; 8089; 8093; 8101; 8111; 8117; 8123; 8147; 8161; 8167; 8171; 8179; 8191 ] let moduli_small_primes n = let ln = num_digits n in let dend = create_nat (ln + 1) and dsor = create_nat 1 and quot = create_nat ln and rem = create_nat 1 in let res = List.map (fun p -> (* Compute m = n mod p *) blit_nat dend 0 n 0 ln; set_digit_nat dend ln 0; set_digit_nat dsor 0 p; div_digit_nat quot 0 rem 0 dend 0 (ln + 1) dsor 0; nth_digit_nat rem 0) small_primes in wipe dend; wipe dsor; wipe quot; wipe rem; res let is_divisible_by_small_prime delta remainders = List.exists2 (fun p m -> (m + delta) mod p = 0) small_primes remainders let pseudoprime_test_values = [2;3;5;7;11;13;17;19] let is_pseudoprime p = let p1 = sub p one in let res = List.for_all (fun x -> let q = mod_power (nat_of_int x) p1 p in let r = compare q one in wipe q; r = 0) pseudoprime_test_values in wipe p1; res let rec random_prime ~rng numbits = (* Generate random odd number *) let n = random ~rng ~odd:true numbits in (* Precompute moduli with small primes *) let moduli = moduli_small_primes n in (* Search from n *) let rec find_prime delta = if delta < 0 then (* arithmetic overflow in incrementing delta *) random_prime ~rng numbits else if is_divisible_by_small_prime delta moduli then find_prime (delta + 2) else begin let n' = add n (nat_of_int delta) in if is_pseudoprime n' then if num_bits n' = numbits then begin wipe n; n' end else begin (* overflow in adding delta to n *) wipe n; wipe n'; random_prime ~rng numbits end else find_prime (delta + 2) end in find_prime 0 cryptokit-release119/src/cryptokitBignumOld.mli000066400000000000000000000027101453705265000221110ustar00rootroot00000000000000(***********************************************************************) (* *) (* The Cryptokit library *) (* *) (* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) (* *) (* Copyright 2002 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file LICENSE. *) (* *) (***********************************************************************) (* Arithmetic on big integers *) type t val zero : t val one : t val of_int : int -> t val compare : t -> t -> int val add : t -> t -> t val sub : t -> t -> t val mult : t -> t -> t val mod_ : t -> t -> t val relative_prime : t -> t -> bool val mod_power : t -> t -> t -> t val mod_power_CRT : t -> t -> t -> t -> t -> t -> t val mod_inv : t -> t -> t val of_bytes : string -> t val to_bytes : ?numbits:int -> t -> bytes val random : rng:(bytes -> int -> int -> unit) -> ?lowbits:int -> int -> t val random_prime : rng:(bytes -> int -> int -> unit) -> int -> t val wipe : t -> unit cryptokit-release119/src/d3des.c000066400000000000000000000330731453705265000167310ustar00rootroot00000000000000/* D3DES (V5.09) - * * A portable, public domain, version of the Data Encryption Standard. * * Written with Symantec's THINK (Lightspeed) C by Richard Outerbridge. * Thanks to: Dan Hoey for his excellent Initial and Inverse permutation * code; Jim Gillogly & Phil Karn for the DES key schedule code; Dennis * Ferguson, Eric Young and Dana How for comparing notes; and Ray Lau, * for humouring me on. * * Copyright (c) 1988,1989,1990,1991,1992 by Richard Outerbridge. * (GEnie : OUTER; CIS : [71755,204]) Graven Imagery, 1992. * * Modified and adapted by Xavier Leroy, 2002. */ #include "d3des.h" static void scrunch(u8 *, u32 *); static void unscrun(u32 *, u8 *); static void desfunc(u32 *, u32 *); static void cookey(u32 *, u32 *); static unsigned short bytebit[8] = { 0200, 0100, 040, 020, 010, 04, 02, 01 }; static u32 bigbyte[24] = { 0x800000L, 0x400000L, 0x200000L, 0x100000L, 0x80000L, 0x40000L, 0x20000L, 0x10000L, 0x8000L, 0x4000L, 0x2000L, 0x1000L, 0x800L, 0x400L, 0x200L, 0x100L, 0x80L, 0x40L, 0x20L, 0x10L, 0x8L, 0x4L, 0x2L, 0x1L }; /* Use the key schedule specified in the Standard (ANSI X3.92-1981). */ static u8 pc1[56] = { 56, 48, 40, 32, 24, 16, 8, 0, 57, 49, 41, 33, 25, 17, 9, 1, 58, 50, 42, 34, 26, 18, 10, 2, 59, 51, 43, 35, 62, 54, 46, 38, 30, 22, 14, 6, 61, 53, 45, 37, 29, 21, 13, 5, 60, 52, 44, 36, 28, 20, 12, 4, 27, 19, 11, 3 }; static u8 totrot[16] = { 1,2,4,6,8,10,12,14,15,17,19,21,23,25,27,28 }; static u8 pc2[48] = { 13, 16, 10, 23, 0, 4, 2, 27, 14, 5, 20, 9, 22, 18, 11, 3, 25, 7, 15, 6, 26, 19, 12, 1, 40, 51, 30, 36, 46, 54, 29, 39, 50, 44, 32, 47, 43, 48, 38, 55, 33, 52, 45, 41, 49, 35, 28, 31 }; void d3des_cook_key(u8 key[8], int edf, u32 res[32]) /* Thanks to James Gillogly & Phil Karn! */ { register int i, j, l, m, n; u8 pc1m[56], pcr[56]; u32 kn[32]; for ( j = 0; j < 56; j++ ) { l = pc1[j]; m = l & 07; pc1m[j] = (key[l >> 3] & bytebit[m]) ? 1 : 0; } for( i = 0; i < 16; i++ ) { if( edf == DE1 ) m = (15 - i) << 1; else m = i << 1; n = m + 1; kn[m] = kn[n] = 0L; for( j = 0; j < 28; j++ ) { l = j + totrot[i]; if( l < 28 ) pcr[j] = pc1m[l]; else pcr[j] = pc1m[l - 28]; } for( j = 28; j < 56; j++ ) { l = j + totrot[i]; if( l < 56 ) pcr[j] = pc1m[l]; else pcr[j] = pc1m[l - 28]; } for( j = 0; j < 24; j++ ) { if( pcr[pc2[j]] ) kn[m] |= bigbyte[j]; if( pcr[pc2[j+24]] ) kn[n] |= bigbyte[j]; } } cookey(kn, res); return; } static void cookey(u32 * raw1, u32 * cook) { register u32 *raw0; register int i; for( i = 0; i < 16; i++, raw1++ ) { raw0 = raw1++; *cook = (*raw0 & 0x00fc0000L) << 6; *cook |= (*raw0 & 0x00000fc0L) << 10; *cook |= (*raw1 & 0x00fc0000L) >> 10; *cook++ |= (*raw1 & 0x00000fc0L) >> 6; *cook = (*raw0 & 0x0003f000L) << 12; *cook |= (*raw0 & 0x0000003fL) << 16; *cook |= (*raw1 & 0x0003f000L) >> 4; *cook++ |= (*raw1 & 0x0000003fL); } return; } void d3des_transform(u32 key[32], u8 inblock[8], u8 outblock[8]) { u32 work[2]; scrunch(inblock, work); desfunc(work, key); unscrun(work, outblock); } static void scrunch(u8 * outof, u32 * into) { into[0] = (outof[0] << 24) | (outof[1] << 16) | (outof[2] << 8) | outof[3]; into[1] = (outof[4] << 24) | (outof[5] << 16) | (outof[6] << 8) | outof[7]; } static void unscrun(u32 * outof, u8 * into) { u32 n; n = outof[0]; into[0] = (n >> 24); into[1] = (n >> 16); into[2] = (n >> 8); into[3] = n; n = outof[1]; into[4] = (n >> 24); into[5] = (n >> 16); into[6] = (n >> 8); into[7] = n; } static u32 SP1[64] = { 0x01010400L, 0x00000000L, 0x00010000L, 0x01010404L, 0x01010004L, 0x00010404L, 0x00000004L, 0x00010000L, 0x00000400L, 0x01010400L, 0x01010404L, 0x00000400L, 0x01000404L, 0x01010004L, 0x01000000L, 0x00000004L, 0x00000404L, 0x01000400L, 0x01000400L, 0x00010400L, 0x00010400L, 0x01010000L, 0x01010000L, 0x01000404L, 0x00010004L, 0x01000004L, 0x01000004L, 0x00010004L, 0x00000000L, 0x00000404L, 0x00010404L, 0x01000000L, 0x00010000L, 0x01010404L, 0x00000004L, 0x01010000L, 0x01010400L, 0x01000000L, 0x01000000L, 0x00000400L, 0x01010004L, 0x00010000L, 0x00010400L, 0x01000004L, 0x00000400L, 0x00000004L, 0x01000404L, 0x00010404L, 0x01010404L, 0x00010004L, 0x01010000L, 0x01000404L, 0x01000004L, 0x00000404L, 0x00010404L, 0x01010400L, 0x00000404L, 0x01000400L, 0x01000400L, 0x00000000L, 0x00010004L, 0x00010400L, 0x00000000L, 0x01010004L }; static u32 SP2[64] = { 0x80108020L, 0x80008000L, 0x00008000L, 0x00108020L, 0x00100000L, 0x00000020L, 0x80100020L, 0x80008020L, 0x80000020L, 0x80108020L, 0x80108000L, 0x80000000L, 0x80008000L, 0x00100000L, 0x00000020L, 0x80100020L, 0x00108000L, 0x00100020L, 0x80008020L, 0x00000000L, 0x80000000L, 0x00008000L, 0x00108020L, 0x80100000L, 0x00100020L, 0x80000020L, 0x00000000L, 0x00108000L, 0x00008020L, 0x80108000L, 0x80100000L, 0x00008020L, 0x00000000L, 0x00108020L, 0x80100020L, 0x00100000L, 0x80008020L, 0x80100000L, 0x80108000L, 0x00008000L, 0x80100000L, 0x80008000L, 0x00000020L, 0x80108020L, 0x00108020L, 0x00000020L, 0x00008000L, 0x80000000L, 0x00008020L, 0x80108000L, 0x00100000L, 0x80000020L, 0x00100020L, 0x80008020L, 0x80000020L, 0x00100020L, 0x00108000L, 0x00000000L, 0x80008000L, 0x00008020L, 0x80000000L, 0x80100020L, 0x80108020L, 0x00108000L }; static u32 SP3[64] = { 0x00000208L, 0x08020200L, 0x00000000L, 0x08020008L, 0x08000200L, 0x00000000L, 0x00020208L, 0x08000200L, 0x00020008L, 0x08000008L, 0x08000008L, 0x00020000L, 0x08020208L, 0x00020008L, 0x08020000L, 0x00000208L, 0x08000000L, 0x00000008L, 0x08020200L, 0x00000200L, 0x00020200L, 0x08020000L, 0x08020008L, 0x00020208L, 0x08000208L, 0x00020200L, 0x00020000L, 0x08000208L, 0x00000008L, 0x08020208L, 0x00000200L, 0x08000000L, 0x08020200L, 0x08000000L, 0x00020008L, 0x00000208L, 0x00020000L, 0x08020200L, 0x08000200L, 0x00000000L, 0x00000200L, 0x00020008L, 0x08020208L, 0x08000200L, 0x08000008L, 0x00000200L, 0x00000000L, 0x08020008L, 0x08000208L, 0x00020000L, 0x08000000L, 0x08020208L, 0x00000008L, 0x00020208L, 0x00020200L, 0x08000008L, 0x08020000L, 0x08000208L, 0x00000208L, 0x08020000L, 0x00020208L, 0x00000008L, 0x08020008L, 0x00020200L }; static u32 SP4[64] = { 0x00802001L, 0x00002081L, 0x00002081L, 0x00000080L, 0x00802080L, 0x00800081L, 0x00800001L, 0x00002001L, 0x00000000L, 0x00802000L, 0x00802000L, 0x00802081L, 0x00000081L, 0x00000000L, 0x00800080L, 0x00800001L, 0x00000001L, 0x00002000L, 0x00800000L, 0x00802001L, 0x00000080L, 0x00800000L, 0x00002001L, 0x00002080L, 0x00800081L, 0x00000001L, 0x00002080L, 0x00800080L, 0x00002000L, 0x00802080L, 0x00802081L, 0x00000081L, 0x00800080L, 0x00800001L, 0x00802000L, 0x00802081L, 0x00000081L, 0x00000000L, 0x00000000L, 0x00802000L, 0x00002080L, 0x00800080L, 0x00800081L, 0x00000001L, 0x00802001L, 0x00002081L, 0x00002081L, 0x00000080L, 0x00802081L, 0x00000081L, 0x00000001L, 0x00002000L, 0x00800001L, 0x00002001L, 0x00802080L, 0x00800081L, 0x00002001L, 0x00002080L, 0x00800000L, 0x00802001L, 0x00000080L, 0x00800000L, 0x00002000L, 0x00802080L }; static u32 SP5[64] = { 0x00000100L, 0x02080100L, 0x02080000L, 0x42000100L, 0x00080000L, 0x00000100L, 0x40000000L, 0x02080000L, 0x40080100L, 0x00080000L, 0x02000100L, 0x40080100L, 0x42000100L, 0x42080000L, 0x00080100L, 0x40000000L, 0x02000000L, 0x40080000L, 0x40080000L, 0x00000000L, 0x40000100L, 0x42080100L, 0x42080100L, 0x02000100L, 0x42080000L, 0x40000100L, 0x00000000L, 0x42000000L, 0x02080100L, 0x02000000L, 0x42000000L, 0x00080100L, 0x00080000L, 0x42000100L, 0x00000100L, 0x02000000L, 0x40000000L, 0x02080000L, 0x42000100L, 0x40080100L, 0x02000100L, 0x40000000L, 0x42080000L, 0x02080100L, 0x40080100L, 0x00000100L, 0x02000000L, 0x42080000L, 0x42080100L, 0x00080100L, 0x42000000L, 0x42080100L, 0x02080000L, 0x00000000L, 0x40080000L, 0x42000000L, 0x00080100L, 0x02000100L, 0x40000100L, 0x00080000L, 0x00000000L, 0x40080000L, 0x02080100L, 0x40000100L }; static u32 SP6[64] = { 0x20000010L, 0x20400000L, 0x00004000L, 0x20404010L, 0x20400000L, 0x00000010L, 0x20404010L, 0x00400000L, 0x20004000L, 0x00404010L, 0x00400000L, 0x20000010L, 0x00400010L, 0x20004000L, 0x20000000L, 0x00004010L, 0x00000000L, 0x00400010L, 0x20004010L, 0x00004000L, 0x00404000L, 0x20004010L, 0x00000010L, 0x20400010L, 0x20400010L, 0x00000000L, 0x00404010L, 0x20404000L, 0x00004010L, 0x00404000L, 0x20404000L, 0x20000000L, 0x20004000L, 0x00000010L, 0x20400010L, 0x00404000L, 0x20404010L, 0x00400000L, 0x00004010L, 0x20000010L, 0x00400000L, 0x20004000L, 0x20000000L, 0x00004010L, 0x20000010L, 0x20404010L, 0x00404000L, 0x20400000L, 0x00404010L, 0x20404000L, 0x00000000L, 0x20400010L, 0x00000010L, 0x00004000L, 0x20400000L, 0x00404010L, 0x00004000L, 0x00400010L, 0x20004010L, 0x00000000L, 0x20404000L, 0x20000000L, 0x00400010L, 0x20004010L }; static u32 SP7[64] = { 0x00200000L, 0x04200002L, 0x04000802L, 0x00000000L, 0x00000800L, 0x04000802L, 0x00200802L, 0x04200800L, 0x04200802L, 0x00200000L, 0x00000000L, 0x04000002L, 0x00000002L, 0x04000000L, 0x04200002L, 0x00000802L, 0x04000800L, 0x00200802L, 0x00200002L, 0x04000800L, 0x04000002L, 0x04200000L, 0x04200800L, 0x00200002L, 0x04200000L, 0x00000800L, 0x00000802L, 0x04200802L, 0x00200800L, 0x00000002L, 0x04000000L, 0x00200800L, 0x04000000L, 0x00200800L, 0x00200000L, 0x04000802L, 0x04000802L, 0x04200002L, 0x04200002L, 0x00000002L, 0x00200002L, 0x04000000L, 0x04000800L, 0x00200000L, 0x04200800L, 0x00000802L, 0x00200802L, 0x04200800L, 0x00000802L, 0x04000002L, 0x04200802L, 0x04200000L, 0x00200800L, 0x00000000L, 0x00000002L, 0x04200802L, 0x00000000L, 0x00200802L, 0x04200000L, 0x00000800L, 0x04000002L, 0x04000800L, 0x00000800L, 0x00200002L }; static u32 SP8[64] = { 0x10001040L, 0x00001000L, 0x00040000L, 0x10041040L, 0x10000000L, 0x10001040L, 0x00000040L, 0x10000000L, 0x00040040L, 0x10040000L, 0x10041040L, 0x00041000L, 0x10041000L, 0x00041040L, 0x00001000L, 0x00000040L, 0x10040000L, 0x10000040L, 0x10001000L, 0x00001040L, 0x00041000L, 0x00040040L, 0x10040040L, 0x10041000L, 0x00001040L, 0x00000000L, 0x00000000L, 0x10040040L, 0x10000040L, 0x10001000L, 0x00041040L, 0x00040000L, 0x00041040L, 0x00040000L, 0x10041000L, 0x00001000L, 0x00000040L, 0x10040040L, 0x00001000L, 0x00041040L, 0x10001000L, 0x00000040L, 0x10000040L, 0x10040000L, 0x10040040L, 0x10000000L, 0x00040000L, 0x10001040L, 0x00000000L, 0x10041040L, 0x00040040L, 0x10000040L, 0x10040000L, 0x10001000L, 0x10001040L, 0x00000000L, 0x10041040L, 0x00041000L, 0x00041000L, 0x00001040L, 0x00001040L, 0x00040040L, 0x10000000L, 0x10041000L }; static void desfunc(u32 * block, u32 * keys) { register u32 fval, work, right, leftt; register int round; leftt = block[0]; right = block[1]; work = ((leftt >> 4) ^ right) & 0x0f0f0f0fL; right ^= work; leftt ^= (work << 4); work = ((leftt >> 16) ^ right) & 0x0000ffffL; right ^= work; leftt ^= (work << 16); work = ((right >> 2) ^ leftt) & 0x33333333L; leftt ^= work; right ^= (work << 2); work = ((right >> 8) ^ leftt) & 0x00ff00ffL; leftt ^= work; right ^= (work << 8); right = ((right << 1) | ((right >> 31) & 1L)); work = (leftt ^ right) & 0xaaaaaaaaL; leftt ^= work; right ^= work; leftt = ((leftt << 1) | ((leftt >> 31) & 1L)); for( round = 0; round < 8; round++ ) { work = (right << 28) | (right >> 4); work ^= *keys++; fval = SP7[ work & 0x3fL]; fval |= SP5[(work >> 8) & 0x3fL]; fval |= SP3[(work >> 16) & 0x3fL]; fval |= SP1[(work >> 24) & 0x3fL]; work = right ^ *keys++; fval |= SP8[ work & 0x3fL]; fval |= SP6[(work >> 8) & 0x3fL]; fval |= SP4[(work >> 16) & 0x3fL]; fval |= SP2[(work >> 24) & 0x3fL]; leftt ^= fval; work = (leftt << 28) | (leftt >> 4); work ^= *keys++; fval = SP7[ work & 0x3fL]; fval |= SP5[(work >> 8) & 0x3fL]; fval |= SP3[(work >> 16) & 0x3fL]; fval |= SP1[(work >> 24) & 0x3fL]; work = leftt ^ *keys++; fval |= SP8[ work & 0x3fL]; fval |= SP6[(work >> 8) & 0x3fL]; fval |= SP4[(work >> 16) & 0x3fL]; fval |= SP2[(work >> 24) & 0x3fL]; right ^= fval; } right = (right << 31) | (right >> 1); work = (leftt ^ right) & 0xaaaaaaaaL; leftt ^= work; right ^= work; leftt = (leftt << 31) | (leftt >> 1); work = ((leftt >> 8) ^ right) & 0x00ff00ffL; right ^= work; leftt ^= (work << 8); work = ((leftt >> 2) ^ right) & 0x33333333L; right ^= work; leftt ^= (work << 2); work = ((right >> 16) ^ leftt) & 0x0000ffffL; leftt ^= work; right ^= (work << 16); work = ((right >> 4) ^ leftt) & 0x0f0f0f0fL; leftt ^= work; right ^= (work << 4); *block++ = right; *block = leftt; } /* Validation sets: * * Single-length key, single-length plaintext - * Key : 0123 4567 89ab cdef * Plain : 0123 4567 89ab cde7 * Cipher : c957 4425 6a5e d31d * * Double-length key, single-length plaintext - * Key : 0123 4567 89ab cdef fedc ba98 7654 3210 * Plain : 0123 4567 89ab cde7 * Cipher : 7f1d 0a77 826b 8aff * * Double-length key, double-length plaintext - * Key : 0123 4567 89ab cdef fedc ba98 7654 3210 * Plain : 0123 4567 89ab cdef 0123 4567 89ab cdff * Cipher : 27a0 8440 406a df60 278f 47cf 42d6 15d7 * * Triple-length key, single-length plaintext - * Key : 0123 4567 89ab cdef fedc ba98 7654 3210 89ab cdef 0123 4567 * Plain : 0123 4567 89ab cde7 * Cipher : de0b 7c06 ae5e 0ed5 * * Triple-length key, double-length plaintext - * Key : 0123 4567 89ab cdef fedc ba98 7654 3210 89ab cdef 0123 4567 * Plain : 0123 4567 89ab cdef 0123 4567 89ab cdff * Cipher : ad0d 1b30 ac17 cf07 0ed1 1c63 81e4 4de5 * * d3des V5.0a rwo 9208.07 18:44 Graven Imagery **********************************************************************/ cryptokit-release119/src/d3des.h000066400000000000000000000014751453705265000167370ustar00rootroot00000000000000/* d3des.h - * * Headers and defines for d3des.c * Graven Imagery, 1992. * * Copyright (c) 1988,1989,1990,1991,1992 by Richard Outerbridge * (GEnie : OUTER; CIS : [71755,204]) * * Modified and adapted by Xavier Leroy, 2002. */ #define EN0 0 /* MODE == encrypt */ #define DE1 1 /* MODE == decrypt */ typedef unsigned char u8; typedef unsigned int u32; extern void d3des_cook_key(u8 key[8], int mode, u32 res[32]); /* Sets the key register [res] according to the hexadecimal * key contained in the 8 bytes of [key], according to the DES, * for encryption or decryption according to [mode]. */ extern void d3des_transform(u32 key[32], u8 from[8], u8 to[8]); /* Encrypts/Decrypts (according to the key [key]) * one block of eight bytes at address 'from' * into the block at address 'to'. They can be the same. */ cryptokit-release119/src/dune000066400000000000000000000024271453705265000164400ustar00rootroot00000000000000(library (name cryptokit) (public_name cryptokit) (libraries unix zarith) (wrapped false) (modules CryptokitBignum Cryptokit) (foreign_stubs (language c) (flags -DCAML_NAME_SPACE -DBLAKE3_NO_SSE2 -DBLAKE3_NO_SSE41 -DBLAKE3_NO_AVX2 -DBLAKE3_NO_AVX512 -DBLAKE3_USE_NEON=0 (:include flags.sexp)) (names aesni arcfour stubs-arcfour blowfish stubs-blowfish d3des stubs-des rijndael-alg-fst ripemd160 stubs-ripemd160 sha1 stubs-sha1 sha256 stubs-sha256 sha512 stubs-sha512 stubs-aes stubs-md5 stubs-misc stubs-rng stubs-zlib keccak stubs-sha3 chacha20 stubs-chacha20 blake2 stubs-blake2 ghash pclmul stubs-ghash poly1305-donna stubs-poly1305 siphash stubs-siphash blake3 blake3_dispatch blake3_portable stubs-blake3)) (c_library_flags (:include library_flags.sexp)) (flags :standard -safe-string -w -7 -w -27 -w -37)) ; compute flags (rule (alias configure) (targets flags.sexp library_flags.sexp) (action (run config/flags.exe))) cryptokit-release119/src/ghash.c000066400000000000000000000075171453705265000170250ustar00rootroot00000000000000/***********************************************************************/ /* */ /* The Cryptokit library */ /* */ /* Xavier Leroy, Collège de France and Inria */ /* */ /* Copyright 2022 Institut National de Recherche en Informatique et */ /* en Automatique. All rights reserved. This file is distributed */ /* under the terms of the GNU Library General Public License, with */ /* the special exception on linking described in file LICENSE. */ /* */ /***********************************************************************/ /* Software implementation of GHASH multiplication */ /* Based on the implementation by Steven M. Gibson at https://github.com/mko-x/SharedAES-GCM/blob/master/Sources/gcm.c Gibson's implementation is in the public domain. */ #include #include #include "ghash.h" static inline uint64_t get_uint64_be(const uint8_t * b, int i) { return ( (uint64_t) b[i ] << 56 ) | ( (uint64_t) b[i + 1] << 48 ) | ( (uint64_t) b[i + 2] << 40 ) | ( (uint64_t) b[i + 3] << 32 ) | ( (uint64_t) b[i + 4] << 24 ) | ( (uint64_t) b[i + 5] << 16 ) | ( (uint64_t) b[i + 6] << 8 ) | ( (uint64_t) b[i + 7] ); } static inline void put_uint64_be(uint64_t n, uint8_t * b, int i) { b[i ] = n >> 56; b[i + 1] = n >> 48; b[i + 2] = n >> 40; b[i + 3] = n >> 32; b[i + 4] = n >> 24; b[i + 5] = n >> 16; b[i + 6] = n >> 8; b[i + 7] = n; } void ghash_mult(const struct ghash_context * ctx, const uint8_t input[16], uint8_t output[16]) { static const uint64_t last4[16] = { 0x0000, 0x1c20, 0x3840, 0x2460, 0x7080, 0x6ca0, 0x48c0, 0x54e0, 0xe100, 0xfd20, 0xd940, 0xc560, 0x9180, 0x8da0, 0xa9c0, 0xb5e0 }; int i; uint8_t lo, hi, rem; uint64_t zh, zl; lo = (uint8_t)( input[15] & 0x0f ); hi = (uint8_t)( input[15] >> 4 ); zh = ctx->HH[lo]; zl = ctx->HL[lo]; for( i = 15; i >= 0; i-- ) { lo = (uint8_t) ( input[i] & 0x0f ); hi = (uint8_t) ( input[i] >> 4 ); if( i != 15 ) { rem = (uint8_t) ( zl & 0x0f ); zl = ( zh << 60 ) | ( zl >> 4 ); zh = ( zh >> 4 ); zh ^= (uint64_t) last4[rem] << 48; zh ^= ctx->HH[lo]; zl ^= ctx->HL[lo]; } rem = (uint8_t) ( zl & 0x0f ); zl = ( zh << 60 ) | ( zl >> 4 ); zh = ( zh >> 4 ); zh ^= (uint64_t) last4[rem] << 48; zh ^= ctx->HH[hi]; zl ^= ctx->HL[hi]; } put_uint64_be(zh, output, 0 ); put_uint64_be(zl, output, 8 ); } void ghash_init(struct ghash_context * ctx, const uint8_t h[16]) { int ret, i, j; uint64_t hi, lo; uint64_t vl, vh; memset(ctx, 0, sizeof(struct ghash_context)); vh = get_uint64_be(h, 0); vl = get_uint64_be(h, 8); ctx->HL[8] = vl; // 8 = 1000 corresponds to 1 in GF(2^128) ctx->HH[8] = vh; ctx->HH[0] = 0; // 0 corresponds to 0 in GF(2^128) ctx->HL[0] = 0; for( i = 4; i > 0; i >>= 1 ) { uint32_t T = (uint32_t) ( vl & 1 ) * 0xe1000000U; vl = ( vh << 63 ) | ( vl >> 1 ); vh = ( vh >> 1 ) ^ ( (uint64_t) T << 32); ctx->HL[i] = vl; ctx->HH[i] = vh; } for (i = 2; i < 16; i <<= 1 ) { uint64_t *HiL = ctx->HL + i, *HiH = ctx->HH + i; vh = *HiH; vl = *HiL; for( j = 1; j < i; j++ ) { HiH[j] = vh ^ ctx->HH[j]; HiL[j] = vl ^ ctx->HL[j]; } } } cryptokit-release119/src/ghash.h000066400000000000000000000024721453705265000170250ustar00rootroot00000000000000/***********************************************************************/ /* */ /* The Cryptokit library */ /* */ /* Xavier Leroy, Collège de France and Inria */ /* */ /* Copyright 2022 Institut National de Recherche en Informatique et */ /* en Automatique. All rights reserved. This file is distributed */ /* under the terms of the GNU Library General Public License, with */ /* the special exception on linking described in file LICENSE. */ /* */ /***********************************************************************/ /* Software implementation of GHASH multiplication */ struct ghash_context { uint64_t HL[16]; // precalculated lo-half HTable uint64_t HH[16]; // precalculated hi-half HTable }; extern void ghash_init(struct ghash_context * ctx, const uint8_t h[16]); extern void ghash_mult(const struct ghash_context * ctx, const uint8_t input[16], uint8_t output[16]); cryptokit-release119/src/keccak.c000066400000000000000000000122441453705265000171450ustar00rootroot00000000000000/* SHA-3 (Keccak) cryptographic hash function */ /* Code adapted from the "readable" implementation written by Markku-Juhani O. Saarinen */ #include #include #include #include "keccak.h" #define KECCAK_ROUNDS 24 #define ROTL64(x, y) (((x) << (y)) | ((x) >> (64 - (y)))) static const u64 keccakf_rndc[24] = { 0x0000000000000001, 0x0000000000008082, 0x800000000000808a, 0x8000000080008000, 0x000000000000808b, 0x0000000080000001, 0x8000000080008081, 0x8000000000008009, 0x000000000000008a, 0x0000000000000088, 0x0000000080008009, 0x000000008000000a, 0x000000008000808b, 0x800000000000008b, 0x8000000000008089, 0x8000000000008003, 0x8000000000008002, 0x8000000000000080, 0x000000000000800a, 0x800000008000000a, 0x8000000080008081, 0x8000000000008080, 0x0000000080000001, 0x8000000080008008 }; #if 0 /* Inlined */ static const int keccakf_rotc[24] = { 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 2, 14, 27, 41, 56, 8, 25, 43, 62, 18, 39, 61, 20, 44 }; static const int keccakf_piln[24] = { 10, 7, 11, 17, 18, 3, 5, 16, 8, 21, 24, 4, 15, 23, 19, 13, 12, 2, 20, 14, 22, 9, 6, 1 }; #endif /* Update the state with KECCAK_ROUND rounds */ static void KeccakPermutation(u64 st[25]) { int round, j; u64 t, bc[5]; for (round = 0; round < KECCAK_ROUNDS; round++) { // Theta #define THETA1(i) \ bc[i] = st[i] ^ st[i + 5] ^ st[i + 10] ^ st[i + 15] ^ st[i + 20] THETA1(0); THETA1(1); THETA1(2); THETA1(3); THETA1(4); #define THETA2(i) \ t = bc[(i + 4) % 5] ^ ROTL64(bc[(i + 1) % 5], 1); \ st[0 + i] ^= t; \ st[5 + i] ^= t; \ st[10 + i] ^= t; \ st[15 + i] ^= t; \ st[20 + i] ^= t THETA2(0); THETA2(1); THETA2(2); THETA2(3); THETA2(4); // Rho Pi #define RHOPI(i, rotc, piln) \ bc[0] = st[piln]; \ st[piln] = ROTL64(t, rotc); \ t = bc[0] t = st[1]; RHOPI(0, 1, 10); RHOPI(1, 3, 7); RHOPI(2, 6, 11); RHOPI(3, 10, 17); RHOPI(4, 15, 18); RHOPI(5, 21, 3); RHOPI(6, 28, 5); RHOPI(7, 36, 16); RHOPI(8, 45, 8); RHOPI(9, 55, 21); RHOPI(10, 2, 24); RHOPI(11, 14, 4); RHOPI(12, 27, 15); RHOPI(13, 41, 23); RHOPI(14, 56, 19); RHOPI(15, 8, 13); RHOPI(16, 25, 12); RHOPI(17, 43, 2); RHOPI(18, 62, 20); RHOPI(19, 18, 14); RHOPI(20, 39, 22); RHOPI(21, 61, 9); RHOPI(22, 20, 6); RHOPI(23, 44, 1); // Chi #define CHI1(i,j) \ bc[i] = st[j + i] #define CHI2(i,j) \ st[j + i] ^= (~bc[(i + 1) % 5]) & bc[(i + 2) % 5] for (j = 0; j < 25; j += 5) { CHI1(0,j); CHI1(1,j); CHI1(2,j); CHI1(3,j); CHI1(4,j); CHI2(0,j); CHI2(1,j); CHI2(2,j); CHI2(3,j); CHI2(4,j); } // Iota st[0] ^= keccakf_rndc[round]; } } /* Absorb the given data and permute */ static void KeccakAbsorb(u64 st[25], unsigned char * p, int rsiz) { int i; rsiz = rsiz / 8; for (i = 0; i < rsiz; i += 1, p += 8) { // fixme: use direct access for little-endian platforms without // alignment constraints? unsigned int l = p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24); unsigned int h = p[4] | (p[5] << 8) | (p[6] << 16) | (p[7] << 24); st[i] ^= l | ((unsigned long long) h << 32); } KeccakPermutation(st); } /* Exported interface */ void SHA3_init(struct SHA3Context * ctx, int hsiz) { assert (hsiz == 224 || hsiz == 256 || hsiz == 384 || hsiz == 512); ctx->hsiz = hsiz / 8; ctx->rsiz = 200 - 2 * ctx->hsiz; ctx->numbytes = 0; memset(ctx->state, 0, sizeof(ctx->state)); } void SHA3_absorb(struct SHA3Context * ctx, unsigned char * data, unsigned long len) { int n; /* If data was left in buffer, fill with fresh data and absorb */ if (ctx->numbytes != 0) { n = ctx->rsiz - ctx->numbytes; if (len < n) { memcpy(ctx->buffer + ctx->numbytes, data, len); ctx->numbytes += len; return; } memcpy(ctx->buffer + ctx->numbytes, data, n); KeccakAbsorb(ctx->state, ctx->buffer, ctx->rsiz); data += n; len -= n; } /* Absorb data in blocks of [rsiz] bytes */ while (len >= ctx->rsiz) { KeccakAbsorb(ctx->state, data, ctx->rsiz); data += ctx->rsiz; len -= ctx->rsiz; } /* Save remaining data */ if (len > 0) memcpy(ctx->buffer, data, len); ctx->numbytes = len; } void SHA3_extract(unsigned char padding, struct SHA3Context * ctx, unsigned char * output) { int i, j, n; /* Apply final padding */ n = ctx->numbytes; ctx->buffer[n] = padding; n++; memset(ctx->buffer + n, 0, ctx->rsiz - n); ctx->buffer[ctx->rsiz - 1] |= 0x80; /* Absorb remaining data + padding */ KeccakAbsorb(ctx->state, ctx->buffer, ctx->rsiz); /* Extract hash as low bits of state */ for (i = 0, j = 0; j < ctx->hsiz; i += 1, j += 8) { u64 st = ctx->state[i]; output[j] = st; output[j + 1] = st >> 8; output[j + 2] = st >> 16; output[j + 3] = st >> 24; if (j + 4 >= ctx->hsiz) break; output[j + 4] = st >> 32; output[j + 5] = st >> 40; output[j + 6] = st >> 48; output[j + 7] = st >> 56; } } cryptokit-release119/src/keccak.h000066400000000000000000000012561453705265000171530ustar00rootroot00000000000000/* SHA-3 (Keccak) cryptographic hash function */ typedef unsigned long long u64; struct SHA3Context { u64 state[25]; unsigned char buffer[144]; int numbytes; /* number of bytes in buffer */ int rsiz; /* number of message bytes processed by permutation */ int hsiz; /* size of hash in bytes */ }; extern void SHA3_init(struct SHA3Context * ctx, int hsiz); extern void SHA3_absorb(struct SHA3Context * ctx, unsigned char * data, unsigned long len); extern void SHA3_extract(unsigned char padding, struct SHA3Context * ctx, unsigned char * output); cryptokit-release119/src/pclmul.c000066400000000000000000000065721453705265000172270ustar00rootroot00000000000000/***********************************************************************/ /* */ /* The Cryptokit library */ /* */ /* Xavier Leroy, Collège de France and Inria */ /* */ /* Copyright 2022 Institut National de Recherche en Informatique et */ /* en Automatique. All rights reserved. This file is distributed */ /* under the terms of the GNU Library General Public License, with */ /* the special exception on linking described in file LICENSE. */ /* */ /***********************************************************************/ /* Hardware-accelerated implementation of GHASH multiplication */ #include #include #include "pclmul.h" #ifdef __PCLMUL__ #include #include #include int pclmul_available = -1; int pclmul_check_available(void) { unsigned int eax, ebx, ecx, edx; if(__get_cpuid(1, &eax, &ebx, &ecx, &edx)) { pclmul_available = (ecx & (1 << 1)) != 0; } else { pclmul_available = 0; } return pclmul_available; } static void copy_reverse_16(void * dst, const void * src) { #define COPY(i) *((uint8_t*) dst + i) = *((const uint8_t *) src + 15 - i) COPY(0); COPY(1); COPY(2); COPY(3); COPY(4); COPY(5); COPY(6); COPY(7); COPY(8); COPY(9); COPY(10); COPY(11); COPY(12); COPY(13); COPY(14); COPY(15); #undef COPY } void pclmul_mult(uint8_t res[16], const uint8_t arg1[16], const uint8_t arg2[16]) { __m128i tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8, tmp9; copy_reverse_16(&tmp0, arg1); copy_reverse_16(&tmp1, arg2); tmp3 = _mm_clmulepi64_si128(tmp0, tmp1, 0x00); tmp4 = _mm_clmulepi64_si128(tmp0, tmp1, 0x10); tmp5 = _mm_clmulepi64_si128(tmp0, tmp1, 0x01); tmp6 = _mm_clmulepi64_si128(tmp0, tmp1, 0x11); tmp4 = _mm_xor_si128(tmp4, tmp5); tmp5 = _mm_slli_si128(tmp4, 8); tmp4 = _mm_srli_si128(tmp4, 8); tmp3 = _mm_xor_si128(tmp3, tmp5); tmp6 = _mm_xor_si128(tmp6, tmp4); tmp7 = _mm_srli_epi32(tmp3, 31); tmp8 = _mm_srli_epi32(tmp6, 31); tmp3 = _mm_slli_epi32(tmp3, 1); tmp6 = _mm_slli_epi32(tmp6, 1); tmp9 = _mm_srli_si128(tmp7, 12); tmp8 = _mm_slli_si128(tmp8, 4); tmp7 = _mm_slli_si128(tmp7, 4); tmp3 = _mm_or_si128(tmp3, tmp7); tmp6 = _mm_or_si128(tmp6, tmp8); tmp6 = _mm_or_si128(tmp6, tmp9); tmp7 = _mm_slli_epi32(tmp3, 31); tmp8 = _mm_slli_epi32(tmp3, 30); tmp9 = _mm_slli_epi32(tmp3, 25); tmp7 = _mm_xor_si128(tmp7, tmp8); tmp7 = _mm_xor_si128(tmp7, tmp9); tmp8 = _mm_srli_si128(tmp7, 4); tmp7 = _mm_slli_si128(tmp7, 12); tmp3 = _mm_xor_si128(tmp3, tmp7); tmp2 = _mm_srli_epi32(tmp3, 1); tmp4 = _mm_srli_epi32(tmp3, 2); tmp5 = _mm_srli_epi32(tmp3, 7); tmp2 = _mm_xor_si128(tmp2, tmp4); tmp2 = _mm_xor_si128(tmp2, tmp5); tmp2 = _mm_xor_si128(tmp2, tmp8); tmp3 = _mm_xor_si128(tmp3, tmp2); tmp6 = _mm_xor_si128(tmp6, tmp3); tmp0 = tmp6; copy_reverse_16(res, &tmp0); } #else int pclmul_available = -1; int pclmul_check_available(void) { return 0; } void pclmul_mult(uint8_t res[16], const uint8_t arg1[16], const uint8_t arg2[16]) { abort(); } #endif cryptokit-release119/src/pclmul.h000066400000000000000000000023361453705265000172260ustar00rootroot00000000000000/***********************************************************************/ /* */ /* The Cryptokit library */ /* */ /* Xavier Leroy, Collège de France and Inria */ /* */ /* Copyright 2022 Institut National de Recherche en Informatique et */ /* en Automatique. All rights reserved. This file is distributed */ /* under the terms of the GNU Library General Public License, with */ /* the special exception on linking described in file LICENSE. */ /* */ /***********************************************************************/ /* Hardware-accelerated implementation of GHASH multiplication */ extern int pclmul_available; /* -1: unknown, call pclmul_check_available() to determine 0: not available 1: available */ extern int pclmul_check_available(void); extern void pclmul_mult(uint8_t res[16], const uint8_t arg1[16], const uint8_t arg2[16]); cryptokit-release119/src/poly1305-donna-32.h000066400000000000000000000137031453705265000205450ustar00rootroot00000000000000/* Poly1305 implementation written by Andrew Moon, https://github.com/floodyberry/poly1305-donna License: MIT or public domain. Minor adaptations for Cryptokit by Xavier Leroy. */ /* poly1305 implementation using 32 bit * 32 bit = 64 bit multiplication and 64 bit addition */ #include #define poly1305_block_size 16 /* 17 + sizeof(size_t) + 14*sizeof(uint32_t) */ typedef struct poly1305_state_internal_t { uint32_t r[5]; uint32_t h[5]; uint32_t pad[4]; size_t leftover; unsigned char buffer[poly1305_block_size]; unsigned char final; } poly1305_state_internal_t; /* interpret four 8 bit unsigned integers as a 32 bit unsigned integer in little endian */ static inline uint32_t U8TO32(const unsigned char *p) { return (((uint32_t)(p[0] & 0xff) ) | ((uint32_t)(p[1] & 0xff) << 8) | ((uint32_t)(p[2] & 0xff) << 16) | ((uint32_t)(p[3] & 0xff) << 24)); } /* store a 32 bit unsigned integer as four 8 bit unsigned integers in little endian */ static inline void U32TO8(unsigned char *p, uint32_t v) { p[0] = (v ) & 0xff; p[1] = (v >> 8) & 0xff; p[2] = (v >> 16) & 0xff; p[3] = (v >> 24) & 0xff; } void poly1305_init(poly1305_context *ctx, const unsigned char key[32]) { poly1305_state_internal_t *st = (poly1305_state_internal_t *)ctx; /* r &= 0xffffffc0ffffffc0ffffffc0fffffff */ st->r[0] = (U8TO32(&key[ 0]) ) & 0x3ffffff; st->r[1] = (U8TO32(&key[ 3]) >> 2) & 0x3ffff03; st->r[2] = (U8TO32(&key[ 6]) >> 4) & 0x3ffc0ff; st->r[3] = (U8TO32(&key[ 9]) >> 6) & 0x3f03fff; st->r[4] = (U8TO32(&key[12]) >> 8) & 0x00fffff; /* h = 0 */ st->h[0] = 0; st->h[1] = 0; st->h[2] = 0; st->h[3] = 0; st->h[4] = 0; /* save pad for later */ st->pad[0] = U8TO32(&key[16]); st->pad[1] = U8TO32(&key[20]); st->pad[2] = U8TO32(&key[24]); st->pad[3] = U8TO32(&key[28]); st->leftover = 0; st->final = 0; } static void poly1305_blocks(poly1305_state_internal_t *st, const unsigned char *m, size_t bytes) { const uint32_t hibit = (st->final) ? 0 : (1UL << 24); /* 1 << 128 */ uint32_t r0,r1,r2,r3,r4; uint32_t s1,s2,s3,s4; uint32_t h0,h1,h2,h3,h4; uint64_t d0,d1,d2,d3,d4; uint32_t c; r0 = st->r[0]; r1 = st->r[1]; r2 = st->r[2]; r3 = st->r[3]; r4 = st->r[4]; s1 = r1 * 5; s2 = r2 * 5; s3 = r3 * 5; s4 = r4 * 5; h0 = st->h[0]; h1 = st->h[1]; h2 = st->h[2]; h3 = st->h[3]; h4 = st->h[4]; while (bytes >= poly1305_block_size) { /* h += m[i] */ h0 += (U8TO32(m+ 0) ) & 0x3ffffff; h1 += (U8TO32(m+ 3) >> 2) & 0x3ffffff; h2 += (U8TO32(m+ 6) >> 4) & 0x3ffffff; h3 += (U8TO32(m+ 9) >> 6) & 0x3ffffff; h4 += (U8TO32(m+12) >> 8) | hibit; /* h *= r */ d0 = ((uint64_t)h0 * r0) + ((uint64_t)h1 * s4) + ((uint64_t)h2 * s3) + ((uint64_t)h3 * s2) + ((uint64_t)h4 * s1); d1 = ((uint64_t)h0 * r1) + ((uint64_t)h1 * r0) + ((uint64_t)h2 * s4) + ((uint64_t)h3 * s3) + ((uint64_t)h4 * s2); d2 = ((uint64_t)h0 * r2) + ((uint64_t)h1 * r1) + ((uint64_t)h2 * r0) + ((uint64_t)h3 * s4) + ((uint64_t)h4 * s3); d3 = ((uint64_t)h0 * r3) + ((uint64_t)h1 * r2) + ((uint64_t)h2 * r1) + ((uint64_t)h3 * r0) + ((uint64_t)h4 * s4); d4 = ((uint64_t)h0 * r4) + ((uint64_t)h1 * r3) + ((uint64_t)h2 * r2) + ((uint64_t)h3 * r1) + ((uint64_t)h4 * r0); /* (partial) h %= p */ c = (uint32_t)(d0 >> 26); h0 = (uint32_t)d0 & 0x3ffffff; d1 += c; c = (uint32_t)(d1 >> 26); h1 = (uint32_t)d1 & 0x3ffffff; d2 += c; c = (uint32_t)(d2 >> 26); h2 = (uint32_t)d2 & 0x3ffffff; d3 += c; c = (uint32_t)(d3 >> 26); h3 = (uint32_t)d3 & 0x3ffffff; d4 += c; c = (uint32_t)(d4 >> 26); h4 = (uint32_t)d4 & 0x3ffffff; h0 += c * 5; c = (h0 >> 26); h0 = h0 & 0x3ffffff; h1 += c; m += poly1305_block_size; bytes -= poly1305_block_size; } st->h[0] = h0; st->h[1] = h1; st->h[2] = h2; st->h[3] = h3; st->h[4] = h4; } void poly1305_finish(poly1305_context *ctx, unsigned char mac[16]) { poly1305_state_internal_t *st = (poly1305_state_internal_t *)ctx; uint32_t h0,h1,h2,h3,h4,c; uint32_t g0,g1,g2,g3,g4; uint64_t f; uint32_t mask; /* process the remaining block */ if (st->leftover) { size_t i = st->leftover; st->buffer[i++] = 1; for (; i < poly1305_block_size; i++) st->buffer[i] = 0; st->final = 1; poly1305_blocks(st, st->buffer, poly1305_block_size); } /* fully carry h */ h0 = st->h[0]; h1 = st->h[1]; h2 = st->h[2]; h3 = st->h[3]; h4 = st->h[4]; c = h1 >> 26; h1 = h1 & 0x3ffffff; h2 += c; c = h2 >> 26; h2 = h2 & 0x3ffffff; h3 += c; c = h3 >> 26; h3 = h3 & 0x3ffffff; h4 += c; c = h4 >> 26; h4 = h4 & 0x3ffffff; h0 += c * 5; c = h0 >> 26; h0 = h0 & 0x3ffffff; h1 += c; /* compute h + -p */ g0 = h0 + 5; c = g0 >> 26; g0 &= 0x3ffffff; g1 = h1 + c; c = g1 >> 26; g1 &= 0x3ffffff; g2 = h2 + c; c = g2 >> 26; g2 &= 0x3ffffff; g3 = h3 + c; c = g3 >> 26; g3 &= 0x3ffffff; g4 = h4 + c - (1UL << 26); /* select h if h < p, or h + -p if h >= p */ mask = (g4 >> ((sizeof(uint32_t) * 8) - 1)) - 1; g0 &= mask; g1 &= mask; g2 &= mask; g3 &= mask; g4 &= mask; mask = ~mask; h0 = (h0 & mask) | g0; h1 = (h1 & mask) | g1; h2 = (h2 & mask) | g2; h3 = (h3 & mask) | g3; h4 = (h4 & mask) | g4; /* h = h % (2^128) */ h0 = ((h0 ) | (h1 << 26)) & 0xffffffff; h1 = ((h1 >> 6) | (h2 << 20)) & 0xffffffff; h2 = ((h2 >> 12) | (h3 << 14)) & 0xffffffff; h3 = ((h3 >> 18) | (h4 << 8)) & 0xffffffff; /* mac = (h + pad) % (2^128) */ f = (uint64_t)h0 + st->pad[0] ; h0 = (uint32_t)f; f = (uint64_t)h1 + st->pad[1] + (f >> 32); h1 = (uint32_t)f; f = (uint64_t)h2 + st->pad[2] + (f >> 32); h2 = (uint32_t)f; f = (uint64_t)h3 + st->pad[3] + (f >> 32); h3 = (uint32_t)f; U32TO8(mac + 0, h0); U32TO8(mac + 4, h1); U32TO8(mac + 8, h2); U32TO8(mac + 12, h3); /* zero out the state */ st->h[0] = 0; st->h[1] = 0; st->h[2] = 0; st->h[3] = 0; st->h[4] = 0; st->r[0] = 0; st->r[1] = 0; st->r[2] = 0; st->r[3] = 0; st->r[4] = 0; st->pad[0] = 0; st->pad[1] = 0; st->pad[2] = 0; st->pad[3] = 0; } cryptokit-release119/src/poly1305-donna-64.h000066400000000000000000000126001453705265000205450ustar00rootroot00000000000000/* Poly1305 implementation written by Andrew Moon, https://github.com/floodyberry/poly1305-donna License: MIT or public domain. Minor adaptations for Cryptokit by Xavier Leroy. */ /* poly1305 implementation using 64 bit * 64 bit = 128 bit multiplication and 128 bit addition */ #include #if defined(__GNUC__) typedef unsigned __int128 uint128; #define MUL(out, x, y) out = ((uint128)x * y) #define ADD(out, in) out += in #define ADDLO(out, in) out += in #define SHR(in, shift) (uint64_t)(in >> (shift)) #define LO(in) (uint64_t)(in) #define POLY1305_NOINLINE __attribute__((noinline)) #endif #define poly1305_block_size 16 /* 17 + sizeof(size_t) + 8*sizeof(uint64_t) */ typedef struct poly1305_state_internal_t { uint64_t r[3]; uint64_t h[3]; uint64_t pad[2]; size_t leftover; unsigned char buffer[poly1305_block_size]; unsigned char final; } poly1305_state_internal_t; /* interpret eight 8 bit unsigned integers as a 64 bit unsigned integer in little endian */ static inline uint64_t U8TO64(const unsigned char *p) { return (((uint64_t)(p[0] & 0xff) ) | ((uint64_t)(p[1] & 0xff) << 8) | ((uint64_t)(p[2] & 0xff) << 16) | ((uint64_t)(p[3] & 0xff) << 24) | ((uint64_t)(p[4] & 0xff) << 32) | ((uint64_t)(p[5] & 0xff) << 40) | ((uint64_t)(p[6] & 0xff) << 48) | ((uint64_t)(p[7] & 0xff) << 56)); } /* store a 64 bit unsigned integer as eight 8 bit unsigned integers in little endian */ static inline void U64TO8(unsigned char *p, uint64_t v) { p[0] = (v ) & 0xff; p[1] = (v >> 8) & 0xff; p[2] = (v >> 16) & 0xff; p[3] = (v >> 24) & 0xff; p[4] = (v >> 32) & 0xff; p[5] = (v >> 40) & 0xff; p[6] = (v >> 48) & 0xff; p[7] = (v >> 56) & 0xff; } void poly1305_init(poly1305_context *ctx, const unsigned char key[32]) { poly1305_state_internal_t *st = (poly1305_state_internal_t *)ctx; uint64_t t0,t1; /* r &= 0xffffffc0ffffffc0ffffffc0fffffff */ t0 = U8TO64(&key[0]); t1 = U8TO64(&key[8]); st->r[0] = ( t0 ) & 0xffc0fffffff; st->r[1] = ((t0 >> 44) | (t1 << 20)) & 0xfffffc0ffff; st->r[2] = ((t1 >> 24) ) & 0x00ffffffc0f; /* h = 0 */ st->h[0] = 0; st->h[1] = 0; st->h[2] = 0; /* save pad for later */ st->pad[0] = U8TO64(&key[16]); st->pad[1] = U8TO64(&key[24]); st->leftover = 0; st->final = 0; } static void poly1305_blocks(poly1305_state_internal_t *st, const unsigned char *m, size_t bytes) { const uint64_t hibit = (st->final) ? 0 : ((uint64_t)1 << 40); /* 1 << 128 */ uint64_t r0,r1,r2; uint64_t s1,s2; uint64_t h0,h1,h2; uint64_t c; uint128 d0,d1,d2,d; r0 = st->r[0]; r1 = st->r[1]; r2 = st->r[2]; h0 = st->h[0]; h1 = st->h[1]; h2 = st->h[2]; s1 = r1 * (5 << 2); s2 = r2 * (5 << 2); while (bytes >= poly1305_block_size) { uint64_t t0,t1; /* h += m[i] */ t0 = U8TO64(&m[0]); t1 = U8TO64(&m[8]); h0 += (( t0 ) & 0xfffffffffff); h1 += (((t0 >> 44) | (t1 << 20)) & 0xfffffffffff); h2 += (((t1 >> 24) ) & 0x3ffffffffff) | hibit; /* h *= r */ MUL(d0, h0, r0); MUL(d, h1, s2); ADD(d0, d); MUL(d, h2, s1); ADD(d0, d); MUL(d1, h0, r1); MUL(d, h1, r0); ADD(d1, d); MUL(d, h2, s2); ADD(d1, d); MUL(d2, h0, r2); MUL(d, h1, r1); ADD(d2, d); MUL(d, h2, r0); ADD(d2, d); /* (partial) h %= p */ c = SHR(d0, 44); h0 = LO(d0) & 0xfffffffffff; ADDLO(d1, c); c = SHR(d1, 44); h1 = LO(d1) & 0xfffffffffff; ADDLO(d2, c); c = SHR(d2, 42); h2 = LO(d2) & 0x3ffffffffff; h0 += c * 5; c = (h0 >> 44); h0 = h0 & 0xfffffffffff; h1 += c; m += poly1305_block_size; bytes -= poly1305_block_size; } st->h[0] = h0; st->h[1] = h1; st->h[2] = h2; } void poly1305_finish(poly1305_context *ctx, unsigned char mac[16]) { poly1305_state_internal_t *st = (poly1305_state_internal_t *)ctx; uint64_t h0,h1,h2,c; uint64_t g0,g1,g2; uint64_t t0,t1; /* process the remaining block */ if (st->leftover) { size_t i = st->leftover; st->buffer[i] = 1; for (i = i + 1; i < poly1305_block_size; i++) st->buffer[i] = 0; st->final = 1; poly1305_blocks(st, st->buffer, poly1305_block_size); } /* fully carry h */ h0 = st->h[0]; h1 = st->h[1]; h2 = st->h[2]; c = (h1 >> 44); h1 &= 0xfffffffffff; h2 += c; c = (h2 >> 42); h2 &= 0x3ffffffffff; h0 += c * 5; c = (h0 >> 44); h0 &= 0xfffffffffff; h1 += c; c = (h1 >> 44); h1 &= 0xfffffffffff; h2 += c; c = (h2 >> 42); h2 &= 0x3ffffffffff; h0 += c * 5; c = (h0 >> 44); h0 &= 0xfffffffffff; h1 += c; /* compute h + -p */ g0 = h0 + 5; c = (g0 >> 44); g0 &= 0xfffffffffff; g1 = h1 + c; c = (g1 >> 44); g1 &= 0xfffffffffff; g2 = h2 + c - ((uint64_t)1 << 42); /* select h if h < p, or h + -p if h >= p */ c = (g2 >> ((sizeof(uint64_t) * 8) - 1)) - 1; g0 &= c; g1 &= c; g2 &= c; c = ~c; h0 = (h0 & c) | g0; h1 = (h1 & c) | g1; h2 = (h2 & c) | g2; /* h = (h + pad) */ t0 = st->pad[0]; t1 = st->pad[1]; h0 += (( t0 ) & 0xfffffffffff) ; c = (h0 >> 44); h0 &= 0xfffffffffff; h1 += (((t0 >> 44) | (t1 << 20)) & 0xfffffffffff) + c; c = (h1 >> 44); h1 &= 0xfffffffffff; h2 += (((t1 >> 24) ) & 0x3ffffffffff) + c; h2 &= 0x3ffffffffff; /* mac = h % (2^128) */ h0 = ((h0 ) | (h1 << 44)); h1 = ((h1 >> 20) | (h2 << 24)); U64TO8(&mac[0], h0); U64TO8(&mac[8], h1); /* zero out the state */ st->h[0] = 0; st->h[1] = 0; st->h[2] = 0; st->r[0] = 0; st->r[1] = 0; st->r[2] = 0; st->pad[0] = 0; st->pad[1] = 0; } cryptokit-release119/src/poly1305-donna.c000066400000000000000000000023641453705265000203170ustar00rootroot00000000000000/* Poly1305 implementation written by Andrew Moon, https://github.com/floodyberry/poly1305-donna License: MIT or public domain. Minor adaptations for Cryptokit by Xavier Leroy. */ #include "poly1305-donna.h" /* auto detect between 32bit / 64bit */ #if defined(__SIZEOF_INT128__) && defined(__LP64__) #include "poly1305-donna-64.h" #else #include "poly1305-donna-32.h" #endif void poly1305_update(poly1305_context *ctx, const unsigned char *m, size_t bytes) { poly1305_state_internal_t *st = (poly1305_state_internal_t *)ctx; size_t i; /* handle leftover */ if (st->leftover) { size_t want = (poly1305_block_size - st->leftover); if (want > bytes) want = bytes; for (i = 0; i < want; i++) st->buffer[st->leftover + i] = m[i]; bytes -= want; m += want; st->leftover += want; if (st->leftover < poly1305_block_size) return; poly1305_blocks(st, st->buffer, poly1305_block_size); st->leftover = 0; } /* process full blocks */ if (bytes >= poly1305_block_size) { size_t want = (bytes & ~(poly1305_block_size - 1)); poly1305_blocks(st, m, want); m += want; bytes -= want; } /* store leftover */ if (bytes) { for (i = 0; i < bytes; i++) st->buffer[st->leftover + i] = m[i]; st->leftover += bytes; } } cryptokit-release119/src/poly1305-donna.h000066400000000000000000000011601453705265000203150ustar00rootroot00000000000000/* Poly1305 implementation written by Andrew Moon, https://github.com/floodyberry/poly1305-donna License: MIT or public domain. Minor adaptations for Cryptokit by Xavier Leroy. */ #ifndef POLY1305_DONNA_H #define POLY1305_DONNA_H #include typedef struct poly1305_context { size_t aligner; unsigned char opaque[136]; } poly1305_context; void poly1305_init(poly1305_context *ctx, const unsigned char key[32]); void poly1305_update(poly1305_context *ctx, const unsigned char *m, size_t bytes); void poly1305_finish(poly1305_context *ctx, unsigned char mac[16]); #endif /* POLY1305_DONNA_H */ cryptokit-release119/src/rijndael-alg-fst.c000066400000000000000000001742641453705265000210620ustar00rootroot00000000000000/** * rijndael-alg-fst.c * * @version 3.0 (December 2000) * * Optimised ANSI C code for the Rijndael cipher (now AES) * * @author Vincent Rijmen * @author Antoon Bosselaers * @author Paulo Barreto * * This code is hereby placed in the public domain. * * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''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 AUTHORS OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include "rijndael-alg-fst.h" /* Te0[x] = S [x].[02, 01, 01, 03]; Te1[x] = S [x].[03, 02, 01, 01]; Te2[x] = S [x].[01, 03, 02, 01]; Te3[x] = S [x].[01, 01, 03, 02]; Te4[x] = S [x].[01, 01, 01, 01]; Td0[x] = Si[x].[0e, 09, 0d, 0b]; Td1[x] = Si[x].[0b, 0e, 09, 0d]; Td2[x] = Si[x].[0d, 0b, 0e, 09]; Td3[x] = Si[x].[09, 0d, 0b, 0e]; Td4[x] = Si[x].[01, 01, 01, 01]; */ static const u32 Te0[256] = { 0xc66363a5U, 0xf87c7c84U, 0xee777799U, 0xf67b7b8dU, 0xfff2f20dU, 0xd66b6bbdU, 0xde6f6fb1U, 0x91c5c554U, 0x60303050U, 0x02010103U, 0xce6767a9U, 0x562b2b7dU, 0xe7fefe19U, 0xb5d7d762U, 0x4dababe6U, 0xec76769aU, 0x8fcaca45U, 0x1f82829dU, 0x89c9c940U, 0xfa7d7d87U, 0xeffafa15U, 0xb25959ebU, 0x8e4747c9U, 0xfbf0f00bU, 0x41adadecU, 0xb3d4d467U, 0x5fa2a2fdU, 0x45afafeaU, 0x239c9cbfU, 0x53a4a4f7U, 0xe4727296U, 0x9bc0c05bU, 0x75b7b7c2U, 0xe1fdfd1cU, 0x3d9393aeU, 0x4c26266aU, 0x6c36365aU, 0x7e3f3f41U, 0xf5f7f702U, 0x83cccc4fU, 0x6834345cU, 0x51a5a5f4U, 0xd1e5e534U, 0xf9f1f108U, 0xe2717193U, 0xabd8d873U, 0x62313153U, 0x2a15153fU, 0x0804040cU, 0x95c7c752U, 0x46232365U, 0x9dc3c35eU, 0x30181828U, 0x379696a1U, 0x0a05050fU, 0x2f9a9ab5U, 0x0e070709U, 0x24121236U, 0x1b80809bU, 0xdfe2e23dU, 0xcdebeb26U, 0x4e272769U, 0x7fb2b2cdU, 0xea75759fU, 0x1209091bU, 0x1d83839eU, 0x582c2c74U, 0x341a1a2eU, 0x361b1b2dU, 0xdc6e6eb2U, 0xb45a5aeeU, 0x5ba0a0fbU, 0xa45252f6U, 0x763b3b4dU, 0xb7d6d661U, 0x7db3b3ceU, 0x5229297bU, 0xdde3e33eU, 0x5e2f2f71U, 0x13848497U, 0xa65353f5U, 0xb9d1d168U, 0x00000000U, 0xc1eded2cU, 0x40202060U, 0xe3fcfc1fU, 0x79b1b1c8U, 0xb65b5bedU, 0xd46a6abeU, 0x8dcbcb46U, 0x67bebed9U, 0x7239394bU, 0x944a4adeU, 0x984c4cd4U, 0xb05858e8U, 0x85cfcf4aU, 0xbbd0d06bU, 0xc5efef2aU, 0x4faaaae5U, 0xedfbfb16U, 0x864343c5U, 0x9a4d4dd7U, 0x66333355U, 0x11858594U, 0x8a4545cfU, 0xe9f9f910U, 0x04020206U, 0xfe7f7f81U, 0xa05050f0U, 0x783c3c44U, 0x259f9fbaU, 0x4ba8a8e3U, 0xa25151f3U, 0x5da3a3feU, 0x804040c0U, 0x058f8f8aU, 0x3f9292adU, 0x219d9dbcU, 0x70383848U, 0xf1f5f504U, 0x63bcbcdfU, 0x77b6b6c1U, 0xafdada75U, 0x42212163U, 0x20101030U, 0xe5ffff1aU, 0xfdf3f30eU, 0xbfd2d26dU, 0x81cdcd4cU, 0x180c0c14U, 0x26131335U, 0xc3ecec2fU, 0xbe5f5fe1U, 0x359797a2U, 0x884444ccU, 0x2e171739U, 0x93c4c457U, 0x55a7a7f2U, 0xfc7e7e82U, 0x7a3d3d47U, 0xc86464acU, 0xba5d5de7U, 0x3219192bU, 0xe6737395U, 0xc06060a0U, 0x19818198U, 0x9e4f4fd1U, 0xa3dcdc7fU, 0x44222266U, 0x542a2a7eU, 0x3b9090abU, 0x0b888883U, 0x8c4646caU, 0xc7eeee29U, 0x6bb8b8d3U, 0x2814143cU, 0xa7dede79U, 0xbc5e5ee2U, 0x160b0b1dU, 0xaddbdb76U, 0xdbe0e03bU, 0x64323256U, 0x743a3a4eU, 0x140a0a1eU, 0x924949dbU, 0x0c06060aU, 0x4824246cU, 0xb85c5ce4U, 0x9fc2c25dU, 0xbdd3d36eU, 0x43acacefU, 0xc46262a6U, 0x399191a8U, 0x319595a4U, 0xd3e4e437U, 0xf279798bU, 0xd5e7e732U, 0x8bc8c843U, 0x6e373759U, 0xda6d6db7U, 0x018d8d8cU, 0xb1d5d564U, 0x9c4e4ed2U, 0x49a9a9e0U, 0xd86c6cb4U, 0xac5656faU, 0xf3f4f407U, 0xcfeaea25U, 0xca6565afU, 0xf47a7a8eU, 0x47aeaee9U, 0x10080818U, 0x6fbabad5U, 0xf0787888U, 0x4a25256fU, 0x5c2e2e72U, 0x381c1c24U, 0x57a6a6f1U, 0x73b4b4c7U, 0x97c6c651U, 0xcbe8e823U, 0xa1dddd7cU, 0xe874749cU, 0x3e1f1f21U, 0x964b4bddU, 0x61bdbddcU, 0x0d8b8b86U, 0x0f8a8a85U, 0xe0707090U, 0x7c3e3e42U, 0x71b5b5c4U, 0xcc6666aaU, 0x904848d8U, 0x06030305U, 0xf7f6f601U, 0x1c0e0e12U, 0xc26161a3U, 0x6a35355fU, 0xae5757f9U, 0x69b9b9d0U, 0x17868691U, 0x99c1c158U, 0x3a1d1d27U, 0x279e9eb9U, 0xd9e1e138U, 0xebf8f813U, 0x2b9898b3U, 0x22111133U, 0xd26969bbU, 0xa9d9d970U, 0x078e8e89U, 0x339494a7U, 0x2d9b9bb6U, 0x3c1e1e22U, 0x15878792U, 0xc9e9e920U, 0x87cece49U, 0xaa5555ffU, 0x50282878U, 0xa5dfdf7aU, 0x038c8c8fU, 0x59a1a1f8U, 0x09898980U, 0x1a0d0d17U, 0x65bfbfdaU, 0xd7e6e631U, 0x844242c6U, 0xd06868b8U, 0x824141c3U, 0x299999b0U, 0x5a2d2d77U, 0x1e0f0f11U, 0x7bb0b0cbU, 0xa85454fcU, 0x6dbbbbd6U, 0x2c16163aU, }; static const u32 Te1[256] = { 0xa5c66363U, 0x84f87c7cU, 0x99ee7777U, 0x8df67b7bU, 0x0dfff2f2U, 0xbdd66b6bU, 0xb1de6f6fU, 0x5491c5c5U, 0x50603030U, 0x03020101U, 0xa9ce6767U, 0x7d562b2bU, 0x19e7fefeU, 0x62b5d7d7U, 0xe64dababU, 0x9aec7676U, 0x458fcacaU, 0x9d1f8282U, 0x4089c9c9U, 0x87fa7d7dU, 0x15effafaU, 0xebb25959U, 0xc98e4747U, 0x0bfbf0f0U, 0xec41adadU, 0x67b3d4d4U, 0xfd5fa2a2U, 0xea45afafU, 0xbf239c9cU, 0xf753a4a4U, 0x96e47272U, 0x5b9bc0c0U, 0xc275b7b7U, 0x1ce1fdfdU, 0xae3d9393U, 0x6a4c2626U, 0x5a6c3636U, 0x417e3f3fU, 0x02f5f7f7U, 0x4f83ccccU, 0x5c683434U, 0xf451a5a5U, 0x34d1e5e5U, 0x08f9f1f1U, 0x93e27171U, 0x73abd8d8U, 0x53623131U, 0x3f2a1515U, 0x0c080404U, 0x5295c7c7U, 0x65462323U, 0x5e9dc3c3U, 0x28301818U, 0xa1379696U, 0x0f0a0505U, 0xb52f9a9aU, 0x090e0707U, 0x36241212U, 0x9b1b8080U, 0x3ddfe2e2U, 0x26cdebebU, 0x694e2727U, 0xcd7fb2b2U, 0x9fea7575U, 0x1b120909U, 0x9e1d8383U, 0x74582c2cU, 0x2e341a1aU, 0x2d361b1bU, 0xb2dc6e6eU, 0xeeb45a5aU, 0xfb5ba0a0U, 0xf6a45252U, 0x4d763b3bU, 0x61b7d6d6U, 0xce7db3b3U, 0x7b522929U, 0x3edde3e3U, 0x715e2f2fU, 0x97138484U, 0xf5a65353U, 0x68b9d1d1U, 0x00000000U, 0x2cc1ededU, 0x60402020U, 0x1fe3fcfcU, 0xc879b1b1U, 0xedb65b5bU, 0xbed46a6aU, 0x468dcbcbU, 0xd967bebeU, 0x4b723939U, 0xde944a4aU, 0xd4984c4cU, 0xe8b05858U, 0x4a85cfcfU, 0x6bbbd0d0U, 0x2ac5efefU, 0xe54faaaaU, 0x16edfbfbU, 0xc5864343U, 0xd79a4d4dU, 0x55663333U, 0x94118585U, 0xcf8a4545U, 0x10e9f9f9U, 0x06040202U, 0x81fe7f7fU, 0xf0a05050U, 0x44783c3cU, 0xba259f9fU, 0xe34ba8a8U, 0xf3a25151U, 0xfe5da3a3U, 0xc0804040U, 0x8a058f8fU, 0xad3f9292U, 0xbc219d9dU, 0x48703838U, 0x04f1f5f5U, 0xdf63bcbcU, 0xc177b6b6U, 0x75afdadaU, 0x63422121U, 0x30201010U, 0x1ae5ffffU, 0x0efdf3f3U, 0x6dbfd2d2U, 0x4c81cdcdU, 0x14180c0cU, 0x35261313U, 0x2fc3ececU, 0xe1be5f5fU, 0xa2359797U, 0xcc884444U, 0x392e1717U, 0x5793c4c4U, 0xf255a7a7U, 0x82fc7e7eU, 0x477a3d3dU, 0xacc86464U, 0xe7ba5d5dU, 0x2b321919U, 0x95e67373U, 0xa0c06060U, 0x98198181U, 0xd19e4f4fU, 0x7fa3dcdcU, 0x66442222U, 0x7e542a2aU, 0xab3b9090U, 0x830b8888U, 0xca8c4646U, 0x29c7eeeeU, 0xd36bb8b8U, 0x3c281414U, 0x79a7dedeU, 0xe2bc5e5eU, 0x1d160b0bU, 0x76addbdbU, 0x3bdbe0e0U, 0x56643232U, 0x4e743a3aU, 0x1e140a0aU, 0xdb924949U, 0x0a0c0606U, 0x6c482424U, 0xe4b85c5cU, 0x5d9fc2c2U, 0x6ebdd3d3U, 0xef43acacU, 0xa6c46262U, 0xa8399191U, 0xa4319595U, 0x37d3e4e4U, 0x8bf27979U, 0x32d5e7e7U, 0x438bc8c8U, 0x596e3737U, 0xb7da6d6dU, 0x8c018d8dU, 0x64b1d5d5U, 0xd29c4e4eU, 0xe049a9a9U, 0xb4d86c6cU, 0xfaac5656U, 0x07f3f4f4U, 0x25cfeaeaU, 0xafca6565U, 0x8ef47a7aU, 0xe947aeaeU, 0x18100808U, 0xd56fbabaU, 0x88f07878U, 0x6f4a2525U, 0x725c2e2eU, 0x24381c1cU, 0xf157a6a6U, 0xc773b4b4U, 0x5197c6c6U, 0x23cbe8e8U, 0x7ca1ddddU, 0x9ce87474U, 0x213e1f1fU, 0xdd964b4bU, 0xdc61bdbdU, 0x860d8b8bU, 0x850f8a8aU, 0x90e07070U, 0x427c3e3eU, 0xc471b5b5U, 0xaacc6666U, 0xd8904848U, 0x05060303U, 0x01f7f6f6U, 0x121c0e0eU, 0xa3c26161U, 0x5f6a3535U, 0xf9ae5757U, 0xd069b9b9U, 0x91178686U, 0x5899c1c1U, 0x273a1d1dU, 0xb9279e9eU, 0x38d9e1e1U, 0x13ebf8f8U, 0xb32b9898U, 0x33221111U, 0xbbd26969U, 0x70a9d9d9U, 0x89078e8eU, 0xa7339494U, 0xb62d9b9bU, 0x223c1e1eU, 0x92158787U, 0x20c9e9e9U, 0x4987ceceU, 0xffaa5555U, 0x78502828U, 0x7aa5dfdfU, 0x8f038c8cU, 0xf859a1a1U, 0x80098989U, 0x171a0d0dU, 0xda65bfbfU, 0x31d7e6e6U, 0xc6844242U, 0xb8d06868U, 0xc3824141U, 0xb0299999U, 0x775a2d2dU, 0x111e0f0fU, 0xcb7bb0b0U, 0xfca85454U, 0xd66dbbbbU, 0x3a2c1616U, }; static const u32 Te2[256] = { 0x63a5c663U, 0x7c84f87cU, 0x7799ee77U, 0x7b8df67bU, 0xf20dfff2U, 0x6bbdd66bU, 0x6fb1de6fU, 0xc55491c5U, 0x30506030U, 0x01030201U, 0x67a9ce67U, 0x2b7d562bU, 0xfe19e7feU, 0xd762b5d7U, 0xabe64dabU, 0x769aec76U, 0xca458fcaU, 0x829d1f82U, 0xc94089c9U, 0x7d87fa7dU, 0xfa15effaU, 0x59ebb259U, 0x47c98e47U, 0xf00bfbf0U, 0xadec41adU, 0xd467b3d4U, 0xa2fd5fa2U, 0xafea45afU, 0x9cbf239cU, 0xa4f753a4U, 0x7296e472U, 0xc05b9bc0U, 0xb7c275b7U, 0xfd1ce1fdU, 0x93ae3d93U, 0x266a4c26U, 0x365a6c36U, 0x3f417e3fU, 0xf702f5f7U, 0xcc4f83ccU, 0x345c6834U, 0xa5f451a5U, 0xe534d1e5U, 0xf108f9f1U, 0x7193e271U, 0xd873abd8U, 0x31536231U, 0x153f2a15U, 0x040c0804U, 0xc75295c7U, 0x23654623U, 0xc35e9dc3U, 0x18283018U, 0x96a13796U, 0x050f0a05U, 0x9ab52f9aU, 0x07090e07U, 0x12362412U, 0x809b1b80U, 0xe23ddfe2U, 0xeb26cdebU, 0x27694e27U, 0xb2cd7fb2U, 0x759fea75U, 0x091b1209U, 0x839e1d83U, 0x2c74582cU, 0x1a2e341aU, 0x1b2d361bU, 0x6eb2dc6eU, 0x5aeeb45aU, 0xa0fb5ba0U, 0x52f6a452U, 0x3b4d763bU, 0xd661b7d6U, 0xb3ce7db3U, 0x297b5229U, 0xe33edde3U, 0x2f715e2fU, 0x84971384U, 0x53f5a653U, 0xd168b9d1U, 0x00000000U, 0xed2cc1edU, 0x20604020U, 0xfc1fe3fcU, 0xb1c879b1U, 0x5bedb65bU, 0x6abed46aU, 0xcb468dcbU, 0xbed967beU, 0x394b7239U, 0x4ade944aU, 0x4cd4984cU, 0x58e8b058U, 0xcf4a85cfU, 0xd06bbbd0U, 0xef2ac5efU, 0xaae54faaU, 0xfb16edfbU, 0x43c58643U, 0x4dd79a4dU, 0x33556633U, 0x85941185U, 0x45cf8a45U, 0xf910e9f9U, 0x02060402U, 0x7f81fe7fU, 0x50f0a050U, 0x3c44783cU, 0x9fba259fU, 0xa8e34ba8U, 0x51f3a251U, 0xa3fe5da3U, 0x40c08040U, 0x8f8a058fU, 0x92ad3f92U, 0x9dbc219dU, 0x38487038U, 0xf504f1f5U, 0xbcdf63bcU, 0xb6c177b6U, 0xda75afdaU, 0x21634221U, 0x10302010U, 0xff1ae5ffU, 0xf30efdf3U, 0xd26dbfd2U, 0xcd4c81cdU, 0x0c14180cU, 0x13352613U, 0xec2fc3ecU, 0x5fe1be5fU, 0x97a23597U, 0x44cc8844U, 0x17392e17U, 0xc45793c4U, 0xa7f255a7U, 0x7e82fc7eU, 0x3d477a3dU, 0x64acc864U, 0x5de7ba5dU, 0x192b3219U, 0x7395e673U, 0x60a0c060U, 0x81981981U, 0x4fd19e4fU, 0xdc7fa3dcU, 0x22664422U, 0x2a7e542aU, 0x90ab3b90U, 0x88830b88U, 0x46ca8c46U, 0xee29c7eeU, 0xb8d36bb8U, 0x143c2814U, 0xde79a7deU, 0x5ee2bc5eU, 0x0b1d160bU, 0xdb76addbU, 0xe03bdbe0U, 0x32566432U, 0x3a4e743aU, 0x0a1e140aU, 0x49db9249U, 0x060a0c06U, 0x246c4824U, 0x5ce4b85cU, 0xc25d9fc2U, 0xd36ebdd3U, 0xacef43acU, 0x62a6c462U, 0x91a83991U, 0x95a43195U, 0xe437d3e4U, 0x798bf279U, 0xe732d5e7U, 0xc8438bc8U, 0x37596e37U, 0x6db7da6dU, 0x8d8c018dU, 0xd564b1d5U, 0x4ed29c4eU, 0xa9e049a9U, 0x6cb4d86cU, 0x56faac56U, 0xf407f3f4U, 0xea25cfeaU, 0x65afca65U, 0x7a8ef47aU, 0xaee947aeU, 0x08181008U, 0xbad56fbaU, 0x7888f078U, 0x256f4a25U, 0x2e725c2eU, 0x1c24381cU, 0xa6f157a6U, 0xb4c773b4U, 0xc65197c6U, 0xe823cbe8U, 0xdd7ca1ddU, 0x749ce874U, 0x1f213e1fU, 0x4bdd964bU, 0xbddc61bdU, 0x8b860d8bU, 0x8a850f8aU, 0x7090e070U, 0x3e427c3eU, 0xb5c471b5U, 0x66aacc66U, 0x48d89048U, 0x03050603U, 0xf601f7f6U, 0x0e121c0eU, 0x61a3c261U, 0x355f6a35U, 0x57f9ae57U, 0xb9d069b9U, 0x86911786U, 0xc15899c1U, 0x1d273a1dU, 0x9eb9279eU, 0xe138d9e1U, 0xf813ebf8U, 0x98b32b98U, 0x11332211U, 0x69bbd269U, 0xd970a9d9U, 0x8e89078eU, 0x94a73394U, 0x9bb62d9bU, 0x1e223c1eU, 0x87921587U, 0xe920c9e9U, 0xce4987ceU, 0x55ffaa55U, 0x28785028U, 0xdf7aa5dfU, 0x8c8f038cU, 0xa1f859a1U, 0x89800989U, 0x0d171a0dU, 0xbfda65bfU, 0xe631d7e6U, 0x42c68442U, 0x68b8d068U, 0x41c38241U, 0x99b02999U, 0x2d775a2dU, 0x0f111e0fU, 0xb0cb7bb0U, 0x54fca854U, 0xbbd66dbbU, 0x163a2c16U, }; static const u32 Te3[256] = { 0x6363a5c6U, 0x7c7c84f8U, 0x777799eeU, 0x7b7b8df6U, 0xf2f20dffU, 0x6b6bbdd6U, 0x6f6fb1deU, 0xc5c55491U, 0x30305060U, 0x01010302U, 0x6767a9ceU, 0x2b2b7d56U, 0xfefe19e7U, 0xd7d762b5U, 0xababe64dU, 0x76769aecU, 0xcaca458fU, 0x82829d1fU, 0xc9c94089U, 0x7d7d87faU, 0xfafa15efU, 0x5959ebb2U, 0x4747c98eU, 0xf0f00bfbU, 0xadadec41U, 0xd4d467b3U, 0xa2a2fd5fU, 0xafafea45U, 0x9c9cbf23U, 0xa4a4f753U, 0x727296e4U, 0xc0c05b9bU, 0xb7b7c275U, 0xfdfd1ce1U, 0x9393ae3dU, 0x26266a4cU, 0x36365a6cU, 0x3f3f417eU, 0xf7f702f5U, 0xcccc4f83U, 0x34345c68U, 0xa5a5f451U, 0xe5e534d1U, 0xf1f108f9U, 0x717193e2U, 0xd8d873abU, 0x31315362U, 0x15153f2aU, 0x04040c08U, 0xc7c75295U, 0x23236546U, 0xc3c35e9dU, 0x18182830U, 0x9696a137U, 0x05050f0aU, 0x9a9ab52fU, 0x0707090eU, 0x12123624U, 0x80809b1bU, 0xe2e23ddfU, 0xebeb26cdU, 0x2727694eU, 0xb2b2cd7fU, 0x75759feaU, 0x09091b12U, 0x83839e1dU, 0x2c2c7458U, 0x1a1a2e34U, 0x1b1b2d36U, 0x6e6eb2dcU, 0x5a5aeeb4U, 0xa0a0fb5bU, 0x5252f6a4U, 0x3b3b4d76U, 0xd6d661b7U, 0xb3b3ce7dU, 0x29297b52U, 0xe3e33eddU, 0x2f2f715eU, 0x84849713U, 0x5353f5a6U, 0xd1d168b9U, 0x00000000U, 0xeded2cc1U, 0x20206040U, 0xfcfc1fe3U, 0xb1b1c879U, 0x5b5bedb6U, 0x6a6abed4U, 0xcbcb468dU, 0xbebed967U, 0x39394b72U, 0x4a4ade94U, 0x4c4cd498U, 0x5858e8b0U, 0xcfcf4a85U, 0xd0d06bbbU, 0xefef2ac5U, 0xaaaae54fU, 0xfbfb16edU, 0x4343c586U, 0x4d4dd79aU, 0x33335566U, 0x85859411U, 0x4545cf8aU, 0xf9f910e9U, 0x02020604U, 0x7f7f81feU, 0x5050f0a0U, 0x3c3c4478U, 0x9f9fba25U, 0xa8a8e34bU, 0x5151f3a2U, 0xa3a3fe5dU, 0x4040c080U, 0x8f8f8a05U, 0x9292ad3fU, 0x9d9dbc21U, 0x38384870U, 0xf5f504f1U, 0xbcbcdf63U, 0xb6b6c177U, 0xdada75afU, 0x21216342U, 0x10103020U, 0xffff1ae5U, 0xf3f30efdU, 0xd2d26dbfU, 0xcdcd4c81U, 0x0c0c1418U, 0x13133526U, 0xecec2fc3U, 0x5f5fe1beU, 0x9797a235U, 0x4444cc88U, 0x1717392eU, 0xc4c45793U, 0xa7a7f255U, 0x7e7e82fcU, 0x3d3d477aU, 0x6464acc8U, 0x5d5de7baU, 0x19192b32U, 0x737395e6U, 0x6060a0c0U, 0x81819819U, 0x4f4fd19eU, 0xdcdc7fa3U, 0x22226644U, 0x2a2a7e54U, 0x9090ab3bU, 0x8888830bU, 0x4646ca8cU, 0xeeee29c7U, 0xb8b8d36bU, 0x14143c28U, 0xdede79a7U, 0x5e5ee2bcU, 0x0b0b1d16U, 0xdbdb76adU, 0xe0e03bdbU, 0x32325664U, 0x3a3a4e74U, 0x0a0a1e14U, 0x4949db92U, 0x06060a0cU, 0x24246c48U, 0x5c5ce4b8U, 0xc2c25d9fU, 0xd3d36ebdU, 0xacacef43U, 0x6262a6c4U, 0x9191a839U, 0x9595a431U, 0xe4e437d3U, 0x79798bf2U, 0xe7e732d5U, 0xc8c8438bU, 0x3737596eU, 0x6d6db7daU, 0x8d8d8c01U, 0xd5d564b1U, 0x4e4ed29cU, 0xa9a9e049U, 0x6c6cb4d8U, 0x5656faacU, 0xf4f407f3U, 0xeaea25cfU, 0x6565afcaU, 0x7a7a8ef4U, 0xaeaee947U, 0x08081810U, 0xbabad56fU, 0x787888f0U, 0x25256f4aU, 0x2e2e725cU, 0x1c1c2438U, 0xa6a6f157U, 0xb4b4c773U, 0xc6c65197U, 0xe8e823cbU, 0xdddd7ca1U, 0x74749ce8U, 0x1f1f213eU, 0x4b4bdd96U, 0xbdbddc61U, 0x8b8b860dU, 0x8a8a850fU, 0x707090e0U, 0x3e3e427cU, 0xb5b5c471U, 0x6666aaccU, 0x4848d890U, 0x03030506U, 0xf6f601f7U, 0x0e0e121cU, 0x6161a3c2U, 0x35355f6aU, 0x5757f9aeU, 0xb9b9d069U, 0x86869117U, 0xc1c15899U, 0x1d1d273aU, 0x9e9eb927U, 0xe1e138d9U, 0xf8f813ebU, 0x9898b32bU, 0x11113322U, 0x6969bbd2U, 0xd9d970a9U, 0x8e8e8907U, 0x9494a733U, 0x9b9bb62dU, 0x1e1e223cU, 0x87879215U, 0xe9e920c9U, 0xcece4987U, 0x5555ffaaU, 0x28287850U, 0xdfdf7aa5U, 0x8c8c8f03U, 0xa1a1f859U, 0x89898009U, 0x0d0d171aU, 0xbfbfda65U, 0xe6e631d7U, 0x4242c684U, 0x6868b8d0U, 0x4141c382U, 0x9999b029U, 0x2d2d775aU, 0x0f0f111eU, 0xb0b0cb7bU, 0x5454fca8U, 0xbbbbd66dU, 0x16163a2cU, }; static const u32 Te4[256] = { 0x63636363U, 0x7c7c7c7cU, 0x77777777U, 0x7b7b7b7bU, 0xf2f2f2f2U, 0x6b6b6b6bU, 0x6f6f6f6fU, 0xc5c5c5c5U, 0x30303030U, 0x01010101U, 0x67676767U, 0x2b2b2b2bU, 0xfefefefeU, 0xd7d7d7d7U, 0xababababU, 0x76767676U, 0xcacacacaU, 0x82828282U, 0xc9c9c9c9U, 0x7d7d7d7dU, 0xfafafafaU, 0x59595959U, 0x47474747U, 0xf0f0f0f0U, 0xadadadadU, 0xd4d4d4d4U, 0xa2a2a2a2U, 0xafafafafU, 0x9c9c9c9cU, 0xa4a4a4a4U, 0x72727272U, 0xc0c0c0c0U, 0xb7b7b7b7U, 0xfdfdfdfdU, 0x93939393U, 0x26262626U, 0x36363636U, 0x3f3f3f3fU, 0xf7f7f7f7U, 0xccccccccU, 0x34343434U, 0xa5a5a5a5U, 0xe5e5e5e5U, 0xf1f1f1f1U, 0x71717171U, 0xd8d8d8d8U, 0x31313131U, 0x15151515U, 0x04040404U, 0xc7c7c7c7U, 0x23232323U, 0xc3c3c3c3U, 0x18181818U, 0x96969696U, 0x05050505U, 0x9a9a9a9aU, 0x07070707U, 0x12121212U, 0x80808080U, 0xe2e2e2e2U, 0xebebebebU, 0x27272727U, 0xb2b2b2b2U, 0x75757575U, 0x09090909U, 0x83838383U, 0x2c2c2c2cU, 0x1a1a1a1aU, 0x1b1b1b1bU, 0x6e6e6e6eU, 0x5a5a5a5aU, 0xa0a0a0a0U, 0x52525252U, 0x3b3b3b3bU, 0xd6d6d6d6U, 0xb3b3b3b3U, 0x29292929U, 0xe3e3e3e3U, 0x2f2f2f2fU, 0x84848484U, 0x53535353U, 0xd1d1d1d1U, 0x00000000U, 0xededededU, 0x20202020U, 0xfcfcfcfcU, 0xb1b1b1b1U, 0x5b5b5b5bU, 0x6a6a6a6aU, 0xcbcbcbcbU, 0xbebebebeU, 0x39393939U, 0x4a4a4a4aU, 0x4c4c4c4cU, 0x58585858U, 0xcfcfcfcfU, 0xd0d0d0d0U, 0xefefefefU, 0xaaaaaaaaU, 0xfbfbfbfbU, 0x43434343U, 0x4d4d4d4dU, 0x33333333U, 0x85858585U, 0x45454545U, 0xf9f9f9f9U, 0x02020202U, 0x7f7f7f7fU, 0x50505050U, 0x3c3c3c3cU, 0x9f9f9f9fU, 0xa8a8a8a8U, 0x51515151U, 0xa3a3a3a3U, 0x40404040U, 0x8f8f8f8fU, 0x92929292U, 0x9d9d9d9dU, 0x38383838U, 0xf5f5f5f5U, 0xbcbcbcbcU, 0xb6b6b6b6U, 0xdadadadaU, 0x21212121U, 0x10101010U, 0xffffffffU, 0xf3f3f3f3U, 0xd2d2d2d2U, 0xcdcdcdcdU, 0x0c0c0c0cU, 0x13131313U, 0xececececU, 0x5f5f5f5fU, 0x97979797U, 0x44444444U, 0x17171717U, 0xc4c4c4c4U, 0xa7a7a7a7U, 0x7e7e7e7eU, 0x3d3d3d3dU, 0x64646464U, 0x5d5d5d5dU, 0x19191919U, 0x73737373U, 0x60606060U, 0x81818181U, 0x4f4f4f4fU, 0xdcdcdcdcU, 0x22222222U, 0x2a2a2a2aU, 0x90909090U, 0x88888888U, 0x46464646U, 0xeeeeeeeeU, 0xb8b8b8b8U, 0x14141414U, 0xdedededeU, 0x5e5e5e5eU, 0x0b0b0b0bU, 0xdbdbdbdbU, 0xe0e0e0e0U, 0x32323232U, 0x3a3a3a3aU, 0x0a0a0a0aU, 0x49494949U, 0x06060606U, 0x24242424U, 0x5c5c5c5cU, 0xc2c2c2c2U, 0xd3d3d3d3U, 0xacacacacU, 0x62626262U, 0x91919191U, 0x95959595U, 0xe4e4e4e4U, 0x79797979U, 0xe7e7e7e7U, 0xc8c8c8c8U, 0x37373737U, 0x6d6d6d6dU, 0x8d8d8d8dU, 0xd5d5d5d5U, 0x4e4e4e4eU, 0xa9a9a9a9U, 0x6c6c6c6cU, 0x56565656U, 0xf4f4f4f4U, 0xeaeaeaeaU, 0x65656565U, 0x7a7a7a7aU, 0xaeaeaeaeU, 0x08080808U, 0xbabababaU, 0x78787878U, 0x25252525U, 0x2e2e2e2eU, 0x1c1c1c1cU, 0xa6a6a6a6U, 0xb4b4b4b4U, 0xc6c6c6c6U, 0xe8e8e8e8U, 0xddddddddU, 0x74747474U, 0x1f1f1f1fU, 0x4b4b4b4bU, 0xbdbdbdbdU, 0x8b8b8b8bU, 0x8a8a8a8aU, 0x70707070U, 0x3e3e3e3eU, 0xb5b5b5b5U, 0x66666666U, 0x48484848U, 0x03030303U, 0xf6f6f6f6U, 0x0e0e0e0eU, 0x61616161U, 0x35353535U, 0x57575757U, 0xb9b9b9b9U, 0x86868686U, 0xc1c1c1c1U, 0x1d1d1d1dU, 0x9e9e9e9eU, 0xe1e1e1e1U, 0xf8f8f8f8U, 0x98989898U, 0x11111111U, 0x69696969U, 0xd9d9d9d9U, 0x8e8e8e8eU, 0x94949494U, 0x9b9b9b9bU, 0x1e1e1e1eU, 0x87878787U, 0xe9e9e9e9U, 0xcecececeU, 0x55555555U, 0x28282828U, 0xdfdfdfdfU, 0x8c8c8c8cU, 0xa1a1a1a1U, 0x89898989U, 0x0d0d0d0dU, 0xbfbfbfbfU, 0xe6e6e6e6U, 0x42424242U, 0x68686868U, 0x41414141U, 0x99999999U, 0x2d2d2d2dU, 0x0f0f0f0fU, 0xb0b0b0b0U, 0x54545454U, 0xbbbbbbbbU, 0x16161616U, }; static const u32 Td0[256] = { 0x51f4a750U, 0x7e416553U, 0x1a17a4c3U, 0x3a275e96U, 0x3bab6bcbU, 0x1f9d45f1U, 0xacfa58abU, 0x4be30393U, 0x2030fa55U, 0xad766df6U, 0x88cc7691U, 0xf5024c25U, 0x4fe5d7fcU, 0xc52acbd7U, 0x26354480U, 0xb562a38fU, 0xdeb15a49U, 0x25ba1b67U, 0x45ea0e98U, 0x5dfec0e1U, 0xc32f7502U, 0x814cf012U, 0x8d4697a3U, 0x6bd3f9c6U, 0x038f5fe7U, 0x15929c95U, 0xbf6d7aebU, 0x955259daU, 0xd4be832dU, 0x587421d3U, 0x49e06929U, 0x8ec9c844U, 0x75c2896aU, 0xf48e7978U, 0x99583e6bU, 0x27b971ddU, 0xbee14fb6U, 0xf088ad17U, 0xc920ac66U, 0x7dce3ab4U, 0x63df4a18U, 0xe51a3182U, 0x97513360U, 0x62537f45U, 0xb16477e0U, 0xbb6bae84U, 0xfe81a01cU, 0xf9082b94U, 0x70486858U, 0x8f45fd19U, 0x94de6c87U, 0x527bf8b7U, 0xab73d323U, 0x724b02e2U, 0xe31f8f57U, 0x6655ab2aU, 0xb2eb2807U, 0x2fb5c203U, 0x86c57b9aU, 0xd33708a5U, 0x302887f2U, 0x23bfa5b2U, 0x02036abaU, 0xed16825cU, 0x8acf1c2bU, 0xa779b492U, 0xf307f2f0U, 0x4e69e2a1U, 0x65daf4cdU, 0x0605bed5U, 0xd134621fU, 0xc4a6fe8aU, 0x342e539dU, 0xa2f355a0U, 0x058ae132U, 0xa4f6eb75U, 0x0b83ec39U, 0x4060efaaU, 0x5e719f06U, 0xbd6e1051U, 0x3e218af9U, 0x96dd063dU, 0xdd3e05aeU, 0x4de6bd46U, 0x91548db5U, 0x71c45d05U, 0x0406d46fU, 0x605015ffU, 0x1998fb24U, 0xd6bde997U, 0x894043ccU, 0x67d99e77U, 0xb0e842bdU, 0x07898b88U, 0xe7195b38U, 0x79c8eedbU, 0xa17c0a47U, 0x7c420fe9U, 0xf8841ec9U, 0x00000000U, 0x09808683U, 0x322bed48U, 0x1e1170acU, 0x6c5a724eU, 0xfd0efffbU, 0x0f853856U, 0x3daed51eU, 0x362d3927U, 0x0a0fd964U, 0x685ca621U, 0x9b5b54d1U, 0x24362e3aU, 0x0c0a67b1U, 0x9357e70fU, 0xb4ee96d2U, 0x1b9b919eU, 0x80c0c54fU, 0x61dc20a2U, 0x5a774b69U, 0x1c121a16U, 0xe293ba0aU, 0xc0a02ae5U, 0x3c22e043U, 0x121b171dU, 0x0e090d0bU, 0xf28bc7adU, 0x2db6a8b9U, 0x141ea9c8U, 0x57f11985U, 0xaf75074cU, 0xee99ddbbU, 0xa37f60fdU, 0xf701269fU, 0x5c72f5bcU, 0x44663bc5U, 0x5bfb7e34U, 0x8b432976U, 0xcb23c6dcU, 0xb6edfc68U, 0xb8e4f163U, 0xd731dccaU, 0x42638510U, 0x13972240U, 0x84c61120U, 0x854a247dU, 0xd2bb3df8U, 0xaef93211U, 0xc729a16dU, 0x1d9e2f4bU, 0xdcb230f3U, 0x0d8652ecU, 0x77c1e3d0U, 0x2bb3166cU, 0xa970b999U, 0x119448faU, 0x47e96422U, 0xa8fc8cc4U, 0xa0f03f1aU, 0x567d2cd8U, 0x223390efU, 0x87494ec7U, 0xd938d1c1U, 0x8ccaa2feU, 0x98d40b36U, 0xa6f581cfU, 0xa57ade28U, 0xdab78e26U, 0x3fadbfa4U, 0x2c3a9de4U, 0x5078920dU, 0x6a5fcc9bU, 0x547e4662U, 0xf68d13c2U, 0x90d8b8e8U, 0x2e39f75eU, 0x82c3aff5U, 0x9f5d80beU, 0x69d0937cU, 0x6fd52da9U, 0xcf2512b3U, 0xc8ac993bU, 0x10187da7U, 0xe89c636eU, 0xdb3bbb7bU, 0xcd267809U, 0x6e5918f4U, 0xec9ab701U, 0x834f9aa8U, 0xe6956e65U, 0xaaffe67eU, 0x21bccf08U, 0xef15e8e6U, 0xbae79bd9U, 0x4a6f36ceU, 0xea9f09d4U, 0x29b07cd6U, 0x31a4b2afU, 0x2a3f2331U, 0xc6a59430U, 0x35a266c0U, 0x744ebc37U, 0xfc82caa6U, 0xe090d0b0U, 0x33a7d815U, 0xf104984aU, 0x41ecdaf7U, 0x7fcd500eU, 0x1791f62fU, 0x764dd68dU, 0x43efb04dU, 0xccaa4d54U, 0xe49604dfU, 0x9ed1b5e3U, 0x4c6a881bU, 0xc12c1fb8U, 0x4665517fU, 0x9d5eea04U, 0x018c355dU, 0xfa877473U, 0xfb0b412eU, 0xb3671d5aU, 0x92dbd252U, 0xe9105633U, 0x6dd64713U, 0x9ad7618cU, 0x37a10c7aU, 0x59f8148eU, 0xeb133c89U, 0xcea927eeU, 0xb761c935U, 0xe11ce5edU, 0x7a47b13cU, 0x9cd2df59U, 0x55f2733fU, 0x1814ce79U, 0x73c737bfU, 0x53f7cdeaU, 0x5ffdaa5bU, 0xdf3d6f14U, 0x7844db86U, 0xcaaff381U, 0xb968c43eU, 0x3824342cU, 0xc2a3405fU, 0x161dc372U, 0xbce2250cU, 0x283c498bU, 0xff0d9541U, 0x39a80171U, 0x080cb3deU, 0xd8b4e49cU, 0x6456c190U, 0x7bcb8461U, 0xd532b670U, 0x486c5c74U, 0xd0b85742U, }; static const u32 Td1[256] = { 0x5051f4a7U, 0x537e4165U, 0xc31a17a4U, 0x963a275eU, 0xcb3bab6bU, 0xf11f9d45U, 0xabacfa58U, 0x934be303U, 0x552030faU, 0xf6ad766dU, 0x9188cc76U, 0x25f5024cU, 0xfc4fe5d7U, 0xd7c52acbU, 0x80263544U, 0x8fb562a3U, 0x49deb15aU, 0x6725ba1bU, 0x9845ea0eU, 0xe15dfec0U, 0x02c32f75U, 0x12814cf0U, 0xa38d4697U, 0xc66bd3f9U, 0xe7038f5fU, 0x9515929cU, 0xebbf6d7aU, 0xda955259U, 0x2dd4be83U, 0xd3587421U, 0x2949e069U, 0x448ec9c8U, 0x6a75c289U, 0x78f48e79U, 0x6b99583eU, 0xdd27b971U, 0xb6bee14fU, 0x17f088adU, 0x66c920acU, 0xb47dce3aU, 0x1863df4aU, 0x82e51a31U, 0x60975133U, 0x4562537fU, 0xe0b16477U, 0x84bb6baeU, 0x1cfe81a0U, 0x94f9082bU, 0x58704868U, 0x198f45fdU, 0x8794de6cU, 0xb7527bf8U, 0x23ab73d3U, 0xe2724b02U, 0x57e31f8fU, 0x2a6655abU, 0x07b2eb28U, 0x032fb5c2U, 0x9a86c57bU, 0xa5d33708U, 0xf2302887U, 0xb223bfa5U, 0xba02036aU, 0x5ced1682U, 0x2b8acf1cU, 0x92a779b4U, 0xf0f307f2U, 0xa14e69e2U, 0xcd65daf4U, 0xd50605beU, 0x1fd13462U, 0x8ac4a6feU, 0x9d342e53U, 0xa0a2f355U, 0x32058ae1U, 0x75a4f6ebU, 0x390b83ecU, 0xaa4060efU, 0x065e719fU, 0x51bd6e10U, 0xf93e218aU, 0x3d96dd06U, 0xaedd3e05U, 0x464de6bdU, 0xb591548dU, 0x0571c45dU, 0x6f0406d4U, 0xff605015U, 0x241998fbU, 0x97d6bde9U, 0xcc894043U, 0x7767d99eU, 0xbdb0e842U, 0x8807898bU, 0x38e7195bU, 0xdb79c8eeU, 0x47a17c0aU, 0xe97c420fU, 0xc9f8841eU, 0x00000000U, 0x83098086U, 0x48322bedU, 0xac1e1170U, 0x4e6c5a72U, 0xfbfd0effU, 0x560f8538U, 0x1e3daed5U, 0x27362d39U, 0x640a0fd9U, 0x21685ca6U, 0xd19b5b54U, 0x3a24362eU, 0xb10c0a67U, 0x0f9357e7U, 0xd2b4ee96U, 0x9e1b9b91U, 0x4f80c0c5U, 0xa261dc20U, 0x695a774bU, 0x161c121aU, 0x0ae293baU, 0xe5c0a02aU, 0x433c22e0U, 0x1d121b17U, 0x0b0e090dU, 0xadf28bc7U, 0xb92db6a8U, 0xc8141ea9U, 0x8557f119U, 0x4caf7507U, 0xbbee99ddU, 0xfda37f60U, 0x9ff70126U, 0xbc5c72f5U, 0xc544663bU, 0x345bfb7eU, 0x768b4329U, 0xdccb23c6U, 0x68b6edfcU, 0x63b8e4f1U, 0xcad731dcU, 0x10426385U, 0x40139722U, 0x2084c611U, 0x7d854a24U, 0xf8d2bb3dU, 0x11aef932U, 0x6dc729a1U, 0x4b1d9e2fU, 0xf3dcb230U, 0xec0d8652U, 0xd077c1e3U, 0x6c2bb316U, 0x99a970b9U, 0xfa119448U, 0x2247e964U, 0xc4a8fc8cU, 0x1aa0f03fU, 0xd8567d2cU, 0xef223390U, 0xc787494eU, 0xc1d938d1U, 0xfe8ccaa2U, 0x3698d40bU, 0xcfa6f581U, 0x28a57adeU, 0x26dab78eU, 0xa43fadbfU, 0xe42c3a9dU, 0x0d507892U, 0x9b6a5fccU, 0x62547e46U, 0xc2f68d13U, 0xe890d8b8U, 0x5e2e39f7U, 0xf582c3afU, 0xbe9f5d80U, 0x7c69d093U, 0xa96fd52dU, 0xb3cf2512U, 0x3bc8ac99U, 0xa710187dU, 0x6ee89c63U, 0x7bdb3bbbU, 0x09cd2678U, 0xf46e5918U, 0x01ec9ab7U, 0xa8834f9aU, 0x65e6956eU, 0x7eaaffe6U, 0x0821bccfU, 0xe6ef15e8U, 0xd9bae79bU, 0xce4a6f36U, 0xd4ea9f09U, 0xd629b07cU, 0xaf31a4b2U, 0x312a3f23U, 0x30c6a594U, 0xc035a266U, 0x37744ebcU, 0xa6fc82caU, 0xb0e090d0U, 0x1533a7d8U, 0x4af10498U, 0xf741ecdaU, 0x0e7fcd50U, 0x2f1791f6U, 0x8d764dd6U, 0x4d43efb0U, 0x54ccaa4dU, 0xdfe49604U, 0xe39ed1b5U, 0x1b4c6a88U, 0xb8c12c1fU, 0x7f466551U, 0x049d5eeaU, 0x5d018c35U, 0x73fa8774U, 0x2efb0b41U, 0x5ab3671dU, 0x5292dbd2U, 0x33e91056U, 0x136dd647U, 0x8c9ad761U, 0x7a37a10cU, 0x8e59f814U, 0x89eb133cU, 0xeecea927U, 0x35b761c9U, 0xede11ce5U, 0x3c7a47b1U, 0x599cd2dfU, 0x3f55f273U, 0x791814ceU, 0xbf73c737U, 0xea53f7cdU, 0x5b5ffdaaU, 0x14df3d6fU, 0x867844dbU, 0x81caaff3U, 0x3eb968c4U, 0x2c382434U, 0x5fc2a340U, 0x72161dc3U, 0x0cbce225U, 0x8b283c49U, 0x41ff0d95U, 0x7139a801U, 0xde080cb3U, 0x9cd8b4e4U, 0x906456c1U, 0x617bcb84U, 0x70d532b6U, 0x74486c5cU, 0x42d0b857U, }; static const u32 Td2[256] = { 0xa75051f4U, 0x65537e41U, 0xa4c31a17U, 0x5e963a27U, 0x6bcb3babU, 0x45f11f9dU, 0x58abacfaU, 0x03934be3U, 0xfa552030U, 0x6df6ad76U, 0x769188ccU, 0x4c25f502U, 0xd7fc4fe5U, 0xcbd7c52aU, 0x44802635U, 0xa38fb562U, 0x5a49deb1U, 0x1b6725baU, 0x0e9845eaU, 0xc0e15dfeU, 0x7502c32fU, 0xf012814cU, 0x97a38d46U, 0xf9c66bd3U, 0x5fe7038fU, 0x9c951592U, 0x7aebbf6dU, 0x59da9552U, 0x832dd4beU, 0x21d35874U, 0x692949e0U, 0xc8448ec9U, 0x896a75c2U, 0x7978f48eU, 0x3e6b9958U, 0x71dd27b9U, 0x4fb6bee1U, 0xad17f088U, 0xac66c920U, 0x3ab47dceU, 0x4a1863dfU, 0x3182e51aU, 0x33609751U, 0x7f456253U, 0x77e0b164U, 0xae84bb6bU, 0xa01cfe81U, 0x2b94f908U, 0x68587048U, 0xfd198f45U, 0x6c8794deU, 0xf8b7527bU, 0xd323ab73U, 0x02e2724bU, 0x8f57e31fU, 0xab2a6655U, 0x2807b2ebU, 0xc2032fb5U, 0x7b9a86c5U, 0x08a5d337U, 0x87f23028U, 0xa5b223bfU, 0x6aba0203U, 0x825ced16U, 0x1c2b8acfU, 0xb492a779U, 0xf2f0f307U, 0xe2a14e69U, 0xf4cd65daU, 0xbed50605U, 0x621fd134U, 0xfe8ac4a6U, 0x539d342eU, 0x55a0a2f3U, 0xe132058aU, 0xeb75a4f6U, 0xec390b83U, 0xefaa4060U, 0x9f065e71U, 0x1051bd6eU, 0x8af93e21U, 0x063d96ddU, 0x05aedd3eU, 0xbd464de6U, 0x8db59154U, 0x5d0571c4U, 0xd46f0406U, 0x15ff6050U, 0xfb241998U, 0xe997d6bdU, 0x43cc8940U, 0x9e7767d9U, 0x42bdb0e8U, 0x8b880789U, 0x5b38e719U, 0xeedb79c8U, 0x0a47a17cU, 0x0fe97c42U, 0x1ec9f884U, 0x00000000U, 0x86830980U, 0xed48322bU, 0x70ac1e11U, 0x724e6c5aU, 0xfffbfd0eU, 0x38560f85U, 0xd51e3daeU, 0x3927362dU, 0xd9640a0fU, 0xa621685cU, 0x54d19b5bU, 0x2e3a2436U, 0x67b10c0aU, 0xe70f9357U, 0x96d2b4eeU, 0x919e1b9bU, 0xc54f80c0U, 0x20a261dcU, 0x4b695a77U, 0x1a161c12U, 0xba0ae293U, 0x2ae5c0a0U, 0xe0433c22U, 0x171d121bU, 0x0d0b0e09U, 0xc7adf28bU, 0xa8b92db6U, 0xa9c8141eU, 0x198557f1U, 0x074caf75U, 0xddbbee99U, 0x60fda37fU, 0x269ff701U, 0xf5bc5c72U, 0x3bc54466U, 0x7e345bfbU, 0x29768b43U, 0xc6dccb23U, 0xfc68b6edU, 0xf163b8e4U, 0xdccad731U, 0x85104263U, 0x22401397U, 0x112084c6U, 0x247d854aU, 0x3df8d2bbU, 0x3211aef9U, 0xa16dc729U, 0x2f4b1d9eU, 0x30f3dcb2U, 0x52ec0d86U, 0xe3d077c1U, 0x166c2bb3U, 0xb999a970U, 0x48fa1194U, 0x642247e9U, 0x8cc4a8fcU, 0x3f1aa0f0U, 0x2cd8567dU, 0x90ef2233U, 0x4ec78749U, 0xd1c1d938U, 0xa2fe8ccaU, 0x0b3698d4U, 0x81cfa6f5U, 0xde28a57aU, 0x8e26dab7U, 0xbfa43fadU, 0x9de42c3aU, 0x920d5078U, 0xcc9b6a5fU, 0x4662547eU, 0x13c2f68dU, 0xb8e890d8U, 0xf75e2e39U, 0xaff582c3U, 0x80be9f5dU, 0x937c69d0U, 0x2da96fd5U, 0x12b3cf25U, 0x993bc8acU, 0x7da71018U, 0x636ee89cU, 0xbb7bdb3bU, 0x7809cd26U, 0x18f46e59U, 0xb701ec9aU, 0x9aa8834fU, 0x6e65e695U, 0xe67eaaffU, 0xcf0821bcU, 0xe8e6ef15U, 0x9bd9bae7U, 0x36ce4a6fU, 0x09d4ea9fU, 0x7cd629b0U, 0xb2af31a4U, 0x23312a3fU, 0x9430c6a5U, 0x66c035a2U, 0xbc37744eU, 0xcaa6fc82U, 0xd0b0e090U, 0xd81533a7U, 0x984af104U, 0xdaf741ecU, 0x500e7fcdU, 0xf62f1791U, 0xd68d764dU, 0xb04d43efU, 0x4d54ccaaU, 0x04dfe496U, 0xb5e39ed1U, 0x881b4c6aU, 0x1fb8c12cU, 0x517f4665U, 0xea049d5eU, 0x355d018cU, 0x7473fa87U, 0x412efb0bU, 0x1d5ab367U, 0xd25292dbU, 0x5633e910U, 0x47136dd6U, 0x618c9ad7U, 0x0c7a37a1U, 0x148e59f8U, 0x3c89eb13U, 0x27eecea9U, 0xc935b761U, 0xe5ede11cU, 0xb13c7a47U, 0xdf599cd2U, 0x733f55f2U, 0xce791814U, 0x37bf73c7U, 0xcdea53f7U, 0xaa5b5ffdU, 0x6f14df3dU, 0xdb867844U, 0xf381caafU, 0xc43eb968U, 0x342c3824U, 0x405fc2a3U, 0xc372161dU, 0x250cbce2U, 0x498b283cU, 0x9541ff0dU, 0x017139a8U, 0xb3de080cU, 0xe49cd8b4U, 0xc1906456U, 0x84617bcbU, 0xb670d532U, 0x5c74486cU, 0x5742d0b8U, }; static const u32 Td3[256] = { 0xf4a75051U, 0x4165537eU, 0x17a4c31aU, 0x275e963aU, 0xab6bcb3bU, 0x9d45f11fU, 0xfa58abacU, 0xe303934bU, 0x30fa5520U, 0x766df6adU, 0xcc769188U, 0x024c25f5U, 0xe5d7fc4fU, 0x2acbd7c5U, 0x35448026U, 0x62a38fb5U, 0xb15a49deU, 0xba1b6725U, 0xea0e9845U, 0xfec0e15dU, 0x2f7502c3U, 0x4cf01281U, 0x4697a38dU, 0xd3f9c66bU, 0x8f5fe703U, 0x929c9515U, 0x6d7aebbfU, 0x5259da95U, 0xbe832dd4U, 0x7421d358U, 0xe0692949U, 0xc9c8448eU, 0xc2896a75U, 0x8e7978f4U, 0x583e6b99U, 0xb971dd27U, 0xe14fb6beU, 0x88ad17f0U, 0x20ac66c9U, 0xce3ab47dU, 0xdf4a1863U, 0x1a3182e5U, 0x51336097U, 0x537f4562U, 0x6477e0b1U, 0x6bae84bbU, 0x81a01cfeU, 0x082b94f9U, 0x48685870U, 0x45fd198fU, 0xde6c8794U, 0x7bf8b752U, 0x73d323abU, 0x4b02e272U, 0x1f8f57e3U, 0x55ab2a66U, 0xeb2807b2U, 0xb5c2032fU, 0xc57b9a86U, 0x3708a5d3U, 0x2887f230U, 0xbfa5b223U, 0x036aba02U, 0x16825cedU, 0xcf1c2b8aU, 0x79b492a7U, 0x07f2f0f3U, 0x69e2a14eU, 0xdaf4cd65U, 0x05bed506U, 0x34621fd1U, 0xa6fe8ac4U, 0x2e539d34U, 0xf355a0a2U, 0x8ae13205U, 0xf6eb75a4U, 0x83ec390bU, 0x60efaa40U, 0x719f065eU, 0x6e1051bdU, 0x218af93eU, 0xdd063d96U, 0x3e05aeddU, 0xe6bd464dU, 0x548db591U, 0xc45d0571U, 0x06d46f04U, 0x5015ff60U, 0x98fb2419U, 0xbde997d6U, 0x4043cc89U, 0xd99e7767U, 0xe842bdb0U, 0x898b8807U, 0x195b38e7U, 0xc8eedb79U, 0x7c0a47a1U, 0x420fe97cU, 0x841ec9f8U, 0x00000000U, 0x80868309U, 0x2bed4832U, 0x1170ac1eU, 0x5a724e6cU, 0x0efffbfdU, 0x8538560fU, 0xaed51e3dU, 0x2d392736U, 0x0fd9640aU, 0x5ca62168U, 0x5b54d19bU, 0x362e3a24U, 0x0a67b10cU, 0x57e70f93U, 0xee96d2b4U, 0x9b919e1bU, 0xc0c54f80U, 0xdc20a261U, 0x774b695aU, 0x121a161cU, 0x93ba0ae2U, 0xa02ae5c0U, 0x22e0433cU, 0x1b171d12U, 0x090d0b0eU, 0x8bc7adf2U, 0xb6a8b92dU, 0x1ea9c814U, 0xf1198557U, 0x75074cafU, 0x99ddbbeeU, 0x7f60fda3U, 0x01269ff7U, 0x72f5bc5cU, 0x663bc544U, 0xfb7e345bU, 0x4329768bU, 0x23c6dccbU, 0xedfc68b6U, 0xe4f163b8U, 0x31dccad7U, 0x63851042U, 0x97224013U, 0xc6112084U, 0x4a247d85U, 0xbb3df8d2U, 0xf93211aeU, 0x29a16dc7U, 0x9e2f4b1dU, 0xb230f3dcU, 0x8652ec0dU, 0xc1e3d077U, 0xb3166c2bU, 0x70b999a9U, 0x9448fa11U, 0xe9642247U, 0xfc8cc4a8U, 0xf03f1aa0U, 0x7d2cd856U, 0x3390ef22U, 0x494ec787U, 0x38d1c1d9U, 0xcaa2fe8cU, 0xd40b3698U, 0xf581cfa6U, 0x7ade28a5U, 0xb78e26daU, 0xadbfa43fU, 0x3a9de42cU, 0x78920d50U, 0x5fcc9b6aU, 0x7e466254U, 0x8d13c2f6U, 0xd8b8e890U, 0x39f75e2eU, 0xc3aff582U, 0x5d80be9fU, 0xd0937c69U, 0xd52da96fU, 0x2512b3cfU, 0xac993bc8U, 0x187da710U, 0x9c636ee8U, 0x3bbb7bdbU, 0x267809cdU, 0x5918f46eU, 0x9ab701ecU, 0x4f9aa883U, 0x956e65e6U, 0xffe67eaaU, 0xbccf0821U, 0x15e8e6efU, 0xe79bd9baU, 0x6f36ce4aU, 0x9f09d4eaU, 0xb07cd629U, 0xa4b2af31U, 0x3f23312aU, 0xa59430c6U, 0xa266c035U, 0x4ebc3774U, 0x82caa6fcU, 0x90d0b0e0U, 0xa7d81533U, 0x04984af1U, 0xecdaf741U, 0xcd500e7fU, 0x91f62f17U, 0x4dd68d76U, 0xefb04d43U, 0xaa4d54ccU, 0x9604dfe4U, 0xd1b5e39eU, 0x6a881b4cU, 0x2c1fb8c1U, 0x65517f46U, 0x5eea049dU, 0x8c355d01U, 0x877473faU, 0x0b412efbU, 0x671d5ab3U, 0xdbd25292U, 0x105633e9U, 0xd647136dU, 0xd7618c9aU, 0xa10c7a37U, 0xf8148e59U, 0x133c89ebU, 0xa927eeceU, 0x61c935b7U, 0x1ce5ede1U, 0x47b13c7aU, 0xd2df599cU, 0xf2733f55U, 0x14ce7918U, 0xc737bf73U, 0xf7cdea53U, 0xfdaa5b5fU, 0x3d6f14dfU, 0x44db8678U, 0xaff381caU, 0x68c43eb9U, 0x24342c38U, 0xa3405fc2U, 0x1dc37216U, 0xe2250cbcU, 0x3c498b28U, 0x0d9541ffU, 0xa8017139U, 0x0cb3de08U, 0xb4e49cd8U, 0x56c19064U, 0xcb84617bU, 0x32b670d5U, 0x6c5c7448U, 0xb85742d0U, }; static const u32 Td4[256] = { 0x52525252U, 0x09090909U, 0x6a6a6a6aU, 0xd5d5d5d5U, 0x30303030U, 0x36363636U, 0xa5a5a5a5U, 0x38383838U, 0xbfbfbfbfU, 0x40404040U, 0xa3a3a3a3U, 0x9e9e9e9eU, 0x81818181U, 0xf3f3f3f3U, 0xd7d7d7d7U, 0xfbfbfbfbU, 0x7c7c7c7cU, 0xe3e3e3e3U, 0x39393939U, 0x82828282U, 0x9b9b9b9bU, 0x2f2f2f2fU, 0xffffffffU, 0x87878787U, 0x34343434U, 0x8e8e8e8eU, 0x43434343U, 0x44444444U, 0xc4c4c4c4U, 0xdedededeU, 0xe9e9e9e9U, 0xcbcbcbcbU, 0x54545454U, 0x7b7b7b7bU, 0x94949494U, 0x32323232U, 0xa6a6a6a6U, 0xc2c2c2c2U, 0x23232323U, 0x3d3d3d3dU, 0xeeeeeeeeU, 0x4c4c4c4cU, 0x95959595U, 0x0b0b0b0bU, 0x42424242U, 0xfafafafaU, 0xc3c3c3c3U, 0x4e4e4e4eU, 0x08080808U, 0x2e2e2e2eU, 0xa1a1a1a1U, 0x66666666U, 0x28282828U, 0xd9d9d9d9U, 0x24242424U, 0xb2b2b2b2U, 0x76767676U, 0x5b5b5b5bU, 0xa2a2a2a2U, 0x49494949U, 0x6d6d6d6dU, 0x8b8b8b8bU, 0xd1d1d1d1U, 0x25252525U, 0x72727272U, 0xf8f8f8f8U, 0xf6f6f6f6U, 0x64646464U, 0x86868686U, 0x68686868U, 0x98989898U, 0x16161616U, 0xd4d4d4d4U, 0xa4a4a4a4U, 0x5c5c5c5cU, 0xccccccccU, 0x5d5d5d5dU, 0x65656565U, 0xb6b6b6b6U, 0x92929292U, 0x6c6c6c6cU, 0x70707070U, 0x48484848U, 0x50505050U, 0xfdfdfdfdU, 0xededededU, 0xb9b9b9b9U, 0xdadadadaU, 0x5e5e5e5eU, 0x15151515U, 0x46464646U, 0x57575757U, 0xa7a7a7a7U, 0x8d8d8d8dU, 0x9d9d9d9dU, 0x84848484U, 0x90909090U, 0xd8d8d8d8U, 0xababababU, 0x00000000U, 0x8c8c8c8cU, 0xbcbcbcbcU, 0xd3d3d3d3U, 0x0a0a0a0aU, 0xf7f7f7f7U, 0xe4e4e4e4U, 0x58585858U, 0x05050505U, 0xb8b8b8b8U, 0xb3b3b3b3U, 0x45454545U, 0x06060606U, 0xd0d0d0d0U, 0x2c2c2c2cU, 0x1e1e1e1eU, 0x8f8f8f8fU, 0xcacacacaU, 0x3f3f3f3fU, 0x0f0f0f0fU, 0x02020202U, 0xc1c1c1c1U, 0xafafafafU, 0xbdbdbdbdU, 0x03030303U, 0x01010101U, 0x13131313U, 0x8a8a8a8aU, 0x6b6b6b6bU, 0x3a3a3a3aU, 0x91919191U, 0x11111111U, 0x41414141U, 0x4f4f4f4fU, 0x67676767U, 0xdcdcdcdcU, 0xeaeaeaeaU, 0x97979797U, 0xf2f2f2f2U, 0xcfcfcfcfU, 0xcecececeU, 0xf0f0f0f0U, 0xb4b4b4b4U, 0xe6e6e6e6U, 0x73737373U, 0x96969696U, 0xacacacacU, 0x74747474U, 0x22222222U, 0xe7e7e7e7U, 0xadadadadU, 0x35353535U, 0x85858585U, 0xe2e2e2e2U, 0xf9f9f9f9U, 0x37373737U, 0xe8e8e8e8U, 0x1c1c1c1cU, 0x75757575U, 0xdfdfdfdfU, 0x6e6e6e6eU, 0x47474747U, 0xf1f1f1f1U, 0x1a1a1a1aU, 0x71717171U, 0x1d1d1d1dU, 0x29292929U, 0xc5c5c5c5U, 0x89898989U, 0x6f6f6f6fU, 0xb7b7b7b7U, 0x62626262U, 0x0e0e0e0eU, 0xaaaaaaaaU, 0x18181818U, 0xbebebebeU, 0x1b1b1b1bU, 0xfcfcfcfcU, 0x56565656U, 0x3e3e3e3eU, 0x4b4b4b4bU, 0xc6c6c6c6U, 0xd2d2d2d2U, 0x79797979U, 0x20202020U, 0x9a9a9a9aU, 0xdbdbdbdbU, 0xc0c0c0c0U, 0xfefefefeU, 0x78787878U, 0xcdcdcdcdU, 0x5a5a5a5aU, 0xf4f4f4f4U, 0x1f1f1f1fU, 0xddddddddU, 0xa8a8a8a8U, 0x33333333U, 0x88888888U, 0x07070707U, 0xc7c7c7c7U, 0x31313131U, 0xb1b1b1b1U, 0x12121212U, 0x10101010U, 0x59595959U, 0x27272727U, 0x80808080U, 0xececececU, 0x5f5f5f5fU, 0x60606060U, 0x51515151U, 0x7f7f7f7fU, 0xa9a9a9a9U, 0x19191919U, 0xb5b5b5b5U, 0x4a4a4a4aU, 0x0d0d0d0dU, 0x2d2d2d2dU, 0xe5e5e5e5U, 0x7a7a7a7aU, 0x9f9f9f9fU, 0x93939393U, 0xc9c9c9c9U, 0x9c9c9c9cU, 0xefefefefU, 0xa0a0a0a0U, 0xe0e0e0e0U, 0x3b3b3b3bU, 0x4d4d4d4dU, 0xaeaeaeaeU, 0x2a2a2a2aU, 0xf5f5f5f5U, 0xb0b0b0b0U, 0xc8c8c8c8U, 0xebebebebU, 0xbbbbbbbbU, 0x3c3c3c3cU, 0x83838383U, 0x53535353U, 0x99999999U, 0x61616161U, 0x17171717U, 0x2b2b2b2bU, 0x04040404U, 0x7e7e7e7eU, 0xbabababaU, 0x77777777U, 0xd6d6d6d6U, 0x26262626U, 0xe1e1e1e1U, 0x69696969U, 0x14141414U, 0x63636363U, 0x55555555U, 0x21212121U, 0x0c0c0c0cU, 0x7d7d7d7dU, }; static const u32 rcon[] = { 0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000, 0x20000000, 0x40000000, 0x80000000, 0x1B000000, 0x36000000, /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */ }; #define SWAP(x) (_lrotl(x, 8) & 0x00ff00ff | _lrotr(x, 8) & 0xff00ff00) #ifdef _MSC_VER #define GETU32(p) SWAP(*((u32 *)(p))) #define PUTU32(ct, st) { *((u32 *)(ct)) = SWAP((st)); } #else #define GETU32(pt) (((u32)(pt)[0] << 24) ^ ((u32)(pt)[1] << 16) ^ ((u32)(pt)[2] << 8) ^ ((u32)(pt)[3])) #define PUTU32(ct, st) { (ct)[0] = (u8)((st) >> 24); (ct)[1] = (u8)((st) >> 16); (ct)[2] = (u8)((st) >> 8); (ct)[3] = (u8)(st); } #endif /** * Expand the cipher key into the encryption key schedule. * * @return the number of rounds for the given cipher key size. */ int rijndaelKeySetupEnc(u32 rk[/*4*(Nr + 1)*/], const u8 cipherKey[], int keyBits) { int i = 0; u32 temp; rk[0] = GETU32(cipherKey ); rk[1] = GETU32(cipherKey + 4); rk[2] = GETU32(cipherKey + 8); rk[3] = GETU32(cipherKey + 12); if (keyBits == 128) { for (;;) { temp = rk[3]; rk[4] = rk[0] ^ (Te4[(temp >> 16) & 0xff] & 0xff000000) ^ (Te4[(temp >> 8) & 0xff] & 0x00ff0000) ^ (Te4[(temp ) & 0xff] & 0x0000ff00) ^ (Te4[(temp >> 24) ] & 0x000000ff) ^ rcon[i]; rk[5] = rk[1] ^ rk[4]; rk[6] = rk[2] ^ rk[5]; rk[7] = rk[3] ^ rk[6]; if (++i == 10) { return 10; } rk += 4; } } rk[4] = GETU32(cipherKey + 16); rk[5] = GETU32(cipherKey + 20); if (keyBits == 192) { for (;;) { temp = rk[ 5]; rk[ 6] = rk[ 0] ^ (Te4[(temp >> 16) & 0xff] & 0xff000000) ^ (Te4[(temp >> 8) & 0xff] & 0x00ff0000) ^ (Te4[(temp ) & 0xff] & 0x0000ff00) ^ (Te4[(temp >> 24) ] & 0x000000ff) ^ rcon[i]; rk[ 7] = rk[ 1] ^ rk[ 6]; rk[ 8] = rk[ 2] ^ rk[ 7]; rk[ 9] = rk[ 3] ^ rk[ 8]; if (++i == 8) { return 12; } rk[10] = rk[ 4] ^ rk[ 9]; rk[11] = rk[ 5] ^ rk[10]; rk += 6; } } rk[6] = GETU32(cipherKey + 24); rk[7] = GETU32(cipherKey + 28); if (keyBits == 256) { for (;;) { temp = rk[ 7]; rk[ 8] = rk[ 0] ^ (Te4[(temp >> 16) & 0xff] & 0xff000000) ^ (Te4[(temp >> 8) & 0xff] & 0x00ff0000) ^ (Te4[(temp ) & 0xff] & 0x0000ff00) ^ (Te4[(temp >> 24) ] & 0x000000ff) ^ rcon[i]; rk[ 9] = rk[ 1] ^ rk[ 8]; rk[10] = rk[ 2] ^ rk[ 9]; rk[11] = rk[ 3] ^ rk[10]; if (++i == 7) { return 14; } temp = rk[11]; rk[12] = rk[ 4] ^ (Te4[(temp >> 24) ] & 0xff000000) ^ (Te4[(temp >> 16) & 0xff] & 0x00ff0000) ^ (Te4[(temp >> 8) & 0xff] & 0x0000ff00) ^ (Te4[(temp ) & 0xff] & 0x000000ff); rk[13] = rk[ 5] ^ rk[12]; rk[14] = rk[ 6] ^ rk[13]; rk[15] = rk[ 7] ^ rk[14]; rk += 8; } } return 0; } /** * Expand the cipher key into the decryption key schedule. * * @return the number of rounds for the given cipher key size. */ int rijndaelKeySetupDec(u32 rk[/*4*(Nr + 1)*/], const u8 cipherKey[], int keyBits) { int Nr, i, j; u32 temp; /* expand the cipher key: */ Nr = rijndaelKeySetupEnc(rk, cipherKey, keyBits); /* invert the order of the round keys: */ for (i = 0, j = 4*Nr; i < j; i += 4, j -= 4) { temp = rk[i ]; rk[i ] = rk[j ]; rk[j ] = temp; temp = rk[i + 1]; rk[i + 1] = rk[j + 1]; rk[j + 1] = temp; temp = rk[i + 2]; rk[i + 2] = rk[j + 2]; rk[j + 2] = temp; temp = rk[i + 3]; rk[i + 3] = rk[j + 3]; rk[j + 3] = temp; } /* apply the inverse MixColumn transform to all round keys but the first and the last: */ for (i = 1; i < Nr; i++) { rk += 4; rk[0] = Td0[Te4[(rk[0] >> 24) ] & 0xff] ^ Td1[Te4[(rk[0] >> 16) & 0xff] & 0xff] ^ Td2[Te4[(rk[0] >> 8) & 0xff] & 0xff] ^ Td3[Te4[(rk[0] ) & 0xff] & 0xff]; rk[1] = Td0[Te4[(rk[1] >> 24) ] & 0xff] ^ Td1[Te4[(rk[1] >> 16) & 0xff] & 0xff] ^ Td2[Te4[(rk[1] >> 8) & 0xff] & 0xff] ^ Td3[Te4[(rk[1] ) & 0xff] & 0xff]; rk[2] = Td0[Te4[(rk[2] >> 24) ] & 0xff] ^ Td1[Te4[(rk[2] >> 16) & 0xff] & 0xff] ^ Td2[Te4[(rk[2] >> 8) & 0xff] & 0xff] ^ Td3[Te4[(rk[2] ) & 0xff] & 0xff]; rk[3] = Td0[Te4[(rk[3] >> 24) ] & 0xff] ^ Td1[Te4[(rk[3] >> 16) & 0xff] & 0xff] ^ Td2[Te4[(rk[3] >> 8) & 0xff] & 0xff] ^ Td3[Te4[(rk[3] ) & 0xff] & 0xff]; } return Nr; } void rijndaelEncrypt(const u32 rk[/*4*(Nr + 1)*/], int Nr, const u8 pt[16], u8 ct[16]) { u32 s0, s1, s2, s3, t0, t1, t2, t3; #ifndef FULL_UNROLL int r; #endif /* ?FULL_UNROLL */ /* * map byte array block to cipher state * and add initial round key: */ s0 = GETU32(pt ) ^ rk[0]; s1 = GETU32(pt + 4) ^ rk[1]; s2 = GETU32(pt + 8) ^ rk[2]; s3 = GETU32(pt + 12) ^ rk[3]; #ifdef FULL_UNROLL /* round 1: */ t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[ 4]; t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[ 5]; t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[ 6]; t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[ 7]; /* round 2: */ s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[ 8]; s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[ 9]; s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[10]; s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[11]; /* round 3: */ t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[12]; t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[13]; t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[14]; t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[15]; /* round 4: */ s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[16]; s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[17]; s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[18]; s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[19]; /* round 5: */ t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[20]; t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[21]; t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[22]; t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[23]; /* round 6: */ s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[24]; s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[25]; s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[26]; s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[27]; /* round 7: */ t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[28]; t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[29]; t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[30]; t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[31]; /* round 8: */ s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[32]; s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[33]; s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[34]; s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[35]; /* round 9: */ t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[36]; t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[37]; t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[38]; t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[39]; if (Nr > 10) { /* round 10: */ s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[40]; s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[41]; s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[42]; s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[43]; /* round 11: */ t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[44]; t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[45]; t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[46]; t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[47]; if (Nr > 12) { /* round 12: */ s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[48]; s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[49]; s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[50]; s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[51]; /* round 13: */ t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[52]; t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[53]; t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[54]; t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[55]; } } rk += Nr << 2; #else /* !FULL_UNROLL */ /* * Nr - 1 full rounds: */ r = Nr >> 1; for (;;) { t0 = Te0[(s0 >> 24) ] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[(s3 ) & 0xff] ^ rk[4]; t1 = Te0[(s1 >> 24) ] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[(s0 ) & 0xff] ^ rk[5]; t2 = Te0[(s2 >> 24) ] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[(s1 ) & 0xff] ^ rk[6]; t3 = Te0[(s3 >> 24) ] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[(s2 ) & 0xff] ^ rk[7]; rk += 8; if (--r == 0) { break; } s0 = Te0[(t0 >> 24) ] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[(t3 ) & 0xff] ^ rk[0]; s1 = Te0[(t1 >> 24) ] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[(t0 ) & 0xff] ^ rk[1]; s2 = Te0[(t2 >> 24) ] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[(t1 ) & 0xff] ^ rk[2]; s3 = Te0[(t3 >> 24) ] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[(t2 ) & 0xff] ^ rk[3]; } #endif /* ?FULL_UNROLL */ /* * apply last round and * map cipher state to byte array block: */ s0 = (Te4[(t0 >> 24) ] & 0xff000000) ^ (Te4[(t1 >> 16) & 0xff] & 0x00ff0000) ^ (Te4[(t2 >> 8) & 0xff] & 0x0000ff00) ^ (Te4[(t3 ) & 0xff] & 0x000000ff) ^ rk[0]; PUTU32(ct , s0); s1 = (Te4[(t1 >> 24) ] & 0xff000000) ^ (Te4[(t2 >> 16) & 0xff] & 0x00ff0000) ^ (Te4[(t3 >> 8) & 0xff] & 0x0000ff00) ^ (Te4[(t0 ) & 0xff] & 0x000000ff) ^ rk[1]; PUTU32(ct + 4, s1); s2 = (Te4[(t2 >> 24) ] & 0xff000000) ^ (Te4[(t3 >> 16) & 0xff] & 0x00ff0000) ^ (Te4[(t0 >> 8) & 0xff] & 0x0000ff00) ^ (Te4[(t1 ) & 0xff] & 0x000000ff) ^ rk[2]; PUTU32(ct + 8, s2); s3 = (Te4[(t3 >> 24) ] & 0xff000000) ^ (Te4[(t0 >> 16) & 0xff] & 0x00ff0000) ^ (Te4[(t1 >> 8) & 0xff] & 0x0000ff00) ^ (Te4[(t2 ) & 0xff] & 0x000000ff) ^ rk[3]; PUTU32(ct + 12, s3); } void rijndaelDecrypt(const u32 rk[/*4*(Nr + 1)*/], int Nr, const u8 ct[16], u8 pt[16]) { u32 s0, s1, s2, s3, t0, t1, t2, t3; #ifndef FULL_UNROLL int r; #endif /* ?FULL_UNROLL */ /* * map byte array block to cipher state * and add initial round key: */ s0 = GETU32(ct ) ^ rk[0]; s1 = GETU32(ct + 4) ^ rk[1]; s2 = GETU32(ct + 8) ^ rk[2]; s3 = GETU32(ct + 12) ^ rk[3]; #ifdef FULL_UNROLL /* round 1: */ t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[ 4]; t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[ 5]; t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[ 6]; t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[ 7]; /* round 2: */ s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[ 8]; s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[ 9]; s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[10]; s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[11]; /* round 3: */ t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[12]; t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[13]; t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[14]; t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[15]; /* round 4: */ s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[16]; s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[17]; s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[18]; s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[19]; /* round 5: */ t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[20]; t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[21]; t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[22]; t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[23]; /* round 6: */ s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[24]; s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[25]; s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[26]; s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[27]; /* round 7: */ t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[28]; t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[29]; t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[30]; t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[31]; /* round 8: */ s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[32]; s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[33]; s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[34]; s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[35]; /* round 9: */ t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[36]; t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[37]; t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[38]; t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[39]; if (Nr > 10) { /* round 10: */ s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[40]; s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[41]; s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[42]; s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[43]; /* round 11: */ t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[44]; t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[45]; t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[46]; t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[47]; if (Nr > 12) { /* round 12: */ s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[48]; s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[49]; s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[50]; s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[51]; /* round 13: */ t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[52]; t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[53]; t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[54]; t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[55]; } } rk += Nr << 2; #else /* !FULL_UNROLL */ /* * Nr - 1 full rounds: */ r = Nr >> 1; for (;;) { t0 = Td0[(s0 >> 24) ] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[(s1 ) & 0xff] ^ rk[4]; t1 = Td0[(s1 >> 24) ] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[(s2 ) & 0xff] ^ rk[5]; t2 = Td0[(s2 >> 24) ] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[(s3 ) & 0xff] ^ rk[6]; t3 = Td0[(s3 >> 24) ] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[(s0 ) & 0xff] ^ rk[7]; rk += 8; if (--r == 0) { break; } s0 = Td0[(t0 >> 24) ] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[(t1 ) & 0xff] ^ rk[0]; s1 = Td0[(t1 >> 24) ] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[(t2 ) & 0xff] ^ rk[1]; s2 = Td0[(t2 >> 24) ] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[(t3 ) & 0xff] ^ rk[2]; s3 = Td0[(t3 >> 24) ] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[(t0 ) & 0xff] ^ rk[3]; } #endif /* ?FULL_UNROLL */ /* * apply last round and * map cipher state to byte array block: */ s0 = (Td4[(t0 >> 24) ] & 0xff000000) ^ (Td4[(t3 >> 16) & 0xff] & 0x00ff0000) ^ (Td4[(t2 >> 8) & 0xff] & 0x0000ff00) ^ (Td4[(t1 ) & 0xff] & 0x000000ff) ^ rk[0]; PUTU32(pt , s0); s1 = (Td4[(t1 >> 24) ] & 0xff000000) ^ (Td4[(t0 >> 16) & 0xff] & 0x00ff0000) ^ (Td4[(t3 >> 8) & 0xff] & 0x0000ff00) ^ (Td4[(t2 ) & 0xff] & 0x000000ff) ^ rk[1]; PUTU32(pt + 4, s1); s2 = (Td4[(t2 >> 24) ] & 0xff000000) ^ (Td4[(t1 >> 16) & 0xff] & 0x00ff0000) ^ (Td4[(t0 >> 8) & 0xff] & 0x0000ff00) ^ (Td4[(t3 ) & 0xff] & 0x000000ff) ^ rk[2]; PUTU32(pt + 8, s2); s3 = (Td4[(t3 >> 24) ] & 0xff000000) ^ (Td4[(t2 >> 16) & 0xff] & 0x00ff0000) ^ (Td4[(t1 >> 8) & 0xff] & 0x0000ff00) ^ (Td4[(t0 ) & 0xff] & 0x000000ff) ^ rk[3]; PUTU32(pt + 12, s3); } #ifdef INTERMEDIATE_VALUE_KAT void rijndaelEncryptRound(const u32 rk[/*4*(Nr + 1)*/], int Nr, u8 block[16], int rounds) { int r; u32 s0, s1, s2, s3, t0, t1, t2, t3; /* * map byte array block to cipher state * and add initial round key: */ s0 = GETU32(block ) ^ rk[0]; s1 = GETU32(block + 4) ^ rk[1]; s2 = GETU32(block + 8) ^ rk[2]; s3 = GETU32(block + 12) ^ rk[3]; rk += 4; /* * Nr - 1 full rounds: */ for (r = (rounds < Nr ? rounds : Nr - 1); r > 0; r--) { t0 = Te0[(s0 >> 24) ] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[(s3 ) & 0xff] ^ rk[0]; t1 = Te0[(s1 >> 24) ] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[(s0 ) & 0xff] ^ rk[1]; t2 = Te0[(s2 >> 24) ] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[(s1 ) & 0xff] ^ rk[2]; t3 = Te0[(s3 >> 24) ] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[(s2 ) & 0xff] ^ rk[3]; s0 = t0; s1 = t1; s2 = t2; s3 = t3; rk += 4; } /* * apply last round and * map cipher state to byte array block: */ if (rounds == Nr) { t0 = (Te4[(s0 >> 24) ] & 0xff000000) ^ (Te4[(s1 >> 16) & 0xff] & 0x00ff0000) ^ (Te4[(s2 >> 8) & 0xff] & 0x0000ff00) ^ (Te4[(s3 ) & 0xff] & 0x000000ff) ^ rk[0]; t1 = (Te4[(s1 >> 24) ] & 0xff000000) ^ (Te4[(s2 >> 16) & 0xff] & 0x00ff0000) ^ (Te4[(s3 >> 8) & 0xff] & 0x0000ff00) ^ (Te4[(s0 ) & 0xff] & 0x000000ff) ^ rk[1]; t2 = (Te4[(s2 >> 24) ] & 0xff000000) ^ (Te4[(s3 >> 16) & 0xff] & 0x00ff0000) ^ (Te4[(s0 >> 8) & 0xff] & 0x0000ff00) ^ (Te4[(s1 ) & 0xff] & 0x000000ff) ^ rk[2]; t3 = (Te4[(s3 >> 24) ] & 0xff000000) ^ (Te4[(s0 >> 16) & 0xff] & 0x00ff0000) ^ (Te4[(s1 >> 8) & 0xff] & 0x0000ff00) ^ (Te4[(s2 ) & 0xff] & 0x000000ff) ^ rk[3]; s0 = t0; s1 = t1; s2 = t2; s3 = t3; } PUTU32(block , s0); PUTU32(block + 4, s1); PUTU32(block + 8, s2); PUTU32(block + 12, s3); } void rijndaelDecryptRound(const u32 rk[/*4*(Nr + 1)*/], int Nr, u8 block[16], int rounds) { int r; u32 s0, s1, s2, s3, t0, t1, t2, t3; /* * map byte array block to cipher state * and add initial round key: */ s0 = GETU32(block ) ^ rk[0]; s1 = GETU32(block + 4) ^ rk[1]; s2 = GETU32(block + 8) ^ rk[2]; s3 = GETU32(block + 12) ^ rk[3]; rk += 4; /* * Nr - 1 full rounds: */ for (r = (rounds < Nr ? rounds : Nr) - 1; r > 0; r--) { t0 = Td0[(s0 >> 24) ] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[(s1 ) & 0xff] ^ rk[0]; t1 = Td0[(s1 >> 24) ] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[(s2 ) & 0xff] ^ rk[1]; t2 = Td0[(s2 >> 24) ] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[(s3 ) & 0xff] ^ rk[2]; t3 = Td0[(s3 >> 24) ] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[(s0 ) & 0xff] ^ rk[3]; s0 = t0; s1 = t1; s2 = t2; s3 = t3; rk += 4; } /* * complete the last round and * map cipher state to byte array block: */ t0 = (Td4[(s0 >> 24) ] & 0xff000000) ^ (Td4[(s3 >> 16) & 0xff] & 0x00ff0000) ^ (Td4[(s2 >> 8) & 0xff] & 0x0000ff00) ^ (Td4[(s1 ) & 0xff] & 0x000000ff); t1 = (Td4[(s1 >> 24) ] & 0xff000000) ^ (Td4[(s0 >> 16) & 0xff] & 0x00ff0000) ^ (Td4[(s3 >> 8) & 0xff] & 0x0000ff00) ^ (Td4[(s2 ) & 0xff] & 0x000000ff); t2 = (Td4[(s2 >> 24) ] & 0xff000000) ^ (Td4[(s1 >> 16) & 0xff] & 0x00ff0000) ^ (Td4[(s0 >> 8) & 0xff] & 0x0000ff00) ^ (Td4[(s3 ) & 0xff] & 0x000000ff); t3 = (Td4[(s3 >> 24) ] & 0xff000000) ^ (Td4[(s2 >> 16) & 0xff] & 0x00ff0000) ^ (Td4[(s1 >> 8) & 0xff] & 0x0000ff00) ^ (Td4[(s0 ) & 0xff] & 0x000000ff); if (rounds == Nr) { t0 ^= rk[0]; t1 ^= rk[1]; t2 ^= rk[2]; t3 ^= rk[3]; } PUTU32(block , t0); PUTU32(block + 4, t1); PUTU32(block + 8, t2); PUTU32(block + 12, t3); } #endif /* INTERMEDIATE_VALUE_KAT */ cryptokit-release119/src/rijndael-alg-fst.h000066400000000000000000000036531453705265000210600ustar00rootroot00000000000000/** * rijndael-alg-fst.h * * @version 3.0 (December 2000) * * Optimised ANSI C code for the Rijndael cipher (now AES) * * @author Vincent Rijmen * @author Antoon Bosselaers * @author Paulo Barreto * * This code is hereby placed in the public domain. * * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''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 AUTHORS 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 __RIJNDAEL_ALG_FST_H #define __RIJNDAEL_ALG_FST_H #define MAXKC (256/32) #define MAXKB (256/8) #define MAXNR 14 typedef unsigned char u8; typedef unsigned short u16; typedef unsigned int u32; int rijndaelKeySetupEnc(u32 rk[/*4*(Nr + 1)*/], const u8 cipherKey[], int keyBits); int rijndaelKeySetupDec(u32 rk[/*4*(Nr + 1)*/], const u8 cipherKey[], int keyBits); void rijndaelEncrypt(const u32 rk[/*4*(Nr + 1)*/], int Nr, const u8 pt[16], u8 ct[16]); void rijndaelDecrypt(const u32 rk[/*4*(Nr + 1)*/], int Nr, const u8 ct[16], u8 pt[16]); #ifdef INTERMEDIATE_VALUE_KAT void rijndaelEncryptRound(const u32 rk[/*4*(Nr + 1)*/], int Nr, u8 block[16], int rounds); void rijndaelDecryptRound(const u32 rk[/*4*(Nr + 1)*/], int Nr, u8 block[16], int rounds); #endif /* INTERMEDIATE_VALUE_KAT */ #endif /* __RIJNDAEL_ALG_FST_H */ cryptokit-release119/src/ripemd160.c000066400000000000000000000300431453705265000174300ustar00rootroot00000000000000/***********************************************************************/ /* */ /* The Cryptokit library */ /* */ /* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ /* */ /* Copyright 2005 Institut National de Recherche en Informatique et */ /* en Automatique. All rights reserved. This file is distributed */ /* under the terms of the GNU Library General Public License, with */ /* the special exception on linking described in file LICENSE. */ /* */ /***********************************************************************/ /* $Id$ */ /* RIPEMD160 hashing */ #include #include #include "ripemd160.h" /* Refs: - The reference implementation written by Antoon Bosselaers, available at http://www.esat.kuleuven.ac.be/~cosicart/ps/AB-9601/ - Handbook of Applied Cryptography, section 9.4.2, algorithm 9.55 */ /* Rotation n bits to the left */ #define ROL(x,n) (((x) << (n)) | ((x) >> (32-(n)))) /* The five basic functions */ #define F(x,y,z) ((x) ^ (y) ^ (z)) #define G(x,y,z) (((x) & (y)) | (~(x) & (z))) #define H(x,y,z) (((x) | ~(y)) ^ (z)) #define I(x,y,z) (((x) & (z)) | ((y) & ~(z))) #define J(x,y,z) ((x) ^ ((y) | ~(z))) /* The ten "steps" for the rounds */ #define FF(a, b, c, d, e, x, s) {\ (a) += F((b), (c), (d)) + (x);\ (a) = ROL((a), (s)) + (e);\ (c) = ROL((c), 10);\ } #define GG(a, b, c, d, e, x, s) {\ (a) += G((b), (c), (d)) + (x) + 0x5a827999U;\ (a) = ROL((a), (s)) + (e);\ (c) = ROL((c), 10);\ } #define HH(a, b, c, d, e, x, s) {\ (a) += H((b), (c), (d)) + (x) + 0x6ed9eba1U;\ (a) = ROL((a), (s)) + (e);\ (c) = ROL((c), 10);\ } #define II(a, b, c, d, e, x, s) {\ (a) += I((b), (c), (d)) + (x) + 0x8f1bbcdcU;\ (a) = ROL((a), (s)) + (e);\ (c) = ROL((c), 10);\ } #define JJ(a, b, c, d, e, x, s) {\ (a) += J((b), (c), (d)) + (x) + 0xa953fd4eU;\ (a) = ROL((a), (s)) + (e);\ (c) = ROL((c), 10);\ } #define FFF(a, b, c, d, e, x, s) {\ (a) += F((b), (c), (d)) + (x);\ (a) = ROL((a), (s)) + (e);\ (c) = ROL((c), 10);\ } #define GGG(a, b, c, d, e, x, s) {\ (a) += G((b), (c), (d)) + (x) + 0x7a6d76e9U;\ (a) = ROL((a), (s)) + (e);\ (c) = ROL((c), 10);\ } #define HHH(a, b, c, d, e, x, s) {\ (a) += H((b), (c), (d)) + (x) + 0x6d703ef3U;\ (a) = ROL((a), (s)) + (e);\ (c) = ROL((c), 10);\ } #define III(a, b, c, d, e, x, s) {\ (a) += I((b), (c), (d)) + (x) + 0x5c4dd124U;\ (a) = ROL((a), (s)) + (e);\ (c) = ROL((c), 10);\ } #define JJJ(a, b, c, d, e, x, s) {\ (a) += J((b), (c), (d)) + (x) + 0x50a28be6U;\ (a) = ROL((a), (s)) + (e);\ (c) = ROL((c), 10);\ } static void RIPEMD160_copy_and_swap(void * src, void * dst, int numwords) { #ifdef ARCH_BIG_ENDIAN unsigned char * s, * d; unsigned char a, b; for (s = src, d = dst; numwords > 0; s += 4, d += 4, numwords--) { a = s[0]; b = s[1]; d[0] = s[3]; d[1] = s[2]; d[2] = b; d[3] = a; } #else memcpy(dst, src, numwords * sizeof(u32)); #endif } static void RIPEMD160_compress(struct RIPEMD160Context * ctx) { register u32 a, b, c, d, e; u32 aa, bb, cc, dd, ee; u32 data[16]; /* Convert buffer data to 16 little-endian integers */ RIPEMD160_copy_and_swap(ctx->buffer, data, 16); /* Perform "left" rounds */ a = ctx->state[0]; b = ctx->state[1]; c = ctx->state[2]; d = ctx->state[3]; e = ctx->state[4]; /* left round 1 */ FF(a, b, c, d, e, data[ 0], 11); FF(e, a, b, c, d, data[ 1], 14); FF(d, e, a, b, c, data[ 2], 15); FF(c, d, e, a, b, data[ 3], 12); FF(b, c, d, e, a, data[ 4], 5); FF(a, b, c, d, e, data[ 5], 8); FF(e, a, b, c, d, data[ 6], 7); FF(d, e, a, b, c, data[ 7], 9); FF(c, d, e, a, b, data[ 8], 11); FF(b, c, d, e, a, data[ 9], 13); FF(a, b, c, d, e, data[10], 14); FF(e, a, b, c, d, data[11], 15); FF(d, e, a, b, c, data[12], 6); FF(c, d, e, a, b, data[13], 7); FF(b, c, d, e, a, data[14], 9); FF(a, b, c, d, e, data[15], 8); /* left round 2 */ GG(e, a, b, c, d, data[ 7], 7); GG(d, e, a, b, c, data[ 4], 6); GG(c, d, e, a, b, data[13], 8); GG(b, c, d, e, a, data[ 1], 13); GG(a, b, c, d, e, data[10], 11); GG(e, a, b, c, d, data[ 6], 9); GG(d, e, a, b, c, data[15], 7); GG(c, d, e, a, b, data[ 3], 15); GG(b, c, d, e, a, data[12], 7); GG(a, b, c, d, e, data[ 0], 12); GG(e, a, b, c, d, data[ 9], 15); GG(d, e, a, b, c, data[ 5], 9); GG(c, d, e, a, b, data[ 2], 11); GG(b, c, d, e, a, data[14], 7); GG(a, b, c, d, e, data[11], 13); GG(e, a, b, c, d, data[ 8], 12); /* left round 3 */ HH(d, e, a, b, c, data[ 3], 11); HH(c, d, e, a, b, data[10], 13); HH(b, c, d, e, a, data[14], 6); HH(a, b, c, d, e, data[ 4], 7); HH(e, a, b, c, d, data[ 9], 14); HH(d, e, a, b, c, data[15], 9); HH(c, d, e, a, b, data[ 8], 13); HH(b, c, d, e, a, data[ 1], 15); HH(a, b, c, d, e, data[ 2], 14); HH(e, a, b, c, d, data[ 7], 8); HH(d, e, a, b, c, data[ 0], 13); HH(c, d, e, a, b, data[ 6], 6); HH(b, c, d, e, a, data[13], 5); HH(a, b, c, d, e, data[11], 12); HH(e, a, b, c, d, data[ 5], 7); HH(d, e, a, b, c, data[12], 5); /* left round 4 */ II(c, d, e, a, b, data[ 1], 11); II(b, c, d, e, a, data[ 9], 12); II(a, b, c, d, e, data[11], 14); II(e, a, b, c, d, data[10], 15); II(d, e, a, b, c, data[ 0], 14); II(c, d, e, a, b, data[ 8], 15); II(b, c, d, e, a, data[12], 9); II(a, b, c, d, e, data[ 4], 8); II(e, a, b, c, d, data[13], 9); II(d, e, a, b, c, data[ 3], 14); II(c, d, e, a, b, data[ 7], 5); II(b, c, d, e, a, data[15], 6); II(a, b, c, d, e, data[14], 8); II(e, a, b, c, d, data[ 5], 6); II(d, e, a, b, c, data[ 6], 5); II(c, d, e, a, b, data[ 2], 12); /* left round 5 */ JJ(b, c, d, e, a, data[ 4], 9); JJ(a, b, c, d, e, data[ 0], 15); JJ(e, a, b, c, d, data[ 5], 5); JJ(d, e, a, b, c, data[ 9], 11); JJ(c, d, e, a, b, data[ 7], 6); JJ(b, c, d, e, a, data[12], 8); JJ(a, b, c, d, e, data[ 2], 13); JJ(e, a, b, c, d, data[10], 12); JJ(d, e, a, b, c, data[14], 5); JJ(c, d, e, a, b, data[ 1], 12); JJ(b, c, d, e, a, data[ 3], 13); JJ(a, b, c, d, e, data[ 8], 14); JJ(e, a, b, c, d, data[11], 11); JJ(d, e, a, b, c, data[ 6], 8); JJ(c, d, e, a, b, data[15], 5); JJ(b, c, d, e, a, data[13], 6); /* Save result of left rounds */ aa = a; bb = b; cc = c; dd = d; ee = e; /* Perform "right" rounds */ a = ctx->state[0]; b = ctx->state[1]; c = ctx->state[2]; d = ctx->state[3]; e = ctx->state[4]; /* right round 1 */ JJJ(a, b, c, d, e, data[ 5], 8); JJJ(e, a, b, c, d, data[14], 9); JJJ(d, e, a, b, c, data[ 7], 9); JJJ(c, d, e, a, b, data[ 0], 11); JJJ(b, c, d, e, a, data[ 9], 13); JJJ(a, b, c, d, e, data[ 2], 15); JJJ(e, a, b, c, d, data[11], 15); JJJ(d, e, a, b, c, data[ 4], 5); JJJ(c, d, e, a, b, data[13], 7); JJJ(b, c, d, e, a, data[ 6], 7); JJJ(a, b, c, d, e, data[15], 8); JJJ(e, a, b, c, d, data[ 8], 11); JJJ(d, e, a, b, c, data[ 1], 14); JJJ(c, d, e, a, b, data[10], 14); JJJ(b, c, d, e, a, data[ 3], 12); JJJ(a, b, c, d, e, data[12], 6); /* right round 2 */ III(e, a, b, c, d, data[ 6], 9); III(d, e, a, b, c, data[11], 13); III(c, d, e, a, b, data[ 3], 15); III(b, c, d, e, a, data[ 7], 7); III(a, b, c, d, e, data[ 0], 12); III(e, a, b, c, d, data[13], 8); III(d, e, a, b, c, data[ 5], 9); III(c, d, e, a, b, data[10], 11); III(b, c, d, e, a, data[14], 7); III(a, b, c, d, e, data[15], 7); III(e, a, b, c, d, data[ 8], 12); III(d, e, a, b, c, data[12], 7); III(c, d, e, a, b, data[ 4], 6); III(b, c, d, e, a, data[ 9], 15); III(a, b, c, d, e, data[ 1], 13); III(e, a, b, c, d, data[ 2], 11); /* right round 3 */ HHH(d, e, a, b, c, data[15], 9); HHH(c, d, e, a, b, data[ 5], 7); HHH(b, c, d, e, a, data[ 1], 15); HHH(a, b, c, d, e, data[ 3], 11); HHH(e, a, b, c, d, data[ 7], 8); HHH(d, e, a, b, c, data[14], 6); HHH(c, d, e, a, b, data[ 6], 6); HHH(b, c, d, e, a, data[ 9], 14); HHH(a, b, c, d, e, data[11], 12); HHH(e, a, b, c, d, data[ 8], 13); HHH(d, e, a, b, c, data[12], 5); HHH(c, d, e, a, b, data[ 2], 14); HHH(b, c, d, e, a, data[10], 13); HHH(a, b, c, d, e, data[ 0], 13); HHH(e, a, b, c, d, data[ 4], 7); HHH(d, e, a, b, c, data[13], 5); /* right round 4 */ GGG(c, d, e, a, b, data[ 8], 15); GGG(b, c, d, e, a, data[ 6], 5); GGG(a, b, c, d, e, data[ 4], 8); GGG(e, a, b, c, d, data[ 1], 11); GGG(d, e, a, b, c, data[ 3], 14); GGG(c, d, e, a, b, data[11], 14); GGG(b, c, d, e, a, data[15], 6); GGG(a, b, c, d, e, data[ 0], 14); GGG(e, a, b, c, d, data[ 5], 6); GGG(d, e, a, b, c, data[12], 9); GGG(c, d, e, a, b, data[ 2], 12); GGG(b, c, d, e, a, data[13], 9); GGG(a, b, c, d, e, data[ 9], 12); GGG(e, a, b, c, d, data[ 7], 5); GGG(d, e, a, b, c, data[10], 15); GGG(c, d, e, a, b, data[14], 8); /* right round 5 */ FFF(b, c, d, e, a, data[12] , 8); FFF(a, b, c, d, e, data[15] , 5); FFF(e, a, b, c, d, data[10] , 12); FFF(d, e, a, b, c, data[ 4] , 9); FFF(c, d, e, a, b, data[ 1] , 12); FFF(b, c, d, e, a, data[ 5] , 5); FFF(a, b, c, d, e, data[ 8] , 14); FFF(e, a, b, c, d, data[ 7] , 6); FFF(d, e, a, b, c, data[ 6] , 8); FFF(c, d, e, a, b, data[ 2] , 13); FFF(b, c, d, e, a, data[13] , 6); FFF(a, b, c, d, e, data[14] , 5); FFF(e, a, b, c, d, data[ 0] , 15); FFF(d, e, a, b, c, data[ 3] , 13); FFF(c, d, e, a, b, data[ 9] , 11); FFF(b, c, d, e, a, data[11] , 11); /* Update chaining values */ d += cc + ctx->state[1]; ctx->state[1] = ctx->state[2] + dd + e; ctx->state[2] = ctx->state[3] + ee + a; ctx->state[3] = ctx->state[4] + aa + b; ctx->state[4] = ctx->state[0] + bb + c; ctx->state[0] = d; } void RIPEMD160_init(struct RIPEMD160Context * ctx) { ctx->state[0] = 0x67452301U; ctx->state[1] = 0xEFCDAB89U; ctx->state[2] = 0x98BADCFEU; ctx->state[3] = 0x10325476U; ctx->state[4] = 0xC3D2E1F0U; ctx->numbytes = 0; ctx->length[0] = 0; ctx->length[1] = 0; } void RIPEMD160_add_data(struct RIPEMD160Context * ctx, unsigned char * data, unsigned long len) { u32 t; /* Update length */ t = ctx->length[0]; if ((ctx->length[0] = t + (u32) (len << 3)) < t) ctx->length[1]++; /* carry from low 32 bits to high 32 bits */ ctx->length[1] += (u32) (len >> 29); /* If data was left in buffer, pad it with fresh data and munge block */ if (ctx->numbytes != 0) { t = 64 - ctx->numbytes; if (len < t) { memcpy(ctx->buffer + ctx->numbytes, data, len); ctx->numbytes += len; return; } memcpy(ctx->buffer + ctx->numbytes, data, t); RIPEMD160_compress(ctx); data += t; len -= t; } /* Munge data in 64-byte chunks */ while (len >= 64) { memcpy(ctx->buffer, data, 64); RIPEMD160_compress(ctx); data += 64; len -= 64; } /* Save remaining data */ memcpy(ctx->buffer, data, len); ctx->numbytes = len; } void RIPEMD160_finish(struct RIPEMD160Context * ctx, unsigned char output[20]) { int i = ctx->numbytes; /* Set first char of padding to 0x80. There is always room. */ ctx->buffer[i++] = 0x80; /* If we do not have room for the length (8 bytes), pad to 64 bytes with zeroes and munge the data block */ if (i > 56) { memset(ctx->buffer + i, 0, 64 - i); RIPEMD160_compress(ctx); i = 0; } /* Pad to byte 56 with zeroes */ memset(ctx->buffer + i, 0, 56 - i); /* Add length in little-endian */ RIPEMD160_copy_and_swap(ctx->length, ctx->buffer + 56, 2); /* Munge the final block */ RIPEMD160_compress(ctx); /* Final hash value is in ctx->state modulo little-endian conversion */ RIPEMD160_copy_and_swap(ctx->state, output, 5); } cryptokit-release119/src/ripemd160.h000066400000000000000000000025731453705265000174440ustar00rootroot00000000000000/***********************************************************************/ /* */ /* The Cryptokit library */ /* */ /* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ /* */ /* Copyright 2005 Institut National de Recherche en Informatique et */ /* en Automatique. All rights reserved. This file is distributed */ /* under the terms of the GNU Library General Public License, with */ /* the special exception on linking described in file LICENSE. */ /* */ /***********************************************************************/ /* $Id$ */ /* RIPEMD160 hashing */ typedef unsigned int u32; struct RIPEMD160Context { u32 state[5]; u32 length[2]; int numbytes; unsigned char buffer[64]; }; extern void RIPEMD160_init(struct RIPEMD160Context * ctx); extern void RIPEMD160_add_data(struct RIPEMD160Context * ctx, unsigned char * data, unsigned long len); extern void RIPEMD160_finish(struct RIPEMD160Context * ctx, unsigned char output[20]); cryptokit-release119/src/sha1.c000066400000000000000000000114361453705265000165620ustar00rootroot00000000000000/***********************************************************************/ /* */ /* The Cryptokit library */ /* */ /* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ /* */ /* Copyright 2002 Institut National de Recherche en Informatique et */ /* en Automatique. All rights reserved. This file is distributed */ /* under the terms of the GNU Library General Public License, with */ /* the special exception on linking described in file LICENSE. */ /* */ /***********************************************************************/ /* $Id$ */ /* SHA-1 hashing */ #include #include #include "sha1.h" /* Ref: Handbook of Applied Cryptography, section 9.4.2, algorithm 9.53 */ #define rol1(x) (((x) << 1) | ((x) >> 31)) #define rol5(x) (((x) << 5) | ((x) >> 27)) #define rol30(x) (((x) << 30) | ((x) >> 2)) static void SHA1_copy_and_swap(void * src, void * dst, int numwords) { #ifdef ARCH_BIG_ENDIAN memcpy(dst, src, numwords * sizeof(u32)); #else unsigned char * s, * d; unsigned char a, b; for (s = src, d = dst; numwords > 0; s += 4, d += 4, numwords--) { a = s[0]; b = s[1]; d[0] = s[3]; d[1] = s[2]; d[2] = b; d[3] = a; } #endif } #define F(x,y,z) ( z ^ (x & (y ^ z) ) ) #define G(x,y,z) ( (x & y) | (z & (x | y) ) ) #define H(x,y,z) ( x ^ y ^ z ) #define Y1 0x5A827999U #define Y2 0x6ED9EBA1U #define Y3 0x8F1BBCDCU #define Y4 0xCA62C1D6U static void SHA1_transform(struct SHA1Context * ctx) { int i; register u32 a, b, c, d, e, t; u32 data[80]; /* Convert buffer data to 16 big-endian integers */ SHA1_copy_and_swap(ctx->buffer, data, 16); /* Expand into 80 integers */ for (i = 16; i < 80; i++) { t = data[i-3] ^ data[i-8] ^ data[i-14] ^ data[i-16]; data[i] = rol1(t); } /* Initialize working variables */ a = ctx->state[0]; b = ctx->state[1]; c = ctx->state[2]; d = ctx->state[3]; e = ctx->state[4]; /* Perform rounds */ for (i = 0; i < 20; i++) { t = F(b, c, d) + Y1 + rol5(a) + e + data[i]; e = d; d = c; c = rol30(b); b = a; a = t; } for (/*nothing*/; i < 40; i++) { t = H(b, c, d) + Y2 + rol5(a) + e + data[i]; e = d; d = c; c = rol30(b); b = a; a = t; } for (/*nothing*/; i < 60; i++) { t = G(b, c, d) + Y3 + rol5(a) + e + data[i]; e = d; d = c; c = rol30(b); b = a; a = t; } for (/*nothing*/; i < 80; i++) { t = H(b, c, d) + Y4 + rol5(a) + e + data[i]; e = d; d = c; c = rol30(b); b = a; a = t; } /* Update chaining values */ ctx->state[0] += a; ctx->state[1] += b; ctx->state[2] += c; ctx->state[3] += d; ctx->state[4] += e; } void SHA1_init(struct SHA1Context * ctx) { ctx->state[0] = 0x67452301U; ctx->state[1] = 0xEFCDAB89U; ctx->state[2] = 0x98BADCFEU; ctx->state[3] = 0x10325476U; ctx->state[4] = 0xC3D2E1F0U; ctx->numbytes = 0; ctx->length[0] = 0; ctx->length[1] = 0; } void SHA1_add_data(struct SHA1Context * ctx, unsigned char * data, unsigned long len) { u32 t; /* Update length */ t = ctx->length[1]; if ((ctx->length[1] = t + (u32) (len << 3)) < t) ctx->length[0]++; /* carry from low 32 bits to high 32 bits */ ctx->length[0] += (u32) (len >> 29); /* If data was left in buffer, pad it with fresh data and munge block */ if (ctx->numbytes != 0) { t = 64 - ctx->numbytes; if (len < t) { memcpy(ctx->buffer + ctx->numbytes, data, len); ctx->numbytes += len; return; } memcpy(ctx->buffer + ctx->numbytes, data, t); SHA1_transform(ctx); data += t; len -= t; } /* Munge data in 64-byte chunks */ while (len >= 64) { memcpy(ctx->buffer, data, 64); SHA1_transform(ctx); data += 64; len -= 64; } /* Save remaining data */ memcpy(ctx->buffer, data, len); ctx->numbytes = len; } void SHA1_finish(struct SHA1Context * ctx, unsigned char output[20]) { int i = ctx->numbytes; /* Set first char of padding to 0x80. There is always room. */ ctx->buffer[i++] = 0x80; /* If we do not have room for the length (8 bytes), pad to 64 bytes with zeroes and munge the data block */ if (i > 56) { memset(ctx->buffer + i, 0, 64 - i); SHA1_transform(ctx); i = 0; } /* Pad to byte 56 with zeroes */ memset(ctx->buffer + i, 0, 56 - i); /* Add length in big-endian */ SHA1_copy_and_swap(ctx->length, ctx->buffer + 56, 2); /* Munge the final block */ SHA1_transform(ctx); /* Final hash value is in ctx->state modulo big-endian conversion */ SHA1_copy_and_swap(ctx->state, output, 5); } cryptokit-release119/src/sha1.h000066400000000000000000000024211453705265000165610ustar00rootroot00000000000000/***********************************************************************/ /* */ /* The Cryptokit library */ /* */ /* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ /* */ /* Copyright 2002 Institut National de Recherche en Informatique et */ /* en Automatique. All rights reserved. This file is distributed */ /* under the terms of the GNU Library General Public License, with */ /* the special exception on linking described in file LICENSE. */ /* */ /***********************************************************************/ /* $Id$ */ /* SHA-1 hashing */ typedef unsigned int u32; struct SHA1Context { u32 state[5]; u32 length[2]; int numbytes; unsigned char buffer[64]; }; extern void SHA1_init(struct SHA1Context * ctx); extern void SHA1_add_data(struct SHA1Context * ctx, unsigned char * data, unsigned long len); extern void SHA1_finish(struct SHA1Context * ctx, unsigned char output[20]); cryptokit-release119/src/sha256.c000066400000000000000000000153231453705265000167350ustar00rootroot00000000000000/***********************************************************************/ /* */ /* The Cryptokit library */ /* */ /* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ /* */ /* Copyright 2004 Institut National de Recherche en Informatique et */ /* en Automatique. All rights reserved. This file is distributed */ /* under the terms of the GNU Library General Public License, with */ /* the special exception on linking described in file LICENSE. */ /* */ /***********************************************************************/ /* $Id$ */ /* SHA-256 hashing */ #include #include #include "sha256.h" /* Ref: FIPS publication 180-2 */ #define ROTR(x,n) ((x) >> (n) | (x) << (32 - (n))) #define CH(x,y,z) (z ^ (x & (y ^ z))) #define MAJ(x,y,z) ((x & y) | (z & (x | y))) #define SIGMA0(x) (ROTR(x,2) ^ ROTR(x,13) ^ ROTR(x,22)) #define SIGMA1(x) (ROTR(x,6) ^ ROTR(x,11) ^ ROTR(x,25)) #define sigma0(x) (ROTR(x,7) ^ ROTR(x,18) ^ (x >> 3)) #define sigma1(x) (ROTR(x,17) ^ ROTR(x,19) ^ (x >> 10)) static void SHA256_copy_and_swap(void * src, void * dst, int numwords) { #ifdef ARCH_BIG_ENDIAN memcpy(dst, src, numwords * sizeof(u32)); #else unsigned char * s, * d; unsigned char a, b; for (s = src, d = dst; numwords > 0; s += 4, d += 4, numwords--) { a = s[0]; b = s[1]; d[0] = s[3]; d[1] = s[2]; d[2] = b; d[3] = a; } #endif } static u32 SHA256_constants[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 }; static void SHA256_transform(struct SHA256Context * ctx) { int i; register u32 a, b, c, d, e, f, g, h, t1, t2; u32 data[80]; /* Convert buffer data to 16 big-endian integers */ SHA256_copy_and_swap(ctx->buffer, data, 16); /* Expand into 80 integers */ for (i = 16; i < 80; i++) { data[i] = sigma1(data[i-2]) + data[i-7] + sigma0(data[i-15]) + data[i-16]; } /* Initialize working variables */ a = ctx->state[0]; b = ctx->state[1]; c = ctx->state[2]; d = ctx->state[3]; e = ctx->state[4]; f = ctx->state[5]; g = ctx->state[6]; h = ctx->state[7]; /* Perform rounds */ #if 0 for (i = 0; i < 64; i++) { t1 = h + SIGMA1(e) + CH(e, f, g) + SHA256_constants[i] + data[i]; t2 = SIGMA0(a) + MAJ(a, b, c); h = g; g = f; f = e; e = d + t1; d = c; c = b; b = a; a = t1 + t2; } #else #define STEP(a,b,c,d,e,f,g,h,i) \ t1 = h + SIGMA1(e) + CH(e, f, g) + SHA256_constants[i] + data[i]; \ t2 = SIGMA0(a) + MAJ(a, b, c); \ d = d + t1; \ h = t1 + t2 for (i = 0; i < 64; i += 8) { STEP(a,b,c,d,e,f,g,h,i); STEP(h,a,b,c,d,e,f,g,i+1); STEP(g,h,a,b,c,d,e,f,i+2); STEP(f,g,h,a,b,c,d,e,i+3); STEP(e,f,g,h,a,b,c,d,i+4); STEP(d,e,f,g,h,a,b,c,i+5); STEP(c,d,e,f,g,h,a,b,i+6); STEP(b,c,d,e,f,g,h,a,i+7); } #endif /* Update chaining values */ ctx->state[0] += a; ctx->state[1] += b; ctx->state[2] += c; ctx->state[3] += d; ctx->state[4] += e; ctx->state[5] += f; ctx->state[6] += g; ctx->state[7] += h; } void SHA256_init(struct SHA256Context * ctx, int bitsize) { switch (bitsize) { case 224: ctx->state[0] = 0xc1059ed8; ctx->state[1] = 0x367cd507; ctx->state[2] = 0x3070dd17; ctx->state[3] = 0xf70e5939; ctx->state[4] = 0xffc00b31; ctx->state[5] = 0x68581511; ctx->state[6] = 0x64f98fa7; ctx->state[7] = 0xbefa4fa4; break; case 256: ctx->state[0] = 0x6A09E667; ctx->state[1] = 0xBB67AE85; ctx->state[2] = 0x3C6EF372; ctx->state[3] = 0xA54FF53A; ctx->state[4] = 0x510E527F; ctx->state[5] = 0x9B05688C; ctx->state[6] = 0x1F83D9AB; ctx->state[7] = 0x5BE0CD19; break; default: /* The bit size is wrong. Just zero the state to produce incorrect hashes. */ memset(ctx->state, 0, sizeof(ctx->state)); break; } ctx->numbytes = 0; ctx->length[0] = 0; ctx->length[1] = 0; } void SHA256_add_data(struct SHA256Context * ctx, unsigned char * data, unsigned long len) { u32 t; /* Update length */ t = ctx->length[1]; if ((ctx->length[1] = t + (u32) (len << 3)) < t) ctx->length[0]++; /* carry from low 32 bits to high 32 bits */ ctx->length[0] += (u32) (len >> 29); /* If data was left in buffer, pad it with fresh data and munge block */ if (ctx->numbytes != 0) { t = 64 - ctx->numbytes; if (len < t) { memcpy(ctx->buffer + ctx->numbytes, data, len); ctx->numbytes += len; return; } memcpy(ctx->buffer + ctx->numbytes, data, t); SHA256_transform(ctx); data += t; len -= t; } /* Munge data in 64-byte chunks */ while (len >= 64) { memcpy(ctx->buffer, data, 64); SHA256_transform(ctx); data += 64; len -= 64; } /* Save remaining data */ memcpy(ctx->buffer, data, len); ctx->numbytes = len; } void SHA256_finish(struct SHA256Context * ctx, int bitsize, unsigned char * output) { int i = ctx->numbytes; /* Set first char of padding to 0x80. There is always room. */ ctx->buffer[i++] = 0x80; /* If we do not have room for the length (8 bytes), pad to 64 bytes with zeroes and munge the data block */ if (i > 56) { memset(ctx->buffer + i, 0, 64 - i); SHA256_transform(ctx); i = 0; } /* Pad to byte 56 with zeroes */ memset(ctx->buffer + i, 0, 56 - i); /* Add length in big-endian */ SHA256_copy_and_swap(ctx->length, ctx->buffer + 56, 2); /* Munge the final block */ SHA256_transform(ctx); /* Final hash value is in ctx->state modulo big-endian conversion */ switch (bitsize) { case 256: SHA256_copy_and_swap(ctx->state, output, 8); break; case 224: SHA256_copy_and_swap(ctx->state, output, 7); break; /* default: The bit size is wrong. Produce no output. */ } } cryptokit-release119/src/sha256.h000066400000000000000000000026701453705265000167430ustar00rootroot00000000000000/***********************************************************************/ /* */ /* The Cryptokit library */ /* */ /* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ /* */ /* Copyright 2002 Institut National de Recherche en Informatique et */ /* en Automatique. All rights reserved. This file is distributed */ /* under the terms of the GNU Library General Public License, with */ /* the special exception on linking described in file LICENSE. */ /* */ /***********************************************************************/ /* $Id$ */ /* SHA-256 hashing */ #ifndef _MSC_VER #include typedef uint32_t u32; #else typedef unsigned int u32; #endif struct SHA256Context { u32 state[8]; u32 length[2]; int numbytes; unsigned char buffer[64]; }; extern void SHA256_init(struct SHA256Context * ctx, int bitsize); extern void SHA256_add_data(struct SHA256Context * ctx, unsigned char * data, unsigned long len); extern void SHA256_finish(struct SHA256Context * ctx, int bitsize, unsigned char * output); cryptokit-release119/src/sha512.c000066400000000000000000000215561453705265000167350ustar00rootroot00000000000000/***********************************************************************/ /* */ /* The Cryptokit library */ /* */ /* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ /* */ /* Copyright 2015 Institut National de Recherche en Informatique et */ /* en Automatique. All rights reserved. This file is distributed */ /* under the terms of the GNU Library General Public License, with */ /* the special exception on linking described in file LICENSE. */ /* */ /***********************************************************************/ /* $Id: sha256.c 53 2010-08-30 10:53:00Z gildor-admin $ */ /* SHA-512 hashing */ #include #include #include "sha512.h" /* Ref: FIPS publication 180-2 */ #define ROTR(x,n) ((x) >> (n) | (x) << (64 - (n))) #define CH(x,y,z) (z ^ (x & (y ^ z))) #define MAJ(x,y,z) ((x & y) | (z & (x | y))) #define SIGMA0(x) (ROTR(x,28) ^ ROTR(x,34) ^ ROTR(x,39)) #define SIGMA1(x) (ROTR(x,14) ^ ROTR(x,18) ^ ROTR(x,41)) #define sigma0(x) (ROTR(x,1) ^ ROTR(x,8) ^ (x >> 7)) #define sigma1(x) (ROTR(x,19) ^ ROTR(x,61) ^ (x >> 6)) static void SHA512_copy_and_swap(void * src, void * dst, int numwords) { #ifdef ARCH_BIG_ENDIAN memcpy(dst, src, numwords * 8); #else unsigned char * s, * d; unsigned char a, b; for (s = src, d = dst; numwords > 0; s += 8, d += 8, numwords--) { a = s[0]; b = s[1]; d[0] = s[7]; d[1] = s[6]; d[6] = b; d[7] = a; a = s[2]; b = s[3]; d[2] = s[5]; d[3] = s[4]; d[4] = b; d[5] = a; } #endif } static u64 SHA512_constants[80] = { UINT64_C(0x428a2f98d728ae22), UINT64_C(0x7137449123ef65cd), UINT64_C(0xb5c0fbcfec4d3b2f), UINT64_C(0xe9b5dba58189dbbc), UINT64_C(0x3956c25bf348b538), UINT64_C(0x59f111f1b605d019), UINT64_C(0x923f82a4af194f9b), UINT64_C(0xab1c5ed5da6d8118), UINT64_C(0xd807aa98a3030242), UINT64_C(0x12835b0145706fbe), UINT64_C(0x243185be4ee4b28c), UINT64_C(0x550c7dc3d5ffb4e2), UINT64_C(0x72be5d74f27b896f), UINT64_C(0x80deb1fe3b1696b1), UINT64_C(0x9bdc06a725c71235), UINT64_C(0xc19bf174cf692694), UINT64_C(0xe49b69c19ef14ad2), UINT64_C(0xefbe4786384f25e3), UINT64_C(0x0fc19dc68b8cd5b5), UINT64_C(0x240ca1cc77ac9c65), UINT64_C(0x2de92c6f592b0275), UINT64_C(0x4a7484aa6ea6e483), UINT64_C(0x5cb0a9dcbd41fbd4), UINT64_C(0x76f988da831153b5), UINT64_C(0x983e5152ee66dfab), UINT64_C(0xa831c66d2db43210), UINT64_C(0xb00327c898fb213f), UINT64_C(0xbf597fc7beef0ee4), UINT64_C(0xc6e00bf33da88fc2), UINT64_C(0xd5a79147930aa725), UINT64_C(0x06ca6351e003826f), UINT64_C(0x142929670a0e6e70), UINT64_C(0x27b70a8546d22ffc), UINT64_C(0x2e1b21385c26c926), UINT64_C(0x4d2c6dfc5ac42aed), UINT64_C(0x53380d139d95b3df), UINT64_C(0x650a73548baf63de), UINT64_C(0x766a0abb3c77b2a8), UINT64_C(0x81c2c92e47edaee6), UINT64_C(0x92722c851482353b), UINT64_C(0xa2bfe8a14cf10364), UINT64_C(0xa81a664bbc423001), UINT64_C(0xc24b8b70d0f89791), UINT64_C(0xc76c51a30654be30), UINT64_C(0xd192e819d6ef5218), UINT64_C(0xd69906245565a910), UINT64_C(0xf40e35855771202a), UINT64_C(0x106aa07032bbd1b8), UINT64_C(0x19a4c116b8d2d0c8), UINT64_C(0x1e376c085141ab53), UINT64_C(0x2748774cdf8eeb99), UINT64_C(0x34b0bcb5e19b48a8), UINT64_C(0x391c0cb3c5c95a63), UINT64_C(0x4ed8aa4ae3418acb), UINT64_C(0x5b9cca4f7763e373), UINT64_C(0x682e6ff3d6b2b8a3), UINT64_C(0x748f82ee5defb2fc), UINT64_C(0x78a5636f43172f60), UINT64_C(0x84c87814a1f0ab72), UINT64_C(0x8cc702081a6439ec), UINT64_C(0x90befffa23631e28), UINT64_C(0xa4506cebde82bde9), UINT64_C(0xbef9a3f7b2c67915), UINT64_C(0xc67178f2e372532b), UINT64_C(0xca273eceea26619c), UINT64_C(0xd186b8c721c0c207), UINT64_C(0xeada7dd6cde0eb1e), UINT64_C(0xf57d4f7fee6ed178), UINT64_C(0x06f067aa72176fba), UINT64_C(0x0a637dc5a2c898a6), UINT64_C(0x113f9804bef90dae), UINT64_C(0x1b710b35131c471b), UINT64_C(0x28db77f523047d84), UINT64_C(0x32caab7b40c72493), UINT64_C(0x3c9ebe0a15c9bebc), UINT64_C(0x431d67c49c100d4c), UINT64_C(0x4cc5d4becb3e42b6), UINT64_C(0x597f299cfc657e2a), UINT64_C(0x5fcb6fab3ad6faec), UINT64_C(0x6c44198c4a475817) }; static void SHA512_transform(struct SHA512Context * ctx) { int i; register u64 a, b, c, d, e, f, g, h, t1, t2; u64 data[80]; /* Convert buffer data to 16 big-endian integers */ SHA512_copy_and_swap(ctx->buffer, data, 16); /* Expand into 80 integers */ for (i = 16; i < 80; i++) { data[i] = sigma1(data[i-2]) + data[i-7] + sigma0(data[i-15]) + data[i-16]; } /* Initialize working variables */ a = ctx->state[0]; b = ctx->state[1]; c = ctx->state[2]; d = ctx->state[3]; e = ctx->state[4]; f = ctx->state[5]; g = ctx->state[6]; h = ctx->state[7]; /* Perform rounds */ #if 0 for (i = 0; i < 80; i++) { t1 = h + SIGMA1(e) + CH(e, f, g) + SHA512_constants[i] + data[i]; t2 = SIGMA0(a) + MAJ(a, b, c); h = g; g = f; f = e; e = d + t1; d = c; c = b; b = a; a = t1 + t2; } #else #define STEP(a,b,c,d,e,f,g,h,i) \ t1 = h + SIGMA1(e) + CH(e, f, g) + SHA512_constants[i] + data[i]; \ t2 = SIGMA0(a) + MAJ(a, b, c); \ d = d + t1; \ h = t1 + t2 for (i = 0; i < 80; i += 8) { STEP(a,b,c,d,e,f,g,h,i); STEP(h,a,b,c,d,e,f,g,i+1); STEP(g,h,a,b,c,d,e,f,i+2); STEP(f,g,h,a,b,c,d,e,i+3); STEP(e,f,g,h,a,b,c,d,i+4); STEP(d,e,f,g,h,a,b,c,i+5); STEP(c,d,e,f,g,h,a,b,i+6); STEP(b,c,d,e,f,g,h,a,i+7); } #endif /* Update chaining values */ ctx->state[0] += a; ctx->state[1] += b; ctx->state[2] += c; ctx->state[3] += d; ctx->state[4] += e; ctx->state[5] += f; ctx->state[6] += g; ctx->state[7] += h; } void SHA512_init(struct SHA512Context * ctx, int bitsize) { switch (bitsize) { case 512: ctx->state[0] = UINT64_C(0x6a09e667f3bcc908); ctx->state[1] = UINT64_C(0xbb67ae8584caa73b); ctx->state[2] = UINT64_C(0x3c6ef372fe94f82b); ctx->state[3] = UINT64_C(0xa54ff53a5f1d36f1 ); ctx->state[4] = UINT64_C(0x510e527fade682d1); ctx->state[5] = UINT64_C(0x9b05688c2b3e6c1f); ctx->state[6] = UINT64_C(0x1f83d9abfb41bd6b); ctx->state[7] = UINT64_C(0x5be0cd19137e2179); break; case 384: ctx->state[0] = UINT64_C(0xcbbb9d5dc1059ed8); ctx->state[1] = UINT64_C(0x629a292a367cd507); ctx->state[2] = UINT64_C(0x9159015a3070dd17); ctx->state[3] = UINT64_C(0x152fecd8f70e5939 ); ctx->state[4] = UINT64_C(0x67332667ffc00b31); ctx->state[5] = UINT64_C(0x8eb44a8768581511); ctx->state[6] = UINT64_C(0xdb0c2e0d64f98fa7); ctx->state[7] = UINT64_C(0x47b5481dbefa4fa4); break; default: /* The bit size is wrong. Just zero the state to produce incorrect hashes. */ memset(ctx->state, 0, sizeof(ctx->state)); break; } ctx->numbytes = 0; ctx->length[0] = 0; ctx->length[1] = 0; } void SHA512_add_data(struct SHA512Context * ctx, unsigned char * data, unsigned long len) { u64 t; /* Update length */ t = ctx->length[1]; if ((ctx->length[1] = t + (u64) (len << 3)) < t) ctx->length[0]++; /* carry from low 64 bits to high 64 bits */ ctx->length[0] += (u64) len >> 61; /* If data was left in buffer, pad it with fresh data and munge block */ if (ctx->numbytes != 0) { unsigned long l = 128 - ctx->numbytes; if (len < l) { memcpy(ctx->buffer + ctx->numbytes, data, len); ctx->numbytes += len; return; } memcpy(ctx->buffer + ctx->numbytes, data, l); SHA512_transform(ctx); data += l; len -= l; } /* Munge data in 128-byte chunks */ while (len >= 128) { memcpy(ctx->buffer, data, 128); SHA512_transform(ctx); data += 128; len -= 128; } /* Save remaining data */ memcpy(ctx->buffer, data, len); ctx->numbytes = len; } void SHA512_finish(struct SHA512Context * ctx, int bitsize, unsigned char * output) { int i = ctx->numbytes; /* Set first char of padding to 0x80. There is always room. */ ctx->buffer[i++] = 0x80; /* If we do not have room for the length (8 bytes), pad to 64 bytes with zeroes and munge the data block */ if (i > 112) { memset(ctx->buffer + i, 0, 128 - i); SHA512_transform(ctx); i = 0; } /* Pad to byte 112 with zeroes */ memset(ctx->buffer + i, 0, 112 - i); /* Add length in big-endian */ SHA512_copy_and_swap(ctx->length, ctx->buffer + 112, 2); /* Munge the final block */ SHA512_transform(ctx); /* Final hash value is in ctx->state modulo big-endian conversion */ switch (bitsize) { case 512: SHA512_copy_and_swap(ctx->state, output, 8); break; case 384: SHA512_copy_and_swap(ctx->state, output, 6); break; /* default: The bit size is wrong. Produce no output. */ } } cryptokit-release119/src/sha512.h000066400000000000000000000027561453705265000167430ustar00rootroot00000000000000/***********************************************************************/ /* */ /* The Cryptokit library */ /* */ /* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ /* */ /* Copyright 2015 Institut National de Recherche en Informatique et */ /* en Automatique. All rights reserved. This file is distributed */ /* under the terms of the GNU Library General Public License, with */ /* the special exception on linking described in file LICENSE. */ /* */ /***********************************************************************/ /* $Id: sha256.h 53 2010-08-30 10:53:00Z gildor-admin $ */ /* SHA-512 hashing */ #ifndef _MSC_VER #include typedef uint64_t u64; #else typedef unsigned __int64 u64; #define UINT64_C(x) x##ui64 #endif struct SHA512Context { u64 state[8]; u64 length[2]; int numbytes; unsigned char buffer[128]; }; extern void SHA512_init(struct SHA512Context * ctx, int bitsize); extern void SHA512_add_data(struct SHA512Context * ctx, unsigned char * data, unsigned long len); extern void SHA512_finish(struct SHA512Context * ctx, int bitsize, unsigned char * output); cryptokit-release119/src/siphash.c000066400000000000000000000115151453705265000173630ustar00rootroot00000000000000/***********************************************************************/ /* */ /* The Cryptokit library */ /* */ /* Xavier Leroy, Collège de France and Inria */ /* */ /* Copyright (c) 2012-2016 Jean-Philippe Aumasson */ /* */ /* Copyright (c) 2012-2014 Daniel J. Bernstein */ /* Copyright 2022 Institut National de Recherche en Informatique et */ /* en Automatique. All rights reserved. This file is distributed */ /* under the terms of the GNU Library General Public License, with */ /* the special exception on linking described in file LICENSE. */ /* */ /***********************************************************************/ /* Based on the SipHash reference C implementation by Aumasson and Berstein https://github.com/veorq/SipHash and lightly adapted by Leroy. The original implementation is distributed under the CC0 Public Domain Dedication. */ #include #include #include #include "siphash.h" #define ROTL64(x,n) ((x) << n | (x) >> (64-n)) static inline uint64_t U8TO64_LE(const unsigned char *p) { return (((uint64_t)(p[0] & 0xff) ) | ((uint64_t)(p[1] & 0xff) << 8) | ((uint64_t)(p[2] & 0xff) << 16) | ((uint64_t)(p[3] & 0xff) << 24) | ((uint64_t)(p[4] & 0xff) << 32) | ((uint64_t)(p[5] & 0xff) << 40) | ((uint64_t)(p[6] & 0xff) << 48) | ((uint64_t)(p[7] & 0xff) << 56)); } static inline void U64TO8_LE(unsigned char *p, uint64_t v) { p[0] = (v ) & 0xff; p[1] = (v >> 8) & 0xff; p[2] = (v >> 16) & 0xff; p[3] = (v >> 24) & 0xff; p[4] = (v >> 32) & 0xff; p[5] = (v >> 40) & 0xff; p[6] = (v >> 48) & 0xff; p[7] = (v >> 56) & 0xff; } void siphash_init(struct siphash * st, const unsigned char * key, int outlen) { uint64_t k0 = U8TO64_LE(key); uint64_t k1 = U8TO64_LE(key + 8); st->v0 = 0x736f6d6570736575; st->v1 = 0x646f72616e646f6d; st->v2 = 0x6c7967656e657261; st->v3 = 0x7465646279746573; st->v3 ^= k1; st->v2 ^= k0; st->v1 ^= k1; st->v0 ^= k0; if (outlen == 16) st->v1 ^= 0xEE; st->used = 0; st->len8 = 0; } static inline void siphash_round(struct siphash * st) { st->v0 += st->v1; st->v1 = ROTL64(st->v1, 13); st->v1 ^= st->v0; st->v0 = ROTL64(st->v0, 32); st->v2 += st->v3; st->v3 = ROTL64(st->v3, 16); st->v3 ^= st->v2; st->v0 += st->v3; st->v3 = ROTL64(st->v3, 21); st->v3 ^= st->v0; st->v2 += st->v1; st->v1 = ROTL64(st->v1, 17); st->v1 ^= st->v2; st->v2 = ROTL64(st->v2, 32); } static void siphash_mix(struct siphash * st, uint64_t x) { st->v3 ^= x; siphash_round(st); siphash_round(st); st->v0 ^= x; } void siphash_add(struct siphash * st, const unsigned char * p, size_t len) { int used = st->used; int free = SIPHASH_BUFLEN - used; st->len8 += len; if (len < free) { memcpy(st->buffer + used, p, len); st->used = used + len; return; } if (used > 0) { memcpy(st->buffer + used, p, free); siphash_mix(st, U8TO64_LE(st->buffer)); p += free; len -= free; } while (len >= SIPHASH_BUFLEN) { siphash_mix(st, U8TO64_LE(p)); p += SIPHASH_BUFLEN; len -= SIPHASH_BUFLEN; } if (len > 0) memcpy(st->buffer, p, len); st->used = len; } static uint64_t siphash_final_rounds(struct siphash * st) { /* Four rounds at the end */ for (int i = 0; i < 4; i++) siphash_round(st); /* Fold state down to 64 bits */ return st->v0 ^ st->v1 ^ st->v2 ^ st->v3; } void siphash_final(struct siphash * st, int outlen, unsigned char * out) { uint64_t w; /* Finish with the remaining bytes (up to 7 bytes). Also use the low 8 bits of the length. */ w = (uint64_t) st->len8 << 56; switch (st->len8 & 7) { case 7: w |= (uint64_t) st->buffer[6] << 48; /* fallthrough */ case 6: w |= (uint64_t) st->buffer[5] << 40; /* fallthrough */ case 5: w |= (uint64_t) st->buffer[4] << 32; /* fallthrough */ case 4: w |= (uint64_t) st->buffer[3] << 24; /* fallthrough */ case 3: w |= (uint64_t) st->buffer[2] << 16; /* fallthrough */ case 2: w |= (uint64_t) st->buffer[1] << 8; /* fallthrough */ case 1: w |= (uint64_t) st->buffer[0]; /* fallthrough */ case 0: /*skip*/; } siphash_mix(st, w); /* First 64 bit of hash */ st->v2 ^= (outlen == 16 ? 0xEE : 0xFF); U64TO8_LE(out, siphash_final_rounds(st)); /* Next 64 bits of hash, if requested */ if (outlen == 16) { st->v1 ^= 0xDD; U64TO8_LE(out + 8, siphash_final_rounds(st)); } } cryptokit-release119/src/siphash.h000066400000000000000000000026441453705265000173730ustar00rootroot00000000000000/***********************************************************************/ /* */ /* The Cryptokit library */ /* */ /* Xavier Leroy, Collège de France and Inria */ /* */ /* Copyright 2022 Institut National de Recherche en Informatique et */ /* en Automatique. All rights reserved. This file is distributed */ /* under the terms of the GNU Library General Public License, with */ /* the special exception on linking described in file LICENSE. */ /* */ /***********************************************************************/ #define SIPHASH_BUFLEN 8 struct siphash { uint64_t v0, v1, v2, v3; unsigned char buffer[SIPHASH_BUFLEN]; int used; /* number of valid bytes in buffer */ uint8_t len8; /* 8 low bits of total data length */ }; extern void siphash_init(struct siphash * st, const unsigned char * key, int outlen); extern void siphash_add(struct siphash * st, const unsigned char * p, size_t len); extern void siphash_final(struct siphash * st, int outlen, unsigned char * out); cryptokit-release119/src/stubs-aes.c000066400000000000000000000071371453705265000176370ustar00rootroot00000000000000/***********************************************************************/ /* */ /* The Cryptokit library */ /* */ /* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ /* */ /* Copyright 2002 Institut National de Recherche en Informatique et */ /* en Automatique. All rights reserved. This file is distributed */ /* under the terms of the GNU Library General Public License, with */ /* the special exception on linking described in file LICENSE. */ /* */ /***********************************************************************/ /* $Id$ */ /* Stub code for AES */ #include "rijndael-alg-fst.h" #include "aesni.h" #include #include #include #define Cooked_key_NR_offset ((4 * (MAXNR + 1)) * sizeof(u32)) #define Cooked_key_size (Cooked_key_NR_offset + 1) CAMLprim value caml_aes_cook_encrypt_key(value key) { CAMLparam1(key); value ckey = caml_alloc_string(Cooked_key_size); int nr; if (aesni_available == -1) aesni_check_available(); if (aesni_available == 1) nr = aesniKeySetupEnc((u8 *) String_val(ckey), (const u8 *) String_val(key), 8 * caml_string_length(key)); else nr = rijndaelKeySetupEnc((u32 *) String_val(ckey), (const u8 *) String_val(key), 8 * caml_string_length(key)); Byte(ckey, Cooked_key_NR_offset) = nr; CAMLreturn(ckey); } CAMLprim value caml_aes_cook_decrypt_key(value key) { CAMLparam1(key); value ckey = caml_alloc_string(Cooked_key_size); int nr; if (aesni_available == -1) aesni_check_available(); if (aesni_available == 1) nr = aesniKeySetupDec((u8 *) String_val(ckey), (const u8 *) String_val(key), 8 * caml_string_length(key)); else nr = rijndaelKeySetupDec((u32 *) String_val(ckey), (const u8 *) String_val(key), 8 * caml_string_length(key)); Byte(ckey, Cooked_key_NR_offset) = nr; CAMLreturn(ckey); } CAMLprim value caml_aes_encrypt(value ckey, value src, value src_ofs, value dst, value dst_ofs) { if (aesni_available == 1) aesniEncrypt((const u8 *) String_val(ckey), Byte(ckey, Cooked_key_NR_offset), (const u8 *) &Byte(src, Long_val(src_ofs)), (u8 *) &Byte(dst, Long_val(dst_ofs))); else rijndaelEncrypt((const u32 *) String_val(ckey), Byte(ckey, Cooked_key_NR_offset), (const u8 *) &Byte(src, Long_val(src_ofs)), (u8 *) &Byte(dst, Long_val(dst_ofs))); return Val_unit; } CAMLprim value caml_aes_decrypt(value ckey, value src, value src_ofs, value dst, value dst_ofs) { if (aesni_available == 1) aesniDecrypt((const u8 *) String_val(ckey), Byte(ckey, Cooked_key_NR_offset), (const u8 *) &Byte(src, Long_val(src_ofs)), (u8 *) &Byte(dst, Long_val(dst_ofs))); else rijndaelDecrypt((const u32 *) String_val(ckey), Byte(ckey, Cooked_key_NR_offset), (const u8 *) &Byte(src, Long_val(src_ofs)), (u8 *) &Byte(dst, Long_val(dst_ofs))); return Val_unit; } cryptokit-release119/src/stubs-arcfour.c000066400000000000000000000036331453705265000205250ustar00rootroot00000000000000/***********************************************************************/ /* */ /* The Cryptokit library */ /* */ /* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ /* */ /* Copyright 2002 Institut National de Recherche en Informatique et */ /* en Automatique. All rights reserved. This file is distributed */ /* under the terms of the GNU Library General Public License, with */ /* the special exception on linking described in file LICENSE. */ /* */ /***********************************************************************/ /* $Id$ */ /* Stub code for ARC4 */ #include "arcfour.h" #include #include #include #define Cooked_key_size (sizeof(struct arcfour_key)) #define Key_val(v) ((struct arcfour_key *) String_val(v)) CAMLprim value caml_arcfour_cook_key(value key) { CAMLparam1(key); value ckey = caml_alloc_string(Cooked_key_size); arcfour_cook_key(Key_val(ckey), (unsigned char *) String_val(key), caml_string_length(key)); CAMLreturn(ckey); } CAMLprim value caml_arcfour_transform(value ckey, value src, value src_ofs, value dst, value dst_ofs, value len) { arcfour_encrypt(Key_val(ckey), &Byte(src, Long_val(src_ofs)), &Byte(dst, Long_val(dst_ofs)), Long_val(len)); return Val_unit; } CAMLprim value caml_arcfour_transform_bytecode(value * argv, int argc) { return caml_arcfour_transform(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]); } cryptokit-release119/src/stubs-blake2.c000066400000000000000000000050521453705265000202210ustar00rootroot00000000000000/***********************************************************************/ /* */ /* The Cryptokit library */ /* */ /* Xavier Leroy, Collège de France and Inria */ /* */ /* Copyright 2020 Institut National de Recherche en Informatique et */ /* en Automatique. All rights reserved. This file is distributed */ /* under the terms of the GNU Library General Public License, with */ /* the special exception on linking described in file LICENSE. */ /* */ /***********************************************************************/ #include #include #include #include #include #include "blake2.h" #define blake2b_val(v) ((struct blake2b *) String_val(v)) CAMLprim value caml_blake2b_init(value hashlen, value key) { CAMLparam1(key); value ctx = caml_alloc_string(sizeof(struct blake2b)); blake2b_init(blake2b_val(ctx), Int_val(hashlen), caml_string_length(key), &Byte_u(key, 0)); CAMLreturn(ctx); } CAMLprim value caml_blake2b_update(value ctx, value src, value ofs, value len) { blake2b_add_data(blake2b_val(ctx), &Byte_u(src, Long_val(ofs)), Long_val(len)); return Val_unit; } CAMLprim value caml_blake2b_final(value ctx, value hashlen) { CAMLparam1(ctx); CAMLlocal1(res); int len = Int_val(hashlen); res = caml_alloc_string(len); blake2b_final(blake2b_val(ctx), len, &Byte_u(res, 0)); CAMLreturn(res); } #define blake2s_val(v) ((struct blake2s *) String_val(v)) CAMLprim value caml_blake2s_init(value hashlen, value key) { CAMLparam1(key); value ctx = caml_alloc_string(sizeof(struct blake2s)); blake2s_init(blake2s_val(ctx), Int_val(hashlen), caml_string_length(key), &Byte_u(key, 0)); CAMLreturn(ctx); } CAMLprim value caml_blake2s_update(value ctx, value src, value ofs, value len) { blake2s_add_data(blake2s_val(ctx), &Byte_u(src, Long_val(ofs)), Long_val(len)); return Val_unit; } CAMLprim value caml_blake2s_final(value ctx, value hashlen) { CAMLparam1(ctx); CAMLlocal1(res); int len = Int_val(hashlen); res = caml_alloc_string(len); blake2s_final(blake2s_val(ctx), len, &Byte_u(res, 0)); CAMLreturn(res); } cryptokit-release119/src/stubs-blake3.c000066400000000000000000000051451453705265000202250ustar00rootroot00000000000000/***********************************************************************/ /* */ /* The Cryptokit library */ /* */ /* Xavier Leroy, Collège de France and Inria */ /* */ /* Copyright 2022 Institut National de Recherche en Informatique et */ /* en Automatique. All rights reserved. This file is distributed */ /* under the terms of the GNU Library General Public License, with */ /* the special exception on linking described in file LICENSE. */ /* */ /***********************************************************************/ #include #include #include #include #include #include #include "blake3.h" #define Context_val(v) (*((blake3_hasher **) Data_custom_val(v))) static void caml_blake3_finalize(value ctx) { if (Context_val(ctx) != NULL) { caml_stat_free(Context_val(ctx)); Context_val(ctx) = NULL; } } static struct custom_operations blake3_context_ops = { "fr.inria.caml.cryptokit.blake3_context", caml_blake3_finalize, custom_compare_default, custom_hash_default, custom_deserialize_default, custom_compare_ext_default }; CAMLprim value caml_blake3_init(value optkey) { CAMLparam1(optkey); blake3_hasher * ctx = caml_stat_alloc(sizeof(blake3_hasher)); value res = caml_alloc_custom(&blake3_context_ops, sizeof(blake3_hasher *), 0, 1); if (caml_string_length(optkey) == BLAKE3_KEY_LEN) { blake3_hasher_init_keyed(ctx, &Byte_u(optkey, 0)); } else { blake3_hasher_init(ctx); } Context_val(res) = ctx; CAMLreturn(res); } CAMLprim value caml_blake3_update(value ctx, value src, value ofs, value len) { blake3_hasher_update(Context_val(ctx), &Byte_u(src, Long_val(ofs)), Long_val(len)); return Val_unit; } CAMLprim value caml_blake3_extract(value ctx, value vlen) { CAMLparam2(ctx, vlen); CAMLlocal1(res); size_t len = Long_val(vlen); res = caml_alloc_string(len); blake3_hasher_finalize(Context_val(ctx), &Byte_u(res, 0), len); CAMLreturn(res); } CAMLprim value caml_blake3_wipe(value ctx) { if (Context_val(ctx) != NULL) memset(Context_val(ctx), 0, sizeof(blake3_hasher)); caml_blake3_finalize(ctx); return Val_unit; } cryptokit-release119/src/stubs-blowfish.c000066400000000000000000000050661453705265000207030ustar00rootroot00000000000000/***********************************************************************/ /* */ /* The Cryptokit library */ /* */ /* Xavier Leroy, projet Gallium, INRIA Rocquencourt */ /* */ /* Copyright 2006 Institut National de Recherche en Informatique et */ /* en Automatique. All rights reserved. This file is distributed */ /* under the terms of the GNU Library General Public License, with */ /* the special exception on linking described in file LICENSE. */ /* */ /***********************************************************************/ /* $Id$ */ /* Stub code for Blowfish */ #include "blowfish.h" #include #include #include CAMLprim value caml_blowfish_cook_key(value key) { CAMLparam1(key); value ckey = caml_alloc_string(sizeof(BLOWFISH_CTX)); Blowfish_Init((BLOWFISH_CTX *) String_val(ckey), &Byte_u(key, 0), caml_string_length(key)); CAMLreturn(ckey); } #ifdef ARCH_BIG_ENDIAN #define COPY4BYTES(dst,src) \ (dst)[0] = (src)[0], \ (dst)[1] = (src)[1], \ (dst)[2] = (src)[2], \ (dst)[3] = (src)[3] #else #define COPY4BYTES(dst,src) \ (dst)[0] = (src)[3], \ (dst)[1] = (src)[2], \ (dst)[2] = (src)[1], \ (dst)[3] = (src)[0] #endif CAMLprim value caml_blowfish_encrypt(value ckey, value src, value src_ofs, value dst, value dst_ofs) { u32 xl, xr; unsigned char * p; p = &Byte_u(src, Long_val(src_ofs)); COPY4BYTES((unsigned char *) &xl, p); COPY4BYTES((unsigned char *) &xr, p + 4); Blowfish_Encrypt((BLOWFISH_CTX *) String_val(ckey), &xl, &xr); p = &Byte_u(dst, Long_val(dst_ofs)); COPY4BYTES(p, (unsigned char *) &xl); COPY4BYTES(p + 4, (unsigned char *) &xr); return Val_unit; } CAMLprim value caml_blowfish_decrypt(value ckey, value src, value src_ofs, value dst, value dst_ofs) { u32 xl, xr; unsigned char * p; p = &Byte_u(src, Long_val(src_ofs)); COPY4BYTES((unsigned char *) &xl, p); COPY4BYTES((unsigned char *) &xr, p + 4); Blowfish_Decrypt((BLOWFISH_CTX *) String_val(ckey), &xl, &xr); p = &Byte_u(dst, Long_val(dst_ofs)); COPY4BYTES(p, (unsigned char *) &xl); COPY4BYTES(p + 4, (unsigned char *) &xr); return Val_unit; } cryptokit-release119/src/stubs-chacha20.c000066400000000000000000000044451453705265000204370ustar00rootroot00000000000000/***********************************************************************/ /* */ /* The Cryptokit library */ /* */ /* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ /* */ /* Copyright 2002 Institut National de Recherche en Informatique et */ /* en Automatique. All rights reserved. This file is distributed */ /* under the terms of the GNU Library General Public License, with */ /* the special exception on linking described in file LICENSE. */ /* */ /***********************************************************************/ /* Stub code for Chacha20 */ #include "chacha20.h" #include #include #include #define Cooked_key_size (sizeof(chacha20_ctx)) #define Key_val(v) ((chacha20_ctx *) String_val(v)) CAMLprim value caml_chacha20_cook_key(value key, value iv, value counter) { CAMLparam3(key, iv, counter); value ckey = caml_alloc_string(Cooked_key_size); chacha20_init(Key_val(ckey), (unsigned char *) String_val(key), caml_string_length(key), (unsigned char *) String_val(iv), caml_string_length(iv), Int64_val(counter)); CAMLreturn(ckey); } CAMLprim value caml_chacha20_transform(value ckey, value src, value src_ofs, value dst, value dst_ofs, value len) { chacha20_transform(Key_val(ckey), &Byte_u(src, Long_val(src_ofs)), &Byte_u(dst, Long_val(dst_ofs)), Long_val(len)); return Val_unit; } CAMLprim value caml_chacha20_transform_bytecode(value * argv, int argc) { return caml_chacha20_transform(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]); } CAMLprim value caml_chacha20_extract(value ckey, value dst, value dst_ofs, value len) { chacha20_extract(Key_val(ckey), &Byte_u(dst, Long_val(dst_ofs)), Long_val(len)); return Val_unit; } cryptokit-release119/src/stubs-des.c000066400000000000000000000032301453705265000176300ustar00rootroot00000000000000/***********************************************************************/ /* */ /* The Cryptokit library */ /* */ /* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ /* */ /* Copyright 2002 Institut National de Recherche en Informatique et */ /* en Automatique. All rights reserved. This file is distributed */ /* under the terms of the GNU Library General Public License, with */ /* the special exception on linking described in file LICENSE. */ /* */ /***********************************************************************/ /* $Id$ */ /* Stub code for DES */ #include "d3des.h" #include #include #include #define Cooked_key_size (32 * sizeof(u32)) CAMLprim value caml_des_cook_key(value key, value ofs, value direction) { CAMLparam2(key,direction); value ckey = caml_alloc_string(Cooked_key_size); d3des_cook_key((u8 *) &Byte(key, Long_val(ofs)), Int_val(direction), (u32 *) String_val(ckey)); CAMLreturn(ckey); } CAMLprim value caml_des_transform(value ckey, value src, value src_ofs, value dst, value dst_ofs) { d3des_transform((u32 *) String_val(ckey), (u8 *) &Byte(src, Long_val(src_ofs)), (u8 *) &Byte(dst, Long_val(dst_ofs))); return Val_unit; } cryptokit-release119/src/stubs-ghash.c000066400000000000000000000042641453705265000201570ustar00rootroot00000000000000/***********************************************************************/ /* */ /* The Cryptokit library */ /* */ /* Xavier Leroy, Collège de France and Inria */ /* */ /* Copyright 2022 Institut National de Recherche en Informatique et */ /* en Automatique. All rights reserved. This file is distributed */ /* under the terms of the GNU Library General Public License, with */ /* the special exception on linking described in file LICENSE. */ /* */ /***********************************************************************/ #include #include #include "ghash.h" #include "pclmul.h" #include #include #include #define Context_val(v) (*((struct ghash_context **) Data_custom_val(v))) static void caml_ghash_finalize(value ctx) { if (Context_val(ctx) != NULL) { caml_stat_free(Context_val(ctx)); Context_val(ctx) = NULL; } } static struct custom_operations ghash_context_ops = { "fr.inria.caml.cryptokit.GHASH_context", caml_ghash_finalize, custom_compare_default, custom_hash_default, custom_deserialize_default, custom_compare_ext_default }; CAMLprim value caml_ghash_init(value key) { if (pclmul_available == -1) pclmul_check_available(); if (pclmul_available == 1) { return key; } else { struct ghash_context * ctx = caml_stat_alloc(sizeof(struct ghash_context)); value res = caml_alloc_custom(&ghash_context_ops, sizeof(struct ghash_context *), 0, 1); ghash_init(ctx, &Byte_u(key, 0)); Context_val(res) = ctx; return res; } } CAMLprim value caml_ghash_mult(value ctx, value x) { if (pclmul_available == 1) { pclmul_mult(&Byte_u(x, 0), &Byte_u(ctx, 0), &Byte_u(x, 0)); } else { ghash_mult(Context_val(ctx), &Byte_u(x, 0), &Byte_u(x, 0)); } return Val_unit; } cryptokit-release119/src/stubs-md5.c000066400000000000000000000037371453705265000175560ustar00rootroot00000000000000/***********************************************************************/ /* */ /* The Cryptokit library */ /* */ /* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ /* */ /* Copyright 2002 Institut National de Recherche en Informatique et */ /* en Automatique. All rights reserved. This file is distributed */ /* under the terms of the GNU Library General Public License, with */ /* the special exception on linking described in file LICENSE. */ /* */ /***********************************************************************/ /* $Id$ */ #include #include #include #ifndef _MSC_VER #include typedef uint32_t u32; #else typedef unsigned int u32; #endif struct MD5Context { u32 buf[4]; u32 bits[2]; unsigned char in[64]; }; CAMLextern void caml_MD5Init (struct MD5Context *context); CAMLextern void caml_MD5Update (struct MD5Context *context, unsigned char *buf, unsigned len); CAMLextern void caml_MD5Final (unsigned char *digest, struct MD5Context *ctx); #define Context_val(v) ((struct MD5Context *) String_val(v)) CAMLprim value caml_md5_init(value unit) { value ctx = caml_alloc_string(sizeof(struct MD5Context)); caml_MD5Init(Context_val(ctx)); return ctx; } CAMLprim value caml_md5_update(value ctx, value src, value ofs, value len) { caml_MD5Update(Context_val(ctx), &Byte_u(src, Long_val(ofs)), Long_val(len)); return Val_unit; } CAMLprim value caml_md5_final(value ctx) { CAMLparam1(ctx); CAMLlocal1(res); res = caml_alloc_string(16); caml_MD5Final(&Byte_u(res, 0), Context_val(ctx)); CAMLreturn(res); } cryptokit-release119/src/stubs-misc.c000066400000000000000000000035241453705265000200160ustar00rootroot00000000000000/***********************************************************************/ /* */ /* The Cryptokit library */ /* */ /* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ /* */ /* Copyright 2002 Institut National de Recherche en Informatique et */ /* en Automatique. All rights reserved. This file is distributed */ /* under the terms of the GNU Library General Public License, with */ /* the special exception on linking described in file LICENSE. */ /* */ /***********************************************************************/ /* $Id$ */ #include #include #define ALIGNMENT_OF(x) ((long)(x) & (sizeof(long) - 1)) CAMLprim value caml_xor_string(value src, value src_ofs, value dst, value dst_ofs, value len) { char * s = &Byte(src, Long_val(src_ofs)); char * d = &Byte(dst, Long_val(dst_ofs)); long l = Long_val(len); if (l >= 64 && ALIGNMENT_OF(s) == ALIGNMENT_OF(d)) { while (ALIGNMENT_OF(s) != 0 && l > 0) { *d ^= *s; s += 1; d += 1; l -= 1; } while (l >= sizeof(long)) { *((long *) d) ^= *((long *) s); s += sizeof(long); d += sizeof(long); l -= sizeof(long); } } while (l > 0) { *d ^= *s; s += 1; d += 1; l -= 1; } return Val_unit; } CAMLprim value caml_wipe_z(value v) { if (Is_block(v) && Tag_val(v) == Custom_tag) { memset(Data_custom_val(v), 0, (Wosize_val(v) - 1) * sizeof(value)); } return Val_unit; } cryptokit-release119/src/stubs-poly1305.c000066400000000000000000000031571453705265000203610ustar00rootroot00000000000000/***********************************************************************/ /* */ /* The Cryptokit library */ /* */ /* Xavier Leroy, Collège de France and Inria */ /* */ /* Copyright 2022 Institut National de Recherche en Informatique et */ /* en Automatique. All rights reserved. This file is distributed */ /* under the terms of the GNU Library General Public License, with */ /* the special exception on linking described in file LICENSE. */ /* */ /***********************************************************************/ #include "poly1305-donna.h" #include #include #include #define Context_val(v) ((struct poly1305_context *) String_val(v)) CAMLprim value caml_poly1305_init(value key) { CAMLparam1(key); value ctx = caml_alloc_string(sizeof(struct poly1305_context)); poly1305_init(Context_val(ctx), &Byte_u(key, 0)); CAMLreturn(ctx); } CAMLprim value caml_poly1305_update(value ctx, value src, value ofs, value len) { poly1305_update(Context_val(ctx), &Byte_u(src, Long_val(ofs)), Long_val(len)); return Val_unit; } CAMLprim value caml_poly1305_final(value ctx) { CAMLparam1(ctx); CAMLlocal1(res); res = caml_alloc_string(16); poly1305_finish(Context_val(ctx), &Byte_u(res, 0)); CAMLreturn(res); } cryptokit-release119/src/stubs-ripemd160.c000066400000000000000000000031261453705265000205700ustar00rootroot00000000000000/***********************************************************************/ /* */ /* The Cryptokit library */ /* */ /* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ /* */ /* Copyright 2005 Institut National de Recherche en Informatique et */ /* en Automatique. All rights reserved. This file is distributed */ /* under the terms of the GNU Library General Public License, with */ /* the special exception on linking described in file LICENSE. */ /* */ /***********************************************************************/ /* $Id$ */ #include "ripemd160.h" #include #include #include #define Context_val(v) ((struct RIPEMD160Context *) String_val(v)) CAMLprim value caml_ripemd160_init(value unit) { value ctx = caml_alloc_string(sizeof(struct RIPEMD160Context)); RIPEMD160_init(Context_val(ctx)); return ctx; } CAMLprim value caml_ripemd160_update(value ctx, value src, value ofs, value len) { RIPEMD160_add_data(Context_val(ctx), &Byte_u(src, Long_val(ofs)), Long_val(len)); return Val_unit; } CAMLprim value caml_ripemd160_final(value ctx) { CAMLparam1(ctx); CAMLlocal1(res); res = caml_alloc_string(20); RIPEMD160_finish(Context_val(ctx), &Byte_u(res, 0)); CAMLreturn(res); } cryptokit-release119/src/stubs-rng.c000066400000000000000000000115641453705265000176540ustar00rootroot00000000000000/***********************************************************************/ /* */ /* The Cryptokit library */ /* */ /* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ /* */ /* Copyright 2003 Institut National de Recherche en Informatique et */ /* en Automatique. All rights reserved. This file is distributed */ /* under the terms of the GNU Library General Public License, with */ /* the special exception on linking described in file LICENSE. */ /* */ /***********************************************************************/ /* $Id$ */ /* Stub code for the system-provided RNG and for hardware RNG */ #include #include #include #include #if defined(HAVE_GETENTROPY) || defined(__APPLE__) /* getentropy() system RNG */ #include #ifdef __APPLE__ #include #endif CAMLprim value caml_get_system_rng(value unit) { return Val_unit; } CAMLprim value caml_close_system_rng(value vhc) { return Val_unit; } CAMLprim value caml_system_rng_random_bytes(value vhc, value str, value ofs, value len) { unsigned char * p = &Byte_u(str, Long_val(ofs)); intnat l = Long_val(len); while (l > 0) { int n = l < 256 ? l : 256; if (getentropy(p, n) == -1) return Val_false; p += n; l -= n; } return Val_true; } #elif defined(_WIN32) /* Win32 system RNG */ /* Inspired by Mike Lin's port of Cryptokit 1.0 */ #define _WIN32_WINNT 0x0400 #define WIN32_LEAN_AND_MEAN #include #include #ifndef CRYPT_SILENT #define CRYPT_SILENT 0 #endif #define HCRYPTPROV_val(v) (*((HCRYPTPROV *) &Field(v, 0))) CAMLprim value caml_get_system_rng(value unit) { HCRYPTPROV prov; value res; if (! CryptAcquireContext(&prov, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) caml_raise_not_found(); res = caml_alloc((sizeof(HCRYPTPROV) + sizeof(value) - 1) / sizeof(value), Abstract_tag); HCRYPTPROV_val(res) = prov; return res; } CAMLprim value caml_close_system_rng(value vhc) { CryptReleaseContext(HCRYPTPROV_val(vhc), 0); return Val_unit; } CAMLprim value caml_system_rng_random_bytes(value vhc, value str, value ofs, value len) { return Val_bool(CryptGenRandom(HCRYPTPROV_val(vhc), Long_val(len), &Byte(str, Long_val(ofs)))); } #else CAMLprim value caml_get_system_rng(value unit) { caml_raise_not_found(); return Val_unit; /* not reached */ } CAMLprim value caml_close_system_rng(value vhc) { return Val_unit; } CAMLprim value caml_system_rng_random_bytes(value vhc, value str, value ofs, value len) { return Val_false; } #endif /* Intel RDRAND instruction */ #if defined(__GNUC__) && defined(__x86_64) #include #include static inline int rdrand64(uint64_t * res) { uint64_t n; unsigned char ok; int retries; for (retries = 0; retries < 20; retries++) { __asm__ __volatile__ ("rdrand %0; setc %1" : "=r" (n), "=qm" (ok)); if (ok) { *res = n; return 1; } } return 0; } CAMLprim value caml_hardware_rng_available(value unit) { uint32_t ax, bx, cx, dx; uint64_t n; int retries; __asm__ __volatile__ ("cpuid" : "=a" (ax), "=b" (bx), "=c" (cx), "=d" (dx) : "a" (1)); if ((cx & (1U << 30)) == 0) return Val_false; /* Early AMD Ryzen 3000 processors have a most annoying bug: the rdrand instruction always returns 0xFF....FF. We check for this condition here. */ for (retries = 0; retries < 8; retries++) { if (rdrand64(&n) && n != (uint64_t) (-1)) return Val_true; } /* If we reach here, either rdrand64 failed 8*20=160 times in a row, or it returned 8*64=512 "1" bits in a row. In either case, it's unusable. */ return Val_false; } CAMLprim value caml_hardware_rng_random_bytes(value str, value ofs, value len) { unsigned char * dst = &Byte_u(str, Long_val(ofs)); intnat nbytes = Long_val(len); uint64_t r, rr; while (nbytes >= 8) { if (! rdrand64(&r)) return Val_false; *((uint64_t *) dst) = r; dst += 8; nbytes -= 8; } if (nbytes > 0) { if (! rdrand64(&rr)) return Val_false; memcpy(dst, &rr, nbytes); } return Val_true; } #else CAMLprim value caml_hardware_rng_available(value unit) { return Val_false; } CAMLprim value caml_hardware_rng_random_bytes(value str, value ofs, value len) { return Val_false; } #endif cryptokit-release119/src/stubs-sha1.c000066400000000000000000000030511453705265000177120ustar00rootroot00000000000000/***********************************************************************/ /* */ /* The Cryptokit library */ /* */ /* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ /* */ /* Copyright 2002 Institut National de Recherche en Informatique et */ /* en Automatique. All rights reserved. This file is distributed */ /* under the terms of the GNU Library General Public License, with */ /* the special exception on linking described in file LICENSE. */ /* */ /***********************************************************************/ /* $Id$ */ #include "sha1.h" #include #include #include #define Context_val(v) ((struct SHA1Context *) String_val(v)) CAMLprim value caml_sha1_init(value unit) { value ctx = caml_alloc_string(sizeof(struct SHA1Context)); SHA1_init(Context_val(ctx)); return ctx; } CAMLprim value caml_sha1_update(value ctx, value src, value ofs, value len) { SHA1_add_data(Context_val(ctx), &Byte_u(src, Long_val(ofs)), Long_val(len)); return Val_unit; } CAMLprim value caml_sha1_final(value ctx) { CAMLparam1(ctx); CAMLlocal1(res); res = caml_alloc_string(20); SHA1_finish(Context_val(ctx), &Byte_u(res, 0)); CAMLreturn(res); } cryptokit-release119/src/stubs-sha256.c000066400000000000000000000036551453705265000201000ustar00rootroot00000000000000/***********************************************************************/ /* */ /* The Cryptokit library */ /* */ /* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ /* */ /* Copyright 2004 Institut National de Recherche en Informatique et */ /* en Automatique. All rights reserved. This file is distributed */ /* under the terms of the GNU Library General Public License, with */ /* the special exception on linking described in file LICENSE. */ /* */ /***********************************************************************/ /* $Id$ */ #include "sha256.h" #include #include #include #define Context_val(v) ((struct SHA256Context *) String_val(v)) CAMLprim value caml_sha256_init(value unit) { value ctx = caml_alloc_string(sizeof(struct SHA256Context)); SHA256_init(Context_val(ctx), 256); return ctx; } CAMLprim value caml_sha224_init(value unit) { value ctx = caml_alloc_string(sizeof(struct SHA256Context)); SHA256_init(Context_val(ctx), 224); return ctx; } CAMLprim value caml_sha256_update(value ctx, value src, value ofs, value len) { SHA256_add_data(Context_val(ctx), &Byte_u(src, Long_val(ofs)), Long_val(len)); return Val_unit; } CAMLprim value caml_sha256_final(value ctx) { CAMLparam1(ctx); CAMLlocal1(res); res = caml_alloc_string(32); SHA256_finish(Context_val(ctx), 256, &Byte_u(res, 0)); CAMLreturn(res); } CAMLprim value caml_sha224_final(value ctx) { CAMLparam1(ctx); CAMLlocal1(res); res = caml_alloc_string(28); SHA256_finish(Context_val(ctx), 224, &Byte_u(res, 0)); CAMLreturn(res); } cryptokit-release119/src/stubs-sha3.c000066400000000000000000000057151453705265000177250ustar00rootroot00000000000000/***********************************************************************/ /* */ /* The Cryptokit library */ /* */ /* Xavier Leroy, projet Gallium, INRIA Rocquencourt */ /* */ /* Copyright 2013 Institut National de Recherche en Informatique et */ /* en Automatique. All rights reserved. This file is distributed */ /* under the terms of the GNU Library General Public License, with */ /* the special exception on linking described in file LICENSE. */ /* */ /***********************************************************************/ /* $Id: stubs-sha1.c 53 2010-08-30 10:53:00Z gildor-admin $ */ #include #include "keccak.h" #include #include #include #include #define Context_val(v) (*((struct SHA3Context **) Data_custom_val(v))) static void caml_sha3_finalize(value ctx) { if (Context_val(ctx) != NULL) { caml_stat_free(Context_val(ctx)); Context_val(ctx) = NULL; } } static struct custom_operations SHA3_context_ops = { "fr.inria.caml.cryptokit.SHA3_context", caml_sha3_finalize, custom_compare_default, custom_hash_default, custom_deserialize_default, custom_compare_ext_default }; CAMLprim value caml_sha3_init(value vsize) { struct SHA3Context * ctx = caml_stat_alloc(sizeof(struct SHA3Context)); value res = caml_alloc_custom(&SHA3_context_ops, sizeof(struct SHA3Context *), 0, 1); SHA3_init(ctx, Int_val(vsize)); Context_val(res) = ctx; return res; } CAMLprim value caml_sha3_absorb(value ctx, value src, value ofs, value len) { SHA3_absorb(Context_val(ctx), &Byte_u(src, Long_val(ofs)), Long_val(len)); return Val_unit; } /* On page 9 of Keccak Implementation Overview (Version 3.2) http://keccak.noekeon.org/Keccak-implementation-3.2.pdf, there is a figure `0x01` as the padding byte. */ static const unsigned keccak_padding = 0x01; /* In a similar, updated description at http://keccak.noekeon.org/specs_summary.html, on Table 3, `0x06` is shown as the relevant padding byte. */ static const unsigned sha3_padding = 0x06; CAMLprim value caml_sha3_extract(value official, value ctx) { CAMLparam2(official, ctx); CAMLlocal1(res); res = caml_alloc_string(Context_val(ctx)->hsiz); SHA3_extract(Bool_val(official) ? sha3_padding : keccak_padding, Context_val(ctx), &Byte_u(res, 0)); CAMLreturn(res); } CAMLprim value caml_sha3_wipe(value ctx) { if (Context_val(ctx) != NULL) { memset(Context_val(ctx), 0, sizeof(struct SHA3Context)); caml_stat_free(Context_val(ctx)); Context_val(ctx) = NULL; } return Val_unit; } cryptokit-release119/src/stubs-sha512.c000066400000000000000000000037421453705265000200700ustar00rootroot00000000000000/***********************************************************************/ /* */ /* The Cryptokit library */ /* */ /* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ /* */ /* Copyright 2015 Institut National de Recherche en Informatique et */ /* en Automatique. All rights reserved. This file is distributed */ /* under the terms of the GNU Library General Public License, with */ /* the special exception on linking described in file LICENSE. */ /* */ /***********************************************************************/ /* $Id: stubs-sha256.c 53 2010-08-30 10:53:00Z gildor-admin $ */ #include "sha512.h" #include #include #include #define Context_val(v) ((struct SHA512Context *) String_val(v)) CAMLprim value caml_sha512_init(value unit) { value ctx = caml_alloc_string(sizeof(struct SHA512Context)); SHA512_init(Context_val(ctx), 512); return ctx; } CAMLprim value caml_sha384_init(value unit) { value ctx = caml_alloc_string(sizeof(struct SHA512Context)); SHA512_init(Context_val(ctx), 384); return ctx; } CAMLprim value caml_sha512_update(value ctx, value src, value ofs, value len) { SHA512_add_data(Context_val(ctx), &Byte_u(src, Long_val(ofs)), Long_val(len)); return Val_unit; } CAMLprim value caml_sha512_final(value ctx) { CAMLparam1(ctx); CAMLlocal1(res); res = caml_alloc_string(64); SHA512_finish(Context_val(ctx), 512, &Byte_u(res, 0)); CAMLreturn(res); } CAMLprim value caml_sha384_final(value ctx) { CAMLparam1(ctx); CAMLlocal1(res); res = caml_alloc_string(48); SHA512_finish(Context_val(ctx), 384, &Byte_u(res, 0)); CAMLreturn(res); } cryptokit-release119/src/stubs-siphash.c000066400000000000000000000032571453705265000205250ustar00rootroot00000000000000/***********************************************************************/ /* */ /* The Cryptokit library */ /* */ /* Xavier Leroy, Collège de France and Inria */ /* */ /* Copyright 2022 Institut National de Recherche en Informatique et */ /* en Automatique. All rights reserved. This file is distributed */ /* under the terms of the GNU Library General Public License, with */ /* the special exception on linking described in file LICENSE. */ /* */ /***********************************************************************/ #include #include #include #include #include #include "siphash.h" #define siphash_val(v) ((struct siphash *) String_val(v)) CAMLprim value caml_siphash_init(value key, value hashlen) { value ctx = caml_alloc_string(sizeof(struct siphash)); siphash_init(siphash_val(ctx), &Byte_u(key, 0), Int_val(hashlen)); return ctx; } CAMLprim value caml_siphash_update(value ctx, value src, value ofs, value len) { siphash_add(siphash_val(ctx), &Byte_u(src, Long_val(ofs)), Long_val(len)); return Val_unit; } CAMLprim value caml_siphash_final(value ctx, value hashlen) { CAMLparam1(ctx); CAMLlocal1(res); int len = Int_val(hashlen); res = caml_alloc_string(len); siphash_final(siphash_val(ctx), len, &Byte_u(res, 0)); CAMLreturn(res); } cryptokit-release119/src/stubs-zlib.c000066400000000000000000000163361453705265000200300ustar00rootroot00000000000000/***********************************************************************/ /* */ /* The Cryptokit library */ /* */ /* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ /* */ /* Copyright 2002 Institut National de Recherche en Informatique et */ /* en Automatique. All rights reserved. This file is distributed */ /* under the terms of the GNU Library General Public License, with */ /* the special exception on linking described in file LICENSE. */ /* */ /***********************************************************************/ /* $Id$ */ /* Stub code to interface with Zlib */ #ifdef HAVE_ZLIB #include #endif #include #include #include #include #include #include static const value * caml_zlib_error_exn = NULL; #ifdef HAVE_ZLIB #define ZStream_val(v) (*((z_streamp *)Data_custom_val(v))) static void caml_zlib_error(char * fn, value vzs) { char * msg; CAMLparam1(vzs); CAMLlocal4(s1, s2, tuple, bucket); msg = ZStream_val(vzs)->msg; if (msg == NULL) msg = ""; if (caml_zlib_error_exn == NULL) { caml_zlib_error_exn = caml_named_value("Cryptokit.Error"); if (caml_zlib_error_exn == NULL) caml_invalid_argument("Exception Cryptokit.Error not initialized"); } s1 = caml_copy_string(fn); s2 = caml_copy_string(msg); tuple = caml_alloc_small(2, 0); Field(tuple, 0) = s1; Field(tuple, 1) = s2; bucket = caml_alloc_small(2, 0); Field(bucket, 0) = *caml_zlib_error_exn; Field(bucket, 1) = tuple; CAMLdrop; caml_raise(bucket); } void caml_zlib_free_stream(value vzs) { caml_stat_free(ZStream_val(vzs)); ZStream_val(vzs) = NULL; } static struct custom_operations caml_zlib_stream_ops = { "caml_zlib_stream_ops", &caml_zlib_free_stream, NULL, NULL, NULL, NULL }; static value caml_zlib_new_stream(void) { value res = caml_alloc_custom(&caml_zlib_stream_ops, sizeof(z_streamp), 0, 1); ZStream_val(res) = caml_stat_alloc(sizeof(z_stream)); ZStream_val(res)->zalloc = NULL; ZStream_val(res)->zfree = NULL; ZStream_val(res)->opaque = NULL; ZStream_val(res)->next_in = NULL; ZStream_val(res)->next_out = NULL; return res; } CAMLprim value caml_zlib_deflateInit(value vlevel, value expect_header) { value vzs = caml_zlib_new_stream(); if (deflateInit2(ZStream_val(vzs), Int_val(vlevel), Z_DEFLATED, Bool_val(expect_header) ? MAX_WBITS : -MAX_WBITS, 8, Z_DEFAULT_STRATEGY) != Z_OK) caml_zlib_error("Zlib.deflateInit", vzs); return vzs; } static int caml_zlib_flush_table[] = { Z_NO_FLUSH, Z_SYNC_FLUSH, Z_FULL_FLUSH, Z_FINISH }; CAMLprim value caml_zlib_deflate(value vzs, value srcbuf, value srcpos, value srclen, value dstbuf, value dstpos, value dstlen, value vflush) { z_stream * zs = ZStream_val(vzs); int retcode; long used_in, used_out; value res; zs->next_in = &Byte_u(srcbuf, Long_val(srcpos)); zs->avail_in = Long_val(srclen); zs->next_out = &Byte_u(dstbuf, Long_val(dstpos)); zs->avail_out = Long_val(dstlen); retcode = deflate(zs, caml_zlib_flush_table[Int_val(vflush)]); if (retcode < 0) caml_zlib_error("Zlib.deflate", vzs); used_in = Long_val(srclen) - zs->avail_in; used_out = Long_val(dstlen) - zs->avail_out; zs->next_in = NULL; /* not required, but cleaner */ zs->next_out = NULL; /* (avoid dangling pointers into Caml heap) */ res = caml_alloc_small(3, 0); Field(res, 0) = Val_bool(retcode == Z_STREAM_END); Field(res, 1) = Val_int(used_in); Field(res, 2) = Val_int(used_out); return res; } CAMLprim value caml_zlib_deflateEnd(value vzs) { if (deflateEnd(ZStream_val(vzs)) != Z_OK) caml_zlib_error("Zlib.deflateEnd", vzs); return Val_unit; } CAMLprim value caml_zlib_inflateInit(value expect_header) { value vzs = caml_zlib_new_stream(); if (inflateInit2(ZStream_val(vzs), Bool_val(expect_header) ? MAX_WBITS : -MAX_WBITS) != Z_OK) caml_zlib_error("Zlib.inflateInit", vzs); return vzs; } CAMLprim value caml_zlib_inflate(value vzs, value srcbuf, value srcpos, value srclen, value dstbuf, value dstpos, value dstlen, value vflush) { z_stream * zs = ZStream_val(vzs); int retcode; long used_in, used_out; value res; zs->next_in = &Byte_u(srcbuf, Long_val(srcpos)); zs->avail_in = Long_val(srclen); zs->next_out = &Byte_u(dstbuf, Long_val(dstpos)); zs->avail_out = Long_val(dstlen); retcode = inflate(zs, caml_zlib_flush_table[Int_val(vflush)]); if (retcode < 0 || retcode == Z_NEED_DICT) caml_zlib_error("Zlib.inflate", vzs); used_in = Long_val(srclen) - zs->avail_in; used_out = Long_val(dstlen) - zs->avail_out; zs->next_in = NULL; /* not required, but cleaner */ zs->next_out = NULL; /* (avoid dangling pointers into Caml heap) */ res = caml_alloc_small(3, 0); Field(res, 0) = Val_bool(retcode == Z_STREAM_END); Field(res, 1) = Val_int(used_in); Field(res, 2) = Val_int(used_out); return res; } CAMLprim value caml_zlib_inflateEnd(value vzs) { if (inflateEnd(ZStream_val(vzs)) != Z_OK) caml_zlib_error("Zlib.inflateEnd", vzs); return Val_unit; } #else static void caml_zlib_not_supported(void) { value bucket; if (caml_zlib_error_exn == NULL) { caml_zlib_error_exn = caml_named_value("Cryptokit.Error"); if (caml_zlib_error_exn == NULL) caml_invalid_argument("Exception Cryptokit.Error not initialized"); } bucket = caml_alloc_small(2, 0); Field(bucket, 0) = *caml_zlib_error_exn; Field(bucket, 1) = Val_int(12); /* Compression_not_supported */ caml_raise(bucket); } CAMLprim value caml_zlib_deflateInit(value vlevel, value expect_header) { caml_zlib_not_supported(); return Val_unit; } CAMLprim value caml_zlib_deflate(value vzs, value srcbuf, value srcpos, value srclen, value dstbuf, value dstpos, value dstlen, value vflush) { caml_zlib_not_supported(); return Val_unit; } CAMLprim value caml_zlib_deflateEnd(value vzs) { caml_zlib_not_supported(); return Val_unit; } CAMLprim value caml_zlib_inflateInit(value expect_header) { caml_zlib_not_supported(); return Val_unit; } CAMLprim value caml_zlib_inflate(value vzs, value srcbuf, value srcpos, value srclen, value dstbuf, value dstpos, value dstlen, value vflush) { caml_zlib_not_supported(); return Val_unit; } CAMLprim value caml_zlib_inflateEnd(value vzs) { caml_zlib_not_supported(); return Val_unit; } #endif CAMLprim value caml_zlib_deflate_bytecode(value * arg, int nargs) { return caml_zlib_deflate(arg[0], arg[1], arg[2], arg[3], arg[4], arg[5], arg[6], arg[7]); } CAMLprim value caml_zlib_inflate_bytecode(value * arg, int nargs) { return caml_zlib_inflate(arg[0], arg[1], arg[2], arg[3], arg[4], arg[5], arg[6], arg[7]); } cryptokit-release119/test/000077500000000000000000000000001453705265000157455ustar00rootroot00000000000000cryptokit-release119/test/dune000066400000000000000000000004431453705265000166240ustar00rootroot00000000000000(test (name test) (modules test) (libraries cryptokit) (flags :standard -w -35 -alert -crypto)) (executable (name prngtest) (modules prngtest) (libraries cryptokit)) (executable (name speedtest) (modules speedtest) (libraries cryptokit) (flags :standard -w -35 -alert -crypto)) cryptokit-release119/test/prngtest.ml000066400000000000000000000034121453705265000201450ustar00rootroot00000000000000(***********************************************************************) (* *) (* The Cryptokit library *) (* *) (* Xavier Leroy, projet Gallium, INRIA Paris *) (* *) (* Copyright 2017 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file LICENSE. *) (* *) (***********************************************************************) (* Generate pseudorandom data on stdout, for testing with "dieharder" *) open Cryptokit let output_pr_data rng = let b = Bytes.create 64 in while true do rng#random_bytes b 0 64; output stdout b 0 64 done let usage() = prerr_string {|Usage: ./prngtest.native aes-ctr | dieharder -a -g 200 ./prngtest.native chacha20 | dieharder -a -g 200 ./prngtest.native hardware | dieharder -a -g 200 Warning: each dieharder run takes a long time. |}; exit 2 let _ = let seed = if Array.length Sys.argv > 2 then Sys.argv.(2) else "Supercalifragilistusexpialidolcius" in let rng = if Array.length Sys.argv > 1 then begin match Sys.argv.(1) with | "aes-ctr" -> Random.pseudo_rng_aes_ctr seed | "chacha20" -> Random.pseudo_rng seed | "hardware" -> Random.hardware_rng () | _ -> usage() end else usage() in output_pr_data rng cryptokit-release119/test/speedtest.ml000066400000000000000000000162461453705265000203100ustar00rootroot00000000000000(***********************************************************************) (* *) (* The Cryptokit library *) (* *) (* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) (* *) (* Copyright 2002 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file LICENSE. *) (* *) (***********************************************************************) (* $Id$ *) (* Performance measurement *) open Cryptokit let time_fn msg fn = let start = Sys.time() in let rec do_time nrun = let res = fn () in let stop = Sys.time() in let t = stop -. start in if t < 0.5 then do_time (nrun + 1) else begin Printf.printf "%7.3f %s\n%!" (t /. float nrun) msg; res end in do_time 1 let rec repeat n fn () = if n <= 1 then fn() else (ignore(fn()); repeat (n-1) fn ()) let raw_block_cipher cipher niter () = let msg = Bytes.create cipher#blocksize in for i = 1 to niter do cipher#transform msg 0 msg 0 done let raw_stream_cipher cipher niter blocksize () = let msg = Bytes.create blocksize in for i = 1 to niter do cipher#transform msg 0 msg 0 blocksize done let transform tr niter blocksize () = let msg = Bytes.create blocksize in for i = 1 to niter do tr#put_substring msg 0 blocksize; ignore(tr#get_substring) done let hash h niter blocksize () = let msg = Bytes.create blocksize in for i = 1 to niter do h#add_substring msg 0 blocksize done; ignore(h#result) let rng r niter blocksize () = let buf = Bytes.create blocksize in for i = 1 to niter do r#random_bytes buf 0 blocksize done let _ = time_fn "Raw AES 128, 64_000_000 bytes" (raw_block_cipher (new Block.aes_encrypt "0123456789ABCDEF") 4000000); time_fn "Raw AES 192, 64_000_000 bytes" (raw_block_cipher (new Block.aes_encrypt "0123456789ABCDEF01234567") 4000000); time_fn "Raw AES 256, 64_000_000 bytes" (raw_block_cipher (new Block.aes_encrypt "0123456789ABCDEF0123456789ABCDEF") 4000000); time_fn "Raw DES, 16_000_000 bytes" (raw_block_cipher (new Block.des_encrypt "01234567") 2000000); time_fn "Raw 3DES, 16_000_000 bytes" (raw_block_cipher (new Block.triple_des_encrypt "0123456789ABCDEF") 2000000); time_fn "Raw ARCfour, 64_000_000 bytes, 16-byte chunks" (raw_stream_cipher (new Stream.arcfour "0123456789ABCDEF") 4000000 16); time_fn "Raw ARCfour, 64_000_000 bytes, 64-byte chunks" (raw_stream_cipher (new Stream.arcfour "0123456789ABCDEF") 1000000 64); time_fn "Raw Chacha20, 64_000_000 bytes, 16-byte chunks" (raw_stream_cipher (new Stream.arcfour "0123456789ABCDEF") 4000000 16); time_fn "Raw Chacha20, 64_000_000 bytes, 64-byte chunks" (raw_stream_cipher (new Stream.arcfour "0123456789ABCDEF") 1000000 64); time_fn "Raw Blowfish 128, 64_000_000 bytes" (raw_block_cipher (new Block.blowfish_encrypt "0123456789ABCDEF") 8000000); time_fn "AES-GCM, 64_000_000 bytes" (transform (AEAD.aes_gcm ~iv:"0123456789AB" "0123456789ABCDEF" AEAD.Encrypt) 4000000 16); time_fn "Chacha20-Poly1305, 64_000_000 bytes" (transform (AEAD.chacha20_poly1305 ~iv:"0123456789AB" "0123456789ABCDEF" AEAD.Encrypt) 4000000 16); time_fn "Wrapped AES 128 CBC, 64_000_000 bytes" (transform (Cipher.aes "0123456789ABCDEF" Cipher.Encrypt) 4000000 16); time_fn "Wrapped AES 192 CBC, 64_000_000 bytes" (transform (Cipher.aes "0123456789ABCDEF01234567" Cipher.Encrypt) 4000000 16); time_fn "Wrapped AES 256 CBC, 64_000_000 bytes" (transform (Cipher.aes "0123456789ABCDEF0123456789ABCDEF" Cipher.Encrypt) 4000000 16); time_fn "Wrapped DES CBC, 16_000_000 bytes" (transform (Cipher.des "01234567" Cipher.Encrypt) 1000000 16); time_fn "Wrapped 3DES CBC, 16_000_000 bytes" (transform (Cipher.triple_des "0123456789ABCDEF" Cipher.Encrypt) 1000000 16); time_fn "Wrapped ARCfour, 64_000_000 bytes" (transform (Cipher.arcfour "0123456789ABCDEF" Cipher.Encrypt) 4000000 16); time_fn "Wrapped Chacha20, 64_000_000 bytes" (transform (Cipher.chacha20 "0123456789ABCDEF" Cipher.Encrypt) 4000000 16); time_fn "Wrapped Blowfish 128 CBC, 64_000_000 bytes" (transform (Cipher.blowfish "0123456789ABCDEF" Cipher.Encrypt) 4000000 16); time_fn "SHA-1, 64_000_000 bytes, 16-byte chunks" (hash (Hash.sha1()) 4000000 16); time_fn "SHA-256, 64_000_000 bytes, 16-byte chunks" (hash (Hash.sha256()) 4000000 16); time_fn "SHA-512, 64_000_000 bytes, 16-byte chunks" (hash (Hash.sha512()) 4000000 16); time_fn "SHA-3 256, 64_000_000 bytes, 16-byte chunks" (hash (Hash.sha3 256) 4000000 16); time_fn "SHA-3 512, 64_000_000 bytes, 16-byte chunks" (hash (Hash.sha3 512) 4000000 16); time_fn "BLAKE2b 512, 64_000_000 bytes, 16-byte chunks" (hash (Hash.blake2b 512) 4000000 16); time_fn "BLAKE2s 256, 64_000_000 bytes, 16-byte chunks" (hash (Hash.blake2s 256) 4000000 16); time_fn "BLAKE3, 64_000_000 bytes, 16-byte chunks" (hash (Hash.blake3 256) 4000000 16); time_fn "RIPEMD-160, 64_000_000 bytes, 16-byte chunks" (hash (Hash.ripemd160()) 4000000 16); time_fn "MD5, 64_000_000 bytes, 16-byte chunks" (hash (Hash.md5()) 4000000 16); time_fn "AES CMAC, 64_000_000 bytes, 16-byte chunks" (hash (MAC.aes_cmac "0123456789ABCDEF") 4000000 16); time_fn "HMAC-SHA1, 64_000_000 bytes, 16-byte chunks" (hash (MAC.hmac_sha1 "0123456789ABCDEF") 4000000 16); time_fn "HMAC-SHA256, 64_000_000 bytes, 16-byte chunks" (hash (MAC.hmac_sha256 "0123456789ABCDEF") 4000000 16); time_fn "SipHash 64, 64_000_000 bytes, 16-byte chunks" (hash (MAC.siphash "0123456789ABCDEF") 4000000 16); time_fn "SipHash 128, 64_000_000 bytes, 16-byte chunks" (hash (MAC.siphash128 "0123456789ABCDEF") 4000000 16); let prng = Random.pseudo_rng "supercalifragilistusexpialidolcius" in let key = time_fn "RSA key generation (2048 bits) x 10" (repeat 10 (fun () -> RSA.new_key ~rng:prng ~e:65537 2048)) in let plaintext = "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ" in let ciphertext = time_fn "RSA public-key operation (2048 bits, exponent 65537) x 1000" (repeat 1000 (fun () -> RSA.encrypt key plaintext)) in time_fn "RSA private-key operation (2048 bits) x 100" (repeat 100 (fun () -> ignore(RSA.decrypt key ciphertext))); time_fn "RSA private-key operation with CRT (2048 bits) x 100" (repeat 100 (fun () -> ignore(RSA.decrypt_CRT key ciphertext))); time_fn "PRNG, 64_000_000 bytes" (rng prng 1000000 64); time_fn "PRNG AES CTR, 64_000_000 bytes" (rng (Random.pseudo_rng_aes_ctr "supercalifragilistusexpialidolcius") 1000000 64); begin try let hr = Random.hardware_rng () in time_fn "Hardware RNG, 64_000_000 bytes" (rng hr 1000000 64) with Error No_entropy_source -> () end; () cryptokit-release119/test/test.ml000066400000000000000000002375341453705265000172740ustar00rootroot00000000000000(***********************************************************************) (* *) (* The Cryptokit library *) (* *) (* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) (* *) (* Copyright 2002 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License, with *) (* the special exception on linking described in file LICENSE. *) (* *) (***********************************************************************) (* $Id$ *) (* Test vectors *) open Printf open Cryptokit (* Test harness *) let error_occurred = ref false let function_tested = ref "" let testing_function s = function_tested := s; print_newline(); print_string s; print_newline() let test test_number answer correct_answer = flush stdout; flush stderr; if answer <> correct_answer then begin eprintf "*** Bad result (%s, test %d)\n" !function_tested test_number; flush stderr; error_occurred := true end else begin printf " %d..." test_number end (* Whether to run the most expensive tests or not *) let long_tests = ref false (* Useful auxiliaries *) let hex s = transform_string (Hexa.decode()) s let hexbytes s = Bytes.of_string (hex s) let tohex s = transform_string (Hexa.encode()) s (* Test hex conversion first... *) let _ = testing_function "Hex conversion"; test 1 "6162636465666768696a6b6c6d6e6f70710a" (tohex "abcdefghijklmnopq\n"); test 2 "abcdefghijklmnopq\n" (hex "616263 64656667 \n 68696a6b 6c6d6e6f\t70710a") (* Basic ciphers and hashes *) (* AES *) let _ = testing_function "AES"; let res = Bytes.create 16 in let do_test key plain cipher testno1 testno2 = let c = new Block.aes_encrypt (hex key) and d = new Block.aes_decrypt (hex key) in let plain = hexbytes plain and cipher = hexbytes cipher in c#transform plain 0 res 0; test testno1 res cipher; d#transform cipher 0 res 0; test testno2 res plain in do_test "000102030405060708090A0B0C0D0E0F" "00112233445566778899AABBCCDDEEFF" "69C4E0D86A7B0430D8CDB78070B4C55A" 1 2; do_test "000102030405060708090A0B0C0D0E0F1011121314151617" "00112233445566778899AABBCCDDEEFF" "DDA97CA4864CDFE06EAF70A0EC0D7191" 3 4; do_test "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F" "00112233445566778899AABBCCDDEEFF" "8EA2B7CA516745BFEAFC49904B496089" 5 6 (* Blowfish *) let _ = testing_function "Blowfish"; let res = Bytes.create 16 in let do_test key plain cipher testno = let c = new Block.blowfish_encrypt (hex key) and d = new Block.blowfish_decrypt (hex key) in let plain = hexbytes plain and cipher = hexbytes cipher in c#transform plain 0 res 0; d#transform cipher 0 res 8; test testno res (Bytes.cat cipher plain) in do_test "0000000000000000" "0000000000000000" "4EF997456198DD78" 1; do_test "FFFFFFFFFFFFFFFF" "FFFFFFFFFFFFFFFF" "51866FD5B85ECB8A" 2; do_test "3000000000000000" "1000000000000001" "7D856F9A613063F2" 3; do_test "1111111111111111" "1111111111111111" "2466DD878B963C9D" 4; do_test "0123456789ABCDEF" "1111111111111111" "61F9C3802281B096" 5; do_test "1111111111111111" "0123456789ABCDEF" "7D0CC630AFDA1EC7" 6; do_test "0000000000000000" "0000000000000000" "4EF997456198DD78" 7; do_test "FEDCBA9876543210" "0123456789ABCDEF" "0ACEAB0FC6A0A28D" 8; do_test "7CA110454A1A6E57" "01A1D6D039776742" "59C68245EB05282B" 9; do_test "0131D9619DC1376E" "5CD54CA83DEF57DA" "B1B8CC0B250F09A0" 10; do_test "07A1133E4A0B2686" "0248D43806F67172" "1730E5778BEA1DA4" 11; do_test "3849674C2602319E" "51454B582DDF440A" "A25E7856CF2651EB" 12; do_test "04B915BA43FEB5B6" "42FD443059577FA2" "353882B109CE8F1A" 13; do_test "0113B970FD34F2CE" "059B5E0851CF143A" "48F4D0884C379918" 14; do_test "0170F175468FB5E6" "0756D8E0774761D2" "432193B78951FC98" 15; do_test "43297FAD38E373FE" "762514B829BF486A" "13F04154D69D1AE5" 16; do_test "07A7137045DA2A16" "3BDD119049372802" "2EEDDA93FFD39C79" 17; do_test "04689104C2FD3B2F" "26955F6835AF609A" "D887E0393C2DA6E3" 18; do_test "37D06BB516CB7546" "164D5E404F275232" "5F99D04F5B163969" 19; do_test "1F08260D1AC2465E" "6B056E18759F5CCA" "4A057A3B24D3977B" 20; do_test "584023641ABA6176" "004BD6EF09176062" "452031C1E4FADA8E" 21; do_test "025816164629B007" "480D39006EE762F2" "7555AE39F59B87BD" 22; do_test "49793EBC79B3258F" "437540C8698F3CFA" "53C55F9CB49FC019" 23; do_test "4FB05E1515AB73A7" "072D43A077075292" "7A8E7BFA937E89A3" 24; do_test "49E95D6D4CA229BF" "02FE55778117F12A" "CF9C5D7A4986ADB5" 25; do_test "018310DC409B26D6" "1D9D5C5018F728C2" "D1ABB290658BC778" 26; do_test "1C587F1C13924FEF" "305532286D6F295A" "55CB3774D13EF201" 27; do_test "0101010101010101" "0123456789ABCDEF" "FA34EC4847B268B2" 28; do_test "1F1F1F1F0E0E0E0E" "0123456789ABCDEF" "A790795108EA3CAE" 29; do_test "E0FEE0FEF1FEF1FE" "0123456789ABCDEF" "C39E072D9FAC631D" 30; do_test "0000000000000000" "FFFFFFFFFFFFFFFF" "014933E0CDAFF6E4" 31; do_test "FFFFFFFFFFFFFFFF" "0000000000000000" "F21E9A77B71C49BC" 32; do_test "0123456789ABCDEF" "0000000000000000" "245946885754369A" 33; do_test "FEDCBA9876543210" "FFFFFFFFFFFFFFFF" "6B5C5A9C5D9E0A5A" 34 (* DES *) let _ = testing_function "DES"; let res = Bytes.create 8 in let c = new Block.des_encrypt (hex "0123456789abcdef") and d = new Block.des_decrypt (hex "0123456789abcdef") in let plain = hexbytes "0123456789abcde7" and cipher = hexbytes "c95744256a5ed31d" in c#transform plain 0 res 0; test 1 res cipher; d#transform cipher 0 res 0; test 2 res plain; let rec iter n key input = if n <= 0 then key else begin let c = new Block.des_encrypt key in let t1 = Bytes.create 8 in c#transform input 0 t1 0; let t2 = Bytes.create 8 in c#transform t1 0 t2 0; let d = new Block.des_decrypt (Bytes.unsafe_to_string t2) in let t3 = Bytes.create 8 in d#transform t1 0 t3 0; iter (n-1) (Bytes.unsafe_to_string t3) t1 end in test 3 (iter 64 (hex "5555555555555555") (hexbytes "ffffffffffffffff")) (hex "246e9db9c550381a") (* Triple DES *) let _ = testing_function "Triple DES"; let res = Bytes.create 8 in let do_test key plain cipher testno1 testno2 = let c = new Block.triple_des_encrypt (hex key) and d = new Block.triple_des_decrypt (hex key) in let plain = hexbytes plain and cipher = hexbytes cipher in c#transform plain 0 res 0; test testno1 res cipher; d#transform cipher 0 res 0; test testno2 res plain in do_test "0123456789abcdeffedcba9876543210" "0123456789abcde7" "7f1d0a77826b8aff" 1 2; do_test "0123456789abcdef0123456789abcdef" "0123456789abcde7" "c95744256a5ed31d" 3 4; do_test "0123456789abcdeffedcba987654321089abcdef01234567" "0123456789abcde7" "de0b7c06ae5e0ed5" 5 6 (* ARCfour *) let _ = testing_function "ARCfour"; let do_test n1 n2 key input output = let key = hex key and input = hexbytes input and output = hexbytes output in let c = new Stream.arcfour key in let d = new Stream.arcfour key in let res = Bytes.create (Bytes.length input) in c#transform input 0 res 0 (Bytes.length input); test n1 res output; d#transform output 0 res 0 (Bytes.length output); test n2 res input in do_test 1 2 "0123456789abcdef" "0123456789abcdef" "75b7878099e0c596"; do_test 3 4 "0123456789abcdef" "0000000000000000" "7494c2e7104b0879"; do_test 5 6 "0000000000000000" "0000000000000000" "de188941a3375d3a"; do_test 7 8 "ef012345" "00000000000000000000" "d6a141a7ec3c38dfbd61"; let c2 = Cipher.arcfour "key" Cipher.Encrypt in c2#put_string (String.make 1024 'x'); test 9 c2#available_output 1024 (* Chacha20 *) let _ = testing_function "Chacha20"; let do_test n1 n2 key nonce plain cipher counter = let key = hex key and nonce = hex nonce and plain = hexbytes plain and cipher = hexbytes cipher in let c = new Stream.chacha20 ~iv:nonce ~ctr:counter key in let d = new Stream.chacha20 ~iv:nonce ~ctr:counter key in let res = Bytes.create (Bytes.length plain) in c#transform plain 0 res 0 (Bytes.length plain); test n1 res cipher; d#transform cipher 0 res 0 (Bytes.length cipher); test n2 res plain in do_test 1 2 "0000000000000000000000000000000000000000000000000000000000000000" "0000000000000000" "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" "76b8e0ada0f13d90405d6ae55386bd28bdd219b8a08ded1aa836efcc8b770dc7da41597c5157488d7724e03fb8d84a376a43b8f41518a11cc387b669b2ee6586" 0L; do_test 3 4 "0000000000000000000000000000000000000000000000000000000000000001" "0000000000000002" "416e79207375626d697373696f6e20746f20746865204945544620696e74656e6465642062792074686520436f6e7472696275746f7220666f72207075626c69636174696f6e20617320616c6c206f722070617274206f6620616e204945544620496e7465726e65742d4472616674206f722052464320616e6420616e792073746174656d656e74206d6164652077697468696e2074686520636f6e74657874206f6620616e204945544620616374697669747920697320636f6e7369646572656420616e20224945544620436f6e747269627574696f6e222e20537563682073746174656d656e747320696e636c756465206f72616c2073746174656d656e747320696e20494554462073657373696f6e732c2061732077656c6c206173207772697474656e20616e6420656c656374726f6e696320636f6d6d756e69636174696f6e73206d61646520617420616e792074696d65206f7220706c6163652c207768696368206172652061646472657373656420746f" "a3fbf07df3fa2fde4f376ca23e82737041605d9f4f4f57bd8cff2c1d4b7955ec2a97948bd3722915c8f3d337f7d370050e9e96d647b7c39f56e031ca5eb6250d4042e02785ececfa4b4bb5e8ead0440e20b6e8db09d881a7c6132f420e52795042bdfa7773d8a9051447b3291ce1411c680465552aa6c405b7764d5e87bea85ad00f8449ed8f72d0d662ab052691ca66424bc86d2df80ea41f43abf937d3259dc4b2d0dfb48a6c9139ddd7f76966e928e635553ba76c5c879d7b35d49eb2e62b0871cdac638939e25e8a1e0ef9d5280fa8ca328b351c3c765989cbcf3daa8b6ccc3aaf9f3979c92b3720fc88dc95ed84a1be059c6499b9fda236e7e818b04b0bc39c1e876b193bfe5569753f88128cc08aaa9b63d1a16f80ef2554d7189c411f5869ca52c5b83fa36ff216b9c1d30062bebcfd2dc5bce0911934fda79a86f6e698ced759c3ff9b6477338f3da4f9cd8514ea9982ccafb341b2384dd902f3d1ab7ac61dd29c6f21ba5b862f3730e37cfdc4fd806c22f221" 1L; do_test 5 6 "1c9240a5eb55d38af333888604f6b5f0473917c1402b80099dca5cbc207075c0" "0000000000000002" "2754776173206272696c6c69672c20616e642074686520736c6974687920746f7665730a446964206779726520616e642067696d626c6520696e2074686520776162653a0a416c6c206d696d737920776572652074686520626f726f676f7665732c0a416e6420746865206d6f6d65207261746873206f757467726162652e" "62e6347f95ed87a45ffae7426f27a1df5fb69110044c0d73118effa95b01e5cf166d3df2d721caf9b21e5fb14c616871fd84c54f9d65b283196c7fe4f60553ebf39c6402c42234e32a356b3e764312a61a5532055716ead6962568f87d3f3f7704c6a8d1bcd1bf4d50d6154b6da731b187b58dfd728afa36757a797ac188d1" 42L; (* From RFC 7539 *) do_test 7 8 "00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f" "00 00 00 00 00 00 00 4a 00 00 00 00" "4c 61 64 69 65 73 20 61 6e 64 20 47 65 6e 74 6c 65 6d 65 6e 20 6f 66 20 74 68 65 20 63 6c 61 73 73 20 6f 66 20 27 39 39 3a 20 49 66 20 49 20 63 6f 75 6c 64 20 6f 66 66 65 72 20 79 6f 75 20 6f 6e 6c 79 20 6f 6e 65 20 74 69 70 20 66 6f 72 20 74 68 65 20 66 75 74 75 72 65 2c 20 73 75 6e 73 63 72 65 65 6e 20 77 6f 75 6c 64 20 62 65 20 69 74 2e" "6e 2e 35 9a 25 68 f9 80 41 ba 07 28 dd 0d 69 81 e9 7e 7a ec 1d 43 60 c2 0a 27 af cc fd 9f ae 0b f9 1b 65 c5 52 47 33 ab 8f 59 3d ab cd 62 b3 57 16 39 d6 24 e6 51 52 ab 8f 53 0c 35 9f 08 61 d8 07 ca 0d bf 50 0d 6a 61 56 a3 8e 08 8a 22 b6 5e 52 bc 51 4d 16 cc f8 06 81 8c e9 1a b7 79 37 36 5a f9 0b bf 74 a3 5b e6 b4 0b 8e ed f2 78 5e 42 87 4d" 1L (* Blowfish *) let _ = testing_function "Blowfish"; let testcnt = ref 0 in let res = Bytes.create 8 in let do_test (key, plain, cipher) = let key = hex key and plain = hexbytes plain and cipher = hexbytes cipher in let c = new Block.blowfish_encrypt key and d = new Block.blowfish_decrypt key in c#transform plain 0 res 0; incr testcnt; test !testcnt res cipher; d#transform cipher 0 res 0; incr testcnt; test !testcnt res plain in List.iter do_test [ ("0000000000000000", "0000000000000000", "4EF997456198DD78"); ("FFFFFFFFFFFFFFFF", "FFFFFFFFFFFFFFFF", "51866FD5B85ECB8A"); ("3000000000000000", "1000000000000001", "7D856F9A613063F2"); ("1111111111111111", "1111111111111111", "2466DD878B963C9D"); ("0123456789ABCDEF", "1111111111111111", "61F9C3802281B096"); ("1111111111111111", "0123456789ABCDEF", "7D0CC630AFDA1EC7"); ("0000000000000000", "0000000000000000", "4EF997456198DD78"); ("FEDCBA9876543210", "0123456789ABCDEF", "0ACEAB0FC6A0A28D"); ("7CA110454A1A6E57", "01A1D6D039776742", "59C68245EB05282B"); ("0131D9619DC1376E", "5CD54CA83DEF57DA", "B1B8CC0B250F09A0"); ("07A1133E4A0B2686", "0248D43806F67172", "1730E5778BEA1DA4"); ("3849674C2602319E", "51454B582DDF440A", "A25E7856CF2651EB"); ("04B915BA43FEB5B6", "42FD443059577FA2", "353882B109CE8F1A"); ("0113B970FD34F2CE", "059B5E0851CF143A", "48F4D0884C379918"); ("0170F175468FB5E6", "0756D8E0774761D2", "432193B78951FC98"); ("43297FAD38E373FE", "762514B829BF486A", "13F04154D69D1AE5"); ("07A7137045DA2A16", "3BDD119049372802", "2EEDDA93FFD39C79"); ("04689104C2FD3B2F", "26955F6835AF609A", "D887E0393C2DA6E3"); ("37D06BB516CB7546", "164D5E404F275232", "5F99D04F5B163969"); ("1F08260D1AC2465E", "6B056E18759F5CCA", "4A057A3B24D3977B"); ("584023641ABA6176", "004BD6EF09176062", "452031C1E4FADA8E"); ("025816164629B007", "480D39006EE762F2", "7555AE39F59B87BD"); ("49793EBC79B3258F", "437540C8698F3CFA", "53C55F9CB49FC019"); ("4FB05E1515AB73A7", "072D43A077075292", "7A8E7BFA937E89A3"); ("49E95D6D4CA229BF", "02FE55778117F12A", "CF9C5D7A4986ADB5"); ("018310DC409B26D6", "1D9D5C5018F728C2", "D1ABB290658BC778"); ("1C587F1C13924FEF", "305532286D6F295A", "55CB3774D13EF201"); ("0101010101010101", "0123456789ABCDEF", "FA34EC4847B268B2"); ("1F1F1F1F0E0E0E0E", "0123456789ABCDEF", "A790795108EA3CAE"); ("E0FEE0FEF1FEF1FE", "0123456789ABCDEF", "C39E072D9FAC631D"); ("0000000000000000", "FFFFFFFFFFFFFFFF", "014933E0CDAFF6E4"); ("FFFFFFFFFFFFFFFF", "0000000000000000", "F21E9A77B71C49BC"); ("0123456789ABCDEF", "0000000000000000", "245946885754369A"); ("FEDCBA9876543210", "FFFFFFFFFFFFFFFF", "6B5C5A9C5D9E0A5A") ] (* AES-GCM *) let _ = testing_function "AES-GCM"; let testcnt = ref 0 in let do_test (key, plain, header, iv, cipher, tag) = let key = hex key and plain = hex plain and header = hex header and iv = hex iv and cipher = hex cipher and tag = hex tag in let c = AEAD.(aes_gcm ~header ~iv key Encrypt) in let ct = auth_transform_string c plain in incr testcnt; test !testcnt ct (cipher ^ tag); let d = AEAD.(aes_gcm ~header ~iv key Decrypt) in let pp = auth_check_transform_string d ct in incr testcnt; test !testcnt pp (Some plain) in List.iter do_test [ ("00000000000000000000000000000000", "", "", "000000000000000000000000", "", "58e2fccefa7e3061367f1d57a4e7455a"); ("00000000000000000000000000000000", "00000000000000000000000000000000", "", "000000000000000000000000", "0388dace60b6a392f328c2b971b2fe78", "ab6e47d42cec13bdf53a67b21257bddf"); ("feffe9928665731c6d6a8f9467308308", "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255", "", "cafebabefacedbaddecaf888", "42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e21d514b25466931c7d8f6a5aac84aa051ba30b396a0aac973d58e091473f5985", "4d5c2af327cd64a62cf35abd2ba6fab4"); ("feffe9928665731c6d6a8f9467308308", "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39", "feedfacedeadbeeffeedfacedeadbeefabaddad2", "cafebabefacedbaddecaf888", "42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e21d514b25466931c7d8f6a5aac84aa051ba30b396a0aac973d58e091", "5bc94fbc3221a5db94fae95ae7121a47"); ("feffe9928665731c6d6a8f9467308308", "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39", "feedfacedeadbeeffeedfacedeadbeefabaddad2", "cafebabefacedbaddecaf888", "42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e21d514b25466931c7d8f6a5aac84aa051ba30b396a0aac973d58e091", "5bc94fbc3221a5db94fae95ae7121a47"); ("feffe9928665731c6d6a8f9467308308", "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39", "feedfacedeadbeeffeedfacedeadbeefabaddad2", "cafebabefacedbad", "61353b4c2806934a777ff51fa22a4755699b2a714fcdc6f83766e5f97b6c742373806900e49f24b22b097544d4896b424989b5e1ebac0f07c23f4598", "3612d2e79e3b0785561be14aaca2fccb"); ("feffe9928665731c6d6a8f9467308308", "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39", "feedfacedeadbeeffeedfacedeadbeefabaddad2", "9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b", "8ce24998625615b603a033aca13fb894be9112a5c3a211a8ba262a3cca7e2ca701e4a9a4fba43c90ccdcb281d48c7c6fd62875d2aca417034c34aee5", "619cc5aefffe0bfa462af43c1699d050") ] (* Chacha20-Poly1305 *) let _ = testing_function "Chacha20-Poly1305"; let testcnt = ref 0 in let do_test (key, iv, plain, header, cipher, tag) = let key = hex key and iv = hex iv and cipher = hex cipher and tag = hex tag in let c = AEAD.(chacha20_poly1305 ~header ~iv key Encrypt) in let ct = auth_transform_string c plain in incr testcnt; test !testcnt ct (cipher ^ tag); let d = AEAD.(chacha20_poly1305 ~header ~iv key Decrypt) in let pp = auth_check_transform_string d ct in incr testcnt; test !testcnt pp (Some plain) in List.iter do_test [ (* From RFC 7539 *) ("808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f", "070000004041424344454647", "Ladies and Gentlemen of the class of '99: If I could offer you only one tip for the future, sunscreen would be it.", hex "50515253c0c1c2c3c4c5c6c7", "d31a8d34648e60db7b86afbc53ef7ec2a4aded51296e08fea9e2b5a736ee62d63dbea45e8ca9671282fafb69da92728b1a71de0a9e060b2905d6a5b67ecd3b3692ddbd7f2d778b8c9803aee328091b58fab324e4fad675945585808b4831d7bc3ff4def08e4b7a9de576d26586cec64b6116", "1ae10b594f09e26a7e902ecbd0600691"); (* From BoringSSL *) (* Test padding AD with 15 zeros in the tag calculation. *) ("808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f", "070000004041424344454647", "123456789abcdef0", "1", "ae49da6934cb77822c83ed9852e46c9e", "dac9c841c168379dcf8f2bb8e22d6da2"); (* Test padding IN with 15 zeros in the tag calculation. *) ("808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f", "070000004041424344454647", "1", "123456789abcdef0", "ae", "3ed2f824f901a8994052f852127c196a"); (* Test padding AD with 1 zero in the tag calculation. *) ("808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f", "070000004041424344454647", "123456789abcdef0", "123456789abcdef", "ae49da6934cb77822c83ed9852e46c9e", "2e9c9b1689adb5ec444002eb920efb66"); (* Test padding IN with 1 zero in the tag calculation. *) ("808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f", "070000004041424344454647", "123456789abcdef", "123456789abcdef0", "ae49da6934cb77822c83ed9852e46c", "05b2937f8bbc64fed21f0fb74cd7147c"); (* Test maximal nonce value. *) ("808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f", "ffffffffffffffffffffffff", "123456789abcdef0", "123456789abcdef0", "e275aeb341e1fc9a70c4fd4496fc7cdb", "41acd0560ea6843d3e5d4e5babf6e946"); (* Empty text *) ("9a97f65b9b4c721b960a672145fca8d4e32e67f9111ea979ce9c4826806aeee6", "000000003de9c0da2bd7f91e", "", "", "", "5a6e21f4ba6dbee57380e79e79c30def") ] (* Input message: a million 'a' *) let hash_million_a (h: hash) = for i = 1 to 10_000 do h#add_string "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" done; h#result (* Input message: the extremely-long message "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmno" repeated 16,777,216 times: a bit string of length 2^{33} bits. This test is from the SHA-3 Candidate Algorithm Submissions document. *) let hash_extremely_long (h: hash) = for i = 1 to 16_777_216 do h#add_string "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmno" done; h#result (* SHA-1 *) let _ = testing_function "SHA-1"; let hash s = hash_string (Hash.sha1()) s in test 1 (hash "") (hex "da39a3ee5e6b4b0d3255bfef95601890afd80709"); test 2 (hash "a") (hex "86f7e437faa5a7fce15d1ddcb9eaeaea377667b8"); test 3 (hash "abc") (hex "a9993e364706816aba3e25717850c26c9cd0d89d"); test 4 (hash "abcdefghijklmnopqrstuvwxyz") (hex "32d10c7b8cf96570ca04ce37f2a19d84240d3a89"); test 5 (hash "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq") (hex "84983E441C3BD26EBAAE4AA1F95129E5E54670F1"); test 6 (hash_million_a (Hash.sha1())) (hex "34AA973CD4C4DAA4F61EEB2BDBAD27316534016F"); if !long_tests then test 99 (hash_extremely_long (Hash.sha1())) (hex "7789f0c9 ef7bfc40 d9331114 3dfbe69e 2017f592") (* SHA-224 *) let _ = testing_function "SHA-2 224"; let hash s = hash_string (Hash.sha2 224) s in test 1 (hash "abc") (hex "23097d22 3405d822 8642a477 bda255b3 2aadbce4 bda0b3f7 e36c9da7"); test 2 (hash "") (hex "d14a028c 2a3a2bc9 476102bb 288234c4 15a2b01f 828ea62a c5b3e42f"); test 3 (hash "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq") (hex "75388b16 512776cc 5dba5da1 fd890150 b0c6455c b4f58b19 52522525"); test 4 (hash_million_a (Hash.sha2 224)) (hex "20794655 980c91d8 bbb4c1ea 97618a4b f03f4258 1948b2ee 4ee7ad67") (* SHA-256 *) let _ = testing_function "SHA-2 256"; let hash s = hash_string (Hash.sha2 256) s in test 1 (hash "abc") (hex "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"); test 2 (hash "") (hex "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"); test 3 (hash "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq") (hex "248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1"); test 4 (hash_million_a (Hash.sha2 256)) (hex "cdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0"); if !long_tests then test 99 (hash_extremely_long (Hash.sha256())) (hex "50e72a0e 26442fe2 552dc393 8ac58658 228c0cbf b1d2ca87 2ae43526 6fcd055e") (* SHA-384 *) let _ = testing_function "SHA-2 384"; let hash s = hash_string (Hash.sha2 384) s in test 1 (hash "abc") (hex "cb00753f45a35e8b b5a03d699ac65007 272c32ab0eded163 1a8b605a43ff5bed 8086072ba1e7cc23 58baeca134c825a7"); test 2 (hash "") (hex "38b060a751ac9638 4cd9327eb1b1e36a 21fdb71114be0743 4c0cc7bf63f6e1da 274edebfe76f65fb d51ad2f14898b95b"); test 3 (hash "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq") (hex "3391fdddfc8dc739 3707a65b1b470939 7cf8b1d162af05ab fe8f450de5f36bc6 b0455a8520bc4e6f 5fe95b1fe3c8452b"); test 4 (hash_million_a (Hash.sha2 384)) (hex "9d0e1809716474cb 086e834e310a4a1c ed149e9c00f24852 7972cec5704c2a5b 07b8b3dc38ecc4eb ae97ddd87f3d8985") (* SHA-512 *) let _ = testing_function "SHA-2 512"; let hash s = hash_string (Hash.sha2 512) s in test 1 (hash "abc") (hex "ddaf35a193617aba cc417349ae204131 12e6fa4e89a97ea2 0a9eeee64b55d39a 2192992a274fc1a8 36ba3c23a3feebbd 454d4423643ce80e 2a9ac94fa54ca49f"); test 2 (hash "") (hex "cf83e1357eefb8bd f1542850d66d8007 d620e4050b5715dc 83f4a921d36ce9ce 47d0d13c5d85f2b0 ff8318d2877eec2f 63b931bd47417a81 a538327af927da3e"); test 3 (hash "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq") (hex "204a8fc6dda82f0a 0ced7beb8e08a416 57c16ef468b228a8 279be331a703c335 96fd15c13b1b07f9 aa1d3bea57789ca0 31ad85c7a71dd703 54ec631238ca3445"); test 4 (hash "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu") (hex "8e959b75dae313da 8cf4f72814fc143f 8f7779c6eb9f7fa1 7299aeadb6889018 501d289e4900f7e4 331b99dec4b5433a c7d329eeb6dd2654 5e96e55b874be909"); test 5 (hash_million_a (Hash.sha2 512)) (hex "e718483d0ce76964 4e2e42c7bc15b463 8e1f98b13b204428 5632a803afa973eb de0ff244877ea60a 4cb0432ce577c31b eb009c5c2c49aa2e 4eadb217ad8cc09b"); if !long_tests then test 99 (hash_extremely_long (Hash.sha2 512)) (hex "b47c933421ea2db1 49ad6e10fce6c7f9 3d0752380180ffd7 f4629a712134831d 77be6091b819ed35 2c2967a2e2d4fa50 50723c9630691f1a 05a7281dbe6c1086") (* SHA-3 *) let _ = testing_function "SHA-3"; let hash n s = hash_string (Hash.sha3 n) s in let s = "" in test 1 (hash 224 s) (hex "6b4e03423667dbb7 3b6e15454f0eb1ab d4597f9a1b078e3f 5b5a6bc7"); test 2 (hash 256 s) (hex "a7ffc6f8bf1ed766 51c14756a061d662 f580ff4de43b49fa 82d80a4b80f8434a"); test 3 (hash 384 s) (hex "0c63a75b845e4f7d 01107d852e4c2485 c51a50aaaa94fc61 995e71bbee983a2a c3713831264adb47 fb6bd1e058d5f004"); test 4 (hash 512 s) (hex "a69f73cca23a9ac5 c8b567dc185a756e 97c982164fe25859 e0d1dcc1475c80a6 15b2123af1f5f94c 11e3e9402c3ac558 f500199d95b6d3e3 01758586281dcd26"); let s = "abc" in test 5 (hash 224 s) (hex "e642824c3f8cf24a d09234ee7d3c766f c9a3a5168d0c94ad 73b46fdf"); test 6 (hash 256 s) (hex "3a985da74fe225b2 045c172d6bd390bd 855f086e3e9d525b 46bfe24511431532"); test 7 (hash 384 s) (hex "ec01498288516fc9 26459f58e2c6ad8d f9b473cb0fc08c25 96da7cf0e49be4b2 98d88cea927ac7f5 39f1edf228376d25"); test 8 (hash 512 s) (hex "b751850b1a57168a 5693cd924b6b096e 08f621827444f70d 884f5d0240d2712e 10e116e9192af3c9 1a7ec57647e39340 57340b4cf408d5a5 6592f8274eec53f0"); let s = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" in test 9 (hash 224 s) (hex "8a24108b154ada21 c9fd5574494479ba 5c7e7ab76ef264ea d0fcce33"); test 10 (hash 256 s) (hex "41c0dba2a9d62408 49100376a8235e2c 82e1b9998a999e21 db32dd97496d3376"); test 11 (hash 384 s) (hex "991c665755eb3a4b 6bbdfb75c78a492e 8c56a22c5c4d7e42 9bfdbc32b9d4ad5a a04a1f076e62fea1 9eef51acd0657c22"); test 12 (hash 512 s) (hex "04a371e84ecfb5b8 b77cb48610fca818 2dd457ce6f326a0f d3d7ec2f1e91636d ee691fbe0c985302 ba1b0d8dc78c0863 46b533b49c030d99 a27daf1139d6e75e"); let s = "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu" in test 13 (hash 224 s) (hex "543e6868e1666c1a 643630df77367ae5 a62a85070a51c14c bf665cbc"); test 14 (hash 256 s) (hex "916f6061fe879741 ca6469b43971dfdb 28b1a32dc36cb325 4e812be27aad1d18"); test 15 (hash 384 s) (hex "79407d3b5916b59c 3e30b09822974791 c313fb9ecc849e40 6f23592d04f625dc 8c709b98b43b3852 b337216179aa7fc7"); test 16 (hash 512 s) (hex "afebb2ef542e6579 c50cad06d2e578f9 f8dd6881d7dc824d 26360feebf18a4fa 73e3261122948efc fd492e74e82e2189 ed0fb440d187f382 270cb455f21dd185"); test 17 (hash_million_a (Hash.sha3 224)) (hex "d69335b93325192e 516a912e6d19a15c b51c6ed5c15243e7 a7fd653c"); test 18 (hash_million_a (Hash.sha3 256)) (hex "5c8875ae474a3634 ba4fd55ec85bffd6 61f32aca75c6d699 d0cdcb6c115891c1"); test 19 (hash_million_a (Hash.sha3 384)) (hex "eee9e24d78c18553 37983451df97c8ad 9eedf256c6334f8e 948d252d5e0e7684 7aa0774ddb90a842 190d2c558b4b8340"); test 20 (hash_million_a (Hash.sha3 512)) (hex "3c3a876da14034ab 60627c077bb98f7e 120a2a5370212dff b3385a18d4f38859 ed311d0a9d5141ce 9cc5c66ee689b266 a8aa18ace8282a0e 0db596c90b0a7b87"); if !long_tests then test 99 (hash_extremely_long (Hash.sha3 512)) (hex "235ffd53504ef836 a1342b488f483b39 6eabbfe642cf78ee 0d31feec788b23d0 d18d5c339550dd59 58a500d4b95363da 1b5fa18affc1bab2 292dc63b7d85097c") (* Keccak *) (* The test cases are taken from commit dec7e6dd8e5bbfe4534f7dd4c3fb4429575b23f8 *) let _ = testing_function "Keccak"; let hash n s = hash_string (Hash.keccak n) s in let s = "abc" in test 1 (hash 224 s) (hex "c30411768506ebe1 c2871b1ee2e87d38 df342317300a9b97 a95ec6a8"); test 2 (hash 256 s) (hex "4e03657aea45a94f c7d47ba826c8d667 c0d1e6e33a64a036 ec44f58fa12d6c45"); test 3 (hash 384 s) (hex "f7df1165f033337b e098e7d288ad6a2f 74409d7a60b49c36 642218de161b1f99 f8c681e4afaf31a3 4db29fb763e3c28e"); test 4 (hash 512 s) (hex "18587dc2ea106b9a 1563e32b3312421c a164c7f1f07bc922 a9c83d77cea3a1e5 d0c6991073902537 2dc14ac964262937 9540c17e2a65b19d 77aa511a9d00bb96"); let s = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" in test 5 (hash 224 s) (hex "e51faa2b4655150b 931ee8d700dc202f 763ca5f962c529ea e55012b6"); test 6 (hash 256 s) (hex "45d3b367a6904e6e 8d502ee04999a7c2 7647f91fa845d456 525fd352ae3d7371"); test 7 (hash 384 s) (hex "b41e8896428f1bcb b51e17abd6acc980 52a3502e0d5bf7fa 1af949b4d3c855e7 c4dc2c390326b3f3 e74c7b1e2b9a3657"); test 8 (hash 512 s) (hex "6aa6d3669597df6d 5a007b00d09c2079 5b5c4218234e1698 a944757a488ecdc0 9965435d97ca32c3 cfed7201ff30e070 cd947f1fc12b9d92 14c467d342bcba5d"); let s = "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu" in test 9 (hash 224 s) (hex "344298994b1b0687 3eae2ce739c425c4 7291a2e24189e01b 524f88dc"); test 10 (hash 256 s) (hex "f519747ed599024f 3882238e5ab43960 132572b7345fbeb9 a90769dafd21ad67"); test 11 (hash 384 s) (hex "cc063f3468513536 8b34f7449108f6d1 0fa727b09d696ec5 331771da46a923b6 c34dbd1d4f77e595 689c1f3800681c28"); test 12 (hash 512 s) (hex "ac2fb35251825d3a a48468a9948c0a91 b8256f6d97d8fa41 60faff2dd9dfcc24 f3f1db7a983dad13 d53439ccac0b37e2 4037e7b95f80f59f 37a2f683c4ba4682"); test 13 (hash_million_a (Hash.keccak 224)) (hex "19f9167be2a04c43 abd0ed554788101b 9c339031acc8e146 8531303f"); test 14 (hash_million_a (Hash.keccak 256)) (hex "fadae6b49f129bbb 812be8407b7b2894 f34aecf6dbd1f9b0 f0c7e9853098fc96"); test 15 (hash_million_a (Hash.keccak 384)) (hex "0c8324e1ebc18282 2c5e2a086cac07c2 fe00e3bce61d01ba 8ad6b71780e2dec5 fb89e5ae90cb593e 57bc6258fdd94e17"); test 16 (hash_million_a (Hash.keccak 512)) (hex "5cf53f2e556be5a6 24425ede23d0e8b2 c7814b4ba0e4e09c bbf3c2fac7056f61 e048fc341262875e bc58a5183fea6514 47124370c1ebf4d6 c89bc9a7731063bb"); let s = "" in test 17 (hash 224 s) (hex "f71837502ba8e108 37bdd8d365adb855 91895602fc552b48 b7390abd"); test 18 (hash 256 s) (hex "c5d2460186f7233c 927e7db2dcc703c0 e500b653ca82273b 7bfad8045d85a470"); test 19 (hash 384 s) (hex "2c23146a63a29acf 99e73b88f8c24eaa 7dc60aa771780ccc 006afbfa8fe2479b 2dd2b21362337441 ac12b515911957ff"); test 20 (hash 512 s) (hex "0eab42de4c3ceb92 35fc91acffe746b2 9c29a8c366b7c60e 4e67c466f36a4304 c00fa9caf9d87976 ba469bcbe06713b4 35f091ef2769fb16 0cdab33d3670680e"); if !long_tests then test 98 (hash_extremely_long (Hash.keccak 256)) (hex "5f313c39963dcf79 2b5470d4ade9f3a3 56a3e4021748690a 958372e2b06f82a4"); if !long_tests then test 99 (hash_extremely_long (Hash.keccak 512)) (hex "3e122edaf3739823 1cfaca4c7c216c9d 66d5b899ec1d7ac6 17c40c7261906a45 fc01617a021e5da3 bd8d4182695b5cb7 85a28237cbb16759 0e34718e56d8aab8") (* BLAKE2b *) let _ = testing_function "BLAKE2b-512"; let hash s = hash_string (Hash.blake2b512 ()) s in test 1 (hash "") (hex "786a02f742015903c6c6fd852552d272912f4740e15847618a86e217f71f5419d25e1031afee585313896444934eb04b903a685b1448b755d56f701afe9be2ce"); test 2 (hash "abc") (hex "ba80a53f981c4d0d6a2797b69f12f6e94c212f14685ac4b74b12bb6fdbffa2d17d87c5392aab792dc252d5de4533cc9518d38aa8dbf1925ab92386edd4009923"); test 3 (hash "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu") (hex "ce741ac5930fe346811175c5227bb7bfcd47f42612fae46c0809514f9e0e3a11ee1773287147cdeaeedff50709aa716341fe65240f4ad6777d6bfaf9726e5e52") let _ = testing_function "BLAKE2b-512 (keyed)"; let mkstring n = String.init n (fun i -> Char.chr i) in let key = mkstring 0x40 in let hash s = hash_string (MAC.blake2b512 key) s in List.iter (fun (len, result) -> test len (hash (mkstring len)) (hex result)) [ 0, "10ebb67700b1868efb4417987acf4690ae9d972fb7a590c2f02871799aaa4786b5e996e8f0f4eb981fc214b005f42d2ff4233499391653df7aefcbc13fc51568"; 1, "961f6dd1e4dd30f63901690c512e78e4b45e4742ed197c3c5e45c549fd25f2e4187b0bc9fe30492b16b0d0bc4ef9b0f34c7003fac09a5ef1532e69430234cebd"; 2, "da2cfbe2d8409a0f38026113884f84b50156371ae304c4430173d08a99d9fb1b983164a3770706d537f49e0c916d9f32b95cc37a95b99d857436f0232c88a965"; 3, "33d0825dddf7ada99b0e7e307104ad07ca9cfd9692214f1561356315e784f3e5a17e364ae9dbb14cb2036df932b77f4b292761365fb328de7afdc6d8998f5fc1"; 4, "beaa5a3d08f3807143cf621d95cd690514d0b49efff9c91d24b59241ec0eefa5f60196d407048bba8d2146828ebcb0488d8842fd56bb4f6df8e19c4b4daab8ac"; 5, "098084b51fd13deae5f4320de94a688ee07baea2800486689a8636117b46c1f4c1f6af7f74ae7c857600456a58a3af251dc4723a64cc7c0a5ab6d9cac91c20bb"; 6, "6044540d560853eb1c57df0077dd381094781cdb9073e5b1b3d3f6c7829e12066bbaca96d989a690de72ca3133a83652ba284a6d62942b271ffa2620c9e75b1f"; 7, "7a8cfe9b90f75f7ecb3acc053aaed6193112b6f6a4aeeb3f65d3de541942deb9e2228152a3c4bbbe72fc3b12629528cfbb09fe630f0474339f54abf453e2ed52"; 128, "72065ee4dd91c2d8509fa1fc28a37c7fc9fa7d5b3f8ad3d0d7a25626b57b1b44788d4caf806290425f9890a3a2a35a905ab4b37acfd0da6e4517b2525c9651e4"; 192, "8d6cf87c08380d2d1506eee46fd4222d21d8c04e585fbfd08269c98f702833a156326a0724656400ee09351d57b440175e2a5de93cc5f80db6daf83576cf75fa"; 255, "142709d62e28fcccd0af97fad0f8465b971e82201dc51070faa0372aa43e92484be1c1e73ba10906d5d1853db6a4106e0a7bf9800d373d6dee2d46d62ef2a461" ] let _ = testing_function "BLAKE2s-256 (keyed)"; let mkstring n = String.init n (fun i -> Char.chr i) in let key = mkstring 0x20 in let hash s = hash_string (MAC.blake2s256 key) s in List.iter (fun (len, result) -> test len (hash (mkstring len)) (hex result)) [ 0, "48a8997da407876b3d79c0d92325ad3b89cbb754d86ab71aee047ad345fd2c49"; 1, "40d15fee7c328830166ac3f918650f807e7e01e177258cdc0a39b11f598066f1"; 2, "6bb71300644cd3991b26ccd4d274acd1adeab8b1d7914546c1198bbe9fc9d803"; 3, "1d220dbe2ee134661fdf6d9e74b41704710556f2f6e5a091b227697445dbea6b"; 4, "f6c3fbadb4cc687a0064a5be6e791bec63b868ad62fba61b3757ef9ca52e05b2"; 5, "49c1f21188dfd769aea0e911dd6b41f14dab109d2b85977aa3088b5c707e8598"; 6, "fdd8993dcd43f696d44f3cea0ff35345234ec8ee083eb3cada017c7f78c17143"; 7, "e6c8125637438d0905b749f46560ac89fd471cf8692e28fab982f73f019b83a9"; 128, "0c311f38c35a4fb90d651c289d486856cd1413df9b0677f53ece2cd9e477c60a"; 192, "5950d39a23e1545f301270aa1a12f2e6c453776e4d6355de425cc153f9818867"; 255, "3fb735061abc519dfe979e54c1ee5bfad0a9d858b3315bad34bde999efd724dd" ] (* BLAKE3 *) let _ = testing_function "BLAKE3"; let key = "whats the Elvish word for friend" in let mktest (len, h, kh) = let input = String.init len (fun i -> Char.chr (i mod 251)) in let h = hex h and kh = hex kh in test len (hash_string (Hash.blake3 (8 * String.length h)) input) h; test len (hash_string (MAC.blake3 (8 * String.length kh) key) input) kh in List.iter mktest [ (0, "af1349b9f5f9a1a6a0404dea36dcc9499bcb25c9adc112b7cc9a93cae41f3262e00f03e7b69af26b7faaf09fcd333050338ddfe085b8cc869ca98b206c08243a26f5487789e8f660afe6c99ef9e0c52b92e7393024a80459cf91f476f9ffdbda7001c22e159b402631f277ca96f2defdf1078282314e763699a31c5363165421cce14d", "92b2b75604ed3c761f9d6f62392c8a9227ad0ea3f09573e783f1498a4ed60d26b18171a2f22a4b94822c701f107153dba24918c4bae4d2945c20ece13387627d3b73cbf97b797d5e59948c7ef788f54372df45e45e4293c7dc18c1d41144a9758be58960856be1eabbe22c2653190de560ca3b2ac4aa692a9210694254c371e851bc8f"); (1, "2d3adedff11b61f14c886e35afa036736dcd87a74d27b5c1510225d0f592e213c3a6cb8bf623e20cdb535f8d1a5ffb86342d9c0b64aca3bce1d31f60adfa137b358ad4d79f97b47c3d5e79f179df87a3b9776ef8325f8329886ba42f07fb138bb502f4081cbcec3195c5871e6c23e2cc97d3c69a613eba131e5f1351f3f1da786545e5", "6d7878dfff2f485635d39013278ae14f1454b8c0a3a2d34bc1ab38228a80c95b6568c0490609413006fbd428eb3fd14e7756d90f73a4725fad147f7bf70fd61c4e0cf7074885e92b0e3f125978b4154986d4fb202a3f331a3fb6cf349a3a70e49990f98fe4289761c8602c4e6ab1138d31d3b62218078b2f3ba9a88e1d08d0dd4cea11"); (2, "7b7015bb92cf0b318037702a6cdd81dee41224f734684c2c122cd6359cb1ee63d8386b22e2ddc05836b7c1bb693d92af006deb5ffbc4c70fb44d0195d0c6f252faac61659ef86523aa16517f87cb5f1340e723756ab65efb2f91964e14391de2a432263a6faf1d146937b35a33621c12d00be8223a7f1919cec0acd12097ff3ab00ab1", "5392ddae0e0a69d5f40160462cbd9bd889375082ff224ac9c758802b7a6fd20a9ffbf7efd13e989a6c246f96d3a96b9d279f2c4e63fb0bdff633957acf50ee1a5f658be144bab0f6f16500dee4aa5967fc2c586d85a04caddec90fffb7633f46a60786024353b9e5cebe277fcd9514217fee2267dcda8f7b31697b7c54fab6a939bf8f"); (3, "e1be4d7a8ab5560aa4199eea339849ba8e293d55ca0a81006726d184519e647f5b49b82f805a538c68915c1ae8035c900fd1d4b13902920fd05e1450822f36de9454b7e9996de4900c8e723512883f93f4345f8a58bfe64ee38d3ad71ab027765d25cdd0e448328a8e7a683b9a6af8b0af94fa09010d9186890b096a08471e4230a134", "39e67b76b5a007d4921969779fe666da67b5213b096084ab674742f0d5ec62b9b9142d0fab08e1b161efdbb28d18afc64d8f72160c958e53a950cdecf91c1a1bbab1a9c0f01def762a77e2e8545d4dec241e98a89b6db2e9a5b070fc110caae2622690bd7b76c02ab60750a3ea75426a6bb8803c370ffe465f07fb57def95df772c39f"); (4, "f30f5ab28fe047904037f77b6da4fea1e27241c5d132638d8bedce9d40494f328f603ba4564453e06cdcee6cbe728a4519bbe6f0d41e8a14b5b225174a566dbfa61b56afb1e452dc08c804f8c3143c9e2cc4a31bb738bf8c1917b55830c6e65797211701dc0b98daa1faeaa6ee9e56ab606ce03a1a881e8f14e87a4acf4646272cfd12", "7671dde590c95d5ac9616651ff5aa0a27bee5913a348e053b8aa9108917fe070116c0acff3f0d1fa97ab38d813fd46506089118147d83393019b068a55d646251ecf81105f798d76a10ae413f3d925787d6216a7eb444e510fd56916f1d753a5544ecf0072134a146b2615b42f50c179f56b8fae0788008e3e27c67482349e249cb86a"); (5, "b40b44dfd97e7a84a996a91af8b85188c66c126940ba7aad2e7ae6b385402aa2ebcfdac6c5d32c31209e1f81a454751280db64942ce395104e1e4eaca62607de1c2ca748251754ea5bbe8c20150e7f47efd57012c63b3c6a6632dc1c7cd15f3e1c999904037d60fac2eb9397f2adbe458d7f264e64f1e73aa927b30988e2aed2f03620", "73ac69eecf286894d8102018a6fc729f4b1f4247d3703f69bdc6a5fe3e0c84616ab199d1f2f3e53bffb17f0a2209fe8b4f7d4c7bae59c2bc7d01f1ff94c67588cc6b38fa6024886f2c078bfe09b5d9e6584cd6c521c3bb52f4de7687b37117a2dbbec0d59e92fa9a8cc3240d4432f91757aabcae03e87431dac003e7d73574bfdd8218"); (6, "06c4e8ffb6872fad96f9aaca5eee1553eb62aed0ad7198cef42e87f6a616c844611a30c4e4f37fe2fe23c0883cde5cf7059d88b657c7ed2087e3d210925ede716435d6d5d82597a1e52b9553919e804f5656278bd739880692c94bff2824d8e0b48cac1d24682699e4883389dc4f2faa2eb3b4db6e39debd5061ff3609916f3e07529a", "82d3199d0013035682cc7f2a399d4c212544376a839aa863a0f4c91220ca7a6dc2ffb3aa05f2631f0fa9ac19b6e97eb7e6669e5ec254799350c8b8d189e8807800842a5383c4d907c932f34490aaf00064de8cdb157357bde37c1504d2960034930887603abc5ccb9f5247f79224baff6120a3c622a46d7b1bcaee02c5025460941256"); (7, "3f8770f387faad08faa9d8414e9f449ac68e6ff0417f673f602a646a891419fe66036ef6e6d1a8f54baa9fed1fc11c77cfb9cff65bae915045027046ebe0c01bf5a941f3bb0f73791d3fc0b84370f9f30af0cd5b0fc334dd61f70feb60dad785f070fef1f343ed933b49a5ca0d16a503f599a365a4296739248b28d1a20b0e2cc8975c", "af0a7ec382aedc0cfd626e49e7628bc7a353a4cb108855541a5651bf64fbb28a7c5035ba0f48a9c73dabb2be0533d02e8fd5d0d5639a18b2803ba6bf527e1d145d5fd6406c437b79bcaad6c7bdf1cf4bd56a893c3eb9510335a7a798548c6753f74617bede88bef924ba4b334f8852476d90b26c5dc4c3668a2519266a562c6c8034a6"); (8, "2351207d04fc16ade43ccab08600939c7c1fa70a5c0aaca76063d04c3228eaeb725d6d46ceed8f785ab9f2f9b06acfe398c6699c6129da084cb531177445a682894f9685eaf836999221d17c9a64a3a057000524cd2823986db378b074290a1a9b93a22e135ed2c14c7e20c6d045cd00b903400374126676ea78874d79f2dd7883cf5c", "be2f5495c61cba1bb348a34948c004045e3bd4dae8f0fe82bf44d0da245a060048eb5e68ce6dea1eb0229e144f578b3aa7e9f4f85febd135df8525e6fe40c6f0340d13dd09b255ccd5112a94238f2be3c0b5b7ecde06580426a93e0708555a265305abf86d874e34b4995b788e37a823491f25127a502fe0704baa6bfdf04e76c13276"); (63, "e9bc37a594daad83be9470df7f7b3798297c3d834ce80ba85d6e207627b7db7b1197012b1e7d9af4d7cb7bdd1f3bb49a90a9b5dec3ea2bbc6eaebce77f4e470cbf4687093b5352f04e4a4570fba233164e6acc36900e35d185886a827f7ea9bdc1e5c3ce88b095a200e62c10c043b3e9bc6cb9b6ac4dfa51794b02ace9f98779040755", "bb1eb5d4afa793c1ebdd9fb08def6c36d10096986ae0cfe148cd101170ce37aea05a63d74a840aecd514f654f080e51ac50fd617d22610d91780fe6b07a26b0847abb38291058c97474ef6ddd190d30fc318185c09ca1589d2024f0a6f16d45f11678377483fa5c005b2a107cb9943e5da634e7046855eaa888663de55d6471371d55d"); (64, "4eed7141ea4a5cd4b788606bd23f46e212af9cacebacdc7d1f4c6dc7f2511b98fc9cc56cb831ffe33ea8e7e1d1df09b26efd2767670066aa82d023b1dfe8ab1b2b7fbb5b97592d46ffe3e05a6a9b592e2949c74160e4674301bc3f97e04903f8c6cf95b863174c33228924cdef7ae47559b10b294acd660666c4538833582b43f82d74", "ba8ced36f327700d213f120b1a207a3b8c04330528586f414d09f2f7d9ccb7e68244c26010afc3f762615bbac552a1ca909e67c83e2fd5478cf46b9e811efccc93f77a21b17a152ebaca1695733fdb086e23cd0eb48c41c034d52523fc21236e5d8c9255306e48d52ba40b4dac24256460d56573d1312319afcf3ed39d72d0bfc69acb"); (65, "de1e5fa0be70df6d2be8fffd0e99ceaa8eb6e8c93a63f2d8d1c30ecb6b263dee0e16e0a4749d6811dd1d6d1265c29729b1b75a9ac346cf93f0e1d7296dfcfd4313b3a227faaaaf7757cc95b4e87a49be3b8a270a12020233509b1c3632b3485eef309d0abc4a4a696c9decc6e90454b53b000f456a3f10079072baaf7a981653221f2c", "c0a4edefa2d2accb9277c371ac12fcdbb52988a86edc54f0716e1591b4326e72d5e795f46a596b02d3d4bfb43abad1e5d19211152722ec1f20fef2cd413e3c22f2fc5da3d73041275be6ede3517b3b9f0fc67ade5956a672b8b75d96cb43294b9041497de92637ed3f2439225e683910cb3ae923374449ca788fb0f9bea92731bc26ad"); (127, "d81293fda863f008c09e92fc382a81f5a0b4a1251cba1634016a0f86a6bd640de3137d477156d1fde56b0cf36f8ef18b44b2d79897bece12227539ac9ae0a5119da47644d934d26e74dc316145dcb8bb69ac3f2e05c242dd6ee06484fcb0e956dc44355b452c5e2bbb5e2b66e99f5dd443d0cbcaaafd4beebaed24ae2f8bb672bcef78", "c64200ae7dfaf35577ac5a9521c47863fb71514a3bcad18819218b818de85818ee7a317aaccc1458f78d6f65f3427ec97d9c0adb0d6dacd4471374b621b7b5f35cd54663c64dbe0b9e2d95632f84c611313ea5bd90b71ce97b3cf645776f3adc11e27d135cbadb9875c2bf8d3ae6b02f8a0206aba0c35bfe42574011931c9a255ce6dc"); (128, "f17e570564b26578c33bb7f44643f539624b05df1a76c81f30acd548c44b45efa69faba091427f9c5c4caa873aa07828651f19c55bad85c47d1368b11c6fd99e47ecba5820a0325984d74fe3e4058494ca12e3f1d3293d0010a9722f7dee64f71246f75e9361f44cc8e214a100650db1313ff76a9f93ec6e84edb7add1cb4a95019b0c", "b04fe15577457267ff3b6f3c947d93be581e7e3a4b018679125eaf86f6a628ecd86bbe0001f10bda47e6077b735016fca8119da11348d93ca302bbd125bde0db2b50edbe728a620bb9d3e6f706286aedea973425c0b9eedf8a38873544cf91badf49ad92a635a93f71ddfcee1eae536c25d1b270956be16588ef1cfef2f1d15f650bd5"); (129, "683aaae9f3c5ba37eaaf072aed0f9e30bac0865137bae68b1fde4ca2aebdcb12f96ffa7b36dd78ba321be7e842d364a62a42e3746681c8bace18a4a8a79649285c7127bf8febf125be9de39586d251f0d41da20980b70d35e3dac0eee59e468a894fa7e6a07129aaad09855f6ad4801512a116ba2b7841e6cfc99ad77594a8f2d181a7", "d4a64dae6cdccbac1e5287f54f17c5f985105457c1a2ec1878ebd4b57e20d38f1c9db018541eec241b748f87725665b7b1ace3e0065b29c3bcb232c90e37897fa5aaee7e1e8a2ecfcd9b51463e42238cfdd7fee1aecb3267fa7f2128079176132a412cd8aaf0791276f6b98ff67359bd8652ef3a203976d5ff1cd41885573487bcd683"); (1023, "10108970eeda3eb932baac1428c7a2163b0e924c9a9e25b35bba72b28f70bd11a182d27a591b05592b15607500e1e8dd56bc6c7fc063715b7a1d737df5bad3339c56778957d870eb9717b57ea3d9fb68d1b55127bba6a906a4a24bbd5acb2d123a37b28f9e9a81bbaae360d58f85e5fc9d75f7c370a0cc09b6522d9c8d822f2f28f485", "c951ecdf03288d0fcc96ee3413563d8a6d3589547f2c2fb36d9786470f1b9d6e890316d2e6d8b8c25b0a5b2180f94fb1a158ef508c3cde45e2966bd796a696d3e13efd86259d756387d9becf5c8bf1ce2192b87025152907b6d8cc33d17826d8b7b9bc97e38c3c85108ef09f013e01c229c20a83d9e8efac5b37470da28575fd755a10"); (1024, "42214739f095a406f3fc83deb889744ac00df831c10daa55189b5d121c855af71cf8107265ecdaf8505b95d8fcec83a98a6a96ea5109d2c179c47a387ffbb404756f6eeae7883b446b70ebb144527c2075ab8ab204c0086bb22b7c93d465efc57f8d917f0b385c6df265e77003b85102967486ed57db5c5ca170ba441427ed9afa684e", "75c46f6f3d9eb4f55ecaaee480db732e6c2105546f1e675003687c31719c7ba4a78bc838c72852d4f49c864acb7adafe2478e824afe51c8919d06168414c265f298a8094b1ad813a9b8614acabac321f24ce61c5a5346eb519520d38ecc43e89b5000236df0597243e4d2493fd626730e2ba17ac4d8824d09d1a4a8f57b8227778e2de"); (1025, "d00278ae47eb27b34faecf67b4fe263f82d5412916c1ffd97c8cb7fb814b8444f4c4a22b4b399155358a994e52bf255de60035742ec71bd08ac275a1b51cc6bfe332b0ef84b409108cda080e6269ed4b3e2c3f7d722aa4cdc98d16deb554e5627be8f955c98e1d5f9565a9194cad0c4285f93700062d9595adb992ae68ff12800ab67a", "357dc55de0c7e382c900fd6e320acc04146be01db6a8ce7210b7189bd664ea69362396b77fdc0d2634a552970843722066c3c15902ae5097e00ff53f1e116f1cd5352720113a837ab2452cafbde4d54085d9cf5d21ca613071551b25d52e69d6c81123872b6f19cd3bc1333edf0c52b94de23ba772cf82636cff4542540a7738d5b930"); (2048, "e776b6028c7cd22a4d0ba182a8bf62205d2ef576467e838ed6f2529b85fba24a9a60bf80001410ec9eea6698cd537939fad4749edd484cb541aced55cd9bf54764d063f23f6f1e32e12958ba5cfeb1bf618ad094266d4fc3c968c2088f677454c288c67ba0dba337b9d91c7e1ba586dc9a5bc2d5e90c14f53a8863ac75655461cea8f9", "879cf1fa2ea0e79126cb1063617a05b6ad9d0b696d0d757cf053439f60a99dd10173b961cd574288194b23ece278c330fbb8585485e74967f31352a8183aa782b2b22f26cdcadb61eed1a5bc144b8198fbb0c13abbf8e3192c145d0a5c21633b0ef86054f42809df823389ee40811a5910dcbd1018af31c3b43aa55201ed4edaac74fe"); (2049, "5f4d72f40d7a5f82b15ca2b2e44b1de3c2ef86c426c95c1af0b687952256303096de31d71d74103403822a2e0bc1eb193e7aecc9643a76b7bbc0c9f9c52e8783aae98764ca468962b5c2ec92f0c74eb5448d519713e09413719431c802f948dd5d90425a4ecdadece9eb178d80f26efccae630734dff63340285adec2aed3b51073ad3", "9f29700902f7c86e514ddc4df1e3049f258b2472b6dd5267f61bf13983b78dd5f9a88abfefdfa1e00b418971f2b39c64ca621e8eb37fceac57fd0c8fc8e117d43b81447be22d5d8186f8f5919ba6bcc6846bd7d50726c06d245672c2ad4f61702c646499ee1173daa061ffe15bf45a631e2946d616a4c345822f1151284712f76b2b0e"); (3072, "b98cb0ff3623be03326b373de6b9095218513e64f1ee2edd2525c7ad1e5cffd29a3f6b0b978d6608335c09dc94ccf682f9951cdfc501bfe47b9c9189a6fc7b404d120258506341a6d802857322fbd20d3e5dae05b95c88793fa83db1cb08e7d8008d1599b6209d78336e24839724c191b2a52a80448306e0daa84a3fdb566661a37e11", "044a0e7b172a312dc02a4c9a818c036ffa2776368d7f528268d2e6b5df19177022f302d0529e4174cc507c463671217975e81dab02b8fdeb0d7ccc7568dd22574c783a76be215441b32e91b9a904be8ea81f7a0afd14bad8ee7c8efc305ace5d3dd61b996febe8da4f56ca0919359a7533216e2999fc87ff7d8f176fbecb3d6f34278b"); (3073, "7124b49501012f81cc7f11ca069ec9226cecb8a2c850cfe644e327d22d3e1cd39a27ae3b79d68d89da9bf25bc27139ae65a324918a5f9b7828181e52cf373c84f35b639b7fccbb985b6f2fa56aea0c18f531203497b8bbd3a07ceb5926f1cab74d14bd66486d9a91eba99059a98bd1cd25876b2af5a76c3e9eed554ed72ea952b603bf", "68dede9bef00ba89e43f31a6825f4cf433389fedae75c04ee9f0cf16a427c95a96d6da3fe985054d3478865be9a092250839a697bbda74e279e8a9e69f0025e4cfddd6cfb434b1cd9543aaf97c635d1b451a4386041e4bb100f5e45407cbbc24fa53ea2de3536ccb329e4eb9466ec37093a42cf62b82903c696a93a50b702c80f3c3c5"); (4096, "015094013f57a5277b59d8475c0501042c0b642e531b0a1c8f58d2163229e9690289e9409ddb1b99768eafe1623da896faf7e1114bebeadc1be30829b6f8af707d85c298f4f0ff4d9438aef948335612ae921e76d411c3a9111df62d27eaf871959ae0062b5492a0feb98ef3ed4af277f5395172dbe5c311918ea0074ce0036454f620", "befc660aea2f1718884cd8deb9902811d332f4fc4a38cf7c7300d597a081bfc0bbb64a36edb564e01e4b4aaf3b060092a6b838bea44afebd2deb8298fa562b7b597c757b9df4c911c3ca462e2ac89e9a787357aaf74c3b56d5c07bc93ce899568a3eb17d9250c20f6c5f6c1e792ec9a2dcb715398d5a6ec6d5c54f586a00403a1af1de"); (4097, "9b4052b38f1c5fc8b1f9ff7ac7b27cd242487b3d890d15c96a1c25b8aa0fb99505f91b0b5600a11251652eacfa9497b31cd3c409ce2e45cfe6c0a016967316c426bd26f619eab5d70af9a418b845c608840390f361630bd497b1ab44019316357c61dbe091ce72fc16dc340ac3d6e009e050b3adac4b5b2c92e722cffdc46501531956", "00df940cd36bb9fa7cbbc3556744e0dbc8191401afe70520ba292ee3ca80abbc606db4976cfdd266ae0abf667d9481831ff12e0caa268e7d3e57260c0824115a54ce595ccc897786d9dcbf495599cfd90157186a46ec800a6763f1c59e36197e9939e900809f7077c102f888caaf864b253bc41eea812656d46742e4ea42769f89b83f"); (5120, "9cadc15fed8b5d854562b26a9536d9707cadeda9b143978f319ab34230535833acc61c8fdc114a2010ce8038c853e121e1544985133fccdd0a2d507e8e615e611e9a0ba4f47915f49e53d721816a9198e8b30f12d20ec3689989175f1bf7a300eee0d9321fad8da232ece6efb8e9fd81b42ad161f6b9550a069e66b11b40487a5f5059", "2c493e48e9b9bf31e0553a22b23503c0a3388f035cece68eb438d22fa1943e209b4dc9209cd80ce7c1f7c9a744658e7e288465717ae6e56d5463d4f80cdb2ef56495f6a4f5487f69749af0c34c2cdfa857f3056bf8d807336a14d7b89bf62bef2fb54f9af6a546f818dc1e98b9e07f8a5834da50fa28fb5874af91bf06020d1bf0120e"); (5121, "628bd2cb2004694adaab7bbd778a25df25c47b9d4155a55f8fbd79f2fe154cff96adaab0613a6146cdaabe498c3a94e529d3fc1da2bd08edf54ed64d40dcd6777647eac51d8277d70219a9694334a68bc8f0f23e20b0ff70ada6f844542dfa32cd4204ca1846ef76d811cdb296f65e260227f477aa7aa008bac878f72257484f2b6c95", "6ccf1c34753e7a044db80798ecd0782a8f76f33563accaddbfbb2e0ea4b2d0240d07e63f13667a8d1490e5e04f13eb617aea16a8c8a5aaed1ef6fbde1b0515e3c81050b361af6ead126032998290b563e3caddeaebfab592e155f2e161fb7cba939092133f23f9e65245e58ec23457b78a2e8a125588aad6e07d7f11a85b88d375b72d"); (6144, "3e2e5b74e048f3add6d21faab3f83aa44d3b2278afb83b80b3c35164ebeca2054d742022da6fdda444ebc384b04a54c3ac5839b49da7d39f6d8a9db03deab32aade156c1c0311e9b3435cde0ddba0dce7b26a376cad121294b689193508dd63151603c6ddb866ad16c2ee41585d1633a2cea093bea714f4c5d6b903522045b20395c83", "3d6b6d21281d0ade5b2b016ae4034c5dec10ca7e475f90f76eac7138e9bc8f1dc35754060091dc5caf3efabe0603c60f45e415bb3407db67e6beb3d11cf8e4f7907561f05dace0c15807f4b5f389c841eb114d81a82c02a00b57206b1d11fa6e803486b048a5ce87105a686dee041207e095323dfe172df73deb8c9532066d88f9da7e"); (6145, "f1323a8631446cc50536a9f705ee5cb619424d46887f3c376c695b70e0f0507f18a2cfdd73c6e39dd75ce7c1c6e3ef238fd54465f053b25d21044ccb2093beb015015532b108313b5829c3621ce324b8e14229091b7c93f32db2e4e63126a377d2a63a3597997d4f1cba59309cb4af240ba70cebff9a23d5e3ff0cdae2cfd54e070022", "9ac301e9e39e45e3250a7e3b3df701aa0fb6889fbd80eeecf28dbc6300fbc539f3c184ca2f59780e27a576c1d1fb9772e99fd17881d02ac7dfd39675aca918453283ed8c3169085ef4a466b91c1649cc341dfdee60e32231fc34c9c4e0b9a2ba87ca8f372589c744c15fd6f985eec15e98136f25beeb4b13c4e43dc84abcc79cd4646c"); (7168, "61da957ec2499a95d6b8023e2b0e604ec7f6b50e80a9678b89d2628e99ada77a5707c321c83361793b9af62a40f43b523df1c8633cecb4cd14d00bdc79c78fca5165b863893f6d38b02ff7236c5a9a8ad2dba87d24c547cab046c29fc5bc1ed142e1de4763613bb162a5a538e6ef05ed05199d751f9eb58d332791b8d73fb74e4fce95", "b42835e40e9d4a7f42ad8cc04f85a963a76e18198377ed84adddeaecacc6f3fca2f01d5277d69bb681c70fa8d36094f73ec06e452c80d2ff2257ed82e7ba348400989a65ee8daa7094ae0933e3d2210ac6395c4af24f91c2b590ef87d7788d7066ea3eaebca4c08a4f14b9a27644f99084c3543711b64a070b94f2c9d1d8a90d035d52"); (7169, "a003fc7a51754a9b3c7fae0367ab3d782dccf28855a03d435f8cfe74605e781798a8b20534be1ca9eb2ae2df3fae2ea60e48c6fb0b850b1385b5de0fe460dbe9d9f9b0d8db4435da75c601156df9d047f4ede008732eb17adc05d96180f8a73548522840779e6062d643b79478a6e8dbce68927f36ebf676ffa7d72d5f68f050b119c8", "ed9b1a922c046fdb3d423ae34e143b05ca1bf28b710432857bf738bcedbfa5113c9e28d72fcbfc020814ce3f5d4fc867f01c8f5b6caf305b3ea8a8ba2da3ab69fabcb438f19ff11f5378ad4484d75c478de425fb8e6ee809b54eec9bdb184315dc856617c09f5340451bf42fd3270a7b0b6566169f242e533777604c118a6358250f54"); (8192, "aae792484c8efe4f19e2ca7d371d8c467ffb10748d8a5a1ae579948f718a2a635fe51a27db045a567c1ad51be5aa34c01c6651c4d9b5b5ac5d0fd58cf18dd61a47778566b797a8c67df7b1d60b97b19288d2d877bb2df417ace009dcb0241ca1257d62712b6a4043b4ff33f690d849da91ea3bf711ed583cb7b7a7da2839ba71309bbf", "dc9637c8845a770b4cbf76b8daec0eebf7dc2eac11498517f08d44c8fc00d58a4834464159dcbc12a0ba0c6d6eb41bac0ed6585cabfe0aca36a375e6c5480c22afdc40785c170f5a6b8a1107dbee282318d00d915ac9ed1143ad40765ec120042ee121cd2baa36250c618adaf9e27260fda2f94dea8fb6f08c04f8f10c78292aa46102"); (8193, "bab6c09cb8ce8cf459261398d2e7aef35700bf488116ceb94a36d0f5f1b7bc3bb2282aa69be089359ea1154b9a9286c4a56af4de975a9aa4a5c497654914d279bea60bb6d2cf7225a2fa0ff5ef56bbe4b149f3ed15860f78b4e2ad04e158e375c1e0c0b551cd7dfc82f1b155c11b6b3ed51ec9edb30d133653bb5709d1dbd55f4e1ff6", "954a2a75420c8d6547e3ba5b98d963e6fa6491addc8c023189cc519821b4a1f5f03228648fd983aef045c2fa8290934b0866b615f585149587dda2299039965328835a2b18f1d63b7e300fc76ff260b571839fe44876a4eae66cbac8c67694411ed7e09df51068a22c6e67d6d3dd2cca8ff12e3275384006c80f4db68023f24eebba57"); (16384, "f875d6646de28985646f34ee13be9a576fd515f76b5b0a26bb324735041ddde49d764c270176e53e97bdffa58d549073f2c660be0e81293767ed4e4929f9ad34bbb39a529334c57c4a381ffd2a6d4bfdbf1482651b172aa883cc13408fa67758a3e47503f93f87720a3177325f7823251b85275f64636a8f1d599c2e49722f42e93893", "9e9fc4eb7cf081ea7c47d1807790ed211bfec56aa25bb7037784c13c4b707b0df9e601b101e4cf63a404dfe50f2e1865bb12edc8fca166579ce0c70dba5a5c0fc960ad6f3772183416a00bd29d4c6e651ea7620bb100c9449858bf14e1ddc9ecd35725581ca5b9160de04060045993d972571c3e8f71e9d0496bfa744656861b169d65"); (31744, "62b6960e1a44bcc1eb1a611a8d6235b6b4b78f32e7abc4fb4c6cdcce94895c47860cc51f2b0c28a7b77304bd55fe73af663c02d3f52ea053ba43431ca5bab7bfea2f5e9d7121770d88f70ae9649ea713087d1914f7f312147e247f87eb2d4ffef0ac978bf7b6579d57d533355aa20b8b77b13fd09748728a5cc327a8ec470f4013226f", "efa53b389ab67c593dba624d898d0f7353ab99e4ac9d42302ee64cbf9939a4193a7258db2d9cd32a7a3ecfce46144114b15c2fcb68a618a976bd74515d47be08b628be420b5e830fade7c080e351a076fbc38641ad80c736c8a18fe3c66ce12f95c61c2462a9770d60d0f77115bbcd3782b593016a4e728d4c06cee4505cb0c08a42ec"); (102400, "bc3e3d41a1146b069abffad3c0d44860cf664390afce4d9661f7902e7943e085e01c59dab908c04c3342b816941a26d69c2605ebee5ec5291cc55e15b76146e6745f0601156c3596cb75065a9c57f35585a52e1ac70f69131c23d611ce11ee4ab1ec2c009012d236648e77be9295dd0426f29b764d65de58eb7d01dd42248204f45f8e", "1c35d1a5811083fd7119f5d5d1ba027b4d01c0c6c49fb6ff2cf75393ea5db4a7f9dbdd3e1d81dcbca3ba241bb18760f207710b751846faaeb9dff8262710999a59b2aa1aca298a032d94eacfadf1aa192418eb54808db23b56e34213266aa08499a16b354f018fc4967d05f8b9d2ad87a7278337be9693fc638a3bfdbe314574ee6fc4"); ] (* RIPEMD-160 *) let _ = testing_function "RIPEMD-160"; let hash s = hash_string (Hash.ripemd160()) s in test 1 (hash "") (hex "9c1185a5c5e9fc54612808977ee8f548b2258d31"); test 2 (hash "a") (hex "0bdc9d2d256b3ee9daae347be6f4dc835a467ffe"); test 3 (hash "abc") (hex "8eb208f7e05d987a9b044a8e98c6b087f15a0bfc"); test 4 (hash "message digest") (hex "5d0689ef49d2fae572b881b123a85ffa21595f36"); test 5 (hash "abcdefghijklmnopqrstuvwxyz") (hex "f71c27109c692c1b56bbdceb5b9d2865b3708dbc"); test 6 (hash "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq") (hex "12a053384a9c0c88e405a06c27dcf49ada62eb2b"); test 7 (hash "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789") (hex "b0e20b6e3116640286ed3a87a5713079b21f5189"); test 8 (hash "12345678901234567890123456789012345678901234567890123456789012345678901234567890") (hex "9b752e45573d4b39f4dbd3323cab82bf63326bfb"); test 9 (hash (String.make 1000000 'a')) (hex "52783243c1697bdbe16d37f97f68f08325dc1528") (* MD5 *) let _ = testing_function "MD5"; let hash s = hash_string (Hash.md5()) s in test 1 (hash "") (hex "D41D8CD98F00B204E9800998ECF8427E"); test 2 (hash "a") (hex "0CC175B9C0F1B6A831C399E269772661"); test 3 (hash "abc") (hex "900150983CD24FB0D6963F7D28E17F72"); test 4 (hash "message digest") (hex "F96B697D7CB7938D525A2F31AAF161D0") (* GHASH *) module GHash = struct type t external init: string -> t = "caml_ghash_init" external mult: t -> bytes -> unit = "caml_ghash_mult" let mul x y = let g = init x and h = Bytes.of_string y in mult g h; Bytes.to_string h let _ = testing_function "GFmul"; test 1 (mul (hex "dfa6bf4ded81db03ffcaff95f830f061") (hex "952b2a56a5604ac0b32b6656a05b40b6")) (hex "da53eb0ad2c55bb64fc4802cc3feda60") end (* Poly1305 *) module Poly1305 = struct external poly1305_init: string -> bytes = "caml_poly1305_init" external poly1305_update: bytes -> bytes -> int -> int -> unit = "caml_poly1305_update" external poly1305_final: bytes -> string = "caml_poly1305_final" let _ = testing_function "Poly1305"; let key = String.init 32 (fun i -> Char.chr (i + 221)) and msg = Bytes.init 73 (fun i -> Char.chr (i + 121)) in let h = poly1305_init key in poly1305_update h msg 0 73; let mac = poly1305_final h in test 1 mac (hex "dd b9 da 7d dd 5e 52 79 27 30 ed 5c da 5f 90 a4") end (* SipHash *) let testsip mac vectors = let key = String.init 16 Char.chr in List.iteri (fun i result -> let input = String.init i Char.chr in test i (hash_string (mac key) input) (hex result)) vectors let _ = testing_function "SipHash 64"; testsip MAC.siphash [ "310e0edd47db6f72"; "fd67dc93c539f874"; "5a4fa9d909806c0d"; "2d7efbd796666785"; "b7877127e09427cf"; "8da699cd64557618"; "cee3fe586e46c9cb"; "37d1018bf50002ab"; "6224939a79f5f593"; "b0e4a90bdf82009e"; "f3b9dd94c5bb5d7a"; "a7ad6b22462fb3f4"; "fbe50e86bc8f1e75"; "903d84c02756ea14"; "eef27a8e90ca23f7"; "e545be4961ca29a1"; "db9bc2577fcc2a3f"; "9447be2cf5e99a69"; "9cd38d96f0b3c14b"; "bd6179a71dc96dbb"; "98eea21af25cd6be"; "c7673b2eb0cbf2d0"; "883ea3e395675393"; "c8ce5ccd8c030ca8"; "94af49f6c650adb8"; "eab8858ade92e1bc"; "f315bb5bb835d817"; "adcf6b0763612e2f"; "a5c91da7acaa4dde"; "716595876650a2a6"; "28ef495c53a387ad"; "42c341d8fa92d832"; "ce7cf2722f512771"; "e37859f94623f3a7"; "381205bb1ab0e012"; "ae97a10fd434e015"; "b4a31508beff4d31"; "81396229f0907902"; "4d0cf49ee5d4dcca"; "5c73336a76d8bf9a"; "d0a704536ba93e0e"; "925958fcd6420cad"; "a915c29bc8067318"; "952b79f3bc0aa6d4"; "f21df2e41d4535f9"; "87577519048f53a9"; "10a56cf5dfcd9adb"; "eb75095ccd986cd0"; "51a9cb9ecba312e6"; "96afadfc2ce666c7"; "72fe52975a4364ee"; "5a1645b276d592a1"; "b274cb8ebf87870a"; "6f9bb4203de7b381"; "eaecb2a30b22a87f"; "9924a43cc1315724"; "bd838d3aafbf8db7"; "0b1a2a3265d51aea"; "135079a3231ce660"; "932b2846e4d70666"; "e1915f5cb1eca46c"; "f325965ca16d629f"; "575ff28e60381be5"; "724506eb4c328a95" ]; testing_function "SipHash 128"; testsip MAC.siphash128 [ "a3817f04ba25a8e66df67214c7550293"; "da87c1d86b99af44347659119b22fc45"; "8177228da4a45dc7fca38bdef60affe4"; "9c70b60c5267a94e5f33b6b02985ed51"; "f88164c12d9c8faf7d0f6e7c7bcd5579"; "1368875980776f8854527a07690e9627"; "14eeca338b208613485ea0308fd7a15e"; "a1f1ebbed8dbc153c0b84aa61ff08239"; "3b62a9ba6258f5610f83e264f31497b4"; "264499060ad9baabc47f8b02bb6d71ed"; "00110dc378146956c95447d3f3d0fbba"; "0151c568386b6677a2b4dc6f81e5dc18"; "d626b266905ef35882634df68532c125"; "9869e247e9c08b10d029934fc4b952f7"; "31fcefac66d7de9c7ec7485fe4494902"; "5493e99933b0a8117e08ec0f97cfc3d9"; "6ee2a4ca67b054bbfd3315bf85230577"; "473d06e8738db89854c066c47ae47740"; "a426e5e423bf4885294da481feaef723"; "78017731cf65fab074d5208952512eb1"; "9e25fc833f2290733e9344a5e83839eb"; "568e495abe525a218a2214cd3e071d12"; "4a29b54552d16b9a469c10528eff0aae"; "c9d184ddd5a9f5e0cf8ce29a9abf691c"; "2db479ae78bd50d8882a8a178a6132ad"; "8ece5f042d5e447b5051b9eacb8d8f6f"; "9c0b53b4b3c307e87eaee08678141f66"; "abf248af69a6eae4bfd3eb2f129eeb94"; "0664da1668574b88b935f3027358aef4"; "aa4b9dc4bf337de90cd4fd3c467c6ab7"; "ea5c7f471faf6bde2b1ad7d4686d2287"; "2939b0183223fafc1723de4f52c43d35"; "7c3956ca5eeafc3e363e9d556546eb68"; "77c6077146f01c32b6b69d5f4ea9ffcf"; "37a6986cb8847edf0925f0f1309b54de"; "a705f0e69da9a8f907241a2e923c8cc8"; "3dc47d1f29c448461e9e76ed904f6711"; "0d62bf01e6fc0e1a0d3c4751c5d3692b"; "8c03468bca7c669ee4fd5e084bbee7b5"; "528a5bb93baf2c9c4473cce5d0d22bd9"; "df6a301e95c95dad97ae0cc8c6913bd8"; "801189902c857f39e73591285e70b6db"; "e617346ac9c231bb3650ae34ccca0c5b"; "27d93437efb721aa401821dcec5adf89"; "89237d9ded9c5e78d8b1c9b166cc7342"; "4a6d8091bf5e7d651189fa94a250b14c"; "0e33f96055e7ae893ffc0e3dcf492902"; "e61c432b720b19d18ec8d84bdc63151b"; "f7e5aef549f782cf379055a608269b16"; "438d030fd0b7a54fa837f2ad201a6403"; "a590d3ee4fbf04e3247e0d27f286423f"; "5fe2c1a172fe93c4b15cd37caef9f538"; "2c97325cbd06b36eb2133dd08b3a017c"; "92c814227a6bca949ff0659f002ad39e"; "dce850110bd8328cfbd50841d6911d87"; "67f14984c7da791248e32bb5922583da"; "1938f2cf72d54ee97e94166fa91d2a36"; "74481e9646ed49fe0f6224301604698e"; "57fca5de98a9d6d8006438d0583d8a1d"; "9fecde1cefdc1cbed4763674d9575359"; "e3040c00eb28f15366ca73cbd872e740"; "7697009a6a831dfecca91c5993670f7a"; "5853542321f567a005d547a4f04759bd"; "5150d1772f50834a503e069a973fbd7c"; ] open Cipher let some_key = hex "0123456789abcdef" let test_enc_dec testno cipher cleartext = let enc = cipher some_key Encrypt and dec = cipher some_key Decrypt in test testno (transform_string dec (transform_string enc cleartext)) cleartext let _ = testing_function "ECB"; test_enc_dec 1 (des ~mode:ECB) "abcdefgh"; test_enc_dec 2 (des ~mode:ECB) "abcdefgh01234567"; test_enc_dec 3 (des ~mode:ECB ~pad:Padding.length) "0123456789"; test_enc_dec 4 (des ~mode:ECB ~pad:Padding.length) "abcdefghijklmnopqrstuvwxyz"; test_enc_dec 5 (des ~mode:ECB ~pad:Padding._8000) "0123456789"; test_enc_dec 6 (des ~mode:ECB ~pad:Padding._8000) "abcdefghijklmnopqrstuvwxyz" let _ = testing_function "CBC"; test_enc_dec 1 (des ~mode:CBC) "abcdefgh"; test_enc_dec 2 (des ~mode:CBC) "abcdefgh01234567"; test_enc_dec 3 (des ~mode:CBC ~pad:Padding.length) "0123456789"; test_enc_dec 4 (des ~mode:CBC ~pad:Padding.length) "abcdefghijklmnopqrstuvwxyz"; test_enc_dec 5 (des ~mode:CBC ~pad:Padding.length ~iv:"#@#@#@#@") "0123456789"; test_enc_dec 6 (des ~mode:CBC ~pad:Padding.length ~iv:"ABCDEFGH") "abcdefghijklmnopqrstuvwxyz" let _ = testing_function "CFB 1"; test_enc_dec 1 (des ~mode:(CFB 1)) "ab"; test_enc_dec 2 (des ~mode:(CFB 1)) "abcd"; test_enc_dec 3 (des ~mode:(CFB 1)) "abcdefgh01234567"; test_enc_dec 4 (des ~mode:(CFB 1)) "abcdefghijklmnopqrstuvwxyz"; test_enc_dec 5 (des ~mode:(CFB 1) ~iv:"#@#@#@#@") "abcdefghijklmnopqrstuvwxyz" let _ = testing_function "CFB 4"; test_enc_dec 1 (des ~mode:(CFB 4)) "abcd"; test_enc_dec 2 (des ~mode:(CFB 4)) "abcdefgh01234567"; test_enc_dec 3 (des ~mode:(CFB 4) ~pad:Padding._8000) "abcdefghijklmnopqrstuvwxyz" let _ = testing_function "OFB 1"; test_enc_dec 1 (des ~mode:(OFB 1)) "ab"; test_enc_dec 2 (des ~mode:(OFB 1)) "abcd"; test_enc_dec 3 (des ~mode:(OFB 1)) "abcdefgh01234567"; test_enc_dec 4 (des ~mode:(OFB 1)) "abcdefghijklmnopqrstuvwxyz"; test_enc_dec 5 (des ~mode:(OFB 1) ~iv:"#@#@#@#@") "abcdefghijklmnopqrstuvwxyz" let _ = testing_function "OFB 8"; test_enc_dec 1 (des ~mode:(OFB 8)) "abcdefgh"; test_enc_dec 2 (des ~mode:(OFB 8)) "abcdefgh01234567"; test_enc_dec 3 (des ~mode:(OFB 8) ~pad:Padding._8000) "abcdefghijklmnopqrstuvwxyz" let _ = testing_function "CTR"; test_enc_dec 1 (des ~mode:CTR) "abcdefgh"; test_enc_dec 2 (des ~mode:CTR) "abcdefgh01234567"; test_enc_dec 3 (des ~mode:CTR ~pad:Padding._8000) "abcdefghijklmnopqrstuvwxyz"; test_enc_dec 4 (des ~mode:CTR ~iv:"\000\000\000\000\255\255\255\255" ~pad:Padding._8000) "abcdefghijklmnopqrstuvwxyz" let _ = testing_function "CTR_N"; test_enc_dec 1 (des ~mode:(CTR_N 1)) "abcdefgh"; let test_overflow len = try ignore(transform_string (des ~mode:(CTR_N 1) some_key Encrypt) (String.make len 'x')); false with Error Message_too_long -> true in test 2 (test_overflow (256 * 8)) true; test 3 (test_overflow (255 * 8)) false (* HMAC-SHA256 *) let _ = testing_function "HMAC-SHA256"; List.iter (fun (testno, hexkey, msg, hexhash) -> test testno (hash_string (MAC.hmac_sha256 (hex hexkey)) msg) (hex hexhash)) [ (1, "0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20", "abc", "a21b1f5d4cf4f73a4dd939750f7a066a7f98cc131cb16a6692759021cfab8181"); (2, "0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20", "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", "104fdc1257328f08184ba73131c53caee698e36119421149ea8c712456697d30"); (3, "0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20", "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopqabcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", "470305fc7e40fe34d3eeb3e773d95aab73acf0fd060447a5eb4595bf33a9d1a3"); (4, "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", "Hi There", "198a607eb44bfbc69903a0f1cf2bbdc5ba0aa3f3d9ae3c1c7a3b1696a0b68cf7"); (5, "4a656665", (* "Jefe" *) "what do ya want for nothing?", "5bdcc146bf60754e6a042426089575c75a003f089d2739839dec58b964ec3843"); (6, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd", "cdcb1220d1ecccea91e53aba3092f962e549fe6ce9ed7fdc43191fbde45c30b0"); (7, "0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425", "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd", "d4633c17f6fb8d744c66dee0f8f074556ec4af55ef07998541468eb49bd2e917"); (8, "0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c", "Test With Truncation", "7546af01841fc09b1ab9c3749a5f1c17d4f589668a587b2700a9c97c1193cf42"); (9, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "Test Using Larger Than Block-Size Key - Hash Key First", "6953025ed96f0c09f80a96f78e6538dbe2e7b820e3dd970e7ddd39091b32352f"); (10, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data", "6355ac22e890d0a3c8481a5ca4825bc884d3e7a1ff98a2fc2ac7d8e064c3b2e6") ] (* HMAC-SHA384 *) let _ = testing_function "HMAC-SHA384"; List.iter (fun (testno, hexkey, hexmsg, hexhash) -> test testno (hash_string (MAC.hmac_sha384 (hex hexkey)) (hex hexmsg)) (hex hexhash)) [(1, "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b\ 0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b\ 0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b\ 0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", "4869205468657265", "51b2151ae771770f36cc6c5d63de41fc\ febab0900a22b41cb81e12209215337e\ 5d5384201f6dc3ca9f92764c503380e6"); (2, "4a6566654a6566654a6566654a656665\ 4a6566654a6566654a6566654a656665\ 4a6566654a6566654a6566654a656665\ 4a6566654a6566654a6566654a656665", "7768617420646f2079612077616e7420\ 666f72206e6f7468696e673f", "b57bd579eda34ac3f203e28660ed9992\ f7400d147af77a297b8a8a052e0d7eaa\ f54288f8a219dc55b49bb3147271f0b7"); (3, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "dddddddddddddddddddddddddddddddd\ dddddddddddddddddddddddddddddddd\ dddddddddddddddddddddddddddddddd\ dddd", "0b97cc8c49ef7ad3abd3e459c1084409\ a1778f0bd832e2126d25c93f7524b272\ a94f86587d874fefb80309910e70d958")] (* HMAC-SHA512 *) let _ = testing_function "HMAC-SHA512"; List.iter (fun (testno, hexkey, hexmsg, hexhash) -> test testno (hash_string (MAC.hmac_sha512 (hex hexkey)) (hex hexmsg)) (hex hexhash)) [(1, "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b\ 0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b\ 0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b\ 0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", "4869205468657265", "637edc6e01dce7e6742a99451aae82df\ 23da3e92439e590e43e761b33e910fb8\ ac2878ebd5803f6f0b61dbce5e251ff8\ 789a4722c1be65aea45fd464e89f8f5b"); (2, "4a6566654a6566654a6566654a656665\ 4a6566654a6566654a6566654a656665\ 4a6566654a6566654a6566654a656665\ 4a6566654a6566654a6566654a656665", "7768617420646f2079612077616e7420\ 666f72206e6f7468696e673f", "cb370917ae8a7ce28cfd1d8f4705d614\ 1c173b2a9362c15df235dfb251b15454\ 6aa334ae9fb9afc2184932d8695e397b\ fa0ffb93466cfcceaae38c833b7dba38"); (3, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "dddddddddddddddddddddddddddddddd\ dddddddddddddddddddddddddddddddd\ dddddddddddddddddddddddddddddddd\ dddd", "2ee7acd783624ca9398710f3ee05ae41\ b9f9b0510c87e49e586cc9bf961733d8\ 623c7b55cebefccf02d5581acc1c9d5f\ b1ff68a1de45509fbe4da9a433922655")] (* HMAC-MD5 *) let _ = testing_function "HMAC-MD5"; test 1 (hash_string (MAC.hmac_md5 (hex "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b")) "Hi There") (hex "9294727a3638bb1c13f48ef8158bfc9d"); test 2 (hash_string (MAC.hmac_md5 "Jefe") "what do ya want for nothing?") (hex "750c783e6ab0b503eaa86e310a5db738"); test 3 (hash_string (MAC.hmac_md5 (hex "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA")) (String.make 50 '\221')) (hex "56be34521d144c88dbb8c733f0e8b3f6") (* AES-CMAC (from RFC4493) *) let _ = testing_function "AES-CMAC"; let key = hex "2b7e1516 28aed2a6 abf71588 09cf4f3c" in let msg = hex "6bc1bee2 2e409f96 e93d7e11 7393172a \ ae2d8a57 1e03ac9c 9eb76fac 45af8e51 \ 30c81c46 a35ce411 e5fbc119 1a0a52ef \ f69f2445 df4f9b17 ad2b417b e66c3710" in test 1 (hash_string (MAC.aes_cmac key) "") (hex "bb1d6929 e9593728 7fa37d12 9b756746"); test 2 (hash_string (MAC.aes_cmac key) (String.sub msg 0 16)) (hex "070a16b4 6b4d4144 f79bdd9d d04a287c"); test 3 (hash_string (MAC.aes_cmac key) (String.sub msg 0 40)) (hex "dfa66747 de9ae630 30ca3261 1497c827"); test 4 (hash_string (MAC.aes_cmac key) msg) (hex "51f0bebf 7e3b9d92 fc497417 79363cfe") (* RSA *) let some_rsa_key = { RSA.size = 512; RSA.n = hex "c0764797b8bec8972a0ed8c90a8c334dd049add0222c09d20be0a79e338910bcae422060906ae0221de3f3fc747ccf98aecc85d6edc52d93d5b7396776160525"; RSA.e = hex "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010001"; RSA.d = hex "1ae36b7522f66487d9f4610d1550290ac202c929bedc7032cc3e02acf37e3ebc1f866ee7ef7a0868d23ae2b184c1abd6d4db8ea9bec046bd82803727f2888701"; RSA.p = hex "df02b615fe15928f41b02b586b51c2c02260ca396818ca4cba60bb892465be35"; RSA.q = hex "dceeb60d543518b4ac74834a0546c507f2e91e389a87e2f2becc6f8c67d1c931"; RSA.dp = hex "59487e99e375c38d732112d97d6de8687fdafc5b6b5fb16e7297d3bd1e435599"; RSA.dq = hex "61b550de6437774db0577718ed6c770724eee466b43114b5b69c43591d313281"; RSA.qinv = hex "744c79c4b9bea97c25e563c9407a2d09b57358afe09af67d71f8198cb7c956b8" } let some_msg = "Supercalifragilistusexpialidolcius" let test_same_message testno msg1 msg2 = test testno msg1 (String.sub msg2 (String.length msg2 - String.length msg1) (String.length msg1)) let _ = testing_function "RSA"; (* Signature, no CRT *) test_same_message 1 some_msg (RSA.unwrap_signature some_rsa_key (RSA.sign some_rsa_key some_msg)); (* Signature, CRT *) test_same_message 2 some_msg (RSA.unwrap_signature some_rsa_key (RSA.sign_CRT some_rsa_key some_msg)); (* Encryption, no CRT *) test_same_message 3 some_msg (RSA.decrypt some_rsa_key (RSA.encrypt some_rsa_key some_msg)); (* Encryption, CRT *) test_same_message 4 some_msg (RSA.decrypt_CRT some_rsa_key (RSA.encrypt some_rsa_key some_msg)); (* Same, with a home-made key *) let prng = Random.pseudo_rng (hex "5b5e50dc5b6eaf5346eba8244e5666ac4dcd5409") in let key = RSA.new_key ~rng:prng 1024 in test_same_message 5 some_msg (RSA.unwrap_signature key (RSA.sign key some_msg)); test_same_message 6 some_msg (RSA.unwrap_signature key (RSA.sign_CRT key some_msg)); test_same_message 7 some_msg (RSA.decrypt key (RSA.encrypt key some_msg)); test_same_message 8 some_msg (RSA.decrypt_CRT key (RSA.encrypt key some_msg)); (* Same, with a home-made key of fixed public exponent *) let key = RSA.new_key ~rng:prng ~e:65537 1024 in test_same_message 9 some_msg (RSA.unwrap_signature key (RSA.sign key some_msg)); test_same_message 10 some_msg (RSA.unwrap_signature key (RSA.sign_CRT key some_msg)); test_same_message 11 some_msg (RSA.decrypt key (RSA.encrypt key some_msg)); test_same_message 12 some_msg (RSA.decrypt_CRT key (RSA.encrypt key some_msg)) (* Diffie-Hellman *) let _ = testing_function "Diffie-Hellman"; let prng = Random.pseudo_rng (hex "5b5e50dc5b6eaf5346eba8244e5666ac4dcd5409") in let param = DH.new_parameters ~rng:prng 1024 in let ps1 = DH.private_secret ~rng:prng param and ps2 = DH.private_secret ~rng:prng param in let msg1 = DH.message param ps1 and msg2 = DH.message param ps2 in let ss1 = DH.shared_secret param ps1 msg2 and ss2 = DH.shared_secret param ps2 msg1 in test 1 ss1 ss2 (* Base64 encoding *) let _ = testing_function "Base64"; test 1 "VGhlIHF1aWNrIGJyb3duIGZveCBqdW1wcyBvdmVyIHRoZSBsYXp5IGRvZy4KVGhlIHF1aWNr IGJyb3duIGZveCBqdW1wcyBvdmVyIHRoZSBsYXp5IGRvZy4KVGhlIHF1aWNrIGJyb3duIGZv eCBqdW1wcyBvdmVyIHRoZSBsYXp5IGRvZy4KVGhlIHF1aWNrIGJyb3duIGZveCBqdW1wcyBv dmVyIHRoZSBsYXp5IGRvZy4K " (transform_string (Base64.encode_multiline()) "The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. "); test 2 "VGhlIHF1aWNrIGJyb3duIGZveCBqdW1wcyBvdmVyIHRoZSBsYXp5IGRvZy4KVGhlIHF1aWNr IGJyb3duIGZveCBqdW1wcyBvdmVyIHRoZSBsYXp5IGRvZy4KVGhlIHF1aWNrIGJyb3duIGZv eCBqdW1wcyBvdmVyIHRoZSBsYXp5IGRvZy4KVGhlIHF1aWNrIGJyb3duIGZveCBqdW1wcyBv dmVyIHRoZSBsYXp5IGRvZy4uCg== " (transform_string (Base64.encode_multiline()) "The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog.. "); test 3 "VGhlIHF1aWNrIGJyb3duIGZveCBqdW1wcyBvdmVyIHRoZSBsYXp5IGRvZy4KVGhlIHF1aWNr IGJyb3duIGZveCBqdW1wcyBvdmVyIHRoZSBsYXp5IGRvZy4KVGhlIHF1aWNrIGJyb3duIGZv eCBqdW1wcyBvdmVyIHRoZSBsYXp5IGRvZy4KVGhlIHF1aWNrIGJyb3duIGZveCBqdW1wcyBv dmVyIHRoZSBsYXp5IGRvZy4uLgo= " (transform_string (Base64.encode_multiline()) "The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog... "); test 4 "The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. " (transform_string (Base64.decode()) "VGhlIHF1aWNrIGJyb3duIGZveCBqdW1wcyBvdmVyIHRoZSBsYXp5IGRvZy4KVGhlIHF1aWNr IGJyb3duIGZveCBqdW1wcyBvdmVyIHRoZSBsYXp5IGRvZy4KVGhlIHF1aWNrIGJyb3duIGZv eCBqdW1wcyBvdmVyIHRoZSBsYXp5IGRvZy4KVGhlIHF1aWNrIGJyb3duIGZveCBqdW1wcyBv dmVyIHRoZSBsYXp5IGRvZy4K "); test 5 "The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog.. " (transform_string (Base64.decode()) "VGhlIHF1aWNrIGJyb3duIGZveCBqdW1wcyBvdmVyIHRoZSBsYXp5IGRvZy4KVGhlIHF1aWNr IGJyb3duIGZveCBqdW1wcyBvdmVyIHRoZSBsYXp5IGRvZy4KVGhlIHF1aWNrIGJyb3duIGZv eCBqdW1wcyBvdmVyIHRoZSBsYXp5IGRvZy4KVGhlIHF1aWNrIGJyb3duIGZveCBqdW1wcyBv dmVyIHRoZSBsYXp5IGRvZy4uCg== "); test 6 "The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog... " (transform_string (Base64.decode()) "VGhlIHF1aWNrIGJyb3duIGZveCBqdW1wcyBvdmVyIHRoZSBsYXp5IGRvZy4KVGhlIHF1aWNr IGJyb3duIGZveCBqdW1wcyBvdmVyIHRoZSBsYXp5IGRvZy4KVGhlIHF1aWNrIGJyb3duIGZv eCBqdW1wcyBvdmVyIHRoZSBsYXp5IGRvZy4KVGhlIHF1aWNrIGJyb3duIGZveCBqdW1wcyBv dmVyIHRoZSBsYXp5IGRvZy4uLgo= "); let binarytext = String.init 256 Char.chr in test 7 binarytext (transform_string (Base64.decode()) (transform_string (Base64.encode_compact()) binarytext)) (* Compression *) let _ = testing_function "Zlib compression"; let text = "The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. " in try test 1 text (transform_string (Zlib.uncompress()) (transform_string (Zlib.compress()) text)); let c = Zlib.compress() and u = Zlib.uncompress() in c#put_string text; c#flush; u#put_string c#get_string; u#flush; test 2 text u#get_string; c#put_string text; c#finish; u#put_string c#get_string; u#finish; test 3 text u#get_string with Error Compression_not_supported -> printf " (not supported)" (* Miscellaneous functions *) let test_equal_data = [ ""; "a"; "b"; "aa"; "ab"; "ba"; "abc" ] let test_equal (of_string: string -> 'a) (f: 'a -> 'a -> bool) = List.fold_left (fun acc s1 -> List.fold_left (fun acc s2 -> acc && (f (of_string s1) (of_string s2) = String.equal s1 s2)) acc test_equal_data) true test_equal_data let _ = testing_function "Comparison functions"; test 1 (test_equal (fun x -> x) Cryptokit.string_equal) true; test 2 (test_equal Bytes.of_string Cryptokit.bytes_equal) true (* Random numbers *) (* This is not a serious statistical test of Cryptokit's RNGs (use Dieharder or TestU01 for this). Rather, it's a simplistic test intended to detect obvious bugs such as providing fewer random bytes than requested. *) let chisquare b = let n = Bytes.length b in let r = 256 in let freq = Array.make r 0 in for i = 0 to n - 1 do let t = Char.code (Bytes.get b i) in freq.(t) <- freq.(t) + 1 done; let expected = float n /. float r in let t = Array.fold_left (fun s x -> let d = float x -. expected in d *. d +. s) 0.0 freq in let chi2 = t /. expected in let degfree = float r -. 1.0 in (* The degree of freedom is high, so we approximate as a normal distribution with mean equal to degfree and variance 2 * degfree. Four sigmas correspond to a 99.9936% confidence interval. *) chi2 <= degfree +. 4.0 *. sqrt (2.0 *. degfree) let test_rng ?(len = 10000) (r: Random.rng) = let b = Bytes.make len '\000' in r#random_bytes b 0 len; r#wipe; printf "chi^2 %s\n" (if chisquare b then "plausible" else (error_occurred := true; "BROKEN? rerun test!")) let _ = testing_function "Random number generation"; printf " 1. PRNG: "; test_rng (Random.pseudo_rng "abcdefghijklmnopqrstuvwxyz"); printf " 2. PRNG based on AES CTR: "; test_rng (Random.pseudo_rng_aes_ctr "abcdefghijklmnopqrstuvwxyz"); printf " 3. /dev/urandom: "; begin try test_rng (Random.device_rng "/dev/urandom") with Unix.Unix_error _ -> printf "not available\n" end; printf " 4. Hardware RNG: "; begin try test_rng (Random.hardware_rng ()) with Error No_entropy_source -> printf "not available\n" end; printf " 5. System RNG: "; begin try test_rng (Random.system_rng ()) with Error No_entropy_source -> printf "not available\n" end (* End of tests *) let _ = print_newline(); if !error_occurred then begin printf "********* TEST FAILED ***********\n"; exit 2 end else begin printf "All tests successful.\n"; exit 0 end